@allxsmith/bestax-bulma 5.53.0 → 5.54.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/Avatars.js +7 -2
- package/dist/esm/components/Avatars.js.map +1 -1
- package/dist/esm/components/Badge.js +7 -2
- package/dist/esm/components/Badge.js.map +1 -1
- package/dist/esm/components/Command.js +19 -9
- package/dist/esm/components/Command.js.map +1 -1
- package/dist/esm/components/Pagination.js +9 -1
- package/dist/esm/components/Pagination.js.map +1 -1
- package/dist/esm/components/Steps.js +5 -1
- package/dist/esm/components/Steps.js.map +1 -1
- package/dist/esm/elements/RingProgress.js +6 -1
- package/dist/esm/elements/RingProgress.js.map +1 -1
- package/dist/esm/form/Autocomplete.js +4 -0
- package/dist/esm/form/Autocomplete.js.map +1 -1
- package/dist/esm/form/Combobox.js +7 -2
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/File.js +4 -1
- package/dist/esm/form/File.js.map +1 -1
- package/dist/esm/form/Rate.js +9 -1
- package/dist/esm/form/Rate.js.map +1 -1
- package/dist/esm/form/Slider.js +7 -4
- package/dist/esm/form/Slider.js.map +1 -1
- package/dist/esm/form/Taginput.js +9 -3
- package/dist/esm/form/Taginput.js.map +1 -1
- package/dist/esm/helpers/LocaleProvider.js +9 -6
- package/dist/esm/helpers/LocaleProvider.js.map +1 -1
- package/dist/esm/helpers/localeFormat.js +108 -0
- package/dist/esm/helpers/localeFormat.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +435 -276
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/Avatars.d.ts +1 -1
- package/dist/types/components/Badge.d.ts +1 -1
- package/dist/types/components/Command.d.ts +4 -2
- package/dist/types/components/Pagination.d.ts +3 -0
- package/dist/types/components/Steps.d.ts +4 -1
- package/dist/types/elements/RingProgress.d.ts +3 -2
- package/dist/types/form/Autocomplete.d.ts +6 -1
- package/dist/types/form/Combobox.d.ts +3 -2
- package/dist/types/form/File.d.ts +4 -1
- package/dist/types/form/Rate.d.ts +4 -1
- package/dist/types/form/Slider.d.ts +9 -2
- package/dist/types/form/Taginput.d.ts +8 -2
- package/dist/types/helpers/LocaleProvider.d.ts +9 -6
- package/dist/types/helpers/localeFormat.d.ts +26 -0
- package/dist/types-cjs/components/Avatars.d.ts +1 -1
- package/dist/types-cjs/components/Badge.d.ts +1 -1
- package/dist/types-cjs/components/Command.d.ts +4 -2
- package/dist/types-cjs/components/Pagination.d.ts +3 -0
- package/dist/types-cjs/components/Steps.d.ts +4 -1
- package/dist/types-cjs/elements/RingProgress.d.ts +3 -2
- package/dist/types-cjs/form/Autocomplete.d.ts +6 -1
- package/dist/types-cjs/form/Combobox.d.ts +3 -2
- package/dist/types-cjs/form/File.d.ts +4 -1
- package/dist/types-cjs/form/Rate.d.ts +4 -1
- package/dist/types-cjs/form/Slider.d.ts +9 -2
- package/dist/types-cjs/form/Taginput.d.ts +8 -2
- package/dist/types-cjs/helpers/LocaleProvider.d.ts +9 -6
- package/dist/types-cjs/helpers/localeFormat.d.ts +26 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/form/_file.scss +29 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Taginput.js","sources":["../../../src/form/Taginput.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n useId,\n} from 'react';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { useConfig, useIconLibrary } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { isEventInside } from '../helpers/shadowDom';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n useFieldsetDisabled,\n} from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { Icon } from '../elements/Icon';\n\n/**\n * Represents a tag item object with a value and optional label.\n */\nexport interface TaginputItem {\n /** The tag value. */\n value: string;\n /** Display label (optional). */\n label?: string;\n [key: string]: unknown;\n}\n\n/** A tag can be either a TaginputItem object or a plain string. */\nexport type TaginputTag = TaginputItem | string;\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n// An IME that's composing owns every key: Enter confirms what it composed,\n// the arrows move through its candidates, and Escape cancels it. Safari can\n// say so with `keyCode` 229 rather than `isComposing` (#1102).\nconst isComposing = (e: React.KeyboardEvent): boolean =>\n e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229;\n\n/**\n * Props for the Taginput component.\n * Inside an outer `Field`, or a `Control` with no `Field` around it, it\n * renders no `Field` of its own. The exception is `label`, `message`,\n * `horizontal` or `fieldClassName` in that bare `Control`: it keeps a `Field`\n * for them, nested in the `.control`, and warns in development. Wrap the\n * `Control` in a `Field` instead, and set the `label`, `horizontal` and class\n * name on that `Field`.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface TaginputProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here; it then replaces the `aria-label=\"Add tag\"` fallback too. With `data`, the label naming the input also names the open suggestion list, through `aria-labelledby`, when it has an id: this label always does, and an outer `Field`'s does unless you wired it by hand without an `id` in its `labelProps`. Otherwise the list is named \"Suggestions\". */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). With `data`, while the label names the input, the suggestion list's `aria-labelledby` points at it, through an `id` here when you give one and a generated one otherwise. */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Applied to the inner text input (the labellable control), not the wrapper div. */\n id?: string;\n /** The current tags (controlled). */\n value?: TaginputTag[];\n /** Default tags (uncontrolled). */\n defaultValue?: TaginputTag[];\n /**\n * Autocomplete suggestions. With `data` set, even to an empty array, the\n * text input is a `role=\"combobox\"` that controls the suggestion list and\n * points `aria-activedescendant` at the highlighted suggestion. Without it\n * there's no list, so the input stays a plain text field.\n */\n data?: string[];\n /** Placeholder text when no tags. */\n placeholder?: string;\n /** Object property to use as display field. */\n field?: string;\n /** Allow creating new tags not in suggestions. */\n allowNew?: boolean;\n /** Allow duplicate tags. */\n allowDuplicates?: boolean;\n /** Open autocomplete dropdown on focus. */\n openOnFocus?: boolean;\n /** Remove tag on backspace. Default: true. */\n removeOnKeys?: boolean;\n /** Keys to confirm tag creation. Default: ['Enter', ',']. */\n confirmKeys?: string[];\n /** Show close button on tags. Default: true. */\n closable?: boolean;\n /** Attach tags visually. */\n attached?: boolean;\n /**\n * Maximum number of tags allowed. At the limit the text input stays but\n * turns read-only, so focus stays put and the label still names it. It\n * takes no more tags and the suggestion list stays closed. Backspace (with\n * `removeOnKeys`) or a tag's remove button makes room again. While the\n * counter shows, it describes the input.\n */\n maxTags?: number;\n /** Maximum length of input. */\n maxlength?: number;\n /** Whether the input is disabled. */\n disabled?: boolean;\n /** Whether the input is read-only. */\n readonly?: boolean;\n /** Applies rounded corners to the tags. */\n rounded?: boolean;\n /** Truncates long tag text with ellipsis. */\n ellipsis?: boolean;\n /** Shows a counter of the number of tags. */\n hasCounter?: boolean;\n /**\n * Characters that split pasted text into tags. Each part goes through the\n * same checks as a typed tag, against the tags before it, the paste's own\n * included, and adding stops at `maxTags`. `onChange` fires once for the\n * whole paste, and `onAdd` once for each tag it adds.\n */\n onPasteSeparators?: string[];\n /** Validation function called before adding a tag. */\n beforeAdding?: (tag: string) => boolean;\n /** Custom function for creating tag objects from input. */\n createTag?: (input: string) => TaginputTag;\n /** Keeps the first autocomplete suggestion highlighted. */\n keepFirst?: boolean;\n /** Keeps the autocomplete dropdown open after selection. */\n keepOpen?: boolean;\n /**\n * Shows a loading spinner in the input.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n loading?: boolean;\n /** ARIA label for tag close buttons. */\n ariaCloseLabel?: string;\n /** Icon name for the input field. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Tag color variant. */\n tagColor?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'dark'\n | 'light';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. When set, one hidden input per tag is rendered. */\n name?: string;\n /** Optional id of the form the hidden inputs belong to. */\n form?: string;\n /** Callback when tags change. */\n onChange?: (tags: TaginputTag[]) => void;\n /** Callback when tag is added. */\n onAdd?: (tag: TaginputTag) => void;\n /** Callback when tag is removed. */\n onRemove?: (tag: TaginputTag, index: number) => void;\n /** Callback when typing in input. */\n onTyping?: (value: string) => void;\n /** Custom render for tags. */\n tagTemplate?: (tag: TaginputTag) => React.ReactNode;\n}\n\n/**\n * The `Taginput` component provides a tag/chip input field for managing multiple tags.\n *\n * @function\n * @param {TaginputProps} props - Props for the Taginput component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered taginput component.\n *\n * @example\n * // Basic usage\n * <Taginput\n * placeholder=\"Add a tag...\"\n * onChange={(tags) => console.log(tags)}\n * />\n *\n * @example\n * // With autocomplete\n * <Taginput\n * data={['React', 'Vue', 'Angular', 'Svelte']}\n * allowNew={false}\n * placeholder=\"Select frameworks...\"\n * />\n */\nexport const Taginput = forwardRef<HTMLInputElement, TaginputProps>(\n (\n {\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n value: controlledValue,\n defaultValue = [],\n data: dataProp,\n placeholder,\n field = 'label',\n allowNew = true,\n allowDuplicates = false,\n openOnFocus = false,\n removeOnKeys = true,\n confirmKeys = ['Enter', ','],\n closable = true,\n attached = false,\n maxTags,\n maxlength,\n disabled: disabledProp,\n readonly = false,\n rounded = false,\n ellipsis = false,\n hasCounter = true,\n onPasteSeparators = [','],\n beforeAdding,\n createTag,\n keepFirst = false,\n keepOpen = true,\n loading = false,\n ariaCloseLabel,\n icon,\n iconLibrary: iconLibraryProp,\n iconVariant,\n iconFeatures,\n color,\n tagColor,\n size,\n onChange,\n onAdd,\n onRemove,\n onTyping,\n tagTemplate,\n name,\n form,\n id,\n className,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Taginput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const defaultIconLibrary = useIconLibrary();\n const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';\n const pcn = (\n ...args: (\n | string\n | number\n | undefined\n | null\n | false\n | Record<string, unknown>\n | unknown[]\n )[]\n ) => prefixedClassNames(classPrefix, ...args);\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalTags, setInternalTags] =\n useState<TaginputTag[]>(defaultValue);\n const [inputValue, setInputValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const baseId = useId();\n const listboxId = `${baseId}-listbox`;\n const counterId = `${baseId}-counter`;\n\n // With `data` the input offers suggestions, so it's a combobox, even\n // while none match. Without it there's never a list, so it stays a plain\n // text field.\n const hasSuggestions = dataProp !== undefined;\n const data = dataProp ?? [];\n\n // Use controlled or internal tags\n const tags = controlledValue !== undefined ? controlledValue : internalTags;\n\n const isMaxReached = maxTags !== undefined && tags.length >= maxTags;\n // The suggestion list points `aria-labelledby` at the label that names\n // the input, so with suggestions it needs that label's id.\n const {\n controlId,\n fieldLabelProps,\n labelled,\n labelId: listLabelId,\n } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: ownField,\n needsLabelId: hasSuggestions,\n });\n\n // Get display value from tag\n const getDisplayValue = (tag: TaginputTag): string => {\n if (typeof tag === 'string') return tag;\n const fieldValue = tag[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return tag.value || '';\n };\n\n // Filter autocomplete data\n const filteredData = data.filter(item => {\n const displayValue = item.toLowerCase();\n const matchesInput = displayValue.includes(inputValue.toLowerCase());\n const notAlreadyAdded =\n allowDuplicates ||\n !tags.some(tag => getDisplayValue(tag).toLowerCase() === displayValue);\n const hasInput = inputValue || (openOnFocus && isActive);\n return matchesInput && notAlreadyAdded && hasInput;\n });\n // At the tag limit the list stays closed, since it could only offer tags\n // past the limit (#1087).\n const listOpen = isActive && !isMaxReached && filteredData.length > 0;\n\n // keepFirst: auto-highlight first item when dropdown opens\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length]);\n\n // Update tags\n const updateTags = useCallback(\n (newTags: TaginputTag[]) => {\n if (controlledValue === undefined) {\n setInternalTags(newTags);\n }\n onChange?.(newTags);\n },\n [controlledValue, onChange]\n );\n\n // Add tags from text typed, pasted or picked from the list. Each one is\n // checked against the tags before it, this batch's included, so a paste\n // of several adds them all in one change (#1101). Only `createTag` turns\n // text into an object.\n const addTags = useCallback(\n (values: string[]) => {\n if (disabled || readonly) return;\n\n let next = tags;\n const added: TaginputTag[] = [];\n for (const value of values) {\n // A paste can bring more tags than there's room for, and at the\n // limit the read-only input still takes Enter.\n if (maxTags !== undefined && next.length >= maxTags) break;\n\n const displayValue = value.trim();\n if (!displayValue) continue;\n const lower = displayValue.toLowerCase();\n\n // Duplicates, data and the dropdown filter all compare\n // case-insensitively.\n if (\n !allowDuplicates &&\n next.some(tag => getDisplayValue(tag).toLowerCase() === lower)\n )\n continue;\n\n // Without allowNew, only a suggestion can become a tag.\n if (!allowNew && !data.some(d => d.toLowerCase() === lower)) continue;\n\n if (beforeAdding && !beforeAdding(displayValue)) continue;\n\n const tag = createTag ? createTag(displayValue) : displayValue;\n next = [...next, tag];\n added.push(tag);\n }\n if (added.length === 0) return;\n\n updateTags(next);\n added.forEach(tag => onAdd?.(tag));\n setInputValue('');\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [\n disabled,\n readonly,\n tags,\n maxTags,\n allowDuplicates,\n allowNew,\n data,\n field,\n updateTags,\n onAdd,\n beforeAdding,\n createTag,\n keepOpen,\n ]\n );\n\n // Remove tag\n const removeTag = useCallback(\n (index: number) => {\n /* istanbul ignore next: both triggers (delete button click, Backspace handler) are already gated on disabled/readonly */\n if (disabled || readonly) return;\n\n const removedTag = tags[index];\n const newTags = tags.filter((_, i) => i !== index);\n updateTags(newTags);\n onRemove?.(removedTag, index);\n },\n [disabled, readonly, tags, updateTags, onRemove]\n );\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n\n // Check if a confirm key was typed\n const lastChar = newValue.slice(-1);\n if (confirmKeys.includes(lastChar) && lastChar !== 'Enter') {\n const valueWithoutKey = newValue.slice(0, -1).trim();\n if (valueWithoutKey) {\n addTags([valueWithoutKey]);\n }\n return;\n }\n\n setInputValue(newValue);\n onTyping?.(newValue);\n\n if (newValue && data.length > 0) {\n setIsActive(true);\n }\n },\n [confirmKeys, addTags, onTyping, data.length]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (onPasteSeparators.length === 0) return;\n\n const pastedText = e.clipboardData.getData('text');\n // Check if any separator exists in the pasted text\n const hasSeparator = onPasteSeparators.some(sep =>\n pastedText.includes(sep)\n );\n\n if (!hasSeparator) return;\n\n e.preventDefault();\n\n // Build a character class from all separators. A `-` is escaped\n // too, since between two others it would make a range.\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[-.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n addTags(pastedText.split(regex));\n },\n [onPasteSeparators, addTags]\n );\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && data.length > 0 && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, data.length, disabled]);\n\n // Reaching the limit dismisses the list the way a click outside does, so\n // making room later doesn't bring it back unasked. It's an effect, not a\n // step in addTag, because a click on a suggestion also bubbles to the\n // container, whose focus on the input reopens the list in that same\n // event, and because a controlled value can reach the limit too.\n useEffect(() => {\n if (isMaxReached) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n }, [isMaxReached]);\n\n // Handle click outside\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !isEventInside(e, containerRef.current)) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [isActive]);\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled || readonly || isComposing(e)) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTags([filteredData[highlightedIndex]]);\n } else if (inputValue.trim()) {\n addTags([inputValue]);\n }\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive && data.length > 0) {\n setIsActive(true);\n } else {\n setHighlightedIndex(prev =>\n prev < filteredData.length - 1 ? prev + 1 : prev\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : prev));\n break;\n case 'Backspace':\n if (removeOnKeys && !inputValue && tags.length > 0) {\n e.preventDefault();\n removeTag(tags.length - 1);\n }\n break;\n case 'Escape':\n // Closing the suggestions claims the key, so a Modal around the\n // field stays open. With none showing, the key goes on to it.\n if (listOpen) e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTags,\n inputValue,\n isActive,\n listOpen,\n data.length,\n removeOnKeys,\n tags.length,\n removeTag,\n ]\n );\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n }\n },\n [ref]\n );\n\n // Focus input when container is clicked\n const handleContainerClick = useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n // Generate classes\n const taginputClasses = pcn('taginput', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n [`is-${color}`]: !!color,\n 'is-disabled': disabled,\n 'is-rounded': rounded,\n 'is-ellipsis': ellipsis,\n });\n\n const containerClasses = pcn('taginput-container', {\n 'is-attached': attached,\n 'has-icons-left': !!icon,\n });\n\n const inputClasses = pcn('input', {\n [`is-${size}`]: !!size,\n });\n\n const tagClasses = pcn('tag', {\n [`is-${tagColor}`]: !!tagColor,\n [`is-${size}`]: !!size,\n });\n\n const combinedClasses = classNames(\n taginputClasses,\n bulmaHelperClasses,\n className\n );\n\n // Counter text\n const showCounter =\n hasCounter && (maxTags !== undefined || maxlength !== undefined);\n const counterText =\n maxTags !== undefined\n ? `${tags.length} / ${maxTags}`\n : maxlength !== undefined\n ? `${inputValue.length} / ${maxlength}`\n : '';\n\n const counterClasses = pcn('help', 'counter');\n const tagsClasses = pcn('tags');\n const dropdownMenuClasses = pcn('dropdown-menu', 'is-active');\n const dropdownContentClasses = pcn('dropdown-content');\n const iconRightClass = pcn('icon', 'is-right');\n const loaderClass = pcn('loader', 'is-loading');\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n // The combobox controls its listbox and points at the highlighted option,\n // the way Autocomplete's does. The listbox takes its name from the label\n // that names the combobox, the one this renders or a surrounding Field's,\n // and keeps a fallback name when no label names it or the one that does\n // has no id to point at. While no suggestion matches there's no listbox,\n // so the combobox is collapsed and points at nothing. It skips a\n // highlighted suggestion that's blank once trimmed, since that one can't\n // become a tag, and the option it points at is the one marked selected.\n const optionId = (index: number) => `${listboxId}-${index}`;\n const activeOptionId =\n listOpen && filteredData[highlightedIndex]?.trim()\n ? optionId(highlightedIndex)\n : undefined;\n const comboboxProps: React.InputHTMLAttributes<HTMLInputElement> = {\n role: 'combobox',\n 'aria-expanded': listOpen,\n 'aria-controls': listOpen ? listboxId : undefined,\n 'aria-activedescendant': activeOptionId,\n 'aria-haspopup': 'listbox',\n 'aria-autocomplete': 'list',\n };\n\n const taginputElement = (\n <div\n ref={containerRef}\n className={combinedClasses}\n onClick={handleContainerClick}\n {...rest}\n >\n <div className={containerClasses}>\n {icon && (\n <Icon\n name={icon}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n containerClassName={pcn('icon', 'is-left')}\n />\n )}\n <div className={tagsClasses}>\n {tags.map((tag, index) => {\n const displayVal = getDisplayValue(tag);\n return (\n <span key={index} className={tagClasses}>\n {tagTemplate ? (\n tagTemplate(tag)\n ) : ellipsis ? (\n <span title={displayVal}>{displayVal}</span>\n ) : (\n displayVal\n )}\n {closable && !disabled && !readonly && (\n <button\n type=\"button\"\n className={pcn('delete', 'is-small')}\n onClick={e => {\n e.stopPropagation();\n removeTag(index);\n }}\n aria-label={ariaCloseLabel || `Remove ${displayVal}`}\n />\n )}\n </span>\n );\n })}\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={tags.length === 0 ? placeholder : undefined}\n disabled={disabled}\n // Read-only at the tag limit rather than gone, so focus stays\n // put and a label keeps naming it, and Backspace still makes\n // room (#1103).\n readOnly={readonly || isMaxReached}\n maxLength={maxlength}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n {...(hasSuggestions && comboboxProps)}\n // Fallback name, dropped only when a rendered label actually\n // targets this input, its own or a surrounding Field's\n // (aria-label would win otherwise). A label pointing elsewhere\n // keeps the fallback so the input is never nameless.\n aria-label={labelled ? undefined : 'Add tag'}\n // The counter, while it shows, describes the input, so at the\n // limit it says why the field takes no more.\n aria-describedby={showCounter ? counterId : undefined}\n />\n </div>\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {listOpen && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n id={listboxId}\n className={dropdownContentClasses}\n role=\"listbox\"\n aria-labelledby={listLabelId}\n aria-label={listLabelId ? undefined : 'Suggestions'}\n >\n {filteredData.map((item, index) => (\n <a\n key={index}\n id={optionId(index)}\n className={pcn('dropdown-item', {\n 'is-active': index === highlightedIndex,\n })}\n onClick={() => addTags([item])}\n onMouseEnter={() => setHighlightedIndex(index)}\n role=\"option\"\n aria-selected={optionId(index) === activeOptionId}\n >\n {item}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {showCounter && (\n <small id={counterId} className={counterClasses}>\n {counterText}\n </small>\n )}\n\n {name &&\n tags.map((tag, i) => (\n <input\n key={`tag-input-${i}`}\n type=\"hidden\"\n name={name}\n value={getDisplayValue(tag)}\n form={form}\n />\n ))}\n </div>\n );\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {taginputElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {taginputElement}\n {messageEl}\n </>\n );\n }\n);\n\nTaginput.displayName = 'Taginput';\n\n/** @deprecated Use `Taginput` — same component. */\nexport const TagInput = Taginput;\n\n/** @deprecated Use `TaginputProps`. */\nexport type TagInputProps = TaginputProps;\n\nexport default Taginput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Taginput.js","sources":["../../../src/form/Taginput.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n useId,\n} from 'react';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { useConfig, useIconLibrary } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { isEventInside } from '../helpers/shadowDom';\nimport { useLocaleMatcher, useNumberFormat } from '../helpers/localeFormat';\nimport {\n useInsideField,\n useInsideControl,\n rendersOwnField,\n useFieldsetDisabled,\n} from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { Icon } from '../elements/Icon';\n\n/**\n * Represents a tag item object with a value and optional label.\n */\nexport interface TaginputItem {\n /** The tag value. */\n value: string;\n /** Display label (optional). */\n label?: string;\n [key: string]: unknown;\n}\n\n/** A tag can be either a TaginputItem object or a plain string. */\nexport type TaginputTag = TaginputItem | string;\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n// An IME that's composing owns every key: Enter confirms what it composed,\n// the arrows move through its candidates, and Escape cancels it. Safari can\n// say so with `keyCode` 229 rather than `isComposing` (#1102).\nconst isComposing = (e: React.KeyboardEvent): boolean =>\n e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229;\n\n/**\n * Props for the Taginput component.\n * Inside an outer `Field`, or a `Control` with no `Field` around it, it\n * renders no `Field` of its own. The exception is `label`, `message`,\n * `horizontal` or `fieldClassName` in that bare `Control`: it keeps a `Field`\n * for them, nested in the `.control`, and warns in development. Wrap the\n * `Control` in a `Field` instead, and set the `label`, `horizontal` and class\n * name on that `Field`.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface TaginputProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label. Automatically associated with the text input via `htmlFor` — uses your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose own label associates instead when that `Field` generates a target id (not `grouped`/`hasAddons`, no explicit `labelProps.htmlFor`) and you set no `id` here; it then replaces the `aria-label=\"Add tag\"` fallback too. With `data`, the label naming the input also names the open suggestion list, through `aria-labelledby`, when it has an id: this label always does, and an outer `Field`'s does unless you wired it by hand without an `id` in its `labelProps`. Otherwise the list is named \"Suggestions\". */\n label?: React.ReactNode;\n /** Props for the label element. An explicit `htmlFor` here overrides the automatic association (no id is generated then). With `data`, while the label names the input, the suggestion list's `aria-labelledby` points at it, through an `id` here when you give one and a generated one otherwise. */\n labelProps?: React.LabelHTMLAttributes<HTMLLabelElement> & {\n [key: string]: unknown;\n };\n /** Applied to the inner text input (the labellable control), not the wrapper div. */\n id?: string;\n /** The current tags (controlled). */\n value?: TaginputTag[];\n /** Default tags (uncontrolled). */\n defaultValue?: TaginputTag[];\n /**\n * Autocomplete suggestions. With `data` set, even to an empty array, the\n * text input is a `role=\"combobox\"` that controls the suggestion list and\n * points `aria-activedescendant` at the highlighted suggestion. Without it\n * there's no list, so the input stays a plain text field. The list shows\n * the suggestions that contain what's typed, ignoring case, and inside a\n * `LocaleProvider` with a `locale`, ignoring accents too where that\n * language does, so \"cafe\" finds \"Café\".\n */\n data?: string[];\n /** Placeholder text when no tags. */\n placeholder?: string;\n /** Object property to use as display field. */\n field?: string;\n /** Allow creating new tags not in suggestions. */\n allowNew?: boolean;\n /** Allow duplicate tags. */\n allowDuplicates?: boolean;\n /** Open autocomplete dropdown on focus. */\n openOnFocus?: boolean;\n /** Remove tag on backspace. Default: true. */\n removeOnKeys?: boolean;\n /** Keys to confirm tag creation. Default: ['Enter', ',']. */\n confirmKeys?: string[];\n /** Show close button on tags. Default: true. */\n closable?: boolean;\n /** Attach tags visually. */\n attached?: boolean;\n /**\n * Maximum number of tags allowed. At the limit the text input stays but\n * turns read-only, so focus stays put and the label still names it. It\n * takes no more tags and the suggestion list stays closed. Backspace (with\n * `removeOnKeys`) or a tag's remove button makes room again. While the\n * counter shows, it describes the input.\n */\n maxTags?: number;\n /** Maximum length of input. */\n maxlength?: number;\n /** Whether the input is disabled. */\n disabled?: boolean;\n /** Whether the input is read-only. */\n readonly?: boolean;\n /** Applies rounded corners to the tags. */\n rounded?: boolean;\n /** Truncates long tag text with ellipsis. */\n ellipsis?: boolean;\n /**\n * Shows a counter of the number of tags, written the way the `locale` of\n * a `LocaleProvider` around it writes numbers.\n */\n hasCounter?: boolean;\n /**\n * Characters that split pasted text into tags. Each part goes through the\n * same checks as a typed tag, against the tags before it, the paste's own\n * included, and adding stops at `maxTags`. `onChange` fires once for the\n * whole paste, and `onAdd` once for each tag it adds.\n */\n onPasteSeparators?: string[];\n /** Validation function called before adding a tag. */\n beforeAdding?: (tag: string) => boolean;\n /** Custom function for creating tag objects from input. */\n createTag?: (input: string) => TaginputTag;\n /** Keeps the first autocomplete suggestion highlighted. */\n keepFirst?: boolean;\n /** Keeps the autocomplete dropdown open after selection. */\n keepOpen?: boolean;\n /**\n * Shows a loading spinner in the input.\n * Under `prefers-reduced-motion: reduce` the spinner stops and stays\n * drawn (with bestax's CSS loaded).\n */\n loading?: boolean;\n /** ARIA label for tag close buttons. */\n ariaCloseLabel?: string;\n /** Icon name for the input field. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Tag color variant. */\n tagColor?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'dark'\n | 'light';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. When set, one hidden input per tag is rendered. */\n name?: string;\n /** Optional id of the form the hidden inputs belong to. */\n form?: string;\n /** Callback when tags change. */\n onChange?: (tags: TaginputTag[]) => void;\n /** Callback when tag is added. */\n onAdd?: (tag: TaginputTag) => void;\n /** Callback when tag is removed. */\n onRemove?: (tag: TaginputTag, index: number) => void;\n /** Callback when typing in input. */\n onTyping?: (value: string) => void;\n /** Custom render for tags. */\n tagTemplate?: (tag: TaginputTag) => React.ReactNode;\n}\n\n/**\n * The `Taginput` component provides a tag/chip input field for managing multiple tags.\n *\n * @function\n * @param {TaginputProps} props - Props for the Taginput component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered taginput component.\n *\n * @example\n * // Basic usage\n * <Taginput\n * placeholder=\"Add a tag...\"\n * onChange={(tags) => console.log(tags)}\n * />\n *\n * @example\n * // With autocomplete\n * <Taginput\n * data={['React', 'Vue', 'Angular', 'Svelte']}\n * allowNew={false}\n * placeholder=\"Select frameworks...\"\n * />\n */\nexport const Taginput = forwardRef<HTMLInputElement, TaginputProps>(\n (\n {\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n value: controlledValue,\n defaultValue = [],\n data: dataProp,\n placeholder,\n field = 'label',\n allowNew = true,\n allowDuplicates = false,\n openOnFocus = false,\n removeOnKeys = true,\n confirmKeys = ['Enter', ','],\n closable = true,\n attached = false,\n maxTags,\n maxlength,\n disabled: disabledProp,\n readonly = false,\n rounded = false,\n ellipsis = false,\n hasCounter = true,\n onPasteSeparators = [','],\n beforeAdding,\n createTag,\n keepFirst = false,\n keepOpen = true,\n loading = false,\n ariaCloseLabel,\n icon,\n iconLibrary: iconLibraryProp,\n iconVariant,\n iconFeatures,\n color,\n tagColor,\n size,\n onChange,\n onAdd,\n onRemove,\n onTyping,\n tagTemplate,\n name,\n form,\n id,\n className,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const insideField = useInsideField();\n const insideControl = useInsideControl();\n const ownField = rendersOwnField('Taginput', {\n insideField,\n insideControl,\n label,\n message,\n horizontal,\n fieldClassName,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const defaultIconLibrary = useIconLibrary();\n const formatNumber = useNumberFormat();\n const matchText = useLocaleMatcher();\n const resolvedLibrary = iconLibraryProp || defaultIconLibrary || 'fa';\n const pcn = (\n ...args: (\n | string\n | number\n | undefined\n | null\n | false\n | Record<string, unknown>\n | unknown[]\n )[]\n ) => prefixedClassNames(classPrefix, ...args);\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalTags, setInternalTags] =\n useState<TaginputTag[]>(defaultValue);\n const [inputValue, setInputValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const baseId = useId();\n const listboxId = `${baseId}-listbox`;\n const counterId = `${baseId}-counter`;\n\n // With `data` the input offers suggestions, so it's a combobox, even\n // while none match. Without it there's never a list, so it stays a plain\n // text field.\n const hasSuggestions = dataProp !== undefined;\n const data = dataProp ?? [];\n\n // Use controlled or internal tags\n const tags = controlledValue !== undefined ? controlledValue : internalTags;\n\n const isMaxReached = maxTags !== undefined && tags.length >= maxTags;\n // The suggestion list points `aria-labelledby` at the label that names\n // the input, so with suggestions it needs that label's id.\n const {\n controlId,\n fieldLabelProps,\n labelled,\n labelId: listLabelId,\n } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: ownField,\n needsLabelId: hasSuggestions,\n });\n\n // Get display value from tag\n const getDisplayValue = (tag: TaginputTag): string => {\n if (typeof tag === 'string') return tag;\n const fieldValue = tag[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return tag.value || '';\n };\n\n // Filter autocomplete data\n const filteredData = data.filter(item => {\n const displayValue = item.toLowerCase();\n const matchesInput = matchText\n ? matchText(item, inputValue)\n : displayValue.includes(inputValue.toLowerCase());\n const notAlreadyAdded =\n allowDuplicates ||\n !tags.some(tag => getDisplayValue(tag).toLowerCase() === displayValue);\n const hasInput = inputValue || (openOnFocus && isActive);\n return matchesInput && notAlreadyAdded && hasInput;\n });\n // At the tag limit the list stays closed, since it could only offer tags\n // past the limit (#1087).\n const listOpen = isActive && !isMaxReached && filteredData.length > 0;\n\n // keepFirst: auto-highlight first item when dropdown opens\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length]);\n\n // Update tags\n const updateTags = useCallback(\n (newTags: TaginputTag[]) => {\n if (controlledValue === undefined) {\n setInternalTags(newTags);\n }\n onChange?.(newTags);\n },\n [controlledValue, onChange]\n );\n\n // Add tags from text typed, pasted or picked from the list. Each one is\n // checked against the tags before it, this batch's included, so a paste\n // of several adds them all in one change (#1101). Only `createTag` turns\n // text into an object.\n const addTags = useCallback(\n (values: string[]) => {\n if (disabled || readonly) return;\n\n let next = tags;\n const added: TaginputTag[] = [];\n for (const value of values) {\n // A paste can bring more tags than there's room for, and at the\n // limit the read-only input still takes Enter.\n if (maxTags !== undefined && next.length >= maxTags) break;\n\n const displayValue = value.trim();\n if (!displayValue) continue;\n const lower = displayValue.toLowerCase();\n\n // Duplicates, data and the dropdown filter all compare\n // case-insensitively.\n if (\n !allowDuplicates &&\n next.some(tag => getDisplayValue(tag).toLowerCase() === lower)\n )\n continue;\n\n // Without allowNew, only a suggestion can become a tag.\n if (!allowNew && !data.some(d => d.toLowerCase() === lower)) continue;\n\n if (beforeAdding && !beforeAdding(displayValue)) continue;\n\n const tag = createTag ? createTag(displayValue) : displayValue;\n next = [...next, tag];\n added.push(tag);\n }\n if (added.length === 0) return;\n\n updateTags(next);\n added.forEach(tag => onAdd?.(tag));\n setInputValue('');\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [\n disabled,\n readonly,\n tags,\n maxTags,\n allowDuplicates,\n allowNew,\n data,\n field,\n updateTags,\n onAdd,\n beforeAdding,\n createTag,\n keepOpen,\n ]\n );\n\n // Remove tag\n const removeTag = useCallback(\n (index: number) => {\n /* istanbul ignore next: both triggers (delete button click, Backspace handler) are already gated on disabled/readonly */\n if (disabled || readonly) return;\n\n const removedTag = tags[index];\n const newTags = tags.filter((_, i) => i !== index);\n updateTags(newTags);\n onRemove?.(removedTag, index);\n },\n [disabled, readonly, tags, updateTags, onRemove]\n );\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n\n // Check if a confirm key was typed\n const lastChar = newValue.slice(-1);\n if (confirmKeys.includes(lastChar) && lastChar !== 'Enter') {\n const valueWithoutKey = newValue.slice(0, -1).trim();\n if (valueWithoutKey) {\n addTags([valueWithoutKey]);\n }\n return;\n }\n\n setInputValue(newValue);\n onTyping?.(newValue);\n\n if (newValue && data.length > 0) {\n setIsActive(true);\n }\n },\n [confirmKeys, addTags, onTyping, data.length]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLInputElement>) => {\n if (onPasteSeparators.length === 0) return;\n\n const pastedText = e.clipboardData.getData('text');\n // Check if any separator exists in the pasted text\n const hasSeparator = onPasteSeparators.some(sep =>\n pastedText.includes(sep)\n );\n\n if (!hasSeparator) return;\n\n e.preventDefault();\n\n // Build a character class from all separators. A `-` is escaped\n // too, since between two others it would make a range.\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[-.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n addTags(pastedText.split(regex));\n },\n [onPasteSeparators, addTags]\n );\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && data.length > 0 && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, data.length, disabled]);\n\n // Reaching the limit dismisses the list the way a click outside does, so\n // making room later doesn't bring it back unasked. It's an effect, not a\n // step in addTag, because a click on a suggestion also bubbles to the\n // container, whose focus on the input reopens the list in that same\n // event, and because a controlled value can reach the limit too.\n useEffect(() => {\n if (isMaxReached) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n }, [isMaxReached]);\n\n // Handle click outside\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (containerRef.current && !isEventInside(e, containerRef.current)) {\n setIsActive(false);\n setHighlightedIndex(-1);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [isActive]);\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled || readonly || isComposing(e)) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTags([filteredData[highlightedIndex]]);\n } else if (inputValue.trim()) {\n addTags([inputValue]);\n }\n return;\n }\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive && data.length > 0) {\n setIsActive(true);\n } else {\n setHighlightedIndex(prev =>\n prev < filteredData.length - 1 ? prev + 1 : prev\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n setHighlightedIndex(prev => (prev > 0 ? prev - 1 : prev));\n break;\n case 'Backspace':\n if (removeOnKeys && !inputValue && tags.length > 0) {\n e.preventDefault();\n removeTag(tags.length - 1);\n }\n break;\n case 'Escape':\n // Closing the suggestions claims the key, so a Modal around the\n // field stays open. With none showing, the key goes on to it.\n if (listOpen) e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTags,\n inputValue,\n isActive,\n listOpen,\n data.length,\n removeOnKeys,\n tags.length,\n removeTag,\n ]\n );\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLInputElement | null) => {\n (inputRef as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLInputElement | null>).current =\n node;\n }\n },\n [ref]\n );\n\n // Focus input when container is clicked\n const handleContainerClick = useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n // Generate classes\n const taginputClasses = pcn('taginput', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n [`is-${color}`]: !!color,\n 'is-disabled': disabled,\n 'is-rounded': rounded,\n 'is-ellipsis': ellipsis,\n });\n\n const containerClasses = pcn('taginput-container', {\n 'is-attached': attached,\n 'has-icons-left': !!icon,\n });\n\n const inputClasses = pcn('input', {\n [`is-${size}`]: !!size,\n });\n\n const tagClasses = pcn('tag', {\n [`is-${tagColor}`]: !!tagColor,\n [`is-${size}`]: !!size,\n });\n\n const combinedClasses = classNames(\n taginputClasses,\n bulmaHelperClasses,\n className\n );\n\n // Counter text\n const showCounter =\n hasCounter && (maxTags !== undefined || maxlength !== undefined);\n const write = formatNumber ?? String;\n const counterText =\n maxTags !== undefined\n ? `${write(tags.length)} / ${write(maxTags)}`\n : maxlength !== undefined\n ? `${write(inputValue.length)} / ${write(maxlength)}`\n : '';\n\n const counterClasses = pcn('help', 'counter');\n const tagsClasses = pcn('tags');\n const dropdownMenuClasses = pcn('dropdown-menu', 'is-active');\n const dropdownContentClasses = pcn('dropdown-content');\n const iconRightClass = pcn('icon', 'is-right');\n const loaderClass = pcn('loader', 'is-loading');\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n // The combobox controls its listbox and points at the highlighted option,\n // the way Autocomplete's does. The listbox takes its name from the label\n // that names the combobox, the one this renders or a surrounding Field's,\n // and keeps a fallback name when no label names it or the one that does\n // has no id to point at. While no suggestion matches there's no listbox,\n // so the combobox is collapsed and points at nothing. It skips a\n // highlighted suggestion that's blank once trimmed, since that one can't\n // become a tag, and the option it points at is the one marked selected.\n const optionId = (index: number) => `${listboxId}-${index}`;\n const activeOptionId =\n listOpen && filteredData[highlightedIndex]?.trim()\n ? optionId(highlightedIndex)\n : undefined;\n const comboboxProps: React.InputHTMLAttributes<HTMLInputElement> = {\n role: 'combobox',\n 'aria-expanded': listOpen,\n 'aria-controls': listOpen ? listboxId : undefined,\n 'aria-activedescendant': activeOptionId,\n 'aria-haspopup': 'listbox',\n 'aria-autocomplete': 'list',\n };\n\n const taginputElement = (\n <div\n ref={containerRef}\n className={combinedClasses}\n onClick={handleContainerClick}\n {...rest}\n >\n <div className={containerClasses}>\n {icon && (\n <Icon\n name={icon}\n library={resolvedLibrary}\n variant={iconVariant}\n features={iconFeatures}\n containerClassName={pcn('icon', 'is-left')}\n />\n )}\n <div className={tagsClasses}>\n {tags.map((tag, index) => {\n const displayVal = getDisplayValue(tag);\n return (\n <span key={index} className={tagClasses}>\n {tagTemplate ? (\n tagTemplate(tag)\n ) : ellipsis ? (\n <span title={displayVal}>{displayVal}</span>\n ) : (\n displayVal\n )}\n {closable && !disabled && !readonly && (\n <button\n type=\"button\"\n className={pcn('delete', 'is-small')}\n onClick={e => {\n e.stopPropagation();\n removeTag(index);\n }}\n aria-label={ariaCloseLabel || `Remove ${displayVal}`}\n />\n )}\n </span>\n );\n })}\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={tags.length === 0 ? placeholder : undefined}\n disabled={disabled}\n // Read-only at the tag limit rather than gone, so focus stays\n // put and a label keeps naming it, and Backspace still makes\n // room (#1103).\n readOnly={readonly || isMaxReached}\n maxLength={maxlength}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n {...(hasSuggestions && comboboxProps)}\n // Fallback name, dropped only when a rendered label actually\n // targets this input, its own or a surrounding Field's\n // (aria-label would win otherwise). A label pointing elsewhere\n // keeps the fallback so the input is never nameless.\n aria-label={labelled ? undefined : 'Add tag'}\n // The counter, while it shows, describes the input, so at the\n // limit it says why the field takes no more.\n aria-describedby={showCounter ? counterId : undefined}\n />\n </div>\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {listOpen && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n id={listboxId}\n className={dropdownContentClasses}\n role=\"listbox\"\n aria-labelledby={listLabelId}\n aria-label={listLabelId ? undefined : 'Suggestions'}\n >\n {filteredData.map((item, index) => (\n <a\n key={index}\n id={optionId(index)}\n className={pcn('dropdown-item', {\n 'is-active': index === highlightedIndex,\n })}\n onClick={() => addTags([item])}\n onMouseEnter={() => setHighlightedIndex(index)}\n role=\"option\"\n aria-selected={optionId(index) === activeOptionId}\n >\n {item}\n </a>\n ))}\n </div>\n </div>\n )}\n\n {showCounter && (\n <small id={counterId} className={counterClasses}>\n {counterText}\n </small>\n )}\n\n {name &&\n tags.map((tag, i) => (\n <input\n key={`tag-input-${i}`}\n type=\"hidden\"\n name={name}\n value={getDisplayValue(tag)}\n form={form}\n />\n ))}\n </div>\n );\n\n if (ownField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {taginputElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {taginputElement}\n {messageEl}\n </>\n );\n }\n);\n\nTaginput.displayName = 'Taginput';\n\n/** @deprecated Use `Taginput` — same component. */\nexport const TagInput = Taginput;\n\n/** @deprecated Use `TaginputProps`. */\nexport type TagInputProps = TaginputProps;\n\nexport default Taginput;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":";;;;;;;;;;;;;AA4CA;AACA;AACA;AACA,MAAM,WAAW,GAAG,CAAC,CAAsB,KACzC,CAAC,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,KAAK,GAAG;AA8I5D;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACI,MAAM,QAAQ,GAAG,UAAU,CAChC,CACE;AACE;AACA,KAAK,EACL,SAAS,EACT,UAAU,EACV,UAAU,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,KAAK,EAAE,eAAe,EACtB,YAAY,GAAG,EAAE,EACjB,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,KAAK,GAAG,OAAO,EACf,QAAQ,GAAG,IAAI,EACf,eAAe,GAAG,KAAK,EACvB,WAAW,GAAG,KAAK,EACnB,YAAY,GAAG,IAAI,EACnB,WAAW,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,EAC5B,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,KAAK,EAChB,OAAO,EACP,SAAS,EACT,QAAQ,EAAE,YAAY,EACtB,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,QAAQ,GAAG,KAAK,EAChB,UAAU,GAAG,IAAI,EACjB,iBAAiB,GAAG,CAAC,GAAG,CAAC,EACzB,YAAY,EACZ,SAAS,EACT,SAAS,GAAG,KAAK,EACjB,QAAQ,GAAG,IAAI,EACf,OAAO,GAAG,KAAK,EACf,cAAc,EACd,IAAI,EACJ,WAAW,EAAE,eAAe,EAC5B,WAAW,EACX,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,IAAI,EACJ,EAAE,EACF,SAAS,EACT,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,CAAC;AAClD,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;AACpC,IAAA,MAAM,aAAa,GAAG,gBAAgB,EAAE;AACxC,IAAA,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE;QAC3C,WAAW;QACX,aAAa;QACb,KAAK;QACL,OAAO;QACP,UAAU;QACV,cAAc;AACf,KAAA,CAAC;IACF,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC;AAC3D,IAAA,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE;AACnC,IAAA,MAAM,kBAAkB,GAAG,cAAc,EAAE;AAC3C,IAAA,MAAM,YAAY,GAAG,eAAe,EAAE;AACtC,IAAA,MAAM,SAAS,GAAG,gBAAgB,EAAE;AACpC,IAAA,MAAM,eAAe,GAAG,eAAe,IAAI,kBAAkB,IAAI,IAAI;AACrE,IAAA,MAAM,GAAG,GAAG,CACV,GAAG,IAQA,KACA,kBAAkB,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC;AAC7C,IAAA,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC;AACjD,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC;AAC/C,IAAA,MAAM,WAAW,GAAG,MAAM,CAAiB,IAAI,CAAC;IAEhD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GACnC,QAAQ,CAAgB,YAAY,CAAC;IACvC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC/C,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC5D,IAAA,MAAM,MAAM,GAAG,KAAK,EAAE;AACtB,IAAA,MAAM,SAAS,GAAG,CAAA,EAAG,MAAM,UAAU;AACrC,IAAA,MAAM,SAAS,GAAG,CAAA,EAAG,MAAM,UAAU;;;;AAKrC,IAAA,MAAM,cAAc,GAAG,QAAQ,KAAK,SAAS;AAC7C,IAAA,MAAM,IAAI,GAAG,QAAQ,IAAI,EAAE;;AAG3B,IAAA,MAAM,IAAI,GAAG,eAAe,KAAK,SAAS,GAAG,eAAe,GAAG,YAAY;IAE3E,MAAM,YAAY,GAAG,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO;;;AAGpE,IAAA,MAAM,EACJ,SAAS,EACT,eAAe,EACf,QAAQ,EACR,OAAO,EAAE,WAAW,GACrB,GAAG,cAAc,CAAC;QACjB,KAAK;QACL,EAAE;QACF,UAAU;AACV,QAAA,YAAY,EAAE,QAAQ;AACtB,QAAA,YAAY,EAAE,cAAc;AAC7B,KAAA,CAAC;;AAGF,IAAA,MAAM,eAAe,GAAG,CAAC,GAAgB,KAAY;QACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,YAAA,OAAO,GAAG;AACvC,QAAA,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC;QAC7B,IAAI,OAAO,UAAU,KAAK,QAAQ;AAAE,YAAA,OAAO,UAAU;AACrD,QAAA,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;AACxB,IAAA,CAAC;;IAGD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,IAAG;AACtC,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE;QACvC,MAAM,YAAY,GAAG;AACnB,cAAE,SAAS,CAAC,IAAI,EAAE,UAAU;cAC1B,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QACnD,MAAM,eAAe,GACnB,eAAe;AACf,YAAA,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC;QACxE,MAAM,QAAQ,GAAG,UAAU,KAAK,WAAW,IAAI,QAAQ,CAAC;AACxD,QAAA,OAAO,YAAY,IAAI,eAAe,IAAI,QAAQ;AACpD,IAAA,CAAC,CAAC;;;AAGF,IAAA,MAAM,QAAQ,GAAG,QAAQ,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC;;IAGrE,SAAS,CAAC,MAAK;QACb,IAAI,SAAS,IAAI,QAAQ,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE;YACpD,mBAAmB,CAAC,CAAC,CAAC;QACxB;IACF,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;;AAG9C,IAAA,MAAM,UAAU,GAAG,WAAW,CAC5B,CAAC,OAAsB,KAAI;AACzB,QAAA,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,eAAe,CAAC,OAAO,CAAC;QAC1B;AACA,QAAA,QAAQ,GAAG,OAAO,CAAC;AACrB,IAAA,CAAC,EACD,CAAC,eAAe,EAAE,QAAQ,CAAC,CAC5B;;;;;AAMD,IAAA,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,MAAgB,KAAI;QACnB,IAAI,QAAQ,IAAI,QAAQ;YAAE;QAE1B,IAAI,IAAI,GAAG,IAAI;QACf,MAAM,KAAK,GAAkB,EAAE;AAC/B,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;;;YAG1B,IAAI,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO;gBAAE;AAErD,YAAA,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,EAAE;AACjC,YAAA,IAAI,CAAC,YAAY;gBAAE;AACnB,YAAA,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE;;;AAIxC,YAAA,IACE,CAAC,eAAe;AAChB,gBAAA,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;gBAE9D;;AAGF,YAAA,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;gBAAE;AAE7D,YAAA,IAAI,YAAY,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;gBAAE;AAEjD,YAAA,MAAM,GAAG,GAAG,SAAS,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,YAAY;AAC9D,YAAA,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC;AACrB,YAAA,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QACjB;AACA,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE;QAExB,UAAU,CAAC,IAAI,CAAC;AAChB,QAAA,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC;QAClC,aAAa,CAAC,EAAE,CAAC;QACjB,IAAI,CAAC,QAAQ,EAAE;YACb,WAAW,CAAC,KAAK,CAAC;QACpB;AACA,QAAA,mBAAmB,CAAC,EAAE,CAAC;AACzB,IAAA,CAAC,EACD;QACE,QAAQ;QACR,QAAQ;QACR,IAAI;QACJ,OAAO;QACP,eAAe;QACf,QAAQ;QACR,IAAI;QACJ,KAAK;QACL,UAAU;QACV,KAAK;QACL,YAAY;QACZ,SAAS;QACT,QAAQ;AACT,KAAA,CACF;;AAGD,IAAA,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,KAAa,KAAI;;QAEhB,IAAI,QAAQ,IAAI,QAAQ;YAAE;AAE1B,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC;AAC9B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;QAClD,UAAU,CAAC,OAAO,CAAC;AACnB,QAAA,QAAQ,GAAG,UAAU,EAAE,KAAK,CAAC;AAC/B,IAAA,CAAC,EACD,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,CACjD;;AAGD,IAAA,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,CAAsC,KAAI;AACzC,QAAA,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK;;QAG/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,OAAO,EAAE;AAC1D,YAAA,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE;YACpD,IAAI,eAAe,EAAE;AACnB,gBAAA,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC;YAC5B;YACA;QACF;QAEA,aAAa,CAAC,QAAQ,CAAC;AACvB,QAAA,QAAQ,GAAG,QAAQ,CAAC;QAEpB,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;YAC/B,WAAW,CAAC,IAAI,CAAC;QACnB;AACF,IAAA,CAAC,EACD,CAAC,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAC9C;;AAGD,IAAA,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,CAAyC,KAAI;AAC5C,QAAA,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC;YAAE;QAEpC,MAAM,UAAU,GAAG,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC;;AAElD,QAAA,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,IAC7C,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CACzB;AAED,QAAA,IAAI,CAAC,YAAY;YAAE;QAEnB,CAAC,CAAC,cAAc,EAAE;;;AAIlB,QAAA,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAC/C,CAAC,CAAC,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAC1C;AACD,QAAA,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,CAAA,CAAA,EAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA,CAAA,CAAG,CAAC;QAE3D,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAClC,IAAA,CAAC,EACD,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAC7B;;AAGD,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,MAAK;QACnC,IAAI,WAAW,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC/C,WAAW,CAAC,IAAI,CAAC;QACnB;IACF,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;;;;;;IAOxC,SAAS,CAAC,MAAK;QACb,IAAI,YAAY,EAAE;YAChB,WAAW,CAAC,KAAK,CAAC;AAClB,YAAA,mBAAmB,CAAC,EAAE,CAAC;QACzB;AACF,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;;IAGlB,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,SAAS;AAE/B,QAAA,MAAM,kBAAkB,GAAG,CAAC,CAAa,KAAI;AAC3C,YAAA,IAAI,YAAY,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE;gBACnE,WAAW,CAAC,KAAK,CAAC;AAClB,gBAAA,mBAAmB,CAAC,EAAE,CAAC;YACzB;AACF,QAAA,CAAC;AAED,QAAA,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC;QAC1D,OAAO,MACL,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC;AACjE,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;;AAGd,IAAA,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,CAAsB,KAAI;AACzB,QAAA,IAAI,QAAQ,IAAI,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC;YAAE;;QAG5C,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;YAC/B,CAAC,CAAC,cAAc,EAAE;YAClB,IAAI,gBAAgB,IAAI,CAAC,IAAI,YAAY,CAAC,gBAAgB,CAAC,EAAE;gBAC3D,OAAO,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAC3C;AAAO,iBAAA,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE;AAC5B,gBAAA,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC;YACvB;YACA;QACF;AAEA,QAAA,QAAQ,CAAC,CAAC,GAAG;AACX,YAAA,KAAK,WAAW;gBACd,CAAC,CAAC,cAAc,EAAE;gBAClB,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;oBAChC,WAAW,CAAC,IAAI,CAAC;gBACnB;qBAAO;oBACL,mBAAmB,CAAC,IAAI,IACtB,IAAI,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CACjD;gBACH;gBACA;AACF,YAAA,KAAK,SAAS;gBACZ,CAAC,CAAC,cAAc,EAAE;gBAClB,mBAAmB,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;gBACzD;AACF,YAAA,KAAK,WAAW;gBACd,IAAI,YAAY,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;oBAClD,CAAC,CAAC,cAAc,EAAE;AAClB,oBAAA,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC5B;gBACA;AACF,YAAA,KAAK,QAAQ;;;AAGX,gBAAA,IAAI,QAAQ;oBAAE,CAAC,CAAC,cAAc,EAAE;gBAChC,WAAW,CAAC,KAAK,CAAC;AAClB,gBAAA,mBAAmB,CAAC,EAAE,CAAC;gBACvB;;AAEN,IAAA,CAAC,EACD;QACE,QAAQ;QACR,QAAQ;QACR,WAAW;QACX,gBAAgB;QAChB,YAAY;QACZ,OAAO;QACP,UAAU;QACV,QAAQ;QACR,QAAQ;AACR,QAAA,IAAI,CAAC,MAAM;QACX,YAAY;AACZ,QAAA,IAAI,CAAC,MAAM;QACX,SAAS;AACV,KAAA,CACF;;AAGD,IAAA,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAA6B,KAAI;AAC/B,QAAA,QAA4D,CAAC,OAAO;AACnE,YAAA,IAAI;AACN,QAAA,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;YAC7B,GAAG,CAAC,IAAI,CAAC;QACX;aAAO,IAAI,GAAG,EAAE;AACb,YAAA,GAAuD,CAAC,OAAO;AAC9D,gBAAA,IAAI;QACR;AACF,IAAA,CAAC,EACD,CAAC,GAAG,CAAC,CACN;;AAGD,IAAA,MAAM,oBAAoB,GAAG,WAAW,CAAC,MAAK;AAC5C,QAAA,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE;IAC3B,CAAC,EAAE,EAAE,CAAC;;AAGN,IAAA,MAAM,eAAe,GAAG,GAAG,CAAC,UAAU,EAAE;AACtC,QAAA,WAAW,EAAE,QAAQ;AACrB,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACtB,QAAA,CAAC,MAAM,KAAK,CAAA,CAAE,GAAG,CAAC,CAAC,KAAK;AACxB,QAAA,aAAa,EAAE,QAAQ;AACvB,QAAA,YAAY,EAAE,OAAO;AACrB,QAAA,aAAa,EAAE,QAAQ;AACxB,KAAA,CAAC;AAEF,IAAA,MAAM,gBAAgB,GAAG,GAAG,CAAC,oBAAoB,EAAE;AACjD,QAAA,aAAa,EAAE,QAAQ;QACvB,gBAAgB,EAAE,CAAC,CAAC,IAAI;AACzB,KAAA,CAAC;AAEF,IAAA,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,EAAE;AAChC,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACvB,KAAA,CAAC;AAEF,IAAA,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,EAAE;AAC5B,QAAA,CAAC,MAAM,QAAQ,CAAA,CAAE,GAAG,CAAC,CAAC,QAAQ;AAC9B,QAAA,CAAC,MAAM,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,IAAI;AACvB,KAAA,CAAC;IAEF,MAAM,eAAe,GAAG,UAAU,CAChC,eAAe,EACf,kBAAkB,EAClB,SAAS,CACV;;AAGD,IAAA,MAAM,WAAW,GACf,UAAU,KAAK,OAAO,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,CAAC;AAClE,IAAA,MAAM,KAAK,GAAG,YAAY,IAAI,MAAM;AACpC,IAAA,MAAM,WAAW,GACf,OAAO,KAAK;AACV,UAAE,CAAA,EAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA,GAAA,EAAM,KAAK,CAAC,OAAO,CAAC,CAAA;UACzC,SAAS,KAAK;AACd,cAAE,CAAA,EAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA,GAAA,EAAM,KAAK,CAAC,SAAS,CAAC,CAAA;cACjD,EAAE;IAEV,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;AAC7C,IAAA,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC;IAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC,eAAe,EAAE,WAAW,CAAC;AAC7D,IAAA,MAAM,sBAAsB,GAAG,GAAG,CAAC,kBAAkB,CAAC;IACtD,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;IAC9C,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC;AAE/C,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,EAAE;AAC9C,QAAA,CAAC,MAAM,YAAY,CAAA,CAAE,GAAG,CAAC,CAAC,YAAY;AACvC,KAAA,CAAC;AACF,IAAA,MAAM,SAAS,GAAG,OAAO,GAAGA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAE,SAAS,YAAG,OAAO,EAAA,CAAK,GAAG,IAAI;;;;;;;;;AAUzE,IAAA,MAAM,QAAQ,GAAG,CAAC,KAAa,KAAK,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE;IAC3D,MAAM,cAAc,GAClB,QAAQ,IAAI,YAAY,CAAC,gBAAgB,CAAC,EAAE,IAAI;AAC9C,UAAE,QAAQ,CAAC,gBAAgB;UACzB,SAAS;AACf,IAAA,MAAM,aAAa,GAAgD;AACjE,QAAA,IAAI,EAAE,UAAU;AAChB,QAAA,eAAe,EAAE,QAAQ;QACzB,eAAe,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS;AACjD,QAAA,uBAAuB,EAAE,cAAc;AACvC,QAAA,eAAe,EAAE,SAAS;AAC1B,QAAA,mBAAmB,EAAE,MAAM;KAC5B;AAED,IAAA,MAAM,eAAe,IACnBC,IAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,eAAe,EAC1B,OAAO,EAAE,oBAAoB,EAAA,GACzB,IAAI,EAAA,QAAA,EAAA,CAERA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,gBAAgB,aAC7B,IAAI,KACHD,GAAA,CAAC,IAAI,EAAA,EACH,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EAAA,CAC1C,CACH,EACDC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,WAAW,EAAA,QAAA,EAAA,CACxB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,KAAI;AACvB,gCAAA,MAAM,UAAU,GAAG,eAAe,CAAC,GAAG,CAAC;AACvC,gCAAA,QACEA,IAAA,CAAA,MAAA,EAAA,EAAkB,SAAS,EAAE,UAAU,EAAA,QAAA,EAAA,CACpC,WAAW,IACV,WAAW,CAAC,GAAG,CAAC,IACd,QAAQ,IACVD,GAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAE,UAAU,EAAA,QAAA,EAAG,UAAU,GAAQ,KAE5C,UAAU,CACX,EACA,QAAQ,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,KACjCA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,EACpC,OAAO,EAAE,CAAC,IAAG;gDACX,CAAC,CAAC,eAAe,EAAE;gDACnB,SAAS,CAAC,KAAK,CAAC;AAClB,4CAAA,CAAC,EAAA,YAAA,EACW,cAAc,IAAI,CAAA,OAAA,EAAU,UAAU,CAAA,CAAE,EAAA,CACpD,CACH,CAAA,EAAA,EAlBQ,KAAK,CAmBT;AAEX,4BAAA,CAAC,CAAC,EACFA,GAAA,CAAA,OAAA,EAAA,EACE,GAAG,EAAE,WAAW,EAChB,IAAI,EAAC,MAAM,EACX,SAAS,EAAE,YAAY,EACvB,EAAE,EAAE,SAAS,EACb,KAAK,EAAE,UAAU,EACjB,WAAW,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,GAAG,WAAW,GAAG,SAAS,EACxD,QAAQ,EAAE,QAAQ;;;;AAIlB,gCAAA,QAAQ,EAAE,QAAQ,IAAI,YAAY,EAClC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,OAAO,EAAE,WAAW,EAAA,IACf,cAAc,IAAI,aAAa,CAAC,EAAA,YAAA,EAKzB,QAAQ,GAAG,SAAS,GAAG,SAAS,EAAA,kBAAA,EAG1B,WAAW,GAAG,SAAS,GAAG,SAAS,EAAA,CACrD,CAAA,EAAA,CACE,EACL,OAAO,KACNA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,cAAc,EAAA,QAAA,EAC7BA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,WAAW,EAAA,CAAI,EAAA,CAC3B,CACR,CAAA,EAAA,CACG,EAEL,QAAQ,KACPA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,mBAAmB,EAAA,QAAA,EACjCA,GAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,SAAS,EACb,SAAS,EAAE,sBAAsB,EACjC,IAAI,EAAC,SAAS,EAAA,iBAAA,EACG,WAAW,EAAA,YAAA,EAChB,WAAW,GAAG,SAAS,GAAG,aAAa,EAAA,QAAA,EAElD,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,MAC5BA,GAAA,CAAA,GAAA,EAAA,EAEE,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,EACnB,SAAS,EAAE,GAAG,CAAC,eAAe,EAAE;4BAC9B,WAAW,EAAE,KAAK,KAAK,gBAAgB;AACxC,yBAAA,CAAC,EACF,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAC9B,YAAY,EAAE,MAAM,mBAAmB,CAAC,KAAK,CAAC,EAC9C,IAAI,EAAC,QAAQ,EAAA,eAAA,EACE,QAAQ,CAAC,KAAK,CAAC,KAAK,cAAc,EAAA,QAAA,EAEhD,IAAI,EAAA,EAVA,KAAK,CAWR,CACL,CAAC,EAAA,CACE,EAAA,CACF,CACP,EAEA,WAAW,KACVA,GAAA,CAAA,OAAA,EAAA,EAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAA,QAAA,EAC5C,WAAW,EAAA,CACN,CACT,EAEA,IAAI;AACH,gBAAA,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,MACdA,GAAA,CAAA,OAAA,EAAA,EAEE,IAAI,EAAC,QAAQ,EACb,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,EAC3B,IAAI,EAAE,IAAI,EAAA,EAJL,CAAA,UAAA,EAAa,CAAC,CAAA,CAAE,CAKrB,CACH,CAAC,CAAA,EAAA,CACA,CACP;IAED,IAAI,QAAQ,EAAE;AACZ,QAAA,QACEC,IAAA,CAAC,KAAK,EAAA,EACJ,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,eAAe,EAC3B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,cAAc,EAAA,QAAA,EAAA,CAExB,eAAe,EACf,SAAS,CAAA,EAAA,CACJ;IAEZ;AAEA,IAAA,QACEA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACG,eAAe,EACf,SAAS,CAAA,EAAA,CACT;AAEP,CAAC;AAGH,QAAQ,CAAC,WAAW,GAAG,UAAU;AAEjC;AACO,MAAM,QAAQ,GAAG;;"}
|
|
@@ -32,12 +32,15 @@ function validLocale(tag) {
|
|
|
32
32
|
* Inside it, the date and time pickers take its `locale` unless given their
|
|
33
33
|
* own, and their week starts on the first day of the locale they use unless
|
|
34
34
|
* `firstDayOfWeek` is set, and a picker with a `locale` of its own is read
|
|
35
|
-
* like a nested provider.
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* like a nested provider. With a `locale`, the numbers the library writes,
|
|
36
|
+
* such as page numbers and badge counts, follow it, and so does the
|
|
37
|
+
* filtering in `Combobox`, `Autocomplete`, `Taginput` and `Command`, which then ignores
|
|
38
|
+
* accents where the language treats letters as the same. The library's
|
|
39
|
+
* portaled content, such as a `Popover` panel, a `Modal` with `portal`, a
|
|
40
|
+
* `Toast` or a `Portal`'s children, keeps the same `dir` and `lang` though
|
|
41
|
+
* it renders outside the wrapper: in a container outside the wrapper, it
|
|
42
|
+
* sits in a `display: contents` element that carries them. Without a
|
|
43
|
+
* provider none of this changes.
|
|
41
44
|
*
|
|
42
45
|
* @function
|
|
43
46
|
* @param {LocaleProviderProps} props - Props for the LocaleProvider.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocaleProvider.js","sources":["../../../src/helpers/LocaleProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames } from './classNames';\nimport { useBulmaClasses, BulmaClassesProps } from './useBulmaClasses';\nimport { warnOnce } from './devWarnings';\nimport { canonicalLocale, localeDirection } from './localeInfo';\n\n/** A writing direction. */\nexport type TextDirection = 'ltr' | 'rtl';\n\n/** What the nearest `LocaleProvider` sets, both `undefined` outside one. */\nexport interface LocaleContextValue {\n /**\n * The locale, as a canonical BCP 47 tag such as `\"ar-EG\"`: the provider's\n * own, else the one an outer provider sets.\n */\n locale?: string;\n /**\n * The direction: the provider's own `dir`, else its own locale's, else the\n * one an outer provider sets.\n */\n dir?: TextDirection;\n}\n\nconst LocaleContext = createContext<LocaleContextValue | null>(null);\n\n/** The nearest provider's wrapper element, for `LocalePortalScope` to test targets against. */\nconst LocaleElementContext =\n createContext<React.RefObject<HTMLDivElement | null> | null>(null);\n\n/**\n * Props for the LocaleProvider component. The helper props, the other\n * attributes and the `ref` land on its `<div>`.\n */\nexport interface LocaleProviderProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'dir' | 'lang' | 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /**\n * A BCP 47 language tag, such as `\"de\"` or `\"ar-EG\"`. It becomes the\n * wrapper's `lang`, the default `locale` of the date and time pickers\n * inside, and, with no `dir`, the direction, from the way its script is\n * written. Unset, a nested provider keeps the outer one's. A tag `Intl`\n * refuses is ignored, with a warning in development.\n */\n locale?: string;\n /**\n * The direction, whatever the locale. Unset, it follows this provider's\n * `locale`, else an outer provider's direction, else the page's.\n */\n dir?: TextDirection;\n /** The part of the app it covers. */\n children?: React.ReactNode;\n}\n\n/** A tag in canonical form, or `undefined`, warning about one `Intl` refuses. */\nfunction validLocale(tag: string | undefined): string | undefined {\n try {\n return canonicalLocale(tag);\n } catch {\n warnOnce(\n `locale-provider-invalid:${tag}`,\n `[bestax-bulma] <LocaleProvider locale=\"${tag}\">: not a language ` +\n 'tag Intl accepts, so it is ignored. Use a BCP 47 tag such as ' +\n '\"en-US\", with a hyphen rather than an underscore.'\n );\n return undefined;\n }\n}\n\n/**\n * Sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.\n *\n * The wrapper carries `dir` and `lang`, so CSS and the components that read\n * the computed direction follow it, as they follow `<html dir>`. A `locale`\n * alone sets the direction of its script, and a `dir` sets the direction\n * whatever the locale. A nested provider keeps whatever it leaves unset.\n *\n * Inside it, the date and time pickers take its `locale` unless given their\n * own, and their week starts on the first day of the locale they use unless\n * `firstDayOfWeek` is set, and a picker with a `locale` of its own is read\n * like a nested provider. The library's portaled content, such as a\n * `Popover` panel, a `Modal` with `portal`, a `Toast` or a `Portal`'s\n * children, keeps the same `dir` and `lang` though it renders outside the\n * wrapper: in a container outside the wrapper, it sits in a\n * `display: contents` element that carries them. Without a provider none of\n * this changes.\n *\n * @function\n * @param {LocaleProviderProps} props - Props for the LocaleProvider.\n * @returns {JSX.Element} The wrapper, inside the context.\n *\n * @example\n * <LocaleProvider locale=\"ar-EG\">\n * <App />\n * </LocaleProvider>\n */\nexport const LocaleProvider = forwardRef<HTMLDivElement, LocaleProviderProps>(\n (\n { locale: localeProp, dir: dirProp, className, children, ...props },\n ref\n ) => {\n const outer = useContext(LocaleContext);\n const ownLocale = useMemo(() => validLocale(localeProp), [localeProp]);\n const ownLocaleDir = useMemo(\n () => (ownLocale ? localeDirection(ownLocale) : undefined),\n [ownLocale]\n );\n const locale = ownLocale || outer?.locale;\n const dir = dirProp || ownLocaleDir || outer?.dir;\n const value = useMemo(() => ({ locale, dir }), [locale, dir]);\n\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // The wrapper, for portaled content to tell whether its target is inside\n // it, and the caller's ref. A callback ref's cleanup is held and run on\n // detach, as Toast and Modal do, since React 18 discards the return value.\n const elementRef = useRef<HTMLDivElement | null>(null);\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const setElement = useCallback(\n (node: HTMLDivElement | null) => {\n elementRef.current = node;\n if (typeof ref === 'function') {\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) consumerCleanup();\n else ref(null);\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n return (\n <LocaleContext.Provider value={value}>\n <LocaleElementContext.Provider value={elementRef}>\n <div\n ref={setElement}\n className={classNames(bulmaHelperClasses, className) || undefined}\n {...rest}\n dir={dir}\n lang={locale}\n >\n {children}\n </div>\n </LocaleElementContext.Provider>\n </LocaleContext.Provider>\n );\n }\n);\n\nLocaleProvider.displayName = 'LocaleProvider';\n\n/** What `useLocale` returns outside a provider, the same object each time. */\nconst noLocale: LocaleContextValue = {};\n\n/**\n * The locale and direction the nearest `LocaleProvider` sets, for an app's own `Intl` calls or its own portaled content; both are `undefined` outside one.\n *\n * It isn't the page's direction: with no provider, or one that sets no\n * direction, the page's `<html dir>` still decides. To act on the direction\n * an element is laid out in, read `getComputedStyle(element).direction`, as\n * the library's components do.\n *\n * @function\n * @returns {LocaleContextValue} The nearest provider's `locale` and `dir`.\n *\n * @example\n * const { locale } = useLocale();\n * const price = new Intl.NumberFormat(locale, {\n * style: 'currency',\n * currency: 'EUR',\n * }).format(12.5);\n */\nexport function useLocale(): LocaleContextValue {\n return useContext(LocaleContext) ?? noLocale;\n}\n\n/**\n * INTERNAL, deliberately not exported from `src/index.ts`. The nearest\n * provider's settings, or `null` outside any provider, so a caller can tell\n * \"no provider\" from \"a provider that sets nothing\".\n */\nexport function useLocaleScope(): LocaleContextValue | null {\n return useContext(LocaleContext);\n}\n\nconst displayContents: React.CSSProperties = { display: 'contents' };\n\n/** The `dir` and `lang` portaled content carries: a provider's, or a picker's own. */\nexport interface PortalLocale {\n /** The `lang` to carry, unset for none. */\n locale?: string;\n /** The `dir` to carry, unset for none. */\n dir?: string;\n}\n\n/**\n * INTERNAL, deliberately not exported from `src/index.ts`. Keeps the `dir`\n * and `lang` of the nearest provider, or the `scope` given in their place,\n * on content the library portals into `target`, which has left the\n * provider's wrapper behind.\n *\n * A target inside the provider's own wrapper gets the content as it is: it\n * inherits from the wrapper, and follows it when the provider changes.\n * Content that must be its container's direct child, a `<tr>` portaled into\n * a `<tbody>` there, stays one. Any other target, `document.body` included,\n * gets the content inside a `display: contents` element carrying the\n * values, which adds no box. So does content with a `scope` of its own, a\n * picker's panel, since the provider's values aren't its own.\n *\n * Which of the two is decided once, when the content mounts, and kept while\n * it stays: switching between them would put a different element in its\n * place and remount everything inside, losing typed text, focus and timers.\n * A change of locale or direction updates the wrapper's attributes instead.\n * A target is never left bare because something else, such as `<html>`,\n * happens to carry the same values, since that can stop being true without\n * the content remounting. Outside a provider it renders the children alone,\n * so nothing changes there.\n */\nexport function LocalePortalScope({\n children,\n target,\n scope,\n}: {\n children: React.ReactNode;\n /** The element the content is portaled into. */\n target: Element;\n /** Values to carry in place of the provider's, such as a picker's own. */\n scope?: PortalLocale;\n}) {\n const provider = useContext(LocaleContext);\n const element = useContext(LocaleElementContext);\n const [wrap] = useState(\n () => scope !== undefined || !element?.current?.contains(target)\n );\n if (!provider || !wrap) return <>{children}</>;\n const values = scope ?? provider;\n return (\n <div dir={values.dir} lang={values.locale} style={displayContents}>\n {children}\n </div>\n );\n}\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LocaleProvider.js","sources":["../../../src/helpers/LocaleProvider.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames } from './classNames';\nimport { useBulmaClasses, BulmaClassesProps } from './useBulmaClasses';\nimport { warnOnce } from './devWarnings';\nimport { canonicalLocale, localeDirection } from './localeInfo';\n\n/** A writing direction. */\nexport type TextDirection = 'ltr' | 'rtl';\n\n/** What the nearest `LocaleProvider` sets, both `undefined` outside one. */\nexport interface LocaleContextValue {\n /**\n * The locale, as a canonical BCP 47 tag such as `\"ar-EG\"`: the provider's\n * own, else the one an outer provider sets.\n */\n locale?: string;\n /**\n * The direction: the provider's own `dir`, else its own locale's, else the\n * one an outer provider sets.\n */\n dir?: TextDirection;\n}\n\nconst LocaleContext = createContext<LocaleContextValue | null>(null);\n\n/** The nearest provider's wrapper element, for `LocalePortalScope` to test targets against. */\nconst LocaleElementContext =\n createContext<React.RefObject<HTMLDivElement | null> | null>(null);\n\n/**\n * Props for the LocaleProvider component. The helper props, the other\n * attributes and the `ref` land on its `<div>`.\n */\nexport interface LocaleProviderProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'dir' | 'lang' | 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /**\n * A BCP 47 language tag, such as `\"de\"` or `\"ar-EG\"`. It becomes the\n * wrapper's `lang`, the default `locale` of the date and time pickers\n * inside, and, with no `dir`, the direction, from the way its script is\n * written. Unset, a nested provider keeps the outer one's. A tag `Intl`\n * refuses is ignored, with a warning in development.\n */\n locale?: string;\n /**\n * The direction, whatever the locale. Unset, it follows this provider's\n * `locale`, else an outer provider's direction, else the page's.\n */\n dir?: TextDirection;\n /** The part of the app it covers. */\n children?: React.ReactNode;\n}\n\n/** A tag in canonical form, or `undefined`, warning about one `Intl` refuses. */\nfunction validLocale(tag: string | undefined): string | undefined {\n try {\n return canonicalLocale(tag);\n } catch {\n warnOnce(\n `locale-provider-invalid:${tag}`,\n `[bestax-bulma] <LocaleProvider locale=\"${tag}\">: not a language ` +\n 'tag Intl accepts, so it is ignored. Use a BCP 47 tag such as ' +\n '\"en-US\", with a hyphen rather than an underscore.'\n );\n return undefined;\n }\n}\n\n/**\n * Sets the language and writing direction for the part of the app inside it, on a wrapper `<div>` and on what the library portals out of it.\n *\n * The wrapper carries `dir` and `lang`, so CSS and the components that read\n * the computed direction follow it, as they follow `<html dir>`. A `locale`\n * alone sets the direction of its script, and a `dir` sets the direction\n * whatever the locale. A nested provider keeps whatever it leaves unset.\n *\n * Inside it, the date and time pickers take its `locale` unless given their\n * own, and their week starts on the first day of the locale they use unless\n * `firstDayOfWeek` is set, and a picker with a `locale` of its own is read\n * like a nested provider. With a `locale`, the numbers the library writes,\n * such as page numbers and badge counts, follow it, and so does the\n * filtering in `Combobox`, `Autocomplete`, `Taginput` and `Command`, which then ignores\n * accents where the language treats letters as the same. The library's\n * portaled content, such as a `Popover` panel, a `Modal` with `portal`, a\n * `Toast` or a `Portal`'s children, keeps the same `dir` and `lang` though\n * it renders outside the wrapper: in a container outside the wrapper, it\n * sits in a `display: contents` element that carries them. Without a\n * provider none of this changes.\n *\n * @function\n * @param {LocaleProviderProps} props - Props for the LocaleProvider.\n * @returns {JSX.Element} The wrapper, inside the context.\n *\n * @example\n * <LocaleProvider locale=\"ar-EG\">\n * <App />\n * </LocaleProvider>\n */\nexport const LocaleProvider = forwardRef<HTMLDivElement, LocaleProviderProps>(\n (\n { locale: localeProp, dir: dirProp, className, children, ...props },\n ref\n ) => {\n const outer = useContext(LocaleContext);\n const ownLocale = useMemo(() => validLocale(localeProp), [localeProp]);\n const ownLocaleDir = useMemo(\n () => (ownLocale ? localeDirection(ownLocale) : undefined),\n [ownLocale]\n );\n const locale = ownLocale || outer?.locale;\n const dir = dirProp || ownLocaleDir || outer?.dir;\n const value = useMemo(() => ({ locale, dir }), [locale, dir]);\n\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // The wrapper, for portaled content to tell whether its target is inside\n // it, and the caller's ref. A callback ref's cleanup is held and run on\n // detach, as Toast and Modal do, since React 18 discards the return value.\n const elementRef = useRef<HTMLDivElement | null>(null);\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const setElement = useCallback(\n (node: HTMLDivElement | null) => {\n elementRef.current = node;\n if (typeof ref === 'function') {\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) consumerCleanup();\n else ref(null);\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref]\n );\n\n return (\n <LocaleContext.Provider value={value}>\n <LocaleElementContext.Provider value={elementRef}>\n <div\n ref={setElement}\n className={classNames(bulmaHelperClasses, className) || undefined}\n {...rest}\n dir={dir}\n lang={locale}\n >\n {children}\n </div>\n </LocaleElementContext.Provider>\n </LocaleContext.Provider>\n );\n }\n);\n\nLocaleProvider.displayName = 'LocaleProvider';\n\n/** What `useLocale` returns outside a provider, the same object each time. */\nconst noLocale: LocaleContextValue = {};\n\n/**\n * The locale and direction the nearest `LocaleProvider` sets, for an app's own `Intl` calls or its own portaled content; both are `undefined` outside one.\n *\n * It isn't the page's direction: with no provider, or one that sets no\n * direction, the page's `<html dir>` still decides. To act on the direction\n * an element is laid out in, read `getComputedStyle(element).direction`, as\n * the library's components do.\n *\n * @function\n * @returns {LocaleContextValue} The nearest provider's `locale` and `dir`.\n *\n * @example\n * const { locale } = useLocale();\n * const price = new Intl.NumberFormat(locale, {\n * style: 'currency',\n * currency: 'EUR',\n * }).format(12.5);\n */\nexport function useLocale(): LocaleContextValue {\n return useContext(LocaleContext) ?? noLocale;\n}\n\n/**\n * INTERNAL, deliberately not exported from `src/index.ts`. The nearest\n * provider's settings, or `null` outside any provider, so a caller can tell\n * \"no provider\" from \"a provider that sets nothing\".\n */\nexport function useLocaleScope(): LocaleContextValue | null {\n return useContext(LocaleContext);\n}\n\nconst displayContents: React.CSSProperties = { display: 'contents' };\n\n/** The `dir` and `lang` portaled content carries: a provider's, or a picker's own. */\nexport interface PortalLocale {\n /** The `lang` to carry, unset for none. */\n locale?: string;\n /** The `dir` to carry, unset for none. */\n dir?: string;\n}\n\n/**\n * INTERNAL, deliberately not exported from `src/index.ts`. Keeps the `dir`\n * and `lang` of the nearest provider, or the `scope` given in their place,\n * on content the library portals into `target`, which has left the\n * provider's wrapper behind.\n *\n * A target inside the provider's own wrapper gets the content as it is: it\n * inherits from the wrapper, and follows it when the provider changes.\n * Content that must be its container's direct child, a `<tr>` portaled into\n * a `<tbody>` there, stays one. Any other target, `document.body` included,\n * gets the content inside a `display: contents` element carrying the\n * values, which adds no box. So does content with a `scope` of its own, a\n * picker's panel, since the provider's values aren't its own.\n *\n * Which of the two is decided once, when the content mounts, and kept while\n * it stays: switching between them would put a different element in its\n * place and remount everything inside, losing typed text, focus and timers.\n * A change of locale or direction updates the wrapper's attributes instead.\n * A target is never left bare because something else, such as `<html>`,\n * happens to carry the same values, since that can stop being true without\n * the content remounting. Outside a provider it renders the children alone,\n * so nothing changes there.\n */\nexport function LocalePortalScope({\n children,\n target,\n scope,\n}: {\n children: React.ReactNode;\n /** The element the content is portaled into. */\n target: Element;\n /** Values to carry in place of the provider's, such as a picker's own. */\n scope?: PortalLocale;\n}) {\n const provider = useContext(LocaleContext);\n const element = useContext(LocaleElementContext);\n const [wrap] = useState(\n () => scope !== undefined || !element?.current?.contains(target)\n );\n if (!provider || !wrap) return <>{children}</>;\n const values = scope ?? provider;\n return (\n <div dir={values.dir} lang={values.locale} style={displayContents}>\n {children}\n </div>\n );\n}\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useLocaleScope } from './LocaleProvider.js';
|
|
4
|
+
|
|
5
|
+
// INTERNAL: deliberately not exported from src/index.ts. Number formatting
|
|
6
|
+
// and text matching in a LocaleProvider's locale. Both return `null` outside
|
|
7
|
+
// a provider that gives a locale, so each caller keeps the formatting and the
|
|
8
|
+
// matching it has always had there.
|
|
9
|
+
/** A combining mark: an accent, a vowel sign or a point written on a letter. */
|
|
10
|
+
const MARK = /\p{M}/u;
|
|
11
|
+
/**
|
|
12
|
+
* The locale a component formats and matches in: inside a `LocaleProvider`,
|
|
13
|
+
* the component's own locale when it has one (a picker's `locale`), else the
|
|
14
|
+
* provider's; outside a provider, none.
|
|
15
|
+
*/
|
|
16
|
+
function useScopedLocale(own) {
|
|
17
|
+
const scope = useLocaleScope();
|
|
18
|
+
if (!scope)
|
|
19
|
+
return undefined;
|
|
20
|
+
return scope.locale;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A formatter for numbers shown on screen, in the locale of the
|
|
24
|
+
* `LocaleProvider` around the component, or `null` outside one that gives a
|
|
25
|
+
* locale. Formatters are kept per set of options, since building one is the
|
|
26
|
+
* expensive part.
|
|
27
|
+
*
|
|
28
|
+
* @param own - The component's own locale, such as a picker's `locale`,
|
|
29
|
+
* which wins inside a provider.
|
|
30
|
+
*/
|
|
31
|
+
function useNumberFormat(own) {
|
|
32
|
+
const locale = useScopedLocale();
|
|
33
|
+
return useMemo(() => {
|
|
34
|
+
if (!locale)
|
|
35
|
+
return null;
|
|
36
|
+
const formats = new Map();
|
|
37
|
+
return (value, options) => {
|
|
38
|
+
const key = options ? JSON.stringify(options) : '';
|
|
39
|
+
let format = formats.get(key);
|
|
40
|
+
if (!format) {
|
|
41
|
+
format = new Intl.NumberFormat(locale, options);
|
|
42
|
+
formats.set(key, format);
|
|
43
|
+
}
|
|
44
|
+
return format.format(value);
|
|
45
|
+
};
|
|
46
|
+
}, [locale]);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A matcher for filtering a list by what was typed, in the locale of the
|
|
50
|
+
* `LocaleProvider` around the component, or `null` outside one that gives a
|
|
51
|
+
* locale. It compares with `Intl.Collator` at `usage: 'search'` and
|
|
52
|
+
* `sensitivity: 'base'`, so it ignores case and accents where the language
|
|
53
|
+
* treats the letters as the same: "cafe" finds "Café", while in Swedish "a"
|
|
54
|
+
* doesn't find "å", a letter of its own there. Marks the language ignores
|
|
55
|
+
* count for nothing on either side, so in Arabic محمد finds مُحَمَّد and the
|
|
56
|
+
* other way round. An empty query, or one of nothing but such marks,
|
|
57
|
+
* matches everything.
|
|
58
|
+
*/
|
|
59
|
+
function useLocaleMatcher() {
|
|
60
|
+
const locale = useScopedLocale();
|
|
61
|
+
return useMemo(() => {
|
|
62
|
+
if (!locale)
|
|
63
|
+
return null;
|
|
64
|
+
const collator = new Intl.Collator(locale, {
|
|
65
|
+
usage: 'search',
|
|
66
|
+
sensitivity: 'base',
|
|
67
|
+
});
|
|
68
|
+
return (text, query) => {
|
|
69
|
+
const needle = query.normalize('NFC');
|
|
70
|
+
if (collator.compare(needle, '') === 0)
|
|
71
|
+
return true;
|
|
72
|
+
// Compared by code point, so a slice never splits a surrogate pair.
|
|
73
|
+
const chars = Array.from(text.normalize('NFC'));
|
|
74
|
+
const marks = chars.map(char => MARK.test(char));
|
|
75
|
+
// A slice equal to the needle can be longer or shorter than it: the
|
|
76
|
+
// marks the collator ignores, Arabic harakat or Hebrew niqqud, take
|
|
77
|
+
// code points on one side and not the other, and the expansions the
|
|
78
|
+
// collator makes, "ß" against "ss" or "æ" against "ae", turn one letter
|
|
79
|
+
// into two. So each slice runs from a letter to just before the next
|
|
80
|
+
// letter, never cutting a letter from its marks, and the slices from
|
|
81
|
+
// one start grow until they hold twice the needle's letters, which
|
|
82
|
+
// those expansions can't get past. That keeps the work proportional to
|
|
83
|
+
// the text's length, however long a label is, rather than to its
|
|
84
|
+
// square.
|
|
85
|
+
const most = 2 * Array.from(needle).filter(char => !MARK.test(char)).length;
|
|
86
|
+
for (let start = 0; start < chars.length; start++) {
|
|
87
|
+
if (marks[start])
|
|
88
|
+
continue;
|
|
89
|
+
let letters = 0;
|
|
90
|
+
for (let end = start + 1; end <= chars.length; end++) {
|
|
91
|
+
if (!marks[end - 1])
|
|
92
|
+
letters++;
|
|
93
|
+
if (letters > most)
|
|
94
|
+
break;
|
|
95
|
+
if (marks[end])
|
|
96
|
+
continue;
|
|
97
|
+
if (collator.compare(chars.slice(start, end).join(''), needle) === 0) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
}, [locale]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export { useLocaleMatcher, useNumberFormat };
|
|
108
|
+
//# sourceMappingURL=localeFormat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localeFormat.js","sources":["../../../src/helpers/localeFormat.ts"],"sourcesContent":["// INTERNAL: deliberately not exported from src/index.ts. Number formatting\n// and text matching in a LocaleProvider's locale. Both return `null` outside\n// a provider that gives a locale, so each caller keeps the formatting and the\n// matching it has always had there.\n\nimport { useMemo } from 'react';\nimport { useLocaleScope } from './LocaleProvider';\n\n/** A combining mark: an accent, a vowel sign or a point written on a letter. */\nconst MARK = /\\p{M}/u;\n\n/** Formats a number for display, with `Intl.NumberFormat` options. */\nexport type NumberFormatter = (\n value: number,\n options?: Intl.NumberFormatOptions\n) => string;\n\n/** Whether `text` contains `query`, as the locale compares letters. */\nexport type TextMatcher = (text: string, query: string) => boolean;\n\n/**\n * The locale a component formats and matches in: inside a `LocaleProvider`,\n * the component's own locale when it has one (a picker's `locale`), else the\n * provider's; outside a provider, none.\n */\nfunction useScopedLocale(own: string | undefined): string | undefined {\n const scope = useLocaleScope();\n if (!scope) return undefined;\n return own || scope.locale;\n}\n\n/**\n * A formatter for numbers shown on screen, in the locale of the\n * `LocaleProvider` around the component, or `null` outside one that gives a\n * locale. Formatters are kept per set of options, since building one is the\n * expensive part.\n *\n * @param own - The component's own locale, such as a picker's `locale`,\n * which wins inside a provider.\n */\nexport function useNumberFormat(own?: string): NumberFormatter | null {\n const locale = useScopedLocale(own);\n return useMemo(() => {\n if (!locale) return null;\n const formats = new Map<string, Intl.NumberFormat>();\n return (value, options) => {\n const key = options ? JSON.stringify(options) : '';\n let format = formats.get(key);\n if (!format) {\n format = new Intl.NumberFormat(locale, options);\n formats.set(key, format);\n }\n return format.format(value);\n };\n }, [locale]);\n}\n\n/**\n * A matcher for filtering a list by what was typed, in the locale of the\n * `LocaleProvider` around the component, or `null` outside one that gives a\n * locale. It compares with `Intl.Collator` at `usage: 'search'` and\n * `sensitivity: 'base'`, so it ignores case and accents where the language\n * treats the letters as the same: \"cafe\" finds \"Café\", while in Swedish \"a\"\n * doesn't find \"å\", a letter of its own there. Marks the language ignores\n * count for nothing on either side, so in Arabic محمد finds مُحَمَّد and the\n * other way round. An empty query, or one of nothing but such marks,\n * matches everything.\n */\nexport function useLocaleMatcher(): TextMatcher | null {\n const locale = useScopedLocale(undefined);\n return useMemo(() => {\n if (!locale) return null;\n const collator = new Intl.Collator(locale, {\n usage: 'search',\n sensitivity: 'base',\n });\n return (text, query) => {\n const needle = query.normalize('NFC');\n if (collator.compare(needle, '') === 0) return true;\n // Compared by code point, so a slice never splits a surrogate pair.\n const chars = Array.from(text.normalize('NFC'));\n const marks = chars.map(char => MARK.test(char));\n // A slice equal to the needle can be longer or shorter than it: the\n // marks the collator ignores, Arabic harakat or Hebrew niqqud, take\n // code points on one side and not the other, and the expansions the\n // collator makes, \"ß\" against \"ss\" or \"æ\" against \"ae\", turn one letter\n // into two. So each slice runs from a letter to just before the next\n // letter, never cutting a letter from its marks, and the slices from\n // one start grow until they hold twice the needle's letters, which\n // those expansions can't get past. That keeps the work proportional to\n // the text's length, however long a label is, rather than to its\n // square.\n const most =\n 2 * Array.from(needle).filter(char => !MARK.test(char)).length;\n for (let start = 0; start < chars.length; start++) {\n if (marks[start]) continue;\n let letters = 0;\n for (let end = start + 1; end <= chars.length; end++) {\n if (!marks[end - 1]) letters++;\n if (letters > most) break;\n if (marks[end]) continue;\n if (\n collator.compare(chars.slice(start, end).join(''), needle) === 0\n ) {\n return true;\n }\n }\n }\n return false;\n };\n }, [locale]);\n}\n"],"names":[],"mappings":"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"}
|