UNPKG

@aokiapp/rjsf-mantine-corporate

Version:

Corporational variant of theme, based on @aokiapp/rjsf-mantine-theme

91 lines 4.53 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { createErrors } from '@aokiapp/rjsf-mantine-theme'; import { Pill, PillsInput } from '@mantine/core'; import { labelValue, ariaDescribedByIds, } from '@rjsf/utils'; import { useCallback, useMemo, useState } from 'react'; /** * The `PillInputWidget` is the special case of the array field where the user can enter a value and press enter to add * it to the array. * The schema of this widget must match the follwing criteria: * - type: array * - items: type: string * - uniqueItems: true */ export default function PillInputWidget({ id, placeholder, label, hideLabel, value, required, readonly, disabled, onChange: onChangeBase, onChangeOverride, autofocus, rawErrors, hideError, schema, options: { description, removeOnBackspace = false, punctuation = null }, }) { // check the schema criteria if (schema.type !== 'array' || typeof schema.items !== 'object' || Array.isArray(schema.items) || schema.items.type !== 'string') { throw new Error('The PillInputWidget is only compatible with a schema that is an array of unique strings'); } // field-level controls start const _value = useMemo(() => (Array.isArray(value) ? value : []), [value]); const onChange = onChangeOverride || onChangeBase; const onRemove = useCallback((i) => { onChange(_value.filter((_, index) => index !== i)); }, [_value, onChange]); const onAdd = useCallback((value) => { onChange([..._value, value]); }, [_value, onChange]); // add multiple values at once // I need this onAdd can be called within one render const onBulkAdd = useCallback((values) => { onChange([..._value, ...values]); }, [_value, onChange]); const currentPills = _value.map((v, i) => (_jsx(Pill, { withRemoveButton: !disabled && !readonly, onRemove: () => { onRemove(i); }, children: v }, i))); // field-level controls end // pill input start const [tmpValue, setTmpValue] = useState(''); const handleChange = useCallback((e) => { const v = e.target.value; if (typeof punctuation === 'string' && punctuation.length) { // split by punctuation const split = v.split(punctuation); // add all but the last one onBulkAdd(split.slice(0, -1)); // set the last one as the tmp value setTmpValue(split[split.length - 1]); } else { setTmpValue(v); } }, [onBulkAdd, punctuation]); // Japanese IME support const [isComposing, setIsComposing] = useState(false); const handleCompositionStart = useCallback(() => { setIsComposing(true); }, [setIsComposing]); const handleCompositionEnd = useCallback(() => { setIsComposing(false); }, [setIsComposing]); const handleBlur = useCallback(() => { if (tmpValue) { onAdd(tmpValue); setTmpValue(''); } }, [tmpValue, onAdd]); const handleKeyDown = useCallback((e) => { // handle enter air shot if (e.key === 'Enter' && !isComposing && tmpValue) { e.preventDefault(); // without this, enter will trigger the form submit onAdd(tmpValue); setTmpValue(''); } // handle backspace when empty if (e.key === 'Backspace' && !tmpValue && _value.length > 0) { e.preventDefault(); // without this, the last character also gets deleted const last = _value[_value.length - 1]; onRemove(_value.length - 1); if (!removeOnBackspace) { setTmpValue(last); } } }, [isComposing, tmpValue, _value, onAdd, onRemove, removeOnBackspace]); const pillInput = (_jsx(PillsInput.Field, { placeholder: placeholder, id: id, value: tmpValue, onChange: handleChange, onKeyDown: handleKeyDown, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd, autoFocus: autofocus, disabled: disabled || readonly, onBlur: handleBlur })); // pill input end return (_jsx(PillsInput, { label: labelValue(label, hideLabel, undefined), description: description, disabled: disabled || readonly, error: createErrors(rawErrors, hideError), "aria-describedby": ariaDescribedByIds(id), required: required, className: 'armt-widget-pill-input', children: _jsxs(Pill.Group, { children: [currentPills, pillInput] }) })); } //# sourceMappingURL=PillInputWidget.js.map