@allxsmith/bestax-bulma 5.56.0 → 5.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/columns/Column.js +1 -0
- package/dist/esm/columns/Column.js.map +1 -1
- package/dist/esm/columns/Columns.js +1 -0
- package/dist/esm/columns/Columns.js.map +1 -1
- package/dist/esm/components/Avatar.js +1 -0
- package/dist/esm/components/Avatar.js.map +1 -1
- package/dist/esm/components/Avatars.js +1 -0
- package/dist/esm/components/Avatars.js.map +1 -1
- package/dist/esm/components/Badge.js +1 -0
- package/dist/esm/components/Badge.js.map +1 -1
- package/dist/esm/components/Breadcrumb.js +1 -0
- package/dist/esm/components/Breadcrumb.js.map +1 -1
- package/dist/esm/components/Card.js +1 -0
- package/dist/esm/components/Card.js.map +1 -1
- package/dist/esm/components/Carousel.js +1 -0
- package/dist/esm/components/Carousel.js.map +1 -1
- package/dist/esm/components/Collapse.js +1 -0
- package/dist/esm/components/Collapse.js.map +1 -1
- package/dist/esm/components/Collapses.js +1 -0
- package/dist/esm/components/Collapses.js.map +1 -1
- package/dist/esm/components/Command.js +1 -0
- package/dist/esm/components/Command.js.map +1 -1
- package/dist/esm/components/ContextMenu.js +1 -0
- package/dist/esm/components/ContextMenu.js.map +1 -1
- package/dist/esm/components/DataTable.js +1 -0
- package/dist/esm/components/DataTable.js.map +1 -1
- package/dist/esm/components/Dialog.js +1 -0
- package/dist/esm/components/Dialog.js.map +1 -1
- package/dist/esm/components/Dropdown.js +1 -0
- package/dist/esm/components/Dropdown.js.map +1 -1
- package/dist/esm/components/EmptyState.js +1 -0
- package/dist/esm/components/EmptyState.js.map +1 -1
- package/dist/esm/components/HoverCard.js +1 -0
- package/dist/esm/components/HoverCard.js.map +1 -1
- package/dist/esm/components/Loading.js +1 -0
- package/dist/esm/components/Loading.js.map +1 -1
- package/dist/esm/components/Menu.js +1 -0
- package/dist/esm/components/Menu.js.map +1 -1
- package/dist/esm/components/Message.js +1 -0
- package/dist/esm/components/Message.js.map +1 -1
- package/dist/esm/components/Modal.js +1 -0
- package/dist/esm/components/Modal.js.map +1 -1
- package/dist/esm/components/Navbar.js +1 -0
- package/dist/esm/components/Navbar.js.map +1 -1
- package/dist/esm/components/Pagination.js +1 -0
- package/dist/esm/components/Pagination.js.map +1 -1
- package/dist/esm/components/Panel.js +1 -0
- package/dist/esm/components/Panel.js.map +1 -1
- package/dist/esm/components/Popover.js +1 -0
- package/dist/esm/components/Popover.js.map +1 -1
- package/dist/esm/components/Reveal.js +1 -0
- package/dist/esm/components/Reveal.js.map +1 -1
- package/dist/esm/components/ScrollArea.js +1 -0
- package/dist/esm/components/ScrollArea.js.map +1 -1
- package/dist/esm/components/SegmentedControl.js +1 -0
- package/dist/esm/components/SegmentedControl.js.map +1 -1
- package/dist/esm/components/Sidebar.js +1 -0
- package/dist/esm/components/Sidebar.js.map +1 -1
- package/dist/esm/components/Steps.js +1 -0
- package/dist/esm/components/Steps.js.map +1 -1
- package/dist/esm/components/Tabs.js +1 -0
- package/dist/esm/components/Tabs.js.map +1 -1
- package/dist/esm/components/Timeline.js +1 -0
- package/dist/esm/components/Timeline.js.map +1 -1
- package/dist/esm/components/Toast.js +1 -0
- package/dist/esm/components/Toast.js.map +1 -1
- package/dist/esm/components/Tooltip.js +1 -0
- package/dist/esm/components/Tooltip.js.map +1 -1
- package/dist/esm/components/TreeView.js +1 -0
- package/dist/esm/components/TreeView.js.map +1 -1
- package/dist/esm/components/collapsesContext.js +1 -0
- package/dist/esm/components/collapsesContext.js.map +1 -1
- package/dist/esm/components/useDataTable.js +1 -0
- package/dist/esm/components/useDataTable.js.map +1 -1
- package/dist/esm/elements/Block.js +1 -0
- package/dist/esm/elements/Block.js.map +1 -1
- package/dist/esm/elements/Box.js +1 -0
- package/dist/esm/elements/Box.js.map +1 -1
- package/dist/esm/elements/Button.js +1 -0
- package/dist/esm/elements/Button.js.map +1 -1
- package/dist/esm/elements/Buttons.js +1 -0
- package/dist/esm/elements/Buttons.js.map +1 -1
- package/dist/esm/elements/Code.js +1 -0
- package/dist/esm/elements/Code.js.map +1 -1
- package/dist/esm/elements/ColorSwatch.js +1 -0
- package/dist/esm/elements/ColorSwatch.js.map +1 -1
- package/dist/esm/elements/Content.js +1 -0
- package/dist/esm/elements/Content.js.map +1 -1
- package/dist/esm/elements/Delete.js +1 -0
- package/dist/esm/elements/Delete.js.map +1 -1
- package/dist/esm/elements/DescriptionList.js +1 -0
- package/dist/esm/elements/DescriptionList.js.map +1 -1
- package/dist/esm/elements/Divider.js +1 -0
- package/dist/esm/elements/Divider.js.map +1 -1
- package/dist/esm/elements/Emphasis.js +1 -0
- package/dist/esm/elements/Emphasis.js.map +1 -1
- package/dist/esm/elements/Figure.js +1 -0
- package/dist/esm/elements/Figure.js.map +1 -1
- package/dist/esm/elements/Icon.js +1 -0
- package/dist/esm/elements/Icon.js.map +1 -1
- package/dist/esm/elements/IconText.js +1 -0
- package/dist/esm/elements/IconText.js.map +1 -1
- package/dist/esm/elements/Image.js +1 -0
- package/dist/esm/elements/Image.js.map +1 -1
- package/dist/esm/elements/Kbd.js +1 -0
- package/dist/esm/elements/Kbd.js.map +1 -1
- package/dist/esm/elements/Link.js +1 -0
- package/dist/esm/elements/Link.js.map +1 -1
- package/dist/esm/elements/LinkButton.js +1 -0
- package/dist/esm/elements/LinkButton.js.map +1 -1
- package/dist/esm/elements/ListItem.js +1 -0
- package/dist/esm/elements/ListItem.js.map +1 -1
- package/dist/esm/elements/Loader.js +1 -0
- package/dist/esm/elements/Loader.js.map +1 -1
- package/dist/esm/elements/Notification.js +1 -0
- package/dist/esm/elements/Notification.js.map +1 -1
- package/dist/esm/elements/OrderedList.js +1 -0
- package/dist/esm/elements/OrderedList.js.map +1 -1
- package/dist/esm/elements/Paragraph.js +1 -0
- package/dist/esm/elements/Paragraph.js.map +1 -1
- package/dist/esm/elements/Pre.js +1 -0
- package/dist/esm/elements/Pre.js.map +1 -1
- package/dist/esm/elements/Progress.js +1 -0
- package/dist/esm/elements/Progress.js.map +1 -1
- package/dist/esm/elements/RingProgress.js +1 -0
- package/dist/esm/elements/RingProgress.js.map +1 -1
- package/dist/esm/elements/Skeleton.js +1 -0
- package/dist/esm/elements/Skeleton.js.map +1 -1
- package/dist/esm/elements/Span.js +1 -0
- package/dist/esm/elements/Span.js.map +1 -1
- package/dist/esm/elements/Strong.js +1 -0
- package/dist/esm/elements/Strong.js.map +1 -1
- package/dist/esm/elements/SubTitle.js +1 -0
- package/dist/esm/elements/SubTitle.js.map +1 -1
- package/dist/esm/elements/Table.js +1 -0
- package/dist/esm/elements/Table.js.map +1 -1
- package/dist/esm/elements/Tag.js +1 -0
- package/dist/esm/elements/Tag.js.map +1 -1
- package/dist/esm/elements/Tags.js +1 -0
- package/dist/esm/elements/Tags.js.map +1 -1
- package/dist/esm/elements/Tbody.js +1 -0
- package/dist/esm/elements/Tbody.js.map +1 -1
- package/dist/esm/elements/Td.js +1 -0
- package/dist/esm/elements/Td.js.map +1 -1
- package/dist/esm/elements/Tfoot.js +1 -0
- package/dist/esm/elements/Tfoot.js.map +1 -1
- package/dist/esm/elements/Th.js +1 -0
- package/dist/esm/elements/Th.js.map +1 -1
- package/dist/esm/elements/Thead.js +1 -0
- package/dist/esm/elements/Thead.js.map +1 -1
- package/dist/esm/elements/Title.js +1 -0
- package/dist/esm/elements/Title.js.map +1 -1
- package/dist/esm/elements/ToggleButton.js +1 -0
- package/dist/esm/elements/ToggleButton.js.map +1 -1
- package/dist/esm/elements/Tr.js +1 -0
- package/dist/esm/elements/Tr.js.map +1 -1
- package/dist/esm/elements/UnorderedList.js +1 -0
- package/dist/esm/elements/UnorderedList.js.map +1 -1
- package/dist/esm/elements/iconProps.js +1 -0
- package/dist/esm/elements/iconProps.js.map +1 -1
- package/dist/esm/form/Autocomplete.js +1 -0
- package/dist/esm/form/Autocomplete.js.map +1 -1
- package/dist/esm/form/Checkbox.js +1 -0
- package/dist/esm/form/Checkbox.js.map +1 -1
- package/dist/esm/form/CheckboxCard.js +1 -0
- package/dist/esm/form/CheckboxCard.js.map +1 -1
- package/dist/esm/form/Checkboxes.js +1 -0
- package/dist/esm/form/Checkboxes.js.map +1 -1
- package/dist/esm/form/ColorInput.js +1 -0
- package/dist/esm/form/ColorInput.js.map +1 -1
- package/dist/esm/form/ColorInputBase.js +1 -0
- package/dist/esm/form/ColorInputBase.js.map +1 -1
- package/dist/esm/form/ColorPicker.js +1 -0
- package/dist/esm/form/ColorPicker.js.map +1 -1
- package/dist/esm/form/Combobox.js +1 -0
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/Control.js +1 -0
- package/dist/esm/form/Control.js.map +1 -1
- package/dist/esm/form/DateInput.js +1 -0
- package/dist/esm/form/DateInput.js.map +1 -1
- package/dist/esm/form/DateInputBase.js +1 -0
- package/dist/esm/form/DateInputBase.js.map +1 -1
- package/dist/esm/form/DateRangeInput.js +1 -0
- package/dist/esm/form/DateRangeInput.js.map +1 -1
- package/dist/esm/form/DateRangeInputBase.js +1 -0
- package/dist/esm/form/DateRangeInputBase.js.map +1 -1
- package/dist/esm/form/DateTimeInput.js +1 -0
- package/dist/esm/form/DateTimeInput.js.map +1 -1
- package/dist/esm/form/DateTimeInputBase.js +1 -0
- package/dist/esm/form/DateTimeInputBase.js.map +1 -1
- package/dist/esm/form/Dropzone.js +1 -0
- package/dist/esm/form/Dropzone.js.map +1 -1
- package/dist/esm/form/Field.js +1 -0
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/Fieldset.js +1 -0
- package/dist/esm/form/Fieldset.js.map +1 -1
- package/dist/esm/form/File.js +1 -0
- package/dist/esm/form/File.js.map +1 -1
- package/dist/esm/form/FormContext.js +1 -0
- package/dist/esm/form/FormContext.js.map +1 -1
- package/dist/esm/form/Input.js +1 -0
- package/dist/esm/form/Input.js.map +1 -1
- package/dist/esm/form/InputBase.js +1 -0
- package/dist/esm/form/InputBase.js.map +1 -1
- package/dist/esm/form/Numberinput.js +1 -0
- package/dist/esm/form/Numberinput.js.map +1 -1
- package/dist/esm/form/PinInput.js +1 -0
- package/dist/esm/form/PinInput.js.map +1 -1
- package/dist/esm/form/Radio.js +1 -0
- package/dist/esm/form/Radio.js.map +1 -1
- package/dist/esm/form/RadioCard.js +1 -0
- package/dist/esm/form/RadioCard.js.map +1 -1
- package/dist/esm/form/Radios.js +1 -0
- package/dist/esm/form/Radios.js.map +1 -1
- package/dist/esm/form/Rate.js +1 -0
- package/dist/esm/form/Rate.js.map +1 -1
- package/dist/esm/form/Select.js +1 -0
- package/dist/esm/form/Select.js.map +1 -1
- package/dist/esm/form/SelectBase.js +1 -0
- package/dist/esm/form/SelectBase.js.map +1 -1
- package/dist/esm/form/Slider.js +1 -0
- package/dist/esm/form/Slider.js.map +1 -1
- package/dist/esm/form/Switch.js +1 -0
- package/dist/esm/form/Switch.js.map +1 -1
- package/dist/esm/form/Taginput.js +1 -0
- package/dist/esm/form/Taginput.js.map +1 -1
- package/dist/esm/form/TextArea.js +1 -0
- package/dist/esm/form/TextArea.js.map +1 -1
- package/dist/esm/form/TextAreaBase.js +1 -0
- package/dist/esm/form/TextAreaBase.js.map +1 -1
- package/dist/esm/form/TimeInput.js +1 -0
- package/dist/esm/form/TimeInput.js.map +1 -1
- package/dist/esm/form/TimeInputBase.js +1 -0
- package/dist/esm/form/TimeInputBase.js.map +1 -1
- package/dist/esm/form/_colorInternals/EyeDropperButton.js +1 -0
- package/dist/esm/form/_colorInternals/EyeDropperButton.js.map +1 -1
- package/dist/esm/form/_colorInternals/pickerState.js +1 -0
- package/dist/esm/form/_colorInternals/pickerState.js.map +1 -1
- package/dist/esm/form/_pickerInternals/Calendar.js +1 -0
- package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js +1 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/esm/form/_pickerInternals/TimeWheels.js +1 -0
- package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -1
- package/dist/esm/form/_pickerInternals/useLocaleDefaults.js +1 -0
- package/dist/esm/form/_pickerInternals/useLocaleDefaults.js.map +1 -1
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js +1 -0
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js.map +1 -1
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js +1 -0
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js.map +1 -1
- package/dist/esm/form/controlLoading.js +1 -0
- package/dist/esm/form/controlLoading.js.map +1 -1
- package/dist/esm/form/groupFieldset.js +1 -0
- package/dist/esm/form/groupFieldset.js.map +1 -1
- package/dist/esm/form/useAutoLabelId.js +1 -0
- package/dist/esm/form/useAutoLabelId.js.map +1 -1
- package/dist/esm/grid/Cell.js +1 -0
- package/dist/esm/grid/Cell.js.map +1 -1
- package/dist/esm/grid/Grid.js +1 -0
- package/dist/esm/grid/Grid.js.map +1 -1
- package/dist/esm/helpers/ClientOnly.js +1 -0
- package/dist/esm/helpers/ClientOnly.js.map +1 -1
- package/dist/esm/helpers/Config.js +1 -0
- package/dist/esm/helpers/Config.js.map +1 -1
- package/dist/esm/helpers/LocaleProvider.js +1 -0
- package/dist/esm/helpers/LocaleProvider.js.map +1 -1
- package/dist/esm/helpers/Theme.js +1 -0
- package/dist/esm/helpers/Theme.js.map +1 -1
- package/dist/esm/helpers/flattenChildren.js +1 -0
- package/dist/esm/helpers/flattenChildren.js.map +1 -1
- package/dist/esm/helpers/inertProps.js +1 -0
- package/dist/esm/helpers/inertProps.js.map +1 -1
- package/dist/esm/helpers/localeFormat.js +1 -0
- package/dist/esm/helpers/localeFormat.js.map +1 -1
- package/dist/esm/helpers/overlayStack.js +1 -0
- package/dist/esm/helpers/overlayStack.js.map +1 -1
- package/dist/esm/helpers/portal.js +1 -0
- package/dist/esm/helpers/portal.js.map +1 -1
- package/dist/esm/helpers/scrollLock.js +1 -0
- package/dist/esm/helpers/scrollLock.js.map +1 -1
- package/dist/esm/helpers/statusRegion.js +1 -0
- package/dist/esm/helpers/statusRegion.js.map +1 -1
- package/dist/esm/helpers/typeahead.js +1 -0
- package/dist/esm/helpers/typeahead.js.map +1 -1
- package/dist/esm/helpers/useAnchoredPosition.js +1 -0
- package/dist/esm/helpers/useAnchoredPosition.js.map +1 -1
- package/dist/esm/helpers/useBulmaClasses.js +1 -0
- package/dist/esm/helpers/useBulmaClasses.js.map +1 -1
- package/dist/esm/helpers/useClientLayoutEffect.js +1 -0
- package/dist/esm/helpers/useClientLayoutEffect.js.map +1 -1
- package/dist/esm/helpers/useColorClasses.js +1 -0
- package/dist/esm/helpers/useColorClasses.js.map +1 -1
- package/dist/esm/helpers/useComboboxEngine.js +1 -0
- package/dist/esm/helpers/useComboboxEngine.js.map +1 -1
- package/dist/esm/helpers/useContextMenuTrigger.js +1 -0
- package/dist/esm/helpers/useContextMenuTrigger.js.map +1 -1
- package/dist/esm/helpers/useFlexboxClasses.js +1 -0
- package/dist/esm/helpers/useFlexboxClasses.js.map +1 -1
- package/dist/esm/helpers/useFocusTrap.js +1 -0
- package/dist/esm/helpers/useFocusTrap.js.map +1 -1
- package/dist/esm/helpers/useHoverOpen.js +1 -0
- package/dist/esm/helpers/useHoverOpen.js.map +1 -1
- package/dist/esm/helpers/useInertSiblings.js +1 -0
- package/dist/esm/helpers/useInertSiblings.js.map +1 -1
- package/dist/esm/helpers/useIsHydrated.js +1 -0
- package/dist/esm/helpers/useIsHydrated.js.map +1 -1
- package/dist/esm/helpers/useLatestRef.js +1 -0
- package/dist/esm/helpers/useLatestRef.js.map +1 -1
- package/dist/esm/helpers/useMenuKeys.js +1 -0
- package/dist/esm/helpers/useMenuKeys.js.map +1 -1
- package/dist/esm/helpers/useOtherClasses.js +1 -0
- package/dist/esm/helpers/useOtherClasses.js.map +1 -1
- package/dist/esm/helpers/useSpacingClasses.js +1 -0
- package/dist/esm/helpers/useSpacingClasses.js.map +1 -1
- package/dist/esm/helpers/useTreeView.js +1 -0
- package/dist/esm/helpers/useTreeView.js.map +1 -1
- package/dist/esm/helpers/useTypographyClasses.js +1 -0
- package/dist/esm/helpers/useTypographyClasses.js.map +1 -1
- package/dist/esm/helpers/useVisibilityClasses.js +1 -0
- package/dist/esm/helpers/useVisibilityClasses.js.map +1 -1
- package/dist/esm/layout/Container.js +1 -0
- package/dist/esm/layout/Container.js.map +1 -1
- package/dist/esm/layout/Footer.js +1 -0
- package/dist/esm/layout/Footer.js.map +1 -1
- package/dist/esm/layout/Hero.js +1 -0
- package/dist/esm/layout/Hero.js.map +1 -1
- package/dist/esm/layout/Level.js +1 -0
- package/dist/esm/layout/Level.js.map +1 -1
- package/dist/esm/layout/Media.js +1 -0
- package/dist/esm/layout/Media.js.map +1 -1
- package/dist/esm/layout/Section.js +1 -0
- package/dist/esm/layout/Section.js.map +1 -1
- package/dist/esm/layout/Splitter.js +1 -0
- package/dist/esm/layout/Splitter.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.js","sources":["../../../src/components/SegmentedControl.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonOwnProps } from '../elements/Button';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\n\n// Spelled out so the API page can list the values. The tests hold it to\n// ToggleButton's, since the checked segment fills the way a pressed toggle\n// does and for the same reasons.\n/**\n * The fills the checked segment takes: `Button`'s colors, minus `text` and\n * `ghost`, which don't fill, and `white`, `light`, `dark` and `black`, which in\n * one theme or the other fill about as light or dark as an unchecked segment\n * already is. The same set `ToggleButton` takes.\n */\nexport type SegmentedControlColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\n/** A mounted segment, as the group needs to know it for the tab stop. */\ninterface SegmentRecord {\n value: string;\n disabled: boolean;\n node: HTMLButtonElement;\n}\n\ninterface SegmentedControlContextValue {\n /** The checked segment's value, or `undefined` while none is. */\n checked: string | undefined;\n /** The segment that holds `tabIndex={0}`, or `undefined` for none. */\n tabStop: string | undefined;\n /** The fill the checked segment takes. */\n color: SegmentedControlColor;\n /** Checks a segment, unless it's checked already. */\n select: (value: string) => void;\n /** Records which segment has focus, so the tab stop can follow it. */\n setFocused: (value: string | undefined) => void;\n register: (record: SegmentRecord) => () => void;\n}\n\n// Not exported, so it stays out of the public API that `index.ts` re-exports.\nconst SegmentedControlContext =\n createContext<SegmentedControlContextValue | null>(null);\n\n/** Sorts mounted segments into the order they sit in the page. */\nconst inDocumentOrder = (a: SegmentRecord, b: SegmentRecord) =>\n a.node.compareDocumentPosition(b.node) & Node.DOCUMENT_POSITION_FOLLOWING\n ? -1\n : 1;\n\n/** How far each arrow key moves along the row. */\nconst STEPS: Record<string, number> = {\n ArrowRight: 1,\n ArrowDown: 1,\n ArrowLeft: -1,\n ArrowUp: -1,\n};\n\n/**\n * The segment a key moves to, found among the segments of the same group in\n * DOM order, skipping disabled ones and wrapping at either end. `undefined`\n * for a key the group leaves alone, when no enabled segment is left, or when\n * the segment isn't inside its row in the page, as a portaled one isn't.\n */\nfunction segmentFor(\n current: HTMLButtonElement,\n key: string\n): HTMLButtonElement | undefined {\n const group = current.closest('[role=\"radiogroup\"]');\n if (!group) return undefined;\n const segments = Array.from(\n group.querySelectorAll<HTMLButtonElement>('[role=\"radio\"]')\n );\n const enabled = segments.filter(segment => !segment.disabled);\n\n if (key === 'Home') return enabled[0];\n if (key === 'End') return enabled[enabled.length - 1];\n\n const step = STEPS[key];\n if (!step) return undefined;\n const at = segments.indexOf(current);\n for (let i = 1; i <= segments.length; i += 1) {\n const candidate =\n segments[(at + step * i + segments.length) % segments.length];\n if (!candidate.disabled) return candidate;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// SegmentedControl (root)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the SegmentedControl component. The helper props, the other `<div>`\n * attributes and the `ref` all land on the row.\n *\n * @extraProp {string} [aria-label] - Names the group for a screen reader, such as \"Text alignment\". A radio group needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the group, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the row's `<div>`.\n */\nexport interface SegmentedControlProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | 'color' | 'role'\n >,\n Omit<\n BulmaClassesProps,\n 'color' | 'colorShade' | 'backgroundColor' | 'backgroundColorShade'\n > {\n /**\n * The checked segment's `value`, when you hold the state. Setting it makes\n * the group controlled: picking a segment only calls `onChange`, and nothing\n * changes until you pass the new value. `null` checks nothing, with the\n * tab stop `defaultValue` describes for that. Pick this or `defaultValue`\n * for the group's lifetime.\n */\n value?: string | null;\n /**\n * The segment checked to begin with, when the group holds its own state.\n * Leave it out and nothing is checked until someone picks one, and Tab\n * lands on the first enabled segment meanwhile. That fallback takes hold\n * once the row has rendered in the browser: server markup with nothing\n * checked has no tab stop until then, while a checked segment is the stop\n * from the server markup on.\n */\n defaultValue?: string;\n /**\n * Called with the newly checked segment's `value`, whether or not `value`\n * is set. The arrow keys, Home and End check the segment they move to, so\n * each of those calls it too: the check follows focus, as in a native radio\n * group. Pressing the checked segment again doesn't call it, since a\n * segmented control can't be cleared: one stays checked once one is.\n */\n onChange?: (value: string) => void;\n /**\n * The checked segment's fill. The others are plain buttons, so the fill is\n * the difference people see. Takes the same colors as `ToggleButton`, for\n * the same reason: `white`, `light`, `dark` and `black` fill about as light\n * or dark as a plain button already is in one theme or the other.\n */\n color?: SegmentedControlColor;\n /** Size of every segment, through Bulma's `are-<size>` on the row. */\n size?: 'small' | 'medium' | 'large';\n /**\n * Joins the segments into one row with no gap between them, Bulma's\n * `has-addons`. Set it to `false` for separate buttons.\n */\n hasAddons?: boolean;\n /** Centers the row. */\n isCentered?: boolean;\n /** Aligns the row to the right. */\n isRight?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** The `SegmentedControl.Segment`s, each with a `value` of its own. */\n children?: React.ReactNode;\n}\n\n/**\n * The `SegmentedControl` component renders a row of buttons where only one can be on, and tells a screen reader it's a radio group.\n *\n * It's Bulma's `.buttons.has-addons` row, with the checked segment filled and\n * marked `is-selected`, the way Bulma's button docs show it. To a screen\n * reader it's `role=\"radiogroup\"`, with `role=\"radio\"` and `aria-checked` on\n * each segment, which is how the APG toolbar example marks its alignment\n * buttons. The keys follow the APG radio group: the row is one tab stop, the\n * arrow keys move to the next or previous enabled segment and check it,\n * wrapping at either end, Home and End go to the first and last, and Space\n * checks the focused segment. Once a segment is checked, one always is.\n *\n * It carries no form value. A choice that's sent with a form is `Radios`.\n *\n * @function\n * @param {SegmentedControlProps} props - Props for the SegmentedControl component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the row's `<div>`.\n * @returns {JSX.Element} The rendered segmented control.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/radio/ | APG radio group pattern}\n * @see {@link https://bulma.io/documentation/elements/button/#list-of-buttons | Bulma list of buttons}\n *\n * @example\n * <SegmentedControl aria-label=\"Text alignment\" defaultValue=\"left\">\n * <SegmentedControl.Segment value=\"left\">Left</SegmentedControl.Segment>\n * <SegmentedControl.Segment value=\"center\">Center</SegmentedControl.Segment>\n * <SegmentedControl.Segment value=\"right\">Right</SegmentedControl.Segment>\n * </SegmentedControl>\n */\nconst SegmentedControlRoot = forwardRef<HTMLDivElement, SegmentedControlProps>(\n function SegmentedControl(\n {\n value,\n defaultValue,\n onChange,\n color = 'link',\n size,\n hasAddons = true,\n isCentered,\n isRight,\n className,\n children,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n // Controlled vs uncontrolled, as in Tabs and Collapses.\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const checked = isControlled ? (value ?? undefined) : internalValue;\n\n const select = (next: string) => {\n if (next === checked) return;\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n // The segments mount and register from an effect, so the group knows\n // which can hold the tab stop wherever in the tree they sit.\n const [segments, setSegments] = useState<SegmentRecord[]>([]);\n const register = useCallback((record: SegmentRecord) => {\n setSegments(prev => [...prev, record]);\n return () => setSegments(prev => prev.filter(r => r !== record));\n }, []);\n const [focused, setFocused] = useState<string | undefined>();\n\n // The first enabled segment in the page, sorted when it's read rather\n // than when a segment registers, so reordered segments are seen too. It's\n // read after the commit: a render runs before React moves the nodes, so\n // sorting there would find the old order.\n const [firstEnabled, setFirstEnabled] = useState<string | undefined>();\n useClientLayoutEffect(() => {\n const inPage = segments.filter(s => !s.disabled).sort(inDocumentOrder);\n setFirstEnabled(inPage[0]?.value);\n }, [segments, children]);\n\n // One tab stop for the row (roving tabindex). While focus is in the row\n // the stop follows it, so Tab leaves from wherever focus is even when a\n // controlled group hasn't taken the new value. Otherwise it's the checked\n // segment, or the first enabled one when none is checked or the checked\n // one is disabled. Before the segments register (the server render and\n // the first client render) the checked one holds it, so a row with\n // nothing checked has no stop until the client has rendered.\n const canHoldStop = (candidate: string | undefined) =>\n segments.some(s => !s.disabled && s.value === candidate);\n let tabStop: string | undefined;\n if (canHoldStop(focused)) tabStop = focused;\n else if (segments.length === 0 || canHoldStop(checked)) tabStop = checked;\n else tabStop = firstEnabled;\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'SegmentedControl:unnamed',\n '[bestax-bulma] <SegmentedControl> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the choice is.'\n );\n }\n }, [named]);\n\n const rowClasses = usePrefixedClassNames('buttons', {\n 'has-addons': hasAddons,\n 'is-centered': isCentered,\n 'is-right': isRight,\n [`are-${size}`]: size,\n });\n\n // The props are spread first, so the role a screen reader relies on wins\n // over anything a JavaScript caller or a spread object passes along.\n return (\n <SegmentedControlContext.Provider\n value={{ checked, tabStop, color, select, setFocused, register }}\n >\n <div\n {...rest}\n ref={ref}\n role=\"radiogroup\"\n className={classNames(rowClasses, bulmaHelperClasses, className)}\n >\n {children}\n </div>\n </SegmentedControlContext.Provider>\n );\n }\n);\n\n// ---------------------------------------------------------------------------\n// SegmentedControl.Segment\n// ---------------------------------------------------------------------------\n\n/**\n * Props for SegmentedControl.Segment. The helper props, the other button\n * attributes and the `ref` all land on the `<button>`.\n *\n * Some of `Button`'s props are left out on purpose. `as`, `type`, `role` and\n * `tabIndex`, since a segment is always a `<button type=\"button\" role=\"radio\">`\n * and the group decides which segment Tab reaches. `color`, which the group\n * sets for the checked segment, and the props that change the fill\n * (`isActive`, `isLight`, `isOutlined`, `isInverted`, `textColor`, `bgColor`\n * and their shades), since each would color it whether checked or not. `size`\n * and the width and shape props, which the row sets for every segment. And\n * `isStatic` and `isLoading`, a segment you couldn't pick.\n *\n * @extraProp {React.Ref<HTMLButtonElement>} [ref] - Ref forwarded to the `<button>`.\n */\nexport interface SegmentedControlSegmentProps\n extends\n Omit<\n ButtonOwnProps,\n | 'color'\n | 'size'\n | 'isActive'\n | 'isStatic'\n | 'isLoading'\n | 'isLight'\n | 'isOutlined'\n | 'isInverted'\n | 'isRounded'\n | 'isFullwidth'\n | 'isFullWidth'\n | 'textColor'\n | 'bgColor'\n | 'colorShade'\n | 'backgroundColorShade'\n >,\n Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n | keyof ButtonOwnProps\n | 'type'\n | 'value'\n | 'role'\n | 'tabIndex'\n | 'aria-checked'\n | 'aria-pressed'\n > {\n /**\n * **Required.** What `onChange` reports when this segment is checked, and\n * what the group's `value` and `defaultValue` name it by. Unique within the\n * group.\n */\n value: string;\n /**\n * The label. An icon on its own needs an `aria-label`, so a screen reader\n * has something to say.\n */\n children?: React.ReactNode;\n /**\n * Disables the segment, the same as `disabled`: it can't be clicked, the\n * arrow keys, Home and End skip it, and it never holds the row's tab stop.\n * A checked one keeps its fill under Bulma's disabled look.\n */\n isDisabled?: boolean;\n /**\n * Not accepted: `aria-checked` follows the group's value. Declared because\n * JSX lets a hyphenated attribute through when the props don't name it.\n * @internal\n */\n 'aria-checked'?: never;\n /**\n * Not accepted: a segment is a radio, which says checked, not pressed.\n * @internal\n */\n 'aria-pressed'?: never;\n}\n\n/**\n * One option in the row: a `<button role=\"radio\">` that's checked while the group's value is its `value`, filled with the group's `color` and marked `is-selected`.\n *\n * @function\n * @param {SegmentedControlSegmentProps} props - Props for the segment.\n * @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.\n * @returns {JSX.Element} The rendered segment.\n */\nconst Segment = forwardRef<HTMLButtonElement, SegmentedControlSegmentProps>(\n function Segment(\n {\n value,\n isDisabled,\n disabled,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const ctx = useContext(SegmentedControlContext);\n const checked = ctx !== null && ctx.checked === value;\n const off = Boolean(isDisabled || disabled);\n\n // Prefixed like Button's own classes, which a hand-written\n // `className=\"is-selected\"` could not be under ConfigProvider classPrefix.\n // Bulma lifts `is-selected` above its neighbours in `.buttons.has-addons`.\n const selectedClass = usePrefixedClassNames({ 'is-selected': checked });\n\n const nodeRef = useRef<HTMLButtonElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLButtonElement | null) => {\n nodeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref]\n );\n\n const register = ctx?.register;\n useEffect(() => {\n if (!register) {\n warnOnce(\n 'SegmentedControl.Segment:outside',\n '[bestax-bulma] <SegmentedControl.Segment> is outside a ' +\n '<SegmentedControl>, so nothing can check it. Put it inside one.'\n );\n return undefined;\n }\n return register({\n value,\n disabled: off,\n node: nodeRef.current as HTMLButtonElement,\n });\n }, [register, value, off]);\n\n // The caller's onClick runs first, so a `preventDefault()` there keeps\n // the segment from being checked. A disabled button gets no click.\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n ctx?.select(value);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n if (\n !ctx ||\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey\n ) {\n return;\n }\n const target = segmentFor(event.currentTarget, event.key);\n if (!target) return;\n event.preventDefault();\n // The row has taken this key, so nothing above it acts on it too: a\n // Carousel moves its slide on the arrows from a document listener that\n // doesn't read `defaultPrevented`. Keys the row leaves alone still bubble.\n event.stopPropagation();\n target.focus();\n // The check follows focus, APG's rule for a radio group outside a\n // toolbar. It goes through a click on the segment, as a native radio's\n // does, so its onClick sees it. Inside a toolbar the arrows would move\n // focus alone; that is the line a toolbar would change.\n target.click();\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLButtonElement>) => {\n onFocus?.(event);\n ctx?.setFocused(value);\n };\n\n // The segment focus moves to, if any, records itself straight after.\n const handleBlur = (event: React.FocusEvent<HTMLButtonElement>) => {\n onBlur?.(event);\n ctx?.setFocused(undefined);\n };\n\n // The props are spread first, so what a radio depends on wins over\n // anything a JavaScript caller or a spread object passes along: it stays\n // a button, never submits, reports whether it's checked, and the group\n // decides whether Tab reaches it.\n return (\n <Button\n {...props}\n ref={setRefs}\n as=\"button\"\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n tabIndex={ctx ? (ctx.tabStop === value ? 0 : -1) : undefined}\n isDisabled={off}\n color={checked ? ctx.color : undefined}\n className={classNames(selectedClass, className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n />\n );\n }\n);\n\nSegment.displayName = 'SegmentedControl.Segment';\n\nexport const SegmentedControl = withSubComponents(\n SegmentedControlRoot,\n { Segment },\n 'SegmentedControl'\n);\n\nexport default SegmentedControl;\n"],"names":["_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SegmentedControl.js","sources":["../../../src/components/SegmentedControl.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Button, type ButtonOwnProps } from '../elements/Button';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { warnOnce } from '../helpers/devWarnings';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\n\n// Spelled out so the API page can list the values. The tests hold it to\n// ToggleButton's, since the checked segment fills the way a pressed toggle\n// does and for the same reasons.\n/**\n * The fills the checked segment takes: `Button`'s colors, minus `text` and\n * `ghost`, which don't fill, and `white`, `light`, `dark` and `black`, which in\n * one theme or the other fill about as light or dark as an unchecked segment\n * already is. The same set `ToggleButton` takes.\n */\nexport type SegmentedControlColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\n/** A mounted segment, as the group needs to know it for the tab stop. */\ninterface SegmentRecord {\n value: string;\n disabled: boolean;\n node: HTMLButtonElement;\n}\n\ninterface SegmentedControlContextValue {\n /** The checked segment's value, or `undefined` while none is. */\n checked: string | undefined;\n /** The segment that holds `tabIndex={0}`, or `undefined` for none. */\n tabStop: string | undefined;\n /** The fill the checked segment takes. */\n color: SegmentedControlColor;\n /** Checks a segment, unless it's checked already. */\n select: (value: string) => void;\n /** Records which segment has focus, so the tab stop can follow it. */\n setFocused: (value: string | undefined) => void;\n register: (record: SegmentRecord) => () => void;\n}\n\n// Not exported, so it stays out of the public API that `index.ts` re-exports.\nconst SegmentedControlContext =\n createContext<SegmentedControlContextValue | null>(null);\n\n/** Sorts mounted segments into the order they sit in the page. */\nconst inDocumentOrder = (a: SegmentRecord, b: SegmentRecord) =>\n a.node.compareDocumentPosition(b.node) & Node.DOCUMENT_POSITION_FOLLOWING\n ? -1\n : 1;\n\n/** How far each arrow key moves along the row. */\nconst STEPS: Record<string, number> = {\n ArrowRight: 1,\n ArrowDown: 1,\n ArrowLeft: -1,\n ArrowUp: -1,\n};\n\n/**\n * The segment a key moves to, found among the segments of the same group in\n * DOM order, skipping disabled ones and wrapping at either end. `undefined`\n * for a key the group leaves alone, when no enabled segment is left, or when\n * the segment isn't inside its row in the page, as a portaled one isn't.\n */\nfunction segmentFor(\n current: HTMLButtonElement,\n key: string\n): HTMLButtonElement | undefined {\n const group = current.closest('[role=\"radiogroup\"]');\n if (!group) return undefined;\n const segments = Array.from(\n group.querySelectorAll<HTMLButtonElement>('[role=\"radio\"]')\n );\n const enabled = segments.filter(segment => !segment.disabled);\n\n if (key === 'Home') return enabled[0];\n if (key === 'End') return enabled[enabled.length - 1];\n\n const step = STEPS[key];\n if (!step) return undefined;\n const at = segments.indexOf(current);\n for (let i = 1; i <= segments.length; i += 1) {\n const candidate =\n segments[(at + step * i + segments.length) % segments.length];\n if (!candidate.disabled) return candidate;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// SegmentedControl (root)\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the SegmentedControl component. The helper props, the other `<div>`\n * attributes and the `ref` all land on the row.\n *\n * @extraProp {string} [aria-label] - Names the group for a screen reader, such as \"Text alignment\". A radio group needs a name, so pass this or `aria-labelledby`, and a development build warns when it has neither.\n * @extraProp {string} [aria-labelledby] - The id of a visible heading or label that names the group, in place of `aria-label`.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the row's `<div>`.\n */\nexport interface SegmentedControlProps\n extends\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'defaultValue' | 'color' | 'role'\n >,\n Omit<\n BulmaClassesProps,\n 'color' | 'colorShade' | 'backgroundColor' | 'backgroundColorShade'\n > {\n /**\n * The checked segment's `value`, when you hold the state. Setting it makes\n * the group controlled: picking a segment only calls `onChange`, and nothing\n * changes until you pass the new value. `null` checks nothing, with the\n * tab stop `defaultValue` describes for that. Pick this or `defaultValue`\n * for the group's lifetime.\n */\n value?: string | null;\n /**\n * The segment checked to begin with, when the group holds its own state.\n * Leave it out and nothing is checked until someone picks one, and Tab\n * lands on the first enabled segment meanwhile. That fallback takes hold\n * once the row has rendered in the browser: server markup with nothing\n * checked has no tab stop until then, while a checked segment is the stop\n * from the server markup on.\n */\n defaultValue?: string;\n /**\n * Called with the newly checked segment's `value`, whether or not `value`\n * is set. The arrow keys, Home and End check the segment they move to, so\n * each of those calls it too: the check follows focus, as in a native radio\n * group. Pressing the checked segment again doesn't call it, since a\n * segmented control can't be cleared: one stays checked once one is.\n */\n onChange?: (value: string) => void;\n /**\n * The checked segment's fill. The others are plain buttons, so the fill is\n * the difference people see. Takes the same colors as `ToggleButton`, for\n * the same reason: `white`, `light`, `dark` and `black` fill about as light\n * or dark as a plain button already is in one theme or the other.\n */\n color?: SegmentedControlColor;\n /** Size of every segment, through Bulma's `are-<size>` on the row. */\n size?: 'small' | 'medium' | 'large';\n /**\n * Joins the segments into one row with no gap between them, Bulma's\n * `has-addons`. Set it to `false` for separate buttons.\n */\n hasAddons?: boolean;\n /** Centers the row. */\n isCentered?: boolean;\n /** Aligns the row to the right. */\n isRight?: boolean;\n /** Additional CSS classes to apply. */\n className?: string;\n /** The `SegmentedControl.Segment`s, each with a `value` of its own. */\n children?: React.ReactNode;\n}\n\n/**\n * The `SegmentedControl` component renders a row of buttons where only one can be on, and tells a screen reader it's a radio group.\n *\n * It's Bulma's `.buttons.has-addons` row, with the checked segment filled and\n * marked `is-selected`, the way Bulma's button docs show it. To a screen\n * reader it's `role=\"radiogroup\"`, with `role=\"radio\"` and `aria-checked` on\n * each segment, which is how the APG toolbar example marks its alignment\n * buttons. The keys follow the APG radio group: the row is one tab stop, the\n * arrow keys move to the next or previous enabled segment and check it,\n * wrapping at either end, Home and End go to the first and last, and Space\n * checks the focused segment. Once a segment is checked, one always is.\n *\n * It carries no form value. A choice that's sent with a form is `Radios`.\n *\n * @function\n * @param {SegmentedControlProps} props - Props for the SegmentedControl component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the row's `<div>`.\n * @returns {JSX.Element} The rendered segmented control.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/radio/ | APG radio group pattern}\n * @see {@link https://bulma.io/documentation/elements/button/#list-of-buttons | Bulma list of buttons}\n *\n * @example\n * <SegmentedControl aria-label=\"Text alignment\" defaultValue=\"left\">\n * <SegmentedControl.Segment value=\"left\">Left</SegmentedControl.Segment>\n * <SegmentedControl.Segment value=\"center\">Center</SegmentedControl.Segment>\n * <SegmentedControl.Segment value=\"right\">Right</SegmentedControl.Segment>\n * </SegmentedControl>\n */\nconst SegmentedControlRoot = forwardRef<HTMLDivElement, SegmentedControlProps>(\n function SegmentedControl(\n {\n value,\n defaultValue,\n onChange,\n color = 'link',\n size,\n hasAddons = true,\n isCentered,\n isRight,\n className,\n children,\n ...props\n },\n ref\n ) {\n const { bulmaHelperClasses, rest } = useBulmaClasses({ ...props });\n\n // Controlled vs uncontrolled, as in Tabs and Collapses.\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const checked = isControlled ? (value ?? undefined) : internalValue;\n\n const select = (next: string) => {\n if (next === checked) return;\n if (!isControlled) setInternalValue(next);\n onChange?.(next);\n };\n\n // The segments mount and register from an effect, so the group knows\n // which can hold the tab stop wherever in the tree they sit.\n const [segments, setSegments] = useState<SegmentRecord[]>([]);\n const register = useCallback((record: SegmentRecord) => {\n setSegments(prev => [...prev, record]);\n return () => setSegments(prev => prev.filter(r => r !== record));\n }, []);\n const [focused, setFocused] = useState<string | undefined>();\n\n // The first enabled segment in the page, sorted when it's read rather\n // than when a segment registers, so reordered segments are seen too. It's\n // read after the commit: a render runs before React moves the nodes, so\n // sorting there would find the old order.\n const [firstEnabled, setFirstEnabled] = useState<string | undefined>();\n useClientLayoutEffect(() => {\n const inPage = segments.filter(s => !s.disabled).sort(inDocumentOrder);\n setFirstEnabled(inPage[0]?.value);\n }, [segments, children]);\n\n // One tab stop for the row (roving tabindex). While focus is in the row\n // the stop follows it, so Tab leaves from wherever focus is even when a\n // controlled group hasn't taken the new value. Otherwise it's the checked\n // segment, or the first enabled one when none is checked or the checked\n // one is disabled. Before the segments register (the server render and\n // the first client render) the checked one holds it, so a row with\n // nothing checked has no stop until the client has rendered.\n const canHoldStop = (candidate: string | undefined) =>\n segments.some(s => !s.disabled && s.value === candidate);\n let tabStop: string | undefined;\n if (canHoldStop(focused)) tabStop = focused;\n else if (segments.length === 0 || canHoldStop(checked)) tabStop = checked;\n else tabStop = firstEnabled;\n\n const named = Boolean(rest['aria-label'] || rest['aria-labelledby']);\n useEffect(() => {\n if (!named) {\n warnOnce(\n 'SegmentedControl:unnamed',\n '[bestax-bulma] <SegmentedControl> has no accessible name. Pass ' +\n 'aria-label or aria-labelledby, so a screen reader can say what ' +\n 'the choice is.'\n );\n }\n }, [named]);\n\n const rowClasses = usePrefixedClassNames('buttons', {\n 'has-addons': hasAddons,\n 'is-centered': isCentered,\n 'is-right': isRight,\n [`are-${size}`]: size,\n });\n\n // The props are spread first, so the role a screen reader relies on wins\n // over anything a JavaScript caller or a spread object passes along.\n return (\n <SegmentedControlContext.Provider\n value={{ checked, tabStop, color, select, setFocused, register }}\n >\n <div\n {...rest}\n ref={ref}\n role=\"radiogroup\"\n className={classNames(rowClasses, bulmaHelperClasses, className)}\n >\n {children}\n </div>\n </SegmentedControlContext.Provider>\n );\n }\n);\n\n// ---------------------------------------------------------------------------\n// SegmentedControl.Segment\n// ---------------------------------------------------------------------------\n\n/**\n * Props for SegmentedControl.Segment. The helper props, the other button\n * attributes and the `ref` all land on the `<button>`.\n *\n * Some of `Button`'s props are left out on purpose. `as`, `type`, `role` and\n * `tabIndex`, since a segment is always a `<button type=\"button\" role=\"radio\">`\n * and the group decides which segment Tab reaches. `color`, which the group\n * sets for the checked segment, and the props that change the fill\n * (`isActive`, `isLight`, `isOutlined`, `isInverted`, `textColor`, `bgColor`\n * and their shades), since each would color it whether checked or not. `size`\n * and the width and shape props, which the row sets for every segment. And\n * `isStatic` and `isLoading`, a segment you couldn't pick.\n *\n * @extraProp {React.Ref<HTMLButtonElement>} [ref] - Ref forwarded to the `<button>`.\n */\nexport interface SegmentedControlSegmentProps\n extends\n Omit<\n ButtonOwnProps,\n | 'color'\n | 'size'\n | 'isActive'\n | 'isStatic'\n | 'isLoading'\n | 'isLight'\n | 'isOutlined'\n | 'isInverted'\n | 'isRounded'\n | 'isFullwidth'\n | 'isFullWidth'\n | 'textColor'\n | 'bgColor'\n | 'colorShade'\n | 'backgroundColorShade'\n >,\n Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n | keyof ButtonOwnProps\n | 'type'\n | 'value'\n | 'role'\n | 'tabIndex'\n | 'aria-checked'\n | 'aria-pressed'\n > {\n /**\n * **Required.** What `onChange` reports when this segment is checked, and\n * what the group's `value` and `defaultValue` name it by. Unique within the\n * group.\n */\n value: string;\n /**\n * The label. An icon on its own needs an `aria-label`, so a screen reader\n * has something to say.\n */\n children?: React.ReactNode;\n /**\n * Disables the segment, the same as `disabled`: it can't be clicked, the\n * arrow keys, Home and End skip it, and it never holds the row's tab stop.\n * A checked one keeps its fill under Bulma's disabled look.\n */\n isDisabled?: boolean;\n /**\n * Not accepted: `aria-checked` follows the group's value. Declared because\n * JSX lets a hyphenated attribute through when the props don't name it.\n * @internal\n */\n 'aria-checked'?: never;\n /**\n * Not accepted: a segment is a radio, which says checked, not pressed.\n * @internal\n */\n 'aria-pressed'?: never;\n}\n\n/**\n * One option in the row: a `<button role=\"radio\">` that's checked while the group's value is its `value`, filled with the group's `color` and marked `is-selected`.\n *\n * @function\n * @param {SegmentedControlSegmentProps} props - Props for the segment.\n * @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.\n * @returns {JSX.Element} The rendered segment.\n */\nconst Segment = forwardRef<HTMLButtonElement, SegmentedControlSegmentProps>(\n function Segment(\n {\n value,\n isDisabled,\n disabled,\n className,\n onClick,\n onKeyDown,\n onFocus,\n onBlur,\n ...props\n },\n ref\n ) {\n const ctx = useContext(SegmentedControlContext);\n const checked = ctx !== null && ctx.checked === value;\n const off = Boolean(isDisabled || disabled);\n\n // Prefixed like Button's own classes, which a hand-written\n // `className=\"is-selected\"` could not be under ConfigProvider classPrefix.\n // Bulma lifts `is-selected` above its neighbours in `.buttons.has-addons`.\n const selectedClass = usePrefixedClassNames({ 'is-selected': checked });\n\n const nodeRef = useRef<HTMLButtonElement | null>(null);\n const setRefs = useCallback(\n (node: HTMLButtonElement | null) => {\n nodeRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n },\n [ref]\n );\n\n const register = ctx?.register;\n useEffect(() => {\n if (!register) {\n warnOnce(\n 'SegmentedControl.Segment:outside',\n '[bestax-bulma] <SegmentedControl.Segment> is outside a ' +\n '<SegmentedControl>, so nothing can check it. Put it inside one.'\n );\n return undefined;\n }\n return register({\n value,\n disabled: off,\n node: nodeRef.current as HTMLButtonElement,\n });\n }, [register, value, off]);\n\n // The caller's onClick runs first, so a `preventDefault()` there keeps\n // the segment from being checked. A disabled button gets no click.\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n ctx?.select(value);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n if (\n !ctx ||\n event.defaultPrevented ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey\n ) {\n return;\n }\n const target = segmentFor(event.currentTarget, event.key);\n if (!target) return;\n event.preventDefault();\n // The row has taken this key, so nothing above it acts on it too: a\n // Carousel moves its slide on the arrows from a document listener that\n // doesn't read `defaultPrevented`. Keys the row leaves alone still bubble.\n event.stopPropagation();\n target.focus();\n // The check follows focus, APG's rule for a radio group outside a\n // toolbar. It goes through a click on the segment, as a native radio's\n // does, so its onClick sees it. Inside a toolbar the arrows would move\n // focus alone; that is the line a toolbar would change.\n target.click();\n };\n\n const handleFocus = (event: React.FocusEvent<HTMLButtonElement>) => {\n onFocus?.(event);\n ctx?.setFocused(value);\n };\n\n // The segment focus moves to, if any, records itself straight after.\n const handleBlur = (event: React.FocusEvent<HTMLButtonElement>) => {\n onBlur?.(event);\n ctx?.setFocused(undefined);\n };\n\n // The props are spread first, so what a radio depends on wins over\n // anything a JavaScript caller or a spread object passes along: it stays\n // a button, never submits, reports whether it's checked, and the group\n // decides whether Tab reaches it.\n return (\n <Button\n {...props}\n ref={setRefs}\n as=\"button\"\n type=\"button\"\n role=\"radio\"\n aria-checked={checked}\n tabIndex={ctx ? (ctx.tabStop === value ? 0 : -1) : undefined}\n isDisabled={off}\n color={checked ? ctx.color : undefined}\n className={classNames(selectedClass, className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n />\n );\n }\n);\n\nSegment.displayName = 'SegmentedControl.Segment';\n\nexport const SegmentedControl = withSubComponents(\n SegmentedControlRoot,\n { Segment },\n 'SegmentedControl'\n);\n\nexport default SegmentedControl;\n"],"names":["_jsx"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
'use client';
|
|
2
3
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
4
|
import { forwardRef, useRef, useCallback, useEffect } from 'react';
|
|
4
5
|
import { createPortal } from 'react-dom';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","sources":["../../../src/components/Sidebar.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useScrollLock } from '../helpers/scrollLock';\nimport { usePortalContainer } from '../helpers/portal';\nimport { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { useConfig } from '../helpers/Config';\nimport { buttonType } from '../helpers/buttonType';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { isModalOverlayOpen, useOverlayStack } from '../helpers/overlayStack';\nimport { focusTabStop, trapTab } from '../helpers/useFocusTrap';\nimport { inertProps } from '../helpers/inertProps';\nimport {\n getActiveElementInTree,\n getDeepestActiveElement,\n} from '../helpers/shadowDom';\n\n/** Position of the sidebar relative to the viewport. */\nexport type SidebarPosition = 'left' | 'right';\n\n/**\n * Props for the Sidebar component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the sidebar element.\n */\nexport interface SidebarProps\n extends\n Omit<React.HTMLAttributes<HTMLElement>, 'children' | 'color'>,\n BulmaClassesProps {\n /**\n * Whether the sidebar is open (required). Opening moves focus into the\n * sidebar, to its first tab stop or the sidebar itself, except for a sidebar\n * without an overlay opened while a modal overlay, such as a Modal, is open:\n * that one leaves focus where it is. That's decided as it opens, and\n * changing `overlay` while it's open doesn't move focus. Closing hands\n * focus back to whatever had it when the sidebar opened, unless focus has\n * already left the sidebar, as it does for an overlay opened over it. A\n * closed sidebar stays in the page, so it can slide out, and is `inert` and\n * `aria-hidden` there: Tab passes over its content and assistive\n * technology doesn't read it.\n */\n isOpen: boolean;\n /** Callback when sidebar should close. */\n onClose?: () => void;\n /** Which side the sidebar appears from. Default: 'left'. */\n position?: SidebarPosition;\n /** Custom width of the sidebar. */\n width?: string;\n /** Sidebar takes full width (mobile-style). */\n isFullwidth?: boolean;\n /** Sidebar takes full width (mobile-style). @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n fullWidth?: boolean;\n /**\n * Show an overlay behind the sidebar, which makes it modal: it gets\n * `aria-modal=\"true\"`, locks body scroll, and keeps Tab and Shift+Tab\n * inside it while it is the topmost modal overlay. A Modal or Dialog opened\n * over it, even one rendered inside it, holds Tab until it closes. Without\n * an overlay the sidebar isn't modal and holds no Tab: on the page, Tab\n * moves in and out of it freely, and opened over a Modal, it leaves the\n * Modal holding Tab, and focus, while still taking Escape first. Whether\n * the sidebar takes focus is decided as it opens: changing this while it's\n * open moves the Tab trap, not focus. Default: true.\n */\n overlay?: boolean;\n /** Close sidebar when overlay is clicked. Default: true. */\n overlayClose?: boolean;\n /**\n * Close sidebar on Escape key. Only the topmost open overlay responds,\n * whichever Modal, Dialog, Sidebar or full-page Loading opened last, so\n * Escape closes one layer at a time. The sidebar marks the Escape it closes\n * on as used with `preventDefault()`, and a Toast waits until no overlay is\n * open. Turned off, a sidebar on top still keeps Escape from the layers\n * under it. A popup inside it, such as a Dropdown's menu or a date picker's\n * calendar, takes its own Escape first, and so does content that calls\n * `preventDefault()` on it. Default: true.\n */\n escapeClose?: boolean;\n /** Allow closing the sidebar. Default: true. */\n canCancel?: boolean;\n /** Content to display in the sidebar. */\n children?: React.ReactNode;\n /** Renders inline instead of using a portal. */\n inline?: boolean;\n}\n\n/**\n * The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.\n *\n * @function\n * @param {SidebarProps} props - Props for the Sidebar component.\n * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the sidebar element.\n * @returns {JSX.Element | null} The rendered sidebar component.\n *\n * @example\n * // Basic sidebar\n * const [isOpen, setIsOpen] = useState(false);\n * <Sidebar isOpen={isOpen} onClose={() => setIsOpen(false)}>\n * <Menu>...</Menu>\n * </Sidebar>\n *\n * @example\n * // Right-side sidebar with custom width\n * <Sidebar\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * position=\"right\"\n * width=\"320px\"\n * >\n * <div>Panel content</div>\n * </Sidebar>\n */\nconst SidebarComponent = forwardRef<HTMLElement, SidebarProps>(\n (\n {\n isOpen,\n onClose,\n position = 'left',\n width = '260px',\n isFullwidth,\n fullWidth,\n overlay = true,\n overlayClose = true,\n escapeClose = true,\n canCancel = true,\n children,\n inline = false,\n className,\n style,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const { portalContainer } = useConfig();\n // Where the configured default puts the sidebar. An `inline` one doesn't\n // portal, so a change to the default moves nothing.\n const defaultTarget = inline ? undefined : portalContainer;\n const sidebarRef = useRef<HTMLElement>(null);\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const resolvedFullwidth = isFullwidth ?? fullWidth ?? false;\n\n // Close handler\n const handleClose = useCallback(() => {\n if (canCancel && onClose) {\n onClose();\n }\n }, [canCancel, onClose]);\n\n // Handle overlay click\n const handleOverlayClick = useCallback(() => {\n if (overlayClose) {\n handleClose();\n }\n }, [overlayClose, handleClose]);\n\n // Read when Escape arrives, so the key listener stays put while\n // `onClose` changes identity, as an inline one does on every render of\n // the parent.\n const handleCloseRef = useLatestRef(handleClose);\n\n // Joins the stack of open overlays, so the sidebar answers Escape only\n // while it's the topmost overlay, and keeps it from those under it. It's\n // modal with an overlay: without one it leaves Tab to a modal overlay\n // under it.\n const isTopmost = useOverlayStack(isOpen, overlay);\n const closesOnEscape = escapeClose && canCancel && Boolean(onClose);\n\n // Handle escape key. On `window`, as in `Modal`, so everything inside the\n // sidebar has had the key first, and an Escape it used is left to it. One\n // the sidebar closes on is marked used, so nothing under it acts on it.\n useEffect(() => {\n if (!isOpen || !closesOnEscape) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || e.defaultPrevented || !isTopmost()) return;\n e.preventDefault();\n handleCloseRef.current();\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, closesOnEscape, handleCloseRef, isTopmost]);\n\n // Keep Tab inside while there's an overlay, as `Modal` does:\n // `aria-modal` hides the rest of the page from assistive technology, so\n // the keyboard order has to agree. Only while it's the topmost modal\n // overlay, so a Modal or Dialog opened over the sidebar, even one\n // rendered inside it, holds Tab instead until it closes, and a sidebar\n // without an overlay opened over it doesn't. On `window` for the same\n // reason as Escape: a trap inside, such as a portaled popup's, has had\n // the Tab first, and one it used is left where it put focus. It's the trap\n // `useFocusTrap` sets, so a Tab the browser still takes out, as Safari\n // does past links, is sent back in. It reads the aside as each key\n // arrives, so one remounted while the sidebar is open, by a new portal\n // target or by switching `inline`, stays trapped.\n useEffect(() => {\n if (!isOpen || !overlay) return undefined;\n return trapTab(\n () => sidebarRef.current,\n window,\n () => isTopmost('modal')\n );\n }, [isOpen, overlay, isTopmost]);\n\n // Prevent body scroll when sidebar is open. Ref-counted through the shared\n // helper so an overlapping Modal/Dialog/Loading doesn't unlock underneath.\n useScrollLock(isOpen && overlay);\n\n // Move focus into the sidebar on open, to the first stop Tab wraps to or\n // the sidebar itself, and hand it back on close, as `Modal` does. A\n // different `defaultTarget` remounts the portaled sidebar: the cleanup\n // hands focus back from the old nodes, which left it on <body>, and the\n // re-run records the same opener and focuses the new nodes. Whether it\n // takes focus is decided as it opens, so `overlay` changing while it's\n // open leaves focus where the user has it.\n useEffect(() => {\n if (!isOpen) return undefined;\n const element = sidebarRef.current;\n /* istanbul ignore if: the aside renders whenever the sidebar is open, so its ref is set before this runs */\n if (!element) return undefined;\n\n // The element that had focus, wherever it sits: a portaled sidebar\n // renders under `document.body` while its opener can be inside a\n // shadow root.\n const opener = getDeepestActiveElement() as HTMLElement | null;\n // Without an overlay the sidebar holds no Tab, so with a modal overlay\n // open under it, the first Tab would take focus back there and leave\n // the sidebar's other controls out of reach. It leaves focus alone\n // then, and the cleanup below finds focus outside and leaves it too.\n if (overlay || !isModalOverlayOpen()) {\n focusTabStop(element);\n }\n\n return () => {\n // Only while the sidebar still holds focus: closing one under another\n // overlay mustn't pull focus out of the one on top, and focus moved\n // out to the page stays there. A removed subtree leaves focus on\n // <body>, which still counts as held.\n const active = getActiveElementInTree(element);\n if (active === document.body || element.contains(active)) {\n opener?.focus();\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `overlay` is read as the sidebar opens, on purpose\n }, [isOpen, defaultTarget]);\n\n // Use combined ref\n const combinedRef = useCallback(\n (node: HTMLElement | null) => {\n (sidebarRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Toast` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split.\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<HTMLElement | null>).current = node;\n }\n },\n [ref]\n );\n\n // Generate classes\n const sidebarClasses = usePrefixedClassNames('sidebar', {\n 'is-active': isOpen,\n [`is-${position}`]: position,\n 'is-fullwidth': resolvedFullwidth,\n });\n const backgroundClass = usePrefixedClassNames('sidebar-background', {\n 'is-active': isOpen,\n });\n const contentClass = usePrefixedClassNames('sidebar-content');\n\n const combinedClasses = classNames(\n sidebarClasses,\n bulmaHelperClasses,\n className\n );\n\n // Custom style for width\n const sidebarStyle: React.CSSProperties = {\n ...style,\n '--bulma-sidebar-width': resolvedFullwidth ? '100%' : width,\n } as React.CSSProperties;\n\n const sidebarContent = (\n <>\n {overlay && (\n <div\n className={backgroundClass}\n onClick={handleOverlayClick}\n aria-hidden=\"true\"\n />\n )}\n <aside\n ref={combinedRef}\n className={combinedClasses}\n style={sidebarStyle}\n role=\"dialog\"\n aria-modal={overlay ? 'true' : undefined}\n aria-hidden={!isOpen}\n // React commits this before the effect that moves focus in runs, so\n // an opening sidebar is no longer inert by then.\n {...inertProps(!isOpen)}\n tabIndex={-1}\n {...rest}\n >\n <div className={contentClass}>{children}</div>\n </aside>\n </>\n );\n\n if (inline) {\n return sidebarContent;\n }\n\n // Render to portal for proper stacking\n if (typeof document !== 'undefined') {\n const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>{sidebarContent}</LocalePortalScope>,\n target\n );\n }\n\n return null;\n }\n);\n\n// Sub-components\n\n/**\n * Props for the SidebarHeader component.\n */\ninterface SidebarHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Header content. */\n children?: React.ReactNode;\n}\n\n/**\n * Container for the sidebar header.\n *\n * @function\n * @param {SidebarHeaderProps} props - Props for the SidebarHeader component.\n * @returns {JSX.Element} The rendered sidebar header.\n */\nconst SidebarHeader: React.FC<SidebarHeaderProps> = ({\n className,\n children,\n ...props\n}) => {\n const headerClass = usePrefixedClassNames('sidebar-header');\n return (\n <div className={classNames(headerClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the SidebarTitle component.\n */\ninterface SidebarTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {\n /** Title content. */\n children?: React.ReactNode;\n}\n\n/**\n * Title text inside the header.\n *\n * @function\n * @param {SidebarTitleProps} props - Props for the SidebarTitle component.\n * @returns {JSX.Element} The rendered sidebar title.\n */\nconst SidebarTitle: React.FC<SidebarTitleProps> = ({\n className,\n children,\n ...props\n}) => {\n const titleClass = usePrefixedClassNames('sidebar-title');\n return (\n <p className={classNames(titleClass, className)} {...props}>\n {children}\n </p>\n );\n};\n\n/**\n * Props for the SidebarClose component.\n * Extends standard button attributes.\n * @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a close button inside a form does not submit it. Pass `'submit'` or `'reset'` and yours is used; any other value, or a spread carrying `type: undefined`, renders `'button'`.\n * @extraProp {string} [aria-label='Close'] - Accessible name. Pass your own to replace it. An empty one, or a spread carrying `'aria-label': undefined`, keeps the default rather than leaving the button unnamed.\n */\ntype SidebarCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for the sidebar.\n *\n * @function\n * @param {SidebarCloseProps} props - Props for the SidebarClose component.\n * @returns {JSX.Element} The rendered close button.\n */\nconst SidebarClose: React.FC<SidebarCloseProps> = ({\n className,\n children,\n ...props\n}) => {\n const closeClass = usePrefixedClassNames('sidebar-close');\n return (\n <button\n className={classNames(closeClass, className)}\n {...props}\n // After the spread, reading through it: a key the spread carries with no\n // value would otherwise erase the default, leaving a nameless button\n // that submits the form around it. An empty label falls back too: the\n // button is drawn as an icon, so `''` would leave it unnamed. A caller's\n // own value still wins; `buttonType` says more.\n aria-label={props['aria-label'] || 'Close'}\n type={buttonType(props.type)}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Props for the SidebarBody component.\n */\ninterface SidebarBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Body content. */\n children?: React.ReactNode;\n}\n\n/**\n * Main content area of the sidebar.\n *\n * @function\n * @param {SidebarBodyProps} props - Props for the SidebarBody component.\n * @returns {JSX.Element} The rendered sidebar body.\n */\nconst SidebarBody: React.FC<SidebarBodyProps> = ({\n className,\n children,\n ...props\n}) => {\n const bodyClass = usePrefixedClassNames('sidebar-body');\n return (\n <div className={classNames(bodyClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the SidebarFooter component.\n */\ninterface SidebarFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Footer content. */\n children?: React.ReactNode;\n}\n\n/**\n * Footer area of the sidebar.\n *\n * @function\n * @param {SidebarFooterProps} props - Props for the SidebarFooter component.\n * @returns {JSX.Element} The rendered sidebar footer.\n */\nconst SidebarFooter: React.FC<SidebarFooterProps> = ({\n className,\n children,\n ...props\n}) => {\n const footerClass = usePrefixedClassNames('sidebar-footer');\n return (\n <div className={classNames(footerClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n// Attach static subcomponents\nexport const Sidebar = withSubComponents(\n SidebarComponent,\n {\n Header: SidebarHeader,\n Title: SidebarTitle,\n Close: SidebarClose,\n Body: SidebarBody,\n Footer: SidebarFooter,\n },\n 'Sidebar'\n);\n\nexport default Sidebar;\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sources":["../../../src/components/Sidebar.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useScrollLock } from '../helpers/scrollLock';\nimport { usePortalContainer } from '../helpers/portal';\nimport { LocalePortalScope } from '../helpers/LocaleProvider';\nimport { useConfig } from '../helpers/Config';\nimport { buttonType } from '../helpers/buttonType';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { isModalOverlayOpen, useOverlayStack } from '../helpers/overlayStack';\nimport { focusTabStop, trapTab } from '../helpers/useFocusTrap';\nimport { inertProps } from '../helpers/inertProps';\nimport {\n getActiveElementInTree,\n getDeepestActiveElement,\n} from '../helpers/shadowDom';\n\n/** Position of the sidebar relative to the viewport. */\nexport type SidebarPosition = 'left' | 'right';\n\n/**\n * Props for the Sidebar component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the sidebar element.\n */\nexport interface SidebarProps\n extends\n Omit<React.HTMLAttributes<HTMLElement>, 'children' | 'color'>,\n BulmaClassesProps {\n /**\n * Whether the sidebar is open (required). Opening moves focus into the\n * sidebar, to its first tab stop or the sidebar itself, except for a sidebar\n * without an overlay opened while a modal overlay, such as a Modal, is open:\n * that one leaves focus where it is. That's decided as it opens, and\n * changing `overlay` while it's open doesn't move focus. Closing hands\n * focus back to whatever had it when the sidebar opened, unless focus has\n * already left the sidebar, as it does for an overlay opened over it. A\n * closed sidebar stays in the page, so it can slide out, and is `inert` and\n * `aria-hidden` there: Tab passes over its content and assistive\n * technology doesn't read it.\n */\n isOpen: boolean;\n /** Callback when sidebar should close. */\n onClose?: () => void;\n /** Which side the sidebar appears from. Default: 'left'. */\n position?: SidebarPosition;\n /** Custom width of the sidebar. */\n width?: string;\n /** Sidebar takes full width (mobile-style). */\n isFullwidth?: boolean;\n /** Sidebar takes full width (mobile-style). @deprecated Use `isFullwidth` instead — `isFullwidth` wins if both are set. */\n fullWidth?: boolean;\n /**\n * Show an overlay behind the sidebar, which makes it modal: it gets\n * `aria-modal=\"true\"`, locks body scroll, and keeps Tab and Shift+Tab\n * inside it while it is the topmost modal overlay. A Modal or Dialog opened\n * over it, even one rendered inside it, holds Tab until it closes. Without\n * an overlay the sidebar isn't modal and holds no Tab: on the page, Tab\n * moves in and out of it freely, and opened over a Modal, it leaves the\n * Modal holding Tab, and focus, while still taking Escape first. Whether\n * the sidebar takes focus is decided as it opens: changing this while it's\n * open moves the Tab trap, not focus. Default: true.\n */\n overlay?: boolean;\n /** Close sidebar when overlay is clicked. Default: true. */\n overlayClose?: boolean;\n /**\n * Close sidebar on Escape key. Only the topmost open overlay responds,\n * whichever Modal, Dialog, Sidebar or full-page Loading opened last, so\n * Escape closes one layer at a time. The sidebar marks the Escape it closes\n * on as used with `preventDefault()`, and a Toast waits until no overlay is\n * open. Turned off, a sidebar on top still keeps Escape from the layers\n * under it. A popup inside it, such as a Dropdown's menu or a date picker's\n * calendar, takes its own Escape first, and so does content that calls\n * `preventDefault()` on it. Default: true.\n */\n escapeClose?: boolean;\n /** Allow closing the sidebar. Default: true. */\n canCancel?: boolean;\n /** Content to display in the sidebar. */\n children?: React.ReactNode;\n /** Renders inline instead of using a portal. */\n inline?: boolean;\n}\n\n/**\n * The `Sidebar` component provides a slide-out navigation panel that appears from the left or right side of the screen.\n *\n * @function\n * @param {SidebarProps} props - Props for the Sidebar component.\n * @param {React.Ref<HTMLElement>} ref - Forwarded ref to the sidebar element.\n * @returns {JSX.Element | null} The rendered sidebar component.\n *\n * @example\n * // Basic sidebar\n * const [isOpen, setIsOpen] = useState(false);\n * <Sidebar isOpen={isOpen} onClose={() => setIsOpen(false)}>\n * <Menu>...</Menu>\n * </Sidebar>\n *\n * @example\n * // Right-side sidebar with custom width\n * <Sidebar\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * position=\"right\"\n * width=\"320px\"\n * >\n * <div>Panel content</div>\n * </Sidebar>\n */\nconst SidebarComponent = forwardRef<HTMLElement, SidebarProps>(\n (\n {\n isOpen,\n onClose,\n position = 'left',\n width = '260px',\n isFullwidth,\n fullWidth,\n overlay = true,\n overlayClose = true,\n escapeClose = true,\n canCancel = true,\n children,\n inline = false,\n className,\n style,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const resolveContainer = usePortalContainer();\n const { portalContainer } = useConfig();\n // Where the configured default puts the sidebar. An `inline` one doesn't\n // portal, so a change to the default moves nothing.\n const defaultTarget = inline ? undefined : portalContainer;\n const sidebarRef = useRef<HTMLElement>(null);\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const resolvedFullwidth = isFullwidth ?? fullWidth ?? false;\n\n // Close handler\n const handleClose = useCallback(() => {\n if (canCancel && onClose) {\n onClose();\n }\n }, [canCancel, onClose]);\n\n // Handle overlay click\n const handleOverlayClick = useCallback(() => {\n if (overlayClose) {\n handleClose();\n }\n }, [overlayClose, handleClose]);\n\n // Read when Escape arrives, so the key listener stays put while\n // `onClose` changes identity, as an inline one does on every render of\n // the parent.\n const handleCloseRef = useLatestRef(handleClose);\n\n // Joins the stack of open overlays, so the sidebar answers Escape only\n // while it's the topmost overlay, and keeps it from those under it. It's\n // modal with an overlay: without one it leaves Tab to a modal overlay\n // under it.\n const isTopmost = useOverlayStack(isOpen, overlay);\n const closesOnEscape = escapeClose && canCancel && Boolean(onClose);\n\n // Handle escape key. On `window`, as in `Modal`, so everything inside the\n // sidebar has had the key first, and an Escape it used is left to it. One\n // the sidebar closes on is marked used, so nothing under it acts on it.\n useEffect(() => {\n if (!isOpen || !closesOnEscape) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || e.defaultPrevented || !isTopmost()) return;\n e.preventDefault();\n handleCloseRef.current();\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, closesOnEscape, handleCloseRef, isTopmost]);\n\n // Keep Tab inside while there's an overlay, as `Modal` does:\n // `aria-modal` hides the rest of the page from assistive technology, so\n // the keyboard order has to agree. Only while it's the topmost modal\n // overlay, so a Modal or Dialog opened over the sidebar, even one\n // rendered inside it, holds Tab instead until it closes, and a sidebar\n // without an overlay opened over it doesn't. On `window` for the same\n // reason as Escape: a trap inside, such as a portaled popup's, has had\n // the Tab first, and one it used is left where it put focus. It's the trap\n // `useFocusTrap` sets, so a Tab the browser still takes out, as Safari\n // does past links, is sent back in. It reads the aside as each key\n // arrives, so one remounted while the sidebar is open, by a new portal\n // target or by switching `inline`, stays trapped.\n useEffect(() => {\n if (!isOpen || !overlay) return undefined;\n return trapTab(\n () => sidebarRef.current,\n window,\n () => isTopmost('modal')\n );\n }, [isOpen, overlay, isTopmost]);\n\n // Prevent body scroll when sidebar is open. Ref-counted through the shared\n // helper so an overlapping Modal/Dialog/Loading doesn't unlock underneath.\n useScrollLock(isOpen && overlay);\n\n // Move focus into the sidebar on open, to the first stop Tab wraps to or\n // the sidebar itself, and hand it back on close, as `Modal` does. A\n // different `defaultTarget` remounts the portaled sidebar: the cleanup\n // hands focus back from the old nodes, which left it on <body>, and the\n // re-run records the same opener and focuses the new nodes. Whether it\n // takes focus is decided as it opens, so `overlay` changing while it's\n // open leaves focus where the user has it.\n useEffect(() => {\n if (!isOpen) return undefined;\n const element = sidebarRef.current;\n /* istanbul ignore if: the aside renders whenever the sidebar is open, so its ref is set before this runs */\n if (!element) return undefined;\n\n // The element that had focus, wherever it sits: a portaled sidebar\n // renders under `document.body` while its opener can be inside a\n // shadow root.\n const opener = getDeepestActiveElement() as HTMLElement | null;\n // Without an overlay the sidebar holds no Tab, so with a modal overlay\n // open under it, the first Tab would take focus back there and leave\n // the sidebar's other controls out of reach. It leaves focus alone\n // then, and the cleanup below finds focus outside and leaves it too.\n if (overlay || !isModalOverlayOpen()) {\n focusTabStop(element);\n }\n\n return () => {\n // Only while the sidebar still holds focus: closing one under another\n // overlay mustn't pull focus out of the one on top, and focus moved\n // out to the page stays there. A removed subtree leaves focus on\n // <body>, which still counts as held.\n const active = getActiveElementInTree(element);\n if (active === document.body || element.contains(active)) {\n opener?.focus();\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `overlay` is read as the sidebar opens, on purpose\n }, [isOpen, defaultTarget]);\n\n // Use combined ref\n const combinedRef = useCallback(\n (node: HTMLElement | null) => {\n (sidebarRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Toast` and `Carousel`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split.\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<HTMLElement | null>).current = node;\n }\n },\n [ref]\n );\n\n // Generate classes\n const sidebarClasses = usePrefixedClassNames('sidebar', {\n 'is-active': isOpen,\n [`is-${position}`]: position,\n 'is-fullwidth': resolvedFullwidth,\n });\n const backgroundClass = usePrefixedClassNames('sidebar-background', {\n 'is-active': isOpen,\n });\n const contentClass = usePrefixedClassNames('sidebar-content');\n\n const combinedClasses = classNames(\n sidebarClasses,\n bulmaHelperClasses,\n className\n );\n\n // Custom style for width\n const sidebarStyle: React.CSSProperties = {\n ...style,\n '--bulma-sidebar-width': resolvedFullwidth ? '100%' : width,\n } as React.CSSProperties;\n\n const sidebarContent = (\n <>\n {overlay && (\n <div\n className={backgroundClass}\n onClick={handleOverlayClick}\n aria-hidden=\"true\"\n />\n )}\n <aside\n ref={combinedRef}\n className={combinedClasses}\n style={sidebarStyle}\n role=\"dialog\"\n aria-modal={overlay ? 'true' : undefined}\n aria-hidden={!isOpen}\n // React commits this before the effect that moves focus in runs, so\n // an opening sidebar is no longer inert by then.\n {...inertProps(!isOpen)}\n tabIndex={-1}\n {...rest}\n >\n <div className={contentClass}>{children}</div>\n </aside>\n </>\n );\n\n if (inline) {\n return sidebarContent;\n }\n\n // Render to portal for proper stacking\n if (typeof document !== 'undefined') {\n const target = resolveContainer();\n return createPortal(\n <LocalePortalScope target={target}>{sidebarContent}</LocalePortalScope>,\n target\n );\n }\n\n return null;\n }\n);\n\n// Sub-components\n\n/**\n * Props for the SidebarHeader component.\n */\ninterface SidebarHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Header content. */\n children?: React.ReactNode;\n}\n\n/**\n * Container for the sidebar header.\n *\n * @function\n * @param {SidebarHeaderProps} props - Props for the SidebarHeader component.\n * @returns {JSX.Element} The rendered sidebar header.\n */\nconst SidebarHeader: React.FC<SidebarHeaderProps> = ({\n className,\n children,\n ...props\n}) => {\n const headerClass = usePrefixedClassNames('sidebar-header');\n return (\n <div className={classNames(headerClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the SidebarTitle component.\n */\ninterface SidebarTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {\n /** Title content. */\n children?: React.ReactNode;\n}\n\n/**\n * Title text inside the header.\n *\n * @function\n * @param {SidebarTitleProps} props - Props for the SidebarTitle component.\n * @returns {JSX.Element} The rendered sidebar title.\n */\nconst SidebarTitle: React.FC<SidebarTitleProps> = ({\n className,\n children,\n ...props\n}) => {\n const titleClass = usePrefixedClassNames('sidebar-title');\n return (\n <p className={classNames(titleClass, className)} {...props}>\n {children}\n </p>\n );\n};\n\n/**\n * Props for the SidebarClose component.\n * Extends standard button attributes.\n * @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a close button inside a form does not submit it. Pass `'submit'` or `'reset'` and yours is used; any other value, or a spread carrying `type: undefined`, renders `'button'`.\n * @extraProp {string} [aria-label='Close'] - Accessible name. Pass your own to replace it. An empty one, or a spread carrying `'aria-label': undefined`, keeps the default rather than leaving the button unnamed.\n */\ntype SidebarCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for the sidebar.\n *\n * @function\n * @param {SidebarCloseProps} props - Props for the SidebarClose component.\n * @returns {JSX.Element} The rendered close button.\n */\nconst SidebarClose: React.FC<SidebarCloseProps> = ({\n className,\n children,\n ...props\n}) => {\n const closeClass = usePrefixedClassNames('sidebar-close');\n return (\n <button\n className={classNames(closeClass, className)}\n {...props}\n // After the spread, reading through it: a key the spread carries with no\n // value would otherwise erase the default, leaving a nameless button\n // that submits the form around it. An empty label falls back too: the\n // button is drawn as an icon, so `''` would leave it unnamed. A caller's\n // own value still wins; `buttonType` says more.\n aria-label={props['aria-label'] || 'Close'}\n type={buttonType(props.type)}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Props for the SidebarBody component.\n */\ninterface SidebarBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Body content. */\n children?: React.ReactNode;\n}\n\n/**\n * Main content area of the sidebar.\n *\n * @function\n * @param {SidebarBodyProps} props - Props for the SidebarBody component.\n * @returns {JSX.Element} The rendered sidebar body.\n */\nconst SidebarBody: React.FC<SidebarBodyProps> = ({\n className,\n children,\n ...props\n}) => {\n const bodyClass = usePrefixedClassNames('sidebar-body');\n return (\n <div className={classNames(bodyClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the SidebarFooter component.\n */\ninterface SidebarFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Footer content. */\n children?: React.ReactNode;\n}\n\n/**\n * Footer area of the sidebar.\n *\n * @function\n * @param {SidebarFooterProps} props - Props for the SidebarFooter component.\n * @returns {JSX.Element} The rendered sidebar footer.\n */\nconst SidebarFooter: React.FC<SidebarFooterProps> = ({\n className,\n children,\n ...props\n}) => {\n const footerClass = usePrefixedClassNames('sidebar-footer');\n return (\n <div className={classNames(footerClass, className)} {...props}>\n {children}\n </div>\n );\n};\n\n// Attach static subcomponents\nexport const Sidebar = withSubComponents(\n SidebarComponent,\n {\n Header: SidebarHeader,\n Title: SidebarTitle,\n Close: SidebarClose,\n Body: SidebarBody,\n Footer: SidebarFooter,\n },\n 'Sidebar'\n);\n\nexport default Sidebar;\n"],"names":["_jsxs","_Fragment","_jsx"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
'use client';
|
|
2
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { classNames, usePrefixedClassNames } from '../helpers/classNames.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Steps.js","sources":["../../../src/components/Steps.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useNumberFormat } from '../helpers/localeFormat';\n\n/** Available size modifiers for the Steps component. */\nexport type StepsSize = 'small' | 'medium' | 'large';\n/** Available color variants for the Steps component. */\nexport type StepsColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * Props for individual Step items.\n */\nexport interface StepItemProps {\n /**\n * Step label/title. On a `clickable` step it's rendered inside the step's\n * `<button>`, so it has to be phrasing content, like text, a `<span>` or an\n * icon, with no link, button or other control in it.\n */\n label?: React.ReactNode;\n /** Icon for the step marker */\n icon?: React.ReactNode;\n /**\n * Icon shown when the step is completed.\n * @defaultValue '✓'\n */\n completedIcon?: React.ReactNode;\n /**\n * Whether this step is clickable. A clickable step puts its marker and\n * label in a `<button type=\"button\">` inside its list item, which calls\n * `onStepClick`, and the current step's `aria-current` goes on that button.\n */\n clickable?: boolean;\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for the Steps component.\n * @extraProp {React.ReactNode} [children] - Step children (alternative to items).\n * @extraProp {string} [className] - Additional CSS classes.\n */\nexport interface StepsProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Current active step (0-indexed). */\n value?: number;\n /** Array of step items. */\n items?: StepItemProps[];\n /** Size of the steps. */\n size?: StepsSize;\n /** Color variant. */\n color?: StepsColor;\n /** Show step markers. Default: true. */\n hasMarker?: boolean;\n /** Enable animations. Default: true. */\n animated?: boolean;\n /** Use rounded markers. Default: true. */\n rounded?: boolean;\n /** Vertical layout. */\n vertical?: boolean;\n /**\n * Position of labels. `right` and `left` mean the end and the start of the\n * line, so in a right-to-left page `right` puts each label to the left of\n * its marker, and `left` to the right.\n */\n labelPosition?: 'bottom' | 'right' | 'left';\n /** Mobile display mode. */\n mobileMode?: 'minimal' | 'compact' | 'right';\n /** Displays step numbers in the markers. */\n showStepNumbers?: boolean;\n /**\n * Shows previous/next navigation buttons. They render `type=\"button\"`, so a\n * multi-step form wrapped around the steps is not submitted by moving\n * between them.\n */\n hasNavigation?: boolean;\n /** Label for the previous button. */\n prevLabel?: string;\n /** Label for the next button. */\n nextLabel?: string;\n /** Callback when previous button is clicked. */\n onPrev?: () => void;\n /** Callback when next button is clicked. */\n onNext?: () => void;\n /** Callback when a step is clicked. */\n onStepClick?: (step: number) => void;\n}\n\n/**\n * Props for the Step subcomponent.\n */\nexport interface StepProps\n extends\n Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Whether this step is active */\n isActive?: boolean;\n /** Whether this step is completed */\n isCompleted?: boolean;\n /**\n * Step label/title, or pass it as `children`. On a `clickable` step it's\n * rendered inside the step's `<button>`, so it has to be phrasing content,\n * like text, a `<span>` or an icon, with no link, button or other control\n * in it.\n */\n label?: React.ReactNode;\n /** Icon for the step marker */\n icon?: React.ReactNode;\n /**\n * Whether this step is clickable. A clickable step puts its marker and\n * label in a `<button type=\"button\">` inside the `<li>`, which calls\n * `onClick`, and `aria-current` goes on that button. The `<li>` keeps the\n * rest of the props.\n */\n clickable?: boolean;\n /** Click handler */\n onClick?: () => void;\n /**\n * Step number to display in marker (1-indexed), written the way the\n * `locale` of a `LocaleProvider` around it writes numbers.\n */\n stepNumber?: number;\n /**\n * Icon shown when the step is completed.\n * @defaultValue '✓'\n */\n completedIcon?: React.ReactNode;\n}\n\n/**\n * Individual Step component for use inside Steps.\n *\n * @function\n * @param {StepProps} props - Props for the Step component.\n * @returns {JSX.Element} The rendered step segment.\n */\nexport const Step: React.FC<StepProps> = ({\n isActive = false,\n isCompleted = false,\n label,\n icon,\n clickable = false,\n onClick,\n stepNumber,\n completedIcon,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const formatNumber = useNumberFormat();\n\n const stepClasses = classNames(\n usePrefixedClassNames('steps-segment', {\n 'is-active': isActive,\n 'is-completed': isCompleted,\n }),\n bulmaHelperClasses,\n className\n );\n const stepsLinkClass = usePrefixedClassNames('steps-link');\n const stepsMarkerClass = usePrefixedClassNames('steps-marker');\n const stepsContentClass = usePrefixedClassNames('steps-content');\n const stepsTitleClass = usePrefixedClassNames('steps-title');\n\n const resolvedCompletedIcon =\n completedIcon === undefined ? '\\u2713' : completedIcon;\n const markerContent =\n icon ||\n (isCompleted && resolvedCompletedIcon\n ? resolvedCompletedIcon\n : stepNumber == null || !formatNumber\n ? (stepNumber ?? null)\n : formatNumber(stepNumber));\n const title = label || children;\n const current = isActive ? 'step' : undefined;\n\n // The step stays a list item, and a real button inside it does the\n // clicking, so the list keeps its items and the button brings Enter, Space\n // and focus with it. A button holds only phrasing content, so its parts\n // are spans.\n if (clickable) {\n return (\n <li className={stepClasses} {...rest}>\n <button\n type=\"button\"\n className={stepsLinkClass}\n onClick={() => onClick?.()}\n aria-current={current}\n >\n <span className={stepsMarkerClass}>{markerContent}</span>\n {title && (\n <span className={stepsContentClass}>\n <span className={stepsTitleClass}>{title}</span>\n </span>\n )}\n </button>\n </li>\n );\n }\n\n return (\n <li className={stepClasses} aria-current={current} {...rest}>\n <div className={stepsLinkClass}>\n <span className={stepsMarkerClass}>{markerContent}</span>\n {title && (\n <div className={stepsContentClass}>\n <p className={stepsTitleClass}>{title}</p>\n </div>\n )}\n </div>\n </li>\n );\n};\n\n/**\n * The `Steps` component provides a multi-step progress indicator for wizard flows, checkout processes, or any multi-step workflow.\n *\n * @function\n * @param {StepsProps} props - Props for the Steps component.\n * @returns {JSX.Element} The rendered steps component.\n *\n * @example\n * // Basic steps with items\n * <Steps\n * value={1}\n * items={[\n * { label: 'Account' },\n * { label: 'Profile' },\n * { label: 'Complete' },\n * ]}\n * />\n *\n * @example\n * // Clickable steps with navigation\n * <Steps\n * value={currentStep}\n * onStepClick={(step) => setCurrentStep(step)}\n * hasNavigation\n * items={[\n * { label: 'Step 1', clickable: true },\n * { label: 'Step 2', clickable: true },\n * { label: 'Step 3', clickable: true },\n * ]}\n * />\n */\nconst StepsComponent: React.FC<StepsProps> = ({\n value = 0,\n items,\n size,\n color,\n hasMarker = true,\n animated = true,\n rounded = true,\n vertical = false,\n labelPosition = 'bottom',\n mobileMode,\n showStepNumbers = true,\n hasNavigation = false,\n prevLabel,\n nextLabel,\n onPrev,\n onNext,\n onStepClick,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate classes for the wrapper div\n const stepsClasses = usePrefixedClassNames('steps', {\n [`is-${size}`]: size,\n [`is-${color}`]: color,\n 'has-marker': hasMarker,\n 'is-animated': animated,\n 'is-rounded': rounded,\n 'is-vertical': vertical,\n [`has-label-${labelPosition}`]:\n labelPosition && (labelPosition !== 'bottom' || vertical),\n [`is-${mobileMode}`]: mobileMode,\n });\n\n const combinedClasses = classNames(\n stepsClasses,\n bulmaHelperClasses,\n className\n );\n\n // Generate classes for the ul (list)\n const listClasses = usePrefixedClassNames('steps-list', {\n 'is-vertical': vertical,\n });\n const stepsNavigationClass = usePrefixedClassNames('steps-navigation');\n const prevButtonClass = usePrefixedClassNames('button');\n const nextButtonClass = usePrefixedClassNames('button', {\n 'is-primary': true,\n });\n\n // Count total steps for navigation\n const totalSteps = items ? items.length : React.Children.count(children);\n\n // Render items if provided\n const renderSteps = () => {\n if (items && items.length > 0) {\n return items.map((item, index) => (\n <Step\n key={index}\n isActive={index === value}\n isCompleted={index < value}\n label={item.label}\n icon={item.icon}\n completedIcon={item.completedIcon}\n clickable={item.clickable}\n stepNumber={showStepNumbers ? index + 1 : undefined}\n onClick={\n item.clickable && onStepClick ? () => onStepClick(index) : undefined\n }\n className={item.className}\n />\n ));\n }\n\n // If children are provided, clone them with active/completed states\n if (children) {\n return React.Children.map(children, (child, index) => {\n if (React.isValidElement<StepProps>(child)) {\n return React.cloneElement(child, {\n isActive: index === value,\n isCompleted: index < value,\n stepNumber: showStepNumbers ? index + 1 : undefined,\n onClick:\n child.props.clickable && onStepClick\n ? () => onStepClick(index)\n : child.props.onClick,\n });\n }\n return child;\n });\n }\n\n return null;\n };\n\n // role=\"list\" restates the <ul>'s own role, for Safari: WebKit stops\n // exposing a list as one once its markers are hidden, as they are here,\n // unless the role is set explicitly.\n return (\n <div className={combinedClasses} {...rest}>\n <ul className={listClasses} role=\"list\">\n {renderSteps()}\n </ul>\n {hasNavigation && (\n <div className={stepsNavigationClass}>\n <button\n type=\"button\"\n className={prevButtonClass}\n disabled={value === 0}\n onClick={onPrev ?? (() => onStepClick?.(value - 1))}\n >\n {prevLabel ?? 'Previous'}\n </button>\n <button\n type=\"button\"\n className={nextButtonClass}\n disabled={value === totalSteps - 1}\n onClick={onNext ?? (() => onStepClick?.(value + 1))}\n >\n {nextLabel ?? 'Next'}\n </button>\n </div>\n )}\n </div>\n );\n};\n\n// Attach Step as static property\nexport const Steps = withSubComponents(StepsComponent, { Step }, 'Steps');\n\nexport default Steps;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Steps.js","sources":["../../../src/components/Steps.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useNumberFormat } from '../helpers/localeFormat';\n\n/** Available size modifiers for the Steps component. */\nexport type StepsSize = 'small' | 'medium' | 'large';\n/** Available color variants for the Steps component. */\nexport type StepsColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * Props for individual Step items.\n */\nexport interface StepItemProps {\n /**\n * Step label/title. On a `clickable` step it's rendered inside the step's\n * `<button>`, so it has to be phrasing content, like text, a `<span>` or an\n * icon, with no link, button or other control in it.\n */\n label?: React.ReactNode;\n /** Icon for the step marker */\n icon?: React.ReactNode;\n /**\n * Icon shown when the step is completed.\n * @defaultValue '✓'\n */\n completedIcon?: React.ReactNode;\n /**\n * Whether this step is clickable. A clickable step puts its marker and\n * label in a `<button type=\"button\">` inside its list item, which calls\n * `onStepClick`, and the current step's `aria-current` goes on that button.\n */\n clickable?: boolean;\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for the Steps component.\n * @extraProp {React.ReactNode} [children] - Step children (alternative to items).\n * @extraProp {string} [className] - Additional CSS classes.\n */\nexport interface StepsProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size'> {\n /** Current active step (0-indexed). */\n value?: number;\n /** Array of step items. */\n items?: StepItemProps[];\n /** Size of the steps. */\n size?: StepsSize;\n /** Color variant. */\n color?: StepsColor;\n /** Show step markers. Default: true. */\n hasMarker?: boolean;\n /** Enable animations. Default: true. */\n animated?: boolean;\n /** Use rounded markers. Default: true. */\n rounded?: boolean;\n /** Vertical layout. */\n vertical?: boolean;\n /**\n * Position of labels. `right` and `left` mean the end and the start of the\n * line, so in a right-to-left page `right` puts each label to the left of\n * its marker, and `left` to the right.\n */\n labelPosition?: 'bottom' | 'right' | 'left';\n /** Mobile display mode. */\n mobileMode?: 'minimal' | 'compact' | 'right';\n /** Displays step numbers in the markers. */\n showStepNumbers?: boolean;\n /**\n * Shows previous/next navigation buttons. They render `type=\"button\"`, so a\n * multi-step form wrapped around the steps is not submitted by moving\n * between them.\n */\n hasNavigation?: boolean;\n /** Label for the previous button. */\n prevLabel?: string;\n /** Label for the next button. */\n nextLabel?: string;\n /** Callback when previous button is clicked. */\n onPrev?: () => void;\n /** Callback when next button is clicked. */\n onNext?: () => void;\n /** Callback when a step is clicked. */\n onStepClick?: (step: number) => void;\n}\n\n/**\n * Props for the Step subcomponent.\n */\nexport interface StepProps\n extends\n Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Whether this step is active */\n isActive?: boolean;\n /** Whether this step is completed */\n isCompleted?: boolean;\n /**\n * Step label/title, or pass it as `children`. On a `clickable` step it's\n * rendered inside the step's `<button>`, so it has to be phrasing content,\n * like text, a `<span>` or an icon, with no link, button or other control\n * in it.\n */\n label?: React.ReactNode;\n /** Icon for the step marker */\n icon?: React.ReactNode;\n /**\n * Whether this step is clickable. A clickable step puts its marker and\n * label in a `<button type=\"button\">` inside the `<li>`, which calls\n * `onClick`, and `aria-current` goes on that button. The `<li>` keeps the\n * rest of the props.\n */\n clickable?: boolean;\n /** Click handler */\n onClick?: () => void;\n /**\n * Step number to display in marker (1-indexed), written the way the\n * `locale` of a `LocaleProvider` around it writes numbers.\n */\n stepNumber?: number;\n /**\n * Icon shown when the step is completed.\n * @defaultValue '✓'\n */\n completedIcon?: React.ReactNode;\n}\n\n/**\n * Individual Step component for use inside Steps.\n *\n * @function\n * @param {StepProps} props - Props for the Step component.\n * @returns {JSX.Element} The rendered step segment.\n */\nexport const Step: React.FC<StepProps> = ({\n isActive = false,\n isCompleted = false,\n label,\n icon,\n clickable = false,\n onClick,\n stepNumber,\n completedIcon,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const formatNumber = useNumberFormat();\n\n const stepClasses = classNames(\n usePrefixedClassNames('steps-segment', {\n 'is-active': isActive,\n 'is-completed': isCompleted,\n }),\n bulmaHelperClasses,\n className\n );\n const stepsLinkClass = usePrefixedClassNames('steps-link');\n const stepsMarkerClass = usePrefixedClassNames('steps-marker');\n const stepsContentClass = usePrefixedClassNames('steps-content');\n const stepsTitleClass = usePrefixedClassNames('steps-title');\n\n const resolvedCompletedIcon =\n completedIcon === undefined ? '\\u2713' : completedIcon;\n const markerContent =\n icon ||\n (isCompleted && resolvedCompletedIcon\n ? resolvedCompletedIcon\n : stepNumber == null || !formatNumber\n ? (stepNumber ?? null)\n : formatNumber(stepNumber));\n const title = label || children;\n const current = isActive ? 'step' : undefined;\n\n // The step stays a list item, and a real button inside it does the\n // clicking, so the list keeps its items and the button brings Enter, Space\n // and focus with it. A button holds only phrasing content, so its parts\n // are spans.\n if (clickable) {\n return (\n <li className={stepClasses} {...rest}>\n <button\n type=\"button\"\n className={stepsLinkClass}\n onClick={() => onClick?.()}\n aria-current={current}\n >\n <span className={stepsMarkerClass}>{markerContent}</span>\n {title && (\n <span className={stepsContentClass}>\n <span className={stepsTitleClass}>{title}</span>\n </span>\n )}\n </button>\n </li>\n );\n }\n\n return (\n <li className={stepClasses} aria-current={current} {...rest}>\n <div className={stepsLinkClass}>\n <span className={stepsMarkerClass}>{markerContent}</span>\n {title && (\n <div className={stepsContentClass}>\n <p className={stepsTitleClass}>{title}</p>\n </div>\n )}\n </div>\n </li>\n );\n};\n\n/**\n * The `Steps` component provides a multi-step progress indicator for wizard flows, checkout processes, or any multi-step workflow.\n *\n * @function\n * @param {StepsProps} props - Props for the Steps component.\n * @returns {JSX.Element} The rendered steps component.\n *\n * @example\n * // Basic steps with items\n * <Steps\n * value={1}\n * items={[\n * { label: 'Account' },\n * { label: 'Profile' },\n * { label: 'Complete' },\n * ]}\n * />\n *\n * @example\n * // Clickable steps with navigation\n * <Steps\n * value={currentStep}\n * onStepClick={(step) => setCurrentStep(step)}\n * hasNavigation\n * items={[\n * { label: 'Step 1', clickable: true },\n * { label: 'Step 2', clickable: true },\n * { label: 'Step 3', clickable: true },\n * ]}\n * />\n */\nconst StepsComponent: React.FC<StepsProps> = ({\n value = 0,\n items,\n size,\n color,\n hasMarker = true,\n animated = true,\n rounded = true,\n vertical = false,\n labelPosition = 'bottom',\n mobileMode,\n showStepNumbers = true,\n hasNavigation = false,\n prevLabel,\n nextLabel,\n onPrev,\n onNext,\n onStepClick,\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate classes for the wrapper div\n const stepsClasses = usePrefixedClassNames('steps', {\n [`is-${size}`]: size,\n [`is-${color}`]: color,\n 'has-marker': hasMarker,\n 'is-animated': animated,\n 'is-rounded': rounded,\n 'is-vertical': vertical,\n [`has-label-${labelPosition}`]:\n labelPosition && (labelPosition !== 'bottom' || vertical),\n [`is-${mobileMode}`]: mobileMode,\n });\n\n const combinedClasses = classNames(\n stepsClasses,\n bulmaHelperClasses,\n className\n );\n\n // Generate classes for the ul (list)\n const listClasses = usePrefixedClassNames('steps-list', {\n 'is-vertical': vertical,\n });\n const stepsNavigationClass = usePrefixedClassNames('steps-navigation');\n const prevButtonClass = usePrefixedClassNames('button');\n const nextButtonClass = usePrefixedClassNames('button', {\n 'is-primary': true,\n });\n\n // Count total steps for navigation\n const totalSteps = items ? items.length : React.Children.count(children);\n\n // Render items if provided\n const renderSteps = () => {\n if (items && items.length > 0) {\n return items.map((item, index) => (\n <Step\n key={index}\n isActive={index === value}\n isCompleted={index < value}\n label={item.label}\n icon={item.icon}\n completedIcon={item.completedIcon}\n clickable={item.clickable}\n stepNumber={showStepNumbers ? index + 1 : undefined}\n onClick={\n item.clickable && onStepClick ? () => onStepClick(index) : undefined\n }\n className={item.className}\n />\n ));\n }\n\n // If children are provided, clone them with active/completed states\n if (children) {\n return React.Children.map(children, (child, index) => {\n if (React.isValidElement<StepProps>(child)) {\n return React.cloneElement(child, {\n isActive: index === value,\n isCompleted: index < value,\n stepNumber: showStepNumbers ? index + 1 : undefined,\n onClick:\n child.props.clickable && onStepClick\n ? () => onStepClick(index)\n : child.props.onClick,\n });\n }\n return child;\n });\n }\n\n return null;\n };\n\n // role=\"list\" restates the <ul>'s own role, for Safari: WebKit stops\n // exposing a list as one once its markers are hidden, as they are here,\n // unless the role is set explicitly.\n return (\n <div className={combinedClasses} {...rest}>\n <ul className={listClasses} role=\"list\">\n {renderSteps()}\n </ul>\n {hasNavigation && (\n <div className={stepsNavigationClass}>\n <button\n type=\"button\"\n className={prevButtonClass}\n disabled={value === 0}\n onClick={onPrev ?? (() => onStepClick?.(value - 1))}\n >\n {prevLabel ?? 'Previous'}\n </button>\n <button\n type=\"button\"\n className={nextButtonClass}\n disabled={value === totalSteps - 1}\n onClick={onNext ?? (() => onStepClick?.(value + 1))}\n >\n {nextLabel ?? 'Next'}\n </button>\n </div>\n )}\n </div>\n );\n};\n\n// Attach Step as static property\nexport const Steps = withSubComponents(StepsComponent, { Step }, 'Steps');\n\nexport default Steps;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
'use client';
|
|
2
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
4
|
import React, { createContext, useEffect, useRef, useCallback, useState, useId, useContext } from 'react';
|
|
4
5
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
@@ -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 { 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(\n child => React.isValidElement(child) && child.type === TabsContent\n );\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 (React.isValidElement(child) && child.type === 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 (React.isValidElement(child) && child.type === 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 { 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(\n child => React.isValidElement(child) && child.type === TabsContent\n );\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 (React.isValidElement(child) && child.type === 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 (React.isValidElement(child) && child.type === 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,4 +1,5 @@
|
|
|
1
1
|
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
'use client';
|
|
2
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
4
|
import React, { createContext, forwardRef, useContext } from 'react';
|
|
4
5
|
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|