@allxsmith/bestax-bulma 5.26.6 → 5.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/columns/Column.js +48 -0
- package/dist/esm/columns/Column.js.map +1 -0
- package/dist/esm/columns/Columns.js +53 -0
- package/dist/esm/columns/Columns.js.map +1 -0
- package/dist/esm/components/Avatar.js +299 -0
- package/dist/esm/components/Avatar.js.map +1 -0
- package/dist/esm/components/Avatars.js +81 -0
- package/dist/esm/components/Avatars.js.map +1 -0
- package/dist/esm/components/Badge.js +105 -0
- package/dist/esm/components/Badge.js.map +1 -0
- package/dist/esm/components/Breadcrumb.js +36 -0
- package/dist/esm/components/Breadcrumb.js.map +1 -0
- package/dist/esm/components/Card.js +252 -0
- package/dist/esm/components/Card.js.map +1 -0
- package/dist/esm/components/Carousel.js +351 -0
- package/dist/esm/components/Carousel.js.map +1 -0
- package/dist/esm/components/Collapse.js +193 -0
- package/dist/esm/components/Collapse.js.map +1 -0
- package/dist/esm/components/Collapses.js +99 -0
- package/dist/esm/components/Collapses.js.map +1 -0
- package/dist/esm/components/Dialog.js +230 -0
- package/dist/esm/components/Dialog.js.map +1 -0
- package/dist/esm/components/Dropdown.js +362 -0
- package/dist/esm/components/Dropdown.js.map +1 -0
- package/dist/esm/components/Loading.js +87 -0
- package/dist/esm/components/Loading.js.map +1 -0
- package/dist/esm/components/Menu.js +117 -0
- package/dist/esm/components/Menu.js.map +1 -0
- package/dist/esm/components/Message.js +56 -0
- package/dist/esm/components/Message.js.map +1 -0
- package/dist/esm/components/Modal.js +354 -0
- package/dist/esm/components/Modal.js.map +1 -0
- package/dist/esm/components/Navbar.js +287 -0
- package/dist/esm/components/Navbar.js.map +1 -0
- package/dist/esm/components/Pagination.js +191 -0
- package/dist/esm/components/Pagination.js.map +1 -0
- package/dist/esm/components/Panel.js +100 -0
- package/dist/esm/components/Panel.js.map +1 -0
- package/dist/esm/components/Popover.js +298 -0
- package/dist/esm/components/Popover.js.map +1 -0
- package/dist/esm/components/Reveal.js +157 -0
- package/dist/esm/components/Reveal.js.map +1 -0
- package/dist/esm/components/Sidebar.js +209 -0
- package/dist/esm/components/Sidebar.js.map +1 -0
- package/dist/esm/components/Steps.js +128 -0
- package/dist/esm/components/Steps.js.map +1 -0
- package/dist/esm/components/Tabs.js +335 -0
- package/dist/esm/components/Tabs.js.map +1 -0
- package/dist/esm/components/Toast.js +322 -0
- package/dist/esm/components/Toast.js.map +1 -0
- package/dist/esm/components/Tooltip.js +202 -0
- package/dist/esm/components/Tooltip.js.map +1 -0
- package/dist/esm/components/collapsesContext.js +12 -0
- package/dist/esm/components/collapsesContext.js.map +1 -0
- package/dist/esm/elements/Block.js +29 -0
- package/dist/esm/elements/Block.js.map +1 -0
- package/dist/esm/elements/Box.js +32 -0
- package/dist/esm/elements/Box.js.map +1 -0
- package/dist/esm/elements/Button.js +139 -0
- package/dist/esm/elements/Button.js.map +1 -0
- package/dist/esm/elements/Buttons.js +42 -0
- package/dist/esm/elements/Buttons.js.map +1 -0
- package/dist/esm/elements/Code.js +25 -0
- package/dist/esm/elements/Code.js.map +1 -0
- package/dist/esm/elements/Content.js +33 -0
- package/dist/esm/elements/Content.js.map +1 -0
- package/dist/esm/elements/Delete.js +35 -0
- package/dist/esm/elements/Delete.js.map +1 -0
- package/dist/esm/elements/Divider.js +27 -0
- package/dist/esm/elements/Divider.js.map +1 -0
- package/dist/esm/elements/Emphasis.js +25 -0
- package/dist/esm/elements/Emphasis.js.map +1 -0
- package/dist/esm/elements/Figure.js +58 -0
- package/dist/esm/elements/Figure.js.map +1 -0
- package/dist/esm/elements/Icon.js +256 -0
- package/dist/esm/elements/Icon.js.map +1 -0
- package/dist/esm/elements/IconText.js +36 -0
- package/dist/esm/elements/IconText.js.map +1 -0
- package/dist/esm/elements/Image.js +46 -0
- package/dist/esm/elements/Image.js.map +1 -0
- package/dist/esm/elements/Link.js +36 -0
- package/dist/esm/elements/Link.js.map +1 -0
- package/dist/esm/elements/LinkButton.js +37 -0
- package/dist/esm/elements/LinkButton.js.map +1 -0
- package/dist/esm/elements/ListItem.js +28 -0
- package/dist/esm/elements/ListItem.js.map +1 -0
- package/dist/esm/elements/Loader.js +37 -0
- package/dist/esm/elements/Loader.js.map +1 -0
- package/dist/esm/elements/Notification.js +316 -0
- package/dist/esm/elements/Notification.js.map +1 -0
- package/dist/esm/elements/OrderedList.js +31 -0
- package/dist/esm/elements/OrderedList.js.map +1 -0
- package/dist/esm/elements/Paragraph.js +28 -0
- package/dist/esm/elements/Paragraph.js.map +1 -0
- package/dist/esm/elements/Pre.js +25 -0
- package/dist/esm/elements/Pre.js.map +1 -0
- package/dist/esm/elements/Progress.js +33 -0
- package/dist/esm/elements/Progress.js.map +1 -0
- package/dist/esm/elements/Skeleton.js +30 -0
- package/dist/esm/elements/Skeleton.js.map +1 -0
- package/dist/esm/elements/Span.js +28 -0
- package/dist/esm/elements/Span.js.map +1 -0
- package/dist/esm/elements/Strong.js +25 -0
- package/dist/esm/elements/Strong.js.map +1 -0
- package/dist/esm/elements/SubTitle.js +51 -0
- package/dist/esm/elements/SubTitle.js.map +1 -0
- package/dist/esm/elements/Table.js +51 -0
- package/dist/esm/elements/Table.js.map +1 -0
- package/dist/esm/elements/Tag.js +49 -0
- package/dist/esm/elements/Tag.js.map +1 -0
- package/dist/esm/elements/Tags.js +34 -0
- package/dist/esm/elements/Tags.js.map +1 -0
- package/dist/esm/elements/Tbody.js +26 -0
- package/dist/esm/elements/Tbody.js.map +1 -0
- package/dist/esm/elements/Td.js +61 -0
- package/dist/esm/elements/Td.js.map +1 -0
- package/dist/esm/elements/Tfoot.js +26 -0
- package/dist/esm/elements/Tfoot.js.map +1 -0
- package/dist/esm/elements/Th.js +34 -0
- package/dist/esm/elements/Th.js.map +1 -0
- package/dist/esm/elements/Thead.js +26 -0
- package/dist/esm/elements/Thead.js.map +1 -0
- package/dist/esm/elements/Title.js +44 -0
- package/dist/esm/elements/Title.js.map +1 -0
- package/dist/esm/elements/Tr.js +31 -0
- package/dist/esm/elements/Tr.js.map +1 -0
- package/dist/esm/elements/UnorderedList.js +31 -0
- package/dist/esm/elements/UnorderedList.js.map +1 -0
- package/dist/esm/elements/iconProps.js +49 -0
- package/dist/esm/elements/iconProps.js.map +1 -0
- package/dist/esm/form/Autocomplete.js +279 -0
- package/dist/esm/form/Autocomplete.js.map +1 -0
- package/dist/esm/form/Checkbox.js +111 -0
- package/dist/esm/form/Checkbox.js.map +1 -0
- package/dist/esm/form/Checkboxes.js +89 -0
- package/dist/esm/form/Checkboxes.js.map +1 -0
- package/dist/esm/form/Control.js +79 -0
- package/dist/esm/form/Control.js.map +1 -0
- package/dist/esm/form/DateInput.js +87 -0
- package/dist/esm/form/DateInput.js.map +1 -0
- package/dist/esm/form/DateInputBase.js +263 -0
- package/dist/esm/form/DateInputBase.js.map +1 -0
- package/dist/esm/form/DateRangeInput.js +76 -0
- package/dist/esm/form/DateRangeInput.js.map +1 -0
- package/dist/esm/form/DateRangeInputBase.js +301 -0
- package/dist/esm/form/DateRangeInputBase.js.map +1 -0
- package/dist/esm/form/DateTimeInput.js +87 -0
- package/dist/esm/form/DateTimeInput.js.map +1 -0
- package/dist/esm/form/DateTimeInputBase.js +333 -0
- package/dist/esm/form/DateTimeInputBase.js.map +1 -0
- package/dist/esm/form/Field.js +153 -0
- package/dist/esm/form/Field.js.map +1 -0
- package/dist/esm/form/File.js +109 -0
- package/dist/esm/form/File.js.map +1 -0
- package/dist/esm/form/FormContext.js +170 -0
- package/dist/esm/form/FormContext.js.map +1 -0
- package/dist/esm/form/Input.js +88 -0
- package/dist/esm/form/Input.js.map +1 -0
- package/dist/esm/form/InputBase.js +40 -0
- package/dist/esm/form/InputBase.js.map +1 -0
- package/dist/esm/form/Numberinput.js +199 -0
- package/dist/esm/form/Numberinput.js.map +1 -0
- package/dist/esm/form/Radio.js +108 -0
- package/dist/esm/form/Radio.js.map +1 -0
- package/dist/esm/form/Radios.js +91 -0
- package/dist/esm/form/Radios.js.map +1 -0
- package/dist/esm/form/Rate.js +279 -0
- package/dist/esm/form/Rate.js.map +1 -0
- package/dist/esm/form/Select.js +81 -0
- package/dist/esm/form/Select.js.map +1 -0
- package/dist/esm/form/SelectBase.js +54 -0
- package/dist/esm/form/SelectBase.js.map +1 -0
- package/dist/esm/form/Slider.js +459 -0
- package/dist/esm/form/Slider.js.map +1 -0
- package/dist/esm/form/Switch.js +96 -0
- package/dist/esm/form/Switch.js.map +1 -0
- package/dist/esm/form/Taginput.js +352 -0
- package/dist/esm/form/Taginput.js.map +1 -0
- package/dist/esm/form/TextArea.js +77 -0
- package/dist/esm/form/TextArea.js.map +1 -0
- package/dist/esm/form/TextAreaBase.js +45 -0
- package/dist/esm/form/TextAreaBase.js.map +1 -0
- package/dist/esm/form/TimeInput.js +83 -0
- package/dist/esm/form/TimeInput.js.map +1 -0
- package/dist/esm/form/TimeInputBase.js +246 -0
- package/dist/esm/form/TimeInputBase.js.map +1 -0
- package/dist/esm/form/_pickerInternals/Calendar.js +760 -0
- package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js +95 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -0
- package/dist/esm/form/_pickerInternals/TimeWheels.js +721 -0
- package/dist/esm/form/_pickerInternals/TimeWheels.js.map +1 -0
- package/dist/esm/form/_pickerInternals/audioTick.js +109 -0
- package/dist/esm/form/_pickerInternals/audioTick.js.map +1 -0
- package/dist/esm/form/_pickerInternals/dateUtils.js +267 -0
- package/dist/esm/form/_pickerInternals/dateUtils.js.map +1 -0
- package/dist/esm/form/_pickerInternals/formatters.js +322 -0
- package/dist/esm/form/_pickerInternals/formatters.js.map +1 -0
- package/dist/esm/form/_pickerInternals/haptics.js +38 -0
- package/dist/esm/form/_pickerInternals/haptics.js.map +1 -0
- package/dist/esm/form/_pickerInternals/nativeInputSupport.js +25 -0
- package/dist/esm/form/_pickerInternals/nativeInputSupport.js.map +1 -0
- package/dist/esm/form/_pickerInternals/pickerTypes.js +50 -0
- package/dist/esm/form/_pickerInternals/pickerTypes.js.map +1 -0
- package/dist/esm/form/_pickerInternals/segmentMap.js +315 -0
- package/dist/esm/form/_pickerInternals/segmentMap.js.map +1 -0
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js +49 -0
- package/dist/esm/form/_pickerInternals/useNativeMobilePicker.js.map +1 -0
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js +427 -0
- package/dist/esm/form/_pickerInternals/useSegmentedEntry.js.map +1 -0
- package/dist/esm/form/controlLoading.js +18 -0
- package/dist/esm/form/controlLoading.js.map +1 -0
- package/dist/esm/form/useAutoLabelId.js +54 -0
- package/dist/esm/form/useAutoLabelId.js.map +1 -0
- package/dist/esm/grid/Cell.js +35 -0
- package/dist/esm/grid/Cell.js.map +1 -0
- package/dist/esm/grid/Grid.js +51 -0
- package/dist/esm/grid/Grid.js.map +1 -0
- package/dist/esm/helpers/ClientOnly.js +33 -0
- package/dist/esm/helpers/ClientOnly.js.map +1 -0
- package/dist/esm/helpers/Config.js +60 -0
- package/dist/esm/helpers/Config.js.map +1 -0
- package/dist/esm/helpers/Theme.js +947 -0
- package/dist/esm/helpers/Theme.js.map +1 -0
- package/dist/esm/helpers/anchorAttrs.js +72 -0
- package/dist/esm/helpers/anchorAttrs.js.map +1 -0
- package/dist/esm/helpers/bulmaClassHelpers.js +415 -0
- package/dist/esm/helpers/bulmaClassHelpers.js.map +1 -0
- package/dist/esm/helpers/buttonType.js +24 -0
- package/dist/esm/helpers/buttonType.js.map +1 -0
- package/dist/esm/helpers/classNames.js +137 -0
- package/dist/esm/helpers/classNames.js.map +1 -0
- package/dist/esm/helpers/colorDeprecations.js +50 -0
- package/dist/esm/helpers/colorDeprecations.js.map +1 -0
- package/dist/esm/helpers/devWarnings.js +27 -0
- package/dist/esm/helpers/devWarnings.js.map +1 -0
- package/dist/esm/helpers/inertProps.js +27 -0
- package/dist/esm/helpers/inertProps.js.map +1 -0
- package/dist/esm/helpers/mergeBulmaStyles.js +20 -0
- package/dist/esm/helpers/mergeBulmaStyles.js.map +1 -0
- package/dist/esm/helpers/polymorphic.js +18 -0
- package/dist/esm/helpers/polymorphic.js.map +1 -0
- package/dist/esm/helpers/portal.js +76 -0
- package/dist/esm/helpers/portal.js.map +1 -0
- package/dist/esm/helpers/positionStacks.js +45 -0
- package/dist/esm/helpers/positionStacks.js.map +1 -0
- package/dist/esm/helpers/scrollLock.js +38 -0
- package/dist/esm/helpers/scrollLock.js.map +1 -0
- package/dist/esm/helpers/shadowDom.js +71 -0
- package/dist/esm/helpers/shadowDom.js.map +1 -0
- package/dist/esm/helpers/statusRegion.js +282 -0
- package/dist/esm/helpers/statusRegion.js.map +1 -0
- package/dist/esm/helpers/useAnchoredPosition.js +86 -0
- package/dist/esm/helpers/useAnchoredPosition.js.map +1 -0
- package/dist/esm/helpers/useBulmaClasses.js +158 -0
- package/dist/esm/helpers/useBulmaClasses.js.map +1 -0
- package/dist/esm/helpers/useClientLayoutEffect.js +13 -0
- package/dist/esm/helpers/useClientLayoutEffect.js.map +1 -0
- package/dist/esm/helpers/useColorClasses.js +84 -0
- package/dist/esm/helpers/useColorClasses.js.map +1 -0
- package/dist/esm/helpers/useFlexboxClasses.js +92 -0
- package/dist/esm/helpers/useFlexboxClasses.js.map +1 -0
- package/dist/esm/helpers/useFocusTrap.js +470 -0
- package/dist/esm/helpers/useFocusTrap.js.map +1 -0
- package/dist/esm/helpers/useIsHydrated.js +31 -0
- package/dist/esm/helpers/useIsHydrated.js.map +1 -0
- package/dist/esm/helpers/useOtherClasses.js +115 -0
- package/dist/esm/helpers/useOtherClasses.js.map +1 -0
- package/dist/esm/helpers/useSpacingClasses.js +82 -0
- package/dist/esm/helpers/useSpacingClasses.js.map +1 -0
- package/dist/esm/helpers/useTypographyClasses.js +93 -0
- package/dist/esm/helpers/useTypographyClasses.js.map +1 -0
- package/dist/esm/helpers/useVisibilityClasses.js +134 -0
- package/dist/esm/helpers/useVisibilityClasses.js.map +1 -0
- package/dist/esm/helpers/withSubComponents.js +24 -0
- package/dist/esm/helpers/withSubComponents.js.map +1 -0
- package/dist/esm/layout/Container.js +48 -0
- package/dist/esm/layout/Container.js.map +1 -0
- package/dist/esm/layout/Footer.js +33 -0
- package/dist/esm/layout/Footer.js.map +1 -0
- package/dist/esm/layout/Hero.js +90 -0
- package/dist/esm/layout/Hero.js.map +1 -0
- package/dist/esm/layout/Level.js +110 -0
- package/dist/esm/layout/Level.js.map +1 -0
- package/dist/esm/layout/Media.js +86 -0
- package/dist/esm/layout/Media.js.map +1 -0
- package/dist/esm/layout/Section.js +30 -0
- package/dist/esm/layout/Section.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +821 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +115 -16845
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Tabs.d.ts +25 -3
- package/dist/types/elements/Icon.d.ts +10 -7
- package/dist/types/form/DateInputBase.d.ts +8 -6
- package/dist/types/form/DateRangeInput.d.ts +91 -0
- package/dist/types/form/DateRangeInputBase.d.ts +172 -0
- package/dist/types/form/DateTimeInputBase.d.ts +10 -6
- package/dist/types/form/File.d.ts +18 -5
- package/dist/types/form/FormContext.d.ts +11 -0
- package/dist/types/form/TimeInputBase.d.ts +1 -1
- package/dist/types/form/_pickerInternals/PickerPopover.d.ts +1 -0
- package/dist/types/form/_pickerInternals/dateUtils.d.ts +7 -0
- package/dist/types/form/_pickerInternals/formatters.d.ts +14 -0
- package/dist/types/form/_pickerInternals/pickerTypes.d.ts +13 -0
- package/dist/types/form/_pickerInternals/useSegmentedEntry.d.ts +12 -3
- package/dist/types/index.d.ts +4 -0
- package/dist/types-cjs/components/Tabs.d.ts +25 -3
- package/dist/types-cjs/elements/Icon.d.ts +10 -7
- package/dist/types-cjs/form/DateInputBase.d.ts +8 -6
- package/dist/types-cjs/form/DateRangeInput.d.ts +91 -0
- package/dist/types-cjs/form/DateRangeInputBase.d.ts +172 -0
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +10 -6
- package/dist/types-cjs/form/File.d.ts +18 -5
- package/dist/types-cjs/form/FormContext.d.ts +11 -0
- package/dist/types-cjs/form/TimeInputBase.d.ts +1 -1
- package/dist/types-cjs/form/_pickerInternals/PickerPopover.d.ts +1 -0
- package/dist/types-cjs/form/_pickerInternals/dateUtils.d.ts +7 -0
- package/dist/types-cjs/form/_pickerInternals/formatters.d.ts +14 -0
- package/dist/types-cjs/form/_pickerInternals/pickerTypes.d.ts +13 -0
- package/dist/types-cjs/form/_pickerInternals/useSegmentedEntry.d.ts +12 -3
- package/dist/types-cjs/index.d.ts +4 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/components/_tabs.scss +44 -0
- package/src/scss/form/_dateinput.scss +87 -8
- package/src/scss/form/_daterangeinput.scss +63 -0
- package/src/scss/form/_datetimeinput.scss +7 -2
- package/src/scss/form/_file.scss +37 -0
- package/src/scss/form/_index.scss +2 -0
- package/src/scss/form/_picker-popover.scss +1 -4
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { forwardRef, useState, useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
|
+
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
6
|
+
import { withSubComponents } from '../helpers/withSubComponents.js';
|
|
7
|
+
import { isEventInside, getActiveElementInTree } from '../helpers/shadowDom.js';
|
|
8
|
+
import { omitAttrs, ANCHOR_ONLY_ATTRS } from '../helpers/anchorAttrs.js';
|
|
9
|
+
import { buttonType } from '../helpers/buttonType.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Checks if code is running in a browser environment.
|
|
13
|
+
* @deprecated Dropdown's internal SSR guard, exported by accident; it will
|
|
14
|
+
* be removed in the next major. Check `typeof window !== 'undefined' &&
|
|
15
|
+
* typeof document !== 'undefined'` instead.
|
|
16
|
+
* @param win - Window object.
|
|
17
|
+
* @param doc - Document object.
|
|
18
|
+
* @returns {boolean} True if in browser, false otherwise.
|
|
19
|
+
*/
|
|
20
|
+
const isBrowser$1 = (win, doc) => typeof win !== 'undefined' && typeof doc !== 'undefined';
|
|
21
|
+
/**
|
|
22
|
+
* The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.
|
|
23
|
+
*
|
|
24
|
+
* @function
|
|
25
|
+
* @param {DropdownProps} props - Props for the Dropdown component.
|
|
26
|
+
* @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root dropdown element.
|
|
27
|
+
* @returns {JSX.Element} The rendered dropdown.
|
|
28
|
+
* @see {@link https://bulma.io/documentation/components/dropdown/ | Bulma Dropdown documentation}
|
|
29
|
+
*/
|
|
30
|
+
const DropdownComponent = forwardRef(function DropdownComponent({ label, children, className, menuClassName, active: activeProp, up, right, hoverable, disabled, onActiveChange, closeOnClick = true, id, ...props }, ref) {
|
|
31
|
+
const [active, setActive] = useState(!!activeProp);
|
|
32
|
+
const dropdownRef = useRef(null);
|
|
33
|
+
const triggerRef = useRef(null);
|
|
34
|
+
const pendingFocusRef = useRef(null);
|
|
35
|
+
// Cleanup returned by a consumer's callback ref on attach, held until detach.
|
|
36
|
+
const consumerCleanupRef = useRef(null);
|
|
37
|
+
const setRefs = useCallback((node) => {
|
|
38
|
+
dropdownRef.current =
|
|
39
|
+
node;
|
|
40
|
+
if (typeof ref === 'function') {
|
|
41
|
+
// React 19 lets a callback ref return a cleanup function and detaches
|
|
42
|
+
// by running it instead of calling the ref with `null`; React 18
|
|
43
|
+
// discards the return value entirely. Returning it from here would be
|
|
44
|
+
// a React-19-only contract, so instead we hold the cleanup and run it
|
|
45
|
+
// ourselves on detach — a consumer's cleanup ref then behaves the same
|
|
46
|
+
// on both majors of the CI matrix.
|
|
47
|
+
if (node === null) {
|
|
48
|
+
const consumerCleanup = consumerCleanupRef.current;
|
|
49
|
+
consumerCleanupRef.current = null;
|
|
50
|
+
if (consumerCleanup) {
|
|
51
|
+
consumerCleanup();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
ref(null);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const cleanup = ref(node);
|
|
59
|
+
consumerCleanupRef.current =
|
|
60
|
+
typeof cleanup === 'function' ? cleanup : null;
|
|
61
|
+
}
|
|
62
|
+
else if (ref) {
|
|
63
|
+
ref.current = node;
|
|
64
|
+
}
|
|
65
|
+
}, [ref]);
|
|
66
|
+
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
67
|
+
// Generate Bulma classes with prefix
|
|
68
|
+
const bulmaClasses = usePrefixedClassNames('dropdown', {
|
|
69
|
+
'is-active': active,
|
|
70
|
+
'is-up': up,
|
|
71
|
+
'is-right': right,
|
|
72
|
+
'is-hoverable': hoverable,
|
|
73
|
+
'is-disabled': disabled,
|
|
74
|
+
});
|
|
75
|
+
const buttonClass = usePrefixedClassNames('button');
|
|
76
|
+
// Controlled mode support: mirror the controlled `active` prop into local
|
|
77
|
+
// state. This is an intentional external-prop sync (controlled/uncontrolled
|
|
78
|
+
// hybrid); behavior is covered by tests and certified in-browser.
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop
|
|
81
|
+
if (typeof activeProp === 'boolean')
|
|
82
|
+
setActive(activeProp);
|
|
83
|
+
}, [activeProp]);
|
|
84
|
+
// SSR-safe outside click
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!active)
|
|
87
|
+
return;
|
|
88
|
+
if (!isBrowser$1(window, document))
|
|
89
|
+
return;
|
|
90
|
+
const handleClick = (e) => {
|
|
91
|
+
if (!isEventInside(e, dropdownRef.current)) {
|
|
92
|
+
setActive(false);
|
|
93
|
+
onActiveChange?.(false);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
document.addEventListener('mousedown', handleClick);
|
|
97
|
+
return () => document.removeEventListener('mousedown', handleClick);
|
|
98
|
+
}, [active, onActiveChange]);
|
|
99
|
+
const handleToggle = () => {
|
|
100
|
+
/* istanbul ignore next: guard is enforced by button[disabled] at the DOM level */
|
|
101
|
+
if (disabled)
|
|
102
|
+
return;
|
|
103
|
+
const newActive = !active;
|
|
104
|
+
setActive(newActive);
|
|
105
|
+
onActiveChange?.(newActive);
|
|
106
|
+
};
|
|
107
|
+
const handleMenuClick = (e) => {
|
|
108
|
+
if (closeOnClick) {
|
|
109
|
+
setActive(false);
|
|
110
|
+
onActiveChange?.(false);
|
|
111
|
+
// Closing hides the item that has focus, and the browser drops focus
|
|
112
|
+
// to the page when that happens. Hand it back to the trigger, as
|
|
113
|
+
// Escape does. An item that moved focus somewhere else keeps it there.
|
|
114
|
+
// The menu around this content is what a click between items focuses.
|
|
115
|
+
const menu = e.currentTarget.parentElement;
|
|
116
|
+
if (menu.contains(getActiveElementInTree(e.currentTarget))) {
|
|
117
|
+
triggerRef.current?.focus();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const getMenuItems = () => {
|
|
122
|
+
/* istanbul ignore next: dropdownRef.current is never null once mounted */
|
|
123
|
+
if (!dropdownRef.current)
|
|
124
|
+
return [];
|
|
125
|
+
return Array.from(
|
|
126
|
+
// Every menu-item role, so an item a caller gives `menuitemcheckbox`
|
|
127
|
+
// or `menuitemradio` (a filter or sort menu) stays reachable.
|
|
128
|
+
dropdownRef.current.querySelectorAll('[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]')).filter(el => !el.hasAttribute('disabled') &&
|
|
129
|
+
el.getAttribute('aria-disabled') !== 'true');
|
|
130
|
+
};
|
|
131
|
+
// Focus the pending menu item once the menu becomes visible; the item is
|
|
132
|
+
// unfocusable while `display: none` applies, so this must wait for the
|
|
133
|
+
// `is-active` class to actually land in the DOM.
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (!active || !pendingFocusRef.current)
|
|
136
|
+
return;
|
|
137
|
+
const items = getMenuItems();
|
|
138
|
+
if (items.length) {
|
|
139
|
+
const index = pendingFocusRef.current === 'first' ? 0 : items.length - 1;
|
|
140
|
+
items[index].focus();
|
|
141
|
+
}
|
|
142
|
+
pendingFocusRef.current = null;
|
|
143
|
+
}, [active]);
|
|
144
|
+
const handleTriggerKeyDown = (e) => {
|
|
145
|
+
if (disabled)
|
|
146
|
+
return;
|
|
147
|
+
switch (e.key) {
|
|
148
|
+
case 'ArrowDown':
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
pendingFocusRef.current = 'first';
|
|
151
|
+
if (!active) {
|
|
152
|
+
setActive(true);
|
|
153
|
+
onActiveChange?.(true);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const items = getMenuItems();
|
|
157
|
+
if (items.length)
|
|
158
|
+
items[0].focus();
|
|
159
|
+
pendingFocusRef.current = null;
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
case 'ArrowUp':
|
|
163
|
+
e.preventDefault();
|
|
164
|
+
pendingFocusRef.current = 'last';
|
|
165
|
+
if (!active) {
|
|
166
|
+
setActive(true);
|
|
167
|
+
onActiveChange?.(true);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
const items = getMenuItems();
|
|
171
|
+
if (items.length)
|
|
172
|
+
items[items.length - 1].focus();
|
|
173
|
+
pendingFocusRef.current = null;
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
case 'Enter':
|
|
177
|
+
case ' ':
|
|
178
|
+
e.preventDefault();
|
|
179
|
+
// A held key sends a keydown per auto-repeat. Running an item hands
|
|
180
|
+
// focus back here, so without this a held Enter would reopen the
|
|
181
|
+
// menu and run whichever item it focused next.
|
|
182
|
+
if (e.repeat)
|
|
183
|
+
break;
|
|
184
|
+
if (!active) {
|
|
185
|
+
pendingFocusRef.current = 'first';
|
|
186
|
+
setActive(true);
|
|
187
|
+
onActiveChange?.(true);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
setActive(false);
|
|
191
|
+
onActiveChange?.(false);
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
case 'Escape':
|
|
195
|
+
if (active) {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
setActive(false);
|
|
198
|
+
onActiveChange?.(false);
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const handleMenuKeyDown = (e) => {
|
|
204
|
+
// Escape and Tab close the menu regardless of whether it has any focusable
|
|
205
|
+
// items — an empty or all-disabled menu must still honor the close contract.
|
|
206
|
+
if (e.key === 'Escape') {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
setActive(false);
|
|
209
|
+
onActiveChange?.(false);
|
|
210
|
+
triggerRef.current?.focus();
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (e.key === 'Tab') {
|
|
214
|
+
setActive(false);
|
|
215
|
+
onActiveChange?.(false);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const items = getMenuItems();
|
|
219
|
+
if (!items.length)
|
|
220
|
+
return;
|
|
221
|
+
const currentIndex = items.indexOf(getActiveElementInTree(e.currentTarget));
|
|
222
|
+
switch (e.key) {
|
|
223
|
+
case 'ArrowDown': {
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
const next = currentIndex >= 0 ? (currentIndex + 1) % items.length : 0;
|
|
226
|
+
items[next].focus();
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case 'ArrowUp': {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
const prev = currentIndex >= 0
|
|
232
|
+
? (currentIndex - 1 + items.length) % items.length
|
|
233
|
+
: items.length - 1;
|
|
234
|
+
items[prev].focus();
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 'Home':
|
|
238
|
+
e.preventDefault();
|
|
239
|
+
items[0].focus();
|
|
240
|
+
break;
|
|
241
|
+
case 'End':
|
|
242
|
+
e.preventDefault();
|
|
243
|
+
items[items.length - 1].focus();
|
|
244
|
+
break;
|
|
245
|
+
case 'Enter':
|
|
246
|
+
case ' ': {
|
|
247
|
+
// Activate the focused item by clicking it, so its `onClick` runs and
|
|
248
|
+
// closing follows `closeOnClick` as it does for the mouse. A caller's
|
|
249
|
+
// own key handler that prevented the default has claimed the key, and
|
|
250
|
+
// is left to it rather than followed by a second activation.
|
|
251
|
+
if (currentIndex < 0 || e.defaultPrevented)
|
|
252
|
+
break;
|
|
253
|
+
const item = items[currentIndex];
|
|
254
|
+
// Leave the browser's own activation alone, or the item runs twice: a
|
|
255
|
+
// `<button>` answers both keys, and a link with an `href` answers
|
|
256
|
+
// Enter. A link does not answer Space, so Space on a link is handled
|
|
257
|
+
// here too, which also keeps the page from scrolling.
|
|
258
|
+
if (item.tagName === 'BUTTON')
|
|
259
|
+
break;
|
|
260
|
+
if (e.key === 'Enter' &&
|
|
261
|
+
item.tagName === 'A' &&
|
|
262
|
+
item.hasAttribute('href')) {
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
e.preventDefault();
|
|
266
|
+
// A held key sends a keydown per auto-repeat. Clicking on each would
|
|
267
|
+
// toggle a checkbox item over and over while `closeOnClick` is off,
|
|
268
|
+
// so only the first press activates. The default is still prevented
|
|
269
|
+
// on the repeats above, so a held Space does not scroll the page.
|
|
270
|
+
if (!e.repeat)
|
|
271
|
+
item.click();
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const dropdownClasses = classNames(bulmaClasses, bulmaHelperClasses, className);
|
|
277
|
+
return (jsxs("div", { className: dropdownClasses, ref: setRefs, id: id, "data-testid": "dropdown-root", ...rest, children: [jsx("div", { className: usePrefixedClassNames('dropdown-trigger'), children: jsxs("button", { ref: triggerRef, className: buttonClass, "aria-haspopup": "true", "aria-controls": id ? `${id}-menu` : undefined, "aria-expanded": active, onClick: handleToggle, onKeyDown: handleTriggerKeyDown, disabled: disabled, type: "button", children: [jsx("span", { children: label }), jsx("span", { className: usePrefixedClassNames('icon', 'is-small'), "aria-hidden": "true", children: jsx("i", { className: "fas fa-angle-down" }) })] }) }), jsx("div", { className: classNames(usePrefixedClassNames('dropdown-menu'), menuClassName), id: id ? `${id}-menu` : undefined, role: "menu", "data-testid": "dropdown-menu", onKeyDown: handleMenuKeyDown,
|
|
278
|
+
// The menu, not its content, takes focus from a click between items,
|
|
279
|
+
// so the menu owns nothing focusable but its items.
|
|
280
|
+
tabIndex: -1, children: jsx("div", { className: usePrefixedClassNames('dropdown-content'), onClick: handleMenuClick, children: children }) })] }));
|
|
281
|
+
});
|
|
282
|
+
/**
|
|
283
|
+
* The anchor's attributes, minus the one a `<button>` legitimately takes.
|
|
284
|
+
*
|
|
285
|
+
* `type` stays: `as="button"` is a supported form and `type="submit"` is valid
|
|
286
|
+
* there, so stripping it would remove a working attribute. A `<div>` takes no
|
|
287
|
+
* `type`, so it gets the whole `ANCHOR_ONLY_ATTRS` set instead. The set is
|
|
288
|
+
* chosen by the rendered tag because that is where the reason lives (#692).
|
|
289
|
+
*
|
|
290
|
+
* Neither set withholds `rel`, which `Level.Item` does: React declares `rel` on
|
|
291
|
+
* `HTMLAttributes` for every element, so withholding it would diverge from
|
|
292
|
+
* React's own typing, the call #641 recorded for `Navbar.Link`. Level
|
|
293
|
+
* withholds it anyway, because it always has.
|
|
294
|
+
*/
|
|
295
|
+
const STRIP_FROM_BUTTON = (() => {
|
|
296
|
+
const { type: _type, ...rest } = ANCHOR_ONLY_ATTRS;
|
|
297
|
+
return rest;
|
|
298
|
+
})();
|
|
299
|
+
/**
|
|
300
|
+
* Bulma Dropdown item.
|
|
301
|
+
*
|
|
302
|
+
* @function
|
|
303
|
+
* @param {DropdownItemProps} props - Props for the DropdownItem component.
|
|
304
|
+
* @returns {JSX.Element} The rendered dropdown item.
|
|
305
|
+
*/
|
|
306
|
+
const DropdownItem = ((itemProps) => {
|
|
307
|
+
const { children, active, className, as: Component = 'a', ...props } = itemProps;
|
|
308
|
+
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
309
|
+
// The anchor's attributes reach an anchor and nothing else — `<div href>` and
|
|
310
|
+
// `<button target>` are invalid HTML. The same rule Menu applies, for the same
|
|
311
|
+
// reason: the type now derives these from `as`, and deriving them must not
|
|
312
|
+
// quietly widen where they land. The type stops a direct caller; this stops a
|
|
313
|
+
// plain-JS one, a loose `{...props}` spread, and the genericity a wrapping HOC
|
|
314
|
+
// erases.
|
|
315
|
+
//
|
|
316
|
+
// The whole link set, not `href` alone: they all arrive together under
|
|
317
|
+
// `as="a"`. Menu strips `href` only, because its `as` is open and a flat set
|
|
318
|
+
// would delete attributes legal on the element a caller named.
|
|
319
|
+
//
|
|
320
|
+
// `bestax-migrate` tracks the same question from the other side, per attribute
|
|
321
|
+
// per element (`LINK_ATTR_ELEMENTS`) rather than as one set — so the two lists
|
|
322
|
+
// are not interchangeable and neither derives from the other.
|
|
323
|
+
//
|
|
324
|
+
// Menu's condition also admits a custom component and a custom element, which
|
|
325
|
+
// own their prop contracts. Here the set follows the tag: an `<a>` keeps all
|
|
326
|
+
// of them, a `<button>` keeps `type`, and any other `as` keeps none of them.
|
|
327
|
+
const forwarded = Component === 'a'
|
|
328
|
+
? rest
|
|
329
|
+
: Component === 'button'
|
|
330
|
+
? omitAttrs(rest, STRIP_FROM_BUTTON)
|
|
331
|
+
: omitAttrs(rest, ANCHOR_ONLY_ATTRS);
|
|
332
|
+
return (jsx(Component, { className: classNames(usePrefixedClassNames('dropdown-item', {
|
|
333
|
+
'is-active': active,
|
|
334
|
+
}), bulmaHelperClasses, className), "data-testid": "dropdown-item", ...forwarded,
|
|
335
|
+
// After `forwarded` for the same reason as `role` and `type` below: a
|
|
336
|
+
// spread carrying `tabIndex: undefined` would otherwise erase the
|
|
337
|
+
// default. The item keeps its menu role and its place in the arrow-key
|
|
338
|
+
// order, but a `<div>` or an anchor without an `href` cannot take focus
|
|
339
|
+
// without a tabindex, so the arrow keys stall on it.
|
|
340
|
+
tabIndex: forwarded.tabIndex ?? 0,
|
|
341
|
+
// After `forwarded` for the same reason as `type` below: a spread
|
|
342
|
+
// carrying `role: undefined` would otherwise erase the default, and an
|
|
343
|
+
// item with no role drops out of the menu and its arrow-key order.
|
|
344
|
+
role: forwarded.role ?? 'menuitem', ...(Component === 'button'
|
|
345
|
+
? { type: buttonType(forwarded.type) }
|
|
346
|
+
: {}), children: children }));
|
|
347
|
+
});
|
|
348
|
+
/**
|
|
349
|
+
* Bulma Dropdown divider.
|
|
350
|
+
*
|
|
351
|
+
* @function
|
|
352
|
+
* @returns {JSX.Element} The rendered divider element.
|
|
353
|
+
*/
|
|
354
|
+
const DropdownDivider = () => (jsx("hr", { className: usePrefixedClassNames('dropdown-divider') }));
|
|
355
|
+
/** Bulma Dropdown component with Item and Divider sub-components. */
|
|
356
|
+
const Dropdown = withSubComponents(DropdownComponent, {
|
|
357
|
+
Item: DropdownItem,
|
|
358
|
+
Divider: DropdownDivider,
|
|
359
|
+
}, 'Dropdown');
|
|
360
|
+
|
|
361
|
+
export { Dropdown, DropdownDivider, DropdownItem, isBrowser$1 as isBrowser };
|
|
362
|
+
//# sourceMappingURL=Dropdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dropdown.js","sources":["../../../src/components/Dropdown.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useState,\n useRef,\n useEffect,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { getActiveElementInTree, isEventInside } from '../helpers/shadowDom';\nimport type { ConstrainedPolymorphicComponentWithoutRef } from '../helpers/polymorphic';\nimport {\n type AnchorOnlyAttributes,\n ANCHOR_ONLY_ATTRS,\n omitAttrs,\n} from '../helpers/anchorAttrs';\nimport { buttonType } from '../helpers/buttonType';\n\n/**\n * Checks if code is running in a browser environment.\n * @deprecated Dropdown's internal SSR guard, exported by accident; it will\n * be removed in the next major. Check `typeof window !== 'undefined' &&\n * typeof document !== 'undefined'` instead.\n * @param win - Window object.\n * @param doc - Document object.\n * @returns {boolean} True if in browser, false otherwise.\n */\nexport const isBrowser = (win?: typeof window, doc?: typeof document) =>\n typeof win !== 'undefined' && typeof doc !== 'undefined';\n\n/**\n * Props for the Dropdown component.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root dropdown element.\n */\nexport interface DropdownProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** The dropdown button/trigger content. */\n label: React.ReactNode;\n /** Dropdown menu items and dividers. */\n children: React.ReactNode;\n /** Additional CSS classes for root. */\n className?: string;\n /** Additional CSS classes for the dropdown menu. */\n menuClassName?: string;\n /** Whether the dropdown is open (controlled). */\n active?: boolean;\n /** Dropdown menu opens upward. */\n up?: boolean;\n /** Menu is right-aligned. */\n right?: boolean;\n /** Open on hover instead of click. */\n hoverable?: boolean;\n /** Disables the dropdown trigger. */\n disabled?: boolean;\n /** Callback when dropdown active state changes. */\n onActiveChange?: (active: boolean) => void;\n /** Close dropdown when a menu item is clicked, or activated with Enter or Space. */\n closeOnClick?: boolean;\n /** Root element ID (for aria-controls, etc). */\n id?: string;\n}\n\n/**\n * The `Dropdown` component provides Bulma's versatile dropdown menu for your Bulma React UI.\n *\n * @function\n * @param {DropdownProps} props - Props for the Dropdown component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the root dropdown element.\n * @returns {JSX.Element} The rendered dropdown.\n * @see {@link https://bulma.io/documentation/components/dropdown/ | Bulma Dropdown documentation}\n */\nconst DropdownComponent = forwardRef<HTMLDivElement, DropdownProps>(\n function DropdownComponent(\n {\n label,\n children,\n className,\n menuClassName,\n active: activeProp,\n up,\n right,\n hoverable,\n disabled,\n onActiveChange,\n closeOnClick = true,\n id,\n ...props\n },\n ref\n ) {\n const [active, setActive] = useState<boolean>(!!activeProp);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const pendingFocusRef = useRef<'first' | 'last' | null>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n\n const setRefs = useCallback(\n (node: HTMLDivElement | null) => {\n (dropdownRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches\n // by running it instead of calling the ref with `null`; React 18\n // discards the return value entirely. Returning it from here would be\n // a React-19-only contract, so instead we hold the cleanup and run it\n // ourselves on detach — a consumer's cleanup ref then behaves the same\n // on both majors of the CI matrix.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('dropdown', {\n 'is-active': active,\n 'is-up': up,\n 'is-right': right,\n 'is-hoverable': hoverable,\n 'is-disabled': disabled,\n });\n\n const buttonClass = usePrefixedClassNames('button');\n\n // Controlled mode support: mirror the controlled `active` prop into local\n // state. This is an intentional external-prop sync (controlled/uncontrolled\n // hybrid); behavior is covered by tests and certified in-browser.\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop\n if (typeof activeProp === 'boolean') setActive(activeProp);\n }, [activeProp]);\n\n // SSR-safe outside click\n useEffect(() => {\n if (!active) return;\n\n if (!isBrowser(window, document)) return;\n\n const handleClick = (e: MouseEvent) => {\n if (!isEventInside(e, dropdownRef.current)) {\n setActive(false);\n onActiveChange?.(false);\n }\n };\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [active, onActiveChange]);\n\n const handleToggle = () => {\n /* istanbul ignore next: guard is enforced by button[disabled] at the DOM level */\n if (disabled) return;\n\n const newActive = !active;\n setActive(newActive);\n onActiveChange?.(newActive);\n };\n\n const handleMenuClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnClick) {\n setActive(false);\n onActiveChange?.(false);\n // Closing hides the item that has focus, and the browser drops focus\n // to the page when that happens. Hand it back to the trigger, as\n // Escape does. An item that moved focus somewhere else keeps it there.\n // The menu around this content is what a click between items focuses.\n const menu = e.currentTarget.parentElement as HTMLElement;\n if (menu.contains(getActiveElementInTree(e.currentTarget))) {\n triggerRef.current?.focus();\n }\n }\n };\n\n const getMenuItems = (): HTMLElement[] => {\n /* istanbul ignore next: dropdownRef.current is never null once mounted */\n if (!dropdownRef.current) return [];\n return Array.from(\n // Every menu-item role, so an item a caller gives `menuitemcheckbox`\n // or `menuitemradio` (a filter or sort menu) stays reachable.\n dropdownRef.current.querySelectorAll<HTMLElement>(\n '[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]'\n )\n ).filter(\n el =>\n !el.hasAttribute('disabled') &&\n el.getAttribute('aria-disabled') !== 'true'\n );\n };\n\n // Focus the pending menu item once the menu becomes visible; the item is\n // unfocusable while `display: none` applies, so this must wait for the\n // `is-active` class to actually land in the DOM.\n useEffect(() => {\n if (!active || !pendingFocusRef.current) return;\n const items = getMenuItems();\n if (items.length) {\n const index =\n pendingFocusRef.current === 'first' ? 0 : items.length - 1;\n items[index].focus();\n }\n pendingFocusRef.current = null;\n }, [active]);\n\n const handleTriggerKeyDown = (\n e: React.KeyboardEvent<HTMLButtonElement>\n ) => {\n if (disabled) return;\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n pendingFocusRef.current = 'first';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n const items = getMenuItems();\n if (items.length) items[0].focus();\n pendingFocusRef.current = null;\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n pendingFocusRef.current = 'last';\n if (!active) {\n setActive(true);\n onActiveChange?.(true);\n } else {\n const items = getMenuItems();\n if (items.length) items[items.length - 1].focus();\n pendingFocusRef.current = null;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n // A held key sends a keydown per auto-repeat. Running an item hands\n // focus back here, so without this a held Enter would reopen the\n // menu and run whichever item it focused next.\n if (e.repeat) break;\n if (!active) {\n pendingFocusRef.current = 'first';\n setActive(true);\n onActiveChange?.(true);\n } else {\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n case 'Escape':\n if (active) {\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n }\n break;\n default:\n break;\n }\n };\n\n const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n // Escape and Tab close the menu regardless of whether it has any focusable\n // items — an empty or all-disabled menu must still honor the close contract.\n if (e.key === 'Escape') {\n e.preventDefault();\n setActive(false);\n onActiveChange?.(false);\n triggerRef.current?.focus();\n return;\n }\n if (e.key === 'Tab') {\n setActive(false);\n onActiveChange?.(false);\n return;\n }\n\n const items = getMenuItems();\n if (!items.length) return;\n const currentIndex = items.indexOf(\n getActiveElementInTree(e.currentTarget) as HTMLElement\n );\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next =\n currentIndex >= 0 ? (currentIndex + 1) % items.length : 0;\n items[next].focus();\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev =\n currentIndex >= 0\n ? (currentIndex - 1 + items.length) % items.length\n : items.length - 1;\n items[prev].focus();\n break;\n }\n case 'Home':\n e.preventDefault();\n items[0].focus();\n break;\n case 'End':\n e.preventDefault();\n items[items.length - 1].focus();\n break;\n case 'Enter':\n case ' ': {\n // Activate the focused item by clicking it, so its `onClick` runs and\n // closing follows `closeOnClick` as it does for the mouse. A caller's\n // own key handler that prevented the default has claimed the key, and\n // is left to it rather than followed by a second activation.\n if (currentIndex < 0 || e.defaultPrevented) break;\n const item = items[currentIndex];\n // Leave the browser's own activation alone, or the item runs twice: a\n // `<button>` answers both keys, and a link with an `href` answers\n // Enter. A link does not answer Space, so Space on a link is handled\n // here too, which also keeps the page from scrolling.\n if (item.tagName === 'BUTTON') break;\n if (\n e.key === 'Enter' &&\n item.tagName === 'A' &&\n item.hasAttribute('href')\n ) {\n break;\n }\n e.preventDefault();\n // A held key sends a keydown per auto-repeat. Clicking on each would\n // toggle a checkbox item over and over while `closeOnClick` is off,\n // so only the first press activates. The default is still prevented\n // on the repeats above, so a held Space does not scroll the page.\n if (!e.repeat) item.click();\n break;\n }\n default:\n break;\n }\n };\n\n const dropdownClasses = classNames(\n bulmaClasses,\n bulmaHelperClasses,\n className\n );\n\n return (\n <div\n className={dropdownClasses}\n ref={setRefs}\n id={id}\n data-testid=\"dropdown-root\"\n {...rest}\n >\n <div className={usePrefixedClassNames('dropdown-trigger')}>\n <button\n ref={triggerRef}\n className={buttonClass}\n aria-haspopup=\"true\"\n aria-controls={id ? `${id}-menu` : undefined}\n aria-expanded={active}\n onClick={handleToggle}\n onKeyDown={handleTriggerKeyDown}\n disabled={disabled}\n type=\"button\"\n >\n <span>{label}</span>\n <span\n className={usePrefixedClassNames('icon', 'is-small')}\n aria-hidden=\"true\"\n >\n <i className=\"fas fa-angle-down\" />\n </span>\n </button>\n </div>\n <div\n className={classNames(\n usePrefixedClassNames('dropdown-menu'),\n menuClassName\n )}\n id={id ? `${id}-menu` : undefined}\n role=\"menu\"\n data-testid=\"dropdown-menu\"\n onKeyDown={handleMenuKeyDown}\n // The menu, not its content, takes focus from a click between items,\n // so the menu owns nothing focusable but its items.\n tabIndex={-1}\n >\n <div\n className={usePrefixedClassNames('dropdown-content')}\n onClick={handleMenuClick}\n >\n {children}\n </div>\n </div>\n </div>\n );\n }\n);\n\n/**\n * The elements a dropdown item may render as. Bulma's dropdown markup names\n * these three and no others, so `as` is a closed set rather than an open\n * `React.ElementType`.\n */\nexport type DropdownItemElement = 'a' | 'div' | 'button';\n\n/**\n * The DropdownItem component's own props.\n */\nexport interface DropdownItemOwnProps extends BulmaClassesProps {\n /** Whether the item is active. */\n active?: boolean;\n /** Additional CSS classes. */\n className?: string;\n /** Marks the item as disabled; disabled items are skipped during keyboard navigation. Use with `as=\"button\"` for a native disabled control, or pair with `aria-disabled` on a link. */\n disabled?: boolean;\n /** Item content. */\n children?: React.ReactNode;\n}\n\n/**\n * Props for the DropdownItem component. Everything the item does not own\n * follows `as`: `href`, `target` and `rel` under the default `'a'`, `type` and\n * `form` under `'button'`, and the shared HTML attributes under any of them.\n *\n * Pinning these to `React.HTMLAttributes<HTMLElement>` instead — which is what\n * this type did before — rejected `href` on an anchor and `type` on a button,\n * both of which have always worked at runtime. Same defect as #641, in the\n * narrower shape a constrained `as` takes.\n *\n * **Name the tag you mean.** The type parameter defaults to the whole union, not\n * to the rendered element, so bare `DropdownItemProps` keeps accepting\n * `{ as: 'div' }` the way it always has. The cost is that it is not\n * distributive: `Omit` over a union keeps only the shared keys, so the bare\n * alias carries no `href` even though the component takes one under `as=\"a\"`.\n * Write `DropdownItemProps<'a'>` for the anchor's props. That is the #667 alias\n * limitation Button carries, labelled next-major because closing it is\n * source-breaking, and pinned for this component in\n * `__typetests__/polymorphic.tsx`; the component itself is unaffected.\n */\nexport type DropdownItemProps<\n T extends DropdownItemElement = DropdownItemElement,\n> = DropdownItemOwnProps &\n Omit<React.ComponentPropsWithoutRef<T>, keyof DropdownItemOwnProps | 'as'> & {\n /**\n * The element type to render.\n *\n * `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so\n * an item inside a form does not submit it.\n */\n as?: T;\n };\n\n/**\n * The anchor's attributes, minus the one a `<button>` legitimately takes.\n *\n * `type` stays: `as=\"button\"` is a supported form and `type=\"submit\"` is valid\n * there, so stripping it would remove a working attribute. A `<div>` takes no\n * `type`, so it gets the whole `ANCHOR_ONLY_ATTRS` set instead. The set is\n * chosen by the rendered tag because that is where the reason lives (#692).\n *\n * Neither set withholds `rel`, which `Level.Item` does: React declares `rel` on\n * `HTMLAttributes` for every element, so withholding it would diverge from\n * React's own typing, the call #641 recorded for `Navbar.Link`. Level\n * withholds it anyway, because it always has.\n */\nconst STRIP_FROM_BUTTON: Readonly<\n Record<Exclude<keyof AnchorOnlyAttributes, 'type'>, true>\n> = (() => {\n const { type: _type, ...rest } = ANCHOR_ONLY_ATTRS;\n return rest;\n})();\n\n/**\n * The shape the implementation destructures. The public contract is the generic\n * `DropdownItemProps<T>` above — the body cannot see through `T`.\n */\ntype DropdownItemImplProps = DropdownItemOwnProps & {\n as?: DropdownItemElement;\n};\n\n/**\n * Bulma Dropdown item.\n *\n * @function\n * @param {DropdownItemProps} props - Props for the DropdownItem component.\n * @returns {JSX.Element} The rendered dropdown item.\n */\nexport const DropdownItem = ((itemProps: DropdownItemProps) => {\n const {\n children,\n active,\n className,\n as: Component = 'a',\n ...props\n } = itemProps as DropdownItemImplProps;\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n // The anchor's attributes reach an anchor and nothing else — `<div href>` and\n // `<button target>` are invalid HTML. The same rule Menu applies, for the same\n // reason: the type now derives these from `as`, and deriving them must not\n // quietly widen where they land. The type stops a direct caller; this stops a\n // plain-JS one, a loose `{...props}` spread, and the genericity a wrapping HOC\n // erases.\n //\n // The whole link set, not `href` alone: they all arrive together under\n // `as=\"a\"`. Menu strips `href` only, because its `as` is open and a flat set\n // would delete attributes legal on the element a caller named.\n //\n // `bestax-migrate` tracks the same question from the other side, per attribute\n // per element (`LINK_ATTR_ELEMENTS`) rather than as one set — so the two lists\n // are not interchangeable and neither derives from the other.\n //\n // Menu's condition also admits a custom component and a custom element, which\n // own their prop contracts. Here the set follows the tag: an `<a>` keeps all\n // of them, a `<button>` keeps `type`, and any other `as` keeps none of them.\n const forwarded =\n Component === 'a'\n ? rest\n : Component === 'button'\n ? omitAttrs(rest, STRIP_FROM_BUTTON)\n : omitAttrs(rest, ANCHOR_ONLY_ATTRS);\n return (\n <Component\n className={classNames(\n usePrefixedClassNames('dropdown-item', {\n 'is-active': active,\n }),\n bulmaHelperClasses,\n className\n )}\n data-testid=\"dropdown-item\"\n {...forwarded}\n // After `forwarded` for the same reason as `role` and `type` below: a\n // spread carrying `tabIndex: undefined` would otherwise erase the\n // default. The item keeps its menu role and its place in the arrow-key\n // order, but a `<div>` or an anchor without an `href` cannot take focus\n // without a tabindex, so the arrow keys stall on it.\n tabIndex={(forwarded as { tabIndex?: number }).tabIndex ?? 0}\n // After `forwarded` for the same reason as `type` below: a spread\n // carrying `role: undefined` would otherwise erase the default, and an\n // item with no role drops out of the menu and its arrow-key order.\n role={(forwarded as { role?: React.AriaRole }).role ?? 'menuitem'}\n // A menu item inside a form must not submit it. `<button>` defaults to\n // type=\"submit\", and a filter or sort menu sitting in a form is ordinary.\n // Dropdown's own trigger sets it, and `Avatar` and `Menu.Item` default it\n // the same way. A caller's `submit` or `reset` still wins, and anything\n // else becomes `button`, since HTML reads a value it does not define for\n // a button as submit too; `buttonType` says more.\n //\n // After `forwarded`, reading through it rather than before it: React\n // treats `type={undefined}` as \"remove the attribute\", and a spread\n // carrying an absent key is how that arrives. Spreading the default first\n // let such a spread erase it and restore the submit behaviour, so the\n // guard only held for callers who passed nothing.\n {...(Component === 'button'\n ? { type: buttonType((forwarded as { type?: unknown }).type) }\n : {})}\n >\n {children}\n </Component>\n );\n}) as ConstrainedPolymorphicComponentWithoutRef<\n DropdownItemOwnProps,\n DropdownItemElement,\n 'a'\n>;\n\n/**\n * Bulma Dropdown divider.\n *\n * @function\n * @returns {JSX.Element} The rendered divider element.\n */\nexport const DropdownDivider: React.FC = () => (\n <hr className={usePrefixedClassNames('dropdown-divider')} />\n);\n\n/** Bulma Dropdown component with Item and Divider sub-components. */\nexport const Dropdown = withSubComponents(\n DropdownComponent,\n {\n Item: DropdownItem,\n Divider: DropdownDivider,\n },\n 'Dropdown'\n);\n\nexport default Dropdown;\n"],"names":["isBrowser","_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { usePrefixedClassNames, classNames } from '../helpers/classNames.js';
|
|
5
|
+
import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
|
|
6
|
+
import { useScrollLock } from '../helpers/scrollLock.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The `Loading` component provides a loading overlay with a spinner animation.
|
|
10
|
+
*
|
|
11
|
+
* @function
|
|
12
|
+
* @param {LoadingProps} props - Props for the Loading component.
|
|
13
|
+
* @returns {JSX.Element | null} The rendered loading overlay or null if not active.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Full page loading
|
|
17
|
+
* <Loading active isFullPage />
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Container loading with message
|
|
21
|
+
* <div style={{ position: 'relative', height: '200px' }}>
|
|
22
|
+
* <Loading active>Loading data...</Loading>
|
|
23
|
+
* </div>
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // With color variant
|
|
27
|
+
* <Loading active color="primary" />
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // With cancel functionality
|
|
31
|
+
* <Loading
|
|
32
|
+
* active={isLoading}
|
|
33
|
+
* canCancel
|
|
34
|
+
* onCancel={() => setIsLoading(false)}
|
|
35
|
+
* />
|
|
36
|
+
*/
|
|
37
|
+
const Loading = ({ active = false, isFullPage = false, size, color, canCancel = false, onCancel, children, className, overlayClassName, iconClassName, indicator, overlay, ...props }) => {
|
|
38
|
+
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
39
|
+
// Generate Bulma classes with prefix
|
|
40
|
+
const loadingClasses = usePrefixedClassNames('loading', {
|
|
41
|
+
'is-active': active,
|
|
42
|
+
'is-full-page': isFullPage,
|
|
43
|
+
'is-cancelable': canCancel,
|
|
44
|
+
[`is-${overlay}`]: !!overlay,
|
|
45
|
+
[`is-${color}`]: !!color,
|
|
46
|
+
});
|
|
47
|
+
const iconClasses = usePrefixedClassNames('loading-icon', {
|
|
48
|
+
[`is-${size}`]: size,
|
|
49
|
+
});
|
|
50
|
+
// Combine classes
|
|
51
|
+
const combinedClasses = classNames(loadingClasses, bulmaHelperClasses, className);
|
|
52
|
+
const combinedOverlayClasses = classNames(usePrefixedClassNames('loading-overlay'), overlayClassName);
|
|
53
|
+
const combinedIconClasses = classNames(iconClasses, iconClassName);
|
|
54
|
+
const loadingContentClass = usePrefixedClassNames('loading-content');
|
|
55
|
+
const loadingIconCustomClass = usePrefixedClassNames('loading-icon-custom');
|
|
56
|
+
const loadingTextClass = usePrefixedClassNames('loading-text');
|
|
57
|
+
const loadingCancelClass = usePrefixedClassNames('loading-cancel');
|
|
58
|
+
// Handle cancel click
|
|
59
|
+
const handleOverlayClick = () => {
|
|
60
|
+
if (canCancel && onCancel) {
|
|
61
|
+
onCancel();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
// Handle escape key
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
if (!active || !canCancel || !onCancel)
|
|
67
|
+
return;
|
|
68
|
+
const handleKeyDown = (e) => {
|
|
69
|
+
if (e.key === 'Escape') {
|
|
70
|
+
onCancel();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
74
|
+
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
75
|
+
}, [active, canCancel, onCancel]);
|
|
76
|
+
// Prevent body scroll when full page loading is active. Ref-counted through
|
|
77
|
+
// the shared helper so an overlapping Modal/Dialog/Sidebar doesn't have its
|
|
78
|
+
// lock cleared when this one releases.
|
|
79
|
+
useScrollLock(isFullPage && active);
|
|
80
|
+
if (!active) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return (jsxs("div", { className: combinedClasses, role: "alert", "aria-busy": "true", "aria-label": "Loading", ...rest, children: [jsx("div", { className: combinedOverlayClasses, onClick: handleOverlayClick, "aria-hidden": "true" }), jsxs("div", { className: loadingContentClass, children: [indicator ? (jsx("span", { className: loadingIconCustomClass, children: indicator })) : (jsx("span", { className: combinedIconClasses })), children && jsx("div", { className: loadingTextClass, children: children }), canCancel && (jsx("button", { type: "button", className: loadingCancelClass, onClick: onCancel, "aria-label": "Cancel loading", children: "Cancel" }))] })] }));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export { Loading };
|
|
87
|
+
//# sourceMappingURL=Loading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loading.js","sources":["../../../src/components/Loading.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useScrollLock } from '../helpers/scrollLock';\n\n/**\n * Overlay opacity levels for the Loading background.\n */\nexport type LoadingOverlay = 'light' | 'dark' | 'opaque';\n\n/**\n * Color variants for the Loading spinner.\n */\nexport type LoadingColor =\n 'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger';\n\n/**\n * Props for the Loading component.\n * @extraProp {React.ReactNode} [children] - Content to display below the spinner.\n * @extraProp {string} [className] - Additional CSS classes.\n */\nexport interface LoadingProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor' | 'size' | 'overlay'> {\n /** Whether the loading overlay is visible. */\n active?: boolean;\n /** Cover the entire viewport. */\n isFullPage?: boolean;\n /** Size of the loading spinner. */\n size?: 'small' | 'medium' | 'large';\n /** Color variant for the spinner. Default is light grey. */\n color?: LoadingColor;\n /** Show a cancel button and allow closing. */\n canCancel?: boolean;\n /** Callback when cancel is triggered. */\n onCancel?: () => void;\n /** Additional classes for the overlay. */\n overlayClassName?: string;\n /** Additional classes for the spinner icon. */\n iconClassName?: string;\n /** Custom loading indicator element. */\n indicator?: React.ReactNode;\n /** Style of the loading overlay. */\n overlay?: LoadingOverlay;\n}\n\n/**\n * The `Loading` component provides a loading overlay with a spinner animation.\n *\n * @function\n * @param {LoadingProps} props - Props for the Loading component.\n * @returns {JSX.Element | null} The rendered loading overlay or null if not active.\n *\n * @example\n * // Full page loading\n * <Loading active isFullPage />\n *\n * @example\n * // Container loading with message\n * <div style={{ position: 'relative', height: '200px' }}>\n * <Loading active>Loading data...</Loading>\n * </div>\n *\n * @example\n * // With color variant\n * <Loading active color=\"primary\" />\n *\n * @example\n * // With cancel functionality\n * <Loading\n * active={isLoading}\n * canCancel\n * onCancel={() => setIsLoading(false)}\n * />\n */\nexport const Loading: React.FC<LoadingProps> = ({\n active = false,\n isFullPage = false,\n size,\n color,\n canCancel = false,\n onCancel,\n children,\n className,\n overlayClassName,\n iconClassName,\n indicator,\n overlay,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const loadingClasses = usePrefixedClassNames('loading', {\n 'is-active': active,\n 'is-full-page': isFullPage,\n 'is-cancelable': canCancel,\n [`is-${overlay}`]: !!overlay,\n [`is-${color}`]: !!color,\n });\n\n const iconClasses = usePrefixedClassNames('loading-icon', {\n [`is-${size}`]: size,\n });\n\n // Combine classes\n const combinedClasses = classNames(\n loadingClasses,\n bulmaHelperClasses,\n className\n );\n const combinedOverlayClasses = classNames(\n usePrefixedClassNames('loading-overlay'),\n overlayClassName\n );\n const combinedIconClasses = classNames(iconClasses, iconClassName);\n const loadingContentClass = usePrefixedClassNames('loading-content');\n const loadingIconCustomClass = usePrefixedClassNames('loading-icon-custom');\n const loadingTextClass = usePrefixedClassNames('loading-text');\n const loadingCancelClass = usePrefixedClassNames('loading-cancel');\n\n // Handle cancel click\n const handleOverlayClick = () => {\n if (canCancel && onCancel) {\n onCancel();\n }\n };\n\n // Handle escape key\n React.useEffect(() => {\n if (!active || !canCancel || !onCancel) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCancel();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [active, canCancel, onCancel]);\n\n // Prevent body scroll when full page loading is active. Ref-counted through\n // the shared helper so an overlapping Modal/Dialog/Sidebar doesn't have its\n // lock cleared when this one releases.\n useScrollLock(isFullPage && active);\n\n if (!active) {\n return null;\n }\n\n return (\n <div\n className={combinedClasses}\n role=\"alert\"\n aria-busy=\"true\"\n aria-label=\"Loading\"\n {...rest}\n >\n <div\n className={combinedOverlayClasses}\n onClick={handleOverlayClick}\n aria-hidden=\"true\"\n />\n <div className={loadingContentClass}>\n {indicator ? (\n <span className={loadingIconCustomClass}>{indicator}</span>\n ) : (\n <span className={combinedIconClasses} />\n )}\n {children && <div className={loadingTextClass}>{children}</div>}\n {canCancel && (\n <button\n type=\"button\"\n className={loadingCancelClass}\n onClick={onCancel}\n aria-label=\"Cancel loading\"\n >\n Cancel\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Loading;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|