textfields: nix disableTab option; make TextShapes have custom Tab behavior as intended (#3506)

We shouldn't be making this something you have to negate everytime you
use `useEditableText`. The TextShape can just have its custom behavior
since that's the intended usecase. (although I think that Tab there
doesn't do much anyway, but whatevs)

### Change Type

<!--  Please select a 'Scope' label ️ -->

- [x] `sdk` — Changes the tldraw SDK
- [ ] `dotcom` — Changes the tldraw.com web app
- [ ] `docs` — Changes to the documentation, examples, or templates.
- [ ] `vs code` — Changes to the vscode plugin
- [ ] `internal` — Does not affect user-facing stuff

<!--  Please select a 'Type' label ️ -->

- [ ] `bugfix` — Bug fix
- [ ] `feature` — New feature
- [ ] `improvement` — Improving existing features
- [x] `chore` — Updating dependencies, other boring stuff
- [ ] `galaxy brain` — Architectural changes
- [ ] `tests` — Changes to any test code
- [ ] `tools` — Changes to infrastructure, CI, internal scripts,
debugging tools, etc.
- [ ] `dunno` — I don't know
This commit is contained in:
Mime Čuvalo 2024-04-17 12:11:08 +01:00 committed by GitHub
parent 1450454873
commit 34ad856873
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 45 additions and 52 deletions

View file

@ -203,7 +203,6 @@ export class SpeechBubbleUtil extends ShapeUtil<SpeechBubbleShape> {
text={text}
labelColor={theme[color].solid}
isSelected={isSelected}
disableTab
wrap
/>
</>

View file

@ -2507,9 +2507,7 @@ export function useDefaultHelpers(): {
export function useDialogs(): TLUiDialogsContextType;
// @public (undocumented)
export function useEditableText(id: TLShapeId, type: string, text: string, opts?: {
disableTab: boolean;
}): {
export function useEditableText(id: TLShapeId, type: string, text: string): {
handleBlur: () => void;
handleChange: (e: React_2.ChangeEvent<HTMLTextAreaElement>) => void;
handleDoubleClick: (e: any) => any;

View file

@ -15735,7 +15735,7 @@
},
{
"kind": "Content",
"text": ") => {\n id: import(\"@tldraw/editor\")."
"text": ") => {\n id: "
},
{
"kind": "Reference",
@ -15819,7 +15819,7 @@
},
{
"kind": "Content",
"text": ") => {\n id: import(\"@tldraw/editor\")."
"text": ") => {\n id: "
},
{
"kind": "Reference",
@ -15894,7 +15894,7 @@
},
{
"kind": "Content",
"text": ") => {\n id: import(\"@tldraw/editor\")."
"text": ") => {\n id: "
},
{
"kind": "Reference",
@ -15903,7 +15903,7 @@
},
{
"kind": "Content",
"text": ";\n props: {\n autoSize: boolean;\n scale?: undefined;\n };\n type: \"text\";\n } | {\n id: import(\"@tldraw/editor\")."
"text": ";\n props: {\n autoSize: boolean;\n scale?: undefined;\n };\n type: \"text\";\n } | {\n id: "
},
{
"kind": "Reference",
@ -27480,14 +27480,6 @@
"kind": "Content",
"text": "string"
},
{
"kind": "Content",
"text": ", opts?: "
},
{
"kind": "Content",
"text": "{\n disableTab: boolean;\n}"
},
{
"kind": "Content",
"text": "): "
@ -27575,8 +27567,8 @@
],
"fileUrlPath": "packages/tldraw/src/lib/shapes/shared/useEditableText.ts",
"returnTypeTokenRange": {
"startIndex": 9,
"endIndex": 26
"startIndex": 7,
"endIndex": 24
},
"releaseTag": "Public",
"overloadIndex": 1,
@ -27604,14 +27596,6 @@
"endIndex": 6
},
"isOptional": false
},
{
"parameterName": "opts",
"parameterTypeTokenRange": {
"startIndex": 7,
"endIndex": 8
},
"isOptional": true
}
],
"name": "useEditableText"

View file

@ -35,7 +35,6 @@ export const ArrowTextLabel = React.memo(function ArrowTextLabel({
labelColor={theme[labelColor].solid}
textWidth={width}
isSelected={isSelected}
disableTab
style={{
transform: `translate(${position.x}px, ${position.y}px)`,
}}

View file

@ -421,7 +421,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
text={text}
isSelected={isSelected}
labelColor={theme[props.labelColor].solid}
disableTab
wrap
/>
</HTMLContainer>

View file

@ -190,7 +190,6 @@ export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
isNote
isSelected={isSelected}
labelColor={theme[color].note.text}
disableTab
wrap
onKeyDown={handleKeyDown}
/>

View file

@ -27,7 +27,6 @@ type TextLabelProps = {
bounds?: Box
isNote?: boolean
isSelected: boolean
disableTab?: boolean
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
classNamePrefix?: string
style?: React.CSSProperties
@ -51,15 +50,13 @@ export const TextLabel = React.memo(function TextLabel({
onKeyDown: handleKeyDownCustom,
classNamePrefix,
style,
disableTab = false,
textWidth,
textHeight,
}: TextLabelProps) {
const { rInput, isEmpty, isEditing, isEditingAnything, ...editableTextRest } = useEditableText(
id,
type,
text,
{ disableTab }
text
)
const [initialText, setInitialText] = useState(text)

View file

@ -2,7 +2,6 @@ import {
TLShapeId,
TLUnknownShape,
getPointerInfo,
preventDefault,
stopEventPropagation,
useEditor,
useValue,
@ -11,12 +10,7 @@ import React, { useCallback, useEffect, useRef } from 'react'
import { INDENT, TextHelpers } from './TextHelpers'
/** @public */
export function useEditableText(
id: TLShapeId,
type: string,
text: string,
opts = { disableTab: false } as { disableTab: boolean }
) {
export function useEditableText(id: TLShapeId, type: string, text: string) {
const editor = useEditor()
const rInput = useRef<HTMLTextAreaElement>(null)
@ -134,20 +128,9 @@ export function useEditableText(
}
break
}
case 'Tab': {
if (!opts.disableTab) {
preventDefault(e)
if (e.shiftKey) {
TextHelpers.unindent(e.currentTarget)
} else {
TextHelpers.indent(e.currentTarget)
}
}
break
}
}
},
[editor, id, opts.disableTab]
[editor, id]
)
// When the text changes, update the text value.

View file

@ -7,18 +7,22 @@ import {
SvgExportContext,
TLOnEditEndHandler,
TLOnResizeHandler,
TLShapeId,
TLShapeUtilFlag,
TLTextShape,
Vec,
WeakMapCache,
getDefaultColorTheme,
preventDefault,
textShapeMigrations,
textShapeProps,
toDomPrecision,
useEditor,
} from '@tldraw/editor'
import { useCallback } from 'react'
import { useDefaultColorTheme } from '../shared/ShapeFill'
import { SvgTextLabel } from '../shared/SvgTextLabel'
import { TextHelpers } from '../shared/TextHelpers'
import { TextLabel } from '../shared/TextLabel'
import { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'
import { getFontDefForExport } from '../shared/defaultStyleDefs'
@ -73,6 +77,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
const { width, height } = this.getMinDimensions(shape)
const isSelected = shape.id === this.editor.getOnlySelectedShapeId()
const theme = useDefaultColorTheme()
const handleKeyDown = useTextShapeKeydownHandler(id)
return (
<TextLabel
@ -94,6 +99,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
transformOrigin: 'top left',
}}
wrap
onKeyDown={handleKeyDown}
/>
)
}
@ -332,3 +338,32 @@ function getTextSize(editor: Editor, props: TLTextShape['props']) {
height: Math.max(fontSize, result.h),
}
}
function useTextShapeKeydownHandler(id: TLShapeId) {
const editor = useEditor()
return useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (editor.getEditingShapeId() !== id) return
switch (e.key) {
case 'Enter': {
if (e.ctrlKey || e.metaKey) {
editor.complete()
}
break
}
case 'Tab': {
preventDefault(e)
if (e.shiftKey) {
TextHelpers.unindent(e.currentTarget)
} else {
TextHelpers.indent(e.currentTarget)
}
break
}
}
},
[editor, id]
)
}