@allxsmith/bestax-bulma 5.57.0 → 5.57.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.
Files changed (63) hide show
  1. package/README.md +2 -2
  2. package/dist/bestax.css +1 -1
  3. package/dist/bestax.css.map +1 -1
  4. package/dist/esm/components/Dropdown.js +4 -1
  5. package/dist/esm/components/Dropdown.js.map +1 -1
  6. package/dist/esm/components/Toast.js +21 -7
  7. package/dist/esm/components/Toast.js.map +1 -1
  8. package/dist/esm/elements/Tr.js.map +1 -1
  9. package/dist/esm/form/Checkbox.js +21 -14
  10. package/dist/esm/form/Checkbox.js.map +1 -1
  11. package/dist/esm/form/CheckboxCard.js +17 -11
  12. package/dist/esm/form/CheckboxCard.js.map +1 -1
  13. package/dist/esm/form/Checkboxes.js +30 -3
  14. package/dist/esm/form/Checkboxes.js.map +1 -1
  15. package/dist/esm/form/FormContext.js +31 -1
  16. package/dist/esm/form/FormContext.js.map +1 -1
  17. package/dist/esm/form/Radio.js +13 -10
  18. package/dist/esm/form/Radio.js.map +1 -1
  19. package/dist/esm/form/RadioCard.js +10 -8
  20. package/dist/esm/form/RadioCard.js.map +1 -1
  21. package/dist/esm/form/Radios.js +15 -3
  22. package/dist/esm/form/Radios.js.map +1 -1
  23. package/dist/esm/form/Rate.js +2 -2
  24. package/dist/esm/form/Rate.js.map +1 -1
  25. package/dist/extras.css +1 -1
  26. package/dist/extras.css.map +1 -1
  27. package/dist/index.cjs +156 -53
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/types/components/Toast.d.ts +14 -3
  30. package/dist/types/elements/Tr.d.ts +3 -3
  31. package/dist/types/form/CheckboxCard.d.ts +1 -1
  32. package/dist/types/form/Checkboxes.d.ts +7 -1
  33. package/dist/types/form/FormContext.d.ts +34 -1
  34. package/dist/types/form/RadioCard.d.ts +1 -1
  35. package/dist/types/form/Radios.d.ts +5 -1
  36. package/dist/types/form/Rate.d.ts +5 -1
  37. package/dist/types-cjs/components/Toast.d.ts +14 -3
  38. package/dist/types-cjs/elements/Tr.d.ts +3 -3
  39. package/dist/types-cjs/form/CheckboxCard.d.ts +1 -1
  40. package/dist/types-cjs/form/Checkboxes.d.ts +7 -1
  41. package/dist/types-cjs/form/FormContext.d.ts +34 -1
  42. package/dist/types-cjs/form/RadioCard.d.ts +1 -1
  43. package/dist/types-cjs/form/Radios.d.ts +5 -1
  44. package/dist/types-cjs/form/Rate.d.ts +5 -1
  45. package/dist/versions/bestax-no-dark-mode.css +1 -1
  46. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  47. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  48. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  49. package/dist/versions/bestax-no-helpers.css +1 -1
  50. package/dist/versions/bestax-no-helpers.css.map +1 -1
  51. package/dist/versions/bestax-prefixed.css +1 -1
  52. package/dist/versions/bestax-prefixed.css.map +1 -1
  53. package/package.json +28 -28
  54. package/src/scss/CLAUDE.md +4 -1
  55. package/src/scss/_selected-row.scss +43 -0
  56. package/src/scss/components/_index.scss +1 -0
  57. package/src/scss/components/_pagination.scss +25 -0
  58. package/src/scss/components/_toast.scss +2 -1
  59. package/src/scss/form/_checkbox.scss +18 -42
  60. package/src/scss/form/_combobox.scss +11 -0
  61. package/src/scss/form/_radio.scss +28 -2
  62. package/src/scss/form/_switch.scss +9 -5
  63. package/src/scss/form/_taginput.scss +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","sources":["../../../src/components/Dropdown.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useState,\n useRef,\n useEffect,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { getActiveElementInTree, isEventInside } from '../helpers/shadowDom';\nimport type { ConstrainedPolymorphicComponentWithoutRef } from '../helpers/polymorphic';\nimport {\n type AnchorOnlyAttributes,\n ANCHOR_ONLY_ATTRS,\n omitAttrs,\n} from '../helpers/anchorAttrs';\nimport { buttonType } from '../helpers/buttonType';\nimport { enabledMenuItems, useMenuKeys } from '../helpers/useMenuKeys';\nimport { useLatestRef } from '../helpers/useLatestRef';\n\n/**\n * Checks if code is running in a browser environment.\n * @deprecated Dropdown's internal SSR guard, exported by accident; it will\n * be removed in the next major. Check `typeof window !== 'undefined' &&\n * typeof document !== 'undefined'` instead.\n * @param win - Window object.\n * @param doc - Document object.\n * @returns {boolean} True if in browser, false otherwise.\n */\nexport const isBrowser = (win?: typeof window, doc?: typeof document) =>\n typeof win !== 'undefined' && typeof doc !== 'undefined';\n\n/**\n * Props for the Dropdown component.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root dropdown element.\n */\nexport interface DropdownProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** The dropdown button/trigger content. */\n label: React.ReactNode;\n /** Dropdown menu items and dividers. */\n children: React.ReactNode;\n /** Additional CSS classes for root. */\n className?: string;\n /** Additional CSS classes for the dropdown menu. */\n menuClassName?: string;\n /** Whether the dropdown is open (controlled). */\n active?: boolean;\n /** Dropdown menu opens upward. */\n up?: boolean;\n /** Menu is right-aligned. */\n right?: boolean;\n /** Open on hover instead of click. */\n hoverable?: boolean;\n /** Disables the dropdown trigger. */\n disabled?: boolean;\n /** Callback when dropdown active state changes. */\n onActiveChange?: (active: boolean) => void;\n /** Close dropdown when a menu item is clicked, or activated with Enter or Space. */\n closeOnClick?: boolean;\n /** Root element ID (for aria-controls, etc). */\n id?: string;\n}\n\n/**\n * The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.\n *\n * Down, Enter and Space on the trigger open the menu on its first enabled\n * item, and Up opens it on its last. On the trigger of a menu that's already\n * open, Down and Up move focus to its first and last item. In the menu, the\n * arrow keys, Home and End move between the items, and Enter and Space run\n * the focused one the way a click does. Typing a letter moves to the next\n * item whose text starts with it, skipping disabled ones, and letters typed\n * in quick succession add up to one search. Typing searches once focus is in\n * the menu, so a letter typed on the trigger does nothing. Escape closes the\n * menu and focuses the trigger, and Tab closes it and lets focus move on.\n * Anything focusable in the menu that isn't an item, such as a field, keeps\n * its own keys apart from Escape and Tab, though an Escape it calls\n * `preventDefault()` on in its own `onKeyDown` stays its own and leaves the\n * menu open. For a panel built around fields, use `Popover`.\n *\n * @function\n * @param {DropdownProps} props - Props for the Dropdown component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root dropdown element.\n * @returns {JSX.Element} The rendered dropdown.\n * @see {@link https://bulma.io/documentation/components/dropdown/ | Bulma Dropdown documentation}\n */\nconst DropdownComponent = forwardRef<HTMLDivElement, DropdownProps>(\n function DropdownComponent(\n {\n label,\n children,\n className,\n menuClassName,\n active: activeProp,\n up,\n right,\n hoverable,\n disabled,\n onActiveChange,\n closeOnClick = true,\n id,\n ...props\n },\n ref\n ) {\n const [active, setActive] = useState<boolean>(!!activeProp);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const menuKeys = useMenuKeys();\n const pendingFocusRef = useRef<'first' | 'last' | 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\n const setRefs = useCallback(\n (node: HTMLDivElement | null) => {\n (dropdownRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches\n // by running it instead of calling the ref with `null`; React 18\n // discards the return value entirely. Returning it from here would be\n // a React-19-only contract, so instead we hold the cleanup and run it\n // ourselves on detach — a consumer's cleanup ref then behaves the same\n // on both majors of the CI matrix.\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 const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('dropdown', {\n 'is-active': active,\n 'is-up': up,\n 'is-right': right,\n 'is-hoverable': hoverable,\n 'is-disabled': disabled,\n });\n\n const buttonClass = usePrefixedClassNames('button');\n\n // Controlled mode support: mirror the controlled `active` prop into local\n // state. This is an intentional external-prop sync (controlled/uncontrolled\n // hybrid); behavior is covered by tests and certified in-browser.\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop\n if (typeof activeProp === 'boolean') setActive(activeProp);\n }, [activeProp]);\n\n // Read when a click lands outside, so the listener stays put while\n // `onActiveChange` changes identity, as an inline one does on every\n // render of the parent.\n const onActiveChangeRef = useLatestRef(onActiveChange);\n\n // SSR-safe outside click\n useEffect(() => {\n if (!active) return;\n\n if (!isBrowser(window, document)) return;\n\n const handleClick = (e: MouseEvent) => {\n if (!isEventInside(e, dropdownRef.current)) {\n setActive(false);\n onActiveChangeRef.current?.(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [active, onActiveChangeRef]);\n\n const handleToggle = () => {\n /* istanbul ignore next: guard is enforced by button[disabled] at the DOM level */\n if (disabled) return;\n\n const newActive = !active;\n setActive(newActive);\n onActiveChange?.(newActive);\n };\n\n const handleMenuClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnClick) {\n setActive(false);\n onActiveChange?.(false);\n // Closing hides the item that has focus, and the browser drops focus\n // to the page when that happens. Hand it back to the trigger, as\n // Escape does. An item that moved focus somewhere else keeps it there.\n // The menu around this content is what a click between items focuses.\n const menu = e.currentTarget.parentElement as HTMLElement;\n if (menu.contains(getActiveElementInTree(e.currentTarget))) {\n triggerRef.current?.focus();\n }\n }\n };\n\n const focusEdgeItem = (edge: 'first' | 'last') => {\n const items = enabledMenuItems(menuRef.current as HTMLElement);\n items[edge === 'first' ? 0 : items.length - 1]?.focus();\n };\n\n // Once the menu shows, forget a search typed just before it last closed,\n // and focus the pending item. The item is unfocusable while\n // `display: none` applies, so this must wait for the `is-active` class to\n // actually land in the DOM.\n useEffect(() => {\n if (!active) return;\n menuKeys.reset();\n if (!pendingFocusRef.current) return;\n focusEdgeItem(pendingFocusRef.current);\n pendingFocusRef.current = null;\n }, [active, menuKeys]);\n\n const handleTriggerKeyDown = (\n e: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (disabled) return;\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n pendingFocusRef.current = 'first';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n focusEdgeItem('first');\n pendingFocusRef.current = null;\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n pendingFocusRef.current = 'last';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n focusEdgeItem('last');\n pendingFocusRef.current = null;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n // A held key sends a keydown per auto-repeat. Running an item hands\n // focus back here, so without this a held Enter would reopen the\n // menu and run whichever item it focused next.\n if (e.repeat) break;\n if (!active) {\n pendingFocusRef.current = 'first';\n setActive(true);\n onActiveChange?.(true);\n } else {\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n case 'Escape':\n if (active) {\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n default:\n break;\n }\n };\n\n const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n // Closing is Dropdown's: Escape and Tab close the menu from anywhere in\n // it, a field included, and an empty or all-disabled menu too. Moving\n // between the items, running them and typeahead are the hook's, which\n // acts only while focus is on the menu or one of its items. An Escape\n // something in the menu already used, such as a field's own list\n // closing on it, leaves the menu open for the next one.\n if (e.key === 'Escape') {\n if (e.defaultPrevented) return;\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n triggerRef.current?.focus();\n return;\n }\n if (e.key === 'Tab') {\n setActive(false);\n onActiveChange?.(false);\n return;\n }\n\n menuKeys.onKeyDown(e);\n };\n\n const dropdownClasses = classNames(\n bulmaClasses,\n bulmaHelperClasses,\n className\n );\n\n return (\n <div\n className={dropdownClasses}\n ref={setRefs}\n id={id}\n data-testid=\"dropdown-root\"\n {...rest}\n >\n <div className={usePrefixedClassNames('dropdown-trigger')}>\n <button\n ref={triggerRef}\n className={buttonClass}\n aria-haspopup=\"true\"\n aria-controls={id ? `${id}-menu` : undefined}\n aria-expanded={active}\n onClick={handleToggle}\n onKeyDown={handleTriggerKeyDown}\n disabled={disabled}\n type=\"button\"\n >\n <span>{label}</span>\n <span\n className={usePrefixedClassNames('icon', 'is-small')}\n aria-hidden=\"true\"\n >\n <i className=\"fas fa-angle-down\" />\n </span>\n </button>\n </div>\n <div\n className={classNames(\n usePrefixedClassNames('dropdown-menu'),\n menuClassName\n )}\n id={id ? `${id}-menu` : undefined}\n ref={menuRef}\n role=\"menu\"\n data-testid=\"dropdown-menu\"\n onKeyDown={handleMenuKeyDown}\n // The menu, not its content, takes focus from a click between items,\n // so the menu owns nothing focusable but its items.\n tabIndex={-1}\n >\n <div\n className={usePrefixedClassNames('dropdown-content')}\n onClick={handleMenuClick}\n >\n {children}\n </div>\n </div>\n </div>\n );\n }\n);\n\n/**\n * The elements a dropdown item may render as. Bulma's dropdown markup names\n * these three and no others, so `as` is a closed set rather than an open\n * `React.ElementType`.\n */\nexport type DropdownItemElement = 'a' | 'div' | 'button';\n\n/**\n * The DropdownItem component's own props.\n */\nexport interface DropdownItemOwnProps extends BulmaClassesProps {\n /** Whether the item is active. */\n active?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Marks the item as disabled; disabled items are skipped during keyboard navigation. Use with `as=\"button\"` for a native disabled control, or pair with `aria-disabled` on a link. */\n disabled?: boolean;\n /** Item content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the DropdownItem component. Everything the item does not own\n * follows `as`: `href`, `target` and `rel` under the default `'a'`, `type` and\n * `form` under `'button'`, and the shared HTML attributes under any of them.\n *\n * Pinning these to `React.HTMLAttributes<HTMLElement>` instead — which is what\n * this type did before — rejected `href` on an anchor and `type` on a button,\n * both of which have always worked at runtime. Same defect as #641, in the\n * narrower shape a constrained `as` takes.\n *\n * **Name the tag you mean.** The type parameter defaults to the whole union, not\n * to the rendered element, so bare `DropdownItemProps` keeps accepting\n * `{ as: 'div' }` the way it always has. The cost is that it is not\n * distributive: `Omit` over a union keeps only the shared keys, so the bare\n * alias carries no `href` even though the component takes one under `as=\"a\"`.\n * Write `DropdownItemProps<'a'>` for the anchor's props. That is the #667 alias\n * limitation Button carries, labelled next-major because closing it is\n * source-breaking, and pinned for this component in\n * `__typetests__/polymorphic.tsx`; the component itself is unaffected.\n */\nexport type DropdownItemProps<\n T extends DropdownItemElement = DropdownItemElement,\n> = DropdownItemOwnProps &\n Omit<React.ComponentPropsWithoutRef<T>, keyof DropdownItemOwnProps | 'as'> & {\n /**\n * The element type to render.\n *\n * `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so\n * an item inside a form does not submit it.\n */\n as?: T;\n };\n\n/**\n * The anchor's attributes, minus the one a `<button>` legitimately takes.\n *\n * `type` stays: `as=\"button\"` is a supported form and `type=\"submit\"` is valid\n * there, so stripping it would remove a working attribute. A `<div>` takes no\n * `type`, so it gets the whole `ANCHOR_ONLY_ATTRS` set instead. The set is\n * chosen by the rendered tag because that is where the reason lives (#692).\n *\n * Neither set withholds `rel`, which `Level.Item` does: React declares `rel` on\n * `HTMLAttributes` for every element, so withholding it would diverge from\n * React's own typing, the call #641 recorded for `Navbar.Link`. Level\n * withholds it anyway, because it always has.\n */\nconst STRIP_FROM_BUTTON: Readonly<\n Record<Exclude<keyof AnchorOnlyAttributes, 'type'>, true>\n> = (() => {\n const { type: _type, ...rest } = ANCHOR_ONLY_ATTRS;\n return rest;\n})();\n\n/**\n * The shape the implementation destructures. The public contract is the generic\n * `DropdownItemProps<T>` above — the body cannot see through `T`.\n */\ntype DropdownItemImplProps = DropdownItemOwnProps & {\n as?: DropdownItemElement;\n};\n\n/**\n * Bulma Dropdown item.\n *\n * @function\n * @param {DropdownItemProps} props - Props for the DropdownItem component.\n * @returns {JSX.Element} The rendered dropdown item.\n */\nexport const DropdownItem = ((itemProps: DropdownItemProps) => {\n const {\n children,\n active,\n className,\n as: Component = 'a',\n ...props\n } = itemProps as DropdownItemImplProps;\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n // The anchor's attributes reach an anchor and nothing else — `<div href>` and\n // `<button target>` are invalid HTML. The same rule Menu applies, for the same\n // reason: the type now derives these from `as`, and deriving them must not\n // quietly widen where they land. The type stops a direct caller; this stops a\n // plain-JS one, a loose `{...props}` spread, and the genericity a wrapping HOC\n // erases.\n //\n // The whole link set, not `href` alone: they all arrive together under\n // `as=\"a\"`. Menu strips `href` only, because its `as` is open and a flat set\n // would delete attributes legal on the element a caller named.\n //\n // `bestax-migrate` tracks the same question from the other side, per attribute\n // per element (`LINK_ATTR_ELEMENTS`) rather than as one set — so the two lists\n // are not interchangeable and neither derives from the other.\n //\n // Menu's condition also admits a custom component and a custom element, which\n // own their prop contracts. Here the set follows the tag: an `<a>` keeps all\n // of them, a `<button>` keeps `type`, and any other `as` keeps none of them.\n const forwarded =\n Component === 'a'\n ? rest\n : Component === 'button'\n ? omitAttrs(rest, STRIP_FROM_BUTTON)\n : omitAttrs(rest, ANCHOR_ONLY_ATTRS);\n return (\n <Component\n className={classNames(\n usePrefixedClassNames('dropdown-item', {\n 'is-active': active,\n }),\n bulmaHelperClasses,\n className\n )}\n data-testid=\"dropdown-item\"\n {...forwarded}\n // After `forwarded` for the same reason as `role` and `type` below: a\n // spread carrying `tabIndex: undefined` would otherwise erase the\n // default. The item keeps its menu role and its place in the arrow-key\n // order, but a `<div>` or an anchor without an `href` cannot take focus\n // without a tabindex, so the arrow keys stall on it.\n tabIndex={(forwarded as { tabIndex?: number }).tabIndex ?? 0}\n // After `forwarded` for the same reason as `type` below: a spread\n // carrying `role: undefined` would otherwise erase the default, and an\n // item with no role drops out of the menu and its arrow-key order.\n role={(forwarded as { role?: React.AriaRole }).role ?? 'menuitem'}\n // A menu item inside a form must not submit it. `<button>` defaults to\n // type=\"submit\", and a filter or sort menu sitting in a form is ordinary.\n // Dropdown's own trigger sets it, and `Avatar` and `Menu.Item` default it\n // the same way. A caller's `submit` or `reset` still wins, and anything\n // else becomes `button`, since HTML reads a value it does not define for\n // a button as submit too; `buttonType` says more.\n //\n // After `forwarded`, reading through it rather than before it: React\n // treats `type={undefined}` as \"remove the attribute\", and a spread\n // carrying an absent key is how that arrives. Spreading the default first\n // let such a spread erase it and restore the submit behaviour, so the\n // guard only held for callers who passed nothing.\n {...(Component === 'button'\n ? { type: buttonType((forwarded as { type?: unknown }).type) }\n : {})}\n >\n {children}\n </Component>\n );\n}) as ConstrainedPolymorphicComponentWithoutRef<\n DropdownItemOwnProps,\n DropdownItemElement,\n 'a'\n>;\n\n/**\n * Bulma Dropdown divider.\n *\n * @function\n * @returns {JSX.Element} The rendered divider element.\n */\nexport const DropdownDivider: React.FC = () => (\n <hr className={usePrefixedClassNames('dropdown-divider')} />\n);\n\n/** Bulma Dropdown component with Item and Divider sub-components. */\nexport const Dropdown = withSubComponents(\n DropdownComponent,\n {\n Item: DropdownItem,\n Divider: DropdownDivider,\n },\n 'Dropdown'\n);\n\nexport default Dropdown;\n"],"names":["isBrowser","_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Dropdown.js","sources":["../../../src/components/Dropdown.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useState,\n useRef,\n useEffect,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { getActiveElementInTree, isEventInside } from '../helpers/shadowDom';\nimport type { ConstrainedPolymorphicComponentWithoutRef } from '../helpers/polymorphic';\nimport {\n type AnchorOnlyAttributes,\n ANCHOR_ONLY_ATTRS,\n omitAttrs,\n} from '../helpers/anchorAttrs';\nimport { buttonType } from '../helpers/buttonType';\nimport { enabledMenuItems, useMenuKeys } from '../helpers/useMenuKeys';\nimport { useLatestRef } from '../helpers/useLatestRef';\n\n/**\n * Checks if code is running in a browser environment.\n * @deprecated Dropdown's internal SSR guard, exported by accident; it will\n * be removed in the next major. Check `typeof window !== 'undefined' &&\n * typeof document !== 'undefined'` instead.\n * @param win - Window object.\n * @param doc - Document object.\n * @returns {boolean} True if in browser, false otherwise.\n */\nexport const isBrowser = (win?: typeof window, doc?: typeof document) =>\n typeof win !== 'undefined' && typeof doc !== 'undefined';\n\n/**\n * Props for the Dropdown component.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root dropdown element.\n */\nexport interface DropdownProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** The dropdown button/trigger content. */\n label: React.ReactNode;\n /** Dropdown menu items and dividers. */\n children: React.ReactNode;\n /** Additional CSS classes for root. */\n className?: string;\n /** Additional CSS classes for the dropdown menu. */\n menuClassName?: string;\n /** Whether the dropdown is open (controlled). */\n active?: boolean;\n /** Dropdown menu opens upward. */\n up?: boolean;\n /** Menu is right-aligned. */\n right?: boolean;\n /** Open on hover instead of click. */\n hoverable?: boolean;\n /** Disables the dropdown trigger. */\n disabled?: boolean;\n /** Callback when dropdown active state changes. */\n onActiveChange?: (active: boolean) => void;\n /** Close dropdown when a menu item is clicked, or activated with Enter or Space. */\n closeOnClick?: boolean;\n /** Root element ID (for aria-controls, etc). */\n id?: string;\n}\n\n/**\n * The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.\n *\n * Down, Enter and Space on the trigger open the menu on its first enabled\n * item, and Up opens it on its last. On the trigger of a menu that's already\n * open, Down and Up move focus to its first and last item. In the menu, the\n * arrow keys, Home and End move between the items, and Enter and Space run\n * the focused one the way a click does. Typing a letter moves to the next\n * item whose text starts with it, skipping disabled ones, and letters typed\n * in quick succession add up to one search. Typing searches once focus is in\n * the menu, so a letter typed on the trigger does nothing. Escape closes the\n * menu and focuses the trigger, and Tab closes it and lets focus move on.\n * Anything focusable in the menu that isn't an item, such as a field, keeps\n * its own keys apart from Escape and Tab, though an Escape it calls\n * `preventDefault()` on in its own `onKeyDown` stays its own and leaves the\n * menu open. For a panel built around fields, use `Popover`.\n *\n * @function\n * @param {DropdownProps} props - Props for the Dropdown component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root dropdown element.\n * @returns {JSX.Element} The rendered dropdown.\n * @see {@link https://bulma.io/documentation/components/dropdown/ | Bulma Dropdown documentation}\n */\nconst DropdownComponent = forwardRef<HTMLDivElement, DropdownProps>(\n function DropdownComponent(\n {\n label,\n children,\n className,\n menuClassName,\n active: activeProp,\n up,\n right,\n hoverable,\n disabled,\n onActiveChange,\n closeOnClick = true,\n id,\n ...props\n },\n ref\n ) {\n const [active, setActive] = useState<boolean>(!!activeProp);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const menuKeys = useMenuKeys();\n const pendingFocusRef = useRef<'first' | 'last' | 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\n const setRefs = useCallback(\n (node: HTMLDivElement | null) => {\n (dropdownRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches\n // by running it instead of calling the ref with `null`; React 18\n // discards the return value entirely. Returning it from here would be\n // a React-19-only contract, so instead we hold the cleanup and run it\n // ourselves on detach — a consumer's cleanup ref then behaves the same\n // on both majors of the CI matrix.\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 const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('dropdown', {\n 'is-active': active,\n 'is-up': up,\n 'is-right': right,\n 'is-hoverable': hoverable,\n 'is-disabled': disabled,\n });\n\n const buttonClass = usePrefixedClassNames('button');\n\n // Controlled mode support: mirror the controlled `active` prop into local\n // state. This is an intentional external-prop sync (controlled/uncontrolled\n // hybrid); behavior is covered by tests and certified in-browser.\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop\n if (typeof activeProp === 'boolean') setActive(activeProp);\n }, [activeProp]);\n\n // Read when a click lands outside, so the listener stays put while\n // `onActiveChange` changes identity, as an inline one does on every\n // render of the parent.\n const onActiveChangeRef = useLatestRef(onActiveChange);\n\n // SSR-safe outside click\n useEffect(() => {\n if (!active) return;\n\n // Reading `window` or `document` bare throws where neither exists, so\n // the check is `typeof`, as `isBrowser`'s own note recommends.\n /* istanbul ignore next: React DOM runs effects only in a browser */\n if (typeof document === 'undefined') return;\n\n const handleClick = (e: MouseEvent) => {\n if (!isEventInside(e, dropdownRef.current)) {\n setActive(false);\n onActiveChangeRef.current?.(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [active, onActiveChangeRef]);\n\n const handleToggle = () => {\n /* istanbul ignore next: guard is enforced by button[disabled] at the DOM level */\n if (disabled) return;\n\n const newActive = !active;\n setActive(newActive);\n onActiveChange?.(newActive);\n };\n\n const handleMenuClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnClick) {\n setActive(false);\n onActiveChange?.(false);\n // Closing hides the item that has focus, and the browser drops focus\n // to the page when that happens. Hand it back to the trigger, as\n // Escape does. An item that moved focus somewhere else keeps it there.\n // The menu around this content is what a click between items focuses.\n const menu = e.currentTarget.parentElement as HTMLElement;\n if (menu.contains(getActiveElementInTree(e.currentTarget))) {\n triggerRef.current?.focus();\n }\n }\n };\n\n const focusEdgeItem = (edge: 'first' | 'last') => {\n const items = enabledMenuItems(menuRef.current as HTMLElement);\n items[edge === 'first' ? 0 : items.length - 1]?.focus();\n };\n\n // Once the menu shows, forget a search typed just before it last closed,\n // and focus the pending item. The item is unfocusable while\n // `display: none` applies, so this must wait for the `is-active` class to\n // actually land in the DOM.\n useEffect(() => {\n if (!active) return;\n menuKeys.reset();\n if (!pendingFocusRef.current) return;\n focusEdgeItem(pendingFocusRef.current);\n pendingFocusRef.current = null;\n }, [active, menuKeys]);\n\n const handleTriggerKeyDown = (\n e: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (disabled) return;\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n pendingFocusRef.current = 'first';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n focusEdgeItem('first');\n pendingFocusRef.current = null;\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n pendingFocusRef.current = 'last';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n focusEdgeItem('last');\n pendingFocusRef.current = null;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n // A held key sends a keydown per auto-repeat. Running an item hands\n // focus back here, so without this a held Enter would reopen the\n // menu and run whichever item it focused next.\n if (e.repeat) break;\n if (!active) {\n pendingFocusRef.current = 'first';\n setActive(true);\n onActiveChange?.(true);\n } else {\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n case 'Escape':\n if (active) {\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n default:\n break;\n }\n };\n\n const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n // Closing is Dropdown's: Escape and Tab close the menu from anywhere in\n // it, a field included, and an empty or all-disabled menu too. Moving\n // between the items, running them and typeahead are the hook's, which\n // acts only while focus is on the menu or one of its items. An Escape\n // something in the menu already used, such as a field's own list\n // closing on it, leaves the menu open for the next one.\n if (e.key === 'Escape') {\n if (e.defaultPrevented) return;\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n triggerRef.current?.focus();\n return;\n }\n if (e.key === 'Tab') {\n setActive(false);\n onActiveChange?.(false);\n return;\n }\n\n menuKeys.onKeyDown(e);\n };\n\n const dropdownClasses = classNames(\n bulmaClasses,\n bulmaHelperClasses,\n className\n );\n\n return (\n <div\n className={dropdownClasses}\n ref={setRefs}\n id={id}\n data-testid=\"dropdown-root\"\n {...rest}\n >\n <div className={usePrefixedClassNames('dropdown-trigger')}>\n <button\n ref={triggerRef}\n className={buttonClass}\n aria-haspopup=\"true\"\n aria-controls={id ? `${id}-menu` : undefined}\n aria-expanded={active}\n onClick={handleToggle}\n onKeyDown={handleTriggerKeyDown}\n disabled={disabled}\n type=\"button\"\n >\n <span>{label}</span>\n <span\n className={usePrefixedClassNames('icon', 'is-small')}\n aria-hidden=\"true\"\n >\n <i className=\"fas fa-angle-down\" />\n </span>\n </button>\n </div>\n <div\n className={classNames(\n usePrefixedClassNames('dropdown-menu'),\n menuClassName\n )}\n id={id ? `${id}-menu` : undefined}\n ref={menuRef}\n role=\"menu\"\n data-testid=\"dropdown-menu\"\n onKeyDown={handleMenuKeyDown}\n // The menu, not its content, takes focus from a click between items,\n // so the menu owns nothing focusable but its items.\n tabIndex={-1}\n >\n <div\n className={usePrefixedClassNames('dropdown-content')}\n onClick={handleMenuClick}\n >\n {children}\n </div>\n </div>\n </div>\n );\n }\n);\n\n/**\n * The elements a dropdown item may render as. Bulma's dropdown markup names\n * these three and no others, so `as` is a closed set rather than an open\n * `React.ElementType`.\n */\nexport type DropdownItemElement = 'a' | 'div' | 'button';\n\n/**\n * The DropdownItem component's own props.\n */\nexport interface DropdownItemOwnProps extends BulmaClassesProps {\n /** Whether the item is active. */\n active?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Marks the item as disabled; disabled items are skipped during keyboard navigation. Use with `as=\"button\"` for a native disabled control, or pair with `aria-disabled` on a link. */\n disabled?: boolean;\n /** Item content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the DropdownItem component. Everything the item does not own\n * follows `as`: `href`, `target` and `rel` under the default `'a'`, `type` and\n * `form` under `'button'`, and the shared HTML attributes under any of them.\n *\n * Pinning these to `React.HTMLAttributes<HTMLElement>` instead — which is what\n * this type did before — rejected `href` on an anchor and `type` on a button,\n * both of which have always worked at runtime. Same defect as #641, in the\n * narrower shape a constrained `as` takes.\n *\n * **Name the tag you mean.** The type parameter defaults to the whole union, not\n * to the rendered element, so bare `DropdownItemProps` keeps accepting\n * `{ as: 'div' }` the way it always has. The cost is that it is not\n * distributive: `Omit` over a union keeps only the shared keys, so the bare\n * alias carries no `href` even though the component takes one under `as=\"a\"`.\n * Write `DropdownItemProps<'a'>` for the anchor's props. That is the #667 alias\n * limitation Button carries, labelled next-major because closing it is\n * source-breaking, and pinned for this component in\n * `__typetests__/polymorphic.tsx`; the component itself is unaffected.\n */\nexport type DropdownItemProps<\n T extends DropdownItemElement = DropdownItemElement,\n> = DropdownItemOwnProps &\n Omit<React.ComponentPropsWithoutRef<T>, keyof DropdownItemOwnProps | 'as'> & {\n /**\n * The element type to render.\n *\n * `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so\n * an item inside a form does not submit it.\n */\n as?: T;\n };\n\n/**\n * The anchor's attributes, minus the one a `<button>` legitimately takes.\n *\n * `type` stays: `as=\"button\"` is a supported form and `type=\"submit\"` is valid\n * there, so stripping it would remove a working attribute. A `<div>` takes no\n * `type`, so it gets the whole `ANCHOR_ONLY_ATTRS` set instead. The set is\n * chosen by the rendered tag because that is where the reason lives (#692).\n *\n * Neither set withholds `rel`, which `Level.Item` does: React declares `rel` on\n * `HTMLAttributes` for every element, so withholding it would diverge from\n * React's own typing, the call #641 recorded for `Navbar.Link`. Level\n * withholds it anyway, because it always has.\n */\nconst STRIP_FROM_BUTTON: Readonly<\n Record<Exclude<keyof AnchorOnlyAttributes, 'type'>, true>\n> = (() => {\n const { type: _type, ...rest } = ANCHOR_ONLY_ATTRS;\n return rest;\n})();\n\n/**\n * The shape the implementation destructures. The public contract is the generic\n * `DropdownItemProps<T>` above — the body cannot see through `T`.\n */\ntype DropdownItemImplProps = DropdownItemOwnProps & {\n as?: DropdownItemElement;\n};\n\n/**\n * Bulma Dropdown item.\n *\n * @function\n * @param {DropdownItemProps} props - Props for the DropdownItem component.\n * @returns {JSX.Element} The rendered dropdown item.\n */\nexport const DropdownItem = ((itemProps: DropdownItemProps) => {\n const {\n children,\n active,\n className,\n as: Component = 'a',\n ...props\n } = itemProps as DropdownItemImplProps;\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n // The anchor's attributes reach an anchor and nothing else — `<div href>` and\n // `<button target>` are invalid HTML. The same rule Menu applies, for the same\n // reason: the type now derives these from `as`, and deriving them must not\n // quietly widen where they land. The type stops a direct caller; this stops a\n // plain-JS one, a loose `{...props}` spread, and the genericity a wrapping HOC\n // erases.\n //\n // The whole link set, not `href` alone: they all arrive together under\n // `as=\"a\"`. Menu strips `href` only, because its `as` is open and a flat set\n // would delete attributes legal on the element a caller named.\n //\n // `bestax-migrate` tracks the same question from the other side, per attribute\n // per element (`LINK_ATTR_ELEMENTS`) rather than as one set — so the two lists\n // are not interchangeable and neither derives from the other.\n //\n // Menu's condition also admits a custom component and a custom element, which\n // own their prop contracts. Here the set follows the tag: an `<a>` keeps all\n // of them, a `<button>` keeps `type`, and any other `as` keeps none of them.\n const forwarded =\n Component === 'a'\n ? rest\n : Component === 'button'\n ? omitAttrs(rest, STRIP_FROM_BUTTON)\n : omitAttrs(rest, ANCHOR_ONLY_ATTRS);\n return (\n <Component\n className={classNames(\n usePrefixedClassNames('dropdown-item', {\n 'is-active': active,\n }),\n bulmaHelperClasses,\n className\n )}\n data-testid=\"dropdown-item\"\n {...forwarded}\n // After `forwarded` for the same reason as `role` and `type` below: a\n // spread carrying `tabIndex: undefined` would otherwise erase the\n // default. The item keeps its menu role and its place in the arrow-key\n // order, but a `<div>` or an anchor without an `href` cannot take focus\n // without a tabindex, so the arrow keys stall on it.\n tabIndex={(forwarded as { tabIndex?: number }).tabIndex ?? 0}\n // After `forwarded` for the same reason as `type` below: a spread\n // carrying `role: undefined` would otherwise erase the default, and an\n // item with no role drops out of the menu and its arrow-key order.\n role={(forwarded as { role?: React.AriaRole }).role ?? 'menuitem'}\n // A menu item inside a form must not submit it. `<button>` defaults to\n // type=\"submit\", and a filter or sort menu sitting in a form is ordinary.\n // Dropdown's own trigger sets it, and `Avatar` and `Menu.Item` default it\n // the same way. A caller's `submit` or `reset` still wins, and anything\n // else becomes `button`, since HTML reads a value it does not define for\n // a button as submit too; `buttonType` says more.\n //\n // After `forwarded`, reading through it rather than before it: React\n // treats `type={undefined}` as \"remove the attribute\", and a spread\n // carrying an absent key is how that arrives. Spreading the default first\n // let such a spread erase it and restore the submit behaviour, so the\n // guard only held for callers who passed nothing.\n {...(Component === 'button'\n ? { type: buttonType((forwarded as { type?: unknown }).type) }\n : {})}\n >\n {children}\n </Component>\n );\n}) as ConstrainedPolymorphicComponentWithoutRef<\n DropdownItemOwnProps,\n DropdownItemElement,\n 'a'\n>;\n\n/**\n * Bulma Dropdown divider.\n *\n * @function\n * @returns {JSX.Element} The rendered divider element.\n */\nexport const DropdownDivider: React.FC = () => (\n <hr className={usePrefixedClassNames('dropdown-divider')} />\n);\n\n/** Bulma Dropdown component with Item and Divider sub-components. */\nexport const Dropdown = withSubComponents(\n DropdownComponent,\n {\n Item: DropdownItem,\n Divider: DropdownDivider,\n },\n 'Dropdown'\n);\n\nexport default Dropdown;\n"],"names":["isBrowser","_jsxs","_jsx"],"mappings":"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"}
@@ -4,7 +4,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { forwardRef, useState, useRef, useCallback, useEffect, useSyncExternalStore } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
  import { isEventInside } from '../helpers/shadowDom.js';
7
- import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
7
+ import { usePrefixedClassNames, classNames, prefixedClassNames } from '../helpers/classNames.js';
8
+ import { useClassPrefix } from '../helpers/Config.js';
8
9
  import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
9
10
  import { usePortalContainer } from '../helpers/portal.js';
10
11
  import { LocalePortalScope } from '../helpers/LocaleProvider.js';
@@ -315,7 +316,10 @@ const toastStackOrder = [
315
316
  * Container component for rendering programmatic toasts.
316
317
  * Place once at your app root to enable the toast API. A toast shown with a
317
318
  * `position` appears there, and one shown without goes to the container's
318
- * `position`.
319
+ * `position`. The toasts at one position stack in one `.toast-container`,
320
+ * with a gap between them, in the order they were shown, growing away from
321
+ * the edge of the screen. A toast shown with a `container` of its own, and
322
+ * not `inline`, portals there instead, in a box of its own.
319
323
  *
320
324
  * @function
321
325
  * @param {{ position?: ToastPosition }} props - Container props.
@@ -326,15 +330,25 @@ const ToastContainer = ({ position = 'top-right' }) => {
326
330
  // follows changes.
327
331
  const toastList = useSyncExternalStore(toast.subscribe, getVisibleToasts, getServerToasts);
328
332
  const resolveContainer = usePortalContainer();
333
+ const classPrefix = useClassPrefix();
329
334
  if (typeof document === 'undefined' || toastList.length === 0) {
330
335
  return null;
331
336
  }
332
- const stacks = groupIntoPositionStacks(toastList, t => t.props.position, position, toastStackOrder);
337
+ // A toast shown with a `container` of its own, and not `inline`, portals
338
+ // there in a box of its own. Every other toast renders inline in the stack
339
+ // for its position, so the toasts at one position stack instead of each
340
+ // sitting in a box of its own on top of the others. An empty `container`
341
+ // falls back to the page, as it does on a Toast, so it means none here.
342
+ const ownsContainer = (t) => !!t.props.container && !t.props.inline;
343
+ const renderToast = (t, at, inline) => {
344
+ const { queue: _queue, ...toastProps } = t.props;
345
+ return (jsx(Toast, { ...toastProps, position: at, inline: inline, onClose: () => toast.close(t.id) }, t.id));
346
+ };
347
+ const stacks = groupIntoPositionStacks(toastList.filter(t => !ownsContainer(t)), t => t.props.position, position, toastStackOrder);
333
348
  const target = resolveContainer();
334
- return createPortal(jsx(LocalePortalScope, { target: target, children: stacks.map(stack => (jsx("div", { className: `toast-container is-${stack.position}`, children: stack.items.map(t => {
335
- const { queue: _queue, ...toastProps } = t.props;
336
- return (jsx(Toast, { ...toastProps, position: stack.position, onClose: () => toast.close(t.id) }, t.id));
337
- }) }, stack.key))) }), target);
349
+ return createPortal(jsxs(LocalePortalScope, { target: target, children: [stacks.map(stack => (jsx("div", { className: prefixedClassNames(classPrefix, 'toast-container', `is-${stack.position}`), children: stack.items.map(t => renderToast(t, stack.position, true)) }, stack.key))), toastList
350
+ .filter(ownsContainer)
351
+ .map(t => renderToast(t, t.props.position ?? position, false))] }), target);
338
352
  };
339
353
 
340
354
  export { Toast, ToastContainer, toast };
@@ -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 { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\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. While a Modal, Dialog,\n * Sidebar or full-page Loading is open, Escape goes to that overlay and the\n * toast stays up, so Escape dismisses the toast once none is open. An\n * Escape a popup on the page closed on, by calling `preventDefault()`,\n * leaves it up too. 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 // Read when the timer runs out, a click lands outside or Escape arrives,\n // so the timer and the listeners stay put while `onClose` changes\n // identity, as an inline one does on every render of the parent. An\n // inline one from `ToastContainer` changes whenever another toast shows.\n const handleCloseRef = useLatestRef(handleClose);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleCloseRef.current();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleCloseRef]);\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 handleCloseRef.current();\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, handleCloseRef]);\n\n // A toast is a notification rather than a layer, so it never joins the\n // stack of open overlays. Asking the stack tells it whether one is open:\n // an Escape while one is belongs to the overlay, and the toast waits.\n const isTopmost = useOverlayStack(false);\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 && isTopmost()) {\n handleCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, isVisible, handleCloseRef, isTopmost]);\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 const target = resolveContainer(container);\n return createPortal(\n <LocalePortalScope target={target}>{toastContent}</LocalePortalScope>,\n target\n );\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 const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>\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 </LocalePortalScope>,\n target\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 {\n classNames,\n prefixedClassNames,\n usePrefixedClassNames,\n} from '../helpers/classNames';\nimport { useClassPrefix } from '../helpers/Config';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { usePortalContainer } from '../helpers/portal';\nimport { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { groupIntoPositionStacks } from '../helpers/positionStacks';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\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. While a Modal, Dialog,\n * Sidebar or full-page Loading is open, Escape goes to that overlay and the\n * toast stays up, so Escape dismisses the toast once none is open. An\n * Escape a popup on the page closed on, by calling `preventDefault()`,\n * leaves it up too. 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 /**\n * CSS selector or DOM node to mount the toast into. Through `toast.show()`,\n * a toast with one portals there in a box of its own, rather than joining\n * `ToastContainer`'s stack for its position.\n */\n container?: string | HTMLElement;\n /**\n * Renders inline instead of using a portal. Through `toast.show()`, a toast\n * already renders inline in `ToastContainer`'s stack for its position, and\n * `inline` keeps one with a `container` in that stack too.\n */\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 // Read when the timer runs out, a click lands outside or Escape arrives,\n // so the timer and the listeners stay put while `onClose` changes\n // identity, as an inline one does on every render of the parent. An\n // inline one from `ToastContainer` changes whenever another toast shows.\n const handleCloseRef = useLatestRef(handleClose);\n\n useEffect(() => {\n if (indefinite || duration === 0 || isPaused) return undefined;\n\n const timer = setTimeout(() => {\n handleCloseRef.current();\n }, duration);\n\n return () => clearTimeout(timer);\n }, [duration, indefinite, isPaused, handleCloseRef]);\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 handleCloseRef.current();\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, handleCloseRef]);\n\n // A toast is a notification rather than a layer, so it never joins the\n // stack of open overlays. Asking the stack tells it whether one is open:\n // an Escape while one is belongs to the overlay, and the toast waits.\n const isTopmost = useOverlayStack(false);\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 && isTopmost()) {\n handleCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [cancelable, isVisible, handleCloseRef, isTopmost]);\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 const target = resolveContainer(container);\n return createPortal(\n <LocalePortalScope target={target}>{toastContent}</LocalePortalScope>,\n target\n );\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`. The toasts at one position stack in one `.toast-container`,\n * with a gap between them, in the order they were shown, growing away from\n * the edge of the screen. A toast shown with a `container` of its own, and\n * not `inline`, portals there instead, in a box of its own.\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 const classPrefix = useClassPrefix();\n\n if (typeof document === 'undefined' || toastList.length === 0) {\n return null;\n }\n\n // A toast shown with a `container` of its own, and not `inline`, portals\n // there in a box of its own. Every other toast renders inline in the stack\n // for its position, so the toasts at one position stack instead of each\n // sitting in a box of its own on top of the others. An empty `container`\n // falls back to the page, as it does on a Toast, so it means none here.\n const ownsContainer = (t: ToastInstance) =>\n !!t.props.container && !t.props.inline;\n const renderToast = (\n t: ToastInstance,\n at: ToastPosition,\n inline: boolean\n ) => {\n const { queue: _queue, ...toastProps } = t.props;\n return (\n <Toast\n key={t.id}\n {...toastProps}\n position={at}\n inline={inline}\n onClose={() => toast.close(t.id)}\n />\n );\n };\n\n const stacks = groupIntoPositionStacks(\n toastList.filter(t => !ownsContainer(t)),\n t => t.props.position,\n position,\n toastStackOrder\n );\n\n const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>\n {stacks.map(stack => (\n <div\n key={stack.key}\n className={prefixedClassNames(\n classPrefix,\n 'toast-container',\n `is-${stack.position}`\n )}\n >\n {stack.items.map(t => renderToast(t, stack.position, true))}\n </div>\n ))}\n {toastList\n .filter(ownsContainer)\n .map(t => renderToast(t, t.props.position ?? position, false))}\n </LocalePortalScope>,\n target\n );\n};\n\nexport default Toast;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tr.js","sources":["../../../src/elements/Tr.tsx"],"sourcesContent":["/**\n * @group Table\n */\nimport React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { TableColor, validTableColors } from './Td'; // Import TableColor from Td\n\n/**\n * Props for the Tr component.\n */\nexport interface TrProps\n extends\n Omit<React.HTMLAttributes<HTMLTableRowElement>, 'color'>,\n Omit<BulmaClassesProps, 'backgroundColor' | 'color'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * Whether the row is selected (adds Bulma's is-selected class). It's a look\n * only: it says nothing to assistive tech, so pair it with a checkbox named\n * for the row when the selection matters. A bestax `Checkbox` placed\n * straight in one of the row's cells takes the row's text color, so a\n * checked box shows on the row's fill. One in a menu or a table nested in a\n * cell, or in a cell with a `color` of its own, keeps its own colors, since\n * it sits on that surface instead, and so does every one in a row with a\n * `color`, whose cells paint that color over the fill.\n */\n isSelected?: boolean;\n /** Bulma color modifier for the table row. */\n color?: TableColor;\n /** Table row content (cells). */\n children?: React.ReactNode;\n}\n\n/**\n * Tr component for rendering a styled Bulma table row.\n *\n * Supports the is-selected modifier and color modifiers.\n *\n * @function\n * @param {TrProps} props - Props for the Tr component.\n * @returns {JSX.Element} The rendered table row element.\n * @see {@link https://bulma.io/documentation/elements/table/#table-row | Bulma Table documentation}\n */\nexport const Tr: React.FC<TrProps> = ({\n className,\n isSelected,\n color,\n children,\n ...props\n}) => {\n const bulmaClasses = usePrefixedClassNames('', {\n 'is-selected': isSelected,\n [`is-${color}`]: color && validTableColors.includes(color),\n });\n\n /**\n * Generates Bulma helper classes and separates out remaining props.\n */\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n const trClasses = classNames(bulmaClasses, className, bulmaHelperClasses);\n\n return (\n <tr className={trClasses || undefined} {...rest}>\n {children}\n </tr>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;;;AAkCA;;;;;;;;;AASG;AACI,MAAM,EAAE,GAAsB,CAAC,EACpC,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,YAAY,GAAG,qBAAqB,CAAC,EAAE,EAAE;AAC7C,QAAA,aAAa,EAAE,UAAU;AACzB,QAAA,CAAC,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,KAAK,IAAI,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC3D,KAAA,CAAC;AAEF;;AAEG;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;IAElE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,SAAS,EAAE,kBAAkB,CAAC;AAEzE,IAAA,QACEA,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAE,SAAS,IAAI,SAAS,EAAA,GAAM,IAAI,EAAA,QAAA,EAC5C,QAAQ,EAAA,CACN;AAET;;"}
1
+ {"version":3,"file":"Tr.js","sources":["../../../src/elements/Tr.tsx"],"sourcesContent":["/**\n * @group Table\n */\nimport React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { TableColor, validTableColors } from './Td'; // Import TableColor from Td\n\n/**\n * Props for the Tr component.\n */\nexport interface TrProps\n extends\n Omit<React.HTMLAttributes<HTMLTableRowElement>, 'color'>,\n Omit<BulmaClassesProps, 'backgroundColor' | 'color'> {\n /** Additional CSS classes to apply. */\n className?: string;\n /**\n * Whether the row is selected (adds Bulma's is-selected class). It's a look\n * only: it says nothing to assistive tech, so pair it with a checkbox named\n * for the row when the selection matters. A bestax `Checkbox` or `Radio`\n * placed straight in one of the row's cells takes the row's text color, so\n * a checked one shows on the row's fill. One in a menu or a table nested in a\n * cell, or in a cell with a `color` of its own, keeps its own colors, since\n * it sits on that surface instead, and so does every one in a row with a\n * `color`, whose cells paint that color over the fill.\n */\n isSelected?: boolean;\n /** Bulma color modifier for the table row. */\n color?: TableColor;\n /** Table row content (cells). */\n children?: React.ReactNode;\n}\n\n/**\n * Tr component for rendering a styled Bulma table row.\n *\n * Supports the is-selected modifier and color modifiers.\n *\n * @function\n * @param {TrProps} props - Props for the Tr component.\n * @returns {JSX.Element} The rendered table row element.\n * @see {@link https://bulma.io/documentation/elements/table/#table-row | Bulma Table documentation}\n */\nexport const Tr: React.FC<TrProps> = ({\n className,\n isSelected,\n color,\n children,\n ...props\n}) => {\n const bulmaClasses = usePrefixedClassNames('', {\n 'is-selected': isSelected,\n [`is-${color}`]: color && validTableColors.includes(color),\n });\n\n /**\n * Generates Bulma helper classes and separates out remaining props.\n */\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n const trClasses = classNames(bulmaClasses, className, bulmaHelperClasses);\n\n return (\n <tr className={trClasses || undefined} {...rest}>\n {children}\n </tr>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;;;AAkCA;;;;;;;;;AASG;AACI,MAAM,EAAE,GAAsB,CAAC,EACpC,SAAS,EACT,UAAU,EACV,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,YAAY,GAAG,qBAAqB,CAAC,EAAE,EAAE;AAC7C,QAAA,aAAa,EAAE,UAAU;AACzB,QAAA,CAAC,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,KAAK,IAAI,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC3D,KAAA,CAAC;AAEF;;AAEG;AACH,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;IAElE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,SAAS,EAAE,kBAAkB,CAAC;AAEzE,IAAA,QACEA,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAE,SAAS,IAAI,SAAS,EAAA,GAAM,IAAI,EAAA,QAAA,EAC5C,QAAQ,EAAA,CACN;AAET;;"}
@@ -5,7 +5,7 @@ import { forwardRef, useRef, useCallback } from 'react';
5
5
  import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
6
6
  import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
7
7
  import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
8
- import { useFieldsetDisabled, useCheckboxesGroup } from './FormContext.js';
8
+ import { useFieldsetDisabled, useCheckboxesGroup, useRegisterChecked } from './FormContext.js';
9
9
 
10
10
  /**
11
11
  * The values the Checkbox `color` prop accepts, as a readonly tuple.
@@ -102,15 +102,22 @@ const Checkbox = forwardRef(({ color, size, className, children, textColor, disa
102
102
  // Local props always win over the group (explicit > implicit).
103
103
  const group = useCheckboxesGroup();
104
104
  const effectiveName = name ?? group?.name;
105
- // Group-managed checked state — only when the group is in
106
- // controlled/uncontrolled mode (group.value is defined) AND this Checkbox
107
- // has a value to compare against. Local `checked` always wins.
108
- const groupManaged = group?.value !== undefined && value !== undefined;
109
- const groupHas = groupManaged && group.value.includes(String(value));
105
+ // Group-managed checked state — only when the group manages the selection
106
+ // (it was given `value`, `defaultValue` or `onChange`) AND this Checkbox
107
+ // has a value to compare against. Local `checked` always wins. A group
108
+ // given only `onChange` holds no value until its first change, and until
109
+ // then the box shows its own `defaultChecked`, controlled all the same,
110
+ // so that change doesn't flip it from uncontrolled to controlled.
111
+ const valueKey = value === undefined ? undefined : String(value);
112
+ const groupManaged = group?.onChange !== undefined && valueKey !== undefined;
113
+ const groupHas = groupManaged &&
114
+ (group.value ? group.value.includes(valueKey) : !!defaultChecked);
110
115
  const effectiveChecked = checked !== undefined ? checked : groupManaged ? groupHas : undefined;
111
116
  // When the group manages checked, suppress local defaultChecked to avoid
112
117
  // the controlled/uncontrolled React warning.
113
118
  const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;
119
+ // What the box starts as, so the group's first change starts from it.
120
+ useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));
114
121
  const handleChange = useCallback((e) => {
115
122
  // The click that got here cleared the mixed state. Put it back now,
116
123
  // since a click that changes no state renders nothing to do it.
@@ -119,18 +126,18 @@ const Checkbox = forwardRef(({ color, size, className, children, textColor, disa
119
126
  // Local onChange always fires.
120
127
  onChange?.(e);
121
128
  // Dispatch to the group additionally — toggle this value's
122
- // membership in the group's array.
123
- if (group?.onChange && value !== undefined) {
124
- const valStr = String(value);
125
- const currentArr = group.value ?? [];
129
+ // membership in the group's array, or in what was checked when the
130
+ // group holds no value yet.
131
+ if (group?.onChange && valueKey !== undefined) {
132
+ const currentArr = group.value ?? group.startingValue();
126
133
  const next = e.target.checked
127
- ? currentArr.includes(valStr)
134
+ ? currentArr.includes(valueKey)
128
135
  ? currentArr
129
- : [...currentArr, valStr]
130
- : currentArr.filter(v => v !== valStr);
136
+ : [...currentArr, valueKey]
137
+ : currentArr.filter(v => v !== valueKey);
131
138
  group.onChange(next);
132
139
  }
133
- }, [onChange, group, value, indeterminate]);
140
+ }, [onChange, group, valueKey, indeterminate]);
134
141
  const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {
135
142
  [`is-${color}`]: color && checkboxColors.includes(color),
136
143
  [`is-${size}`]: size && checkboxSizes.includes(size),
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","sources":["../../../src/form/Checkbox.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { useCheckboxesGroup, useFieldsetDisabled } from './FormContext';\n\n/**\n * The values the Checkbox `color` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['color']` is typed from it, so the two list the same values.\n * Map over it to build a color picker, or check a value that arrives at\n * runtime before passing it in: the component adds no color class for a value\n * outside the tuple.\n *\n * @example\n * import { Checkbox, checkboxColors } from '@allxsmith/bestax-bulma';\n *\n * checkboxColors.map(color => (\n * <Checkbox key={color} color={color}>\n * {color}\n * </Checkbox>\n * ));\n */\nexport const checkboxColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * The values the Checkbox `size` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['size']` is typed from it, so the two list the same values.\n * Use it to offer a size choice or to check a value that arrives at runtime:\n * the component adds no size class for a value outside the tuple. These are\n * element sizes, not the spacing scale in `validSizes`.\n *\n * @example\n * import { checkboxSizes } from '@allxsmith/bestax-bulma';\n *\n * type CheckboxSize = (typeof checkboxSizes)[number];\n */\nexport const checkboxSizes = ['small', 'normal', 'medium', 'large'] as const;\n\n/**\n * Props for the Checkbox component.\n *\n * @helperProps Helper props go on the outer `<label>`, with `className`. The\n * other attributes go on the `<input>`.\n */\nexport interface CheckboxProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Color of the checkbox. */\n color?: (typeof checkboxColors)[number];\n /** Size of the checkbox. */\n size?: (typeof checkboxSizes)[number];\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the checkbox is disabled. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" box when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed box renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`. That's the element that\n * declares the `--bulma-checkbox-*` variables, so a class is how to set\n * one: `style` and the other input attributes go to the `<input>`. Name\n * `.styled-checkbox` beside your class in the selector, so it beats the\n * label's own declaration whatever order the stylesheets load in. A\n * `color` prop declares the fills again on `.styled-checkbox.is-<color>`,\n * which ties that selector, so leave `color` unset when a class sets them.\n */\n className?: string;\n /** The label/content for the checkbox. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Checkbox` component provides a Bulma-styled checkbox input.\n *\n * @function\n * @param {CheckboxProps} props - Props for the Checkbox component.\n * @returns {JSX.Element} The rendered checkbox element.\n *\n * @example\n * // Basic checkbox\n * <Checkbox>Accept terms</Checkbox>\n *\n * @example\n * // Inside a group\n * <Checkboxes name=\"tags\" defaultValue={['react']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * </Checkboxes>\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n color,\n size,\n className,\n children,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one. A callback ref's\n // return value is handed back, so React 19 still runs a cleanup it\n // returns, as it did when the ref went straight to the input.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, so it's set on the\n // input rather than rendered. A click clears it, so this runs after every\n // render, not only when the prop changes. Unset, it's left alone, so a\n // ref that sets the property itself still works. `ownsIndeterminateRef`\n // remembers that this component set it, so a prop that goes back to unset\n // clears the dash once instead of leaving it on.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // Inherit name + selection state from a surrounding <Checkboxes> group.\n // Local props always win over the group (explicit > implicit).\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n\n // Group-managed checked state — only when the group is in\n // controlled/uncontrolled mode (group.value is defined) AND this Checkbox\n // has a value to compare against. Local `checked` always wins.\n const groupManaged = group?.value !== undefined && value !== undefined;\n const groupHas = groupManaged && group!.value!.includes(String(value));\n const effectiveChecked =\n checked !== undefined ? checked : groupManaged ? groupHas : undefined;\n // When the group manages checked, suppress local defaultChecked to avoid\n // the controlled/uncontrolled React warning.\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // The click that got here cleared the mixed state. Put it back now,\n // since a click that changes no state renders nothing to do it.\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n // Local onChange always fires.\n onChange?.(e);\n // Dispatch to the group additionally — toggle this value's\n // membership in the group's array.\n if (group?.onChange && value !== undefined) {\n const valStr = String(value);\n const currentArr = group.value ?? [];\n const next = e.target.checked\n ? currentArr.includes(valStr)\n ? currentArr\n : [...currentArr, valStr]\n : currentArr.filter(v => v !== valStr);\n group.onChange(next);\n }\n },\n [onChange, group, value, indeterminate]\n );\n\n const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {\n [`is-${color}`]: color && checkboxColors.includes(color),\n [`is-${size}`]: size && checkboxSizes.includes(size),\n });\n const checkboxClass = classNames(mainClass, bulmaHelperClasses, className);\n const checkClass = usePrefixedClassNames('check');\n const controlLabelClass = usePrefixedClassNames('control-label');\n\n return (\n <label className={checkboxClass}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n />\n <span className={checkClass} />\n {children && <span className={controlLabelClass}>{children}</span>}\n </label>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n\nexport default Checkbox;\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;AAUA;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,MAAM;IACN,MAAM;IACN,SAAS;IACT,SAAS;IACT,QAAQ;;AAGV;;;;;;;;;;;;AAYG;AACI,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO;AAkDlE;;;;;;;;;;;;;;;;;AAiBG;AACI,MAAM,QAAQ,GAAG,UAAU,CAChC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EAAE,YAAY,EACtB,IAAI,EACJ,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,CAAC;AAClD,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;;;AAKF,IAAA,MAAM,QAAQ,GAAG,MAAM,CAA0B,IAAI,CAAC;AACtD,IAAA,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,IAA6B,KAAI;AAChC,QAAA,QAAQ,CAAC,OAAO,GAAG,IAAI;QACvB,IAAI,OAAO,GAAG,KAAK,UAAU;AAAE,YAAA,OAAO,GAAG,CAAC,IAAI,CAAC;AAC/C,QAAA,IAAI,GAAG;AAAE,YAAA,GAAG,CAAC,OAAO,GAAG,IAAI;AAC7B,IAAA,CAAC,EACD,CAAC,GAAG,CAAC,CACN;;;;;;;AAQD,IAAA,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1C,qBAAqB,CAAC,MAAK;AACzB,QAAA,IAAI,aAAa,KAAK,SAAS,EAAE;AAC/B,YAAA,oBAAoB,CAAC,OAAO,GAAG,IAAI;AACnC,YAAA,QAAQ,CAAC,OAAQ,CAAC,aAAa,GAAG,aAAa;QACjD;AAAO,aAAA,IAAI,oBAAoB,CAAC,OAAO,EAAE;AACvC,YAAA,oBAAoB,CAAC,OAAO,GAAG,KAAK;AACpC,YAAA,QAAQ,CAAC,OAAQ,CAAC,aAAa,GAAG,KAAK;QACzC;AACF,IAAA,CAAC,CAAC;;;AAIF,IAAA,MAAM,KAAK,GAAG,kBAAkB,EAAE;AAClC,IAAA,MAAM,aAAa,GAAG,IAAI,IAAI,KAAK,EAAE,IAAI;;;;IAKzC,MAAM,YAAY,GAAG,KAAK,EAAE,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;AACtE,IAAA,MAAM,QAAQ,GAAG,YAAY,IAAI,KAAM,CAAC,KAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtE,MAAM,gBAAgB,GACpB,OAAO,KAAK,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS;;;IAGvE,MAAM,uBAAuB,GAAG,YAAY,GAAG,SAAS,GAAG,cAAc;AAEzE,IAAA,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,CAAsC,KAAI;;;QAGzC,IAAI,aAAa,KAAK,SAAS;AAAE,YAAA,CAAC,CAAC,MAAM,CAAC,aAAa,GAAG,aAAa;;AAEvE,QAAA,QAAQ,GAAG,CAAC,CAAC;;;QAGb,IAAI,KAAK,EAAE,QAAQ,IAAI,KAAK,KAAK,SAAS,EAAE;AAC1C,YAAA,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC;AAC5B,YAAA,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE;AACpC,YAAA,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC;AACpB,kBAAE,UAAU,CAAC,QAAQ,CAAC,MAAM;AAC1B,sBAAE;AACF,sBAAE,CAAC,GAAG,UAAU,EAAE,MAAM;AAC1B,kBAAE,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC;AACxC,YAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB;IACF,CAAC,EACD,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CACxC;AAED,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,iBAAiB,EAAE,UAAU,EAAE;AACrE,QAAA,CAAC,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC;AACxD,QAAA,CAAC,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,GAAG,IAAI,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;AACrD,KAAA,CAAC;IACF,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;AAC1E,IAAA,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC;AACjD,IAAA,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,eAAe,CAAC;IAEhE,QACEA,IAAA,CAAA,OAAA,EAAA,EAAO,SAAS,EAAE,aAAa,EAAA,QAAA,EAAA,CAC7BC,GAAA,CAAA,OAAA,EAAA,EACE,GAAG,EAAE,OAAO,EACZ,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,gBAAgB,EACzB,cAAc,EAAE,uBAAuB,EACvC,QAAQ,EAAE,YAAY,EAAA,GAClB,IAAI,EAAA,CACR,EACFA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,UAAU,EAAA,CAAI,EAC9B,QAAQ,IAAIA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,iBAAiB,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAQ,CAAA,EAAA,CAC5D;AAEZ,CAAC;AAGH,QAAQ,CAAC,WAAW,GAAG,UAAU;;"}
1
+ {"version":3,"file":"Checkbox.js","sources":["../../../src/form/Checkbox.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n useCheckboxesGroup,\n useFieldsetDisabled,\n useRegisterChecked,\n} from './FormContext';\n\n/**\n * The values the Checkbox `color` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['color']` is typed from it, so the two list the same values.\n * Map over it to build a color picker, or check a value that arrives at\n * runtime before passing it in: the component adds no color class for a value\n * outside the tuple.\n *\n * @example\n * import { Checkbox, checkboxColors } from '@allxsmith/bestax-bulma';\n *\n * checkboxColors.map(color => (\n * <Checkbox key={color} color={color}>\n * {color}\n * </Checkbox>\n * ));\n */\nexport const checkboxColors = [\n 'primary',\n 'link',\n 'info',\n 'success',\n 'warning',\n 'danger',\n] as const;\n\n/**\n * The values the Checkbox `size` prop accepts, as a readonly tuple.\n *\n * `CheckboxProps['size']` is typed from it, so the two list the same values.\n * Use it to offer a size choice or to check a value that arrives at runtime:\n * the component adds no size class for a value outside the tuple. These are\n * element sizes, not the spacing scale in `validSizes`.\n *\n * @example\n * import { checkboxSizes } from '@allxsmith/bestax-bulma';\n *\n * type CheckboxSize = (typeof checkboxSizes)[number];\n */\nexport const checkboxSizes = ['small', 'normal', 'medium', 'large'] as const;\n\n/**\n * Props for the Checkbox component.\n *\n * @helperProps Helper props go on the outer `<label>`, with `className`. The\n * other attributes go on the `<input>`.\n */\nexport interface CheckboxProps\n extends\n Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'color'\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Color of the checkbox. */\n color?: (typeof checkboxColors)[number];\n /** Size of the checkbox. */\n size?: (typeof checkboxSizes)[number];\n /** Text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Whether the checkbox is disabled. */\n disabled?: boolean;\n /**\n * Shows the mixed state, as in a \"Select all\" box when some of what it\n * covers is checked. It's a look and an announcement only: `checked` is\n * still the value, and a click still toggles `checked`. Set to `true` or\n * `false`, it's controlled: a browser clears the mixed state on a click,\n * so the component sets it again from this prop after every click and\n * every render. Unset isn't `false`. The component leaves the input's own\n * `indeterminate` property alone, so a ref can set it, and going from set\n * to unset clears it once and hands it back. It has no HTML attribute, so\n * server-rendered markup can't carry it, and a mixed box renders unmixed\n * until hydration.\n */\n indeterminate?: boolean;\n /**\n * Additional CSS classes, on the outer `<label>`. That's the element that\n * declares the `--bulma-checkbox-*` variables, so a class is how to set\n * one: `style` and the other input attributes go to the `<input>`. Name\n * `.styled-checkbox` beside your class in the selector, so it beats the\n * label's own declaration whatever order the stylesheets load in. A\n * `color` prop declares the fills again on `.styled-checkbox.is-<color>`,\n * which ties that selector, so leave `color` unset when a class sets them.\n */\n className?: string;\n /** The label/content for the checkbox. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Checkbox` component provides a Bulma-styled checkbox input.\n *\n * @function\n * @param {CheckboxProps} props - Props for the Checkbox component.\n * @returns {JSX.Element} The rendered checkbox element.\n *\n * @example\n * // Basic checkbox\n * <Checkbox>Accept terms</Checkbox>\n *\n * @example\n * // Inside a group\n * <Checkboxes name=\"tags\" defaultValue={['react']}>\n * <Checkbox value=\"react\">React</Checkbox>\n * <Checkbox value=\"vue\">Vue</Checkbox>\n * </Checkboxes>\n */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\n (\n {\n color,\n size,\n className,\n children,\n textColor,\n disabled: disabledProp,\n name,\n value,\n checked,\n defaultChecked,\n indeterminate,\n onChange,\n ...props\n },\n ref\n ) => {\n const disabled = useFieldsetDisabled(disabledProp);\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n ...props,\n });\n\n // The input's own ref, merged with the forwarded one. A callback ref's\n // return value is handed back, so React 19 still runs a cleanup it\n // returns, as it did when the ref went straight to the input.\n const inputRef = useRef<HTMLInputElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') return ref(node);\n if (ref) ref.current = node;\n },\n [ref]\n );\n\n // `indeterminate` is a DOM property with no attribute, so it's set on the\n // input rather than rendered. A click clears it, so this runs after every\n // render, not only when the prop changes. Unset, it's left alone, so a\n // ref that sets the property itself still works. `ownsIndeterminateRef`\n // remembers that this component set it, so a prop that goes back to unset\n // clears the dash once instead of leaving it on.\n const ownsIndeterminateRef = useRef(false);\n useClientLayoutEffect(() => {\n if (indeterminate !== undefined) {\n ownsIndeterminateRef.current = true;\n inputRef.current!.indeterminate = indeterminate;\n } else if (ownsIndeterminateRef.current) {\n ownsIndeterminateRef.current = false;\n inputRef.current!.indeterminate = false;\n }\n });\n\n // Inherit name + selection state from a surrounding <Checkboxes> group.\n // Local props always win over the group (explicit > implicit).\n const group = useCheckboxesGroup();\n const effectiveName = name ?? group?.name;\n\n // Group-managed checked state — only when the group manages the selection\n // (it was given `value`, `defaultValue` or `onChange`) AND this Checkbox\n // has a value to compare against. Local `checked` always wins. A group\n // given only `onChange` holds no value until its first change, and until\n // then the box shows its own `defaultChecked`, controlled all the same,\n // so that change doesn't flip it from uncontrolled to controlled.\n const valueKey = value === undefined ? undefined : String(value);\n const groupManaged =\n group?.onChange !== undefined && valueKey !== undefined;\n const groupHas =\n groupManaged &&\n (group!.value ? group!.value.includes(valueKey!) : !!defaultChecked);\n const effectiveChecked =\n checked !== undefined ? checked : groupManaged ? groupHas : undefined;\n // When the group manages checked, suppress local defaultChecked to avoid\n // the controlled/uncontrolled React warning.\n const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;\n // What the box starts as, so the group's first change starts from it.\n useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n // The click that got here cleared the mixed state. Put it back now,\n // since a click that changes no state renders nothing to do it.\n if (indeterminate !== undefined) e.target.indeterminate = indeterminate;\n // Local onChange always fires.\n onChange?.(e);\n // Dispatch to the group additionally — toggle this value's\n // membership in the group's array, or in what was checked when the\n // group holds no value yet.\n if (group?.onChange && valueKey !== undefined) {\n const currentArr = group.value ?? group.startingValue!();\n const next = e.target.checked\n ? currentArr.includes(valueKey)\n ? currentArr\n : [...currentArr, valueKey]\n : currentArr.filter(v => v !== valueKey);\n group.onChange(next);\n }\n },\n [onChange, group, valueKey, indeterminate]\n );\n\n const mainClass = usePrefixedClassNames('styled-checkbox', 'checkbox', {\n [`is-${color}`]: color && checkboxColors.includes(color),\n [`is-${size}`]: size && checkboxSizes.includes(size),\n });\n const checkboxClass = classNames(mainClass, bulmaHelperClasses, className);\n const checkClass = usePrefixedClassNames('check');\n const controlLabelClass = usePrefixedClassNames('control-label');\n\n return (\n <label className={checkboxClass}>\n <input\n ref={setRefs}\n type=\"checkbox\"\n disabled={disabled}\n name={effectiveName}\n value={value}\n checked={effectiveChecked}\n defaultChecked={effectiveDefaultChecked}\n onChange={handleChange}\n {...rest}\n />\n <span className={checkClass} />\n {children && <span className={controlLabelClass}>{children}</span>}\n </label>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n\nexport default Checkbox;\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;AAcA;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,MAAM;IACN,MAAM;IACN,SAAS;IACT,SAAS;IACT,QAAQ;;AAGV;;;;;;;;;;;;AAYG;AACI,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO;AAkDlE;;;;;;;;;;;;;;;;;AAiBG;AACI,MAAM,QAAQ,GAAG,UAAU,CAChC,CACE,EACE,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EAAE,YAAY,EACtB,IAAI,EACJ,KAAK,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG,KACD;AACF,IAAA,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,CAAC;AAClD,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;;;AAKF,IAAA,MAAM,QAAQ,GAAG,MAAM,CAA0B,IAAI,CAAC;AACtD,IAAA,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,IAA6B,KAAI;AAChC,QAAA,QAAQ,CAAC,OAAO,GAAG,IAAI;QACvB,IAAI,OAAO,GAAG,KAAK,UAAU;AAAE,YAAA,OAAO,GAAG,CAAC,IAAI,CAAC;AAC/C,QAAA,IAAI,GAAG;AAAE,YAAA,GAAG,CAAC,OAAO,GAAG,IAAI;AAC7B,IAAA,CAAC,EACD,CAAC,GAAG,CAAC,CACN;;;;;;;AAQD,IAAA,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1C,qBAAqB,CAAC,MAAK;AACzB,QAAA,IAAI,aAAa,KAAK,SAAS,EAAE;AAC/B,YAAA,oBAAoB,CAAC,OAAO,GAAG,IAAI;AACnC,YAAA,QAAQ,CAAC,OAAQ,CAAC,aAAa,GAAG,aAAa;QACjD;AAAO,aAAA,IAAI,oBAAoB,CAAC,OAAO,EAAE;AACvC,YAAA,oBAAoB,CAAC,OAAO,GAAG,KAAK;AACpC,YAAA,QAAQ,CAAC,OAAQ,CAAC,aAAa,GAAG,KAAK;QACzC;AACF,IAAA,CAAC,CAAC;;;AAIF,IAAA,MAAM,KAAK,GAAG,kBAAkB,EAAE;AAClC,IAAA,MAAM,aAAa,GAAG,IAAI,IAAI,KAAK,EAAE,IAAI;;;;;;;AAQzC,IAAA,MAAM,QAAQ,GAAG,KAAK,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC;IAChE,MAAM,YAAY,GAChB,KAAK,EAAE,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS;IACzD,MAAM,QAAQ,GACZ,YAAY;SACX,KAAM,CAAC,KAAK,GAAG,KAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAS,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;IACtE,MAAM,gBAAgB,GACpB,OAAO,KAAK,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,SAAS;;;IAGvE,MAAM,uBAAuB,GAAG,YAAY,GAAG,SAAS,GAAG,cAAc;;AAEzE,IAAA,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,IAAI,cAAc,CAAC,CAAC;AAElE,IAAA,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,CAAsC,KAAI;;;QAGzC,IAAI,aAAa,KAAK,SAAS;AAAE,YAAA,CAAC,CAAC,MAAM,CAAC,aAAa,GAAG,aAAa;;AAEvE,QAAA,QAAQ,GAAG,CAAC,CAAC;;;;QAIb,IAAI,KAAK,EAAE,QAAQ,IAAI,QAAQ,KAAK,SAAS,EAAE;YAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,aAAc,EAAE;AACxD,YAAA,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC;AACpB,kBAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ;AAC5B,sBAAE;AACF,sBAAE,CAAC,GAAG,UAAU,EAAE,QAAQ;AAC5B,kBAAE,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC;AAC1C,YAAA,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB;IACF,CAAC,EACD,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,CAC3C;AAED,IAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,iBAAiB,EAAE,UAAU,EAAE;AACrE,QAAA,CAAC,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC;AACxD,QAAA,CAAC,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,GAAG,IAAI,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;AACrD,KAAA,CAAC;IACF,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,EAAE,kBAAkB,EAAE,SAAS,CAAC;AAC1E,IAAA,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC;AACjD,IAAA,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,eAAe,CAAC;IAEhE,QACEA,IAAA,CAAA,OAAA,EAAA,EAAO,SAAS,EAAE,aAAa,EAAA,QAAA,EAAA,CAC7BC,GAAA,CAAA,OAAA,EAAA,EACE,GAAG,EAAE,OAAO,EACZ,IAAI,EAAC,UAAU,EACf,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,gBAAgB,EACzB,cAAc,EAAE,uBAAuB,EACvC,QAAQ,EAAE,YAAY,EAAA,GAClB,IAAI,EAAA,CACR,EACFA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,UAAU,EAAA,CAAI,EAC9B,QAAQ,IAAIA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAE,iBAAiB,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAQ,CAAA,EAAA,CAC5D;AAEZ,CAAC;AAGH,QAAQ,CAAC,WAAW,GAAG,UAAU;;"}
@@ -5,7 +5,7 @@ import { forwardRef, useRef, useCallback, useId } from 'react';
5
5
  import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
6
6
  import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
7
7
  import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
8
- import { useFieldsetDisabled, useCheckboxesGroup } from './FormContext.js';
8
+ import { useFieldsetDisabled, useCheckboxesGroup, useRegisterChecked } from './FormContext.js';
9
9
 
10
10
  // The colors `Checkbox` takes, as `checkboxColors` lists them. Declared here as
11
11
  // well, so the API page can read them off this module, and a type test holds
@@ -69,30 +69,36 @@ const CheckboxCard = forwardRef(({ title, description, children, hasIndicator =
69
69
  });
70
70
  // A surrounding <Checkboxes> hands down its name and, when it manages
71
71
  // the selection, whether this card's value is in it. The card's own
72
- // props win, as they do on Checkbox.
72
+ // props win, as they do on Checkbox. A group given only `onChange` holds
73
+ // no value until its first change, and until then the card shows its own
74
+ // `defaultChecked`, controlled all the same, and registers it, so that
75
+ // change starts from what was checked, as Checkbox does.
73
76
  const group = useCheckboxesGroup();
74
77
  const effectiveName = name ?? group?.name;
75
- const groupManaged = group?.value !== undefined && value !== undefined;
78
+ const valueKey = value === undefined ? undefined : String(value);
79
+ const groupManaged = group?.onChange !== undefined && valueKey !== undefined;
76
80
  const effectiveChecked = checked !== undefined
77
81
  ? checked
78
82
  : groupManaged
79
- ? group.value.includes(String(value))
83
+ ? group.value
84
+ ? group.value.includes(valueKey)
85
+ : !!defaultChecked
80
86
  : undefined;
81
87
  const effectiveDefaultChecked = groupManaged ? undefined : defaultChecked;
88
+ useRegisterChecked(group, valueKey, !!(checked ?? defaultChecked));
82
89
  const handleChange = useCallback((e) => {
83
90
  if (indeterminate !== undefined)
84
91
  e.target.indeterminate = indeterminate;
85
92
  onChange?.(e);
86
- if (group?.onChange && value !== undefined) {
87
- const valStr = String(value);
88
- const current = group.value ?? [];
93
+ if (group?.onChange && valueKey !== undefined) {
94
+ const current = group.value ?? group.startingValue();
89
95
  group.onChange(e.target.checked
90
- ? current.includes(valStr)
96
+ ? current.includes(valueKey)
91
97
  ? current
92
- : [...current, valStr]
93
- : current.filter(v => v !== valStr));
98
+ : [...current, valueKey]
99
+ : current.filter(v => v !== valueKey));
94
100
  }
95
- }, [onChange, group, value, indeterminate]);
101
+ }, [onChange, group, valueKey, indeterminate]);
96
102
  // The title names the input and the description describes it. A name
97
103
  // passed in wins, and without one of either the label's own text names
98
104
  // the input, description included, so it isn't described again.