textfields [1 of 3]: add text into speech bubble; also add rich text example (#3050)
This is the first of three textfield changes. This starts with making the speech bubble actually have text. Also, it creates a TipTap example and how that would be wired up. 🎵 this is dangerous, I walk through textfields so watch your head rock 🎵 ### Change Type - [x] `minor` — New feature ### Release Notes - Refactor textfields be composable/swappable.
This commit is contained in:
parent
3593799d9e
commit
d76d53db95
17 changed files with 616 additions and 346 deletions
|
@ -1,8 +1,7 @@
|
|||
import { TLArrowShape, TLShapeId, VecLike, stopEventPropagation } from '@tldraw/editor'
|
||||
import { TLArrowShape, TLDefaultColorStyle, TLShapeId, VecLike } from '@tldraw/editor'
|
||||
import * as React from 'react'
|
||||
import { TextHelpers } from '../../shared/TextHelpers'
|
||||
import { TextLabel } from '../../shared/TextLabel'
|
||||
import { ARROW_LABEL_FONT_SIZES, TEXT_PROPS } from '../../shared/default-shape-constants'
|
||||
import { useEditableText } from '../../shared/useEditableText'
|
||||
|
||||
export const ArrowTextLabel = React.memo(function ArrowTextLabel({
|
||||
id,
|
||||
|
@ -12,77 +11,26 @@ export const ArrowTextLabel = React.memo(function ArrowTextLabel({
|
|||
position,
|
||||
width,
|
||||
labelColor,
|
||||
}: { id: TLShapeId; position: VecLike; width?: number; labelColor: string } & Pick<
|
||||
}: { id: TLShapeId; position: VecLike; width?: number; labelColor: TLDefaultColorStyle } & Pick<
|
||||
TLArrowShape['props'],
|
||||
'text' | 'size' | 'font'
|
||||
>) {
|
||||
const {
|
||||
rInput,
|
||||
isEditing,
|
||||
handleFocus,
|
||||
handleBlur,
|
||||
handleKeyDown,
|
||||
handleChange,
|
||||
isEmpty,
|
||||
handleInputPointerDown,
|
||||
handleDoubleClick,
|
||||
} = useEditableText(id, 'arrow', text)
|
||||
|
||||
const finalText = TextHelpers.normalizeTextForDom(text)
|
||||
const hasText = finalText.trim().length > 0
|
||||
|
||||
if (!isEditing && !hasText) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="tl-arrow-label"
|
||||
data-font={font}
|
||||
data-align={'center'}
|
||||
data-hastext={!isEmpty}
|
||||
data-isediting={isEditing}
|
||||
<TextLabel
|
||||
id={id}
|
||||
classNamePrefix="tl-arrow"
|
||||
type="arrow"
|
||||
font={font}
|
||||
fontSize={ARROW_LABEL_FONT_SIZES[size]}
|
||||
lineHeight={TEXT_PROPS.lineHeight}
|
||||
align="middle"
|
||||
verticalAlign="middle"
|
||||
text={text}
|
||||
labelColor={labelColor}
|
||||
textWidth={width}
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: ARROW_LABEL_FONT_SIZES[size],
|
||||
lineHeight: ARROW_LABEL_FONT_SIZES[size] * TEXT_PROPS.lineHeight + 'px',
|
||||
transform: `translate(${position.x}px, ${position.y}px)`,
|
||||
color: labelColor,
|
||||
}}
|
||||
>
|
||||
<div className="tl-arrow-label__inner">
|
||||
<p style={{ width: width ? width : '9px' }}>
|
||||
{text ? TextHelpers.normalizeTextForDom(text) : ' '}
|
||||
</p>
|
||||
{isEditing && (
|
||||
// Consider replacing with content-editable
|
||||
<textarea
|
||||
ref={rInput}
|
||||
className="tl-text tl-text-input"
|
||||
name="text"
|
||||
tabIndex={-1}
|
||||
autoComplete="off"
|
||||
autoCapitalize="off"
|
||||
autoCorrect="off"
|
||||
autoSave="off"
|
||||
autoFocus
|
||||
placeholder=""
|
||||
spellCheck="true"
|
||||
wrap="off"
|
||||
dir="auto"
|
||||
datatype="wysiwyg"
|
||||
defaultValue={text}
|
||||
onFocus={handleFocus}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={handleBlur}
|
||||
onTouchEnd={stopEventPropagation}
|
||||
onContextMenu={stopEventPropagation}
|
||||
onPointerDown={handleInputPointerDown}
|
||||
onDoubleClick={handleDoubleClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue