@graphprotocol/gds-react 0.1.2 → 0.2.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/GDSProvider.d.ts +12 -10
- package/dist/GDSProvider.d.ts.map +1 -1
- package/dist/GDSProvider.js +10 -8
- package/dist/GDSProvider.js.map +1 -1
- package/dist/components/Address.js +2 -2
- package/dist/components/Address.meta.d.ts +1 -13
- package/dist/components/Address.meta.d.ts.map +1 -1
- package/dist/components/Avatar.d.ts.map +1 -1
- package/dist/components/Avatar.js +2 -10
- package/dist/components/Avatar.js.map +1 -1
- package/dist/components/Avatar.meta.d.ts +0 -2
- package/dist/components/Avatar.meta.d.ts.map +1 -1
- package/dist/components/AvatarGroup.meta.d.ts +8 -2
- package/dist/components/AvatarGroup.meta.d.ts.map +1 -1
- package/dist/components/Breadcrumbs.meta.d.ts +2 -3
- package/dist/components/Breadcrumbs.meta.d.ts.map +1 -1
- package/dist/components/Breadcrumbs.meta.js +3 -1
- package/dist/components/Breadcrumbs.meta.js.map +1 -1
- package/dist/components/Breadcrumbs.parts.d.ts.map +1 -1
- package/dist/components/Breadcrumbs.parts.js +13 -21
- package/dist/components/Breadcrumbs.parts.js.map +1 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +10 -9
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Button.meta.d.ts +1 -4
- package/dist/components/Button.meta.d.ts.map +1 -1
- package/dist/components/ButtonGroup.d.ts.map +1 -1
- package/dist/components/ButtonGroup.js +1 -5
- package/dist/components/ButtonGroup.js.map +1 -1
- package/dist/components/ButtonGroup.meta.d.ts +1 -5
- package/dist/components/ButtonGroup.meta.d.ts.map +1 -1
- package/dist/components/ButtonGroup.meta.js +8 -0
- package/dist/components/ButtonGroup.meta.js.map +1 -1
- package/dist/components/Card.meta.d.ts +1 -2
- package/dist/components/Card.meta.d.ts.map +1 -1
- package/dist/components/Card.meta.js +1 -0
- package/dist/components/Card.meta.js.map +1 -1
- package/dist/components/Checkbox.meta.d.ts +1 -6
- package/dist/components/Checkbox.meta.d.ts.map +1 -1
- package/dist/components/Checkbox.meta.js +1 -5
- package/dist/components/Checkbox.meta.js.map +1 -1
- package/dist/components/Chip.meta.d.ts +2 -4
- package/dist/components/Chip.meta.d.ts.map +1 -1
- package/dist/components/Chip.parts.d.ts.map +1 -1
- package/dist/components/Chip.parts.js +1 -9
- package/dist/components/Chip.parts.js.map +1 -1
- package/dist/components/Cluster.meta.d.ts +8 -2
- package/dist/components/Cluster.meta.d.ts.map +1 -1
- package/dist/components/CodeBlock.d.ts +1 -1
- package/dist/components/CodeBlock.meta.d.ts +2 -4
- package/dist/components/CodeBlock.meta.d.ts.map +1 -1
- package/dist/components/CodeBlock.parts.d.ts +6 -7
- package/dist/components/CodeBlock.parts.d.ts.map +1 -1
- package/dist/components/CodeBlock.parts.js +28 -10
- package/dist/components/CodeBlock.parts.js.map +1 -1
- package/dist/components/CodeInline.js +3 -3
- package/dist/components/CodeInline.meta.d.ts +1 -1
- package/dist/components/CodeInline.meta.d.ts.map +1 -1
- package/dist/components/CopyButton.d.ts.map +1 -1
- package/dist/components/CopyButton.js +2 -4
- package/dist/components/CopyButton.js.map +1 -1
- package/dist/components/CopyButton.meta.d.ts +1 -12
- package/dist/components/CopyButton.meta.d.ts.map +1 -1
- package/dist/components/CopyButton.meta.js +1 -6
- package/dist/components/CopyButton.meta.js.map +1 -1
- package/dist/components/CurrencyInput.meta.d.ts +1 -6
- package/dist/components/CurrencyInput.meta.d.ts.map +1 -1
- package/dist/components/CurrencyInput.meta.js +1 -5
- package/dist/components/CurrencyInput.meta.js.map +1 -1
- package/dist/components/DescriptionList.meta.d.ts +2 -5
- package/dist/components/DescriptionList.meta.d.ts.map +1 -1
- package/dist/components/DescriptionList.parts.d.ts +3 -0
- package/dist/components/DescriptionList.parts.d.ts.map +1 -1
- package/dist/components/DescriptionList.parts.js +1 -0
- package/dist/components/DescriptionList.parts.js.map +1 -1
- package/dist/components/Divider.meta.d.ts +1 -3
- package/dist/components/Divider.meta.d.ts.map +1 -1
- package/dist/components/Icon.js +4 -4
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/Icon.meta.d.ts +0 -2
- package/dist/components/Icon.meta.d.ts.map +1 -1
- package/dist/components/Icon.meta.js +1 -0
- package/dist/components/Icon.meta.js.map +1 -1
- package/dist/components/Input.d.ts +5 -4
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +1 -0
- package/dist/components/Input.js.map +1 -1
- package/dist/components/Input.meta.d.ts +1 -6
- package/dist/components/Input.meta.d.ts.map +1 -1
- package/dist/components/Input.meta.js +1 -5
- package/dist/components/Input.meta.js.map +1 -1
- package/dist/components/Keyboard.js +1 -1
- package/dist/components/Keyboard.meta.d.ts +0 -1
- package/dist/components/Keyboard.meta.d.ts.map +1 -1
- package/dist/components/Label.meta.d.ts +1 -3
- package/dist/components/Label.meta.d.ts.map +1 -1
- package/dist/components/Link.d.ts +1 -1
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +1 -2
- package/dist/components/Link.js.map +1 -1
- package/dist/components/Link.meta.d.ts +1 -2
- package/dist/components/Link.meta.d.ts.map +1 -1
- package/dist/components/Link.meta.js +1 -0
- package/dist/components/Link.meta.js.map +1 -1
- package/dist/components/Menu.meta.d.ts +31 -2
- package/dist/components/Menu.meta.d.ts.map +1 -1
- package/dist/components/Menu.meta.js +39 -1
- package/dist/components/Menu.meta.js.map +1 -1
- package/dist/components/Menu.parts.d.ts +23 -32
- package/dist/components/Menu.parts.d.ts.map +1 -1
- package/dist/components/Menu.parts.js +284 -303
- package/dist/components/Menu.parts.js.map +1 -1
- package/dist/components/Modal.d.ts +1 -1
- package/dist/components/Modal.meta.d.ts +1 -3
- package/dist/components/Modal.meta.d.ts.map +1 -1
- package/dist/components/Modal.meta.js +1 -1
- package/dist/components/Modal.meta.js.map +1 -1
- package/dist/components/Modal.parts.d.ts +14 -15
- package/dist/components/Modal.parts.d.ts.map +1 -1
- package/dist/components/Modal.parts.js +36 -32
- package/dist/components/Modal.parts.js.map +1 -1
- package/dist/components/OTCInput.js +1 -1
- package/dist/components/OTCInput.meta.d.ts +1 -6
- package/dist/components/OTCInput.meta.d.ts.map +1 -1
- package/dist/components/OTCInput.meta.js +1 -5
- package/dist/components/OTCInput.meta.js.map +1 -1
- package/dist/components/Radio.meta.d.ts +1 -6
- package/dist/components/Radio.meta.d.ts.map +1 -1
- package/dist/components/Radio.meta.js +1 -5
- package/dist/components/Radio.meta.js.map +1 -1
- package/dist/components/Search.meta.d.ts +1 -3
- package/dist/components/Search.meta.d.ts.map +1 -1
- package/dist/components/SegmentedControl.meta.d.ts +2 -3
- package/dist/components/SegmentedControl.meta.d.ts.map +1 -1
- package/dist/components/SegmentedControl.meta.js +3 -1
- package/dist/components/SegmentedControl.meta.js.map +1 -1
- package/dist/components/SegmentedControl.parts.d.ts.map +1 -1
- package/dist/components/SegmentedControl.parts.js +4 -9
- package/dist/components/SegmentedControl.parts.js.map +1 -1
- package/dist/components/Status.meta.d.ts +0 -2
- package/dist/components/Status.meta.d.ts.map +1 -1
- package/dist/components/Stepper.meta.d.ts +1 -2
- package/dist/components/Stepper.meta.d.ts.map +1 -1
- package/dist/components/Stepper.meta.js +1 -0
- package/dist/components/Stepper.meta.js.map +1 -1
- package/dist/components/Stepper.parts.d.ts.map +1 -1
- package/dist/components/Stepper.parts.js +1 -1
- package/dist/components/Stepper.parts.js.map +1 -1
- package/dist/components/Switch.meta.d.ts +1 -6
- package/dist/components/Switch.meta.d.ts.map +1 -1
- package/dist/components/Switch.meta.js +1 -5
- package/dist/components/Switch.meta.js.map +1 -1
- package/dist/components/TabSet.meta.d.ts +2 -5
- package/dist/components/TabSet.meta.d.ts.map +1 -1
- package/dist/components/TabSet.meta.js +3 -1
- package/dist/components/TabSet.meta.js.map +1 -1
- package/dist/components/Tag.meta.d.ts +0 -2
- package/dist/components/Tag.meta.d.ts.map +1 -1
- package/dist/components/TextArea.meta.d.ts +1 -6
- package/dist/components/TextArea.meta.d.ts.map +1 -1
- package/dist/components/TextArea.meta.js +1 -5
- package/dist/components/TextArea.meta.js.map +1 -1
- package/dist/components/ToggleButton.js +2 -2
- package/dist/components/ToggleButton.js.map +1 -1
- package/dist/components/ToggleButton.meta.d.ts +1 -12
- package/dist/components/ToggleButton.meta.d.ts.map +1 -1
- package/dist/components/ToggleButton.meta.js +1 -6
- package/dist/components/ToggleButton.meta.js.map +1 -1
- package/dist/components/Tooltip.d.ts +2 -2
- package/dist/components/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip.js +2 -2
- package/dist/components/Tooltip.js.map +1 -1
- package/dist/components/Tooltip.meta.d.ts +12 -7
- package/dist/components/Tooltip.meta.d.ts.map +1 -1
- package/dist/components/Tooltip.meta.js +13 -2
- package/dist/components/Tooltip.meta.js.map +1 -1
- package/dist/components/Tooltip.parts.d.ts +20 -20
- package/dist/components/Tooltip.parts.d.ts.map +1 -1
- package/dist/components/Tooltip.parts.js +129 -88
- package/dist/components/Tooltip.parts.js.map +1 -1
- package/dist/components/base/Addon.meta.d.ts +1 -1
- package/dist/components/base/Addon.meta.d.ts.map +1 -1
- package/dist/components/base/Addon.meta.js +3 -1
- package/dist/components/base/Addon.meta.js.map +1 -1
- package/dist/components/base/ButtonOrLink.d.ts +1 -1
- package/dist/components/base/ButtonOrLink.parts.d.ts +6 -5
- package/dist/components/base/ButtonOrLink.parts.d.ts.map +1 -1
- package/dist/components/base/ButtonOrLink.parts.js +28 -31
- package/dist/components/base/ButtonOrLink.parts.js.map +1 -1
- package/dist/components/base/Checkable.meta.d.ts +1 -2
- package/dist/components/base/Checkable.meta.d.ts.map +1 -1
- package/dist/components/base/Checkable.parts.d.ts +6 -6
- package/dist/components/base/Checkable.parts.d.ts.map +1 -1
- package/dist/components/base/Checkable.parts.js +2 -2
- package/dist/components/base/Checkable.parts.js.map +1 -1
- package/dist/components/base/Field.meta.d.ts +1 -2
- package/dist/components/base/Field.meta.d.ts.map +1 -1
- package/dist/components/base/Field.parts.d.ts +5 -4
- package/dist/components/base/Field.parts.d.ts.map +1 -1
- package/dist/components/base/Field.parts.js +1 -1
- package/dist/components/base/Field.parts.js.map +1 -1
- package/dist/components/base/MaybeButtonOrLink.d.ts +1 -1
- package/dist/components/base/MaybeButtonOrLink.d.ts.map +1 -1
- package/dist/components/base/Portal.d.ts +1 -1
- package/dist/components/base/Portal.d.ts.map +1 -1
- package/dist/components/base/Portal.js +3 -6
- package/dist/components/base/Portal.js.map +1 -1
- package/dist/components/base/Render.d.ts +21 -6
- package/dist/components/base/Render.d.ts.map +1 -1
- package/dist/components/base/Render.js +3 -2
- package/dist/components/base/Render.js.map +1 -1
- package/dist/components/base/Transition.js +2 -2
- package/dist/components/base/Transition.meta.d.ts +1 -1
- package/dist/components/base/Transition.meta.d.ts.map +1 -1
- package/dist/components/base/Transition.meta.js +1 -0
- package/dist/components/base/Transition.meta.js.map +1 -1
- package/dist/components/base/index.d.ts +1 -2
- package/dist/components/base/index.d.ts.map +1 -1
- package/dist/components/base/index.js +1 -2
- package/dist/components/base/index.js.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useCSSProp.d.ts.map +1 -1
- package/dist/hooks/useCSSProp.js +6 -6
- package/dist/hooks/useCSSProp.js.map +1 -1
- package/dist/hooks/useCSSProps.d.ts +11 -13
- package/dist/hooks/useCSSProps.d.ts.map +1 -1
- package/dist/hooks/useCSSProps.js +11 -19
- package/dist/hooks/useCSSProps.js.map +1 -1
- package/dist/hooks/useCSSPropsPolyfill.d.ts +1 -1
- package/dist/hooks/useCSSPropsPolyfill.d.ts.map +1 -1
- package/dist/hooks/useCSSPropsPolyfill.js +12 -20
- package/dist/hooks/useCSSPropsPolyfill.js.map +1 -1
- package/dist/hooks/useCSSState.d.ts.map +1 -1
- package/dist/hooks/useCSSState.js +7 -3
- package/dist/hooks/useCSSState.js.map +1 -1
- package/dist/hooks/useEffectWithRefDeps.d.ts +2 -2
- package/dist/hooks/useEffectWithRefDeps.d.ts.map +1 -1
- package/dist/hooks/useEffectWithRefDeps.js +1 -1
- package/dist/hooks/useEffectWithRefDeps.js.map +1 -1
- package/dist/hooks/useFirstRender.d.ts +14 -0
- package/dist/hooks/useFirstRender.d.ts.map +1 -0
- package/dist/hooks/useFirstRender.js +20 -0
- package/dist/hooks/useFirstRender.js.map +1 -0
- package/dist/hooks/useGDS.d.ts +1 -1
- package/dist/hooks/usePrevious.d.ts +6 -4
- package/dist/hooks/usePrevious.d.ts.map +1 -1
- package/dist/hooks/usePrevious.js +6 -4
- package/dist/hooks/usePrevious.js.map +1 -1
- package/dist/hooks/useRefWithInit.d.ts +2 -2
- package/dist/hooks/useRefWithInit.d.ts.map +1 -1
- package/dist/hooks/useRefWithInit.js.map +1 -1
- package/dist/hooks/useStyleObserver.d.ts +2 -2
- package/dist/hooks/useStyleObserver.d.ts.map +1 -1
- package/dist/hooks/useStyleObserver.js.map +1 -1
- package/dist/icons/CalendarDynamicIcon.d.ts +8 -5
- package/dist/icons/CalendarDynamicIcon.d.ts.map +1 -1
- package/dist/icons/CalendarDynamicIcon.js +5 -2
- package/dist/icons/CalendarDynamicIcon.js.map +1 -1
- package/dist/icons/CopyInteractiveIcon.d.ts +5 -4
- package/dist/icons/CopyInteractiveIcon.d.ts.map +1 -1
- package/dist/icons/CopyInteractiveIcon.js +2 -2
- package/dist/icons/CopyInteractiveIcon.js.map +1 -1
- package/dist/icons/SidebarLeftInteractiveIcon.d.ts +4 -3
- package/dist/icons/SidebarLeftInteractiveIcon.d.ts.map +1 -1
- package/dist/icons/SidebarLeftInteractiveIcon.js +2 -2
- package/dist/icons/SidebarLeftInteractiveIcon.js.map +1 -1
- package/dist/icons/SidebarRightInteractiveIcon.d.ts +4 -3
- package/dist/icons/SidebarRightInteractiveIcon.d.ts.map +1 -1
- package/dist/icons/SidebarRightInteractiveIcon.js +2 -2
- package/dist/icons/SidebarRightInteractiveIcon.js.map +1 -1
- package/dist/tailwind-plugin.js +5 -5
- package/dist/tailwind-plugin.js.map +1 -1
- package/dist/utils/cn.d.ts +3 -1
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/cn.js +3 -1
- package/dist/utils/cn.js.map +1 -1
- package/dist/utils/getCSSPropsAttributes.d.ts +10 -3
- package/dist/utils/getCSSPropsAttributes.d.ts.map +1 -1
- package/dist/utils/getCSSPropsAttributes.js +4 -5
- package/dist/utils/getCSSPropsAttributes.js.map +1 -1
- package/dist/utils/splitProps.d.ts +1 -4
- package/dist/utils/splitProps.d.ts.map +1 -1
- package/dist/utils/splitProps.js +2 -7
- package/dist/utils/splitProps.js.map +1 -1
- package/dist/utils/trimReactNode.d.ts +10 -8
- package/dist/utils/trimReactNode.d.ts.map +1 -1
- package/dist/utils/trimReactNode.js +10 -8
- package/dist/utils/trimReactNode.js.map +1 -1
- package/package.json +17 -17
- package/src/GDSProvider.tsx +11 -9
- package/src/components/Address.tsx +2 -2
- package/src/components/Avatar.tsx +5 -10
- package/src/components/Breadcrumbs.meta.ts +3 -1
- package/src/components/Breadcrumbs.parts.tsx +16 -28
- package/src/components/Button.tsx +14 -10
- package/src/components/ButtonGroup.meta.ts +8 -0
- package/src/components/ButtonGroup.tsx +1 -5
- package/src/components/Card.meta.ts +1 -0
- package/src/components/Checkbox.meta.ts +1 -5
- package/src/components/Chip.parts.tsx +1 -11
- package/src/components/CodeBlock.parts.tsx +75 -50
- package/src/components/CodeInline.tsx +3 -3
- package/src/components/CopyButton.meta.ts +1 -6
- package/src/components/CopyButton.tsx +3 -4
- package/src/components/CurrencyInput.meta.ts +1 -5
- package/src/components/DescriptionList.parts.tsx +1 -0
- package/src/components/Icon.meta.ts +1 -0
- package/src/components/Icon.tsx +4 -4
- package/src/components/Input.meta.ts +1 -5
- package/src/components/Input.tsx +5 -6
- package/src/components/Keyboard.tsx +1 -1
- package/src/components/Link.meta.ts +1 -0
- package/src/components/Link.tsx +2 -3
- package/src/components/Menu.meta.ts +39 -1
- package/src/components/Menu.parts.tsx +553 -549
- package/src/components/Modal.meta.ts +1 -1
- package/src/components/Modal.parts.tsx +67 -68
- package/src/components/OTCInput.meta.ts +1 -5
- package/src/components/OTCInput.tsx +1 -1
- package/src/components/Radio.meta.ts +1 -5
- package/src/components/SegmentedControl.meta.ts +3 -1
- package/src/components/SegmentedControl.parts.tsx +7 -10
- package/src/components/Stepper.meta.ts +1 -0
- package/src/components/Stepper.parts.tsx +3 -1
- package/src/components/Switch.meta.ts +1 -5
- package/src/components/TabSet.meta.ts +3 -1
- package/src/components/TextArea.meta.ts +1 -5
- package/src/components/ToggleButton.meta.ts +1 -6
- package/src/components/ToggleButton.tsx +1 -1
- package/src/components/Tooltip.meta.ts +13 -2
- package/src/components/Tooltip.parts.tsx +215 -158
- package/src/components/Tooltip.tsx +2 -2
- package/src/components/base/Addon.meta.ts +3 -1
- package/src/components/base/ButtonOrLink.parts.tsx +52 -51
- package/src/components/base/Checkable.parts.tsx +6 -13
- package/src/components/base/Field.parts.tsx +5 -5
- package/src/components/base/Portal.tsx +5 -7
- package/src/components/base/Render.tsx +37 -15
- package/src/components/base/Transition.meta.ts +1 -0
- package/src/components/base/Transition.tsx +2 -2
- package/src/components/base/index.ts +8 -2
- package/src/components/index.ts +1 -2
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useCSSProp.ts +6 -8
- package/src/hooks/useCSSProps.ts +13 -22
- package/src/hooks/useCSSPropsPolyfill.ts +15 -23
- package/src/hooks/useCSSState.ts +11 -6
- package/src/hooks/useEffectWithRefDeps.ts +2 -2
- package/src/hooks/useFirstRender.ts +36 -0
- package/src/hooks/usePrevious.ts +6 -4
- package/src/hooks/useRefWithInit.ts +2 -2
- package/src/hooks/useStyleObserver.ts +5 -1
- package/src/icons/CalendarDynamicIcon.tsx +16 -6
- package/src/icons/CopyInteractiveIcon.tsx +10 -5
- package/src/icons/SidebarLeftInteractiveIcon.tsx +9 -5
- package/src/icons/SidebarRightInteractiveIcon.tsx +9 -5
- package/src/tailwind-plugin.ts +5 -5
- package/src/utils/cn.ts +3 -1
- package/src/utils/getCSSPropsAttributes.ts +13 -8
- package/src/utils/splitProps.ts +9 -9
- package/src/utils/trimReactNode.tsx +10 -8
- package/dist/components/base/ButtonOrLink.meta.d.ts +0 -2
- package/dist/components/base/ButtonOrLink.meta.d.ts.map +0 -1
- package/dist/components/base/ButtonOrLink.meta.js +0 -6
- package/dist/components/base/ButtonOrLink.meta.js.map +0 -1
- package/src/components/base/ButtonOrLink.meta.ts +0 -6
|
@@ -1,219 +1,216 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
3
|
-
import { createContext,
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useRef } from 'react';
|
|
4
4
|
import { Menu } from '@base-ui/react/menu';
|
|
5
5
|
import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
|
|
6
6
|
import { twToPx } from '@graphprotocol/gds-css';
|
|
7
7
|
import { ArrowRightInteractiveIcon, ArrowUpRightInteractiveIcon, CaretRightIcon, CheckIcon, LoadingIcon, MagnifyingGlassIcon, XIcon, } from '@graphprotocol/gds-react/icons';
|
|
8
|
-
import { useAutoValue, useControlled, useCSSState, useGDS } from "../hooks/index.js";
|
|
9
|
-
import { cn } from "../utils/index.js";
|
|
8
|
+
import { useAutoValue, useControlled, useCSSPropsPolyfill, useCSSState, useGDS, } from "../hooks/index.js";
|
|
9
|
+
import { cn, getCSSPropsAttributes, splitProps } from "../utils/index.js";
|
|
10
10
|
import { renderAddon } from "./base/Addon.js";
|
|
11
11
|
import { ButtonOrLink } from "./base/ButtonOrLink.js";
|
|
12
12
|
import { Render } from "./base/Render.js";
|
|
13
13
|
import { Button } from "./Button.js";
|
|
14
14
|
import { Checkbox } from "./Checkbox.js";
|
|
15
|
+
import { MenuMeta } from './Menu.meta.js';
|
|
16
|
+
import { Tooltip } from "./Tooltip.js";
|
|
15
17
|
const MenuTriggerContext = createContext(false);
|
|
16
|
-
export function MenuRoot({ ref: passedRef,
|
|
17
|
-
useGDS();
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
?
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
* Ensure Shift + Tab doesn't close the menu if there is a previous focusable element
|
|
125
|
-
* that is not a menu item (or if the previous focusable element is a menu item while
|
|
126
|
-
* the element that is currently focused is not).
|
|
127
|
-
*/
|
|
128
|
-
if (event.key === 'Tab' && event.shiftKey) {
|
|
129
|
-
const focusableElements = [
|
|
130
|
-
...event.currentTarget.querySelectorAll(`
|
|
131
|
-
a[href],
|
|
132
|
-
button:enabled,
|
|
133
|
-
input:enabled,
|
|
134
|
-
select:enabled,
|
|
135
|
-
textarea:enabled,
|
|
136
|
-
summary,
|
|
137
|
-
[tabindex]:not([tabindex="-1"]),
|
|
138
|
-
[contenteditable="true"]
|
|
139
|
-
`),
|
|
140
|
-
];
|
|
141
|
-
const previousElement = focusableElements.reverse().find((element) => {
|
|
142
|
-
return (element.compareDocumentPosition(document.activeElement) &
|
|
143
|
-
Node.DOCUMENT_POSITION_FOLLOWING);
|
|
144
|
-
});
|
|
145
|
-
const activeElementIsMenuItem = document.activeElement?.classList.contains('gds-menu-item');
|
|
146
|
-
const previousElementIsMenuItem = previousElement?.classList.contains('gds-menu-item');
|
|
147
|
-
if ((previousElement && !previousElementIsMenuItem) ||
|
|
148
|
-
(!activeElementIsMenuItem && previousElementIsMenuItem)) {
|
|
149
|
-
event.preventBaseUIHandler();
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// If there is a search input in the menu...
|
|
154
|
-
const searchInput = event.currentTarget.querySelector('input[type="search"]');
|
|
155
|
-
if (searchInput instanceof HTMLInputElement) {
|
|
156
|
-
// If the user typed some text, ensure it goes in the input instead of Base UI focusing the item that matches
|
|
157
|
-
if ((event.key.length === 1 && event.key !== ' ') ||
|
|
158
|
-
event.key === 'Backspace' ||
|
|
159
|
-
event.key === 'ArrowLeft' ||
|
|
160
|
-
event.key === 'ArrowRight') {
|
|
161
|
-
event.preventBaseUIHandler();
|
|
162
|
-
searchInput.focus();
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
const searchInputIsFocused = document.activeElement === searchInput;
|
|
166
|
-
const menuItems = [
|
|
167
|
-
...event.currentTarget.querySelectorAll('.gds-menu-item'),
|
|
168
|
-
];
|
|
169
|
-
const highlightedMenuItem = menuItems.find((item) => item.matches('[data-highlighted]'));
|
|
18
|
+
export function MenuRoot({ ref: passedRef, trigger, triggerMode: passedTriggerMode, side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight, open: controlledOpen, defaultOpen, onOpenChange, header, footer, label, type, value, defaultValue, onChange, className, style, children, ...props }) {
|
|
19
|
+
const { dirProps } = useGDS();
|
|
20
|
+
const { rootProps, nestedProps } = splitProps(props);
|
|
21
|
+
const portalRef = useRef(null);
|
|
22
|
+
const [cssPropsPolyfillRef, cssPropsPolyfillAttributes, cssProps] = useCSSPropsPolyfill(MenuMeta, {
|
|
23
|
+
side,
|
|
24
|
+
align,
|
|
25
|
+
matchTriggerWidth,
|
|
26
|
+
matchTriggerHeight,
|
|
27
|
+
}, {
|
|
28
|
+
returnPropValues: { side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight },
|
|
29
|
+
});
|
|
30
|
+
const isNested = useContext(MenuGroupContext) !== null;
|
|
31
|
+
const hasTrigger = trigger !== undefined;
|
|
32
|
+
const triggerIsElement = hasTrigger && typeof trigger !== 'function';
|
|
33
|
+
const triggerMode = passedTriggerMode ?? (isNested ? 'hover' : 'click');
|
|
34
|
+
const MenuRoot = isNested ? Menu.SubmenuRoot : Menu.Root;
|
|
35
|
+
const MenuTrigger = isNested ? Menu.SubmenuTrigger : Menu.Trigger;
|
|
36
|
+
const [open, setOpen] = useControlled(controlledOpen ?? (!hasTrigger ? true : undefined), defaultOpen ?? false, onOpenChange);
|
|
37
|
+
const initialOpen = useRef(open);
|
|
38
|
+
if (!open) {
|
|
39
|
+
initialOpen.current = false;
|
|
40
|
+
}
|
|
41
|
+
return (_jsx("div", { ref: cssPropsPolyfillRef, "data-nested": isNested || undefined, "data-has-trigger": hasTrigger || undefined, className: cn(`gds-menu root-contents [anchor-scope:all]
|
|
42
|
+
not-data-has-trigger:**:data-base-ui-focus-guard:hidden
|
|
43
|
+
u:rounded-12
|
|
44
|
+
u:data-nested:default-align-offset-[-2]
|
|
45
|
+
u:data-nested:default-gap-3
|
|
46
|
+
u:data-nested:default-side-end`, className), ...getCSSPropsAttributes(MenuMeta, { side, gap, align, alignOffset, matchTriggerWidth, matchTriggerHeight }, style), ...cssPropsPolyfillAttributes, ...rootProps, children: _jsxs(MenuRoot, { open: open, onOpenChange: (newOpen) => {
|
|
47
|
+
// A menu with no trigger can still be opened/closed by the consumer, but it should not send events
|
|
48
|
+
if (hasTrigger)
|
|
49
|
+
setOpen(newOpen);
|
|
50
|
+
}, modal: !isNested ? hasTrigger : undefined, closeParentOnEsc: true, children: [_jsx(MenuTriggerContext.Provider, { value: true, children: hasTrigger ? (
|
|
51
|
+
// Hoist any tooltip used in `trigger` for its interactions to work properly
|
|
52
|
+
_jsx(Tooltip, { children: _jsx(MenuTrigger, { nativeButton: !isNested,
|
|
53
|
+
// Ensure submenu triggers get disabled properly (see https://github.com/mui/base-ui/issues/3850)
|
|
54
|
+
disabled: triggerIsElement && trigger.props.disabled === true, openOnHover: triggerMode === 'hover', "data-open-on-hover": triggerMode === 'hover' || undefined, className: `
|
|
55
|
+
u:i:open:data-open-on-hover:state-hover
|
|
56
|
+
u:iii:open:not-data-open-on-hover:state-active
|
|
57
|
+
`, render: triggerIsElement
|
|
58
|
+
? trigger
|
|
59
|
+
: (renderProps) => {
|
|
60
|
+
// Don't pass event handlers and other potentially too specific props (e.g. `type`)
|
|
61
|
+
const filteredRenderProps = Object.fromEntries(Object.entries(renderProps).filter(([prop]) => prop === 'ref' ||
|
|
62
|
+
prop === 'id' ||
|
|
63
|
+
prop === 'className' ||
|
|
64
|
+
prop.startsWith('aria-') ||
|
|
65
|
+
prop.startsWith('data-')));
|
|
66
|
+
return trigger(filteredRenderProps, {
|
|
67
|
+
open,
|
|
68
|
+
setOpen,
|
|
69
|
+
openMenu: () => setOpen(true),
|
|
70
|
+
});
|
|
71
|
+
} }) })) : (
|
|
72
|
+
/**
|
|
73
|
+
* Base UI doesn't explicitly support menus with no `Menu.Trigger`, `Menu.Portal`, or
|
|
74
|
+
* `Menu.Positioner`, so we work around it. We render an invisible trigger to satisfy
|
|
75
|
+
* focus and keyboard expectations (note that it is visible when focused, as an
|
|
76
|
+
* outline). Then, to ensure the menu is rendered inline and not anchored to that
|
|
77
|
+
* trigger, we customize the portal container to be a sibling element (with `contents
|
|
78
|
+
* *:contents` so it's a transparent wrapper), and we apply positioning styles only when
|
|
79
|
+
* a trigger is provided (see `Menu.Positioner`'s `render` prop below). Finally, to
|
|
80
|
+
* prevent focus-trapping behavior that assumes a floating menu, we disable `modal` and
|
|
81
|
+
* hide Base UI’s focus guards with CSS (see root styles above).
|
|
82
|
+
*/
|
|
83
|
+
_jsxs(_Fragment, { children: [_jsx(Menu.Trigger, { "aria-label": props['aria-label'] ||
|
|
84
|
+
(label && typeof label === 'string' ? label : undefined) ||
|
|
85
|
+
'Menu', className: `
|
|
86
|
+
pointer-events-none absolute inset-[anchor(inside)] rounded-inherit [position-anchor:--gds-menu]
|
|
87
|
+
not-open:hidden
|
|
88
|
+
` }), _jsx("div", { ref: portalRef, className: "contents *:contents" })] })) }), _jsx(Menu.Portal, { container: !hasTrigger
|
|
89
|
+
? portalRef
|
|
90
|
+
: /**
|
|
91
|
+
* Specifying `document.body` because while it is the default for top-level menus, a nested menu
|
|
92
|
+
* defaults to using the same portal as its parent, which is not desirable when the parent is
|
|
93
|
+
* rendered inline (it can cause the nested menu to appear behind other elements).
|
|
94
|
+
*/
|
|
95
|
+
document?.body, children: _jsx(Menu.Positioner, { side: cssProps.side === 'start'
|
|
96
|
+
? 'inline-start'
|
|
97
|
+
: cssProps.side === 'end'
|
|
98
|
+
? 'inline-end'
|
|
99
|
+
: cssProps.side, sideOffset: twToPx(cssProps.gap), align: cssProps.align, alignOffset: twToPx(cssProps.alignOffset), collisionPadding: 8, collisionAvoidance: {
|
|
100
|
+
side: 'flip',
|
|
101
|
+
align: 'flip',
|
|
102
|
+
fallbackAxisSide: cssProps.side === 'start' || cssProps.side === 'end' ? 'end' : 'none',
|
|
103
|
+
}, "data-has-trigger": hasTrigger || undefined, "data-match-trigger-width": cssProps.matchTriggerWidth || undefined, "data-match-trigger-height": cssProps.matchTriggerHeight || undefined, className: cn(`root-flex
|
|
104
|
+
[--available-height-but-not-too-small:max(var(--available-height),--spacing(16))]
|
|
105
|
+
[anchor-name:--gds-menu]
|
|
106
|
+
has-nested/menu-footer:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
|
|
107
|
+
has-nested/menu-header:[--available-height-but-not-too-small:max(var(--available-height),--spacing(32))]
|
|
108
|
+
u:w-max
|
|
109
|
+
u:max-w-full
|
|
110
|
+
u:rounded-12
|
|
111
|
+
u:data-has-trigger:max-h-(--available-height-but-not-too-small)
|
|
112
|
+
u:data-has-trigger:max-w-(--available-width)
|
|
113
|
+
u:i:data-[match-trigger-height=at-least]:min-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
|
|
114
|
+
u:i:data-[match-trigger-height=at-most]:max-h-[min(var(--anchor-height),var(--available-height-but-not-too-small))]
|
|
115
|
+
u:i:data-[match-trigger-height=true]:h-(--anchor-height)
|
|
116
|
+
u:i:data-[match-trigger-width=at-least]:min-w-[min(var(--anchor-width),var(--available-width))]
|
|
117
|
+
u:i:data-[match-trigger-width=at-most]:max-w-[min(var(--anchor-width),var(--available-width))]
|
|
118
|
+
u:i:data-[match-trigger-width=true]:w-(--anchor-width)`, className), ...dirProps, render: (renderProps) => (_jsx("div", { ...renderProps, style: hasTrigger ? renderProps.style : undefined })), children: _jsxs(Menu.Popup, { ref: passedRef, "data-initial-open": initialOpen.current || undefined, className: `
|
|
119
|
+
flex grow origin-(--transform-origin) flex-col overflow-clip rounded-inherit bg-muted outline-0 transition
|
|
120
|
+
data-ending-style:scale-95
|
|
121
|
+
data-ending-style:opacity-0
|
|
122
|
+
data-starting-style:not-data-initial-open:scale-95
|
|
123
|
+
data-starting-style:not-data-initial-open:opacity-0
|
|
124
|
+
`, ...nestedProps, onKeyDown: (event) => {
|
|
125
|
+
nestedProps.onKeyDown?.(event);
|
|
170
126
|
/**
|
|
171
|
-
*
|
|
172
|
-
* a
|
|
173
|
-
*
|
|
127
|
+
* Ensure Shift + Tab doesn't close the menu if there is a previous focusable
|
|
128
|
+
* element that is not a menu item (or if the previous focusable element is a menu
|
|
129
|
+
* item while the element that is currently focused is not).
|
|
174
130
|
*/
|
|
175
|
-
if (event.key === '
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
131
|
+
if (event.key === 'Tab' && event.shiftKey) {
|
|
132
|
+
const focusableElements = [
|
|
133
|
+
...event.currentTarget.querySelectorAll(`
|
|
134
|
+
a[href],
|
|
135
|
+
button:enabled,
|
|
136
|
+
input:enabled,
|
|
137
|
+
select:enabled,
|
|
138
|
+
textarea:enabled,
|
|
139
|
+
summary,
|
|
140
|
+
[tabindex]:not([tabindex="-1"]),
|
|
141
|
+
[contenteditable="true"]
|
|
142
|
+
`),
|
|
143
|
+
];
|
|
144
|
+
const previousElement = focusableElements.reverse().find((element) => {
|
|
145
|
+
return (element.compareDocumentPosition(document.activeElement) &
|
|
146
|
+
Node.DOCUMENT_POSITION_FOLLOWING);
|
|
147
|
+
});
|
|
148
|
+
const activeElementIsMenuItem = document.activeElement?.classList.contains('gds-menu-item');
|
|
149
|
+
const previousElementIsMenuItem = previousElement?.classList.contains('gds-menu-item');
|
|
150
|
+
if ((previousElement && !previousElementIsMenuItem) ||
|
|
151
|
+
(!activeElementIsMenuItem && previousElementIsMenuItem)) {
|
|
152
|
+
event.preventBaseUIHandler();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
185
155
|
}
|
|
186
|
-
// If
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
156
|
+
// If there is a search input in the menu...
|
|
157
|
+
const searchInput = event.currentTarget.querySelector('input[type="search"]');
|
|
158
|
+
if (searchInput instanceof HTMLInputElement) {
|
|
159
|
+
// If the user typed some text, ensure it goes in the input instead of Base UI focusing the item that matches
|
|
160
|
+
if ((event.key.length === 1 && event.key !== ' ') ||
|
|
161
|
+
event.key === 'Backspace' ||
|
|
162
|
+
event.key === 'ArrowLeft' ||
|
|
163
|
+
event.key === 'ArrowRight') {
|
|
164
|
+
event.preventBaseUIHandler();
|
|
165
|
+
searchInput.focus();
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
const searchInputIsFocused = document.activeElement === searchInput;
|
|
169
|
+
const menuItems = [
|
|
170
|
+
...event.currentTarget.querySelectorAll('.gds-menu-item'),
|
|
171
|
+
];
|
|
172
|
+
const highlightedMenuItem = menuItems.find((item) => item.matches('[data-highlighted]'));
|
|
173
|
+
/**
|
|
174
|
+
* If the user pressed the down arrow while the search input is focused and
|
|
175
|
+
* there is a single menu item in the results, move the focus to it because it
|
|
176
|
+
* may already be highlighted, which would prevent Base UI from focusing it.
|
|
177
|
+
*/
|
|
178
|
+
if (event.key === 'ArrowDown' &&
|
|
179
|
+
searchInputIsFocused &&
|
|
180
|
+
menuItems.length === 1) {
|
|
181
|
+
event.preventBaseUIHandler();
|
|
182
|
+
menuItems[0].focus();
|
|
183
|
+
}
|
|
184
|
+
// Inversely, if the user pressed the up arrow and the focus is on the only menu item, move it back to the search input
|
|
185
|
+
else if (event.key === 'ArrowUp' &&
|
|
186
|
+
menuItems.length === 1 &&
|
|
187
|
+
document.activeElement === menuItems[0]) {
|
|
188
|
+
event.preventDefault();
|
|
189
|
+
searchInput.focus();
|
|
190
|
+
}
|
|
191
|
+
// If the user pressed Enter while the search input is focused and a menu item is highlighted, select it
|
|
192
|
+
else if (event.key === 'Enter' && searchInputIsFocused && highlightedMenuItem) {
|
|
193
|
+
highlightedMenuItem.focus();
|
|
194
|
+
window.setTimeout(() => {
|
|
195
|
+
highlightedMenuItem.dispatchEvent(new KeyboardEvent('keydown', {
|
|
196
|
+
key: 'Enter',
|
|
197
|
+
code: 'Enter',
|
|
198
|
+
keyCode: 13,
|
|
199
|
+
which: 13,
|
|
200
|
+
bubbles: true,
|
|
201
|
+
cancelable: true,
|
|
202
|
+
}));
|
|
203
|
+
}, 0);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
190
206
|
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}, children: [_jsx("div", { className: "w-58" }), header ? (_jsx("div", { className: "nested/menu-header u:shrink-0 u:border-b u:border-muted u:p-4", children: header })) : null, _jsx("div", { className: "scrollbar-thin grow scroll-p-8 overflow-x-clip overflow-y-auto gradient-mask-y", children: _jsx("div", { className: "overflow-clip p-2", children: _jsx(MenuItemsContext.Provider, { value: { position }, children: _jsxs(MenuGroupContext.Provider, { value: null, children: [label !== undefined || type !== undefined ? (type === 'radio' ? (_jsx(MenuGroup, { label: label, type: type, value: value, defaultValue: defaultValue, onChange: onChange, children: children })) : (_jsx(MenuGroup, { label: label, type: type, children: children }))) : (children), _jsx("div", { className: "mt-[calc(-2*(--spacing(2))-1px)] not-preceded-by-peer/menu-group:hidden" })] }) }) }) }), footer ? (_jsx("div", { className: "nested/menu-footer u:shrink-0 u:border-t u:border-muted u:p-4", children: footer })) : null, _jsx("div", { className: "pointer-events-none absolute inset-0 rounded-inherit border border-muted" })] }) })] }));
|
|
207
|
+
}, children: [_jsx("div", { className: "w-58" }), header ? (_jsx("div", { className: "nested/menu-header u:shrink-0 u:border-b u:border-muted u:p-4", children: header })) : null, _jsx("div", { className: "scrollbar-thin grow scroll-p-8 overflow-x-clip overflow-y-auto gradient-mask-y", children: _jsx("div", { className: "overflow-clip p-2", children: _jsxs(MenuGroupContext.Provider, { value: "root", children: [label !== undefined || type !== undefined ? (type === 'radio' ? (_jsx(MenuGroup, { label: label, type: type, value: value, defaultValue: defaultValue, onChange: onChange, children: children })) : (_jsx(MenuGroup, { label: label, type: type, children: children }))) : (children), _jsx("div", { className: "mt-[calc(-2*(--spacing(2))-1px)] not-preceded-by-peer/menu-group:hidden" })] }) }) }), footer ? (_jsx("div", { className: "nested/menu-footer u:shrink-0 u:border-t u:border-muted u:p-4", children: footer })) : null, _jsx("div", { className: "pointer-events-none absolute inset-0 rounded-inherit border border-muted" })] }) }) })] }, `${hasTrigger}-${triggerMode}`) }));
|
|
194
208
|
}
|
|
195
209
|
MenuRoot.displayName = 'Menu';
|
|
196
|
-
const MenuItemsContext = createContext(null);
|
|
197
|
-
const MaybePortal = ({ position, ...props }) => {
|
|
198
|
-
const containerRef = useRef(null);
|
|
199
|
-
const { dirProps } = useGDS();
|
|
200
|
-
return (_jsxs(_Fragment, { children: [!position ? _jsx("div", { ref: containerRef, className: "contents *:contents" }) : null, _jsx(Menu.Portal, { container: !position
|
|
201
|
-
? containerRef
|
|
202
|
-
: /**
|
|
203
|
-
* Specifying `document.body` because while it is the default for top-level menus, a nested menu
|
|
204
|
-
* defaults to using the same portal as its parent, which is not desirable when the parent is not
|
|
205
|
-
* positioned (it can cause the nested menu to appear behind other elements).
|
|
206
|
-
*/
|
|
207
|
-
document?.body, children: _jsx(Menu.Positioner, { align: position ? position.align : 'start', alignOffset: position ? twToPx(position.alignOffset) : 0, side: position ? position.side : 'bottom', sideOffset: position ? twToPx(position.gap) : 0, collisionPadding: 8, ...dirProps, render: ({ style, ...otherPositionerProps }) => {
|
|
208
|
-
const allowedPositionerProps = position
|
|
209
|
-
? { style, ...otherPositionerProps }
|
|
210
|
-
: otherPositionerProps;
|
|
211
|
-
return _jsx("div", { ...allowedPositionerProps, ...props });
|
|
212
|
-
} }) })] }));
|
|
213
|
-
};
|
|
214
210
|
const MenuGroupContext = createContext(null);
|
|
215
211
|
export function MenuGroup({ label, type = 'plain', value, defaultValue, onChange, className, style, children, ...props }) {
|
|
216
|
-
const
|
|
212
|
+
const groupContext = useContext(MenuGroupContext);
|
|
213
|
+
const isNested = groupContext !== null && groupContext !== 'root';
|
|
217
214
|
if (isNested) {
|
|
218
215
|
throw new Error(`[Menu] Groups cannot be nested, make sure you're not using \`Menu.Group\` in a \`Menu\` with a \`label\` and/or \`type\` prop (implicit group)`);
|
|
219
216
|
}
|
|
@@ -235,112 +232,96 @@ export function MenuItem({ ref: passedRef, type: passedType, addonBefore: passed
|
|
|
235
232
|
const hasAncestorMenuTrigger = useContext(MenuTriggerContext) !== false;
|
|
236
233
|
const type = hasAncestorMenuTrigger
|
|
237
234
|
? 'submenu-trigger'
|
|
238
|
-
: (passedType ??
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
235
|
+
: (passedType ??
|
|
236
|
+
(groupContext !== null && groupContext !== 'root' ? groupContext.type : undefined) ??
|
|
237
|
+
'plain');
|
|
238
|
+
const renderContent = (renderProps) => {
|
|
239
|
+
let addonBefore = passedAddonBefore;
|
|
240
|
+
let addonInside = undefined;
|
|
241
|
+
let addonAfter = passedAddonAfter;
|
|
242
|
+
if (type === 'checkbox') {
|
|
243
|
+
if (addonBefore)
|
|
244
|
+
addonInside = addonBefore;
|
|
245
|
+
addonBefore = (_jsx(Checkbox, { inert: true, "aria-label": "" // Prevent console warning about missing label
|
|
246
|
+
, className: `
|
|
247
|
+
@state-checked/menu-item:state-checked
|
|
248
|
+
@state-indeterminate/menu-item:state-indeterminate
|
|
249
|
+
@state-hover/menu-item:state-hover
|
|
250
|
+
@state-active/menu-item:state-active
|
|
251
|
+
@state-disabled/menu-item:state-idle
|
|
252
|
+
@state-disabled/menu-item:@state-checked/menu-item:state-disabled
|
|
253
|
+
` }));
|
|
249
254
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return { disabled };
|
|
255
|
-
case 'checkbox':
|
|
256
|
-
return {
|
|
257
|
-
disabled,
|
|
258
|
-
checked,
|
|
259
|
-
defaultChecked,
|
|
260
|
-
onCheckedChange: onChange,
|
|
261
|
-
closeOnClick: false,
|
|
262
|
-
};
|
|
263
|
-
case 'radio':
|
|
264
|
-
return {
|
|
265
|
-
value: passedValue !== undefined ? passedValue : autoValue,
|
|
266
|
-
disabled,
|
|
267
|
-
closeOnClick: true,
|
|
268
|
-
};
|
|
269
|
-
case 'submenu-trigger':
|
|
270
|
-
return {};
|
|
255
|
+
if (type === 'radio') {
|
|
256
|
+
if (addonBefore)
|
|
257
|
+
addonInside = addonBefore;
|
|
258
|
+
addonBefore = _jsx(CheckIcon, { alt: "", className: "@state-unchecked/menu-item:invisible" });
|
|
271
259
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
@state-active/menu-item:transition-none
|
|
338
|
-
` }), addonBefore ? (_jsx(MenuItemAddon, { className: `
|
|
339
|
-
me-2
|
|
340
|
-
has-checkbox:@state-checked/menu-item:opacity-100
|
|
341
|
-
has-checkbox:@state-checked/menu-item:filter-none
|
|
342
|
-
`, children: renderAddon(addonBefore) })) : null, addonInside ? (_jsx(MenuItemAddon, { className: "me-1", children: renderAddon(addonInside) })) : null, _jsx("span", { className: "grow truncate pe-1", children: children || _jsx(_Fragment, { children: "\u00A0" }) }), addonAfter ? (_jsx(MenuItemAddon, { className: "ms-2", children: renderAddon(addonAfter) })) : null] }));
|
|
343
|
-
} }));
|
|
260
|
+
if (loading) {
|
|
261
|
+
addonAfter = _jsx(LoadingIcon, {});
|
|
262
|
+
}
|
|
263
|
+
if (type === 'submenu-trigger' && addonAfter === undefined) {
|
|
264
|
+
addonAfter = _jsx(CaretRightIcon, { alt: "" });
|
|
265
|
+
}
|
|
266
|
+
if (href !== undefined && addonAfter === undefined) {
|
|
267
|
+
addonAfter = (_jsx(ButtonOrLink.Consumer, { render: (buttonOrLinkState) => buttonOrLinkState?.target === '_blank' ? (_jsx(ArrowUpRightInteractiveIcon, { hiddenByDefault: true })) : (_jsx(ArrowRightInteractiveIcon, { hiddenByDefault: true })) }));
|
|
268
|
+
}
|
|
269
|
+
return (_jsxs(Render, { render: href !== undefined ? (_jsx(ButtonOrLink, { href: href, target: target, disabled: disabled })) : (_jsx("div", {})), "data-type": type, "data-variant": variant, className: cn(
|
|
270
|
+
// TODO: Replace `active:` with `data-pressed:` when https://github.com/mui/base-ui/issues/1726 is added, to style Space presses as well
|
|
271
|
+
`gds-menu-item root-flex w-full items-center outline-0 select-none u:rounded-6 u:p-2 u:text-16
|
|
272
|
+
u:state-idle
|
|
273
|
+
u:checked:state-checked
|
|
274
|
+
u:indeterminate:state-indeterminate
|
|
275
|
+
u:disabled:pointer-events-none
|
|
276
|
+
u:disabled:state-disabled
|
|
277
|
+
u:data-highlighted:state-hover
|
|
278
|
+
u:data-[variant=danger]:text-status-error-default
|
|
279
|
+
u:ii:active:state-active
|
|
280
|
+
u:ii:data-[type=submenu-trigger]:not-[a]:cursor-default
|
|
281
|
+
u:ii:data-[type=submenu-trigger]:not-[a]:active:state-hover
|
|
282
|
+
${ /* Disabled styles */''}
|
|
283
|
+
u:*:transition-opacity
|
|
284
|
+
u:disabled:*:opacity-disabled
|
|
285
|
+
u:disabled:*:grayscale`, className), ...renderProps, children: [_jsx("span", { className: `
|
|
286
|
+
absolute inset-0 rounded-inherit opacity-100 filter-none transition
|
|
287
|
+
@state-hover/menu-item:bg-elevated
|
|
288
|
+
@state-active/menu-item:bg-default
|
|
289
|
+
@state-active/menu-item:transition-none
|
|
290
|
+
` }), addonBefore ? (_jsx(MenuItemAddon, { className: `
|
|
291
|
+
me-2
|
|
292
|
+
has-checkbox:@state-checked/menu-item:opacity-100
|
|
293
|
+
has-checkbox:@state-checked/menu-item:filter-none
|
|
294
|
+
`, children: renderAddon(addonBefore) })) : null, addonInside ? (_jsx(MenuItemAddon, { className: "me-1", children: renderAddon(addonInside) })) : null, _jsx("span", { className: "grow truncate pe-1", children: children || _jsx(_Fragment, { children: "\u00A0" }) }), addonAfter ? (_jsx(MenuItemAddon, { className: "ms-2", children: renderAddon(addonAfter) })) : null] }));
|
|
295
|
+
};
|
|
296
|
+
// Filter out undefined values to satisfy Base UI's `exactOptionalPropertyTypes`
|
|
297
|
+
// TODO: Remove when https://github.com/mui/base-ui/pull/3302 is released
|
|
298
|
+
const definedProps = Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined));
|
|
299
|
+
const baseProps = {
|
|
300
|
+
ref: stateElementPassedRef,
|
|
301
|
+
...state.polyfillAttributes,
|
|
302
|
+
...definedProps,
|
|
303
|
+
};
|
|
304
|
+
if (type === 'submenu-trigger') {
|
|
305
|
+
return renderContent(baseProps);
|
|
306
|
+
}
|
|
307
|
+
const onKeyDown = (event) => {
|
|
308
|
+
props.onKeyDown?.(event);
|
|
309
|
+
/**
|
|
310
|
+
* Allow Space to activate menu items that are links. This may not be needed in the future (see
|
|
311
|
+
* https://github.com/mui/base-ui/issues/1746).
|
|
312
|
+
*/
|
|
313
|
+
if (!event.baseUIHandlerPrevented && event.key === ' ' && href !== undefined) {
|
|
314
|
+
event.preventBaseUIHandler();
|
|
315
|
+
elementRef.current?.click();
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
if (type === 'checkbox') {
|
|
319
|
+
return (_jsx(CheckboxItem, { ...baseProps, closeOnClick: false, checked: checked, defaultChecked: defaultChecked, onCheckedChange: onChange, onKeyDown: onKeyDown, disabled: disabled, render: renderContent }));
|
|
320
|
+
}
|
|
321
|
+
if (type === 'radio') {
|
|
322
|
+
return (_jsx(Menu.RadioItem, { ...baseProps, closeOnClick: true, value: passedValue !== undefined ? passedValue : autoValue, onKeyDown: onKeyDown, disabled: disabled, render: renderContent }));
|
|
323
|
+
}
|
|
324
|
+
return (_jsx(Menu.Item, { ...baseProps, onKeyDown: onKeyDown, disabled: disabled, render: renderContent }));
|
|
344
325
|
}
|
|
345
326
|
MenuItem.displayName = 'Menu.Item';
|
|
346
327
|
function MenuItemAddon({ className, children, ...props }) {
|
|
@@ -360,8 +341,8 @@ export function MenuSearch({ ref: passedRef, placeholder: passedPlaceholder, val
|
|
|
360
341
|
}
|
|
361
342
|
MenuSearch.displayName = 'Menu.Search';
|
|
362
343
|
/**
|
|
363
|
-
* Transparent wrapper for `Menu.CheckboxItem` to support `indeterminate`.
|
|
364
|
-
*
|
|
344
|
+
* Transparent wrapper for `Menu.CheckboxItem` to support `indeterminate`. This may not be needed in
|
|
345
|
+
* the future (see https://github.com/mui/base-ui/issues/1983).
|
|
365
346
|
*/
|
|
366
347
|
function CheckboxItem({ checked: controlledChecked, defaultChecked, onCheckedChange, ...props }) {
|
|
367
348
|
const [checked, setChecked] = useControlled(controlledChecked, defaultChecked ?? false, onCheckedChange);
|