UNPKG

@create-figma-plugin/ui

Version:

Production-grade Preact components that replicate the Figma UI design

104 lines 4.67 kB
import { MIXED_STRING } from '@create-figma-plugin/utilities'; import { h } from 'preact'; import { useCallback, useRef, useState } from 'preact/hooks'; import { createClassName } from '../../../utilities/create-class-name.js'; import { createComponent } from '../../../utilities/create-component.js'; import { getCurrentFromRef } from '../../../utilities/get-current-from-ref.js'; import { noop } from '../../../utilities/no-op.js'; import { isKeyCodeCharacterGenerating } from '../private/is-keycode-character-generating.js'; import styles from './textbox-multiline.module.css'; const EMPTY_STRING = ''; export const TextboxMultiline = createComponent(function ({ grow = false, disabled = false, onBlur = noop, onFocus = noop, onInput = noop, onKeyDown = noop, onValueInput = noop, onMouseDown = noop, placeholder, propagateEscapeKeyDown = true, revertOnEscapeKeyDown = false, rows = 3, spellCheck = false, validateOnBlur, value, ...rest }, ref) { const textAreaElementRef = useRef(null); const [originalValue, setOriginalValue] = useState(EMPTY_STRING); const setTextAreaElementValue = useCallback(function (value) { const textAreaElement = getCurrentFromRef(textAreaElementRef); textAreaElement.value = value; const inputEvent = new window.Event('input', { bubbles: true, cancelable: true }); textAreaElement.dispatchEvent(inputEvent); }, []); const handleBlur = useCallback(function (event) { onBlur(event); if (typeof validateOnBlur !== 'undefined') { const result = validateOnBlur(value); if (typeof result === 'string') { setTextAreaElementValue(result); setOriginalValue(EMPTY_STRING); return; } if (result === false) { if (value !== originalValue) { setTextAreaElementValue(originalValue); } setOriginalValue(EMPTY_STRING); return; } } setOriginalValue(EMPTY_STRING); }, [onBlur, originalValue, setTextAreaElementValue, validateOnBlur, value]); const handleFocus = useCallback(function (event) { onFocus(event); setOriginalValue(value); event.currentTarget.select(); }, [onFocus, value]); const handleInput = useCallback(function (event) { onInput(event); const newValue = event.currentTarget.value; onValueInput(newValue); }, [onInput, onValueInput]); const handleKeyDown = useCallback(function (event) { onKeyDown(event); if (event.key === 'Escape') { if (revertOnEscapeKeyDown === true) { setTextAreaElementValue(originalValue); setOriginalValue(EMPTY_STRING); } if (propagateEscapeKeyDown === false) { event.stopPropagation(); } event.currentTarget.blur(); return; } if (value === MIXED_STRING && isKeyCodeCharacterGenerating(event.keyCode) === false) { event.preventDefault(); event.currentTarget.select(); } }, [ onKeyDown, originalValue, propagateEscapeKeyDown, revertOnEscapeKeyDown, setTextAreaElementValue, value ]); const handleMouseDown = useCallback(function (event) { onMouseDown(event); if (value === MIXED_STRING) { event.preventDefault(); event.currentTarget.select(); } }, [onMouseDown, value]); const refCallback = useCallback(function (textAreaElement) { textAreaElementRef.current = textAreaElement; if (ref === null) { return; } if (typeof ref === 'function') { ref(textAreaElement); return; } ref.current = textAreaElement; }, [ref]); return (h("div", { class: createClassName([ styles.textboxMultiline, grow === true ? styles.grow : null, disabled === true ? styles.disabled : null ]) }, grow === true ? (h("div", { class: styles.ghost }, value === MIXED_STRING ? 'Mixed' : `${value} `)) : null, h("textarea", { ...rest, ref: refCallback, class: styles.textarea, disabled: disabled === true, onBlur: handleBlur, onFocus: handleFocus, onInput: handleInput, onKeyDown: handleKeyDown, onMouseDown: handleMouseDown, placeholder: placeholder, rows: rows, spellcheck: spellCheck, tabIndex: 0, value: value === MIXED_STRING ? 'Mixed' : value }))); }); //# sourceMappingURL=textbox-multiline.js.map