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:
parent
1450454873
commit
34ad856873
9 changed files with 45 additions and 52 deletions
|
@ -203,7 +203,6 @@ export class SpeechBubbleUtil extends ShapeUtil<SpeechBubbleShape> {
|
|||
text={text}
|
||||
labelColor={theme[color].solid}
|
||||
isSelected={isSelected}
|
||||
disableTab
|
||||
wrap
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)`,
|
||||
}}
|
||||
|
|
|
@ -421,7 +421,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
|
|||
text={text}
|
||||
isSelected={isSelected}
|
||||
labelColor={theme[props.labelColor].solid}
|
||||
disableTab
|
||||
wrap
|
||||
/>
|
||||
</HTMLContainer>
|
||||
|
|
|
@ -190,7 +190,6 @@ export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
|
|||
isNote
|
||||
isSelected={isSelected}
|
||||
labelColor={theme[color].note.text}
|
||||
disableTab
|
||||
wrap
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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]
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue