@allxsmith/bestax-bulma 5.34.1 → 5.34.2
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/esm/components/Dropdown.js +8 -3
- package/dist/esm/components/Dropdown.js.map +1 -1
- package/dist/esm/components/Loading.js +5 -4
- package/dist/esm/components/Loading.js.map +1 -1
- package/dist/esm/components/Modal.js +11 -4
- package/dist/esm/components/Modal.js.map +1 -1
- package/dist/esm/components/Sidebar.js +5 -4
- package/dist/esm/components/Sidebar.js.map +1 -1
- package/dist/esm/components/Toast.js +7 -5
- package/dist/esm/components/Toast.js.map +1 -1
- package/dist/esm/form/Autocomplete.js +17 -2
- package/dist/esm/form/Autocomplete.js.map +1 -1
- package/dist/esm/form/Taginput.js +4 -0
- package/dist/esm/form/Taginput.js.map +1 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js +11 -3
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/index.cjs +67 -25
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/Loading.d.ts +5 -1
- package/dist/types/components/Modal.d.ts +4 -1
- package/dist/types/components/Sidebar.d.ts +5 -1
- package/dist/types/components/Toast.d.ts +4 -1
- package/dist/types/form/Autocomplete.d.ts +13 -2
- package/dist/types-cjs/components/Loading.d.ts +5 -1
- package/dist/types-cjs/components/Modal.d.ts +4 -1
- package/dist/types-cjs/components/Sidebar.d.ts +5 -1
- package/dist/types-cjs/components/Toast.d.ts +4 -1
- package/dist/types-cjs/form/Autocomplete.d.ts +13 -2
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.js","sources":["../../../src/components/Toast.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useEffect,\n useRef,\n useState,\n useCallback,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { isEventInside } from '../helpers/shadowDom';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { usePortalContainer } from '../helpers/portal';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\n\n/** Color/style type presets for toast messages. */\nexport type ToastType =\n 'default' | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/** Screen positions where toasts can be displayed. */\nexport type ToastPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Props for the Toast component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the toast element.\n */\nexport interface ToastProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color'> {\n /** The message to display (required). */\n message: string;\n /** Color variant — colors the toast **background**. */\n type?: ToastType;\n /** Color variant — colors the **action button** text. */\n actionType?: ToastType;\n /**\n * Position on the screen. Default: 'top-right'. On a standalone `<Toast>`\n * this places it. Through `toast.show()` it places that toast, and a toast\n * shown without one goes to `ToastContainer`'s `position` instead.\n */\n position?: ToastPosition;\n /** Duration in ms before auto-close. `0` disables auto-close. */\n duration?: number;\n /** Keeps the toast visible until dismissed. */\n indefinite?: boolean;\n /** Whether clicking the toast (or outside it) dismisses it. */\n dismissible?: boolean;\n /** Show an explicit close (X) button. Default: false. */\n closable?: boolean;\n /** Pill-shaped (rounded corners). */\n rounded?: boolean;\n /** Pause auto-close timer on hover. Default: false. */\n pauseOnHover?: boolean;\n /** Whether the toast can be dismissed with Escape. Default: true. */\n cancelable?: boolean;\n /** Text for an action button (e.g. \"Undo\"). */\n actionText?: string;\n /** Text for a cancel button. */\n cancelText?: string;\n /** Callback when the action button is clicked. */\n onAction?: () => void;\n /** Callback when toast closes. */\n onClose?: () => void;\n /** CSS selector or DOM node to mount the toast into. */\n container?: string | HTMLElement;\n /** Renders inline instead of using a portal. */\n inline?: boolean;\n}\n\n/**\n * The `Toast` component provides brief notification messages with optional action and cancel buttons.\n *\n * @function\n * @param {ToastProps} props - Props for the Toast component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the toast element.\n * @returns {JSX.Element | null} The rendered toast component.\n *\n * @example\n * // Basic toast\n * <Toast message=\"Operation successful!\" type=\"success\" />\n *\n * @example\n * // Toast with action button\n * <Toast message=\"Item deleted\" actionText=\"Undo\" onAction={handleUndo} />\n */\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(\n (\n {\n message,\n type = 'default',\n actionType,\n position = 'top-right',\n duration = 2000,\n indefinite = false,\n dismissible = true,\n closable = false,\n rounded = false,\n pauseOnHover = false,\n cancelable = true,\n actionText,\n cancelText,\n onAction,\n onClose,\n container,\n inline = false,\n className,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const [isVisible, setIsVisible] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement | null>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const handleClose = useCallback(() => {\n setIsVisible(false);\n onClose?.();\n }, [onClose]);\n\n const handleAction = useCallback(() => {\n onAction?.();\n handleClose();\n }, [onAction, handleClose]);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleClose();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleClose]);\n\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Click-outside dismiss — deferred so the click that spawned the toast\n // doesn't immediately dismiss it before it's even visible.\n useEffect(() => {\n if (!dismissible || !isVisible) return undefined;\n\n const handleDocumentClick = (e: MouseEvent) => {\n if (toastRef.current && !isEventInside(e, toastRef.current)) {\n handleClose();\n }\n };\n\n const raf = requestAnimationFrame(() => {\n document.addEventListener('click', handleDocumentClick);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [dismissible, isVisible, handleClose]);\n\n useEffect(() => {\n if (!cancelable) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, handleClose]);\n\n const containerClasses = usePrefixedClassNames('toast-container', {\n [`is-${position}`]: true,\n });\n\n const toastClasses = usePrefixedClassNames('toast', {\n [`is-${type}`]: type !== 'default',\n [`is-action-${actionType}`]: !!actionType && actionType !== 'default',\n 'is-rounded': rounded,\n });\n\n const combinedClasses = classNames(\n toastClasses,\n bulmaHelperClasses,\n className\n );\n const toastMessageClass = usePrefixedClassNames('toast-message');\n const toastActionsClass = usePrefixedClassNames('toast-actions');\n const toastCancelClass = usePrefixedClassNames('toast-cancel');\n const toastActionClass = usePrefixedClassNames('toast-action');\n const toastButtonClass = usePrefixedClassNames('button');\n const toastCloseClass = usePrefixedClassNames('delete', 'is-small');\n\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n toastRef.current = node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split. Memoized because an\n // unstable ref identity makes React detach and re-attach on every render,\n // which would run that cleanup each time.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\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 as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n if (!isVisible) {\n return null;\n }\n\n const toastElement = (\n <div\n ref={setRef}\n className={combinedClasses}\n role=\"alert\"\n aria-live={\n type === 'danger' || type === 'warning' ? 'assertive' : 'polite'\n }\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={dismissible ? handleClose : undefined}\n {...rest}\n >\n <span className={toastMessageClass}>{message}</span>\n {(cancelText || actionText) && (\n <div className={toastActionsClass}>\n {cancelText && (\n <span className={toastCancelClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n >\n {cancelText}\n </button>\n </span>\n )}\n {actionText && (\n <span className={toastActionClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleAction();\n }}\n >\n {actionText}\n </button>\n </span>\n )}\n </div>\n )}\n {closable && (\n <button\n type=\"button\"\n className={toastCloseClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n aria-label=\"Close\"\n />\n )}\n </div>\n );\n\n if (inline) {\n return toastElement;\n }\n\n const toastContent = <div className={containerClasses}>{toastElement}</div>;\n\n if (typeof document !== 'undefined') {\n return createPortal(toastContent, resolveContainer(container));\n }\n\n return null;\n }\n);\n\nToast.displayName = 'Toast';\n\n// Toast Manager for programmatic toasts\n\n/**\n * Options for showing a programmatic toast. Extends ToastProps with a required message.\n */\nexport interface ToastOptions extends Omit<ToastProps, 'message'> {\n /** The message to display. */\n message: string;\n /**\n * When true, toasts enter a FIFO queue and display one at a time, one queue\n * across every `position`. Default false.\n */\n queue?: boolean;\n}\n\n/**\n * Internal representation of a toast instance.\n */\nexport interface ToastInstance {\n /** Unique identifier for this toast. */\n id: string;\n /** Configuration options for the toast. */\n props: ToastOptions;\n}\n\nlet toastId = 0;\nconst toastListeners: Set<(toasts: ToastInstance[]) => void> = new Set();\nlet toasts: ToastInstance[] = [];\n\n// Queued toasts: FIFO queue, one at a time\nlet queuedToasts: ToastInstance[] = [];\nlet currentQueuedToast: ToastInstance | null = null;\n\n// The server has nowhere to portal a toast to, and its copy of this module is\n// shared by every request, so server rendering reads an empty list. Hydration\n// reads it too, which keeps the first client render matching the server's.\nconst noToasts: ToastInstance[] = [];\nconst getServerToasts = () => noToasts;\n\n// What a container shows right now: the stacked toasts, then the queued one on\n// screen. ToastContainer renders from this rather than from updates alone, so\n// toasts raised before it mounted still appear. It is replaced rather than\n// mutated, and only when listeners are notified, because useSyncExternalStore\n// needs the same array back between changes. An empty list is `noToasts`\n// itself, so a container that hydrates with nothing to show reads the same\n// snapshot the server did and has no reason to render again.\nlet visibleToasts: ToastInstance[] = noToasts;\nconst getVisibleToasts = () => visibleToasts;\n\nconst notifyListeners = () => {\n const allVisible = [...toasts];\n if (currentQueuedToast) {\n allVisible.push(currentQueuedToast);\n }\n visibleToasts = allVisible.length > 0 ? allVisible : noToasts;\n toastListeners.forEach(listener => listener([...allVisible]));\n};\n\nconst processQueuedToast = () => {\n if (currentQueuedToast || queuedToasts.length === 0) return;\n currentQueuedToast = queuedToasts.shift()!;\n notifyListeners();\n};\n\n/**\n * Programmatic toast API for showing, closing, and managing toasts.\n *\n * @example\n * toast.success('Saved!');\n * toast.show({ message: 'Item deleted', actionText: 'Undo', onAction: handleUndo });\n */\nexport const toast = {\n /**\n * Show a toast with the given options.\n * @param {ToastOptions} options - Toast configuration.\n * @returns {string} The unique ID of the created toast.\n */\n show: (options: ToastOptions): string => {\n const id = `toast-${++toastId}`;\n const instance = { id, props: options };\n\n if (options.queue) {\n queuedToasts.push(instance);\n processQueuedToast();\n } else {\n toasts.push(instance);\n notifyListeners();\n }\n\n return id;\n },\n\n /**\n * Show a success toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n success: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'success', ...options });\n },\n\n /**\n * Show a danger toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n danger: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'danger', ...options });\n },\n\n /**\n * Show a warning toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n warning: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'warning', ...options });\n },\n\n /**\n * Show an info toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n info: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'info', ...options });\n },\n\n /**\n * Close a specific toast by ID.\n * @param {string} id - The toast ID to close.\n */\n close: (id: string): void => {\n if (currentQueuedToast && currentQueuedToast.id === id) {\n currentQueuedToast = null;\n processQueuedToast();\n } else {\n queuedToasts = queuedToasts.filter(t => t.id !== id);\n toasts = toasts.filter(t => t.id !== id);\n }\n notifyListeners();\n },\n\n /** Close all toasts and clear the queue. */\n closeAll: (): void => {\n toasts = [];\n queuedToasts = [];\n currentQueuedToast = null;\n notifyListeners();\n },\n\n /**\n * Subscribe to toast state changes.\n * @param {(toasts: ToastInstance[]) => void} listener - Callback invoked on changes.\n * @returns {() => void} Unsubscribe function.\n */\n subscribe: (listener: (toasts: ToastInstance[]) => void): (() => void) => {\n toastListeners.add(listener);\n return () => toastListeners.delete(listener);\n },\n};\n\n// The order ToastContainer renders its stacks in: across the top of the\n// screen, then across the bottom.\nconst toastStackOrder: readonly ToastPosition[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n];\n\n/**\n * Container component for rendering programmatic toasts.\n * Place once at your app root to enable the toast API. A toast shown with a\n * `position` appears there, and one shown without goes to the container's\n * `position`.\n *\n * @function\n * @param {{ position?: ToastPosition }} props - Container props.\n * @returns {JSX.Element | null} The rendered toast container, or null if empty.\n */\nexport const ToastContainer: React.FC<{\n /**\n * Where a toast shown without a `position` of its own appears. Default:\n * 'top-right'. When it changes, those toasts move without remounting, but\n * one shown with its own `position` equal to the old or new value\n * remounts and starts over as if it had just been shown.\n */\n position?: ToastPosition;\n}> = ({ position = 'top-right' }) => {\n // Starts from the toasts already showing instead of an empty list, then\n // follows changes.\n const toastList = useSyncExternalStore(\n toast.subscribe,\n getVisibleToasts,\n getServerToasts\n );\n const resolveContainer = usePortalContainer();\n\n if (typeof document === 'undefined' || toastList.length === 0) {\n return null;\n }\n\n const stacks = groupIntoPositionStacks(\n toastList,\n t => t.props.position,\n position,\n toastStackOrder\n );\n\n return createPortal(\n stacks.map(stack => (\n <div key={stack.key} className={`toast-container is-${stack.position}`}>\n {stack.items.map(t => {\n const { queue: _queue, ...toastProps } = t.props;\n return (\n <Toast\n key={t.id}\n {...toastProps}\n position={stack.position}\n onClose={() => toast.close(t.id)}\n />\n );\n })}\n </div>\n )),\n resolveContainer()\n );\n};\n\nexport default Toast;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toast.js","sources":["../../../src/components/Toast.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useEffect,\n useRef,\n useState,\n useCallback,\n useSyncExternalStore,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { isEventInside } from '../helpers/shadowDom';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { usePortalContainer } from '../helpers/portal';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\n\n/** Color/style type presets for toast messages. */\nexport type ToastType =\n 'default' | 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/** Screen positions where toasts can be displayed. */\nexport type ToastPosition =\n | 'top-left'\n | 'top-center'\n | 'top-right'\n | 'bottom-left'\n | 'bottom-center'\n | 'bottom-right';\n\n/**\n * Props for the Toast component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the toast element.\n */\nexport interface ToastProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color'> {\n /** The message to display (required). */\n message: string;\n /** Color variant — colors the toast **background**. */\n type?: ToastType;\n /** Color variant — colors the **action button** text. */\n actionType?: ToastType;\n /**\n * Position on the screen. Default: 'top-right'. On a standalone `<Toast>`\n * this places it. Through `toast.show()` it places that toast, and a toast\n * shown without one goes to `ToastContainer`'s `position` instead.\n */\n position?: ToastPosition;\n /** Duration in ms before auto-close. `0` disables auto-close. */\n duration?: number;\n /** Keeps the toast visible until dismissed. */\n indefinite?: boolean;\n /** Whether clicking the toast (or outside it) dismisses it. */\n dismissible?: boolean;\n /** Show an explicit close (X) button. Default: false. */\n closable?: boolean;\n /** Pill-shaped (rounded corners). */\n rounded?: boolean;\n /** Pause auto-close timer on hover. Default: false. */\n pauseOnHover?: boolean;\n /**\n * Whether the toast can be dismissed with Escape. An Escape a popup on the\n * page closed on, by calling `preventDefault()`, leaves it up. Default: true.\n */\n cancelable?: boolean;\n /** Text for an action button (e.g. \"Undo\"). */\n actionText?: string;\n /** Text for a cancel button. */\n cancelText?: string;\n /** Callback when the action button is clicked. */\n onAction?: () => void;\n /** Callback when toast closes. */\n onClose?: () => void;\n /** CSS selector or DOM node to mount the toast into. */\n container?: string | HTMLElement;\n /** Renders inline instead of using a portal. */\n inline?: boolean;\n}\n\n/**\n * The `Toast` component provides brief notification messages with optional action and cancel buttons.\n *\n * @function\n * @param {ToastProps} props - Props for the Toast component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the toast element.\n * @returns {JSX.Element | null} The rendered toast component.\n *\n * @example\n * // Basic toast\n * <Toast message=\"Operation successful!\" type=\"success\" />\n *\n * @example\n * // Toast with action button\n * <Toast message=\"Item deleted\" actionText=\"Undo\" onAction={handleUndo} />\n */\nexport const Toast = forwardRef<HTMLDivElement, ToastProps>(\n (\n {\n message,\n type = 'default',\n actionType,\n position = 'top-right',\n duration = 2000,\n indefinite = false,\n dismissible = true,\n closable = false,\n rounded = false,\n pauseOnHover = false,\n cancelable = true,\n actionText,\n cancelText,\n onAction,\n onClose,\n container,\n inline = false,\n className,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const [isVisible, setIsVisible] = useState(true);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement | null>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const handleClose = useCallback(() => {\n setIsVisible(false);\n onClose?.();\n }, [onClose]);\n\n const handleAction = useCallback(() => {\n onAction?.();\n handleClose();\n }, [onAction, handleClose]);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleClose();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleClose]);\n\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Click-outside dismiss — deferred so the click that spawned the toast\n // doesn't immediately dismiss it before it's even visible.\n useEffect(() => {\n if (!dismissible || !isVisible) return undefined;\n\n const handleDocumentClick = (e: MouseEvent) => {\n if (toastRef.current && !isEventInside(e, toastRef.current)) {\n handleClose();\n }\n };\n\n const raf = requestAnimationFrame(() => {\n document.addEventListener('click', handleDocumentClick);\n });\n\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [dismissible, isVisible, handleClose]);\n\n // On `window`, as in `Modal`, so a popup on the page has had the key\n // first, and an Escape it closed on doesn't dismiss the toast as well.\n useEffect(() => {\n if (!cancelable || !isVisible) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !e.defaultPrevented) {\n handleClose();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, isVisible, handleClose]);\n\n const containerClasses = usePrefixedClassNames('toast-container', {\n [`is-${position}`]: true,\n });\n\n const toastClasses = usePrefixedClassNames('toast', {\n [`is-${type}`]: type !== 'default',\n [`is-action-${actionType}`]: !!actionType && actionType !== 'default',\n 'is-rounded': rounded,\n });\n\n const combinedClasses = classNames(\n toastClasses,\n bulmaHelperClasses,\n className\n );\n const toastMessageClass = usePrefixedClassNames('toast-message');\n const toastActionsClass = usePrefixedClassNames('toast-actions');\n const toastCancelClass = usePrefixedClassNames('toast-cancel');\n const toastActionClass = usePrefixedClassNames('toast-action');\n const toastButtonClass = usePrefixedClassNames('button');\n const toastCloseClass = usePrefixedClassNames('delete', 'is-small');\n\n const setRef = useCallback(\n (node: HTMLDivElement | null) => {\n toastRef.current = node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split. Memoized because an\n // unstable ref identity makes React detach and re-attach on every render,\n // which would run that cleanup each time.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\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 as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n if (!isVisible) {\n return null;\n }\n\n const toastElement = (\n <div\n ref={setRef}\n className={combinedClasses}\n role=\"alert\"\n aria-live={\n type === 'danger' || type === 'warning' ? 'assertive' : 'polite'\n }\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={dismissible ? handleClose : undefined}\n {...rest}\n >\n <span className={toastMessageClass}>{message}</span>\n {(cancelText || actionText) && (\n <div className={toastActionsClass}>\n {cancelText && (\n <span className={toastCancelClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n >\n {cancelText}\n </button>\n </span>\n )}\n {actionText && (\n <span className={toastActionClass}>\n <button\n type=\"button\"\n className={toastButtonClass}\n onClick={e => {\n e.stopPropagation();\n handleAction();\n }}\n >\n {actionText}\n </button>\n </span>\n )}\n </div>\n )}\n {closable && (\n <button\n type=\"button\"\n className={toastCloseClass}\n onClick={e => {\n e.stopPropagation();\n handleClose();\n }}\n aria-label=\"Close\"\n />\n )}\n </div>\n );\n\n if (inline) {\n return toastElement;\n }\n\n const toastContent = <div className={containerClasses}>{toastElement}</div>;\n\n if (typeof document !== 'undefined') {\n return createPortal(toastContent, resolveContainer(container));\n }\n\n return null;\n }\n);\n\nToast.displayName = 'Toast';\n\n// Toast Manager for programmatic toasts\n\n/**\n * Options for showing a programmatic toast. Extends ToastProps with a required message.\n */\nexport interface ToastOptions extends Omit<ToastProps, 'message'> {\n /** The message to display. */\n message: string;\n /**\n * When true, toasts enter a FIFO queue and display one at a time, one queue\n * across every `position`. Default false.\n */\n queue?: boolean;\n}\n\n/**\n * Internal representation of a toast instance.\n */\nexport interface ToastInstance {\n /** Unique identifier for this toast. */\n id: string;\n /** Configuration options for the toast. */\n props: ToastOptions;\n}\n\nlet toastId = 0;\nconst toastListeners: Set<(toasts: ToastInstance[]) => void> = new Set();\nlet toasts: ToastInstance[] = [];\n\n// Queued toasts: FIFO queue, one at a time\nlet queuedToasts: ToastInstance[] = [];\nlet currentQueuedToast: ToastInstance | null = null;\n\n// The server has nowhere to portal a toast to, and its copy of this module is\n// shared by every request, so server rendering reads an empty list. Hydration\n// reads it too, which keeps the first client render matching the server's.\nconst noToasts: ToastInstance[] = [];\nconst getServerToasts = () => noToasts;\n\n// What a container shows right now: the stacked toasts, then the queued one on\n// screen. ToastContainer renders from this rather than from updates alone, so\n// toasts raised before it mounted still appear. It is replaced rather than\n// mutated, and only when listeners are notified, because useSyncExternalStore\n// needs the same array back between changes. An empty list is `noToasts`\n// itself, so a container that hydrates with nothing to show reads the same\n// snapshot the server did and has no reason to render again.\nlet visibleToasts: ToastInstance[] = noToasts;\nconst getVisibleToasts = () => visibleToasts;\n\nconst notifyListeners = () => {\n const allVisible = [...toasts];\n if (currentQueuedToast) {\n allVisible.push(currentQueuedToast);\n }\n visibleToasts = allVisible.length > 0 ? allVisible : noToasts;\n toastListeners.forEach(listener => listener([...allVisible]));\n};\n\nconst processQueuedToast = () => {\n if (currentQueuedToast || queuedToasts.length === 0) return;\n currentQueuedToast = queuedToasts.shift()!;\n notifyListeners();\n};\n\n/**\n * Programmatic toast API for showing, closing, and managing toasts.\n *\n * @example\n * toast.success('Saved!');\n * toast.show({ message: 'Item deleted', actionText: 'Undo', onAction: handleUndo });\n */\nexport const toast = {\n /**\n * Show a toast with the given options.\n * @param {ToastOptions} options - Toast configuration.\n * @returns {string} The unique ID of the created toast.\n */\n show: (options: ToastOptions): string => {\n const id = `toast-${++toastId}`;\n const instance = { id, props: options };\n\n if (options.queue) {\n queuedToasts.push(instance);\n processQueuedToast();\n } else {\n toasts.push(instance);\n notifyListeners();\n }\n\n return id;\n },\n\n /**\n * Show a success toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n success: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'success', ...options });\n },\n\n /**\n * Show a danger toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n danger: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'danger', ...options });\n },\n\n /**\n * Show a warning toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n warning: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'warning', ...options });\n },\n\n /**\n * Show an info toast.\n * @param {string} message - The message to display.\n * @param {Partial<ToastOptions>} [options] - Additional options.\n * @returns {string} The toast ID.\n */\n info: (message: string, options?: Partial<ToastOptions>): string => {\n return toast.show({ message, type: 'info', ...options });\n },\n\n /**\n * Close a specific toast by ID.\n * @param {string} id - The toast ID to close.\n */\n close: (id: string): void => {\n if (currentQueuedToast && currentQueuedToast.id === id) {\n currentQueuedToast = null;\n processQueuedToast();\n } else {\n queuedToasts = queuedToasts.filter(t => t.id !== id);\n toasts = toasts.filter(t => t.id !== id);\n }\n notifyListeners();\n },\n\n /** Close all toasts and clear the queue. */\n closeAll: (): void => {\n toasts = [];\n queuedToasts = [];\n currentQueuedToast = null;\n notifyListeners();\n },\n\n /**\n * Subscribe to toast state changes.\n * @param {(toasts: ToastInstance[]) => void} listener - Callback invoked on changes.\n * @returns {() => void} Unsubscribe function.\n */\n subscribe: (listener: (toasts: ToastInstance[]) => void): (() => void) => {\n toastListeners.add(listener);\n return () => toastListeners.delete(listener);\n },\n};\n\n// The order ToastContainer renders its stacks in: across the top of the\n// screen, then across the bottom.\nconst toastStackOrder: readonly ToastPosition[] = [\n 'top-left',\n 'top-center',\n 'top-right',\n 'bottom-left',\n 'bottom-center',\n 'bottom-right',\n];\n\n/**\n * Container component for rendering programmatic toasts.\n * Place once at your app root to enable the toast API. A toast shown with a\n * `position` appears there, and one shown without goes to the container's\n * `position`.\n *\n * @function\n * @param {{ position?: ToastPosition }} props - Container props.\n * @returns {JSX.Element | null} The rendered toast container, or null if empty.\n */\nexport const ToastContainer: React.FC<{\n /**\n * Where a toast shown without a `position` of its own appears. Default:\n * 'top-right'. When it changes, those toasts move without remounting, but\n * one shown with its own `position` equal to the old or new value\n * remounts and starts over as if it had just been shown.\n */\n position?: ToastPosition;\n}> = ({ position = 'top-right' }) => {\n // Starts from the toasts already showing instead of an empty list, then\n // follows changes.\n const toastList = useSyncExternalStore(\n toast.subscribe,\n getVisibleToasts,\n getServerToasts\n );\n const resolveContainer = usePortalContainer();\n\n if (typeof document === 'undefined' || toastList.length === 0) {\n return null;\n }\n\n const stacks = groupIntoPositionStacks(\n toastList,\n t => t.props.position,\n position,\n toastStackOrder\n );\n\n return createPortal(\n stacks.map(stack => (\n <div key={stack.key} className={`toast-container is-${stack.position}`}>\n {stack.items.map(t => {\n const { queue: _queue, ...toastProps } = t.props;\n return (\n <Toast\n key={t.id}\n {...toastProps}\n position={stack.position}\n onClose={() => toast.close(t.id)}\n />\n );\n })}\n </div>\n )),\n resolveContainer()\n );\n};\n\nexport default Toast;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -39,6 +39,11 @@ const nothingToAnnounce = [];
|
|
|
39
39
|
* />
|
|
40
40
|
*/
|
|
41
41
|
const Autocomplete = forwardRef(({ data = [], value: controlledValue, placeholder, field = 'label', clearable = false, openOnFocus = false, keepFirst = false, keepOpen = false, selectOnClickOutside = false, maxHeight = 200, loading = false, disabled = false, checkInfiniteScroll = false, infiniteScrollDistance = 50, color, size, onInput, onSelect, onActiveChange, onInfiniteScroll, itemTemplate, header, footer, empty, name, form, required, id,
|
|
42
|
+
// Deprecated no-ops, taken here so they stay off the wrapper.
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op
|
|
44
|
+
selected,
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op
|
|
46
|
+
dropdown,
|
|
42
47
|
// Field props
|
|
43
48
|
label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName, className, ...props }, ref) => {
|
|
44
49
|
const insideField = useInsideField();
|
|
@@ -191,7 +196,10 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
191
196
|
}
|
|
192
197
|
break;
|
|
193
198
|
case 'Escape':
|
|
194
|
-
|
|
199
|
+
// Only closing the dropdown claims the key. With it closed, the
|
|
200
|
+
// key goes on to a Modal around the field.
|
|
201
|
+
if (menuOpen)
|
|
202
|
+
e.preventDefault();
|
|
195
203
|
setIsActive(false);
|
|
196
204
|
setHighlightedIndex(-1);
|
|
197
205
|
break;
|
|
@@ -202,7 +210,14 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
202
210
|
setIsActive(false);
|
|
203
211
|
break;
|
|
204
212
|
}
|
|
205
|
-
}, [
|
|
213
|
+
}, [
|
|
214
|
+
disabled,
|
|
215
|
+
isActive,
|
|
216
|
+
menuOpen,
|
|
217
|
+
highlightedIndex,
|
|
218
|
+
filteredData,
|
|
219
|
+
handleSelect,
|
|
220
|
+
]);
|
|
206
221
|
// Handle dropdown scroll for infinite scroll
|
|
207
222
|
const handleDropdownScroll = useCallback(() => {
|
|
208
223
|
if (!checkInfiniteScroll || !dropdownRef.current)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Autocomplete.js","sources":["../../../src/form/Autocomplete.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 } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useInsideField } from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { useControlLoading } from './controlLoading';\nimport { StatusRegion, spokenText } from '../helpers/statusRegion';\n\n/**\n * An item in the Autocomplete dropdown list.\n */\nexport interface AutocompleteItem {\n /** The value used for filtering and selection. */\n value: string;\n /** Display label (optional). */\n label?: string;\n /** Whether the item is disabled and unselectable. */\n disabled?: boolean;\n [key: string]: unknown;\n}\n\n// What the status region announces: the `empty` content, as the one item\n// it's handed while that content is on screen because of the user's typing.\nconst typedNoMatches = [{ id: 'empty' }];\nconst nothingToAnnounce: Array<{ id: string }> = [];\n\n/**\n * Props for the Autocomplete component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface AutocompleteProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect' | 'onInput'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label, associated with the text input via `htmlFor`: through your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose label names the input instead when it points at it. The `Field` points its label there itself when the Autocomplete has no `id` and no inner `Field` sits between them (and the `Field` is not `grouped` or `hasAddons`); a label you wire by hand with `labelProps.htmlFor` points at the input with that `id`. 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 (the input then gets no generated id). 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 options data to display (required). */\n data: AutocompleteItem[] | string[];\n /** The current input value (controlled). */\n value?: string;\n /** The selected item (controlled). */\n selected?: AutocompleteItem | string | null;\n /** Placeholder text for the input. */\n placeholder?: string;\n /** Object property to use as the display field. */\n field?: string;\n /**\n * Whether to show a clear button while the input holds a value.\n * It hides while the input is disabled, and gives way to a loading\n * spinner at the same right edge: the one `loading` draws, or that of a\n * `Control` with `isLoading` around the Autocomplete.\n */\n clearable?: boolean;\n /** Open dropdown when input is focused. */\n openOnFocus?: boolean;\n /** Keep first option highlighted. */\n keepFirst?: boolean;\n /** Keep dropdown open after selection. */\n keepOpen?: boolean;\n /** Select highlighted item on click outside. */\n selectOnClickOutside?: boolean;\n /** Maximum dropdown height in pixels. */\n maxHeight?: number;\n /** Render as dropdown style. */\n dropdown?: boolean;\n /**\n * Show 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 /** Whether the input is disabled. */\n disabled?: boolean;\n /** Enables infinite scroll detection in the dropdown. */\n checkInfiniteScroll?: boolean;\n /** Distance in pixels from the bottom to trigger `onInfiniteScroll`. */\n infiniteScrollDistance?: number;\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. Forwarded to the inner `<input>`. */\n name?: string;\n /** Optional id of the form the input belongs to. */\n form?: string;\n /** Marks the field as required for native HTML form validation. */\n required?: boolean;\n /** Callback when input value changes. */\n onInput?: (value: string) => void;\n /** Callback when item is selected. */\n onSelect?: (item: AutocompleteItem | string | null) => void;\n /** Callback when dropdown active state changes. */\n onActiveChange?: (active: boolean) => void;\n /** Callback when scrolled to bottom (infinite scroll). */\n onInfiniteScroll?: () => void;\n /** Custom render for items. */\n itemTemplate?: (item: AutocompleteItem | string) => React.ReactNode;\n /** Custom header at the top of the dropdown. It sits above the list of options rather than in it, so assistive technology doesn't count it as one. */\n header?: React.ReactNode;\n /** Custom footer at the bottom of the dropdown. It sits below the list of options rather than in it, so assistive technology doesn't count it as one. */\n footer?: React.ReactNode;\n /**\n * A message the dropdown shows in place of the options when nothing\n * matches. Keep it to text: `Tab` closes the list, so a keyboard user\n * can't reach a link or button in it. It sits beside the list of options\n * rather than in it, so the input's `aria-expanded` stays false while it\n * shows. When the user's typing leaves nothing that matches, a polite\n * status region announces its text: once each time the matches run out.\n * The text is read when they first run out, and isn't read again as it\n * changes while they stay out, so a message that names the query is heard\n * for that first query only. Keep it static.\n * Opening the list without typing, or emptying the field, announces\n * nothing. While `loading`, or a `Control` with `isLoading` around the\n * Autocomplete, is on, it waits, and it's announced once loading ends\n * with nothing matching. Without `empty`, the dropdown closes when nothing\n * matches and nothing is announced.\n */\n empty?: React.ReactNode;\n}\n\n/**\n * The `Autocomplete` component provides an input field with dropdown suggestions that filter based on user input.\n *\n * @function\n * @param {AutocompleteProps} props - Props for the Autocomplete component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered autocomplete component.\n *\n * @example\n * // Basic usage with string array\n * <Autocomplete\n * data={['Apple', 'Banana', 'Cherry']}\n * placeholder=\"Search fruit...\"\n * onSelect={(item) => console.log(item)}\n * />\n *\n * @example\n * // With object data\n * <Autocomplete\n * data={[{ value: '1', label: 'Option 1' }, { value: '2', label: 'Option 2' }]}\n * field=\"label\"\n * onSelect={(item) => console.log(item)}\n * />\n */\nexport const Autocomplete = forwardRef<HTMLInputElement, AutocompleteProps>(\n (\n {\n data = [],\n value: controlledValue,\n placeholder,\n field = 'label',\n clearable = false,\n openOnFocus = false,\n keepFirst = false,\n keepOpen = false,\n selectOnClickOutside = false,\n maxHeight = 200,\n loading = false,\n disabled = false,\n checkInfiniteScroll = false,\n infiniteScrollDistance = 50,\n color,\n size,\n onInput,\n onSelect,\n onActiveChange,\n onInfiniteScroll,\n itemTemplate,\n header,\n footer,\n empty,\n name,\n form,\n required,\n id,\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n className,\n ...props\n },\n ref\n ) => {\n const insideField = useInsideField();\n // The suggestion list points `aria-labelledby` at the label that names\n // the input, so it needs that label's id.\n const {\n controlId,\n fieldLabelProps,\n labelId: listLabelId,\n } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: !insideField,\n needsLabelId: true,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalValue, setInternalValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n // Whether the user has typed since the list opened, since only typing\n // gets the `empty` content announced. Closing the list resets it (during\n // render, React's pattern for adjusting state when other state changes),\n // so opening the list again without typing stays quiet.\n const [typed, setTyped] = useState(false);\n if (typed && !isActive) setTyped(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const listboxId = `${useId()}-listbox`;\n\n // Use controlled or internal value\n const inputValue =\n controlledValue !== undefined ? controlledValue : internalValue;\n\n // Get display value from item\n const getDisplayValue = (item: AutocompleteItem | string): string => {\n if (typeof item === 'string') return item;\n const fieldValue = item[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return item.value || '';\n };\n\n // Filter data based on input\n const filteredData = data.filter(item => {\n const displayValue = getDisplayValue(item);\n return displayValue.toLowerCase().includes(inputValue.toLowerCase());\n });\n\n // The dropdown shows the options or, when nothing matches, the `empty`\n // content. The listbox holds only options, so it's on screen only while\n // there are some.\n const menuOpen = isActive && (filteredData.length > 0 || !!empty);\n const listOpen = isActive && filteredData.length > 0;\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (controlledValue === undefined) {\n setInternalValue(newValue);\n }\n onInput?.(newValue);\n setTyped(true);\n if (!isActive && newValue) {\n setIsActive(true);\n }\n },\n [controlledValue, isActive, onInput]\n );\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: AutocompleteItem | string) => {\n if (typeof item !== 'string' && item.disabled) return;\n\n const displayValue = getDisplayValue(item);\n if (controlledValue === undefined) {\n setInternalValue(displayValue);\n }\n onInput?.(displayValue);\n onSelect?.(item);\n\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [controlledValue, field, keepOpen, onInput, onSelect]\n );\n\n // Handle clear\n const handleClear = useCallback(() => {\n if (controlledValue === undefined) {\n setInternalValue('');\n }\n onInput?.('');\n onSelect?.(null);\n inputRef.current?.focus();\n }, [controlledValue, onInput, onSelect]);\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, disabled]);\n\n // Handle blur (click outside)\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n // Use composedPath() to correctly detect clicks inside Shadow DOM\n const path = e.composedPath();\n const isInside = path.includes(containerRef.current);\n\n if (!isInside) {\n if (selectOnClickOutside && highlightedIndex >= 0) {\n handleSelect(filteredData[highlightedIndex]);\n }\n setIsActive(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [\n isActive,\n selectOnClickOutside,\n highlightedIndex,\n filteredData,\n handleSelect,\n ]);\n\n // Notify active state change\n useEffect(() => {\n onActiveChange?.(isActive);\n }, [isActive, onActiveChange]);\n\n // Keep first highlighted\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length, inputValue]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive) {\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 'Enter':\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n handleSelect(filteredData[highlightedIndex]);\n }\n break;\n case 'Escape':\n e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n case 'Tab':\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n handleSelect(filteredData[highlightedIndex]);\n }\n setIsActive(false);\n break;\n }\n },\n [disabled, isActive, highlightedIndex, filteredData, handleSelect]\n );\n\n // Handle dropdown scroll for infinite scroll\n const handleDropdownScroll = useCallback(() => {\n if (!checkInfiniteScroll || !dropdownRef.current) return;\n\n const { scrollTop, scrollHeight, clientHeight } = dropdownRef.current;\n if (scrollHeight - scrollTop - clientHeight <= infiniteScrollDistance) {\n onInfiniteScroll?.();\n }\n }, [checkInfiniteScroll, infiniteScrollDistance, onInfiniteScroll]);\n\n // Scroll highlighted item into view\n useEffect(() => {\n if (highlightedIndex >= 0 && dropdownRef.current) {\n const highlightedEl = dropdownRef.current.querySelector(\n `[data-index=\"${highlightedIndex}\"]`\n );\n if (\n highlightedEl &&\n typeof highlightedEl.scrollIntoView === 'function'\n ) {\n highlightedEl.scrollIntoView({ block: 'nearest' });\n }\n }\n }, [highlightedIndex]);\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 // Generate classes\n const autocompleteClasses = usePrefixedClassNames('autocomplete', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n });\n\n const inputClasses = usePrefixedClassNames('input', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-loading': loading,\n });\n\n const controlClasses = usePrefixedClassNames(\n 'control',\n 'is-expanded',\n 'has-icons-right'\n );\n\n const dropdownMenuClasses = usePrefixedClassNames('dropdown-menu', {\n 'is-active': menuOpen,\n });\n\n const dropdownContentClass = usePrefixedClassNames('dropdown-content');\n const dropdownHeaderClass = usePrefixedClassNames('dropdown-header');\n const dropdownFooterClass = usePrefixedClassNames('dropdown-footer');\n const emptyItemClasses = usePrefixedClassNames(\n 'dropdown-item',\n 'has-text-grey'\n );\n\n const iconRightClickableClass = usePrefixedClassNames(\n 'icon',\n 'is-right',\n 'is-clickable'\n );\n const iconRightClass = usePrefixedClassNames('icon', 'is-right');\n const loaderClass = usePrefixedClassNames('loader', 'is-loading');\n\n const combinedClasses = classNames(\n autocompleteClasses,\n bulmaHelperClasses,\n className\n );\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n // The clear button gives way to a spinner at its spot: the `loading` one,\n // or that of a loading Control this sits in.\n const controlLoading = useControlLoading();\n const showClear =\n clearable && !!inputValue && !disabled && !loading && !controlLoading;\n\n // The combobox controls its listbox and points at the highlighted option.\n // The listbox takes its name from the label that names the combobox, the\n // one this renders or a surrounding Field's, so the two say the same\n // thing. When no label names the combobox, or the one that does has no\n // id to point at, the list keeps a fallback name. While the dropdown\n // shows only the `empty` content there's no listbox, so the combobox is\n // collapsed and points at nothing.\n const activeOptionId =\n listOpen &&\n highlightedIndex >= 0 &&\n highlightedIndex < filteredData.length\n ? `${listboxId}-${highlightedIndex}`\n : undefined;\n\n // A polite status region, in the page from the start so it's there\n // before anything is written into it, announces the `empty` content\n // when the user's typing leaves nothing that matches what's in the\n // field. It follows what's on screen, so results that come in after the\n // typing count too. It's said once each time that happens, not again on\n // each keystroke while nothing matches. An empty field isn't a search,\n // so it stays quiet then, even with no data. While `loading`, or a\n // loading Control around it, says results are on their way, it waits,\n // and it's said once loading ends with nothing matching.\n const emptyItems =\n typed &&\n menuOpen &&\n !listOpen &&\n !!inputValue &&\n !loading &&\n !controlLoading\n ? typedNoMatches\n : nothingToAnnounce;\n // The region reads the text on screen, whatever `empty` renders.\n const emptyRef = useRef<HTMLDivElement>(null);\n const describeEmpty = useCallback(() => {\n const node = emptyRef.current;\n /* istanbul ignore if: it's only announced while it's on screen */\n if (!node) return null;\n return spokenText(node);\n }, []);\n\n const autocompleteElement = (\n <div ref={containerRef} className={combinedClasses} {...rest}>\n <div className={controlClasses}>\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n name={name}\n form={form}\n required={required}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\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 autoComplete=\"off\"\n />\n {showClear && (\n <button\n type=\"button\"\n className={iconRightClickableClass}\n onClick={handleClear}\n aria-label=\"Clear\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n width=\"16\"\n height=\"16\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )}\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {menuOpen && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n className={dropdownContentClass}\n style={{ maxHeight: `${maxHeight}px`, overflowY: 'auto' }}\n onScroll={handleDropdownScroll}\n >\n {header && <div className={dropdownHeaderClass}>{header}</div>}\n\n {listOpen ? (\n <div\n id={listboxId}\n role=\"listbox\"\n aria-labelledby={listLabelId}\n aria-label={listLabelId ? undefined : 'Suggestions'}\n >\n {filteredData.map((item, index) => {\n const isDisabled =\n typeof item !== 'string' && item.disabled;\n const isHighlighted = index === highlightedIndex;\n\n const itemClasses = prefixedClassNames(\n classPrefix,\n 'dropdown-item',\n {\n 'is-active': isHighlighted,\n 'is-disabled': isDisabled,\n }\n );\n\n return (\n <a\n key={index}\n id={`${listboxId}-${index}`}\n data-index={index}\n className={itemClasses}\n onClick={() => !isDisabled && handleSelect(item)}\n onMouseEnter={() =>\n !isDisabled && setHighlightedIndex(index)\n }\n role=\"option\"\n aria-selected={isHighlighted}\n aria-disabled={isDisabled}\n >\n {itemTemplate\n ? itemTemplate(item)\n : getDisplayValue(item)}\n </a>\n );\n })}\n </div>\n ) : (\n <div ref={emptyRef} className={emptyItemClasses}>\n {empty}\n </div>\n )}\n\n {footer && <div className={dropdownFooterClass}>{footer}</div>}\n </div>\n </div>\n )}\n\n <StatusRegion items={emptyItems} describe={describeEmpty} />\n </div>\n );\n\n if (!insideField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {autocompleteElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {autocompleteElement}\n {messageEl}\n </>\n );\n }\n);\n\nAutocomplete.displayName = 'Autocomplete';\n\nexport default Autocomplete;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Autocomplete.js","sources":["../../../src/form/Autocomplete.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 } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useInsideField } from './FormContext';\nimport { Field } from './Field';\nimport { FormFieldProps } from './fieldProps';\nimport { useAutoLabelId } from './useAutoLabelId';\nimport { useControlLoading } from './controlLoading';\nimport { StatusRegion, spokenText } from '../helpers/statusRegion';\n\n/**\n * An item in the Autocomplete dropdown list.\n */\nexport interface AutocompleteItem {\n /** The value used for filtering and selection. */\n value: string;\n /** Display label (optional). */\n label?: string;\n /** Whether the item is disabled and unselectable. */\n disabled?: boolean;\n [key: string]: unknown;\n}\n\n// What the status region announces: the `empty` content, as the one item\n// it's handed while that content is on screen because of the user's typing.\nconst typedNoMatches = [{ id: 'empty' }];\nconst nothingToAnnounce: Array<{ id: string }> = [];\n\n/**\n * Props for the Autocomplete component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the input element.\n */\nexport interface AutocompleteProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect' | 'onInput'>,\n Omit<BulmaClassesProps, 'color'>,\n FormFieldProps {\n /** Field label, associated with the text input via `htmlFor`: through your `id` when provided, otherwise a generated one. Dropped inside an outer `Field`, whose label names the input instead when it points at it. The `Field` points its label there itself when the Autocomplete has no `id` and no inner `Field` sits between them (and the `Field` is not `grouped` or `hasAddons`); a label you wire by hand with `labelProps.htmlFor` points at the input with that `id`. 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 (the input then gets no generated id). 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 options data to display (required). */\n data: AutocompleteItem[] | string[];\n /** The current input value (controlled). */\n value?: string;\n /**\n * Does nothing: Autocomplete doesn't read it.\n *\n * @deprecated Nothing reads it, and `onSelect` is what reports a pick. It\n * will be removed in the next major version.\n */\n selected?: AutocompleteItem | string | null;\n /** Placeholder text for the input. */\n placeholder?: string;\n /** Object property to use as the display field. */\n field?: string;\n /**\n * Whether to show a clear button while the input holds a value.\n * It hides while the input is disabled, and gives way to a loading\n * spinner at the same right edge: the one `loading` draws, or that of a\n * `Control` with `isLoading` around the Autocomplete.\n */\n clearable?: boolean;\n /** Open dropdown when input is focused. */\n openOnFocus?: boolean;\n /** Keep first option highlighted. */\n keepFirst?: boolean;\n /** Keep dropdown open after selection. */\n keepOpen?: boolean;\n /** Select highlighted item on click outside. */\n selectOnClickOutside?: boolean;\n /** Maximum dropdown height in pixels. */\n maxHeight?: number;\n /**\n * Does nothing: Autocomplete doesn't read it, and always shows its\n * suggestions in a dropdown.\n *\n * @deprecated It will be removed in the next major version, with nothing\n * in its place.\n */\n dropdown?: boolean;\n /**\n * Show 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 /** Whether the input is disabled. */\n disabled?: boolean;\n /** Enables infinite scroll detection in the dropdown. */\n checkInfiniteScroll?: boolean;\n /** Distance in pixels from the bottom to trigger `onInfiniteScroll`. */\n infiniteScrollDistance?: number;\n /** Input color variant. */\n color?: 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n /** Size variant. */\n size?: 'small' | 'medium' | 'large';\n /** Form field name. Forwarded to the inner `<input>`. */\n name?: string;\n /** Optional id of the form the input belongs to. */\n form?: string;\n /** Marks the field as required for native HTML form validation. */\n required?: boolean;\n /** Callback when input value changes. */\n onInput?: (value: string) => void;\n /** Callback when item is selected. */\n onSelect?: (item: AutocompleteItem | string | null) => void;\n /** Callback when dropdown active state changes. */\n onActiveChange?: (active: boolean) => void;\n /** Callback when scrolled to bottom (infinite scroll). */\n onInfiniteScroll?: () => void;\n /** Custom render for items. */\n itemTemplate?: (item: AutocompleteItem | string) => React.ReactNode;\n /** Custom header at the top of the dropdown. It sits above the list of options rather than in it, so assistive technology doesn't count it as one. */\n header?: React.ReactNode;\n /** Custom footer at the bottom of the dropdown. It sits below the list of options rather than in it, so assistive technology doesn't count it as one. */\n footer?: React.ReactNode;\n /**\n * A message the dropdown shows in place of the options when nothing\n * matches. Keep it to text: `Tab` closes the list, so a keyboard user\n * can't reach a link or button in it. It sits beside the list of options\n * rather than in it, so the input's `aria-expanded` stays false while it\n * shows. When the user's typing leaves nothing that matches, a polite\n * status region announces its text: once each time the matches run out.\n * The text is read when they first run out, and isn't read again as it\n * changes while they stay out, so a message that names the query is heard\n * for that first query only. Keep it static.\n * Opening the list without typing, or emptying the field, announces\n * nothing. While `loading`, or a `Control` with `isLoading` around the\n * Autocomplete, is on, it waits, and it's announced once loading ends\n * with nothing matching. Without `empty`, the dropdown closes when nothing\n * matches and nothing is announced.\n */\n empty?: React.ReactNode;\n}\n\n/**\n * The `Autocomplete` component provides an input field with dropdown suggestions that filter based on user input.\n *\n * @function\n * @param {AutocompleteProps} props - Props for the Autocomplete component.\n * @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the input element.\n * @returns {JSX.Element} The rendered autocomplete component.\n *\n * @example\n * // Basic usage with string array\n * <Autocomplete\n * data={['Apple', 'Banana', 'Cherry']}\n * placeholder=\"Search fruit...\"\n * onSelect={(item) => console.log(item)}\n * />\n *\n * @example\n * // With object data\n * <Autocomplete\n * data={[{ value: '1', label: 'Option 1' }, { value: '2', label: 'Option 2' }]}\n * field=\"label\"\n * onSelect={(item) => console.log(item)}\n * />\n */\nexport const Autocomplete = forwardRef<HTMLInputElement, AutocompleteProps>(\n (\n {\n data = [],\n value: controlledValue,\n placeholder,\n field = 'label',\n clearable = false,\n openOnFocus = false,\n keepFirst = false,\n keepOpen = false,\n selectOnClickOutside = false,\n maxHeight = 200,\n loading = false,\n disabled = false,\n checkInfiniteScroll = false,\n infiniteScrollDistance = 50,\n color,\n size,\n onInput,\n onSelect,\n onActiveChange,\n onInfiniteScroll,\n itemTemplate,\n header,\n footer,\n empty,\n name,\n form,\n required,\n id,\n // Deprecated no-ops, taken here so they stay off the wrapper.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op\n selected,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- deprecated no-op\n dropdown,\n // Field props\n label,\n labelSize,\n labelProps,\n horizontal,\n message,\n messageColor,\n fieldClassName,\n className,\n ...props\n },\n ref\n ) => {\n const insideField = useInsideField();\n // The suggestion list points `aria-labelledby` at the label that names\n // the input, so it needs that label's id.\n const {\n controlId,\n fieldLabelProps,\n labelId: listLabelId,\n } = useAutoLabelId({\n label,\n id,\n labelProps,\n rendersLabel: !insideField,\n needsLabelId: true,\n });\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const { classPrefix } = useConfig();\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const [internalValue, setInternalValue] = useState('');\n const [isActive, setIsActive] = useState(false);\n // Whether the user has typed since the list opened, since only typing\n // gets the `empty` content announced. Closing the list resets it (during\n // render, React's pattern for adjusting state when other state changes),\n // so opening the list again without typing stays quiet.\n const [typed, setTyped] = useState(false);\n if (typed && !isActive) setTyped(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const listboxId = `${useId()}-listbox`;\n\n // Use controlled or internal value\n const inputValue =\n controlledValue !== undefined ? controlledValue : internalValue;\n\n // Get display value from item\n const getDisplayValue = (item: AutocompleteItem | string): string => {\n if (typeof item === 'string') return item;\n const fieldValue = item[field];\n if (typeof fieldValue === 'string') return fieldValue;\n return item.value || '';\n };\n\n // Filter data based on input\n const filteredData = data.filter(item => {\n const displayValue = getDisplayValue(item);\n return displayValue.toLowerCase().includes(inputValue.toLowerCase());\n });\n\n // The dropdown shows the options or, when nothing matches, the `empty`\n // content. The listbox holds only options, so it's on screen only while\n // there are some.\n const menuOpen = isActive && (filteredData.length > 0 || !!empty);\n const listOpen = isActive && filteredData.length > 0;\n\n // Handle input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (controlledValue === undefined) {\n setInternalValue(newValue);\n }\n onInput?.(newValue);\n setTyped(true);\n if (!isActive && newValue) {\n setIsActive(true);\n }\n },\n [controlledValue, isActive, onInput]\n );\n\n // Handle item selection\n const handleSelect = useCallback(\n (item: AutocompleteItem | string) => {\n if (typeof item !== 'string' && item.disabled) return;\n\n const displayValue = getDisplayValue(item);\n if (controlledValue === undefined) {\n setInternalValue(displayValue);\n }\n onInput?.(displayValue);\n onSelect?.(item);\n\n if (!keepOpen) {\n setIsActive(false);\n }\n setHighlightedIndex(-1);\n },\n [controlledValue, field, keepOpen, onInput, onSelect]\n );\n\n // Handle clear\n const handleClear = useCallback(() => {\n if (controlledValue === undefined) {\n setInternalValue('');\n }\n onInput?.('');\n onSelect?.(null);\n inputRef.current?.focus();\n }, [controlledValue, onInput, onSelect]);\n\n // Handle focus\n const handleFocus = useCallback(() => {\n if (openOnFocus && !disabled) {\n setIsActive(true);\n }\n }, [openOnFocus, disabled]);\n\n // Handle blur (click outside)\n useEffect(() => {\n if (!isActive) return undefined;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (!containerRef.current) return;\n\n // Use composedPath() to correctly detect clicks inside Shadow DOM\n const path = e.composedPath();\n const isInside = path.includes(containerRef.current);\n\n if (!isInside) {\n if (selectOnClickOutside && highlightedIndex >= 0) {\n handleSelect(filteredData[highlightedIndex]);\n }\n setIsActive(false);\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }, [\n isActive,\n selectOnClickOutside,\n highlightedIndex,\n filteredData,\n handleSelect,\n ]);\n\n // Notify active state change\n useEffect(() => {\n onActiveChange?.(isActive);\n }, [isActive, onActiveChange]);\n\n // Keep first highlighted\n useEffect(() => {\n if (keepFirst && isActive && filteredData.length > 0) {\n setHighlightedIndex(0);\n }\n }, [keepFirst, isActive, filteredData.length, inputValue]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isActive) {\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 'Enter':\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n handleSelect(filteredData[highlightedIndex]);\n }\n break;\n case 'Escape':\n // Only closing the dropdown claims the key. With it closed, the\n // key goes on to a Modal around the field.\n if (menuOpen) e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n case 'Tab':\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n handleSelect(filteredData[highlightedIndex]);\n }\n setIsActive(false);\n break;\n }\n },\n [\n disabled,\n isActive,\n menuOpen,\n highlightedIndex,\n filteredData,\n handleSelect,\n ]\n );\n\n // Handle dropdown scroll for infinite scroll\n const handleDropdownScroll = useCallback(() => {\n if (!checkInfiniteScroll || !dropdownRef.current) return;\n\n const { scrollTop, scrollHeight, clientHeight } = dropdownRef.current;\n if (scrollHeight - scrollTop - clientHeight <= infiniteScrollDistance) {\n onInfiniteScroll?.();\n }\n }, [checkInfiniteScroll, infiniteScrollDistance, onInfiniteScroll]);\n\n // Scroll highlighted item into view\n useEffect(() => {\n if (highlightedIndex >= 0 && dropdownRef.current) {\n const highlightedEl = dropdownRef.current.querySelector(\n `[data-index=\"${highlightedIndex}\"]`\n );\n if (\n highlightedEl &&\n typeof highlightedEl.scrollIntoView === 'function'\n ) {\n highlightedEl.scrollIntoView({ block: 'nearest' });\n }\n }\n }, [highlightedIndex]);\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 // Generate classes\n const autocompleteClasses = usePrefixedClassNames('autocomplete', {\n 'is-active': isActive,\n [`is-${size}`]: !!size,\n });\n\n const inputClasses = usePrefixedClassNames('input', {\n [`is-${color}`]: !!color,\n [`is-${size}`]: !!size,\n 'is-loading': loading,\n });\n\n const controlClasses = usePrefixedClassNames(\n 'control',\n 'is-expanded',\n 'has-icons-right'\n );\n\n const dropdownMenuClasses = usePrefixedClassNames('dropdown-menu', {\n 'is-active': menuOpen,\n });\n\n const dropdownContentClass = usePrefixedClassNames('dropdown-content');\n const dropdownHeaderClass = usePrefixedClassNames('dropdown-header');\n const dropdownFooterClass = usePrefixedClassNames('dropdown-footer');\n const emptyItemClasses = usePrefixedClassNames(\n 'dropdown-item',\n 'has-text-grey'\n );\n\n const iconRightClickableClass = usePrefixedClassNames(\n 'icon',\n 'is-right',\n 'is-clickable'\n );\n const iconRightClass = usePrefixedClassNames('icon', 'is-right');\n const loaderClass = usePrefixedClassNames('loader', 'is-loading');\n\n const combinedClasses = classNames(\n autocompleteClasses,\n bulmaHelperClasses,\n className\n );\n\n const helpClass = usePrefixedClassNames('help', {\n [`is-${messageColor}`]: !!messageColor,\n });\n const messageEl = message ? <p className={helpClass}>{message}</p> : null;\n\n // The clear button gives way to a spinner at its spot: the `loading` one,\n // or that of a loading Control this sits in.\n const controlLoading = useControlLoading();\n const showClear =\n clearable && !!inputValue && !disabled && !loading && !controlLoading;\n\n // The combobox controls its listbox and points at the highlighted option.\n // The listbox takes its name from the label that names the combobox, the\n // one this renders or a surrounding Field's, so the two say the same\n // thing. When no label names the combobox, or the one that does has no\n // id to point at, the list keeps a fallback name. While the dropdown\n // shows only the `empty` content there's no listbox, so the combobox is\n // collapsed and points at nothing.\n const activeOptionId =\n listOpen &&\n highlightedIndex >= 0 &&\n highlightedIndex < filteredData.length\n ? `${listboxId}-${highlightedIndex}`\n : undefined;\n\n // A polite status region, in the page from the start so it's there\n // before anything is written into it, announces the `empty` content\n // when the user's typing leaves nothing that matches what's in the\n // field. It follows what's on screen, so results that come in after the\n // typing count too. It's said once each time that happens, not again on\n // each keystroke while nothing matches. An empty field isn't a search,\n // so it stays quiet then, even with no data. While `loading`, or a\n // loading Control around it, says results are on their way, it waits,\n // and it's said once loading ends with nothing matching.\n const emptyItems =\n typed &&\n menuOpen &&\n !listOpen &&\n !!inputValue &&\n !loading &&\n !controlLoading\n ? typedNoMatches\n : nothingToAnnounce;\n // The region reads the text on screen, whatever `empty` renders.\n const emptyRef = useRef<HTMLDivElement>(null);\n const describeEmpty = useCallback(() => {\n const node = emptyRef.current;\n /* istanbul ignore if: it's only announced while it's on screen */\n if (!node) return null;\n return spokenText(node);\n }, []);\n\n const autocompleteElement = (\n <div ref={containerRef} className={combinedClasses} {...rest}>\n <div className={controlClasses}>\n <input\n ref={combinedRef}\n type=\"text\"\n className={inputClasses}\n id={controlId}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n name={name}\n form={form}\n required={required}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\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 autoComplete=\"off\"\n />\n {showClear && (\n <button\n type=\"button\"\n className={iconRightClickableClass}\n onClick={handleClear}\n aria-label=\"Clear\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n width=\"16\"\n height=\"16\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n )}\n {loading && (\n <span className={iconRightClass}>\n <span className={loaderClass} />\n </span>\n )}\n </div>\n\n {menuOpen && (\n <div className={dropdownMenuClasses}>\n <div\n ref={dropdownRef}\n className={dropdownContentClass}\n style={{ maxHeight: `${maxHeight}px`, overflowY: 'auto' }}\n onScroll={handleDropdownScroll}\n >\n {header && <div className={dropdownHeaderClass}>{header}</div>}\n\n {listOpen ? (\n <div\n id={listboxId}\n role=\"listbox\"\n aria-labelledby={listLabelId}\n aria-label={listLabelId ? undefined : 'Suggestions'}\n >\n {filteredData.map((item, index) => {\n const isDisabled =\n typeof item !== 'string' && item.disabled;\n const isHighlighted = index === highlightedIndex;\n\n const itemClasses = prefixedClassNames(\n classPrefix,\n 'dropdown-item',\n {\n 'is-active': isHighlighted,\n 'is-disabled': isDisabled,\n }\n );\n\n return (\n <a\n key={index}\n id={`${listboxId}-${index}`}\n data-index={index}\n className={itemClasses}\n onClick={() => !isDisabled && handleSelect(item)}\n onMouseEnter={() =>\n !isDisabled && setHighlightedIndex(index)\n }\n role=\"option\"\n aria-selected={isHighlighted}\n aria-disabled={isDisabled}\n >\n {itemTemplate\n ? itemTemplate(item)\n : getDisplayValue(item)}\n </a>\n );\n })}\n </div>\n ) : (\n <div ref={emptyRef} className={emptyItemClasses}>\n {empty}\n </div>\n )}\n\n {footer && <div className={dropdownFooterClass}>{footer}</div>}\n </div>\n </div>\n )}\n\n <StatusRegion items={emptyItems} describe={describeEmpty} />\n </div>\n );\n\n if (!insideField) {\n return (\n <Field\n label={label}\n labelSize={labelSize}\n labelProps={fieldLabelProps}\n horizontal={horizontal}\n className={fieldClassName}\n >\n {autocompleteElement}\n {messageEl}\n </Field>\n );\n }\n\n return (\n <>\n {autocompleteElement}\n {messageEl}\n </>\n );\n }\n);\n\nAutocomplete.displayName = 'Autocomplete';\n\nexport default Autocomplete;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
|
|
@@ -266,6 +266,10 @@ label, labelSize, labelProps, horizontal, message, messageColor, fieldClassName,
|
|
|
266
266
|
}
|
|
267
267
|
break;
|
|
268
268
|
case 'Escape':
|
|
269
|
+
// Closing the suggestions claims the key, so a Modal around the
|
|
270
|
+
// field stays open. With none showing, the key goes on to it.
|
|
271
|
+
if (isActive && filteredData.length > 0)
|
|
272
|
+
e.preventDefault();
|
|
269
273
|
setIsActive(false);
|
|
270
274
|
setHighlightedIndex(-1);
|
|
271
275
|
break;
|
|
@@ -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} 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/**\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. Not wired when the tag limit is reached (the input is not rendered). 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 /** Maximum number of tags allowed. */\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 /** Characters that split pasted text into tags. */\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 = false,\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 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 listboxId = `${useId()}-listbox`;\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 // At the tag limit the text input is not rendered, so there is nothing to\n // wire a label to, its own or a surrounding Field's. The suggestion list\n // points `aria-labelledby` at the label that names the input, so with\n // 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 && !isMaxReached,\n hasInput: !isMaxReached,\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 const listOpen = isActive && 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 tag\n const addTag = useCallback(\n (value: string | TaginputTag) => {\n if (disabled || readonly) return;\n\n const tagValue = typeof value === 'string' ? value.trim() : value;\n const displayValue =\n typeof tagValue === 'string' ? tagValue : getDisplayValue(tagValue);\n\n if (!displayValue) return;\n\n // Check max tags\n if (maxTags && tags.length >= maxTags) return;\n\n // Check duplicates\n if (!allowDuplicates) {\n const exists = tags.some(\n tag =>\n getDisplayValue(tag).toLowerCase() === displayValue.toLowerCase()\n );\n if (exists) return;\n }\n\n // Check if allowed (must be in data if allowNew is false). Compare\n // case-insensitively, consistent with the dropdown filter and the\n // duplicate check above.\n if (\n !allowNew &&\n !data.some(d => d.toLowerCase() === displayValue.toLowerCase())\n )\n return;\n\n // beforeAdding validation\n if (beforeAdding && !beforeAdding(displayValue)) return;\n\n // createTag transformation\n const finalTag = createTag ? createTag(displayValue) : tagValue;\n\n const newTags = [...tags, finalTag];\n updateTags(newTags);\n onAdd?.(finalTag);\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 addTag(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, addTag, 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 regex from all separators\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n const parts = pastedText\n .split(regex)\n .map(s => s.trim())\n .filter(Boolean);\n\n for (const part of parts) {\n addTag(part);\n }\n },\n [onPasteSeparators, addTag]\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 // 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) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTag(filteredData[highlightedIndex]);\n } else if (inputValue.trim()) {\n addTag(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 setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTag,\n inputValue,\n isActive,\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 {!isMaxReached && (\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 readOnly={readonly}\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 />\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={() => addTag(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 && <small className={counterClasses}>{counterText}</small>}\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 {\n useInsideField,\n useInsideControl,\n rendersOwnField,\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/**\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. Not wired when the tag limit is reached (the input is not rendered). 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 /** Maximum number of tags allowed. */\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 /** Characters that split pasted text into tags. */\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 = false,\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 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 listboxId = `${useId()}-listbox`;\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 // At the tag limit the text input is not rendered, so there is nothing to\n // wire a label to, its own or a surrounding Field's. The suggestion list\n // points `aria-labelledby` at the label that names the input, so with\n // 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 && !isMaxReached,\n hasInput: !isMaxReached,\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 const listOpen = isActive && 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 tag\n const addTag = useCallback(\n (value: string | TaginputTag) => {\n if (disabled || readonly) return;\n\n const tagValue = typeof value === 'string' ? value.trim() : value;\n const displayValue =\n typeof tagValue === 'string' ? tagValue : getDisplayValue(tagValue);\n\n if (!displayValue) return;\n\n // Check max tags\n if (maxTags && tags.length >= maxTags) return;\n\n // Check duplicates\n if (!allowDuplicates) {\n const exists = tags.some(\n tag =>\n getDisplayValue(tag).toLowerCase() === displayValue.toLowerCase()\n );\n if (exists) return;\n }\n\n // Check if allowed (must be in data if allowNew is false). Compare\n // case-insensitively, consistent with the dropdown filter and the\n // duplicate check above.\n if (\n !allowNew &&\n !data.some(d => d.toLowerCase() === displayValue.toLowerCase())\n )\n return;\n\n // beforeAdding validation\n if (beforeAdding && !beforeAdding(displayValue)) return;\n\n // createTag transformation\n const finalTag = createTag ? createTag(displayValue) : tagValue;\n\n const newTags = [...tags, finalTag];\n updateTags(newTags);\n onAdd?.(finalTag);\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 addTag(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, addTag, 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 regex from all separators\n const escapedSeparators = onPasteSeparators.map(s =>\n s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const regex = new RegExp(`[${escapedSeparators.join('')}]`);\n\n const parts = pastedText\n .split(regex)\n .map(s => s.trim())\n .filter(Boolean);\n\n for (const part of parts) {\n addTag(part);\n }\n },\n [onPasteSeparators, addTag]\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 // 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) return;\n\n // Handle confirm keys\n if (confirmKeys.includes(e.key)) {\n e.preventDefault();\n if (highlightedIndex >= 0 && filteredData[highlightedIndex]) {\n addTag(filteredData[highlightedIndex]);\n } else if (inputValue.trim()) {\n addTag(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 (isActive && filteredData.length > 0) e.preventDefault();\n setIsActive(false);\n setHighlightedIndex(-1);\n break;\n }\n },\n [\n disabled,\n readonly,\n confirmKeys,\n highlightedIndex,\n filteredData,\n addTag,\n inputValue,\n isActive,\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 {!isMaxReached && (\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 readOnly={readonly}\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 />\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={() => addTag(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 && <small className={counterClasses}>{counterText}</small>}\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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"}
|