@allxsmith/bestax-bulma 5.67.4 → 5.67.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/Dropdown.js +24 -5
- package/dist/esm/components/Dropdown.js.map +1 -1
- package/dist/esm/components/HoverCard.js +4 -1
- package/dist/esm/components/HoverCard.js.map +1 -1
- package/dist/esm/components/Tabs.js.map +1 -1
- package/dist/esm/elements/Notification.js.map +1 -1
- package/dist/esm/form/Combobox.js +7 -2
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/Control.js.map +1 -1
- package/dist/esm/form/DateTimeInputBase.js +23 -3
- package/dist/esm/form/DateTimeInputBase.js.map +1 -1
- package/dist/esm/form/TimeInputBase.js +6 -2
- package/dist/esm/form/TimeInputBase.js.map +1 -1
- package/dist/esm/form/_pickerInternals/TimeWheels.js +19 -16
- package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -1
- package/dist/esm/helpers/useFocusTrap.js +84 -10
- package/dist/esm/helpers/useFocusTrap.js.map +1 -1
- package/dist/esm/helpers/useOtherClasses.js.map +1 -1
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +2767 -2640
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/HoverCard.d.ts +5 -1
- package/dist/types/components/Tabs.d.ts +5 -1
- package/dist/types/elements/Notification.d.ts +18 -2
- package/dist/types/form/Combobox.d.ts +4 -1
- package/dist/types/form/Control.d.ts +18 -4
- package/dist/types/form/DateTimeInputBase.d.ts +3 -0
- package/dist/types/form/TimeInputBase.d.ts +5 -1
- package/dist/types/form/_pickerInternals/TimeWheels.d.ts +6 -0
- package/dist/types/helpers/useFocusTrap.d.ts +14 -4
- package/dist/types/helpers/useOtherClasses.d.ts +6 -1
- package/dist/types-cjs/components/HoverCard.d.ts +5 -1
- package/dist/types-cjs/components/Tabs.d.ts +5 -1
- package/dist/types-cjs/elements/Notification.d.ts +18 -2
- package/dist/types-cjs/form/Combobox.d.ts +4 -1
- package/dist/types-cjs/form/Control.d.ts +18 -4
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +3 -0
- package/dist/types-cjs/form/TimeInputBase.d.ts +5 -1
- package/dist/types-cjs/form/_pickerInternals/TimeWheels.d.ts +6 -0
- package/dist/types-cjs/helpers/useFocusTrap.d.ts +14 -4
- package/dist/types-cjs/helpers/useOtherClasses.d.ts +6 -1
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/CLAUDE.md +4 -1
- package/src/scss/_color-classes.scss +27 -0
- package/src/scss/_selected-row.scss +2 -10
- package/src/scss/components/_hovercard.scss +11 -0
- package/src/scss/components/_sidebar.scss +8 -5
- package/src/scss/components/_tabs.scss +16 -17
- package/src/scss/elements/_notification.scss +30 -1
- package/src/scss/form/_combobox.scss +12 -0
- package/src/scss/form/_slider.scss +18 -0
- package/src/scss/form/_timeinput.scss +7 -0
|
@@ -10,6 +10,7 @@ import { omitAttrs, ANCHOR_ONLY_ATTRS } from '../helpers/anchorAttrs.js';
|
|
|
10
10
|
import { buttonType } from '../helpers/buttonType.js';
|
|
11
11
|
import { useMenuKeys, enabledMenuItems } from '../helpers/useMenuKeys.js';
|
|
12
12
|
import { useLatestRef } from '../helpers/useLatestRef.js';
|
|
13
|
+
import { focusTabStopAfter } from '../helpers/useFocusTrap.js';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Checks if code is running in a browser environment.
|
|
@@ -32,11 +33,13 @@ const isBrowser$1 = (win, doc) => typeof win !== 'undefined' && typeof doc !== '
|
|
|
32
33
|
* item whose text starts with it, skipping disabled ones, and letters typed
|
|
33
34
|
* in quick succession add up to one search. Typing searches once focus is in
|
|
34
35
|
* the menu, so a letter typed on the trigger does nothing. Escape closes the
|
|
35
|
-
* menu and focuses the trigger
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
36
|
+
* menu and focuses the trigger. Tab closes it and moves focus to the next
|
|
37
|
+
* tab stop after the Dropdown, wrapping inside a focus trap such as Modal's,
|
|
38
|
+
* and Shift+Tab closes it and focuses the trigger. Anything focusable in the
|
|
39
|
+
* menu that isn't an item, such as a field, keeps its own keys apart from
|
|
40
|
+
* Escape and Tab, though an Escape it calls `preventDefault()` on in its own
|
|
41
|
+
* `onKeyDown` stays its own and leaves the menu open. For a panel built
|
|
42
|
+
* around fields, use `Popover`.
|
|
40
43
|
*
|
|
41
44
|
* @function
|
|
42
45
|
* @param {DropdownProps} props - Props for the Dropdown component.
|
|
@@ -241,6 +244,22 @@ const DropdownComponent = forwardRef(function DropdownComponent({ label, childre
|
|
|
241
244
|
if (e.key === 'Tab') {
|
|
242
245
|
setActive(false);
|
|
243
246
|
onActiveChange?.(false);
|
|
247
|
+
// Closing can hide the items before the browser moves focus, and
|
|
248
|
+
// Firefox then drops focus to the page from one, so focus moves here
|
|
249
|
+
// instead: Shift+Tab to the trigger, and Tab on past the Dropdown.
|
|
250
|
+
// A menu the pointer shows on a `hoverable` Dropdown isn't open and
|
|
251
|
+
// stays shown, so Tab walks its items as the browser does. A Tab
|
|
252
|
+
// something already used, such as a focus trap around the Dropdown
|
|
253
|
+
// wrapping from the last item, keeps the focus it gave.
|
|
254
|
+
if (!active || e.defaultPrevented)
|
|
255
|
+
return;
|
|
256
|
+
if (e.shiftKey) {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
triggerRef.current?.focus();
|
|
259
|
+
}
|
|
260
|
+
else if (focusTabStopAfter(dropdownRef.current)) {
|
|
261
|
+
e.preventDefault();
|
|
262
|
+
}
|
|
244
263
|
return;
|
|
245
264
|
}
|
|
246
265
|
menuKeys.onKeyDown(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.js","sources":["../../../src/components/Dropdown.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useId,\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 /**\n * Root element ID. The trigger gets `<id>-trigger` and the menu `<id>-menu`,\n * which the trigger's `aria-controls` and the menu's `aria-labelledby` point\n * at. Without one, both ids come from `useId`.\n */\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 // The trigger names the menu and the menu is what it controls, so both\n // need an id whether or not the Dropdown has one.\n const generatedId = useId();\n const baseId = id || generatedId;\n const triggerId = `${baseId}-trigger`;\n const menuId = `${baseId}-menu`;\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 id={triggerId}\n className={buttonClass}\n aria-haspopup=\"true\"\n aria-controls={menuId}\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={menuId}\n ref={menuRef}\n role=\"menu\"\n aria-labelledby={triggerId}\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 useId,\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';\nimport { focusTabStopAfter } from '../helpers/useFocusTrap';\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 /**\n * Root element ID. The trigger gets `<id>-trigger` and the menu `<id>-menu`,\n * which the trigger's `aria-controls` and the menu's `aria-labelledby` point\n * at. Without one, both ids come from `useId`.\n */\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. Tab closes it and moves focus to the next\n * tab stop after the Dropdown, wrapping inside a focus trap such as Modal's,\n * and Shift+Tab closes it and focuses the trigger. Anything focusable in the\n * menu that isn't an item, such as a field, keeps its own keys apart from\n * Escape and Tab, though an Escape it calls `preventDefault()` on in its own\n * `onKeyDown` stays its own and leaves the menu open. For a panel built\n * 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 // The trigger names the menu and the menu is what it controls, so both\n // need an id whether or not the Dropdown has one.\n const generatedId = useId();\n const baseId = id || generatedId;\n const triggerId = `${baseId}-trigger`;\n const menuId = `${baseId}-menu`;\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 // Closing can hide the items before the browser moves focus, and\n // Firefox then drops focus to the page from one, so focus moves here\n // instead: Shift+Tab to the trigger, and Tab on past the Dropdown.\n // A menu the pointer shows on a `hoverable` Dropdown isn't open and\n // stays shown, so Tab walks its items as the browser does. A Tab\n // something already used, such as a focus trap around the Dropdown\n // wrapping from the last item, keeps the focus it gave.\n if (!active || e.defaultPrevented) return;\n if (e.shiftKey) {\n e.preventDefault();\n triggerRef.current?.focus();\n } else if (focusTabStopAfter(dropdownRef.current as HTMLElement)) {\n e.preventDefault();\n }\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 id={triggerId}\n className={buttonClass}\n aria-haspopup=\"true\"\n aria-controls={menuId}\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={menuId}\n ref={menuRef}\n role=\"menu\"\n aria-labelledby={triggerId}\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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"}
|
|
@@ -33,7 +33,7 @@ import { isDev, warnOnce } from '../helpers/devWarnings.js';
|
|
|
33
33
|
* <SubTitle as="p" size="6">Analytical Engine team</SubTitle>
|
|
34
34
|
* </HoverCard>
|
|
35
35
|
*/
|
|
36
|
-
const HoverCard = ({ trigger, children, open: controlledOpen, defaultOpen = false, onOpenChange, openDelay = 600, closeDelay = 300, position
|
|
36
|
+
const HoverCard = ({ trigger, children, open: controlledOpen, defaultOpen = false, onOpenChange, openDelay = 600, closeDelay = 300, position, appendToBody = false, openOnTap = false, className, contentClassName, ...props }) => {
|
|
37
37
|
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
38
38
|
const { onPointerEnter, onPointerOver, onPointerLeave, onPointerDown, onPointerUp, onFocus, onBlur, ...attrs } = rest;
|
|
39
39
|
const rootRef = useRef(null);
|
|
@@ -106,6 +106,9 @@ const HoverCard = ({ trigger, children, open: controlledOpen, defaultOpen = fals
|
|
|
106
106
|
const rootClasses = classNames(usePrefixedClassNames('hover-card', { 'is-active': cardMounted }), bulmaHelperClasses, className);
|
|
107
107
|
const cardClasses = classNames(usePrefixedClassNames('hover-card-content', {
|
|
108
108
|
[`is-${resolved.position}`]: true,
|
|
109
|
+
// The default lines up with the trigger's inline start, so the
|
|
110
|
+
// stylesheet moves it to the right edge on a right-to-left page.
|
|
111
|
+
'is-start-aligned': position === undefined,
|
|
109
112
|
'is-portal': appendToBody,
|
|
110
113
|
}), contentClassName);
|
|
111
114
|
return (jsxs("span", { className: rootClasses, ...attrs, onPointerEnter: chain(onPointerEnter, hover.onPointerEnter), onPointerOver: chain(onPointerOver, hover.onPointerOver), onPointerLeave: chain(onPointerLeave, hover.onPointerLeave), onFocus: chain(onFocus, hover.onFocus), onBlur: chain(onBlur, hover.onBlur), onPointerDown: chain(onPointerDown, hover.onPointerDown), onPointerUp: chain(onPointerUp, hover.onPointerUp), ref: rootRef, children: [clonedTrigger, isOpen && (jsx(PopupPortal, { disabled: !appendToBody, children: jsx("div", { ref: cardRef, id: cardId, className: cardClasses, style: appendToBody
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HoverCard.js","sources":["../../../src/components/HoverCard.tsx"],"sourcesContent":["import React, {\n cloneElement,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { PopupPortal } from '../helpers/portal';\nimport { useIsHydrated } from '../helpers/useIsHydrated';\nimport { marginGap, useAnchoredPosition } from '../helpers/useAnchoredPosition';\nimport { chain, useHoverOpen } from '../helpers/useHoverOpen';\nimport { isTabbableKind } from '../helpers/useFocusTrap';\nimport { isDev, warnOnce } from '../helpers/devWarnings';\nimport type { PickerPosition } from '../form/_pickerInternals/pickerTypes';\n\n/**\n * Where the card opens against its trigger: below (`bottom-*`) or above\n * (`top-*`), lined up with the trigger's left or right edge. `auto` picks the\n * one that keeps the card in the viewport, preferring below and lined up on\n * the left. The same union `Popover` and the date and time pickers take.\n */\nexport type HoverCardPosition = PickerPosition;\n\n/**\n * Props for the HoverCard component. `className`, `id`, the other HTML\n * attributes and the helper props land on the `span` around the trigger, not\n * on the card; `contentClassName` reaches the card.\n * @extraProp {string} [className] - Additional classes for the `span` around the trigger. The card takes `contentClassName`.\n */\nexport interface HoverCardProps\n extends\n Omit<React.HTMLAttributes<HTMLSpanElement>, 'color' | 'children'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /**\n * The element the card previews, such as a link or a `Button`. The element\n * itself has to take focus, so keyboard users can open the card too: a\n * link inside a `<span>` doesn't do, since focus comes back to the trigger\n * and its ARIA is on it. HoverCard gives it no role and no tab stop, since\n * it can't know what the element is, and a development build warns when\n * it can't take focus: use a link or a button, or give the element\n * `tabIndex={0}`. A disabled button can't take focus either. HoverCard adds\n * `aria-expanded` and `aria-controls`, both naming the card only while it\n * is on the page, so it has to be a single element that passes those to\n * its DOM node. Its own click and keys stay its own, and the card doesn't\n * toggle on them, except Escape while the card is open, which closes the\n * card before the trigger sees it.\n */\n trigger: React.ReactElement;\n /**\n * The card's content: a preview whose links and buttons are fine, but not a\n * form, which belongs in a `Popover`. The card pads itself, so content goes\n * straight in.\n */\n children?: React.ReactNode;\n /**\n * Controlled open state. When set, hover, focus and Escape only report\n * through `onOpenChange`, so an action inside the card can close it. While\n * the card is open, Escape is reported, and when focus is in the card, on\n * its trigger or nowhere, the key stops there even if you keep the card\n * open, so a `Modal` around it doesn't close from the keyboard until the\n * card does.\n */\n open?: boolean;\n /**\n * Initial open state when uncontrolled. A card that starts open stays open\n * until the pointer or focus has been and gone, or Escape closes it.\n * @defaultValue false\n */\n defaultOpen?: boolean;\n /**\n * Called with the state asked for: when `openDelay` or `closeDelay` runs\n * out, and right away on Escape. Fires in both controlled and uncontrolled\n * use. An Escape it reports stops at the card when focus is in the card,\n * on its trigger or nowhere, so nothing around it sees that key. With\n * focus anywhere else, the card still closes and the key goes on to\n * whatever has focus.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * How long the pointer or keyboard focus waits on the trigger before the\n * card opens, in milliseconds.\n * @defaultValue 600\n */\n openDelay?: number;\n /**\n * How long the card stays after the pointer and focus have left the trigger\n * and the card, in milliseconds. It is the time the pointer has to cross\n * the gap between the trigger and the card: with `0` the card closes as the\n * pointer leaves the trigger, before the pointer can reach it.\n * @defaultValue 300\n */\n closeDelay?: number;\n /**\n * Where the card opens against the trigger.\n * @defaultValue 'bottom-left'\n */\n position?: HoverCardPosition;\n /**\n * Render the card through `Portal`, into the `portalContainer` a\n * `ConfigProvider` sets, else the `Modal`, `Dialog` or `Command.Dialog`\n * it's in, else `document.body`, fixed to the viewport, so an ancestor's\n * `overflow`, `transform` or stacking context can't clip it. A trigger in\n * running text needs it too, since the card's block content can't sit\n * inside a `<p>`. The card then shows from the commit after hydration,\n * never in server markup, and it sits in the Tab order where its container\n * is. At the end of `<body>` or of a dialog, Tab reaches it only after the\n * rest of the page or the dialog, and focus leaving the trigger on the way\n * closes it, so keyboard users can open it, read it and close it with\n * Escape, and whatever it links to has to be reachable from the page as\n * well. Theming variables set on an ancestor of the trigger reach it only\n * when its container is inside that ancestor.\n * @defaultValue false\n */\n appendToBody?: boolean;\n /**\n * Open the card with a tap on a touch screen. Touch has no hover, so\n * without this a phone or tablet never opens the card. With it, a tap on\n * the trigger opens the card at once, and it stays until a second tap on\n * the trigger, a tap outside the trigger and the card, or Escape. The tap\n * still does whatever the trigger does, so turn this on only for a trigger\n * with no tap action of its own, such as a `Button` with no `onClick`: on\n * a link, the first tap would follow the link rather than show the card.\n * Mouse and pen work the same either way.\n * @defaultValue false\n */\n openOnTap?: boolean;\n /** Additional classes for the card (`.hover-card-content`). */\n contentClassName?: string;\n}\n\n/**\n * The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it.\n *\n * Nothing moves focus when the card opens, and nothing traps it. In place,\n * the card comes right after the trigger, so Tab goes from the trigger into\n * its links and tabbing past them closes it. The pointer can move onto the\n * card, Escape closes it from anywhere, and by default touch doesn't open it,\n * so tapping the trigger just does what the trigger does. `openOnTap` opens\n * it with a tap, for a trigger with no tap action of its own. For hints with nothing to\n * click use `Tooltip`, and for content opened on purpose, such as a form,\n * use `Popover`.\n *\n * @function\n * @param {HoverCardProps} props - Props for the HoverCard component.\n * @returns {JSX.Element} The trigger in its wrapper, and the card while open.\n *\n * @example\n * <HoverCard trigger={<a href=\"/people/ada\">Ada Lovelace</a>}>\n * <Title as=\"p\" size=\"6\">Ada Lovelace</Title>\n * <SubTitle as=\"p\" size=\"6\">Analytical Engine team</SubTitle>\n * </HoverCard>\n */\nexport const HoverCard: React.FC<HoverCardProps> = ({\n trigger,\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n openDelay = 600,\n closeDelay = 300,\n position = 'bottom-left',\n appendToBody = false,\n openOnTap = false,\n className,\n contentClassName,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const {\n onPointerEnter,\n onPointerOver,\n onPointerLeave,\n onPointerDown,\n onPointerUp,\n onFocus,\n onBlur,\n ...attrs\n } = rest;\n const rootRef = useRef<HTMLSpanElement>(null);\n const cardRef = useRef<HTMLDivElement>(null);\n const cardId = `${useId()}-card`;\n\n const isControlled = controlledOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isOpen = controlledOpen ?? internalOpen;\n\n const requestOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next);\n if (!isControlled) setInternalOpen(next);\n },\n [isControlled, onOpenChange]\n );\n\n // A portaled card has no server markup, so it only exists from the commit\n // after hydration, and nothing measures it before then.\n const hydrated = useIsHydrated();\n const cardMounted = isOpen && (hydrated || !appendToBody);\n\n const resolved = useAnchoredPosition(rootRef, cardRef, {\n active: cardMounted,\n position,\n fixed: appendToBody,\n // The gap comes from `--bulma-hover-card-offset` in the stylesheet, so\n // the coordinates leave it out and `auto` reads it off the card.\n offset: 0,\n styledGap: marginGap,\n });\n\n // The trigger renders first inside the wrapper. Read when needed rather\n // than held, so a trigger that remounted is still the one found.\n const triggerRef = useMemo(\n () => ({\n get current() {\n const first = (rootRef.current as HTMLSpanElement).firstElementChild;\n return first && first !== cardRef.current\n ? (first as HTMLElement)\n : null;\n },\n }),\n []\n );\n\n const hover = useHoverOpen({\n open: isOpen,\n onOpenChange: requestOpen,\n openDelay,\n closeDelay,\n triggerRef,\n floatingRef: cardRef,\n openOnTap,\n });\n\n // A trigger that can't take focus leaves keyboard users no way to open the\n // card. It has to be the trigger element itself, not something inside it,\n // since focus comes back to it and its ARIA is on it. Judged by what the\n // element is rather than by its styles, which can hide it for now. After\n // every commit, since the trigger can change, and only in development.\n useEffect(() => {\n if (!isDev()) return;\n const triggerNode = triggerRef.current;\n if (!triggerNode) return;\n if (!triggerNode.matches(':disabled') && isTabbableKind(triggerNode)) {\n return;\n }\n warnOnce(\n 'HoverCard:unfocusable-trigger',\n \"[bestax-bulma] <HoverCard> has a trigger that can't take focus, so \" +\n \"keyboard users can't open the card. Use a link or a button as the \" +\n 'trigger, or give it tabIndex={0}.'\n );\n });\n\n // Expanded only while the card is on the page, so a portaled card that\n // waits for hydration isn't announced before it exists.\n const clonedTrigger = cloneElement(\n trigger as React.ReactElement<Record<string, unknown>>,\n {\n 'aria-expanded': cardMounted,\n 'aria-controls': cardMounted ? cardId : undefined,\n }\n );\n\n const rootClasses = classNames(\n usePrefixedClassNames('hover-card', { 'is-active': cardMounted }),\n bulmaHelperClasses,\n className\n );\n const cardClasses = classNames(\n usePrefixedClassNames('hover-card-content', {\n [`is-${resolved.position}`]: true,\n 'is-portal': appendToBody,\n }),\n contentClassName\n );\n\n return (\n // The ref after the spread: React 19 hands a function component a `ref`\n // prop like any other, and the wrapper has to stay ours. The card is in\n // the wrapper's React tree even when portaled, so the hover and focus\n // handlers here hear from both.\n <span\n className={rootClasses}\n {...attrs}\n onPointerEnter={chain(onPointerEnter, hover.onPointerEnter)}\n onPointerOver={chain(onPointerOver, hover.onPointerOver)}\n onPointerLeave={chain(onPointerLeave, hover.onPointerLeave)}\n onFocus={chain(onFocus, hover.onFocus)}\n onBlur={chain(onBlur, hover.onBlur)}\n onPointerDown={chain(onPointerDown, hover.onPointerDown)}\n onPointerUp={chain(onPointerUp, hover.onPointerUp)}\n ref={rootRef}\n >\n {clonedTrigger}\n {isOpen && (\n <PopupPortal disabled={!appendToBody}>\n <div\n ref={cardRef}\n id={cardId}\n className={cardClasses}\n style={\n appendToBody\n ? {\n position: 'fixed',\n top: resolved.top,\n left: resolved.left,\n }\n : undefined\n }\n >\n {children}\n </div>\n </PopupPortal>\n )}\n </span>\n );\n};\n\nexport default HoverCard;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HoverCard.js","sources":["../../../src/components/HoverCard.tsx"],"sourcesContent":["import React, {\n cloneElement,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { PopupPortal } from '../helpers/portal';\nimport { useIsHydrated } from '../helpers/useIsHydrated';\nimport { marginGap, useAnchoredPosition } from '../helpers/useAnchoredPosition';\nimport { chain, useHoverOpen } from '../helpers/useHoverOpen';\nimport { isTabbableKind } from '../helpers/useFocusTrap';\nimport { isDev, warnOnce } from '../helpers/devWarnings';\nimport type { PickerPosition } from '../form/_pickerInternals/pickerTypes';\n\n/**\n * Where the card opens against its trigger: below (`bottom-*`) or above\n * (`top-*`), lined up with the trigger's left or right edge. `auto` picks the\n * one that keeps the card in the viewport, preferring below and lined up on\n * the left. The same union `Popover` and the date and time pickers take.\n */\nexport type HoverCardPosition = PickerPosition;\n\n/**\n * Props for the HoverCard component. `className`, `id`, the other HTML\n * attributes and the helper props land on the `span` around the trigger, not\n * on the card; `contentClassName` reaches the card.\n * @extraProp {string} [className] - Additional classes for the `span` around the trigger. The card takes `contentClassName`.\n */\nexport interface HoverCardProps\n extends\n Omit<React.HTMLAttributes<HTMLSpanElement>, 'color' | 'children'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /**\n * The element the card previews, such as a link or a `Button`. The element\n * itself has to take focus, so keyboard users can open the card too: a\n * link inside a `<span>` doesn't do, since focus comes back to the trigger\n * and its ARIA is on it. HoverCard gives it no role and no tab stop, since\n * it can't know what the element is, and a development build warns when\n * it can't take focus: use a link or a button, or give the element\n * `tabIndex={0}`. A disabled button can't take focus either. HoverCard adds\n * `aria-expanded` and `aria-controls`, both naming the card only while it\n * is on the page, so it has to be a single element that passes those to\n * its DOM node. Its own click and keys stay its own, and the card doesn't\n * toggle on them, except Escape while the card is open, which closes the\n * card before the trigger sees it.\n */\n trigger: React.ReactElement;\n /**\n * The card's content: a preview whose links and buttons are fine, but not a\n * form, which belongs in a `Popover`. The card pads itself, so content goes\n * straight in.\n */\n children?: React.ReactNode;\n /**\n * Controlled open state. When set, hover, focus and Escape only report\n * through `onOpenChange`, so an action inside the card can close it. While\n * the card is open, Escape is reported, and when focus is in the card, on\n * its trigger or nowhere, the key stops there even if you keep the card\n * open, so a `Modal` around it doesn't close from the keyboard until the\n * card does.\n */\n open?: boolean;\n /**\n * Initial open state when uncontrolled. A card that starts open stays open\n * until the pointer or focus has been and gone, or Escape closes it.\n * @defaultValue false\n */\n defaultOpen?: boolean;\n /**\n * Called with the state asked for: when `openDelay` or `closeDelay` runs\n * out, and right away on Escape. Fires in both controlled and uncontrolled\n * use. An Escape it reports stops at the card when focus is in the card,\n * on its trigger or nowhere, so nothing around it sees that key. With\n * focus anywhere else, the card still closes and the key goes on to\n * whatever has focus.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * How long the pointer or keyboard focus waits on the trigger before the\n * card opens, in milliseconds.\n * @defaultValue 600\n */\n openDelay?: number;\n /**\n * How long the card stays after the pointer and focus have left the trigger\n * and the card, in milliseconds. It is the time the pointer has to cross\n * the gap between the trigger and the card: with `0` the card closes as the\n * pointer leaves the trigger, before the pointer can reach it.\n * @defaultValue 300\n */\n closeDelay?: number;\n /**\n * Where the card opens against the trigger. Left out, it opens below and\n * lines up with the trigger's start edge, which is its right edge on a\n * right-to-left page, so a trigger at the start of the line doesn't push\n * the card off the screen. A corner you pass stays physical, so\n * `bottom-left` lines up the left edges on either page.\n * @defaultValue 'bottom-left'\n */\n position?: HoverCardPosition;\n /**\n * Render the card through `Portal`, into the `portalContainer` a\n * `ConfigProvider` sets, else the `Modal`, `Dialog` or `Command.Dialog`\n * it's in, else `document.body`, fixed to the viewport, so an ancestor's\n * `overflow`, `transform` or stacking context can't clip it. A trigger in\n * running text needs it too, since the card's block content can't sit\n * inside a `<p>`. The card then shows from the commit after hydration,\n * never in server markup, and it sits in the Tab order where its container\n * is. At the end of `<body>` or of a dialog, Tab reaches it only after the\n * rest of the page or the dialog, and focus leaving the trigger on the way\n * closes it, so keyboard users can open it, read it and close it with\n * Escape, and whatever it links to has to be reachable from the page as\n * well. Theming variables set on an ancestor of the trigger reach it only\n * when its container is inside that ancestor.\n * @defaultValue false\n */\n appendToBody?: boolean;\n /**\n * Open the card with a tap on a touch screen. Touch has no hover, so\n * without this a phone or tablet never opens the card. With it, a tap on\n * the trigger opens the card at once, and it stays until a second tap on\n * the trigger, a tap outside the trigger and the card, or Escape. The tap\n * still does whatever the trigger does, so turn this on only for a trigger\n * with no tap action of its own, such as a `Button` with no `onClick`: on\n * a link, the first tap would follow the link rather than show the card.\n * Mouse and pen work the same either way.\n * @defaultValue false\n */\n openOnTap?: boolean;\n /** Additional classes for the card (`.hover-card-content`). */\n contentClassName?: string;\n}\n\n/**\n * The `HoverCard` component shows a card previewing what's behind a link or a button while the pointer rests on it or keyboard focus is on it.\n *\n * Nothing moves focus when the card opens, and nothing traps it. In place,\n * the card comes right after the trigger, so Tab goes from the trigger into\n * its links and tabbing past them closes it. The pointer can move onto the\n * card, Escape closes it from anywhere, and by default touch doesn't open it,\n * so tapping the trigger just does what the trigger does. `openOnTap` opens\n * it with a tap, for a trigger with no tap action of its own. For hints with nothing to\n * click use `Tooltip`, and for content opened on purpose, such as a form,\n * use `Popover`.\n *\n * @function\n * @param {HoverCardProps} props - Props for the HoverCard component.\n * @returns {JSX.Element} The trigger in its wrapper, and the card while open.\n *\n * @example\n * <HoverCard trigger={<a href=\"/people/ada\">Ada Lovelace</a>}>\n * <Title as=\"p\" size=\"6\">Ada Lovelace</Title>\n * <SubTitle as=\"p\" size=\"6\">Analytical Engine team</SubTitle>\n * </HoverCard>\n */\nexport const HoverCard: React.FC<HoverCardProps> = ({\n trigger,\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n openDelay = 600,\n closeDelay = 300,\n position,\n appendToBody = false,\n openOnTap = false,\n className,\n contentClassName,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const {\n onPointerEnter,\n onPointerOver,\n onPointerLeave,\n onPointerDown,\n onPointerUp,\n onFocus,\n onBlur,\n ...attrs\n } = rest;\n const rootRef = useRef<HTMLSpanElement>(null);\n const cardRef = useRef<HTMLDivElement>(null);\n const cardId = `${useId()}-card`;\n\n const isControlled = controlledOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isOpen = controlledOpen ?? internalOpen;\n\n const requestOpen = useCallback(\n (next: boolean) => {\n onOpenChange?.(next);\n if (!isControlled) setInternalOpen(next);\n },\n [isControlled, onOpenChange]\n );\n\n // A portaled card has no server markup, so it only exists from the commit\n // after hydration, and nothing measures it before then.\n const hydrated = useIsHydrated();\n const cardMounted = isOpen && (hydrated || !appendToBody);\n\n const resolved = useAnchoredPosition(rootRef, cardRef, {\n active: cardMounted,\n position,\n fixed: appendToBody,\n // The gap comes from `--bulma-hover-card-offset` in the stylesheet, so\n // the coordinates leave it out and `auto` reads it off the card.\n offset: 0,\n styledGap: marginGap,\n });\n\n // The trigger renders first inside the wrapper. Read when needed rather\n // than held, so a trigger that remounted is still the one found.\n const triggerRef = useMemo(\n () => ({\n get current() {\n const first = (rootRef.current as HTMLSpanElement).firstElementChild;\n return first && first !== cardRef.current\n ? (first as HTMLElement)\n : null;\n },\n }),\n []\n );\n\n const hover = useHoverOpen({\n open: isOpen,\n onOpenChange: requestOpen,\n openDelay,\n closeDelay,\n triggerRef,\n floatingRef: cardRef,\n openOnTap,\n });\n\n // A trigger that can't take focus leaves keyboard users no way to open the\n // card. It has to be the trigger element itself, not something inside it,\n // since focus comes back to it and its ARIA is on it. Judged by what the\n // element is rather than by its styles, which can hide it for now. After\n // every commit, since the trigger can change, and only in development.\n useEffect(() => {\n if (!isDev()) return;\n const triggerNode = triggerRef.current;\n if (!triggerNode) return;\n if (!triggerNode.matches(':disabled') && isTabbableKind(triggerNode)) {\n return;\n }\n warnOnce(\n 'HoverCard:unfocusable-trigger',\n \"[bestax-bulma] <HoverCard> has a trigger that can't take focus, so \" +\n \"keyboard users can't open the card. Use a link or a button as the \" +\n 'trigger, or give it tabIndex={0}.'\n );\n });\n\n // Expanded only while the card is on the page, so a portaled card that\n // waits for hydration isn't announced before it exists.\n const clonedTrigger = cloneElement(\n trigger as React.ReactElement<Record<string, unknown>>,\n {\n 'aria-expanded': cardMounted,\n 'aria-controls': cardMounted ? cardId : undefined,\n }\n );\n\n const rootClasses = classNames(\n usePrefixedClassNames('hover-card', { 'is-active': cardMounted }),\n bulmaHelperClasses,\n className\n );\n const cardClasses = classNames(\n usePrefixedClassNames('hover-card-content', {\n [`is-${resolved.position}`]: true,\n // The default lines up with the trigger's inline start, so the\n // stylesheet moves it to the right edge on a right-to-left page.\n 'is-start-aligned': position === undefined,\n 'is-portal': appendToBody,\n }),\n contentClassName\n );\n\n return (\n // The ref after the spread: React 19 hands a function component a `ref`\n // prop like any other, and the wrapper has to stay ours. The card is in\n // the wrapper's React tree even when portaled, so the hover and focus\n // handlers here hear from both.\n <span\n className={rootClasses}\n {...attrs}\n onPointerEnter={chain(onPointerEnter, hover.onPointerEnter)}\n onPointerOver={chain(onPointerOver, hover.onPointerOver)}\n onPointerLeave={chain(onPointerLeave, hover.onPointerLeave)}\n onFocus={chain(onFocus, hover.onFocus)}\n onBlur={chain(onBlur, hover.onBlur)}\n onPointerDown={chain(onPointerDown, hover.onPointerDown)}\n onPointerUp={chain(onPointerUp, hover.onPointerUp)}\n ref={rootRef}\n >\n {clonedTrigger}\n {isOpen && (\n <PopupPortal disabled={!appendToBody}>\n <div\n ref={cardRef}\n id={cardId}\n className={cardClasses}\n style={\n appendToBody\n ? {\n position: 'fixed',\n top: resolved.top,\n left: resolved.left,\n }\n : undefined\n }\n >\n {children}\n </div>\n </PopupPortal>\n )}\n </span>\n );\n};\n\nexport default HoverCard;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.js","sources":["../../../src/components/Tabs.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n useCallback,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { isElementOf } from '../helpers/elementType';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { warnDeprecatedColorProp } from '../helpers/colorDeprecations';\nimport { Icon } from '../elements/Icon';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabRecord {\n index: number;\n id: string;\n disabled: boolean;\n}\n\ninterface PanelRecord {\n index: number;\n id: string;\n}\n\ninterface TabsContextValue {\n activeTab: number;\n setActiveTab: (index: number) => void;\n /** Prefix for the ids the tabs and panels generate. */\n baseId: string;\n /** The tab that holds `tabIndex={0}`, or `null` when every tab is disabled. */\n tabStop: number | null;\n /** Records which tab has focus, so the tab stop can follow it. */\n setFocusedTab: (index: number | null) => void;\n /** The id of the mounted tab for `index`, for its panel's `aria-labelledby`. */\n tabId: (index: number) => string | undefined;\n /** The id of the mounted panel for `index`, for its tab's `aria-controls`. */\n panelId: (index: number) => string | undefined;\n registerTab: (record: TabRecord) => () => void;\n registerPanel: (record: PanelRecord) => () => void;\n orientation: 'horizontal' | 'vertical';\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue | null {\n return useContext(TabsContext);\n}\n\n/**\n * The tabs and panels currently mounted under one `Tabs`. Each registers from\n * an effect and removes itself on cleanup, so the links between them only\n * ever name elements that exist, wherever in the tree the panels sit.\n */\nfunction useRegistry<T>(): [T[], (record: T) => () => void] {\n const [records, setRecords] = useState<T[]>([]);\n const register = useCallback((record: T) => {\n setRecords(prev => [...prev, record]);\n return () => setRecords(prev => prev.filter(r => r !== record));\n }, []);\n return [records, register];\n}\n\n/**\n * The list a tab belongs to: its `role=\"tablist\"` ancestor, so an element\n * wrapped around a tab doesn't cut it off from the others, or its parent when\n * it sits outside a tab list.\n */\nfunction tabListOf(tab: HTMLElement): HTMLElement {\n return (tab.closest('[role=\"tablist\"]') ?? tab.parentElement) as HTMLElement;\n}\n\n/**\n * The tab a key press moves focus to, found among the tabs of the same list\n * in DOM order, skipping disabled ones and wrapping at either end.\n * `undefined` for a key the tab list does not handle, or when no enabled tab\n * is left to go to.\n */\nfunction findTargetTab(\n current: HTMLElement,\n key: string,\n vertical: boolean\n): HTMLElement | undefined {\n const tabs = Array.from(\n tabListOf(current).querySelectorAll<HTMLElement>('[role=\"tab\"]')\n );\n const isEnabled = (el: HTMLElement) =>\n el.getAttribute('aria-disabled') !== 'true';\n\n if (key === 'Home') return tabs.find(isEnabled);\n if (key === 'End') return [...tabs].reverse().find(isEnabled);\n\n let step: number;\n if (key === 'ArrowRight' || (vertical && key === 'ArrowDown')) step = 1;\n else if (key === 'ArrowLeft' || (vertical && key === 'ArrowUp')) step = -1;\n else return undefined;\n\n const start = tabs.indexOf(current);\n for (let i = 1; i <= tabs.length; i++) {\n const candidate =\n tabs[(((start + step * i) % tabs.length) + tabs.length) % tabs.length];\n if (isEnabled(candidate)) return candidate;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the Tabs component.\n */\nexport interface TabsProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Tab alignment. */\n align?: 'centered' | 'right' | 'left';\n /** Tab size. */\n size?: 'small' | 'medium' | 'large';\n /** Tabs expand to fill the horizontal space. */\n isFullwidth?: boolean;\n /** Tabs expand to fill the horizontal space. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n isFullWidth?: boolean;\n /** Tabs expand to fill the horizontal space. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n fullwidth?: boolean;\n /** Tabs use the boxed style. */\n boxed?: boolean;\n /** Tabs use the toggle style. */\n toggle?: boolean;\n /** Tabs use the rounded toggle style (only with `toggle`). */\n rounded?: boolean;\n /**\n * Bulma color for tab underlines and active state (renders `is-<color>`).\n *\n * Bulma ships no tabs color CSS, so this prop has never had a visual effect\n * for any value. Passing it logs a console warning in development.\n * @deprecated No `.tabs.is-<color>` CSS exists; the prop renders unstyled\n * and will be removed in the next major version.\n */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Controlled active tab index. */\n value?: number;\n /**\n * Callback when active tab changes. Called with the tab's `index` when a\n * `Tabs.Tab` is activated: clicked, or Enter or Space pressed on it.\n * Moving focus with the arrow keys, Home or End does not call it, because\n * activation is manual: focus moves freely and the selected tab changes\n * only when the user picks one.\n */\n onChange?: (index: number) => void;\n /** Initial active tab index (uncontrolled). */\n defaultValue?: number;\n /**\n * Renders tabs vertically. With a `Tabs.Content`, the tab list is also\n * marked `aria-orientation=\"vertical\"` and ArrowUp and ArrowDown move focus\n * between tabs, alongside ArrowLeft and ArrowRight (the layout stacks\n * horizontally on mobile).\n */\n vertical?: boolean;\n /** Side placement when `vertical` is true. */\n side?: 'left' | 'right';\n /** Makes tabs take up the full width equally. */\n expanded?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Tab list and tab items. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Tabs` component provides flexible and fully-featured Bulma tab navigation for your Bulma React UI.\n *\n * Built from `Tabs.Tab`, the tabs follow the WAI-ARIA tabs pattern with\n * manual activation: the tab list is a single tab stop, the arrow keys, Home\n * and End move focus between tabs (skipping disabled ones), and Enter or\n * Space activates the focused tab. Each tab names its `Tabs.Content.Item` in\n * `aria-controls`, and each panel names its tab in `aria-labelledby`. Built\n * from `Tabs.Item` with links inside, the tabs stay plain Bulma navigation.\n *\n * @function\n * @param {TabsProps} props - Props for the Tabs component.\n * @returns {JSX.Element} The rendered tabs component.\n * @see {@link https://bulma.io/documentation/components/tabs/ | Bulma Tabs documentation}\n *\n * @example\n * // Basic tabs\n * <Tabs>\n * <Tabs.List>\n * <Tabs.Tab index={0}>Pictures</Tabs.Tab>\n * <Tabs.Tab index={1}>Music</Tabs.Tab>\n * </Tabs.List>\n * <Tabs.Content>\n * <Tabs.Content.Item index={0}>Pictures content</Tabs.Content.Item>\n * <Tabs.Content.Item index={1}>Music content</Tabs.Content.Item>\n * </Tabs.Content>\n * </Tabs>\n */\nconst TabsComponent: React.FC<TabsProps> = ({\n align,\n size,\n isFullwidth,\n isFullWidth,\n fullwidth,\n boxed,\n toggle,\n rounded,\n color,\n value,\n onChange,\n defaultValue = 0,\n vertical,\n side,\n expanded,\n className,\n children,\n ...props\n}) => {\n warnDeprecatedColorProp(\n 'Tabs',\n color,\n 'Remove the prop; no replacement exists.'\n );\n\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n // Controlled vs uncontrolled state\n const isControlled = value !== undefined;\n const [internalTab, setInternalTab] = useState(defaultValue);\n const activeTab = isControlled ? value : internalTab;\n\n const setActiveTab = useCallback(\n (index: number) => {\n if (!isControlled) {\n setInternalTab(index);\n }\n onChange?.(index);\n },\n [isControlled, onChange]\n );\n\n const baseId = useId();\n const [tabs, registerTab] = useRegistry<TabRecord>();\n const [panels, registerPanel] = useRegistry<PanelRecord>();\n const [focusedTab, setFocusedTab] = useState<number | null>(null);\n\n // One tab stop for the whole list (roving tabindex). While focus is inside\n // the list the stop follows it, so Tab and Shift+Tab leave the list from\n // whichever tab has focus; once focus leaves, the stop is the selected tab\n // again. A disabled tab never holds it, and when the selected tab is\n // disabled or missing the enabled tab with the lowest index does, so the\n // list can always be reached. Before the tabs register (the server render\n // and the first client render), the selected tab holds it. The registry is\n // in the order the tabs last registered, which a tab changing its\n // `disabled` or `id` reshuffles, hence the sort.\n const enabledTabs = tabs\n .filter(t => !t.disabled)\n .sort((a, b) => a.index - b.index);\n const canHoldStop = (index: number | null) =>\n enabledTabs.some(t => t.index === index);\n let tabStop: number | null;\n if (canHoldStop(focusedTab)) tabStop = focusedTab;\n else if (tabs.length === 0 || canHoldStop(activeTab)) tabStop = activeTab;\n else tabStop = enabledTabs.length > 0 ? enabledTabs[0].index : null;\n\n // Check if children include TabsContent\n const childArray = React.Children.toArray(children);\n const hasContent = childArray.some(child => isElementOf(child, TabsContent));\n\n const contextValue: TabsContextValue = {\n activeTab,\n setActiveTab,\n baseId,\n tabStop,\n setFocusedTab,\n tabId: index => tabs.find(t => t.index === index)?.id,\n panelId: index => panels.find(p => p.index === index)?.id,\n registerTab,\n registerPanel,\n orientation: hasContent && vertical ? 'vertical' : 'horizontal',\n };\n\n // Build classes for the .tabs div\n const tabsClasses = usePrefixedClassNames('tabs', {\n [`is-${align}`]: align,\n [`is-${size}`]: size,\n [`is-${color}`]: color,\n 'is-fullwidth': isFullwidth ?? isFullWidth ?? fullwidth,\n 'is-boxed': boxed,\n 'is-toggle': toggle,\n 'is-toggle-rounded': rounded,\n });\n\n // Hoisted unconditionally to respect rules-of-hooks. Modifiers gate themselves\n // via their truthy values — `tabs-root` is always prefixed, modifiers only\n // apply in the vertical-with-content branch.\n const rootClasses = usePrefixedClassNames('tabs-root', {\n 'is-vertical': hasContent && vertical,\n 'is-right': hasContent && vertical && side === 'right',\n 'is-expanded': hasContent && vertical && expanded,\n });\n\n if (hasContent && vertical) {\n const combinedRootClasses = classNames(\n rootClasses,\n bulmaHelperClasses,\n className\n );\n\n // Split children into list-like and content children\n const listChildren: React.ReactNode[] = [];\n const contentChildren: React.ReactNode[] = [];\n childArray.forEach(child => {\n if (isElementOf(child, TabsContent)) {\n contentChildren.push(child);\n } else {\n listChildren.push(child);\n }\n });\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedRootClasses} {...rest}>\n <div className={tabsClasses}>{listChildren}</div>\n {contentChildren}\n </div>\n </TabsContext.Provider>\n );\n }\n\n if (hasContent) {\n const combinedRootClasses = classNames(\n rootClasses,\n bulmaHelperClasses,\n className\n );\n\n const listChildren: React.ReactNode[] = [];\n const contentChildren: React.ReactNode[] = [];\n childArray.forEach(child => {\n if (isElementOf(child, TabsContent)) {\n contentChildren.push(child);\n } else {\n listChildren.push(child);\n }\n });\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedRootClasses} {...rest}>\n <div className={tabsClasses}>{listChildren}</div>\n {contentChildren}\n </div>\n </TabsContext.Provider>\n );\n }\n\n // No content children — backward compatible single .tabs div\n const combinedClasses = classNames(\n tabsClasses,\n bulmaHelperClasses,\n className\n );\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedClasses} {...rest}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabList\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabList component.\n */\nexport interface TabListProps extends React.HTMLAttributes<HTMLUListElement> {\n /** Additional CSS classes. */\n className?: string;\n /** Tab elements. */\n children?: React.ReactNode;\n}\n\n/**\n * The `<ul>` container for tab items.\n *\n * @function\n * @param {TabListProps} props - Props for the TabList component.\n * @returns {JSX.Element} The rendered tab list.\n */\nexport const TabList: React.FC<TabListProps> = ({\n className,\n children,\n ...props\n}) => {\n const ctx = useTabsContext();\n return (\n <ul\n role=\"tablist\"\n aria-orientation={\n ctx?.orientation === 'vertical' ? 'vertical' : undefined\n }\n className={classNames(className) || undefined}\n {...props}\n >\n {children}\n </ul>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Tab (new — context-aware)\n// ---------------------------------------------------------------------------\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Props for the Tab component.\n * @extraProp {string} [id] - The tab's id, which its panel names in `aria-labelledby`. Generated inside a `Tabs` when omitted; a passed `id` is used and the panel follows it.\n * @extraProp {React.KeyboardEventHandler<HTMLLIElement>} [onKeyDown] - Called before the tab handles the key; call `event.preventDefault()` to stop the tab handling it.\n */\nexport interface TabProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'onClick'\n> {\n /** **Required.** Tab index for matching with content. */\n index: number;\n /**\n * Disables the tab. A disabled tab is marked `aria-disabled`, cannot be\n * activated, is skipped by the arrow keys, Home and End, and never holds\n * the tab list's tab stop. The bestax extras styles also dim it and turn\n * off its hover.\n */\n disabled?: boolean;\n /** Icon name for the tab. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined', 'rounded'). */\n iconVariant?: string;\n /** Size of the tab icon. */\n iconSize?: 'small' | 'medium' | 'large';\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Additional CSS classes. */\n className?: string;\n /** Tab label content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual tab button. Consumes Tabs context for active state management.\n * Renders `<a>` internally — consumers provide only the label text/children.\n * Inside a `Tabs` it takes part in the tab list's keyboard support and links\n * to the `Tabs.Content.Item` with the same `index`.\n *\n * @function\n * @param {TabProps} props - Props for the Tab component.\n * @returns {JSX.Element} The rendered tab.\n */\nexport const Tab: React.FC<TabProps> = ({\n index,\n disabled,\n icon,\n iconLibrary,\n iconVariant,\n iconSize = 'small',\n iconFeatures,\n className,\n children,\n id,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n}) => {\n const ctx = useTabsContext();\n const isActive = ctx ? ctx.activeTab === index : false;\n const anchorRef = useRef<HTMLAnchorElement>(null);\n\n const activeClass = usePrefixedClassNames({ 'is-active': isActive });\n\n const tabId = id ?? (ctx ? `${ctx.baseId}-tab-${index}` : undefined);\n const registerTab = ctx?.registerTab;\n useEffect(() => {\n if (!registerTab || tabId === undefined) return undefined;\n return registerTab({ index, id: tabId, disabled: !!disabled });\n }, [registerTab, index, tabId, disabled]);\n\n // Outside a Tabs there is no list to rove, so every enabled tab stays in\n // the page tab order, as it always did.\n let tabIndex: number;\n if (disabled) tabIndex = -1;\n else if (ctx) tabIndex = ctx.tabStop === index ? 0 : -1;\n else tabIndex = 0;\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n if (!disabled && ctx) {\n ctx.setActiveTab(index);\n }\n },\n [disabled, ctx, index]\n );\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLLIElement>) => {\n onKeyDown?.(e);\n // A key on something inside the tab is that element's to answer.\n if (\n e.defaultPrevented ||\n e.target !== e.currentTarget ||\n e.altKey ||\n e.ctrlKey ||\n e.metaKey\n ) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n // Activate through a click on the inner <a>, the element a pointer\n // clicks, so click listeners see keyboard activation the way they see\n // a native button's.\n (anchorRef.current as HTMLAnchorElement).click();\n return;\n }\n const target = findTargetTab(\n e.currentTarget,\n e.key,\n ctx?.orientation === 'vertical'\n );\n if (target) {\n e.preventDefault();\n target.focus();\n }\n };\n\n const handleFocus = (e: React.FocusEvent<HTMLLIElement>) => {\n onFocus?.(e);\n ctx?.setFocusedTab(index);\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLLIElement>) => {\n onBlur?.(e);\n if (!tabListOf(e.currentTarget).contains(e.relatedTarget)) {\n ctx?.setFocusedTab(null);\n }\n };\n\n return (\n <li\n className={classNames(activeClass, className) || undefined}\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-controls={ctx?.panelId(index)}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n >\n <a\n ref={anchorRef}\n onClick={handleClick}\n aria-disabled={disabled || undefined}\n >\n {icon && (\n <Icon\n name={icon}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n )}\n {children && <span>{children}</span>}\n </a>\n </li>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabItem (backward-compatible — no context)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabItem component (backward-compatible).\n */\nexport interface TabItemProps extends React.LiHTMLAttributes<HTMLLIElement> {\n /** Whether the tab is active. */\n active?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Tab content. */\n children?: React.ReactNode;\n /** Click handler. */\n onClick?: React.MouseEventHandler<HTMLLIElement>;\n}\n\n/**\n * Each tab; accepts `active`, `onClick`, etc.\n *\n * @function\n * @param {TabItemProps} props - Props for the TabItem component.\n * @returns {JSX.Element} The rendered tab item.\n * @deprecated Use `Tabs.Tab` with an `index` prop instead.\n */\nexport const TabItem: React.FC<TabItemProps> = ({\n active,\n className,\n children,\n onClick,\n ...props\n}) => (\n <li\n className={\n classNames({ [usePrefixedClassNames('is-active')]: active }, className) ||\n undefined\n }\n onClick={onClick}\n {...props}\n >\n {children}\n </li>\n);\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabsContent component.\n */\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n /** TabContentItem elements. */\n children?: React.ReactNode;\n}\n\n/**\n * Container for tab content panels. No custom props beyond `children` and standard `<div>` HTML attributes. Applies the `.tabs-content` class.\n *\n * @function\n * @param {TabsContentProps} props - Props for the TabsContent component.\n * @returns {JSX.Element} The rendered tabs content wrapper.\n */\nconst TabsContentComponent: React.FC<TabsContentProps> = ({\n className,\n children,\n ...props\n}) => {\n const contentClass = usePrefixedClassNames('tabs-content');\n return (\n <div className={classNames(contentClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabContentItem\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabContentItem component.\n * @extraProp {string} [id] - The panel's id, which its tab names in `aria-controls`. Generated inside a `Tabs` when omitted; a passed `id` is used and the tab follows it.\n * @extraProp {number} [tabIndex] - The panel is not focusable by default. Pass `0` when it holds nothing focusable, so Tab moves from the tab list into it.\n */\nexport interface TabContentItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** **Required.** Tab index for matching with content. */\n index: number;\n /** Additional CSS classes. */\n className?: string;\n /** Panel content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual content panel. Shows/hides based on active tab from context.\n *\n * @function\n * @param {TabContentItemProps} props - Props for the TabContentItem component.\n * @returns {JSX.Element} The rendered tab content panel.\n */\nexport const TabContentItem: React.FC<TabContentItemProps> = ({\n index,\n className,\n children,\n id,\n ...props\n}) => {\n const ctx = useTabsContext();\n const isActive = ctx ? ctx.activeTab === index : false;\n\n const itemClass = usePrefixedClassNames('tabs-content-item', {\n 'is-active': isActive,\n });\n\n const panelId = id ?? (ctx ? `${ctx.baseId}-panel-${index}` : undefined);\n const registerPanel = ctx?.registerPanel;\n useEffect(() => {\n if (!registerPanel || panelId === undefined) return undefined;\n return registerPanel({ index, id: panelId });\n }, [registerPanel, index, panelId]);\n\n return (\n <div\n className={classNames(itemClass, className)}\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={ctx?.tabId(index)}\n aria-hidden={!isActive}\n {...props}\n >\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Static property attachment\n// ---------------------------------------------------------------------------\n\nexport const TabsContent = withSubComponents(TabsContentComponent, {\n Item: TabContentItem,\n});\n\nexport const Tabs = withSubComponents(\n TabsComponent,\n {\n List: TabList,\n Tab,\n Item: TabItem,\n Content: TabsContent,\n },\n 'Tabs'\n);\n\nexport default Tabs;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Tabs.js","sources":["../../../src/components/Tabs.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n useCallback,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { isElementOf } from '../helpers/elementType';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { warnDeprecatedColorProp } from '../helpers/colorDeprecations';\nimport { Icon } from '../elements/Icon';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface TabRecord {\n index: number;\n id: string;\n disabled: boolean;\n}\n\ninterface PanelRecord {\n index: number;\n id: string;\n}\n\ninterface TabsContextValue {\n activeTab: number;\n setActiveTab: (index: number) => void;\n /** Prefix for the ids the tabs and panels generate. */\n baseId: string;\n /** The tab that holds `tabIndex={0}`, or `null` when every tab is disabled. */\n tabStop: number | null;\n /** Records which tab has focus, so the tab stop can follow it. */\n setFocusedTab: (index: number | null) => void;\n /** The id of the mounted tab for `index`, for its panel's `aria-labelledby`. */\n tabId: (index: number) => string | undefined;\n /** The id of the mounted panel for `index`, for its tab's `aria-controls`. */\n panelId: (index: number) => string | undefined;\n registerTab: (record: TabRecord) => () => void;\n registerPanel: (record: PanelRecord) => () => void;\n orientation: 'horizontal' | 'vertical';\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue | null {\n return useContext(TabsContext);\n}\n\n/**\n * The tabs and panels currently mounted under one `Tabs`. Each registers from\n * an effect and removes itself on cleanup, so the links between them only\n * ever name elements that exist, wherever in the tree the panels sit.\n */\nfunction useRegistry<T>(): [T[], (record: T) => () => void] {\n const [records, setRecords] = useState<T[]>([]);\n const register = useCallback((record: T) => {\n setRecords(prev => [...prev, record]);\n return () => setRecords(prev => prev.filter(r => r !== record));\n }, []);\n return [records, register];\n}\n\n/**\n * The list a tab belongs to: its `role=\"tablist\"` ancestor, so an element\n * wrapped around a tab doesn't cut it off from the others, or its parent when\n * it sits outside a tab list.\n */\nfunction tabListOf(tab: HTMLElement): HTMLElement {\n return (tab.closest('[role=\"tablist\"]') ?? tab.parentElement) as HTMLElement;\n}\n\n/**\n * The tab a key press moves focus to, found among the tabs of the same list\n * in DOM order, skipping disabled ones and wrapping at either end.\n * `undefined` for a key the tab list does not handle, or when no enabled tab\n * is left to go to.\n */\nfunction findTargetTab(\n current: HTMLElement,\n key: string,\n vertical: boolean\n): HTMLElement | undefined {\n const tabs = Array.from(\n tabListOf(current).querySelectorAll<HTMLElement>('[role=\"tab\"]')\n );\n const isEnabled = (el: HTMLElement) =>\n el.getAttribute('aria-disabled') !== 'true';\n\n if (key === 'Home') return tabs.find(isEnabled);\n if (key === 'End') return [...tabs].reverse().find(isEnabled);\n\n let step: number;\n if (key === 'ArrowRight' || (vertical && key === 'ArrowDown')) step = 1;\n else if (key === 'ArrowLeft' || (vertical && key === 'ArrowUp')) step = -1;\n else return undefined;\n\n const start = tabs.indexOf(current);\n for (let i = 1; i <= tabs.length; i++) {\n const candidate =\n tabs[(((start + step * i) % tabs.length) + tabs.length) % tabs.length];\n if (isEnabled(candidate)) return candidate;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Tabs (root)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the Tabs component.\n */\nexport interface TabsProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Tab alignment. */\n align?: 'centered' | 'right' | 'left';\n /** Tab size. */\n size?: 'small' | 'medium' | 'large';\n /** Tabs expand to fill the horizontal space. */\n isFullwidth?: boolean;\n /** Tabs expand to fill the horizontal space. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n isFullWidth?: boolean;\n /** Tabs expand to fill the horizontal space. @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n fullwidth?: boolean;\n /** Tabs use the boxed style. */\n boxed?: boolean;\n /** Tabs use the toggle style. */\n toggle?: boolean;\n /** Tabs use the rounded toggle style (only with `toggle`). */\n rounded?: boolean;\n /**\n * Bulma color for tab underlines and active state (renders `is-<color>`).\n *\n * Bulma ships no tabs color CSS, so this prop has never had a visual effect\n * for any value. Passing it logs a console warning in development.\n * @deprecated No `.tabs.is-<color>` CSS exists; the prop renders unstyled\n * and will be removed in the next major version.\n */\n color?:\n | 'primary'\n | 'link'\n | 'info'\n | 'success'\n | 'warning'\n | 'danger'\n | 'black'\n | 'dark'\n | 'light'\n | 'white';\n /** Controlled active tab index. */\n value?: number;\n /**\n * Callback when active tab changes. Called with the tab's `index` when a\n * `Tabs.Tab` is activated: clicked, or Enter or Space pressed on it.\n * Moving focus with the arrow keys, Home or End does not call it, because\n * activation is manual: focus moves freely and the selected tab changes\n * only when the user picks one.\n */\n onChange?: (index: number) => void;\n /** Initial active tab index (uncontrolled). */\n defaultValue?: number;\n /**\n * Renders tabs vertically. With a `Tabs.Content`, the tab list is also\n * marked `aria-orientation=\"vertical\"` and ArrowUp and ArrowDown move focus\n * between tabs, alongside ArrowLeft and ArrowRight (the layout stacks\n * horizontally on mobile).\n */\n vertical?: boolean;\n /**\n * Side placement when `vertical` is true. The row follows the page's\n * direction, so on a right-to-left page `left` puts the tabs at the right,\n * where the line starts, and `right` puts them at the left.\n */\n side?: 'left' | 'right';\n /** Makes tabs take up the full width equally. */\n expanded?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Tab list and tab items. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Tabs` component provides flexible and fully-featured Bulma tab navigation for your Bulma React UI.\n *\n * Built from `Tabs.Tab`, the tabs follow the WAI-ARIA tabs pattern with\n * manual activation: the tab list is a single tab stop, the arrow keys, Home\n * and End move focus between tabs (skipping disabled ones), and Enter or\n * Space activates the focused tab. Each tab names its `Tabs.Content.Item` in\n * `aria-controls`, and each panel names its tab in `aria-labelledby`. Built\n * from `Tabs.Item` with links inside, the tabs stay plain Bulma navigation.\n *\n * @function\n * @param {TabsProps} props - Props for the Tabs component.\n * @returns {JSX.Element} The rendered tabs component.\n * @see {@link https://bulma.io/documentation/components/tabs/ | Bulma Tabs documentation}\n *\n * @example\n * // Basic tabs\n * <Tabs>\n * <Tabs.List>\n * <Tabs.Tab index={0}>Pictures</Tabs.Tab>\n * <Tabs.Tab index={1}>Music</Tabs.Tab>\n * </Tabs.List>\n * <Tabs.Content>\n * <Tabs.Content.Item index={0}>Pictures content</Tabs.Content.Item>\n * <Tabs.Content.Item index={1}>Music content</Tabs.Content.Item>\n * </Tabs.Content>\n * </Tabs>\n */\nconst TabsComponent: React.FC<TabsProps> = ({\n align,\n size,\n isFullwidth,\n isFullWidth,\n fullwidth,\n boxed,\n toggle,\n rounded,\n color,\n value,\n onChange,\n defaultValue = 0,\n vertical,\n side,\n expanded,\n className,\n children,\n ...props\n}) => {\n warnDeprecatedColorProp(\n 'Tabs',\n color,\n 'Remove the prop; no replacement exists.'\n );\n\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n // Controlled vs uncontrolled state\n const isControlled = value !== undefined;\n const [internalTab, setInternalTab] = useState(defaultValue);\n const activeTab = isControlled ? value : internalTab;\n\n const setActiveTab = useCallback(\n (index: number) => {\n if (!isControlled) {\n setInternalTab(index);\n }\n onChange?.(index);\n },\n [isControlled, onChange]\n );\n\n const baseId = useId();\n const [tabs, registerTab] = useRegistry<TabRecord>();\n const [panels, registerPanel] = useRegistry<PanelRecord>();\n const [focusedTab, setFocusedTab] = useState<number | null>(null);\n\n // One tab stop for the whole list (roving tabindex). While focus is inside\n // the list the stop follows it, so Tab and Shift+Tab leave the list from\n // whichever tab has focus; once focus leaves, the stop is the selected tab\n // again. A disabled tab never holds it, and when the selected tab is\n // disabled or missing the enabled tab with the lowest index does, so the\n // list can always be reached. Before the tabs register (the server render\n // and the first client render), the selected tab holds it. The registry is\n // in the order the tabs last registered, which a tab changing its\n // `disabled` or `id` reshuffles, hence the sort.\n const enabledTabs = tabs\n .filter(t => !t.disabled)\n .sort((a, b) => a.index - b.index);\n const canHoldStop = (index: number | null) =>\n enabledTabs.some(t => t.index === index);\n let tabStop: number | null;\n if (canHoldStop(focusedTab)) tabStop = focusedTab;\n else if (tabs.length === 0 || canHoldStop(activeTab)) tabStop = activeTab;\n else tabStop = enabledTabs.length > 0 ? enabledTabs[0].index : null;\n\n // Check if children include TabsContent\n const childArray = React.Children.toArray(children);\n const hasContent = childArray.some(child => isElementOf(child, TabsContent));\n\n const contextValue: TabsContextValue = {\n activeTab,\n setActiveTab,\n baseId,\n tabStop,\n setFocusedTab,\n tabId: index => tabs.find(t => t.index === index)?.id,\n panelId: index => panels.find(p => p.index === index)?.id,\n registerTab,\n registerPanel,\n orientation: hasContent && vertical ? 'vertical' : 'horizontal',\n };\n\n // Build classes for the .tabs div\n const tabsClasses = usePrefixedClassNames('tabs', {\n [`is-${align}`]: align,\n [`is-${size}`]: size,\n [`is-${color}`]: color,\n 'is-fullwidth': isFullwidth ?? isFullWidth ?? fullwidth,\n 'is-boxed': boxed,\n 'is-toggle': toggle,\n 'is-toggle-rounded': rounded,\n });\n\n // Hoisted unconditionally to respect rules-of-hooks. Modifiers gate themselves\n // via their truthy values — `tabs-root` is always prefixed, modifiers only\n // apply in the vertical-with-content branch.\n const rootClasses = usePrefixedClassNames('tabs-root', {\n 'is-vertical': hasContent && vertical,\n 'is-right': hasContent && vertical && side === 'right',\n 'is-expanded': hasContent && vertical && expanded,\n });\n\n if (hasContent && vertical) {\n const combinedRootClasses = classNames(\n rootClasses,\n bulmaHelperClasses,\n className\n );\n\n // Split children into list-like and content children\n const listChildren: React.ReactNode[] = [];\n const contentChildren: React.ReactNode[] = [];\n childArray.forEach(child => {\n if (isElementOf(child, TabsContent)) {\n contentChildren.push(child);\n } else {\n listChildren.push(child);\n }\n });\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedRootClasses} {...rest}>\n <div className={tabsClasses}>{listChildren}</div>\n {contentChildren}\n </div>\n </TabsContext.Provider>\n );\n }\n\n if (hasContent) {\n const combinedRootClasses = classNames(\n rootClasses,\n bulmaHelperClasses,\n className\n );\n\n const listChildren: React.ReactNode[] = [];\n const contentChildren: React.ReactNode[] = [];\n childArray.forEach(child => {\n if (isElementOf(child, TabsContent)) {\n contentChildren.push(child);\n } else {\n listChildren.push(child);\n }\n });\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedRootClasses} {...rest}>\n <div className={tabsClasses}>{listChildren}</div>\n {contentChildren}\n </div>\n </TabsContext.Provider>\n );\n }\n\n // No content children — backward compatible single .tabs div\n const combinedClasses = classNames(\n tabsClasses,\n bulmaHelperClasses,\n className\n );\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={combinedClasses} {...rest}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabList\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabList component.\n */\nexport interface TabListProps extends React.HTMLAttributes<HTMLUListElement> {\n /** Additional CSS classes. */\n className?: string;\n /** Tab elements. */\n children?: React.ReactNode;\n}\n\n/**\n * The `<ul>` container for tab items.\n *\n * @function\n * @param {TabListProps} props - Props for the TabList component.\n * @returns {JSX.Element} The rendered tab list.\n */\nexport const TabList: React.FC<TabListProps> = ({\n className,\n children,\n ...props\n}) => {\n const ctx = useTabsContext();\n return (\n <ul\n role=\"tablist\"\n aria-orientation={\n ctx?.orientation === 'vertical' ? 'vertical' : undefined\n }\n className={classNames(className) || undefined}\n {...props}\n >\n {children}\n </ul>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Tab (new — context-aware)\n// ---------------------------------------------------------------------------\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Props for the Tab component.\n * @extraProp {string} [id] - The tab's id, which its panel names in `aria-labelledby`. Generated inside a `Tabs` when omitted; a passed `id` is used and the panel follows it.\n * @extraProp {React.KeyboardEventHandler<HTMLLIElement>} [onKeyDown] - Called before the tab handles the key; call `event.preventDefault()` to stop the tab handling it.\n */\nexport interface TabProps extends Omit<\n React.LiHTMLAttributes<HTMLLIElement>,\n 'onClick'\n> {\n /** **Required.** Tab index for matching with content. */\n index: number;\n /**\n * Disables the tab. A disabled tab is marked `aria-disabled`, cannot be\n * activated, is skipped by the arrow keys, Home and End, and never holds\n * the tab list's tab stop. The bestax extras styles also dim it and turn\n * off its hover.\n */\n disabled?: boolean;\n /** Icon name for the tab. */\n icon?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined', 'rounded'). */\n iconVariant?: string;\n /** Size of the tab icon. */\n iconSize?: 'small' | 'medium' | 'large';\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Additional CSS classes. */\n className?: string;\n /** Tab label content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual tab button. Consumes Tabs context for active state management.\n * Renders `<a>` internally — consumers provide only the label text/children.\n * Inside a `Tabs` it takes part in the tab list's keyboard support and links\n * to the `Tabs.Content.Item` with the same `index`.\n *\n * @function\n * @param {TabProps} props - Props for the Tab component.\n * @returns {JSX.Element} The rendered tab.\n */\nexport const Tab: React.FC<TabProps> = ({\n index,\n disabled,\n icon,\n iconLibrary,\n iconVariant,\n iconSize = 'small',\n iconFeatures,\n className,\n children,\n id,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n}) => {\n const ctx = useTabsContext();\n const isActive = ctx ? ctx.activeTab === index : false;\n const anchorRef = useRef<HTMLAnchorElement>(null);\n\n const activeClass = usePrefixedClassNames({ 'is-active': isActive });\n\n const tabId = id ?? (ctx ? `${ctx.baseId}-tab-${index}` : undefined);\n const registerTab = ctx?.registerTab;\n useEffect(() => {\n if (!registerTab || tabId === undefined) return undefined;\n return registerTab({ index, id: tabId, disabled: !!disabled });\n }, [registerTab, index, tabId, disabled]);\n\n // Outside a Tabs there is no list to rove, so every enabled tab stays in\n // the page tab order, as it always did.\n let tabIndex: number;\n if (disabled) tabIndex = -1;\n else if (ctx) tabIndex = ctx.tabStop === index ? 0 : -1;\n else tabIndex = 0;\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n if (!disabled && ctx) {\n ctx.setActiveTab(index);\n }\n },\n [disabled, ctx, index]\n );\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLLIElement>) => {\n onKeyDown?.(e);\n // A key on something inside the tab is that element's to answer.\n if (\n e.defaultPrevented ||\n e.target !== e.currentTarget ||\n e.altKey ||\n e.ctrlKey ||\n e.metaKey\n ) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n // Activate through a click on the inner <a>, the element a pointer\n // clicks, so click listeners see keyboard activation the way they see\n // a native button's.\n (anchorRef.current as HTMLAnchorElement).click();\n return;\n }\n const target = findTargetTab(\n e.currentTarget,\n e.key,\n ctx?.orientation === 'vertical'\n );\n if (target) {\n e.preventDefault();\n target.focus();\n }\n };\n\n const handleFocus = (e: React.FocusEvent<HTMLLIElement>) => {\n onFocus?.(e);\n ctx?.setFocusedTab(index);\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLLIElement>) => {\n onBlur?.(e);\n if (!tabListOf(e.currentTarget).contains(e.relatedTarget)) {\n ctx?.setFocusedTab(null);\n }\n };\n\n return (\n <li\n className={classNames(activeClass, className) || undefined}\n role=\"tab\"\n id={tabId}\n aria-selected={isActive}\n aria-controls={ctx?.panelId(index)}\n aria-disabled={disabled || undefined}\n tabIndex={tabIndex}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n >\n <a\n ref={anchorRef}\n onClick={handleClick}\n aria-disabled={disabled || undefined}\n >\n {icon && (\n <Icon\n name={icon}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n )}\n {children && <span>{children}</span>}\n </a>\n </li>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabItem (backward-compatible — no context)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabItem component (backward-compatible).\n */\nexport interface TabItemProps extends React.LiHTMLAttributes<HTMLLIElement> {\n /** Whether the tab is active. */\n active?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Tab content. */\n children?: React.ReactNode;\n /** Click handler. */\n onClick?: React.MouseEventHandler<HTMLLIElement>;\n}\n\n/**\n * Each tab; accepts `active`, `onClick`, etc.\n *\n * @function\n * @param {TabItemProps} props - Props for the TabItem component.\n * @returns {JSX.Element} The rendered tab item.\n * @deprecated Use `Tabs.Tab` with an `index` prop instead.\n */\nexport const TabItem: React.FC<TabItemProps> = ({\n active,\n className,\n children,\n onClick,\n ...props\n}) => (\n <li\n className={\n classNames({ [usePrefixedClassNames('is-active')]: active }, className) ||\n undefined\n }\n onClick={onClick}\n {...props}\n >\n {children}\n </li>\n);\n\n// ---------------------------------------------------------------------------\n// TabsContent\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabsContent component.\n */\nexport interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n /** TabContentItem elements. */\n children?: React.ReactNode;\n}\n\n/**\n * Container for tab content panels. No custom props beyond `children` and standard `<div>` HTML attributes. Applies the `.tabs-content` class.\n *\n * @function\n * @param {TabsContentProps} props - Props for the TabsContent component.\n * @returns {JSX.Element} The rendered tabs content wrapper.\n */\nconst TabsContentComponent: React.FC<TabsContentProps> = ({\n className,\n children,\n ...props\n}) => {\n const contentClass = usePrefixedClassNames('tabs-content');\n return (\n <div className={classNames(contentClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// TabContentItem\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the TabContentItem component.\n * @extraProp {string} [id] - The panel's id, which its tab names in `aria-controls`. Generated inside a `Tabs` when omitted; a passed `id` is used and the tab follows it.\n * @extraProp {number} [tabIndex] - The panel is not focusable by default. Pass `0` when it holds nothing focusable, so Tab moves from the tab list into it.\n */\nexport interface TabContentItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** **Required.** Tab index for matching with content. */\n index: number;\n /** Additional CSS classes. */\n className?: string;\n /** Panel content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual content panel. Shows/hides based on active tab from context.\n *\n * @function\n * @param {TabContentItemProps} props - Props for the TabContentItem component.\n * @returns {JSX.Element} The rendered tab content panel.\n */\nexport const TabContentItem: React.FC<TabContentItemProps> = ({\n index,\n className,\n children,\n id,\n ...props\n}) => {\n const ctx = useTabsContext();\n const isActive = ctx ? ctx.activeTab === index : false;\n\n const itemClass = usePrefixedClassNames('tabs-content-item', {\n 'is-active': isActive,\n });\n\n const panelId = id ?? (ctx ? `${ctx.baseId}-panel-${index}` : undefined);\n const registerPanel = ctx?.registerPanel;\n useEffect(() => {\n if (!registerPanel || panelId === undefined) return undefined;\n return registerPanel({ index, id: panelId });\n }, [registerPanel, index, panelId]);\n\n return (\n <div\n className={classNames(itemClass, className)}\n role=\"tabpanel\"\n id={panelId}\n aria-labelledby={ctx?.tabId(index)}\n aria-hidden={!isActive}\n {...props}\n >\n {children}\n </div>\n );\n};\n\n// ---------------------------------------------------------------------------\n// Static property attachment\n// ---------------------------------------------------------------------------\n\nexport const TabsContent = withSubComponents(TabsContentComponent, {\n Item: TabContentItem,\n});\n\nexport const Tabs = withSubComponents(\n TabsComponent,\n {\n List: TabList,\n Tab,\n Item: TabItem,\n Content: TabsContent,\n },\n 'Tabs'\n);\n\nexport default Tabs;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|