@salt-ds/core 1.73.0 → 1.74.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/CHANGELOG.md +56 -0
- package/css/salt-core.css +269 -28
- package/dist-cjs/drawer/Drawer.css.js +1 -1
- package/dist-cjs/drawer/Drawer.js +54 -6
- package/dist-cjs/drawer/Drawer.js.map +1 -1
- package/dist-cjs/drawer/DrawerContext.js +2 -0
- package/dist-cjs/drawer/DrawerContext.js.map +1 -1
- package/dist-cjs/drawer/DrawerFooter.css.js +1 -1
- package/dist-cjs/drawer/DrawerHeader.css.js +1 -1
- package/dist-cjs/drawer/DrawerHeader.js +6 -3
- package/dist-cjs/drawer/DrawerHeader.js.map +1 -1
- package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js +6 -0
- package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
- package/dist-cjs/drawer/internal/DrawerResizeGuide.js +44 -0
- package/dist-cjs/drawer/internal/DrawerResizeGuide.js.map +1 -0
- package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js +6 -0
- package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
- package/dist-cjs/drawer/internal/DrawerResizeHandle.js +43 -0
- package/dist-cjs/drawer/internal/DrawerResizeHandle.js.map +1 -0
- package/dist-cjs/drawer/internal/useDrawerResize.js +519 -0
- package/dist-cjs/drawer/internal/useDrawerResize.js.map +1 -0
- package/dist-cjs/link-button/LinkButton.css.js +1 -1
- package/dist-cjs/menu/MenuAlignmentContext.js +55 -0
- package/dist-cjs/menu/MenuAlignmentContext.js.map +1 -0
- package/dist-cjs/menu/MenuBase.js +9 -3
- package/dist-cjs/menu/MenuBase.js.map +1 -1
- package/dist-cjs/menu/MenuGroup.js +42 -3
- package/dist-cjs/menu/MenuGroup.js.map +1 -1
- package/dist-cjs/menu/MenuGroupContext.js +27 -0
- package/dist-cjs/menu/MenuGroupContext.js.map +1 -0
- package/dist-cjs/menu/MenuItem.css.js +1 -1
- package/dist-cjs/menu/MenuItem.js +176 -50
- package/dist-cjs/menu/MenuItem.js.map +1 -1
- package/dist-cjs/menu/MenuPanel.js +12 -3
- package/dist-cjs/menu/MenuPanel.js.map +1 -1
- package/dist-cjs/menu/MenuPanelContext.js +3 -1
- package/dist-cjs/menu/MenuPanelContext.js.map +1 -1
- package/dist-cjs/toggle-button/ToggleButton.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-cjs/tree/TreeNodeTrigger.js +0 -1
- package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-es/drawer/Drawer.css.js +1 -1
- package/dist-es/drawer/Drawer.js +54 -6
- package/dist-es/drawer/Drawer.js.map +1 -1
- package/dist-es/drawer/DrawerContext.js +2 -0
- package/dist-es/drawer/DrawerContext.js.map +1 -1
- package/dist-es/drawer/DrawerFooter.css.js +1 -1
- package/dist-es/drawer/DrawerHeader.css.js +1 -1
- package/dist-es/drawer/DrawerHeader.js +6 -3
- package/dist-es/drawer/DrawerHeader.js.map +1 -1
- package/dist-es/drawer/internal/DrawerResizeGuide.css.js +4 -0
- package/dist-es/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
- package/dist-es/drawer/internal/DrawerResizeGuide.js +42 -0
- package/dist-es/drawer/internal/DrawerResizeGuide.js.map +1 -0
- package/dist-es/drawer/internal/DrawerResizeHandle.css.js +4 -0
- package/dist-es/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
- package/dist-es/drawer/internal/DrawerResizeHandle.js +41 -0
- package/dist-es/drawer/internal/DrawerResizeHandle.js.map +1 -0
- package/dist-es/drawer/internal/useDrawerResize.js +517 -0
- package/dist-es/drawer/internal/useDrawerResize.js.map +1 -0
- package/dist-es/link-button/LinkButton.css.js +1 -1
- package/dist-es/menu/MenuAlignmentContext.js +50 -0
- package/dist-es/menu/MenuAlignmentContext.js.map +1 -0
- package/dist-es/menu/MenuBase.js +9 -3
- package/dist-es/menu/MenuBase.js.map +1 -1
- package/dist-es/menu/MenuGroup.js +44 -5
- package/dist-es/menu/MenuGroup.js.map +1 -1
- package/dist-es/menu/MenuGroupContext.js +23 -0
- package/dist-es/menu/MenuGroupContext.js.map +1 -0
- package/dist-es/menu/MenuItem.css.js +1 -1
- package/dist-es/menu/MenuItem.js +177 -51
- package/dist-es/menu/MenuItem.js.map +1 -1
- package/dist-es/menu/MenuPanel.js +12 -3
- package/dist-es/menu/MenuPanel.js.map +1 -1
- package/dist-es/menu/MenuPanelContext.js +3 -1
- package/dist-es/menu/MenuPanelContext.js.map +1 -1
- package/dist-es/toggle-button/ToggleButton.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
- package/dist-es/tree/TreeNodeTrigger.js +0 -1
- package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
- package/dist-types/drawer/Drawer.d.ts +6 -0
- package/dist-types/drawer/DrawerContext.d.ts +3 -0
- package/dist-types/drawer/DrawerHeader.d.ts +1 -1
- package/dist-types/drawer/internal/DrawerResizeGuide.d.ts +7 -0
- package/dist-types/drawer/internal/DrawerResizeHandle.d.ts +8 -0
- package/dist-types/drawer/internal/index.d.ts +3 -0
- package/dist-types/drawer/internal/useDrawerResize.d.ts +34 -0
- package/dist-types/menu/MenuAlignmentContext.d.ts +14 -0
- package/dist-types/menu/MenuGroup.d.ts +26 -4
- package/dist-types/menu/MenuGroupContext.d.ts +10 -0
- package/dist-types/menu/MenuItem.d.ts +4 -0
- package/dist-types/menu/MenuPanelContext.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var createContext = require('../utils/createContext.js');
|
|
5
|
+
require('clsx');
|
|
6
|
+
require('react/jsx-runtime');
|
|
7
|
+
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
8
|
+
require('../utils/useId.js');
|
|
9
|
+
require('../salt-provider/SaltProvider.js');
|
|
10
|
+
require('../viewport/ViewportProvider.js');
|
|
11
|
+
|
|
12
|
+
const MenuAlignmentContext = createContext.createContext(
|
|
13
|
+
"MenuAlignmentContext",
|
|
14
|
+
{
|
|
15
|
+
reserveIconSpace: false,
|
|
16
|
+
reserveSelectionIconSpace: false,
|
|
17
|
+
registerIcon: () => () => void 0,
|
|
18
|
+
registerSelectionIcon: () => () => void 0
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
function useSlotRegistry() {
|
|
22
|
+
const [count, setCount] = React.useState(0);
|
|
23
|
+
const register = React.useCallback(() => {
|
|
24
|
+
setCount((current) => current + 1);
|
|
25
|
+
return () => setCount((current) => current - 1);
|
|
26
|
+
}, []);
|
|
27
|
+
return [count > 0, register];
|
|
28
|
+
}
|
|
29
|
+
function useMenuAlignmentScope() {
|
|
30
|
+
const [reserveIconSpace, registerIcon] = useSlotRegistry();
|
|
31
|
+
const [reserveSelectionIconSpace, registerSelectionIcon] = useSlotRegistry();
|
|
32
|
+
return React.useMemo(
|
|
33
|
+
() => ({
|
|
34
|
+
reserveIconSpace,
|
|
35
|
+
reserveSelectionIconSpace,
|
|
36
|
+
registerIcon,
|
|
37
|
+
registerSelectionIcon
|
|
38
|
+
}),
|
|
39
|
+
[
|
|
40
|
+
reserveIconSpace,
|
|
41
|
+
reserveSelectionIconSpace,
|
|
42
|
+
registerIcon,
|
|
43
|
+
registerSelectionIcon
|
|
44
|
+
]
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
function useMenuAlignment() {
|
|
48
|
+
return React.useContext(MenuAlignmentContext);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
exports.MenuAlignmentContext = MenuAlignmentContext;
|
|
52
|
+
exports.useMenuAlignment = useMenuAlignment;
|
|
53
|
+
exports.useMenuAlignmentScope = useMenuAlignmentScope;
|
|
54
|
+
exports.useSlotRegistry = useSlotRegistry;
|
|
55
|
+
//# sourceMappingURL=MenuAlignmentContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuAlignmentContext.js","sources":["../src/menu/MenuAlignmentContext.ts"],"sourcesContent":["import { useCallback, useContext, useMemo, useState } from \"react\";\nimport { createContext } from \"../utils\";\n\n/**\n * The leading slots that items in one alignment scope reserve for each other.\n * Each `MenuGroup` is a scope, and items outside a group share their `MenuPanel`'s scope.\n */\nexport interface MenuAlignmentContextValue {\n reserveIconSpace: boolean;\n reserveSelectionIconSpace: boolean;\n registerIcon: () => () => void;\n registerSelectionIcon: () => () => void;\n}\n\nexport const MenuAlignmentContext = createContext<MenuAlignmentContextValue>(\n \"MenuAlignmentContext\",\n {\n reserveIconSpace: false,\n reserveSelectionIconSpace: false,\n registerIcon: () => () => undefined,\n registerSelectionIcon: () => () => undefined,\n },\n);\n\nexport function useSlotRegistry() {\n const [count, setCount] = useState(0);\n const register = useCallback(() => {\n setCount((current) => current + 1);\n return () => setCount((current) => current - 1);\n }, []);\n return [count > 0, register] as const;\n}\n\nexport function useMenuAlignmentScope(): MenuAlignmentContextValue {\n const [reserveIconSpace, registerIcon] = useSlotRegistry();\n const [reserveSelectionIconSpace, registerSelectionIcon] = useSlotRegistry();\n return useMemo(\n () => ({\n reserveIconSpace,\n reserveSelectionIconSpace,\n registerIcon,\n registerSelectionIcon,\n }),\n [\n reserveIconSpace,\n reserveSelectionIconSpace,\n registerIcon,\n registerSelectionIcon,\n ],\n );\n}\n\nexport function useMenuAlignment() {\n return useContext(MenuAlignmentContext);\n}\n"],"names":["createContext","useState","useCallback","useMemo","useContext"],"mappings":";;;;;;;;;;;AAcO,MAAM,oBAAA,GAAuBA,2BAAA;AAAA,EAClC,sBAAA;AAAA,EACA;AAAA,IACE,gBAAA,EAAkB,KAAA;AAAA,IAClB,yBAAA,EAA2B,KAAA;AAAA,IAC3B,YAAA,EAAc,MAAM,MAAM,MAAA;AAAA,IAC1B,qBAAA,EAAuB,MAAM,MAAM;AAAA;AAEvC;AAEO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,eAAS,CAAC,CAAA;AACpC,EAAA,MAAM,QAAA,GAAWC,kBAAY,MAAM;AACjC,IAAA,QAAA,CAAS,CAAC,OAAA,KAAY,OAAA,GAAU,CAAC,CAAA;AACjC,IAAA,OAAO,MAAM,QAAA,CAAS,CAAC,OAAA,KAAY,UAAU,CAAC,CAAA;AAAA,EAChD,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAO,CAAC,KAAA,GAAQ,CAAA,EAAG,QAAQ,CAAA;AAC7B;AAEO,SAAS,qBAAA,GAAmD;AACjE,EAAA,MAAM,CAAC,gBAAA,EAAkB,YAAY,CAAA,GAAI,eAAA,EAAgB;AACzD,EAAA,MAAM,CAAC,yBAAA,EAA2B,qBAAqB,CAAA,GAAI,eAAA,EAAgB;AAC3E,EAAA,OAAOC,aAAA;AAAA,IACL,OAAO;AAAA,MACL,gBAAA;AAAA,MACA,yBAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,gBAAA;AAAA,MACA,yBAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;AAEO,SAAS,gBAAA,GAAmB;AACjC,EAAA,OAAOC,iBAAW,oBAAoB,CAAA;AACxC;;;;;;;"}
|
|
@@ -11,6 +11,7 @@ require('../utils/useId.js');
|
|
|
11
11
|
require('../salt-provider/SaltProvider.js');
|
|
12
12
|
require('../viewport/ViewportProvider.js');
|
|
13
13
|
var MenuContext = require('./MenuContext.js');
|
|
14
|
+
var MenuGroupContext = require('./MenuGroupContext.js');
|
|
14
15
|
|
|
15
16
|
function MenuBase(props) {
|
|
16
17
|
const {
|
|
@@ -42,10 +43,14 @@ function MenuBase(props) {
|
|
|
42
43
|
const [focusInside, setFocusInside] = React.useState(false);
|
|
43
44
|
const [triggerDisabled, setTriggerDisabled] = React.useState(false);
|
|
44
45
|
const isNested = parentId != null;
|
|
46
|
+
const handleOpenChange = (newOpen) => {
|
|
47
|
+
if (newOpen && triggerDisabled) return;
|
|
48
|
+
setOpen(newOpen);
|
|
49
|
+
};
|
|
45
50
|
const { x, y, strategy, elements, refs, context } = useFloatingUI.useFloatingUI({
|
|
46
51
|
nodeId,
|
|
47
52
|
open: openState,
|
|
48
|
-
onOpenChange:
|
|
53
|
+
onOpenChange: handleOpenChange,
|
|
49
54
|
strategy: !getVirtualElement ? "absolute" : "fixed",
|
|
50
55
|
placement: placement ?? (isNested || getVirtualElement ? "right-start" : "bottom-start"),
|
|
51
56
|
middleware: [
|
|
@@ -86,7 +91,8 @@ function MenuBase(props) {
|
|
|
86
91
|
listRef: elementsRef,
|
|
87
92
|
activeIndex,
|
|
88
93
|
nested: isNested,
|
|
89
|
-
onNavigate: setActiveIndex
|
|
94
|
+
onNavigate: setActiveIndex,
|
|
95
|
+
disabledIndices: (index) => elementsRef.current[index] == null
|
|
90
96
|
})
|
|
91
97
|
]
|
|
92
98
|
);
|
|
@@ -129,7 +135,7 @@ function MenuBase(props) {
|
|
|
129
135
|
triggerDisabled,
|
|
130
136
|
setTriggerDisabled
|
|
131
137
|
},
|
|
132
|
-
children
|
|
138
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MenuGroupContext.MenuGroupContext.Provider, { value: MenuGroupContext.defaultMenuGroupContextValue, children })
|
|
133
139
|
}
|
|
134
140
|
) });
|
|
135
141
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuBase.js","sources":["../src/menu/MenuBase.tsx"],"sourcesContent":["import {\n FloatingNode,\n flip,\n limitShift,\n offset,\n type ReferenceType,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useRole,\n} from \"@floating-ui/react\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { MenuContext } from \"./MenuContext\";\n\nexport interface MenuBaseProps {\n children?: ReactNode;\n /**\n * Display or hide the component.\n */\n open?: boolean;\n /**\n * If true, the menu will be open by default.\n */\n defaultOpen?: boolean;\n /**\n * Callback function triggered when open state changes.\n */\n onOpenChange?: (newOpen: boolean) => void;\n /**\n * Set the placement of the Menu component relative to the trigger element. Defaults to `bottom-start` if it's the root menu or `right-start` if it's nested.\n */\n placement?: UseFloatingUIProps[\"placement\"];\n /**\n * Function that returns a [virtual element](https://floating-ui.com/docs/virtual-elements). If this is provided, it will override MenuTrigger.\n */\n getVirtualElement?: () => ReferenceType | null;\n}\n\nexport function MenuBase(props: MenuBaseProps) {\n const {\n children,\n defaultOpen,\n open,\n onOpenChange,\n placement,\n getVirtualElement,\n } = props;\n const parentId = useFloatingParentNodeId();\n const nodeId = useFloatingNodeId();\n const tree = useFloatingTree();\n const elementsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n const [openState, setOpenState] = useControlled({\n controlled: open,\n default: Boolean(defaultOpen),\n name: \"ListControl\",\n state: \"open\",\n });\n\n const setOpen = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [focusInside, setFocusInside] = useState(false);\n const [triggerDisabled, setTriggerDisabled] = useState(false);\n\n const isNested = parentId != null;\n\n const { x, y, strategy, elements, refs, context } = useFloatingUI({\n nodeId,\n open: openState,\n onOpenChange:
|
|
1
|
+
{"version":3,"file":"MenuBase.js","sources":["../src/menu/MenuBase.tsx"],"sourcesContent":["import {\n FloatingNode,\n flip,\n limitShift,\n offset,\n type ReferenceType,\n safePolygon,\n shift,\n size,\n useClick,\n useDismiss,\n useFloatingNodeId,\n useFloatingParentNodeId,\n useFloatingTree,\n useHover,\n useInteractions,\n useListNavigation,\n useRole,\n} from \"@floating-ui/react\";\nimport {\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n type UseFloatingUIProps,\n useControlled,\n useFloatingUI,\n useIsomorphicLayoutEffect,\n} from \"../utils\";\nimport { MenuContext } from \"./MenuContext\";\nimport {\n defaultMenuGroupContextValue,\n MenuGroupContext,\n} from \"./MenuGroupContext\";\n\nexport interface MenuBaseProps {\n children?: ReactNode;\n /**\n * Display or hide the component.\n */\n open?: boolean;\n /**\n * If true, the menu will be open by default.\n */\n defaultOpen?: boolean;\n /**\n * Callback function triggered when open state changes.\n */\n onOpenChange?: (newOpen: boolean) => void;\n /**\n * Set the placement of the Menu component relative to the trigger element. Defaults to `bottom-start` if it's the root menu or `right-start` if it's nested.\n */\n placement?: UseFloatingUIProps[\"placement\"];\n /**\n * Function that returns a [virtual element](https://floating-ui.com/docs/virtual-elements). If this is provided, it will override MenuTrigger.\n */\n getVirtualElement?: () => ReferenceType | null;\n}\n\nexport function MenuBase(props: MenuBaseProps) {\n const {\n children,\n defaultOpen,\n open,\n onOpenChange,\n placement,\n getVirtualElement,\n } = props;\n const parentId = useFloatingParentNodeId();\n const nodeId = useFloatingNodeId();\n const tree = useFloatingTree();\n const elementsRef = useRef<(HTMLDivElement | null)[]>([]);\n\n const [openState, setOpenState] = useControlled({\n controlled: open,\n default: Boolean(defaultOpen),\n name: \"ListControl\",\n state: \"open\",\n });\n\n const setOpen = useCallback(\n (newOpen: boolean) => {\n setOpenState(newOpen);\n onOpenChange?.(newOpen);\n },\n [onOpenChange],\n );\n\n const [activeIndex, setActiveIndex] = useState<number | null>(null);\n const [focusInside, setFocusInside] = useState(false);\n const [triggerDisabled, setTriggerDisabled] = useState(false);\n\n const isNested = parentId != null;\n\n const handleOpenChange = (newOpen: boolean) => {\n if (newOpen && triggerDisabled) return;\n setOpen(newOpen);\n };\n\n const { x, y, strategy, elements, refs, context } = useFloatingUI({\n nodeId,\n open: openState,\n onOpenChange: handleOpenChange,\n strategy: !getVirtualElement ? \"absolute\" : \"fixed\",\n placement:\n placement ??\n (isNested || getVirtualElement ? \"right-start\" : \"bottom-start\"),\n middleware: [\n // Align the nested menu by shifting it by var(--salt-spacing-fixed-100)\n offset(\n isNested ? { crossAxis: -1, mainAxis: 2 } : !getVirtualElement ? 1 : 0,\n ),\n flip({}),\n shift({ limiter: limitShift() }),\n size({\n apply({ elements, availableHeight }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${availableHeight}px`,\n });\n },\n }),\n ],\n });\n\n useIsomorphicLayoutEffect(() => {\n if (getVirtualElement) {\n refs.setPositionReference(getVirtualElement());\n }\n }, [getVirtualElement, refs]);\n\n const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(\n [\n useHover(context, {\n enabled: isNested && !focusInside && !triggerDisabled,\n handleClose: safePolygon({ blockPointerEvents: true }),\n }),\n useClick(context, {\n event: \"mousedown\",\n toggle: !isNested,\n ignoreMouse: isNested,\n }),\n useRole(context, { role: \"menu\" }),\n useDismiss(context, { bubbles: true }),\n useListNavigation(context, {\n listRef: elementsRef,\n activeIndex,\n nested: isNested,\n onNavigate: setActiveIndex,\n disabledIndices: (index) => elementsRef.current[index] == null,\n }),\n ],\n );\n\n const getPanelPosition = () => ({\n top: y ?? 0,\n left: x ?? 0,\n position: strategy,\n width: elements.floating?.offsetWidth,\n height: elements.floating?.offsetHeight,\n });\n\n useEffect(() => {\n if (!tree) return;\n\n function handleItemClick() {\n setOpen(false);\n }\n\n tree.events.on(\"click\", handleItemClick);\n\n return () => {\n tree.events.off(\"click\", handleItemClick);\n };\n }, [tree, setOpen]);\n\n return (\n <FloatingNode id={nodeId}>\n <MenuContext.Provider\n value={{\n openState,\n getReferenceProps,\n getFloatingProps,\n refs,\n getPanelPosition,\n getItemProps,\n activeIndex,\n context,\n elementsRef,\n focusInside,\n setFocusInside,\n isNested,\n triggerDisabled,\n setTriggerDisabled,\n }}\n >\n <MenuGroupContext.Provider value={defaultMenuGroupContextValue}>\n {children}\n </MenuGroupContext.Provider>\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n"],"names":["useFloatingParentNodeId","useFloatingNodeId","useFloatingTree","useRef","useControlled","useCallback","useState","useFloatingUI","offset","flip","shift","limitShift","size","elements","useIsomorphicLayoutEffect","useInteractions","useHover","safePolygon","useClick","useRole","useDismiss","useListNavigation","useEffect","jsx","FloatingNode","MenuContext","MenuGroupContext","defaultMenuGroupContextValue"],"mappings":"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"}
|
|
@@ -10,12 +10,23 @@ require('../utils/useFloatingUI/useFloatingUI.js');
|
|
|
10
10
|
var useId = require('../utils/useId.js');
|
|
11
11
|
require('../salt-provider/SaltProvider.js');
|
|
12
12
|
require('../viewport/ViewportProvider.js');
|
|
13
|
+
var MenuAlignmentContext = require('./MenuAlignmentContext.js');
|
|
13
14
|
var MenuGroup$1 = require('./MenuGroup.css.js');
|
|
15
|
+
var MenuGroupContext = require('./MenuGroupContext.js');
|
|
14
16
|
|
|
15
17
|
const withBaseName = makePrefixer.makePrefixer("saltMenuGroup");
|
|
18
|
+
const noSelection = [];
|
|
16
19
|
const MenuGroup = React.forwardRef(
|
|
17
20
|
function MenuGroup2(props, ref) {
|
|
18
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
className,
|
|
23
|
+
children,
|
|
24
|
+
label,
|
|
25
|
+
onSelectionChange,
|
|
26
|
+
selected: selectedProp = noSelection,
|
|
27
|
+
selectionVariant,
|
|
28
|
+
...rest
|
|
29
|
+
} = props;
|
|
19
30
|
const targetWindow = window.useWindow();
|
|
20
31
|
styles.useComponentCssInjection({
|
|
21
32
|
testId: "salt-menu-group",
|
|
@@ -23,7 +34,35 @@ const MenuGroup = React.forwardRef(
|
|
|
23
34
|
window: targetWindow
|
|
24
35
|
});
|
|
25
36
|
const labelId = useId.useId();
|
|
26
|
-
|
|
37
|
+
const selected = React.useMemo(
|
|
38
|
+
() => selectionVariant === "single" ? selectedProp.slice(0, 1) : selectedProp,
|
|
39
|
+
[selectedProp, selectionVariant]
|
|
40
|
+
);
|
|
41
|
+
const isSelected = React.useCallback(
|
|
42
|
+
(value) => selected.includes(value),
|
|
43
|
+
[selected]
|
|
44
|
+
);
|
|
45
|
+
const select = React.useCallback(
|
|
46
|
+
(event, value) => {
|
|
47
|
+
if (selectionVariant === "single") {
|
|
48
|
+
if (!selected.includes(value)) {
|
|
49
|
+
onSelectionChange == null ? void 0 : onSelectionChange(event, [value]);
|
|
50
|
+
}
|
|
51
|
+
} else if (selectionVariant === "multiple") {
|
|
52
|
+
onSelectionChange == null ? void 0 : onSelectionChange(
|
|
53
|
+
event,
|
|
54
|
+
selected.includes(value) ? selected.filter((item) => item !== value) : selected.concat(value)
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
[onSelectionChange, selected, selectionVariant]
|
|
59
|
+
);
|
|
60
|
+
const contextValue = React.useMemo(
|
|
61
|
+
() => ({ isSelected, select, selectionVariant }),
|
|
62
|
+
[isSelected, select, selectionVariant]
|
|
63
|
+
);
|
|
64
|
+
const alignment = MenuAlignmentContext.useMenuAlignmentScope();
|
|
65
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MenuGroupContext.MenuGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(MenuAlignmentContext.MenuAlignmentContext.Provider, { value: alignment, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27
66
|
"div",
|
|
28
67
|
{
|
|
29
68
|
"aria-labelledby": label ? labelId : void 0,
|
|
@@ -36,7 +75,7 @@ const MenuGroup = React.forwardRef(
|
|
|
36
75
|
children
|
|
37
76
|
]
|
|
38
77
|
}
|
|
39
|
-
);
|
|
78
|
+
) }) });
|
|
40
79
|
}
|
|
41
80
|
);
|
|
42
81
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuGroup.js","sources":["../src/menu/MenuGroup.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n} from \"react\";\nimport { makePrefixer, useId } from \"../utils\";\nimport menuGroupCss from \"./MenuGroup.css\";\n\
|
|
1
|
+
{"version":3,"file":"MenuGroup.js","sources":["../src/menu/MenuGroup.tsx"],"sourcesContent":["import { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type ReactNode,\n type SyntheticEvent,\n useCallback,\n useMemo,\n} from \"react\";\nimport { makePrefixer, useId } from \"../utils\";\nimport {\n MenuAlignmentContext,\n useMenuAlignmentScope,\n} from \"./MenuAlignmentContext\";\nimport menuGroupCss from \"./MenuGroup.css\";\nimport { MenuGroupContext } from \"./MenuGroupContext\";\n\ninterface BaseMenuGroupProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * Menus to be rendered inside the menu group.\n */\n children?: ReactNode;\n /**\n * The label of the menu group.\n */\n label?: string;\n /**\n * Selection variant of the menu group. If \"single\", the menu items inside behave like radio buttons. If \"multiple\", they behave like checkboxes. Each selectable menu item needs a `value`. When omitted, the menu items are not selectable.\n */\n selectionVariant?: \"single\" | \"multiple\";\n}\n\ninterface SelectableMenuGroupProps extends BaseMenuGroupProps {\n /**\n * Callback fired when the selection changes.\n * @param event\n * @param newSelected The new selected values.\n */\n onSelectionChange?: (event: SyntheticEvent, newSelected: string[]) => void;\n /**\n * The values of the selected menu items. Required when `selectionVariant` is \"single\" or \"multiple\". The menu's content unmounts when it closes, so keep the selection in state and update it in `onSelectionChange`.\n */\n selected: string[];\n selectionVariant: \"single\" | \"multiple\";\n}\n\ninterface NonSelectableMenuGroupProps extends BaseMenuGroupProps {\n selectionVariant?: undefined;\n}\n\nexport type MenuGroupProps =\n | SelectableMenuGroupProps\n | NonSelectableMenuGroupProps;\n\nconst withBaseName = makePrefixer(\"saltMenuGroup\");\n\nconst noSelection: string[] = [];\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(\n function MenuGroup(props, ref) {\n const {\n className,\n children,\n label,\n onSelectionChange,\n selected: selectedProp = noSelection,\n selectionVariant,\n ...rest\n } = props as BaseMenuGroupProps &\n Partial<Pick<SelectableMenuGroupProps, \"onSelectionChange\" | \"selected\">>;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-menu-group\",\n css: menuGroupCss,\n window: targetWindow,\n });\n\n const labelId = useId();\n\n const selected = useMemo(\n () =>\n selectionVariant === \"single\" ? selectedProp.slice(0, 1) : selectedProp,\n [selectedProp, selectionVariant],\n );\n\n const isSelected = useCallback(\n (value: string) => selected.includes(value),\n [selected],\n );\n\n const select = useCallback(\n (event: SyntheticEvent, value: string) => {\n if (selectionVariant === \"single\") {\n if (!selected.includes(value)) {\n onSelectionChange?.(event, [value]);\n }\n } else if (selectionVariant === \"multiple\") {\n onSelectionChange?.(\n event,\n selected.includes(value)\n ? selected.filter((item) => item !== value)\n : selected.concat(value),\n );\n }\n },\n [onSelectionChange, selected, selectionVariant],\n );\n\n const contextValue = useMemo(\n () => ({ isSelected, select, selectionVariant }),\n [isSelected, select, selectionVariant],\n );\n\n const alignment = useMenuAlignmentScope();\n\n return (\n <MenuGroupContext.Provider value={contextValue}>\n <MenuAlignmentContext.Provider value={alignment}>\n <div\n aria-labelledby={label ? labelId : undefined}\n className={clsx(withBaseName(), className)}\n role=\"group\"\n ref={ref}\n {...rest}\n >\n {label && (\n <div aria-hidden className={withBaseName(\"label\")} id={labelId}>\n {label}\n </div>\n )}\n {children}\n </div>\n </MenuAlignmentContext.Provider>\n </MenuGroupContext.Provider>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","MenuGroup","useWindow","useComponentCssInjection","menuGroupCss","useId","useMemo","useCallback","useMenuAlignmentScope","jsx","MenuGroupContext","MenuAlignmentContext","jsxs","clsx"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var createContext = require('../utils/createContext.js');
|
|
5
|
+
require('clsx');
|
|
6
|
+
require('react/jsx-runtime');
|
|
7
|
+
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
8
|
+
require('../utils/useId.js');
|
|
9
|
+
require('../salt-provider/SaltProvider.js');
|
|
10
|
+
require('../viewport/ViewportProvider.js');
|
|
11
|
+
|
|
12
|
+
const defaultMenuGroupContextValue = {
|
|
13
|
+
isSelected: () => false,
|
|
14
|
+
select: () => void 0
|
|
15
|
+
};
|
|
16
|
+
const MenuGroupContext = createContext.createContext(
|
|
17
|
+
"MenuGroupContext",
|
|
18
|
+
defaultMenuGroupContextValue
|
|
19
|
+
);
|
|
20
|
+
function useMenuGroup() {
|
|
21
|
+
return React.useContext(MenuGroupContext);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
exports.MenuGroupContext = MenuGroupContext;
|
|
25
|
+
exports.defaultMenuGroupContextValue = defaultMenuGroupContextValue;
|
|
26
|
+
exports.useMenuGroup = useMenuGroup;
|
|
27
|
+
//# sourceMappingURL=MenuGroupContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuGroupContext.js","sources":["../src/menu/MenuGroupContext.ts"],"sourcesContent":["import { type SyntheticEvent, useContext } from \"react\";\nimport { createContext } from \"../utils\";\nimport type { MenuGroupProps } from \"./MenuGroup\";\n\nexport interface MenuGroupContextValue {\n isSelected: (value: string) => boolean;\n select: (event: SyntheticEvent, value: string) => void;\n selectionVariant?: MenuGroupProps[\"selectionVariant\"];\n}\n\nexport const defaultMenuGroupContextValue: MenuGroupContextValue = {\n isSelected: () => false,\n select: () => undefined,\n};\n\nexport const MenuGroupContext = createContext<MenuGroupContextValue>(\n \"MenuGroupContext\",\n defaultMenuGroupContextValue,\n);\n\nexport function useMenuGroup() {\n return useContext(MenuGroupContext);\n}\n"],"names":["createContext","useContext"],"mappings":";;;;;;;;;;;AAUO,MAAM,4BAAA,GAAsD;AAAA,EACjE,YAAY,MAAM,KAAA;AAAA,EAClB,QAAQ,MAAM;AAChB;AAEO,MAAM,gBAAA,GAAmBA,2BAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AACF;AAEO,SAAS,YAAA,GAAe;AAC7B,EAAA,OAAOC,iBAAW,gBAAgB,CAAA;AACpC;;;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".saltMenuItem {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n cursor: var(--salt-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n}\n\n.saltMenuItem:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMenuItem:hover {\n outline: none;\n}\n\n.saltMenuItem:hover,\n.saltMenuItem:focus-visible {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltMenuItem:active {\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n.saltMenuItem[aria-disabled=\"true\"],\n.saltMenuItem[aria-disabled=\"true\"]:active {\n opacity: 0.4;\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n cursor: var(--salt-cursor-disabled);\n box-shadow: none;\n}\n\n.saltMenuItem-blurActive {\n z-index: var(--salt-zIndex-default);\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n/* TODO: Find a better way of doing this */\n.saltMenuItem .saltIcon:not(.saltCheckboxIcon-icon) {\n min-height: var(--salt-text-lineHeight);\n}\n\n.saltMenuItem-expandIcon.saltIcon {\n margin-left: auto;\n}\n";
|
|
3
|
+
var css_248z = ".saltMenuItem {\n color: var(--salt-content-primary-foreground);\n background: var(--salt-selectable-background);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n font-family: var(--salt-text-fontFamily);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n min-height: calc(var(--salt-size-base) + var(--salt-spacing-100));\n padding: calc(var(--salt-spacing-100) + var(--salt-spacing-25)) var(--salt-spacing-100);\n display: flex;\n gap: var(--salt-spacing-100);\n position: relative;\n cursor: var(--salt-cursor-hover);\n box-sizing: border-box;\n flex-shrink: 0;\n --saltMenuItem-iconColumnWidth: max(var(--salt-size-icon), 12px);\n}\n\n.saltMenuItem:focus-visible {\n outline: var(--salt-focused-outline);\n outline-offset: calc(var(--salt-size-fixed-100) * -2);\n}\n\n.saltMenuItem:hover {\n outline: none;\n}\n\n.saltMenuItem:hover,\n.saltMenuItem:focus-visible {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltMenuItem[role=\"menuitem\"]:active {\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n.saltMenuItem[aria-disabled=\"true\"],\n.saltMenuItem[aria-disabled=\"true\"]:active {\n opacity: 0.4;\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n cursor: var(--salt-cursor-disabled);\n box-shadow: none;\n}\n\n.saltMenuItem-blurActive {\n z-index: var(--salt-zIndex-default);\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-fixed-100) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-fixed-100) 0 0 var(--salt-selectable-borderColor-selected);\n}\n\n/* TODO: Find a better way of doing this */\n.saltMenuItem .saltIcon:not(.saltCheckboxIcon-icon) {\n min-height: var(--salt-text-lineHeight);\n}\n\n.saltMenuItem .saltMenuItem-selectionIcon {\n margin: calc((var(--salt-text-lineHeight) - var(--salt-size-selectable)) / 2) 0;\n}\n\n.saltMenuItem-selectionIconPlaceholder {\n flex-shrink: 0;\n width: var(--salt-size-selectable);\n}\n\n.saltMenuItem-iconPlaceholder {\n flex-shrink: 0;\n width: var(--saltMenuItem-iconColumnWidth);\n}\n\n/* Account for selectable and icon token size differences, so labels after an icon line up with labels after a radio or checkbox */\n.saltMenuItem-selectionAlignedIcon {\n --saltMenuItem-iconColumnWidth: max(var(--salt-size-selectable), var(--salt-size-icon), 12px);\n}\n\n.saltMenuItem-selectionAlignedIcon > .saltIcon:first-child {\n margin-inline: max(0px, calc((var(--saltMenuItem-iconColumnWidth) - var(--icon-size)) / 2));\n}\n\n.saltMenuItem-expandIcon.saltIcon {\n margin-left: auto;\n}\n";
|
|
4
4
|
|
|
5
5
|
module.exports = css_248z;
|
|
6
6
|
//# sourceMappingURL=MenuItem.css.js.map
|
|
@@ -6,19 +6,52 @@ var styles = require('@salt-ds/styles');
|
|
|
6
6
|
var window$1 = require('@salt-ds/window');
|
|
7
7
|
var clsx = require('clsx');
|
|
8
8
|
var React = require('react');
|
|
9
|
+
require('../checkbox/Checkbox.js');
|
|
10
|
+
require('../checkbox/CheckboxGroup.js');
|
|
11
|
+
var CheckboxIcon = require('../checkbox/CheckboxIcon.js');
|
|
12
|
+
require('../radio-button/RadioButton.js');
|
|
13
|
+
require('../radio-button/RadioButtonGroup.js');
|
|
14
|
+
var RadioButtonIcon = require('../radio-button/RadioButtonIcon.js');
|
|
9
15
|
var SemanticIconProvider = require('../semantic-icon-provider/SemanticIconProvider.js');
|
|
10
16
|
var makePrefixer = require('../utils/makePrefixer.js');
|
|
17
|
+
var useIsomorphicLayoutEffect = require('../utils/useIsomorphicLayoutEffect.js');
|
|
11
18
|
require('../utils/useFloatingUI/useFloatingUI.js');
|
|
12
19
|
var useForkRef = require('../utils/useForkRef.js');
|
|
13
20
|
require('../utils/useId.js');
|
|
14
21
|
require('../salt-provider/SaltProvider.js');
|
|
15
22
|
require('../viewport/ViewportProvider.js');
|
|
23
|
+
var MenuAlignmentContext = require('./MenuAlignmentContext.js');
|
|
16
24
|
var MenuContext = require('./MenuContext.js');
|
|
25
|
+
var MenuGroupContext = require('./MenuGroupContext.js');
|
|
17
26
|
var MenuItem$1 = require('./MenuItem.css.js');
|
|
18
27
|
var MenuPanelContext = require('./MenuPanelContext.js');
|
|
19
28
|
var MenuTriggerContext = require('./MenuTriggerContext.js');
|
|
20
29
|
|
|
21
30
|
const withBaseName = makePrefixer.makePrefixer("saltMenuItem");
|
|
31
|
+
const leadingSlotClassNames = [
|
|
32
|
+
withBaseName("selectionIcon"),
|
|
33
|
+
withBaseName("selectionIconPlaceholder"),
|
|
34
|
+
withBaseName("iconPlaceholder")
|
|
35
|
+
];
|
|
36
|
+
function hasLeadingIcon(item) {
|
|
37
|
+
var _a;
|
|
38
|
+
for (const node of Array.from((item == null ? void 0 : item.childNodes) ?? [])) {
|
|
39
|
+
if (node.nodeType === node.TEXT_NODE) {
|
|
40
|
+
if ((_a = node.textContent) == null ? void 0 : _a.trim()) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
} else if (node.nodeType === node.ELEMENT_NODE) {
|
|
44
|
+
const { classList } = node;
|
|
45
|
+
if (!leadingSlotClassNames.some(
|
|
46
|
+
(className) => classList.contains(className)
|
|
47
|
+
)) {
|
|
48
|
+
return classList.contains("saltIcon");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
let missingValueWarningShown = false;
|
|
22
55
|
const MenuItem = React.forwardRef(
|
|
23
56
|
function MenuItem2(props, ref) {
|
|
24
57
|
const {
|
|
@@ -28,12 +61,26 @@ const MenuItem = React.forwardRef(
|
|
|
28
61
|
onClick,
|
|
29
62
|
onFocus,
|
|
30
63
|
onKeyDown,
|
|
64
|
+
value,
|
|
31
65
|
...rest
|
|
32
66
|
} = props;
|
|
33
67
|
const { triggersSubmenu, blurActive } = MenuTriggerContext.useIsMenuTrigger();
|
|
34
68
|
const { setTriggerDisabled } = MenuContext.useMenuContext();
|
|
35
69
|
const { ExpandGroupIcon } = SemanticIconProvider.useIcon();
|
|
36
|
-
const {
|
|
70
|
+
const {
|
|
71
|
+
activeIndex,
|
|
72
|
+
getItemProps,
|
|
73
|
+
setFocusInside,
|
|
74
|
+
hasSelectionIcon,
|
|
75
|
+
registerPanelSelectionIcon
|
|
76
|
+
} = MenuPanelContext.useMenuPanelContext();
|
|
77
|
+
const {
|
|
78
|
+
reserveIconSpace,
|
|
79
|
+
reserveSelectionIconSpace,
|
|
80
|
+
registerIcon,
|
|
81
|
+
registerSelectionIcon
|
|
82
|
+
} = MenuAlignmentContext.useMenuAlignment();
|
|
83
|
+
const { isSelected, select, selectionVariant } = MenuGroupContext.useMenuGroup();
|
|
37
84
|
const item = react.useListItem();
|
|
38
85
|
const tree = react.useFloatingTree();
|
|
39
86
|
const active = item.index === activeIndex;
|
|
@@ -43,57 +90,136 @@ const MenuItem = React.forwardRef(
|
|
|
43
90
|
css: MenuItem$1,
|
|
44
91
|
window: targetWindow
|
|
45
92
|
});
|
|
46
|
-
const
|
|
93
|
+
const itemRef = React.useRef(null);
|
|
94
|
+
const listItemRef = useForkRef.useForkRef(item.ref, itemRef);
|
|
95
|
+
const handleRef = useForkRef.useForkRef(ref, listItemRef);
|
|
96
|
+
const activationKeyRef = React.useRef(null);
|
|
97
|
+
const [hasIcon, setHasIcon] = React.useState(false);
|
|
98
|
+
const insideSelectableGroup = selectionVariant !== void 0 && !triggersSubmenu;
|
|
99
|
+
const selectable = insideSelectableGroup && value !== void 0;
|
|
100
|
+
const selected = selectable && isSelected(value);
|
|
101
|
+
const alignIconWithSelectionIcon = hasSelectionIcon && !selectable && !reserveSelectionIconSpace && (hasIcon || reserveIconSpace);
|
|
102
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
103
|
+
setHasIcon(hasLeadingIcon(itemRef.current));
|
|
104
|
+
});
|
|
105
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(
|
|
106
|
+
() => hasIcon ? registerIcon() : void 0,
|
|
107
|
+
[hasIcon, registerIcon]
|
|
108
|
+
);
|
|
109
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
110
|
+
if (!selectable) {
|
|
111
|
+
return void 0;
|
|
112
|
+
}
|
|
113
|
+
const unregisterFromGroup = registerSelectionIcon();
|
|
114
|
+
const unregisterFromPanel = registerPanelSelectionIcon();
|
|
115
|
+
return () => {
|
|
116
|
+
unregisterFromGroup();
|
|
117
|
+
unregisterFromPanel();
|
|
118
|
+
};
|
|
119
|
+
}, [selectable, registerSelectionIcon, registerPanelSelectionIcon]);
|
|
47
120
|
React.useEffect(() => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
role: "menuitem",
|
|
61
|
-
"aria-disabled": disabled || void 0,
|
|
62
|
-
...getItemProps({
|
|
63
|
-
tabIndex: disabled ? void 0 : active ? 0 : -1,
|
|
64
|
-
onKeyDown(event) {
|
|
65
|
-
const element = event.currentTarget;
|
|
66
|
-
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
67
|
-
if ((event.key === " " || event.key === "Enter") && !triggersSubmenu && !disabled) {
|
|
68
|
-
event.preventDefault();
|
|
69
|
-
const { view, ...eventInit } = event;
|
|
70
|
-
queueMicrotask(() => {
|
|
71
|
-
element.dispatchEvent(
|
|
72
|
-
new window.MouseEvent("click", eventInit)
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
onClick(event) {
|
|
78
|
-
if (!disabled) {
|
|
79
|
-
onClick == null ? void 0 : onClick(event);
|
|
80
|
-
if (!triggersSubmenu) {
|
|
81
|
-
tree == null ? void 0 : tree.events.emit("click");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
onFocus(event) {
|
|
86
|
-
onFocus == null ? void 0 : onFocus(event);
|
|
87
|
-
setFocusInside(true);
|
|
88
|
-
},
|
|
89
|
-
...rest
|
|
90
|
-
}),
|
|
91
|
-
ref: handleRef,
|
|
92
|
-
children: [
|
|
93
|
-
children,
|
|
94
|
-
triggersSubmenu && /* @__PURE__ */ jsxRuntime.jsx(ExpandGroupIcon, { className: withBaseName("expandIcon"), "aria-hidden": true })
|
|
95
|
-
]
|
|
121
|
+
if (triggersSubmenu) {
|
|
122
|
+
setTriggerDisabled(!!disabled);
|
|
123
|
+
}
|
|
124
|
+
}, [disabled, setTriggerDisabled, triggersSubmenu]);
|
|
125
|
+
React.useEffect(() => {
|
|
126
|
+
if (process.env.NODE_ENV !== "production") {
|
|
127
|
+
if (insideSelectableGroup && value === void 0 && !missingValueWarningShown) {
|
|
128
|
+
missingValueWarningShown = true;
|
|
129
|
+
console.warn(
|
|
130
|
+
"Salt: MenuItem requires a `value` to be selectable inside a MenuGroup with `selectionVariant` set. It will behave as a regular menu item."
|
|
131
|
+
);
|
|
132
|
+
}
|
|
96
133
|
}
|
|
134
|
+
}, [insideSelectableGroup, value]);
|
|
135
|
+
const shouldCloseMenu = () => !selectable || activationKeyRef.current === "Enter";
|
|
136
|
+
let role = "menuitem";
|
|
137
|
+
if (selectable) {
|
|
138
|
+
role = selectionVariant === "single" ? "menuitemradio" : "menuitemcheckbox";
|
|
139
|
+
}
|
|
140
|
+
return (
|
|
141
|
+
// biome-ignore lint/a11y/useAriaPropsSupportedByRole: Biome can't detect the role provided by the role variable. aria-checked is only used when the role is appropriate.
|
|
142
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
143
|
+
"div",
|
|
144
|
+
{
|
|
145
|
+
className: clsx.clsx(
|
|
146
|
+
withBaseName(),
|
|
147
|
+
{
|
|
148
|
+
[withBaseName("blurActive")]: blurActive,
|
|
149
|
+
[withBaseName("selectionAlignedIcon")]: alignIconWithSelectionIcon
|
|
150
|
+
},
|
|
151
|
+
className
|
|
152
|
+
),
|
|
153
|
+
role,
|
|
154
|
+
"aria-checked": selectable ? selected : void 0,
|
|
155
|
+
"aria-disabled": disabled || void 0,
|
|
156
|
+
...getItemProps({
|
|
157
|
+
tabIndex: active ? 0 : -1,
|
|
158
|
+
onKeyDown(event) {
|
|
159
|
+
const element = event.currentTarget;
|
|
160
|
+
const { key } = event;
|
|
161
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
162
|
+
if ((key === " " || key === "Enter") && !triggersSubmenu) {
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
if (disabled || event.repeat) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const { view, ...eventInit } = event;
|
|
168
|
+
queueMicrotask(() => {
|
|
169
|
+
activationKeyRef.current = key;
|
|
170
|
+
element.dispatchEvent(
|
|
171
|
+
new window.MouseEvent("click", eventInit)
|
|
172
|
+
);
|
|
173
|
+
activationKeyRef.current = null;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
onClick(event) {
|
|
178
|
+
if (!disabled) {
|
|
179
|
+
onClick == null ? void 0 : onClick(event);
|
|
180
|
+
if (selectable) {
|
|
181
|
+
select(event, value);
|
|
182
|
+
}
|
|
183
|
+
if (!triggersSubmenu && shouldCloseMenu()) {
|
|
184
|
+
tree == null ? void 0 : tree.events.emit("click");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
onFocus(event) {
|
|
189
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
190
|
+
setFocusInside(true);
|
|
191
|
+
},
|
|
192
|
+
...rest
|
|
193
|
+
}),
|
|
194
|
+
ref: handleRef,
|
|
195
|
+
children: [
|
|
196
|
+
selectable && selectionVariant === "single" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
197
|
+
RadioButtonIcon.RadioButtonIcon,
|
|
198
|
+
{
|
|
199
|
+
checked: selected,
|
|
200
|
+
className: withBaseName("selectionIcon")
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
selectable && selectionVariant === "multiple" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
204
|
+
CheckboxIcon.CheckboxIcon,
|
|
205
|
+
{
|
|
206
|
+
checked: selected,
|
|
207
|
+
className: withBaseName("selectionIcon")
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
reserveSelectionIconSpace && !selectable && /* @__PURE__ */ jsxRuntime.jsx(
|
|
211
|
+
"span",
|
|
212
|
+
{
|
|
213
|
+
"aria-hidden": true,
|
|
214
|
+
className: withBaseName("selectionIconPlaceholder")
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
reserveIconSpace && !hasIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: withBaseName("iconPlaceholder") }),
|
|
218
|
+
children,
|
|
219
|
+
triggersSubmenu && /* @__PURE__ */ jsxRuntime.jsx(ExpandGroupIcon, { className: withBaseName("expandIcon"), "aria-hidden": true })
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
)
|
|
97
223
|
);
|
|
98
224
|
}
|
|
99
225
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuItem.js","sources":["../src/menu/MenuItem.tsx"],"sourcesContent":["import { useFloatingTree, useListItem } from \"@floating-ui/react\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n useEffect,\n} from \"react\";\nimport { useIcon } from \"../semantic-icon-provider\";\nimport { makePrefixer, useForkRef } from \"../utils\";\nimport { useMenuContext } from \"./MenuContext\";\nimport menuItemCss from \"./MenuItem.css\";\nimport { useMenuPanelContext } from \"./MenuPanelContext\";\nimport { useIsMenuTrigger } from \"./MenuTriggerContext\";\nexport interface MenuItemProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * If `true`, the item will be disabled.\n */\n disabled?: boolean;\n}\n\nconst withBaseName = makePrefixer(\"saltMenuItem\");\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps>(\n function MenuItem(props, ref) {\n const {\n children,\n className,\n disabled,\n onClick,\n onFocus,\n onKeyDown,\n ...rest\n } = props;\n\n const { triggersSubmenu, blurActive } = useIsMenuTrigger();\n const { setTriggerDisabled } = useMenuContext();\n const { ExpandGroupIcon } = useIcon();\n const { activeIndex, getItemProps, setFocusInside } = useMenuPanelContext();\n const item = useListItem();\n const tree = useFloatingTree();\n const active = item.index === activeIndex;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-menu-item\",\n css: menuItemCss,\n window: targetWindow,\n });\n const handleRef = useForkRef<HTMLDivElement>(ref, item.ref);\n\n useEffect(() => {\n setTriggerDisabled(!!disabled);\n }, [disabled, setTriggerDisabled]);\n\n return (\n <div\n className={clsx(\n withBaseName(),\n {\n [withBaseName(\"blurActive\")]: blurActive,\n },\n className,\n )}\n role=\"menuitem\"\n aria-disabled={disabled || undefined}\n {...getItemProps({\n tabIndex: disabled ? undefined : active ? 0 : -1,\n onKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const element = event.currentTarget;\n onKeyDown?.(event);\n if (\n (event.key === \" \" || event.key === \"Enter\") &&\n !triggersSubmenu &&\n !disabled\n ) {\n event.preventDefault();\n const { view, ...eventInit } = event;\n queueMicrotask(() => {\n element.dispatchEvent(\n new window.MouseEvent(\"click\", eventInit),\n );\n });\n }\n },\n onClick(event: MouseEvent<HTMLDivElement>) {\n if (!disabled) {\n onClick?.(event);\n if (!triggersSubmenu) {\n tree?.events.emit(\"click\");\n }\n }\n },\n onFocus(event: FocusEvent<HTMLDivElement>) {\n onFocus?.(event);\n setFocusInside(true);\n },\n ...rest,\n })}\n ref={handleRef}\n >\n {children}\n {triggersSubmenu && (\n <ExpandGroupIcon className={withBaseName(\"expandIcon\")} aria-hidden />\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","MenuItem","useIsMenuTrigger","useMenuContext","useIcon","useMenuPanelContext","useListItem","useFloatingTree","useWindow","useComponentCssInjection","menuItemCss","useForkRef","useEffect","jsxs","clsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MenuItem.js","sources":["../src/menu/MenuItem.tsx"],"sourcesContent":["import { useFloatingTree, useListItem } from \"@floating-ui/react\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type FocusEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { CheckboxIcon } from \"../checkbox\";\nimport { RadioButtonIcon } from \"../radio-button\";\nimport { useIcon } from \"../semantic-icon-provider\";\nimport { makePrefixer, useForkRef, useIsomorphicLayoutEffect } from \"../utils\";\nimport { useMenuAlignment } from \"./MenuAlignmentContext\";\nimport { useMenuContext } from \"./MenuContext\";\nimport { useMenuGroup } from \"./MenuGroupContext\";\nimport menuItemCss from \"./MenuItem.css\";\nimport { useMenuPanelContext } from \"./MenuPanelContext\";\nimport { useIsMenuTrigger } from \"./MenuTriggerContext\";\nexport interface MenuItemProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * If `true`, the item will be disabled.\n */\n disabled?: boolean;\n /**\n * The value of the item. Identifies the item inside a `MenuGroup` whose `selectionVariant` is \"single\" or \"multiple\".\n */\n value?: string;\n}\n\nconst withBaseName = makePrefixer(\"saltMenuItem\");\n\nconst leadingSlotClassNames = [\n withBaseName(\"selectionIcon\"),\n withBaseName(\"selectionIconPlaceholder\"),\n withBaseName(\"iconPlaceholder\"),\n];\n\nfunction hasLeadingIcon(item: HTMLElement | null) {\n for (const node of Array.from(item?.childNodes ?? [])) {\n if (node.nodeType === node.TEXT_NODE) {\n if (node.textContent?.trim()) {\n return false;\n }\n } else if (node.nodeType === node.ELEMENT_NODE) {\n const { classList } = node as Element;\n if (\n !leadingSlotClassNames.some((className) =>\n classList.contains(className),\n )\n ) {\n return classList.contains(\"saltIcon\");\n }\n }\n }\n return false;\n}\n\nlet missingValueWarningShown = false;\n\nexport const MenuItem = forwardRef<HTMLDivElement, MenuItemProps>(\n function MenuItem(props, ref) {\n const {\n children,\n className,\n disabled,\n onClick,\n onFocus,\n onKeyDown,\n value,\n ...rest\n } = props;\n\n const { triggersSubmenu, blurActive } = useIsMenuTrigger();\n const { setTriggerDisabled } = useMenuContext();\n const { ExpandGroupIcon } = useIcon();\n const {\n activeIndex,\n getItemProps,\n setFocusInside,\n hasSelectionIcon,\n registerPanelSelectionIcon,\n } = useMenuPanelContext();\n const {\n reserveIconSpace,\n reserveSelectionIconSpace,\n registerIcon,\n registerSelectionIcon,\n } = useMenuAlignment();\n const { isSelected, select, selectionVariant } = useMenuGroup();\n const item = useListItem();\n const tree = useFloatingTree();\n const active = item.index === activeIndex;\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-menu-item\",\n css: menuItemCss,\n window: targetWindow,\n });\n const itemRef = useRef<HTMLDivElement>(null);\n const listItemRef = useForkRef<HTMLDivElement>(item.ref, itemRef);\n const handleRef = useForkRef<HTMLDivElement>(ref, listItemRef);\n const activationKeyRef = useRef<string | null>(null);\n const [hasIcon, setHasIcon] = useState(false);\n\n const insideSelectableGroup =\n selectionVariant !== undefined && !triggersSubmenu;\n const selectable = insideSelectableGroup && value !== undefined;\n const selected = selectable && isSelected(value);\n // When icons lead this item and another group in the panel leads with a radio\n // or checkbox, widen the icon column to match so the labels still line up.\n const alignIconWithSelectionIcon =\n hasSelectionIcon &&\n !selectable &&\n !reserveSelectionIconSpace &&\n (hasIcon || reserveIconSpace);\n\n useIsomorphicLayoutEffect(() => {\n setHasIcon(hasLeadingIcon(itemRef.current));\n });\n\n useIsomorphicLayoutEffect(\n () => (hasIcon ? registerIcon() : undefined),\n [hasIcon, registerIcon],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!selectable) {\n return undefined;\n }\n const unregisterFromGroup = registerSelectionIcon();\n const unregisterFromPanel = registerPanelSelectionIcon();\n return () => {\n unregisterFromGroup();\n unregisterFromPanel();\n };\n }, [selectable, registerSelectionIcon, registerPanelSelectionIcon]);\n\n useEffect(() => {\n if (triggersSubmenu) {\n setTriggerDisabled(!!disabled);\n }\n }, [disabled, setTriggerDisabled, triggersSubmenu]);\n\n useEffect(() => {\n if (process.env.NODE_ENV !== \"production\") {\n if (\n insideSelectableGroup &&\n value === undefined &&\n !missingValueWarningShown\n ) {\n missingValueWarningShown = true;\n console.warn(\n \"Salt: MenuItem requires a `value` to be selectable inside a MenuGroup with `selectionVariant` set. It will behave as a regular menu item.\",\n );\n }\n }\n }, [insideSelectableGroup, value]);\n\n const shouldCloseMenu = () =>\n !selectable || activationKeyRef.current === \"Enter\";\n\n let role = \"menuitem\";\n if (selectable) {\n role =\n selectionVariant === \"single\" ? \"menuitemradio\" : \"menuitemcheckbox\";\n }\n\n return (\n // biome-ignore lint/a11y/useAriaPropsSupportedByRole: Biome can't detect the role provided by the role variable. aria-checked is only used when the role is appropriate.\n <div\n className={clsx(\n withBaseName(),\n {\n [withBaseName(\"blurActive\")]: blurActive,\n [withBaseName(\"selectionAlignedIcon\")]: alignIconWithSelectionIcon,\n },\n className,\n )}\n role={role}\n aria-checked={selectable ? selected : undefined}\n aria-disabled={disabled || undefined}\n {...getItemProps({\n tabIndex: active ? 0 : -1,\n onKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const element = event.currentTarget;\n const { key } = event;\n onKeyDown?.(event);\n if ((key === \" \" || key === \"Enter\") && !triggersSubmenu) {\n event.preventDefault();\n if (disabled || event.repeat) {\n return;\n }\n const { view, ...eventInit } = event;\n queueMicrotask(() => {\n activationKeyRef.current = key;\n element.dispatchEvent(\n new window.MouseEvent(\"click\", eventInit),\n );\n activationKeyRef.current = null;\n });\n }\n },\n onClick(event: MouseEvent<HTMLDivElement>) {\n if (!disabled) {\n onClick?.(event);\n if (selectable) {\n select(event, value);\n }\n if (!triggersSubmenu && shouldCloseMenu()) {\n tree?.events.emit(\"click\");\n }\n }\n },\n onFocus(event: FocusEvent<HTMLDivElement>) {\n onFocus?.(event);\n setFocusInside(true);\n },\n ...rest,\n })}\n ref={handleRef}\n >\n {selectable && selectionVariant === \"single\" && (\n <RadioButtonIcon\n checked={selected}\n className={withBaseName(\"selectionIcon\")}\n />\n )}\n {selectable && selectionVariant === \"multiple\" && (\n <CheckboxIcon\n checked={selected}\n className={withBaseName(\"selectionIcon\")}\n />\n )}\n {reserveSelectionIconSpace && !selectable && (\n <span\n aria-hidden\n className={withBaseName(\"selectionIconPlaceholder\")}\n />\n )}\n {reserveIconSpace && !hasIcon && (\n <span aria-hidden className={withBaseName(\"iconPlaceholder\")} />\n )}\n {children}\n {triggersSubmenu && (\n <ExpandGroupIcon className={withBaseName(\"expandIcon\")} aria-hidden />\n )}\n </div>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","MenuItem","useIsMenuTrigger","useMenuContext","useIcon","useMenuPanelContext","useMenuAlignment","useMenuGroup","useListItem","useFloatingTree","useWindow","useComponentCssInjection","menuItemCss","useRef","useForkRef","useState","useIsomorphicLayoutEffect","useEffect","jsxs","clsx","jsx","RadioButtonIcon","CheckboxIcon"],"mappings":"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"}
|