@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.
Files changed (93) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/css/salt-core.css +269 -28
  3. package/dist-cjs/drawer/Drawer.css.js +1 -1
  4. package/dist-cjs/drawer/Drawer.js +54 -6
  5. package/dist-cjs/drawer/Drawer.js.map +1 -1
  6. package/dist-cjs/drawer/DrawerContext.js +2 -0
  7. package/dist-cjs/drawer/DrawerContext.js.map +1 -1
  8. package/dist-cjs/drawer/DrawerFooter.css.js +1 -1
  9. package/dist-cjs/drawer/DrawerHeader.css.js +1 -1
  10. package/dist-cjs/drawer/DrawerHeader.js +6 -3
  11. package/dist-cjs/drawer/DrawerHeader.js.map +1 -1
  12. package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js +6 -0
  13. package/dist-cjs/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
  14. package/dist-cjs/drawer/internal/DrawerResizeGuide.js +44 -0
  15. package/dist-cjs/drawer/internal/DrawerResizeGuide.js.map +1 -0
  16. package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js +6 -0
  17. package/dist-cjs/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
  18. package/dist-cjs/drawer/internal/DrawerResizeHandle.js +43 -0
  19. package/dist-cjs/drawer/internal/DrawerResizeHandle.js.map +1 -0
  20. package/dist-cjs/drawer/internal/useDrawerResize.js +519 -0
  21. package/dist-cjs/drawer/internal/useDrawerResize.js.map +1 -0
  22. package/dist-cjs/link-button/LinkButton.css.js +1 -1
  23. package/dist-cjs/menu/MenuAlignmentContext.js +55 -0
  24. package/dist-cjs/menu/MenuAlignmentContext.js.map +1 -0
  25. package/dist-cjs/menu/MenuBase.js +9 -3
  26. package/dist-cjs/menu/MenuBase.js.map +1 -1
  27. package/dist-cjs/menu/MenuGroup.js +42 -3
  28. package/dist-cjs/menu/MenuGroup.js.map +1 -1
  29. package/dist-cjs/menu/MenuGroupContext.js +27 -0
  30. package/dist-cjs/menu/MenuGroupContext.js.map +1 -0
  31. package/dist-cjs/menu/MenuItem.css.js +1 -1
  32. package/dist-cjs/menu/MenuItem.js +176 -50
  33. package/dist-cjs/menu/MenuItem.js.map +1 -1
  34. package/dist-cjs/menu/MenuPanel.js +12 -3
  35. package/dist-cjs/menu/MenuPanel.js.map +1 -1
  36. package/dist-cjs/menu/MenuPanelContext.js +3 -1
  37. package/dist-cjs/menu/MenuPanelContext.js.map +1 -1
  38. package/dist-cjs/toggle-button/ToggleButton.css.js +1 -1
  39. package/dist-cjs/tree/TreeNodeTrigger.css.js +1 -1
  40. package/dist-cjs/tree/TreeNodeTrigger.js +0 -1
  41. package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -1
  42. package/dist-es/drawer/Drawer.css.js +1 -1
  43. package/dist-es/drawer/Drawer.js +54 -6
  44. package/dist-es/drawer/Drawer.js.map +1 -1
  45. package/dist-es/drawer/DrawerContext.js +2 -0
  46. package/dist-es/drawer/DrawerContext.js.map +1 -1
  47. package/dist-es/drawer/DrawerFooter.css.js +1 -1
  48. package/dist-es/drawer/DrawerHeader.css.js +1 -1
  49. package/dist-es/drawer/DrawerHeader.js +6 -3
  50. package/dist-es/drawer/DrawerHeader.js.map +1 -1
  51. package/dist-es/drawer/internal/DrawerResizeGuide.css.js +4 -0
  52. package/dist-es/drawer/internal/DrawerResizeGuide.css.js.map +1 -0
  53. package/dist-es/drawer/internal/DrawerResizeGuide.js +42 -0
  54. package/dist-es/drawer/internal/DrawerResizeGuide.js.map +1 -0
  55. package/dist-es/drawer/internal/DrawerResizeHandle.css.js +4 -0
  56. package/dist-es/drawer/internal/DrawerResizeHandle.css.js.map +1 -0
  57. package/dist-es/drawer/internal/DrawerResizeHandle.js +41 -0
  58. package/dist-es/drawer/internal/DrawerResizeHandle.js.map +1 -0
  59. package/dist-es/drawer/internal/useDrawerResize.js +517 -0
  60. package/dist-es/drawer/internal/useDrawerResize.js.map +1 -0
  61. package/dist-es/link-button/LinkButton.css.js +1 -1
  62. package/dist-es/menu/MenuAlignmentContext.js +50 -0
  63. package/dist-es/menu/MenuAlignmentContext.js.map +1 -0
  64. package/dist-es/menu/MenuBase.js +9 -3
  65. package/dist-es/menu/MenuBase.js.map +1 -1
  66. package/dist-es/menu/MenuGroup.js +44 -5
  67. package/dist-es/menu/MenuGroup.js.map +1 -1
  68. package/dist-es/menu/MenuGroupContext.js +23 -0
  69. package/dist-es/menu/MenuGroupContext.js.map +1 -0
  70. package/dist-es/menu/MenuItem.css.js +1 -1
  71. package/dist-es/menu/MenuItem.js +177 -51
  72. package/dist-es/menu/MenuItem.js.map +1 -1
  73. package/dist-es/menu/MenuPanel.js +12 -3
  74. package/dist-es/menu/MenuPanel.js.map +1 -1
  75. package/dist-es/menu/MenuPanelContext.js +3 -1
  76. package/dist-es/menu/MenuPanelContext.js.map +1 -1
  77. package/dist-es/toggle-button/ToggleButton.css.js +1 -1
  78. package/dist-es/tree/TreeNodeTrigger.css.js +1 -1
  79. package/dist-es/tree/TreeNodeTrigger.js +0 -1
  80. package/dist-es/tree/TreeNodeTrigger.js.map +1 -1
  81. package/dist-types/drawer/Drawer.d.ts +6 -0
  82. package/dist-types/drawer/DrawerContext.d.ts +3 -0
  83. package/dist-types/drawer/DrawerHeader.d.ts +1 -1
  84. package/dist-types/drawer/internal/DrawerResizeGuide.d.ts +7 -0
  85. package/dist-types/drawer/internal/DrawerResizeHandle.d.ts +8 -0
  86. package/dist-types/drawer/internal/index.d.ts +3 -0
  87. package/dist-types/drawer/internal/useDrawerResize.d.ts +34 -0
  88. package/dist-types/menu/MenuAlignmentContext.d.ts +14 -0
  89. package/dist-types/menu/MenuGroup.d.ts +26 -4
  90. package/dist-types/menu/MenuGroupContext.d.ts +10 -0
  91. package/dist-types/menu/MenuItem.d.ts +4 -0
  92. package/dist-types/menu/MenuPanelContext.d.ts +2 -0
  93. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDrawerResize.js","sources":["../src/drawer/internal/useDrawerResize.ts"],"sourcesContent":["import { useWindow } from \"@salt-ds/window\";\nimport type {\n AriaAttributes,\n CSSProperties,\n KeyboardEvent as ReactKeyboardEvent,\n MouseEvent as ReactMouseEvent,\n PointerEvent as ReactPointerEvent,\n} from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useEventCallback, useIsomorphicLayoutEffect } from \"../../utils\";\nimport type { DrawerProps } from \"../Drawer\";\n\ntype DrawerPosition = NonNullable<DrawerProps[\"position\"]>;\n\ninterface Bounds {\n min: number;\n max: number;\n}\n\ninterface DragState extends Bounds {\n pointerId: number;\n startX: number;\n startY: number;\n originSize: number;\n previousSize: number;\n cancelSize: number | undefined;\n moved: boolean;\n}\n\n/** Click-to-place resizing */\ninterface PlacingState extends Bounds {\n /** In viewport coordinates. */\n guideOffset: number;\n /** The placing press started on the guide layer. */\n pressed: boolean;\n}\n\ntype Interaction = \"inactive\" | \"hover\" | \"active\" | \"placing\";\n\nexport interface SeparatorProps\n extends Pick<\n AriaAttributes,\n \"aria-orientation\" | \"aria-valuenow\" | \"aria-valuemin\" | \"aria-valuemax\"\n > {\n role: \"separator\";\n tabIndex: number;\n ref: (element: HTMLElement | null) => void;\n onKeyDown: (event: ReactKeyboardEvent<HTMLElement>) => void;\n onFocus: () => void;\n}\n\nexport interface GuideProps {\n ref: (element: HTMLElement | null) => void;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n onPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n onClick: (event: ReactMouseEvent<HTMLElement>) => void;\n onContextMenu: () => void;\n}\n\nexport interface UseDrawerResizeProps {\n enabled: boolean;\n position: DrawerPosition;\n element: HTMLElement | null | undefined;\n}\n\nexport interface UseDrawerResizeResult {\n sizeStyle: CSSProperties | undefined;\n isResizing: boolean;\n isHovered: boolean;\n isPlacing: boolean;\n /** Whether the event is the Escape that cancelled a resize, so it shouldn't close the drawer. */\n isCancelResizeEvent: (event?: Event) => boolean;\n separatorProps: SeparatorProps;\n guideProps: GuideProps;\n}\n\nconst KEYBOARD_STEP = 8;\nconst PROBE_SIZE = 1e6;\n// A press that moves less than this is a click on the handle, not a drag.\nconst CLICK_THRESHOLD = 4;\n\nconst isElement = (target: EventTarget | null): target is Element =>\n target !== null && (target as Node).nodeType === 1;\n\nconst focusWithoutRing = (element: HTMLElement | null) =>\n element?.focus({\n preventScroll: true,\n focusVisible: false,\n } as FocusOptions);\n\n/** Shows the cursor everywhere in the document, over any element's own cursor. */\nconst setDocumentCursor = (ownerDocument: Document, cursor: string) => {\n const view = ownerDocument.defaultView as (Window & typeof globalThis) | null;\n if (!view || !ownerDocument.adoptedStyleSheets) return undefined;\n const sheet = new view.CSSStyleSheet();\n sheet.replaceSync(`*, *:hover { cursor: ${cursor} !important; }`);\n ownerDocument.adoptedStyleSheets = [\n ...ownerDocument.adoptedStyleSheets,\n sheet,\n ];\n return () => {\n ownerDocument.adoptedStyleSheets = ownerDocument.adoptedStyleSheets.filter(\n (adopted) => adopted !== sheet,\n );\n };\n};\n\nconst isHorizontal = (position: DrawerPosition) =>\n position === \"left\" || position === \"right\";\n\nconst growsWithCoordinate = (position: DrawerPosition) =>\n position === \"left\" || position === \"top\";\n\nconst measure = (element: HTMLElement, horizontal: boolean) => {\n const { width, height } = element.getBoundingClientRect();\n return horizontal ? width : height;\n};\n\nconst restoreStyle = (\n style: CSSStyleDeclaration,\n property: string,\n value: string,\n priority: string,\n) => {\n if (value) {\n style.setProperty(property, value, priority);\n } else {\n style.removeProperty(property);\n }\n};\n\n/** Resolves the drawer's CSS min/max size by briefly forcing it to both extremes. */\nconst probeBounds = (element: HTMLElement, horizontal: boolean): Bounds => {\n const property = horizontal ? \"width\" : \"height\";\n const { style } = element;\n const previousValue = style.getPropertyValue(property);\n const previousPriority = style.getPropertyPriority(property);\n const previousTransition = style.getPropertyValue(\"transition-property\");\n const previousTransitionPriority = style.getPropertyPriority(\n \"transition-property\",\n );\n\n // A transition would report the current size at both extremes.\n style.setProperty(\"transition-property\", \"none\", \"important\");\n style.setProperty(property, \"0px\", \"important\");\n const min = measure(element, horizontal);\n style.setProperty(property, `${PROBE_SIZE}px`, \"important\");\n const max = measure(element, horizontal);\n\n restoreStyle(style, property, previousValue, previousPriority);\n // Applies the restored size before transitions return, so it doesn't animate.\n measure(element, horizontal);\n restoreStyle(\n style,\n \"transition-property\",\n previousTransition,\n previousTransitionPriority,\n );\n\n return { min, max: Math.max(min, max) };\n};\n\nconst clamp = (value: number, { min, max }: Bounds) =>\n Math.min(Math.max(value, min), max);\n\n/** Size the drawer needs for its moving edge to sit at the given point. */\nconst sizeFromPoint = (\n rect: DOMRect,\n position: DrawerPosition,\n { clientX: x, clientY: y }: Pick<MouseEvent, \"clientX\" | \"clientY\">,\n) => {\n switch (position) {\n case \"left\":\n return x - rect.left;\n case \"right\":\n return rect.right - x;\n case \"top\":\n return y - rect.top;\n case \"bottom\":\n return rect.bottom - y;\n }\n};\n\n/** Viewport coordinate of the moving edge for a given size. */\nconst edgeFromSize = (\n rect: DOMRect,\n position: DrawerPosition,\n size: number,\n) => {\n switch (position) {\n case \"left\":\n return rect.left + size;\n case \"right\":\n return rect.right - size;\n case \"top\":\n return rect.top + size;\n case \"bottom\":\n return rect.bottom - size;\n }\n};\n\nexport function useDrawerResize({\n enabled,\n position,\n element,\n}: UseDrawerResizeProps): UseDrawerResizeResult {\n const horizontal = isHorizontal(position);\n const targetWindow = useWindow();\n\n // Unset until the user resizes, so the drawer keeps its CSS size.\n const [sizeState, setSizeState] = useState<number | undefined>(undefined);\n // Drop the size when `position` switches axis.\n const [sizeAxisHorizontal, setSizeAxisHorizontal] = useState(horizontal);\n const size =\n enabled && sizeAxisHorizontal === horizontal ? sizeState : undefined;\n\n const [interaction, setInteraction] = useState<Interaction>(\"inactive\");\n const [metrics, setMetrics] = useState<(Bounds & { current: number }) | null>(\n null,\n );\n const dragRef = useRef<DragState | null>(null);\n const placingRef = useRef<PlacingState | null>(null);\n const handleRef = useRef<HTMLElement | null>(null);\n const guideRef = useRef<HTMLElement | null>(null);\n const cancelResizeEventRef = useRef<Event | null>(null);\n const restoreSizeRef = useRef<number | null>(null);\n const initialSizeRef = useRef<number | null>(null);\n const axisRef = useRef(horizontal);\n\n // Probing forces layout, so key presses reuse the last bounds.\n const boundsRef = useRef<Bounds | null>(null);\n\n const readMetrics = useEventCallback((reuseBounds = false) => {\n if (!element) return null;\n const bounds =\n reuseBounds && boundsRef.current\n ? boundsRef.current\n : probeBounds(element, horizontal);\n boundsRef.current = bounds;\n const current = clamp(measure(element, horizontal), bounds);\n const next = { ...bounds, current };\n setMetrics(next);\n return next;\n });\n\n const applySize = (nextSize: number) => {\n setSizeState(nextSize);\n setSizeAxisHorizontal(horizontal);\n };\n\n const isOverHandle = ({\n clientX: x,\n clientY: y,\n }: Pick<MouseEvent, \"clientX\" | \"clientY\">) => {\n const rect = handleRef.current?.getBoundingClientRect();\n return (\n rect !== undefined &&\n x >= rect.left &&\n x <= rect.right &&\n y >= rect.top &&\n y <= rect.bottom\n );\n };\n\n const isHandle = useEventCallback(\n (target: EventTarget | null) =>\n enabled &&\n isElement(target) &&\n handleRef.current?.contains(target) === true,\n );\n\n const startDrag = useEventCallback((event: PointerEvent) => {\n const current = readMetrics();\n if (!current) return;\n\n event.preventDefault();\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n originSize: current.current,\n previousSize: current.current,\n cancelSize: size,\n min: current.min,\n max: current.max,\n moved: false,\n };\n focusWithoutRing(handleRef.current);\n setInteraction(\"active\");\n });\n\n const moveDrag = useEventCallback((event: PointerEvent, drag: DragState) => {\n // Small movement keeps the press a click, so it can start placing the edge by click.\n if (!drag.moved) {\n if (\n Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) <\n CLICK_THRESHOLD\n ) {\n return;\n }\n drag.moved = true;\n try {\n handleRef.current?.setPointerCapture(event.pointerId);\n } catch {\n // The pointer is no longer active.\n }\n }\n\n const coordinate = horizontal ? event.clientX : event.clientY;\n const origin = horizontal ? drag.startX : drag.startY;\n const direction = growsWithCoordinate(position) ? 1 : -1;\n const nextSize = clamp(\n drag.originSize + (coordinate - origin) * direction,\n drag,\n );\n if (nextSize !== drag.previousSize) {\n drag.previousSize = nextSize;\n applySize(nextSize);\n }\n });\n\n // Set directly, to avoid a re-render on every pointer move.\n const moveGuide = (offset: number) => {\n const placing = placingRef.current;\n if (!placing) return;\n placing.guideOffset = offset;\n guideRef.current?.style.setProperty(\n \"--drawerResizeGuide-offset\",\n `${offset}px`,\n );\n };\n\n const setGuide = useCallback((node: HTMLElement | null) => {\n guideRef.current = node;\n const placing = placingRef.current;\n if (node && placing) {\n node.style.setProperty(\n \"--drawerResizeGuide-offset\",\n `${placing.guideOffset}px`,\n );\n }\n }, []);\n\n const startPlacing = useEventCallback((drag: DragState) => {\n if (!element) return;\n placingRef.current = {\n min: drag.min,\n max: drag.max,\n guideOffset: edgeFromSize(\n element.getBoundingClientRect(),\n position,\n drag.originSize,\n ),\n pressed: false,\n };\n setInteraction(\"placing\");\n });\n\n const stopPlacing = useEventCallback(() => {\n if (!placingRef.current) return;\n placingRef.current = null;\n setInteraction(\"inactive\");\n });\n\n const endDrag = useEventCallback((event: Event) => {\n const drag = dragRef.current;\n if (!drag) return;\n dragRef.current = null;\n // Pointer capture retargets the release to the handle.\n const pointer = event as PointerEvent;\n const stillHovered =\n \"pointerType\" in event &&\n pointer.pointerType !== \"touch\" &&\n isHandle(\n handleRef.current?.ownerDocument.elementFromPoint(\n pointer.clientX,\n pointer.clientY,\n ) ?? null,\n );\n setInteraction(stillHovered ? \"hover\" : \"inactive\");\n });\n\n const cancelDrag = useEventCallback((event: KeyboardEvent) => {\n const drag = dragRef.current;\n if (!drag) return;\n const handle = handleRef.current;\n if (handle?.hasPointerCapture(drag.pointerId)) {\n handle.releasePointerCapture(drag.pointerId);\n }\n setSizeState(drag.cancelSize);\n endDrag(event);\n });\n\n const sizeToPlace = (\n target: HTMLElement,\n rect: DOMRect,\n point: Pick<MouseEvent, \"clientX\" | \"clientY\">,\n bounds: Bounds,\n ) =>\n clamp(\n isOverHandle(point)\n ? measure(target, horizontal)\n : sizeFromPoint(rect, position, point),\n bounds,\n );\n\n const moveGuideToPointer = (\n event: Pick<MouseEvent, \"clientX\" | \"clientY\">,\n ) => {\n const placing = placingRef.current;\n if (!placing || !element) return;\n const rect = element.getBoundingClientRect();\n moveGuide(\n edgeFromSize(rect, position, sizeToPlace(element, rect, event, placing)),\n );\n };\n\n const onGuidePointerDown = useEventCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n const placing = placingRef.current;\n if (!placing) return;\n if (event.pointerType === \"mouse\" && event.button > 0) {\n stopPlacing();\n return;\n }\n // Keeps focus on the handle.\n event.preventDefault();\n // React bubbles events from the portal up to the drawer.\n event.stopPropagation();\n placing.pressed = true;\n moveGuideToPointer(event);\n },\n );\n\n const onGuidePointerMove = useEventCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n moveGuideToPointer(event);\n },\n );\n\n const onGuideClick = useEventCallback(\n (event: ReactMouseEvent<HTMLElement>) => {\n const placing = placingRef.current;\n // Ignores the click that started placing.\n if (!placing?.pressed || !element) return;\n event.stopPropagation();\n stopPlacing();\n // The drawer may have moved since placing started, e.g. while sliding in.\n const rect = element.getBoundingClientRect();\n const nextSize = sizeToPlace(element, rect, event, placing);\n const current = clamp(measure(element, horizontal), placing);\n if (nextSize !== current) {\n applySize(nextSize);\n }\n focusWithoutRing(handleRef.current);\n },\n );\n\n useEffect(() => {\n if (!enabled || !element || !targetWindow) return;\n const ownerDocument = targetWindow.document;\n\n const onPointerDown = (event: PointerEvent) => {\n if (event.defaultPrevented || !event.isPrimary) return;\n if (event.pointerType === \"mouse\" && event.button > 0) return;\n if (placingRef.current || dragRef.current || !isHandle(event.target)) {\n return;\n }\n startDrag(event);\n };\n\n const onPointerMove = (event: PointerEvent) => {\n if (event.defaultPrevented) return;\n if (placingRef.current) return;\n const drag = dragRef.current;\n if (!drag) {\n // Touch has no hover, so it would leave the hover state behind.\n if (event.pointerType !== \"touch\") {\n setInteraction(isHandle(event.target) ? \"hover\" : \"inactive\");\n }\n return;\n }\n if (event.pointerId !== drag.pointerId) return;\n // No buttons pressed means the release was missed, e.g. over an iframe.\n if (event.buttons === 0) {\n endDrag(event);\n return;\n }\n moveDrag(event, drag);\n };\n\n const onPointerUp = (event: PointerEvent) => {\n if (event.defaultPrevented) return;\n if (event.pointerType === \"mouse\" && event.button > 0) return;\n const drag = dragRef.current;\n if (drag?.pointerId !== event.pointerId) return;\n event.preventDefault();\n if (!drag.moved) {\n dragRef.current = null;\n startPlacing(drag);\n return;\n }\n endDrag(event);\n };\n\n const onPointerCancel = (event: PointerEvent) => {\n if (dragRef.current?.pointerId === event.pointerId) endDrag(event);\n };\n\n const onContextMenu = (event: MouseEvent) => {\n if (!event.defaultPrevented) endDrag(event);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || !dragRef.current) return;\n event.preventDefault();\n cancelResizeEventRef.current = event;\n cancelDrag(event);\n };\n\n const onBlur = (event: FocusEvent) => {\n endDrag(event);\n stopPlacing();\n };\n\n // \"pointerout\" doesn't fire when the pointer moves into an iframe, so hover would stick.\n const onPointerOut = (event: PointerEvent) => {\n if (\n !dragRef.current &&\n isElement(event.relatedTarget) &&\n event.relatedTarget.tagName === \"IFRAME\"\n ) {\n setInteraction(\"inactive\");\n }\n };\n\n ownerDocument.addEventListener(\"pointerdown\", onPointerDown, true);\n ownerDocument.addEventListener(\"pointermove\", onPointerMove);\n ownerDocument.addEventListener(\"pointerup\", onPointerUp, true);\n ownerDocument.addEventListener(\"pointercancel\", onPointerCancel);\n ownerDocument.addEventListener(\"contextmenu\", onContextMenu, true);\n // Capture, to run before the drawer closes on Escape.\n ownerDocument.addEventListener(\"keydown\", onKeyDown, true);\n ownerDocument.addEventListener(\"pointerout\", onPointerOut);\n targetWindow.addEventListener(\"blur\", onBlur);\n return () => {\n ownerDocument.removeEventListener(\"pointerdown\", onPointerDown, true);\n ownerDocument.removeEventListener(\"pointermove\", onPointerMove);\n ownerDocument.removeEventListener(\"pointerup\", onPointerUp, true);\n ownerDocument.removeEventListener(\"pointercancel\", onPointerCancel);\n ownerDocument.removeEventListener(\"contextmenu\", onContextMenu, true);\n ownerDocument.removeEventListener(\"keydown\", onKeyDown, true);\n ownerDocument.removeEventListener(\"pointerout\", onPointerOut);\n targetWindow.removeEventListener(\"blur\", onBlur);\n dragRef.current = null;\n placingRef.current = null;\n setInteraction(\"inactive\");\n };\n }, [\n enabled,\n element,\n targetWindow,\n isHandle,\n startDrag,\n moveDrag,\n endDrag,\n cancelDrag,\n startPlacing,\n stopPlacing,\n ]);\n\n const showResizeCursor = interaction !== \"inactive\";\n useEffect(() => {\n if (!showResizeCursor || !targetWindow) return;\n return setDocumentCursor(\n targetWindow.document,\n horizontal\n ? \"var(--salt-cursor-drag-ew, ew-resize)\"\n : \"var(--salt-cursor-drag-ns, ns-resize)\",\n );\n }, [showResizeCursor, targetWindow, horizontal]);\n\n const onKeyDown = useEventCallback(\n (event: ReactKeyboardEvent<HTMLElement>) => {\n const { key } = event;\n if (placingRef.current) {\n stopPlacing();\n if (key === \"Escape\") {\n event.preventDefault();\n cancelResizeEventRef.current = event.nativeEvent;\n return;\n }\n }\n const resizeKeys = horizontal\n ? [\"ArrowLeft\", \"ArrowRight\"]\n : [\"ArrowUp\", \"ArrowDown\"];\n if (\n !resizeKeys.includes(key) &&\n key !== \"Home\" &&\n key !== \"End\" &&\n key !== \"Enter\"\n ) {\n return;\n }\n\n const current = readMetrics(true);\n if (!current) return;\n\n event.preventDefault();\n\n const collapsed = current.current <= current.min + 1;\n let nextSize: number;\n if (key === \"Home\") {\n if (!collapsed) {\n restoreSizeRef.current = current.current;\n }\n nextSize = current.min;\n } else if (key === \"End\") {\n nextSize = current.max;\n } else if (key === \"Enter\") {\n if (collapsed) {\n nextSize =\n restoreSizeRef.current ?? initialSizeRef.current ?? current.max;\n } else {\n restoreSizeRef.current = current.current;\n nextSize = current.min;\n }\n } else {\n const towardsHigherCoordinate =\n key === \"ArrowRight\" || key === \"ArrowDown\";\n const direction =\n towardsHigherCoordinate === growsWithCoordinate(position) ? 1 : -1;\n nextSize = current.current + KEYBOARD_STEP * direction;\n }\n\n nextSize = clamp(nextSize, current);\n if (nextSize === current.current) return;\n applySize(nextSize);\n },\n );\n\n const isCancelResizeEvent = useCallback(\n (event?: Event) =>\n event !== undefined && event === cancelResizeEventRef.current,\n [],\n );\n\n const onFocus = useCallback(() => {\n if (!dragRef.current) readMetrics();\n }, [readMetrics]);\n\n const setHandle = useCallback((node: HTMLElement | null) => {\n handleRef.current = node;\n }, []);\n\n useEffect(() => {\n if (!enabled) {\n setSizeState(undefined);\n setMetrics(null);\n restoreSizeRef.current = null;\n initialSizeRef.current = null;\n }\n }, [enabled]);\n\n useIsomorphicLayoutEffect(() => {\n if (!enabled || !element) return;\n if (axisRef.current !== horizontal) {\n axisRef.current = horizontal;\n restoreSizeRef.current = null;\n initialSizeRef.current = null;\n }\n const next = readMetrics();\n if (next && initialSizeRef.current === null) {\n initialSizeRef.current = next.current;\n }\n }, [enabled, element, horizontal, readMetrics]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: re-syncs the separator's aria values whenever the size changes.\n useIsomorphicLayoutEffect(() => {\n if (!enabled || !element) return;\n readMetrics(true);\n }, [enabled, element, size, readMetrics]);\n\n useEffect(() => {\n if (!enabled || !element || !targetWindow) return;\n const onResize = () => {\n // The size limits stored for placing are stale after the window resizes.\n stopPlacing();\n readMetrics();\n };\n targetWindow.addEventListener(\"resize\", onResize);\n return () => targetWindow.removeEventListener(\"resize\", onResize);\n }, [enabled, element, targetWindow, readMetrics, stopPlacing]);\n\n return {\n sizeStyle:\n size !== undefined\n ? { [horizontal ? \"width\" : \"height\"]: size }\n : undefined,\n isResizing: interaction === \"active\" || interaction === \"placing\",\n isHovered: interaction === \"hover\",\n isPlacing: interaction === \"placing\",\n isCancelResizeEvent,\n separatorProps: {\n role: \"separator\",\n tabIndex: 0,\n ref: setHandle,\n \"aria-orientation\": horizontal ? \"vertical\" : \"horizontal\",\n \"aria-valuenow\": metrics ? Math.round(metrics.current) : undefined,\n \"aria-valuemin\": metrics ? Math.round(metrics.min) : undefined,\n \"aria-valuemax\": metrics ? Math.round(metrics.max) : undefined,\n onKeyDown,\n onFocus,\n },\n guideProps: {\n ref: setGuide,\n onPointerDown: onGuidePointerDown,\n onPointerMove: onGuidePointerMove,\n onClick: onGuideClick,\n onContextMenu: stopPlacing,\n },\n };\n}\n"],"names":["onKeyDown"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var css_248z = ".saltLinkButton {\n --linkButton-borderWidth: var(--salt-size-fixed-100);\n\n align-items: var(--saltLinkButton-alignItems, center);\n appearance: none;\n background: var(--saltLinkButton-background, var(--linkButton-background));\n border-color: var(--saltLinkButton-borderColor, var(--linkButton-borderColor, transparent));\n border-style: var(--saltLinkButton-borderStyle, solid);\n border-width: var(--saltLinkButton-borderWidth, var(--linkButton-borderWidth));\n border-radius: var(--saltLinkButton-borderRadius, var(--salt-palette-corner-weak, 0));\n color: var(--saltLinkButton-text-color, var(--linkButton-text-color));\n display: inline-flex;\n gap: var(--salt-spacing-50);\n justify-content: var(--saltLinkButton-justifyContent, center);\n font-size: var(--saltLinkButton-fontSize, var(--salt-text-fontSize));\n font-family: var(--saltLinkButton-fontFamily, var(--salt-text-action-fontFamily));\n line-height: var(--saltLinkButton-lineHeight, var(--salt-text-lineHeight));\n letter-spacing: var(--saltLinkButton-letterSpacing, var(--salt-text-action-letterSpacing));\n text-transform: var(--saltLinkButton-textTransform, var(--salt-text-action-textTransform));\n padding: 0 var(--saltLinkButton-padding, calc(var(--salt-spacing-100) - var(--saltLinkButton-borderWidth, var(--linkButton-borderWidth))));\n margin: var(--saltLinkButton-margin, 0);\n height: var(--saltLinkButton-height, var(--salt-size-base));\n min-width: var(--saltLinkButton-minWidth, unset);\n position: relative;\n text-align: var(--saltLinkButton-textAlign, var(--salt-text-action-textAlign));\n text-decoration: var(--linkButton-textDecoration, var(--salt-typography-textDecoration-underline));\n text-underline-offset: var(--salt-spacing-fixed-200);\n transition: none;\n width: var(--saltLinkButton-width, auto);\n -webkit-appearance: none;\n -webkit-tap-highlight-color: transparent;\n /* Styles applied to align children*/\n font-weight: var(--saltLinkButton-fontWeight, var(--salt-text-action-fontWeight));\n}\n\n.saltLinkButton-underlineDefault {\n --linkButton-textDecoration: var(--salt-typography-textDecoration-underline);\n --linkButton-textDecoration-hover: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-focus: var(--linkButton-textDecoration-hover);\n}\n\n.saltLinkButton-underlineNever {\n --linkButton-textDecoration: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-hover: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-focus: var(--salt-typography-textDecoration-none);\n}\n\n/* Class for ADA content - visually hidden but accessible to screen readers.\n Uses clip-path and prevents user selection so the text isn't included\n when users copy the link button's visible content. */\n.saltLinkButton-externalLinkADA {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n user-select: none;\n -webkit-user-select: none;\n}\n\n@media (hover: hover) {\n /* Pseudo-class applied to the root element on hover when LinkButton is not active or disabled */\n .saltLinkButton:hover {\n background: var(--saltLinkButton-background-hover, var(--linkButton-background-hover));\n color: var(--saltLinkButton-text-color-hover, var(--linkButton-text-color-hover));\n border-color: var(--saltLinkButton-borderColor-hover, var(--linkButton-borderColor-hover));\n cursor: var(--salt-cursor-hover);\n text-decoration: var(--linkButton-textDecoration-hover, var(--salt-typography-textDecoration-none));\n }\n}\n\n/* Pseudo-class applied to the root element on focus */\n.saltLinkButton:focus-visible {\n outline: var(--salt-focused-outline);\n\n background: var(--saltLinkButton-background-hover, var(--linkButton-background-hover));\n color: var(--saltLinkButton-text-color-hover, var(--linkButton-text-color-hover));\n border-color: var(--saltLinkButton-borderColor-hover, var(--linkButton-borderColor-hover));\n text-decoration: var(--linkButton-textDecoration-focus, var(--salt-typography-textDecoration-none));\n}\n\n/* Pseudo-class applied to the root element when LinkButton is active */\n.saltLinkButton.saltLinkButton-active:focus-visible,\n.saltLinkButton:focus-visible:active,\n.saltLinkButton:active,\n.saltLinkButton.saltLinkButton-active {\n background: var(--saltLinkButton-background-active, var(--linkButton-background-active));\n color: var(--saltLinkButton-text-color-active, var(--linkButton-text-color-active));\n border-color: var(--saltLinkButton-borderColor-active, var(--linkButton-borderColor-active));\n cursor: var(--salt-cursor-active);\n}\n\n.saltLinkButton-neutral {\n --linkButton-text-color: var(--salt-actionable-subtle-foreground);\n --linkButton-text-color-hover: var(--salt-actionable-subtle-foreground-hover);\n --linkButton-text-color-active: var(--salt-actionable-subtle-foreground-active);\n --linkButton-background: var(--salt-actionable-subtle-background);\n --linkButton-background-hover: var(--salt-actionable-subtle-background-hover);\n --linkButton-background-active: var(--salt-actionable-subtle-background-active);\n --linkButton-borderColor: var(--salt-actionable-subtle-borderColor);\n --linkButton-borderColor-hover: var(--salt-actionable-subtle-borderColor-hover);\n --linkButton-borderColor-active: var(--salt-actionable-subtle-borderColor-active);\n}\n\n.saltLinkButton-accented {\n --linkButton-text-color: var(--salt-actionable-accented-subtle-foreground);\n --linkButton-text-color-hover: var(--salt-actionable-accented-subtle-foreground-hover);\n --linkButton-text-color-active: var(--salt-actionable-accented-subtle-foreground-active);\n --linkButton-background: var(--salt-actionable-accented-subtle-background);\n --linkButton-background-hover: var(--salt-actionable-accented-subtle-background-hover);\n --linkButton-background-active: var(--salt-actionable-accented-subtle-background-active);\n --linkButton-borderColor: var(--salt-actionable-accented-subtle-borderColor);\n --linkButton-borderColor-hover: var(--salt-actionable-accented-subtle-borderColor-hover);\n --linkButton-borderColor-active: var(--salt-actionable-accented-subtle-borderColor-active);\n}\n";
1
+ var css_248z = ".saltLinkButton {\n --linkButton-borderWidth: var(--salt-size-fixed-100);\n\n align-items: var(--saltLinkButton-alignItems, center);\n appearance: none;\n background: var(--saltLinkButton-background, var(--linkButton-background));\n border-color: var(--saltLinkButton-borderColor, var(--linkButton-borderColor, transparent));\n border-style: var(--saltLinkButton-borderStyle, solid);\n border-width: var(--saltLinkButton-borderWidth, var(--linkButton-borderWidth));\n border-radius: var(--saltLinkButton-borderRadius, var(--salt-palette-corner-weak, 0));\n box-sizing: border-box;\n color: var(--saltLinkButton-text-color, var(--linkButton-text-color));\n display: inline-flex;\n gap: var(--salt-spacing-50);\n justify-content: var(--saltLinkButton-justifyContent, center);\n font-size: var(--saltLinkButton-fontSize, var(--salt-text-fontSize));\n font-family: var(--saltLinkButton-fontFamily, var(--salt-text-action-fontFamily));\n line-height: var(--saltLinkButton-lineHeight, var(--salt-text-lineHeight));\n letter-spacing: var(--saltLinkButton-letterSpacing, var(--salt-text-action-letterSpacing));\n text-transform: var(--saltLinkButton-textTransform, var(--salt-text-action-textTransform));\n padding: 0 var(--saltLinkButton-padding, calc(var(--salt-spacing-100) - var(--saltLinkButton-borderWidth, var(--linkButton-borderWidth))));\n margin: var(--saltLinkButton-margin, 0);\n height: var(--saltLinkButton-height, var(--salt-size-base));\n min-width: var(--saltLinkButton-minWidth, unset);\n position: relative;\n text-align: var(--saltLinkButton-textAlign, var(--salt-text-action-textAlign));\n text-decoration: var(--linkButton-textDecoration, var(--salt-typography-textDecoration-underline));\n text-underline-offset: var(--salt-spacing-fixed-200);\n transition: none;\n width: var(--saltLinkButton-width, auto);\n -webkit-appearance: none;\n -webkit-tap-highlight-color: transparent;\n /* Styles applied to align children*/\n font-weight: var(--saltLinkButton-fontWeight, var(--salt-text-action-fontWeight));\n}\n\n.saltLinkButton-underlineDefault {\n --linkButton-textDecoration: var(--salt-typography-textDecoration-underline);\n --linkButton-textDecoration-hover: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-focus: var(--linkButton-textDecoration-hover);\n}\n\n.saltLinkButton-underlineNever {\n --linkButton-textDecoration: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-hover: var(--salt-typography-textDecoration-none);\n --linkButton-textDecoration-focus: var(--salt-typography-textDecoration-none);\n}\n\n/* Class for ADA content - visually hidden but accessible to screen readers.\n Uses clip-path and prevents user selection so the text isn't included\n when users copy the link button's visible content. */\n.saltLinkButton-externalLinkADA {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n user-select: none;\n -webkit-user-select: none;\n}\n\n@media (hover: hover) {\n /* Pseudo-class applied to the root element on hover when LinkButton is not active or disabled */\n .saltLinkButton:hover {\n background: var(--saltLinkButton-background-hover, var(--linkButton-background-hover));\n color: var(--saltLinkButton-text-color-hover, var(--linkButton-text-color-hover));\n border-color: var(--saltLinkButton-borderColor-hover, var(--linkButton-borderColor-hover));\n cursor: var(--salt-cursor-hover);\n text-decoration: var(--linkButton-textDecoration-hover, var(--salt-typography-textDecoration-none));\n }\n}\n\n/* Pseudo-class applied to the root element on focus */\n.saltLinkButton:focus-visible {\n outline: var(--salt-focused-outline);\n\n background: var(--saltLinkButton-background-hover, var(--linkButton-background-hover));\n color: var(--saltLinkButton-text-color-hover, var(--linkButton-text-color-hover));\n border-color: var(--saltLinkButton-borderColor-hover, var(--linkButton-borderColor-hover));\n text-decoration: var(--linkButton-textDecoration-focus, var(--salt-typography-textDecoration-none));\n}\n\n/* Pseudo-class applied to the root element when LinkButton is active */\n.saltLinkButton.saltLinkButton-active:focus-visible,\n.saltLinkButton:focus-visible:active,\n.saltLinkButton:active,\n.saltLinkButton.saltLinkButton-active {\n background: var(--saltLinkButton-background-active, var(--linkButton-background-active));\n color: var(--saltLinkButton-text-color-active, var(--linkButton-text-color-active));\n border-color: var(--saltLinkButton-borderColor-active, var(--linkButton-borderColor-active));\n cursor: var(--salt-cursor-active);\n}\n\n.saltLinkButton-neutral {\n --linkButton-text-color: var(--salt-actionable-subtle-foreground);\n --linkButton-text-color-hover: var(--salt-actionable-subtle-foreground-hover);\n --linkButton-text-color-active: var(--salt-actionable-subtle-foreground-active);\n --linkButton-background: var(--salt-actionable-subtle-background);\n --linkButton-background-hover: var(--salt-actionable-subtle-background-hover);\n --linkButton-background-active: var(--salt-actionable-subtle-background-active);\n --linkButton-borderColor: var(--salt-actionable-subtle-borderColor);\n --linkButton-borderColor-hover: var(--salt-actionable-subtle-borderColor-hover);\n --linkButton-borderColor-active: var(--salt-actionable-subtle-borderColor-active);\n}\n\n.saltLinkButton-accented {\n --linkButton-text-color: var(--salt-actionable-accented-subtle-foreground);\n --linkButton-text-color-hover: var(--salt-actionable-accented-subtle-foreground-hover);\n --linkButton-text-color-active: var(--salt-actionable-accented-subtle-foreground-active);\n --linkButton-background: var(--salt-actionable-accented-subtle-background);\n --linkButton-background-hover: var(--salt-actionable-accented-subtle-background-hover);\n --linkButton-background-active: var(--salt-actionable-accented-subtle-background-active);\n --linkButton-borderColor: var(--salt-actionable-accented-subtle-borderColor);\n --linkButton-borderColor-hover: var(--salt-actionable-accented-subtle-borderColor-hover);\n --linkButton-borderColor-active: var(--salt-actionable-accented-subtle-borderColor-active);\n}\n";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=LinkButton.css.js.map
@@ -0,0 +1,50 @@
1
+ import { useMemo, useState, useCallback, useContext } from 'react';
2
+ import { createContext } from '../utils/createContext.js';
3
+ import 'clsx';
4
+ import 'react/jsx-runtime';
5
+ import '../utils/useFloatingUI/useFloatingUI.js';
6
+ import '../utils/useId.js';
7
+ import '../salt-provider/SaltProvider.js';
8
+ import '../viewport/ViewportProvider.js';
9
+
10
+ const MenuAlignmentContext = createContext(
11
+ "MenuAlignmentContext",
12
+ {
13
+ reserveIconSpace: false,
14
+ reserveSelectionIconSpace: false,
15
+ registerIcon: () => () => void 0,
16
+ registerSelectionIcon: () => () => void 0
17
+ }
18
+ );
19
+ function useSlotRegistry() {
20
+ const [count, setCount] = useState(0);
21
+ const register = useCallback(() => {
22
+ setCount((current) => current + 1);
23
+ return () => setCount((current) => current - 1);
24
+ }, []);
25
+ return [count > 0, register];
26
+ }
27
+ function useMenuAlignmentScope() {
28
+ const [reserveIconSpace, registerIcon] = useSlotRegistry();
29
+ const [reserveSelectionIconSpace, registerSelectionIcon] = useSlotRegistry();
30
+ return useMemo(
31
+ () => ({
32
+ reserveIconSpace,
33
+ reserveSelectionIconSpace,
34
+ registerIcon,
35
+ registerSelectionIcon
36
+ }),
37
+ [
38
+ reserveIconSpace,
39
+ reserveSelectionIconSpace,
40
+ registerIcon,
41
+ registerSelectionIcon
42
+ ]
43
+ );
44
+ }
45
+ function useMenuAlignment() {
46
+ return useContext(MenuAlignmentContext);
47
+ }
48
+
49
+ export { MenuAlignmentContext, useMenuAlignment, useMenuAlignmentScope, useSlotRegistry };
50
+ //# 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":[],"mappings":";;;;;;;;;AAcO,MAAM,oBAAA,GAAuB,aAAA;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,GAAI,SAAS,CAAC,CAAA;AACpC,EAAA,MAAM,QAAA,GAAW,YAAY,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,OAAO,OAAA;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,OAAO,WAAW,oBAAoB,CAAA;AACxC;;;;"}
@@ -9,6 +9,7 @@ import '../utils/useId.js';
9
9
  import '../salt-provider/SaltProvider.js';
10
10
  import '../viewport/ViewportProvider.js';
11
11
  import { MenuContext } from './MenuContext.js';
12
+ import { MenuGroupContext, defaultMenuGroupContextValue } from './MenuGroupContext.js';
12
13
 
13
14
  function MenuBase(props) {
14
15
  const {
@@ -40,10 +41,14 @@ function MenuBase(props) {
40
41
  const [focusInside, setFocusInside] = useState(false);
41
42
  const [triggerDisabled, setTriggerDisabled] = useState(false);
42
43
  const isNested = parentId != null;
44
+ const handleOpenChange = (newOpen) => {
45
+ if (newOpen && triggerDisabled) return;
46
+ setOpen(newOpen);
47
+ };
43
48
  const { x, y, strategy, elements, refs, context } = useFloatingUI({
44
49
  nodeId,
45
50
  open: openState,
46
- onOpenChange: setOpen,
51
+ onOpenChange: handleOpenChange,
47
52
  strategy: !getVirtualElement ? "absolute" : "fixed",
48
53
  placement: placement ?? (isNested || getVirtualElement ? "right-start" : "bottom-start"),
49
54
  middleware: [
@@ -84,7 +89,8 @@ function MenuBase(props) {
84
89
  listRef: elementsRef,
85
90
  activeIndex,
86
91
  nested: isNested,
87
- onNavigate: setActiveIndex
92
+ onNavigate: setActiveIndex,
93
+ disabledIndices: (index) => elementsRef.current[index] == null
88
94
  })
89
95
  ]
90
96
  );
@@ -127,7 +133,7 @@ function MenuBase(props) {
127
133
  triggerDisabled,
128
134
  setTriggerDisabled
129
135
  },
130
- children
136
+ children: /* @__PURE__ */ jsx(MenuGroupContext.Provider, { value: defaultMenuGroupContextValue, children })
131
137
  }
132
138
  ) });
