kopia lustrzana https://github.com/Tldraw/Tldraw
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 knowpull/3512/head
rodzic
1450454873
commit
34ad856873
|
@ -203,7 +203,6 @@ export class SpeechBubbleUtil extends ShapeUtil<SpeechBubbleShape> {
|
||||||
text={text}
|
text={text}
|
||||||
labelColor={theme[color].solid}
|
labelColor={theme[color].solid}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
disableTab
|
|
||||||
wrap
|
wrap
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -2507,9 +2507,7 @@ export function useDefaultHelpers(): {
|
||||||
export function useDialogs(): TLUiDialogsContextType;
|
export function useDialogs(): TLUiDialogsContextType;
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export function useEditableText(id: TLShapeId, type: string, text: string, opts?: {
|
export function useEditableText(id: TLShapeId, type: string, text: string): {
|
||||||
disableTab: boolean;
|
|
||||||
}): {
|
|
||||||
handleBlur: () => void;
|
handleBlur: () => void;
|
||||||
handleChange: (e: React_2.ChangeEvent<HTMLTextAreaElement>) => void;
|
handleChange: (e: React_2.ChangeEvent<HTMLTextAreaElement>) => void;
|
||||||
handleDoubleClick: (e: any) => any;
|
handleDoubleClick: (e: any) => any;
|
||||||
|
|
|
@ -15735,7 +15735,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": ") => {\n id: import(\"@tldraw/editor\")."
|
"text": ") => {\n id: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
|
@ -15819,7 +15819,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": ") => {\n id: import(\"@tldraw/editor\")."
|
"text": ") => {\n id: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
|
@ -15894,7 +15894,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": ") => {\n id: import(\"@tldraw/editor\")."
|
"text": ") => {\n id: "
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Reference",
|
"kind": "Reference",
|
||||||
|
@ -15903,7 +15903,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"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",
|
"kind": "Reference",
|
||||||
|
@ -27480,14 +27480,6 @@
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "string"
|
"text": "string"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"kind": "Content",
|
|
||||||
"text": ", opts?: "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"kind": "Content",
|
|
||||||
"text": "{\n disableTab: boolean;\n}"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
"text": "): "
|
"text": "): "
|
||||||
|
@ -27575,8 +27567,8 @@
|
||||||
],
|
],
|
||||||
"fileUrlPath": "packages/tldraw/src/lib/shapes/shared/useEditableText.ts",
|
"fileUrlPath": "packages/tldraw/src/lib/shapes/shared/useEditableText.ts",
|
||||||
"returnTypeTokenRange": {
|
"returnTypeTokenRange": {
|
||||||
"startIndex": 9,
|
"startIndex": 7,
|
||||||
"endIndex": 26
|
"endIndex": 24
|
||||||
},
|
},
|
||||||
"releaseTag": "Public",
|
"releaseTag": "Public",
|
||||||
"overloadIndex": 1,
|
"overloadIndex": 1,
|
||||||
|
@ -27604,14 +27596,6 @@
|
||||||
"endIndex": 6
|
"endIndex": 6
|
||||||
},
|
},
|
||||||
"isOptional": false
|
"isOptional": false
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameterName": "opts",
|
|
||||||
"parameterTypeTokenRange": {
|
|
||||||
"startIndex": 7,
|
|
||||||
"endIndex": 8
|
|
||||||
},
|
|
||||||
"isOptional": true
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"name": "useEditableText"
|
"name": "useEditableText"
|
||||||
|
|
|
@ -35,7 +35,6 @@ export const ArrowTextLabel = React.memo(function ArrowTextLabel({
|
||||||
labelColor={theme[labelColor].solid}
|
labelColor={theme[labelColor].solid}
|
||||||
textWidth={width}
|
textWidth={width}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
disableTab
|
|
||||||
style={{
|
style={{
|
||||||
transform: `translate(${position.x}px, ${position.y}px)`,
|
transform: `translate(${position.x}px, ${position.y}px)`,
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -421,7 +421,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
|
||||||
text={text}
|
text={text}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
labelColor={theme[props.labelColor].solid}
|
labelColor={theme[props.labelColor].solid}
|
||||||
disableTab
|
|
||||||
wrap
|
wrap
|
||||||
/>
|
/>
|
||||||
</HTMLContainer>
|
</HTMLContainer>
|
||||||
|
|
|
@ -190,7 +190,6 @@ export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
|
||||||
isNote
|
isNote
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
labelColor={theme[color].note.text}
|
labelColor={theme[color].note.text}
|
||||||
disableTab
|
|
||||||
wrap
|
wrap
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -27,7 +27,6 @@ type TextLabelProps = {
|
||||||
bounds?: Box
|
bounds?: Box
|
||||||
isNote?: boolean
|
isNote?: boolean
|
||||||
isSelected: boolean
|
isSelected: boolean
|
||||||
disableTab?: boolean
|
|
||||||
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
|
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
|
||||||
classNamePrefix?: string
|
classNamePrefix?: string
|
||||||
style?: React.CSSProperties
|
style?: React.CSSProperties
|
||||||
|
@ -51,15 +50,13 @@ export const TextLabel = React.memo(function TextLabel({
|
||||||
onKeyDown: handleKeyDownCustom,
|
onKeyDown: handleKeyDownCustom,
|
||||||
classNamePrefix,
|
classNamePrefix,
|
||||||
style,
|
style,
|
||||||
disableTab = false,
|
|
||||||
textWidth,
|
textWidth,
|
||||||
textHeight,
|
textHeight,
|
||||||
}: TextLabelProps) {
|
}: TextLabelProps) {
|
||||||
const { rInput, isEmpty, isEditing, isEditingAnything, ...editableTextRest } = useEditableText(
|
const { rInput, isEmpty, isEditing, isEditingAnything, ...editableTextRest } = useEditableText(
|
||||||
id,
|
id,
|
||||||
type,
|
type,
|
||||||
text,
|
text
|
||||||
{ disableTab }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const [initialText, setInitialText] = useState(text)
|
const [initialText, setInitialText] = useState(text)
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {
|
||||||
TLShapeId,
|
TLShapeId,
|
||||||
TLUnknownShape,
|
TLUnknownShape,
|
||||||
getPointerInfo,
|
getPointerInfo,
|
||||||
preventDefault,
|
|
||||||
stopEventPropagation,
|
stopEventPropagation,
|
||||||
useEditor,
|
useEditor,
|
||||||
useValue,
|
useValue,
|
||||||
|
@ -11,12 +10,7 @@ import React, { useCallback, useEffect, useRef } from 'react'
|
||||||
import { INDENT, TextHelpers } from './TextHelpers'
|
import { INDENT, TextHelpers } from './TextHelpers'
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function useEditableText(
|
export function useEditableText(id: TLShapeId, type: string, text: string) {
|
||||||
id: TLShapeId,
|
|
||||||
type: string,
|
|
||||||
text: string,
|
|
||||||
opts = { disableTab: false } as { disableTab: boolean }
|
|
||||||
) {
|
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
|
|
||||||
const rInput = useRef<HTMLTextAreaElement>(null)
|
const rInput = useRef<HTMLTextAreaElement>(null)
|
||||||
|
@ -134,20 +128,9 @@ export function useEditableText(
|
||||||
}
|
}
|
||||||
break
|
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.
|
// When the text changes, update the text value.
|
||||||
|
|
|
@ -7,18 +7,22 @@ import {
|
||||||
SvgExportContext,
|
SvgExportContext,
|
||||||
TLOnEditEndHandler,
|
TLOnEditEndHandler,
|
||||||
TLOnResizeHandler,
|
TLOnResizeHandler,
|
||||||
|
TLShapeId,
|
||||||
TLShapeUtilFlag,
|
TLShapeUtilFlag,
|
||||||
TLTextShape,
|
TLTextShape,
|
||||||
Vec,
|
Vec,
|
||||||
WeakMapCache,
|
WeakMapCache,
|
||||||
getDefaultColorTheme,
|
getDefaultColorTheme,
|
||||||
|
preventDefault,
|
||||||
textShapeMigrations,
|
textShapeMigrations,
|
||||||
textShapeProps,
|
textShapeProps,
|
||||||
toDomPrecision,
|
toDomPrecision,
|
||||||
useEditor,
|
useEditor,
|
||||||
} from '@tldraw/editor'
|
} from '@tldraw/editor'
|
||||||
|
import { useCallback } from 'react'
|
||||||
import { useDefaultColorTheme } from '../shared/ShapeFill'
|
import { useDefaultColorTheme } from '../shared/ShapeFill'
|
||||||
import { SvgTextLabel } from '../shared/SvgTextLabel'
|
import { SvgTextLabel } from '../shared/SvgTextLabel'
|
||||||
|
import { TextHelpers } from '../shared/TextHelpers'
|
||||||
import { TextLabel } from '../shared/TextLabel'
|
import { TextLabel } from '../shared/TextLabel'
|
||||||
import { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'
|
import { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'
|
||||||
import { getFontDefForExport } from '../shared/defaultStyleDefs'
|
import { getFontDefForExport } from '../shared/defaultStyleDefs'
|
||||||
|
@ -73,6 +77,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
|
||||||
const { width, height } = this.getMinDimensions(shape)
|
const { width, height } = this.getMinDimensions(shape)
|
||||||
const isSelected = shape.id === this.editor.getOnlySelectedShapeId()
|
const isSelected = shape.id === this.editor.getOnlySelectedShapeId()
|
||||||
const theme = useDefaultColorTheme()
|
const theme = useDefaultColorTheme()
|
||||||
|
const handleKeyDown = useTextShapeKeydownHandler(id)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextLabel
|
<TextLabel
|
||||||
|
@ -94,6 +99,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
|
||||||
transformOrigin: 'top left',
|
transformOrigin: 'top left',
|
||||||
}}
|
}}
|
||||||
wrap
|
wrap
|
||||||
|
onKeyDown={handleKeyDown}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -332,3 +338,32 @@ function getTextSize(editor: Editor, props: TLTextShape['props']) {
|
||||||
height: Math.max(fontSize, result.h),
|
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]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue