tldraw/packages/editor/src/lib/app/shapeutils/shared/TextLabel.tsx
Mitja Bezenšek f59bfe01b1
Vertical text alignment for geo shapes (#1414)
Vertical text alignment for geo shapes.

### Change Type

- [x] `minor` — New Feature

### Test Plan

1. Add a step-by-step description of how to test your PR here.
2.

- [ ] Unit Tests
- [ ] Webdriver tests

### Release Notes

- This adds vertical text alignment property to geo shapes.

---------

Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-05-19 10:23:43 +00:00

103 lines
2.3 KiB
TypeScript

import {
TLAlignType,
TLFillType,
TLFontType,
TLShape,
TLSizeType,
TLVerticalAlignType,
} from '@tldraw/tlschema'
import React from 'react'
import { LABEL_FONT_SIZES, TEXT_PROPS } from '../../../constants'
import { stopEventPropagation } from '../../../utils/dom'
import { TextHelpers } from '../TLTextUtil/TextHelpers'
import { useEditableText } from './useEditableText'
export const TextLabel = React.memo(function TextLabel<
T extends Extract<TLShape, { props: { text: string } }>
>({
id,
type,
text,
size,
labelColor,
font,
align,
verticalAlign,
wrap,
}: {
id: T['id']
type: T['type']
size: TLSizeType
font: TLFontType
fill?: TLFillType
align: TLAlignType
verticalAlign: TLVerticalAlignType
wrap?: boolean
text: string
labelColor: string
}) {
const {
rInput,
isEmpty,
isEditing,
isEditableFromHover,
handleFocus,
handleChange,
handleKeyDown,
handleBlur,
} = useEditableText(id, type, text)
const isInteractive = isEditing || isEditableFromHover
return (
<div
className="tl-text-label"
data-font={font}
data-align={align}
data-hastext={!isEmpty}
data-isediting={isEditing}
data-textwrap={!!wrap}
style={{ alignItems: verticalAlign === 'middle' ? 'center' : verticalAlign }}
>
<div
className="tl-text-label__inner"
style={{
fontSize: LABEL_FONT_SIZES[size],
lineHeight: LABEL_FONT_SIZES[size] * TEXT_PROPS.lineHeight + 'px',
minHeight: isEmpty ? LABEL_FONT_SIZES[size] * TEXT_PROPS.lineHeight + 32 : 0,
minWidth: isEmpty ? 33 : 0,
color: labelColor,
}}
>
<div className="tl-text tl-text-content" dir="ltr">
{TextHelpers.normalizeTextForDom(text)}
</div>
{isInteractive ? (
// Consider replacing with content-editable
<textarea
ref={rInput}
className="tl-text tl-text-input"
name="text"
tabIndex={-1}
autoComplete="false"
autoCapitalize="false"
autoCorrect="false"
autoSave="false"
autoFocus={isEditing}
placeholder=""
spellCheck="true"
wrap="off"
dir="auto"
datatype="wysiwyg"
defaultValue={text}
onFocus={handleFocus}
onChange={handleChange}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
onContextMenu={stopEventPropagation}
/>
) : null}
</div>
</div>
)
})