133
139
  }
@@ -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: setOpen,\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 }),\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 {children}\n </MenuContext.Provider>\n </FloatingNode>\n );\n}\n"],"names":["elements"],"mappings":"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"}
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":["elements"],"mappings":"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"}
@@ -1,19 +1,30 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useComponentCssInjection } from '@salt-ds/styles';
3
3
  import { useWindow } from '@salt-ds/window';
4
4
  import { clsx } from 'clsx';
5
- import { forwardRef } from 'react';
5
+ import { forwardRef, useMemo, useCallback } from 'react';
6
6
  import { makePrefixer } from '../utils/makePrefixer.js';
7
7
  import '../utils/useFloatingUI/useFloatingUI.js';
8
8
  import { useId } from '../utils/useId.js';
9
9
  import '../salt-provider/SaltProvider.js';
10
10
  import '../viewport/ViewportProvider.js';
11
+ import { useMenuAlignmentScope, MenuAlignmentContext } from './MenuAlignmentContext.js';
11
12
  import css_248z from './MenuGroup.css.js';
13
+ import { MenuGroupContext } from './MenuGroupContext.js';
12
14
 
13
15
  const withBaseName = makePrefixer("saltMenuGroup");
16
+ const noSelection = [];
14
17
  const MenuGroup = forwardRef(
15
18
  function MenuGroup2(props, ref) {
16
- const { className, children, label, ...rest } = props;
19
+ const {
20
+ className,
21
+ children,
22
+ label,
23
+ onSelectionChange,
24
+ selected: selectedProp = noSelection,
25
+ selectionVariant,
26
+ ...rest
27
+ } = props;
17
28
  const targetWindow = useWindow();
18
29
  useComponentCssInjection({
19
30
  testId: "salt-menu-group",
@@ -21,7 +32,35 @@ const MenuGroup = forwardRef(
21
32
  window: targetWindow
22
33
  });
23
34
  const labelId = useId();
24
- return /* @__PURE__ */ jsxs(
35
+ const selected = useMemo(
36
+ () => selectionVariant === "single" ? selectedProp.slice(0, 1) : selectedProp,
37
+ [selectedProp, selectionVariant]
38
+ );
39
+ const isSelected = useCallback(
40
+ (value) => selected.includes(value),
41
+ [selected]
42
+ );
43
+ const select = useCallback(
44
+ (event, value) => {
45
+ if (selectionVariant === "single") {
46
+ if (!selected.includes(value)) {
47
+ onSelectionChange == null ? void 0 : onSelectionChange(event, [value]);
48
+ }
49
+ } else if (selectionVariant === "multiple") {
50
+ onSelectionChange == null ? void 0 : onSelectionChange(
51
+ event,
52
+ selected.includes(value) ? selected.filter((item) => item !== value) : selected.concat(value)
53
+ );
54
+ }
55
+ },
56
+ [onSelectionChange, selected, selectionVariant]
57
+ );
58
+ const contextValue = useMemo(
59
+ () => ({ isSelected, select, selectionVariant }),
60
+ [isSelected, select, selectionVariant]
61
+ );
62
+ const alignment = useMenuAlignmentScope();
63
+ return /* @__PURE__ */ jsx(MenuGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(MenuAlignmentContext.Provider, { value: alignment, children: /* @__PURE__ */ jsxs(
25
64
  "div",
26
65
  {
27
66
  "aria-labelledby": label ? labelId : void 0,
@@ -34,7 +73,7 @@ const MenuGroup = forwardRef(
34
73
  children
35
74
  ]
36
75
  }
37
- );
76
+ ) }) });
38
77
  }
39
78
  );
40
79
 
@@ -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\nexport interface MenuGroupProps extends ComponentPropsWithoutRef<\"div\"> {\n /**\n * The label of the menu group.\n */\n label?: string;\n /**\n * Menus to be rendered inside the menu group.\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltMenuGroup\");\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(\n function MenuGroup(props, ref) {\n const { className, children, label, ...rest } = props;\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 return (\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 );\n },\n);\n"],"names":["MenuGroup","menuGroupCss"],"mappings":";;;;;;;;;;;;AAsBA,MAAM,YAAA,GAAe,aAAa,eAAe,CAAA;AAE1C,MAAM,SAAA,GAAY,UAAA;AAAA,EACvB,SAASA,UAAAA,CAAU,KAAA,EAAO,GAAA,EAAK;AAC7B,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AAEhD,IAAA,MAAM,eAAe,SAAA,EAAU;AAC/B,IAAA,wBAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,iBAAA;AAAA,MACR,GAAA,EAAKC,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,MAAM,UAAU,KAAA,EAAM;AAEtB,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,iBAAA,EAAiB,QAAQ,OAAA,GAAU,MAAA;AAAA,QACnC,SAAA,EAAW,IAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,IAAA,EAAK,OAAA;AAAA,QACL,GAAA;AAAA,QACC,GAAG,IAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,KAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,aAAA,EAAW,IAAA,EAAC,SAAA,EAAW,aAAa,OAAO,CAAA,EAAG,EAAA,EAAI,OAAA,EACpD,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAED;AAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;;;;"}
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":["MenuGroup","menuGroupCss"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { useContext } from 'react';
2
+ import { createContext } from '../utils/createContext.js';
3
+ import 'clsx';
4
+ import 'react/jsx-runtime';
5
+ import '../utils/useFloatingUI/useFloatingUI.js';
6
+ import '../utils/useId.js';
7
+ import '../salt-provider/SaltProvider.js';
8
+ import '../viewport/ViewportProvider.js';
9
+
10
+ const defaultMenuGroupContextValue = {
11
+ isSelected: () => false,
12
+ select: () => void 0
13
+ };
14
+ const MenuGroupContext = createContext(
15
+ "MenuGroupContext",
16
+ defaultMenuGroupContextValue
17
+ );
18
+ function useMenuGroup() {
19
+ return useContext(MenuGroupContext);
20
+ }
21
+
22
+ export { MenuGroupContext, defaultMenuGroupContextValue, useMenuGroup };
23
+ //# 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":[],"mappings":";;;;;;;;;AAUO,MAAM,4BAAA,GAAsD;AAAA,EACjE,YAAY,MAAM,KAAA;AAAA,EAClB,QAAQ,MAAM;AAChB;AAEO,MAAM,gBAAA,GAAmB,aAAA;AAAA,EAC9B,kBAAA;AAAA,EACA;AACF;AAEO,SAAS,YAAA,GAAe;AAC7B,EAAA,OAAO,WAAW,gBAAgB,CAAA;AACpC;;;;"}
@@ -1,4 +1,4 @@
1
- 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";
1
+ 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";
2
2
 
3
3
  export { css_248z as default };
4
4
  //# sourceMappingURL=MenuItem.css.js.map