@gridui/dropdown-menu 1.1.7 → 2.0.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/README.md CHANGED
@@ -1,9 +1,17 @@
1
1
  # @gridui/dropdown-menu
2
2
 
3
- Core family. Public API: `ContextMenu`, `ContextMenuProps`, `DropdownMenu`, `DropdownMenuContent`, `DropdownMenuContentProps`, `DropdownMenuItem`, `DropdownMenuItemProps`, `DropdownMenuLabel`, `DropdownMenuLabelProps`, `DropdownMenuProps`, `DropdownMenuRadioGroup`, `DropdownMenuRadioGroupProps`, `DropdownMenuRadioItem`, `DropdownMenuRadioItemProps`, `DropdownMenuTrigger`, `DropdownMenuTriggerProps`, `dropdownContentStyles`, `dropdownIndicatorStyles`, `dropdownItemStyles`, `dropdownLabelStyles`.
3
+ Core family. Public API: `ContextMenu`, `ContextMenuProps`, `DropdownMenu`, `DropdownMenuContent`, `DropdownMenuContentProps`, `DropdownMenuItem`, `DropdownMenuItemProps`, `DropdownMenuLabel`, `DropdownMenuLabelProps`, `DropdownMenuProps`, `DropdownMenuRadioGroup`, `DropdownMenuRadioGroupProps`, `DropdownMenuRadioItem`, `DropdownMenuRadioItemProps`, `DropdownMenuTrigger`, `DropdownMenuTriggerProps`, `dropdownContentStyles`.
4
4
 
5
- Import components from `@gridui/dropdown-menu` and load `@gridui/dropdown-menu/styles.css` after Theme.
6
- Load styles for any composed dependency used by this family. Applications own routes, labels, state persistence, and branding.
5
+ Import components from `@gridui/dropdown-menu` and load these styles in order:
6
+
7
+ ```css
8
+ @import "@gridui/theme/styles.css";
9
+ @import "@gridui/overlay/styles.css";
10
+ @import "@gridui/dropdown-menu/styles.css";
11
+ ```
12
+
13
+ Overlay supplies popup surfaces, option rows, group labels, and selection
14
+ indicators. Applications own routes, labels, state persistence, and branding.
7
15
 
8
16
  See [component ownership](https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/docs/component-ownership.md) and [release history](https://github.com/sudo-ui/GridUI-React-Monorepo/tree/main/packages-core/dropdown-menu/.changeset/history).
9
17
 
@@ -13,7 +21,8 @@ Import `Button`, `ButtonLink`, `buttonClass`, and `useAsyncAction`
13
21
  from [`@gridui/button`](https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/packages-core/button/README.md). Load that package's `styles.css`
14
22
  for standalone buttons and composed actions. The Button package owns
15
23
  native semantics, variants, sizes, icons, loading, and action lifecycle behavior.
16
- DropdownMenu uses Button through its public API.
24
+ Compose a styled trigger with `<DropdownMenuTrigger asChild>` and `Button`,
25
+ loading Button’s stylesheet when used. DropdownMenu does not require Button.
17
26
 
18
27
  `@gridui/dropdown-menu` wraps Radix Dropdown Menu.
19
28
  It exports the root, trigger, portalled content, items, label, radio
@@ -22,8 +31,7 @@ its separate `styles.css` export. Radix owns keyboard navigation, focus return,
22
31
  Escape dismissal, and viewport collisions. The portal avoids clipped grid
23
32
  boundaries.
24
33
 
25
-
26
- Surface motion uses `@gridui/overlay`; load `@gridui/overlay/styles.css` after Theme and before this family.
34
+ Surface motion also uses `@gridui/overlay`.
27
35
 
28
36
  Menu options use Theme's outward hover, pressed, and focus outlines. Overlay
29
37
  mirrors their resolved outlines beyond the menu's scrolling boundary, including
@@ -33,3 +41,16 @@ and dismissal; the decorative outline layer cannot receive pointer input.
33
41
  The menu surface has no padding by default: option hit areas reach its inner
34
42
  border, and each option owns its text padding. Caller classes can add deliberate
35
43
  surface padding. Native scrolling uses Theme's shared scrollbar appearance.
44
+
45
+ Menus, context menus, and selection lists share `overlayListStyles()` from Overlay
46
+ and its `overlayListItemStyles()`, `overlayListLabelStyles()`, and
47
+ `overlayListIndicatorStyles()` helpers. Selectable rows reserve
48
+ a trailing 16px check slot in both selected and unselected states. Icons and text
49
+ precede the check; RTL mirrors the order. Labels wrap within the available width.
50
+
51
+ Set `morph` on `DropdownMenuContent` to expand the menu from its trigger
52
+ when opening. `respectReducedMotion` defaults to `true`. Set it to `false`
53
+ to play the expansion even when the system requests reduced motion.
54
+
55
+ `ContextMenu` accepts `dir="ltr" | "rtl"` and forwards it to the menu root,
56
+ so portal positioning and keyboard navigation use the same direction as its rows.
@@ -4,9 +4,10 @@
4
4
  * @namespace ContextMenu
5
5
  * @description Context Menu
6
6
  */
7
- import { type DropdownMenuContentProps } from "../dropdown-menu-content/dropdown-menu-content";
7
+ import { type DropdownMenuProps } from "../dropdown-menu/dropdown-menu";
8
+ import type { MenuContentOptions } from "../shared/menu-content-options";
8
9
  import { type FC, type ReactNode } from "react";
9
- export type ContextMenuProps = Omit<DropdownMenuContentProps, "children"> & {
10
+ export type ContextMenuProps = Omit<MenuContentOptions, "children"> & Pick<DropdownMenuProps, "dir"> & {
10
11
  readonly x: number;
11
12
  readonly y: number;
12
13
  readonly label: string;
@@ -4,7 +4,7 @@
4
4
  * @namespace DropdownMenuContent
5
5
  * @description Dropdown Menu Content
6
6
  */
7
- import * as Primitive from "@radix-ui/react-dropdown-menu";
8
- import type { ComponentPropsWithRef, FC } from "react";
9
- export type DropdownMenuContentProps = ComponentPropsWithRef<typeof Primitive.Content>;
7
+ import type { MenuContentOptions } from "../shared/menu-content-options";
8
+ import type { FC } from "react";
9
+ export type DropdownMenuContentProps = MenuContentOptions;
10
10
  export declare const DropdownMenuContent: FC<DropdownMenuContentProps>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Dropdown Menu
4
+ * @namespace DropdownMenuContent
5
+ * @description Use Menu Morph
6
+ */
7
+ export declare const useMenuMorph: (element: HTMLDivElement | null, enabled: boolean) => void;
package/dist/index.d.ts CHANGED
@@ -15,12 +15,9 @@ export type { DropdownMenuItemProps } from "./dropdown-menu-item/dropdown-menu-i
15
15
  export { DropdownMenuItem } from "./dropdown-menu-item/dropdown-menu-item";
16
16
  export type { DropdownMenuLabelProps } from "./dropdown-menu-label/dropdown-menu-label";
17
17
  export { DropdownMenuLabel } from "./dropdown-menu-label/dropdown-menu-label";
18
- export { dropdownLabelStyles } from "./dropdown-menu-label/style";
19
18
  export type { DropdownMenuRadioGroupProps } from "./dropdown-menu-radio-group/dropdown-menu-radio-group";
20
19
  export { DropdownMenuRadioGroup } from "./dropdown-menu-radio-group/dropdown-menu-radio-group";
21
20
  export type { DropdownMenuRadioItemProps } from "./dropdown-menu-radio-item/dropdown-menu-radio-item";
22
21
  export { DropdownMenuRadioItem } from "./dropdown-menu-radio-item/dropdown-menu-radio-item";
23
- export { dropdownIndicatorStyles } from "./dropdown-menu-radio-item/style";
24
22
  export type { DropdownMenuTriggerProps } from "./dropdown-menu-trigger/dropdown-menu-trigger";
25
23
  export { DropdownMenuTrigger } from "./dropdown-menu-trigger/dropdown-menu-trigger";
26
- export { dropdownItemStyles } from "./shared/style";
package/dist/index.js CHANGED
@@ -20,19 +20,72 @@ var DropdownMenu = (props) => {
20
20
  };
21
21
 
22
22
  // src/dropdown-menu-content/style.ts
23
- import { overlaySurfaceStyles } from "@gridui/overlay";
23
+ import { overlayListStyles } from "@gridui/overlay";
24
24
  import { cn } from "@gridui/style-utils";
25
25
  import { cva } from "class-variance-authority";
26
26
  var dropdownContentStyles = cva(cn(
27
- overlaySurfaceStyles(),
27
+ overlayListStyles(),
28
28
  "gridui-dropdown-content",
29
- "gridui-u-z-(--gridui-z-popover) gridui-u-min-w-44 gridui-u-max-w-[calc(100vw-2*var(--gridui-page-gutter))] gridui-u-max-h-(--radix-dropdown-menu-content-available-height) gridui-u-overflow-y-auto gridui-u-p-0 gridui-u-type-data"
29
+ "gridui-u-dropdown-menu--min-w-44 gridui-u-dropdown-menu--max-w-[calc(100vw-2*var(--gridui-page-gutter))] gridui-u-dropdown-menu--max-h-(--radix-dropdown-menu-content-available-height) gridui-u-dropdown-menu--overflow-y-auto"
30
30
  ));
31
31
 
32
+ // src/dropdown-menu-content/use-menu-morph.ts
33
+ import { useLayoutEffect } from "react";
34
+ var useMenuMorph = (element, enabled) => {
35
+ useLayoutEffect(() => {
36
+ if (!element || !enabled) {
37
+ return;
38
+ }
39
+ const place = () => {
40
+ if (element.style.animation === "none") {
41
+ return;
42
+ }
43
+ observer.disconnect();
44
+ const document2 = element.ownerDocument;
45
+ const trigger = document2.getElementById(element.getAttribute("aria-labelledby") ?? "");
46
+ if (!trigger) {
47
+ return;
48
+ }
49
+ element.setAttribute("data-morph-measuring", "");
50
+ const menu = element.getBoundingClientRect();
51
+ element.removeAttribute("data-morph-measuring");
52
+ const anchor = trigger.getBoundingClientRect();
53
+ const width = Math.min(menu.width, anchor.width);
54
+ const height = Math.min(menu.height, anchor.height);
55
+ if (!width || !height) {
56
+ return;
57
+ }
58
+ const x = anchor.left + (anchor.width - width) / 2 - menu.left;
59
+ const y = anchor.top + (anchor.height - height) / 2 - menu.top;
60
+ const left = Math.max(0, Math.min(x, menu.width - width));
61
+ const top = Math.max(0, Math.min(y, menu.height - height));
62
+ element.style.setProperty("--gridui-menu-morph-clip", `inset(${top}px ${menu.width - width - left}px ${menu.height - height - top}px ${left}px)`);
63
+ element.style.setProperty("--gridui-menu-morph-offset", `${x - left}px, ${y - top}px`);
64
+ element.setAttribute("data-morph-ready", "");
65
+ };
66
+ const observer = new MutationObserver(place);
67
+ observer.observe(element, {
68
+ attributes: true,
69
+ attributeFilter: ["style"]
70
+ });
71
+ place();
72
+ return () => {
73
+ observer.disconnect();
74
+ element.removeAttribute("data-morph-ready");
75
+ element.style.removeProperty("--gridui-menu-morph-clip");
76
+ element.style.removeProperty("--gridui-menu-morph-offset");
77
+ };
78
+ }, [
79
+ element,
80
+ enabled
81
+ ]);
82
+ };
83
+
32
84
  // src/dropdown-menu-content/dropdown-menu-content.tsx
33
- import { interactionLayerProps, RetainedLayer, useInteractionOutline, useScrollbars } from "@gridui/overlay";
85
+ import { interactionLayerProps, OverlayOpen as OverlayOpen2, RetainedLayer, useInteractionOutline, useScrollbars } from "@gridui/overlay";
34
86
  import { cn as cn2 } from "@gridui/style-utils";
35
87
  import * as Primitive2 from "@radix-ui/react-dropdown-menu";
88
+ import { useCallback, useContext, useState } from "react";
36
89
  import { jsx as jsx2 } from "react/jsx-runtime";
37
90
  var DropdownMenuContent = (props) => {
38
91
  const {
@@ -41,9 +94,32 @@ var DropdownMenuContent = (props) => {
41
94
  forceMount,
42
95
  sideOffset = 8,
43
96
  align = "end",
97
+ morph = false,
98
+ respectReducedMotion = true,
44
99
  ...restProps
45
100
  } = props;
46
- const scrollbarRef = useScrollbars({ ref: forwardedRef });
101
+ const open = useContext(OverlayOpen2);
102
+ const [
103
+ element,
104
+ setElement
105
+ ] = useState(null);
106
+ const morphRef = useCallback((node) => {
107
+ setElement(node);
108
+ if (typeof forwardedRef === "function") {
109
+ const cleanup = forwardedRef(node);
110
+ if (cleanup) {
111
+ return () => {
112
+ setElement(null);
113
+ cleanup();
114
+ };
115
+ }
116
+ } else if (forwardedRef) {
117
+ forwardedRef.current = node;
118
+ }
119
+ return void 0;
120
+ }, [forwardedRef]);
121
+ useMenuMorph(element, morph && open === true);
122
+ const scrollbarRef = useScrollbars({ ref: morph ? morphRef : forwardedRef });
47
123
  const ref = useInteractionOutline({
48
124
  ref: scrollbarRef,
49
125
  selector: '[role^="menuitem"]'
@@ -57,6 +133,7 @@ var DropdownMenuContent = (props) => {
57
133
  forceMount,
58
134
  align,
59
135
  sideOffset,
136
+ "data-morph-ignore-reduced-motion": !respectReducedMotion || void 0,
60
137
  className: cn2(dropdownContentStyles(), className)
61
138
  }
62
139
  );
@@ -82,12 +159,12 @@ var DropdownMenuTrigger = (props) => {
82
159
  };
83
160
 
84
161
  // src/context-menu/context-menu.tsx
85
- import { useEffect, useState } from "react";
162
+ import { useEffect, useState as useState2 } from "react";
86
163
  import { createPortal } from "react-dom";
87
164
  import { jsx as jsx4, jsxs } from "react/jsx-runtime";
88
165
  var ContextMenu = (props) => {
89
- const { x, y, label, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;
90
- const [returnFocus] = useState(() => {
166
+ const { x, y, label, dir, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;
167
+ const [returnFocus] = useState2(() => {
91
168
  return typeof document === "undefined" ? null : document.activeElement;
92
169
  });
93
170
  useEffect(() => {
@@ -109,6 +186,7 @@ var ContextMenu = (props) => {
109
186
  {
110
187
  open: true,
111
188
  modal: false,
189
+ dir,
112
190
  onOpenChange: (open) => {
113
191
  if (!open) {
114
192
  onClose();
@@ -181,18 +259,9 @@ var ContextMenu = (props) => {
181
259
  ), document.body);
182
260
  };
183
261
 
184
- // src/shared/style.ts
185
- import { cn as cn3 } from "@gridui/style-utils";
186
- import { cva as cva2 } from "class-variance-authority";
187
- var dropdownItemStyles = cva2(cn3(
188
- "gridui-dropdown-item",
189
- "gridui-u-flex gridui-u-min-h-10 gridui-u-items-center gridui-u-gap-gridui-8 gridui-u-px-gridui-8 gridui-u-py-gridui-8 gridui-u-rounded-control gridui-u-text-inherit gridui-u-no-underline gridui-u-cursor-pointer",
190
- "gridui-u-data-[state=checked]:bg-brand-tint gridui-u-aria-selected:bg-brand-tint",
191
- "gridui-u-data-disabled:opacity-50 gridui-u-data-disabled:pointer-events-none"
192
- ));
193
-
194
262
  // src/dropdown-menu-item/dropdown-menu-item.tsx
195
- import { cn as cn4 } from "@gridui/style-utils";
263
+ import { overlayListItemStyles } from "@gridui/overlay";
264
+ import { cn as cn3 } from "@gridui/style-utils";
196
265
  import * as Primitive4 from "@radix-ui/react-dropdown-menu";
197
266
  import { jsx as jsx5 } from "react/jsx-runtime";
198
267
  var DropdownMenuItem = (props) => {
@@ -204,21 +273,14 @@ var DropdownMenuItem = (props) => {
204
273
  Primitive4.Item,
205
274
  {
206
275
  ...restProps,
207
- className: cn4(dropdownItemStyles(), className)
276
+ className: cn3(overlayListItemStyles(), className)
208
277
  }
209
278
  );
210
279
  };
211
280
 
212
- // src/dropdown-menu-label/style.ts
213
- import { cn as cn5 } from "@gridui/style-utils";
214
- import { cva as cva3 } from "class-variance-authority";
215
- var dropdownLabelStyles = cva3(cn5(
216
- "gridui-dropdown-label",
217
- "gridui-u-p-gridui-8 gridui-u-text-muted gridui-u-type-caption"
218
- ));
219
-
220
281
  // src/dropdown-menu-label/dropdown-menu-label.tsx
221
- import { cn as cn6 } from "@gridui/style-utils";
282
+ import { overlayListLabelStyles } from "@gridui/overlay";
283
+ import { cn as cn4 } from "@gridui/style-utils";
222
284
  import * as Primitive5 from "@radix-ui/react-dropdown-menu";
223
285
  import { jsx as jsx6 } from "react/jsx-runtime";
224
286
  var DropdownMenuLabel = (props) => {
@@ -230,7 +292,7 @@ var DropdownMenuLabel = (props) => {
230
292
  Primitive5.Label,
231
293
  {
232
294
  ...restProps,
233
- className: cn6(dropdownLabelStyles(), className)
295
+ className: cn4(overlayListLabelStyles(), className)
234
296
  }
235
297
  );
236
298
  };
@@ -247,16 +309,9 @@ var DropdownMenuRadioGroup = (props) => {
247
309
  );
248
310
  };
249
311
 
250
- // src/dropdown-menu-radio-item/style.ts
251
- import { cn as cn7 } from "@gridui/style-utils";
252
- import { cva as cva4 } from "class-variance-authority";
253
- var dropdownIndicatorStyles = cva4(cn7(
254
- "gridui-dropdown-indicator",
255
- "gridui-u-w-gridui-16 gridui-u-shrink-0 gridui-u-text-foreground"
256
- ));
257
-
258
312
  // src/dropdown-menu-radio-item/dropdown-menu-radio-item.tsx
259
- import { cn as cn8 } from "@gridui/style-utils";
313
+ import { overlayListIndicatorStyles, overlayListItemStyles as overlayListItemStyles2 } from "@gridui/overlay";
314
+ import { cn as cn5 } from "@gridui/style-utils";
260
315
  import * as Primitive7 from "@radix-ui/react-dropdown-menu";
261
316
  import { Check } from "lucide-react";
262
317
  import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -270,12 +325,19 @@ var DropdownMenuRadioItem = (props) => {
270
325
  Primitive7.RadioItem,
271
326
  {
272
327
  ...restProps,
273
- className: cn8(dropdownItemStyles(), className),
328
+ className: cn5(overlayListItemStyles2(), className),
274
329
  children: [
275
330
  /* @__PURE__ */ jsx8(
276
331
  "span",
277
332
  {
278
- className: cn8(dropdownIndicatorStyles()),
333
+ className: "gridui-u-dropdown-menu--flex gridui-u-dropdown-menu--min-w-0 gridui-u-dropdown-menu--flex-1 gridui-u-dropdown-menu--items-center gridui-u-dropdown-menu--gap-gridui-8",
334
+ children
335
+ }
336
+ ),
337
+ /* @__PURE__ */ jsx8(
338
+ "span",
339
+ {
340
+ className: cn5(overlayListIndicatorStyles()),
279
341
  "aria-hidden": "true",
280
342
  children: /* @__PURE__ */ jsx8(Primitive7.ItemIndicator, { children: /* @__PURE__ */ jsx8(
281
343
  Check,
@@ -285,8 +347,7 @@ var DropdownMenuRadioItem = (props) => {
285
347
  }
286
348
  ) })
287
349
  }
288
- ),
289
- children
350
+ )
290
351
  ]
291
352
  }
292
353
  );
@@ -300,9 +361,6 @@ export {
300
361
  DropdownMenuRadioGroup,
301
362
  DropdownMenuRadioItem,
302
363
  DropdownMenuTrigger,
303
- dropdownContentStyles,
304
- dropdownIndicatorStyles,
305
- dropdownItemStyles,
306
- dropdownLabelStyles
364
+ dropdownContentStyles
307
365
  };
308
366
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/dropdown-menu/dropdown-menu.tsx", "../src/dropdown-menu-content/style.ts", "../src/dropdown-menu-content/dropdown-menu-content.tsx", "../src/dropdown-menu-trigger/dropdown-menu-trigger.tsx", "../src/context-menu/context-menu.tsx", "../src/shared/style.ts", "../src/dropdown-menu-item/dropdown-menu-item.tsx", "../src/dropdown-menu-label/style.ts", "../src/dropdown-menu-label/dropdown-menu-label.tsx", "../src/dropdown-menu-radio-group/dropdown-menu-radio-group.tsx", "../src/dropdown-menu-radio-item/style.ts", "../src/dropdown-menu-radio-item/dropdown-menu-radio-item.tsx"],
4
- "sourcesContent": ["/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenu\n * @description Dropdown Menu\n */\n\nimport { OverlayOpen, useOverlayState } from \"@gridui/overlay\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuProps = ComponentPropsWithRef<typeof Primitive.Root>;\n\nexport const DropdownMenu: FC<DropdownMenuProps> = (props: DropdownMenuProps) => {\n const state = useOverlayState(props);\n return (<OverlayOpen.Provider\n value={state.open}\n >\n <Primitive.Root\n {...props}\n {...state}\n />\n </OverlayOpen.Provider>);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuContent\n * @description Style\n */\n\nimport { overlaySurfaceStyles } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const dropdownContentStyles = cva(cn(\n overlaySurfaceStyles(),\n \"gridui-dropdown-content\",\n \"gridui-u-z-(--gridui-z-popover) gridui-u-min-w-44 gridui-u-max-w-[calc(100vw-2*var(--gridui-page-gutter))] gridui-u-max-h-(--radix-dropdown-menu-content-available-height) gridui-u-overflow-y-auto gridui-u-p-0 gridui-u-type-data\",\n));\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuContent\n * @description Dropdown Menu Content\n */\n\nimport { dropdownContentStyles } from \"./style\";\nimport { interactionLayerProps, RetainedLayer, useInteractionOutline, useScrollbars } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuContentProps = ComponentPropsWithRef<typeof Primitive.Content>;\n\nexport const DropdownMenuContent: FC<DropdownMenuContentProps> = (props: DropdownMenuContentProps) => {\n const {\n className,\n ref: forwardedRef,\n forceMount,\n sideOffset = 8,\n align = \"end\",\n ...restProps\n } = props;\n const scrollbarRef = useScrollbars({ ref: forwardedRef });\n const ref = useInteractionOutline({\n ref: scrollbarRef,\n selector: '[role^=\"menuitem\"]',\n });\n const content = (<Primitive.Content\n {...interactionLayerProps}\n {...restProps}\n ref={ref}\n forceMount={forceMount}\n align={align}\n sideOffset={sideOffset}\n className={cn(dropdownContentStyles(), className)}\n />);\n return (<Primitive.Portal\n forceMount={forceMount}\n >\n {forceMount ? (<RetainedLayer>\n {content}\n </RetainedLayer>) : content}\n </Primitive.Portal>);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuTrigger\n * @description Dropdown Menu Trigger\n */\n\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuTriggerProps = ComponentPropsWithRef<typeof Primitive.Trigger>;\n\nexport const DropdownMenuTrigger: FC<DropdownMenuTriggerProps> = (props: DropdownMenuTriggerProps) => {\n return (<Primitive.Trigger\n {...props}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace ContextMenu\n * @description Context Menu\n */\n\nimport { DropdownMenu } from \"../dropdown-menu/dropdown-menu\";\nimport { DropdownMenuContent, type DropdownMenuContentProps } from \"../dropdown-menu-content/dropdown-menu-content\";\nimport { DropdownMenuTrigger } from \"../dropdown-menu-trigger/dropdown-menu-trigger\";\nimport { type FC, type ReactNode, useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport type ContextMenuProps = Omit<DropdownMenuContentProps, \"children\"> & {\n readonly x: number;\n readonly y: number;\n readonly label: string;\n readonly children: ReactNode;\n readonly onClose: () => void;\n};\n\n/** Uses the same menu semantics and presentation as trigger-based dropdowns. */\nexport const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {\n const { x, y, label, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;\n\n const [returnFocus] = useState(() => {\n return typeof document === \"undefined\" ? null : document.activeElement;\n });\n useEffect(() => {\n\n const dismissWhenInactive = () => {\n\n if (!document.hasFocus()) {\n onClose();\n }\n };\n window.addEventListener(\"blur\", dismissWhenInactive);\n\n return () => {\n\n window.removeEventListener(\"blur\", dismissWhenInactive);\n };\n }, [onClose]);\n\n if (typeof document === \"undefined\") {\n return null;\n }\n return createPortal((<DropdownMenu\n key={`${x}:${y}`}\n open\n modal={false}\n onOpenChange={open => {\n\n if (!open) {\n onClose();\n }\n }}\n >\n <DropdownMenuTrigger\n asChild\n >\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n style={{\n position: \"fixed\",\n left: x,\n top: y,\n width: 0,\n height: 0,\n padding: 0,\n border: 0,\n opacity: 0,\n pointerEvents: \"none\",\n }}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n aria-label={label}\n side=\"bottom\"\n align=\"start\"\n sideOffset={0}\n collisionPadding={8}\n {...contentProps}\n onPointerUpCapture={event => {\n onPointerUpCapture?.(event);\n // The release that opens a flush context menu must not select its first item.\n if (event.button !== 0 || event.ctrlKey) {\n event.preventDefault();\n }\n }}\n onCloseAutoFocus={event => {\n onCloseAutoFocus?.(event);\n if (event.defaultPrevented) {\n return;\n }\n event.preventDefault();\n if (document.activeElement === document.body\n && returnFocus instanceof HTMLElement\n && returnFocus.isConnected) {\n returnFocus.focus();\n }\n }}\n onKeyDown={event => {\n\n onKeyDown?.(event);\n if (!event.defaultPrevented && event.key === \"Tab\") {\n event.preventDefault();\n onClose();\n }\n }}\n >\n {children}\n </DropdownMenuContent>\n </DropdownMenu>), document.body);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace Shared\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const dropdownItemStyles = cva(cn(\n \"gridui-dropdown-item\",\n \"gridui-u-flex gridui-u-min-h-10 gridui-u-items-center gridui-u-gap-gridui-8 gridui-u-px-gridui-8 gridui-u-py-gridui-8 gridui-u-rounded-control gridui-u-text-inherit gridui-u-no-underline gridui-u-cursor-pointer\",\n \"gridui-u-data-[state=checked]:bg-brand-tint gridui-u-aria-selected:bg-brand-tint\",\n \"gridui-u-data-disabled:opacity-50 gridui-u-data-disabled:pointer-events-none\",\n));\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuItem\n * @description Dropdown Menu Item\n */\n\nimport { dropdownItemStyles } from \"../shared/style\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuItemProps = ComponentPropsWithRef<typeof Primitive.Item>;\n\nexport const DropdownMenuItem: FC<DropdownMenuItemProps> = (props: DropdownMenuItemProps) => {\n const {\n className,\n ...restProps\n } = props;\n return (<Primitive.Item\n {...restProps}\n className={cn(dropdownItemStyles(), className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuLabel\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const dropdownLabelStyles = cva(cn(\n \"gridui-dropdown-label\",\n \"gridui-u-p-gridui-8 gridui-u-text-muted gridui-u-type-caption\",\n));\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuLabel\n * @description Dropdown Menu Label\n */\n\nimport { dropdownLabelStyles } from \"./style\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuLabelProps = ComponentPropsWithRef<typeof Primitive.Label>;\n\nexport const DropdownMenuLabel: FC<DropdownMenuLabelProps> = (props: DropdownMenuLabelProps) => {\n const {\n className,\n ...restProps\n } = props;\n return (<Primitive.Label\n {...restProps}\n className={cn(dropdownLabelStyles(), className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuRadioGroup\n * @description Dropdown Menu Radio Group\n */\n\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuRadioGroupProps = ComponentPropsWithRef<typeof Primitive.RadioGroup>;\n\nexport const DropdownMenuRadioGroup: FC<DropdownMenuRadioGroupProps> = (props: DropdownMenuRadioGroupProps) => {\n return (<Primitive.RadioGroup\n {...props}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuRadioItem\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const dropdownIndicatorStyles = cva(cn(\n \"gridui-dropdown-indicator\",\n \"gridui-u-w-gridui-16 gridui-u-shrink-0 gridui-u-text-foreground\",\n));\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuRadioItem\n * @description Dropdown Menu Radio Item\n */\n\nimport { dropdownItemStyles } from \"../shared/style\";\nimport { dropdownIndicatorStyles } from \"./style\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport { Check } from \"lucide-react\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuRadioItemProps = ComponentPropsWithRef<typeof Primitive.RadioItem>;\n\nexport const DropdownMenuRadioItem: FC<DropdownMenuRadioItemProps> = (props: DropdownMenuRadioItemProps) => {\n const {\n className,\n children,\n ...restProps\n } = props;\n return (<Primitive.RadioItem\n {...restProps}\n className={cn(dropdownItemStyles(), className)}\n >\n <span\n className={cn(dropdownIndicatorStyles())}\n aria-hidden=\"true\"\n >\n <Primitive.ItemIndicator>\n <Check\n size={16}\n aria-hidden=\"true\"\n />\n </Primitive.ItemIndicator>\n </span>\n {children}\n </Primitive.RadioItem>);\n};\n"],
5
- "mappings": "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",
6
- "names": ["cn", "Primitive", "jsx", "Primitive", "jsx", "jsx", "cn", "cva", "cn", "Primitive", "jsx", "cn", "cva", "cn", "Primitive", "jsx", "Primitive", "jsx", "cn", "cva", "cn", "Primitive", "jsx", "jsxs"]
3
+ "sources": ["../src/dropdown-menu/dropdown-menu.tsx", "../src/dropdown-menu-content/style.ts", "../src/dropdown-menu-content/use-menu-morph.ts", "../src/dropdown-menu-content/dropdown-menu-content.tsx", "../src/dropdown-menu-trigger/dropdown-menu-trigger.tsx", "../src/context-menu/context-menu.tsx", "../src/dropdown-menu-item/dropdown-menu-item.tsx", "../src/dropdown-menu-label/dropdown-menu-label.tsx", "../src/dropdown-menu-radio-group/dropdown-menu-radio-group.tsx", "../src/dropdown-menu-radio-item/dropdown-menu-radio-item.tsx"],
4
+ "sourcesContent": ["/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenu\n * @description Dropdown Menu\n */\n\nimport { OverlayOpen, useOverlayState } from \"@gridui/overlay\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuProps = ComponentPropsWithRef<typeof Primitive.Root>;\n\nexport const DropdownMenu: FC<DropdownMenuProps> = (props: DropdownMenuProps) => {\n const state = useOverlayState(props);\n return (<OverlayOpen.Provider\n value={state.open}\n >\n <Primitive.Root\n {...props}\n {...state}\n />\n </OverlayOpen.Provider>);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuContent\n * @description Style\n */\n\nimport { overlayListStyles } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const dropdownContentStyles = cva(cn(\n overlayListStyles(),\n \"gridui-dropdown-content\",\n \"gridui-u-dropdown-menu--min-w-44 gridui-u-dropdown-menu--max-w-[calc(100vw-2*var(--gridui-page-gutter))] gridui-u-dropdown-menu--max-h-(--radix-dropdown-menu-content-available-height) gridui-u-dropdown-menu--overflow-y-auto\",\n));\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuContent\n * @description Use Menu Morph\n */\n\nimport { useLayoutEffect } from \"react\";\n\nexport const useMenuMorph = (element: HTMLDivElement | null, enabled: boolean): void => {\n useLayoutEffect(() => {\n if (!element || !enabled) {\n return;\n }\n const place = () => {\n // Radix suppresses entrance animations until the menu has been positioned.\n if (element.style.animation === \"none\") {\n return;\n }\n observer.disconnect();\n const document = element.ownerDocument;\n const trigger = document.getElementById(element.getAttribute(\"aria-labelledby\") ?? \"\");\n if (!trigger) {\n return;\n }\n element.setAttribute(\"data-morph-measuring\", \"\");\n const menu = element.getBoundingClientRect();\n element.removeAttribute(\"data-morph-measuring\");\n const anchor = trigger.getBoundingClientRect();\n const width = Math.min(menu.width, anchor.width);\n const height = Math.min(menu.height, anchor.height);\n if (!width || !height) {\n return;\n }\n const x = anchor.left + (anchor.width - width) / 2 - menu.left;\n const y = anchor.top + (anchor.height - height) / 2 - menu.top;\n const left = Math.max(0, Math.min(x, menu.width - width));\n const top = Math.max(0, Math.min(y, menu.height - height));\n element.style.setProperty(\"--gridui-menu-morph-clip\", `inset(${top}px ${menu.width - width - left}px ${menu.height - height - top}px ${left}px)`);\n element.style.setProperty(\"--gridui-menu-morph-offset\", `${x - left}px, ${y - top}px`);\n element.setAttribute(\"data-morph-ready\", \"\");\n };\n const observer = new MutationObserver(place);\n observer.observe(element, {\n attributes: true,\n attributeFilter: [\"style\"],\n });\n place();\n return () => {\n observer.disconnect();\n element.removeAttribute(\"data-morph-ready\");\n element.style.removeProperty(\"--gridui-menu-morph-clip\");\n element.style.removeProperty(\"--gridui-menu-morph-offset\");\n };\n }, [\n element,\n enabled,\n ]);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuContent\n * @description Dropdown Menu Content\n */\n\nimport type { MenuContentOptions } from \"../shared/menu-content-options\";\nimport { dropdownContentStyles } from \"./style\";\nimport { useMenuMorph } from \"./use-menu-morph\";\nimport { interactionLayerProps, OverlayOpen, RetainedLayer, useInteractionOutline, useScrollbars } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { FC } from \"react\";\nimport { useCallback, useContext, useState } from \"react\";\n\nexport type DropdownMenuContentProps = MenuContentOptions;\n\nexport const DropdownMenuContent: FC<DropdownMenuContentProps> = (props: DropdownMenuContentProps) => {\n const {\n className,\n ref: forwardedRef,\n forceMount,\n sideOffset = 8,\n align = \"end\",\n morph = false,\n respectReducedMotion = true,\n ...restProps\n } = props;\n const open = useContext(OverlayOpen);\n const [\n element,\n setElement,\n ] = useState<HTMLDivElement | null>(null);\n const morphRef = useCallback((node: HTMLDivElement | null) => {\n setElement(node);\n if (typeof forwardedRef === \"function\") {\n const cleanup = forwardedRef(node);\n if (cleanup) {\n return () => {\n setElement(null);\n cleanup();\n };\n }\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n return undefined;\n }, [forwardedRef]);\n useMenuMorph(element, morph && open === true);\n const scrollbarRef = useScrollbars({ ref: morph ? morphRef : forwardedRef });\n const ref = useInteractionOutline({\n ref: scrollbarRef,\n selector: '[role^=\"menuitem\"]',\n });\n const content = (<Primitive.Content\n {...interactionLayerProps}\n {...restProps}\n ref={ref}\n forceMount={forceMount}\n align={align}\n sideOffset={sideOffset}\n data-morph-ignore-reduced-motion={!respectReducedMotion || undefined}\n className={cn(dropdownContentStyles(), className)}\n />);\n return (<Primitive.Portal\n forceMount={forceMount}\n >\n {forceMount ? (<RetainedLayer>\n {content}\n </RetainedLayer>) : content}\n </Primitive.Portal>);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuTrigger\n * @description Dropdown Menu Trigger\n */\n\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuTriggerProps = ComponentPropsWithRef<typeof Primitive.Trigger>;\n\nexport const DropdownMenuTrigger: FC<DropdownMenuTriggerProps> = (props: DropdownMenuTriggerProps) => {\n return (<Primitive.Trigger\n {...props}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace ContextMenu\n * @description Context Menu\n */\n\nimport { DropdownMenu, type DropdownMenuProps } from \"../dropdown-menu/dropdown-menu\";\nimport { DropdownMenuContent } from \"../dropdown-menu-content/dropdown-menu-content\";\nimport { DropdownMenuTrigger } from \"../dropdown-menu-trigger/dropdown-menu-trigger\";\nimport type { MenuContentOptions } from \"../shared/menu-content-options\";\nimport { type FC, type ReactNode, useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport type ContextMenuProps = Omit<MenuContentOptions, \"children\"> & Pick<DropdownMenuProps, \"dir\"> & {\n readonly x: number;\n readonly y: number;\n readonly label: string;\n readonly children: ReactNode;\n readonly onClose: () => void;\n};\n\n/** Uses the same menu semantics and presentation as trigger-based dropdowns. */\nexport const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {\n const { x, y, label, dir, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;\n\n const [returnFocus] = useState(() => {\n return typeof document === \"undefined\" ? null : document.activeElement;\n });\n useEffect(() => {\n\n const dismissWhenInactive = () => {\n\n if (!document.hasFocus()) {\n onClose();\n }\n };\n window.addEventListener(\"blur\", dismissWhenInactive);\n\n return () => {\n\n window.removeEventListener(\"blur\", dismissWhenInactive);\n };\n }, [onClose]);\n\n if (typeof document === \"undefined\") {\n return null;\n }\n return createPortal((<DropdownMenu\n key={`${x}:${y}`}\n open\n modal={false}\n dir={dir}\n onOpenChange={open => {\n\n if (!open) {\n onClose();\n }\n }}\n >\n <DropdownMenuTrigger\n asChild\n >\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n style={{\n position: \"fixed\",\n left: x,\n top: y,\n width: 0,\n height: 0,\n padding: 0,\n border: 0,\n opacity: 0,\n pointerEvents: \"none\",\n }}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n aria-label={label}\n side=\"bottom\"\n align=\"start\"\n sideOffset={0}\n collisionPadding={8}\n {...contentProps}\n onPointerUpCapture={event => {\n onPointerUpCapture?.(event);\n // The release that opens a flush context menu must not select its first item.\n if (event.button !== 0 || event.ctrlKey) {\n event.preventDefault();\n }\n }}\n onCloseAutoFocus={event => {\n onCloseAutoFocus?.(event);\n if (event.defaultPrevented) {\n return;\n }\n event.preventDefault();\n if (document.activeElement === document.body\n && returnFocus instanceof HTMLElement\n && returnFocus.isConnected) {\n returnFocus.focus();\n }\n }}\n onKeyDown={event => {\n\n onKeyDown?.(event);\n if (!event.defaultPrevented && event.key === \"Tab\") {\n event.preventDefault();\n onClose();\n }\n }}\n >\n {children}\n </DropdownMenuContent>\n </DropdownMenu>), document.body);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuItem\n * @description Dropdown Menu Item\n */\n\nimport { overlayListItemStyles } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuItemProps = ComponentPropsWithRef<typeof Primitive.Item>;\n\nexport const DropdownMenuItem: FC<DropdownMenuItemProps> = (props: DropdownMenuItemProps) => {\n const {\n className,\n ...restProps\n } = props;\n return (<Primitive.Item\n {...restProps}\n className={cn(overlayListItemStyles(), className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuLabel\n * @description Dropdown Menu Label\n */\n\nimport { overlayListLabelStyles } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuLabelProps = ComponentPropsWithRef<typeof Primitive.Label>;\n\nexport const DropdownMenuLabel: FC<DropdownMenuLabelProps> = (props: DropdownMenuLabelProps) => {\n const {\n className,\n ...restProps\n } = props;\n return (<Primitive.Label\n {...restProps}\n className={cn(overlayListLabelStyles(), className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuRadioGroup\n * @description Dropdown Menu Radio Group\n */\n\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuRadioGroupProps = ComponentPropsWithRef<typeof Primitive.RadioGroup>;\n\nexport const DropdownMenuRadioGroup: FC<DropdownMenuRadioGroupProps> = (props: DropdownMenuRadioGroupProps) => {\n return (<Primitive.RadioGroup\n {...props}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Dropdown Menu\n * @namespace DropdownMenuRadioItem\n * @description Dropdown Menu Radio Item\n */\n\nimport { overlayListIndicatorStyles, overlayListItemStyles } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport * as Primitive from \"@radix-ui/react-dropdown-menu\";\nimport { Check } from \"lucide-react\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type DropdownMenuRadioItemProps = ComponentPropsWithRef<typeof Primitive.RadioItem>;\n\nexport const DropdownMenuRadioItem: FC<DropdownMenuRadioItemProps> = (props: DropdownMenuRadioItemProps) => {\n const {\n className,\n children,\n ...restProps\n } = props;\n return (<Primitive.RadioItem\n {...restProps}\n className={cn(overlayListItemStyles(), className)}\n >\n <span\n className=\"gridui-u-dropdown-menu--flex gridui-u-dropdown-menu--min-w-0 gridui-u-dropdown-menu--flex-1 gridui-u-dropdown-menu--items-center gridui-u-dropdown-menu--gap-gridui-8\"\n >\n {children}\n </span>\n <span\n className={cn(overlayListIndicatorStyles())}\n aria-hidden=\"true\"\n >\n <Primitive.ItemIndicator>\n <Check\n size={16}\n aria-hidden=\"true\"\n />\n </Primitive.ItemIndicator>\n </span>\n </Primitive.RadioItem>);\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["document", "OverlayOpen", "cn", "Primitive", "jsx", "Primitive", "jsx", "useState", "jsx", "cn", "Primitive", "jsx", "cn", "Primitive", "jsx", "Primitive", "jsx", "overlayListItemStyles", "cn", "Primitive", "jsx", "jsxs"]
7
7
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Dropdown Menu
4
+ * @namespace Shared
5
+ * @description Menu Content Options
6
+ */
7
+ import type * as Primitive from "@radix-ui/react-dropdown-menu";
8
+ import type { ComponentPropsWithRef } from "react";
9
+ export type MenuContentOptions = ComponentPropsWithRef<typeof Primitive.Content> & {
10
+ readonly morph?: boolean | undefined;
11
+ readonly respectReducedMotion?: boolean | undefined;
12
+ };
package/dist/styles.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! tailwindcss v4.3.4 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v4.3.5 | MIT License | https://tailwindcss.com */
2
2
  @layer theme, base, components, utilities;
3
3
  @layer theme {
4
4
  :root, :host {
@@ -6,93 +6,61 @@
6
6
  }
7
7
  }
8
8
  @layer utilities {
9
- .gridui-u-z-\(--gridui-z-popover\) {
10
- z-index: var(--gridui-z-popover);
11
- }
12
- .gridui-u-flex {
9
+ .gridui-u-dropdown-menu--flex {
13
10
  display: flex;
14
11
  }
15
- .gridui-u-max-h-\(--radix-dropdown-menu-content-available-height\) {
12
+ .gridui-u-dropdown-menu--max-h-\(--radix-dropdown-menu-content-available-height\) {
16
13
  max-height: var(--radix-dropdown-menu-content-available-height);
17
14
  }
18
- .gridui-u-min-h-10 {
19
- min-height: calc(var(--spacing) * 10);
20
- }
21
- .gridui-u-w-gridui-16 {
22
- width: var(--gridui-space-16);
23
- }
24
- .gridui-u-max-w-\[calc\(100vw-2\*var\(--gridui-page-gutter\)\)\] {
15
+ .gridui-u-dropdown-menu--max-w-\[calc\(100vw-2\*var\(--gridui-page-gutter\)\)\] {
25
16
  max-width: calc(100vw - 2 * var(--gridui-page-gutter));
26
17
  }
27
- .gridui-u-min-w-44 {
28
- min-width: calc(var(--spacing) * 44);
18
+ .gridui-u-dropdown-menu--min-w-0 {
19
+ min-width: 0px;
29
20
  }
30
- .gridui-u-shrink-0 {
31
- flex-shrink: 0;
21
+ .gridui-u-dropdown-menu--min-w-44 {
22
+ min-width: calc(var(--spacing) * 44);
32
23
  }
33
- .gridui-u-cursor-pointer {
34
- cursor: pointer;
24
+ .gridui-u-dropdown-menu--flex-1 {
25
+ flex: 1;
35
26
  }
36
- .gridui-u-items-center {
27
+ .gridui-u-dropdown-menu--items-center {
37
28
  align-items: center;
38
29
  }
39
- .gridui-u-gap-gridui-8 {
30
+ .gridui-u-dropdown-menu--gap-gridui-8 {
40
31
  gap: var(--gridui-space-8);
41
32
  }
42
- .gridui-u-overflow-y-auto {
33
+ .gridui-u-dropdown-menu--overflow-y-auto {
43
34
  overflow-y: auto;
44
35
  }
45
- .gridui-u-rounded-control {
46
- border-radius: var(--gridui-control-radius);
47
- }
48
- .gridui-u-p-0 {
49
- padding: 0px;
50
- }
51
- .gridui-u-p-gridui-8 {
52
- padding: var(--gridui-space-8);
53
- }
54
- .gridui-u-px-gridui-8 {
55
- padding-inline: var(--gridui-space-8);
56
- }
57
- .gridui-u-py-gridui-8 {
58
- padding-block: var(--gridui-space-8);
59
- }
60
- .gridui-u-type-data {
61
- font: var(--gridui-type-data);
62
- letter-spacing: normal;
63
- font-variant-numeric: tabular-nums;
64
- }
65
- .gridui-u-type-caption {
66
- font: var(--gridui-type-caption);
67
- letter-spacing: normal;
68
- }
69
- .gridui-u-text-foreground {
70
- color: var(--gridui-foreground);
71
- }
72
- .gridui-u-text-inherit {
73
- color: inherit;
74
- }
75
- .gridui-u-text-muted {
76
- color: var(--gridui-muted);
77
- }
78
- .gridui-u-no-underline {
79
- text-decoration-line: none;
80
- }
81
- .gridui-u-aria-selected\:bg-brand-tint[aria-selected="true"] {
82
- background-color: var(--gridui-brand-tint);
83
- }
84
- .gridui-u-data-disabled\:pointer-events-none[data-disabled] {
85
- pointer-events: none;
86
- }
87
- .gridui-u-data-disabled\:opacity-50[data-disabled] {
88
- opacity: 50%;
89
- }
90
- .gridui-u-data-\[state\=checked\]\:bg-brand-tint[data-state="checked"] {
91
- background-color: var(--gridui-brand-tint);
92
- }
93
36
  }
94
37
  @layer components {
95
38
  .gridui-dropdown-content {
96
39
  --gridui-overlay-origin: var(--radix-dropdown-menu-content-transform-origin);
97
40
  }
41
+ .gridui-dropdown-content[data-morph-measuring][data-state="open"] {
42
+ animation: none;
43
+ }
44
+ @supports (clip-path: inset(0)) {
45
+ .gridui-dropdown-content[data-morph-ready][data-state="open"] {
46
+ animation: gridui-menu-morph var(--gridui-motion-duration-normal) var(--gridui-motion-ease-out);
47
+ }
48
+ }
49
+ @media (prefers-reduced-motion: reduce) {
50
+ .gridui-dropdown-content[data-morph-ready][data-state="open"]:not([data-morph-ignore-reduced-motion]) {
51
+ animation: none;
52
+ }
53
+ }
54
+ @keyframes gridui-menu-morph {
55
+ from {
56
+ clip-path: var(--gridui-menu-morph-clip);
57
+ opacity: 0.6;
58
+ transform: translate(var(--gridui-menu-morph-offset));
59
+ }
60
+ to {
61
+ clip-path: inset(0);
62
+ opacity: 1;
63
+ transform: translate(0, 0);
64
+ }
65
+ }
98
66
  }
package/docs/catalog.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "name": "@gridui/dropdown-menu",
4
- "version": "1.1.7",
4
+ "version": "2.0.0",
5
5
  "category": "core",
6
6
  "description": "GridUI React dropdown menu",
7
- "usage": "`@gridui/dropdown-menu` wraps Radix Dropdown Menu. It exports the root, trigger, portalled content, items, label, radio group, and radio item. Native primitive props and refs remain available. Load its separate `styles.css` export. Radix owns keyboard navigation, focus return, Escape dismissal, and viewport collisions. The portal avoids clipped grid boundaries.",
7
+ "usage": "Overlay supplies popup surfaces, option rows, group labels, and selection indicators. Applications own routes, labels, state persistence, and branding.",
8
8
  "documentation": [
9
9
  "README.md",
10
10
  "docs/context-menu.md"
@@ -25,21 +25,6 @@
25
25
  "kind": "value",
26
26
  "importPath": "@gridui/dropdown-menu"
27
27
  },
28
- {
29
- "name": "dropdownIndicatorStyles",
30
- "kind": "value",
31
- "importPath": "@gridui/dropdown-menu"
32
- },
33
- {
34
- "name": "dropdownItemStyles",
35
- "kind": "value",
36
- "importPath": "@gridui/dropdown-menu"
37
- },
38
- {
39
- "name": "dropdownLabelStyles",
40
- "kind": "value",
41
- "importPath": "@gridui/dropdown-menu"
42
- },
43
28
  {
44
29
  "name": "DropdownMenu",
45
30
  "kind": "component",
@@ -2,13 +2,23 @@
2
2
 
3
3
  Import `ContextMenu`, `ContextMenuProps`, and the existing `DropdownMenuItem`,
4
4
  `DropdownMenuRadioGroup`, `DropdownMenuRadioItem`, and `DropdownMenuLabel` from
5
- `@gridui/dropdown-menu`. Load `@gridui/dropdown-menu/styles.css` after Theme.
5
+ `@gridui/dropdown-menu`. Load these styles in order:
6
+
7
+ ```css
8
+ @import "@gridui/theme/styles.css";
9
+ @import "@gridui/overlay/styles.css";
10
+ @import "@gridui/dropdown-menu/styles.css";
11
+ ```
12
+
13
+ Overlay supplies the shared menu surface, option rows, labels, and indicators.
6
14
 
7
15
  Render `ContextMenu` only while open. Pass viewport `x` / `y` coordinates (for
8
16
  example, `clientX` / `clientY`), an accessible `label`, menu children, and `onClose`
9
17
  to clear the owner's open state. The owner decides which pointer or keyboard
10
18
  interaction opens the menu and what each action does. For keyboard opening,
11
- anchor to the invoking element's bounding rectangle.
19
+ anchor to the invoking element's bounding rectangle. Pass `dir="rtl"` for a
20
+ right-to-left menu; direction is forwarded to the menu root for positioning,
21
+ row layout, and keyboard behavior.
12
22
 
13
23
  The menu reuses dropdown keyboard navigation, disabled-item semantics, collision
14
24
  handling, and item selection. It is nonmodal, closes on Escape, Tab, outside
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridui/dropdown-menu",
3
- "version": "1.1.7",
3
+ "version": "2.0.0",
4
4
  "description": "GridUI React dropdown menu",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -27,16 +27,16 @@
27
27
  "react-dom": "^19.2.0"
28
28
  },
29
29
  "dependencies": {
30
- "@gridui/overlay": "^1.2.2",
31
- "@gridui/style-utils": "^2.2.2",
30
+ "@gridui/overlay": "^2.0.0",
31
+ "@gridui/style-utils": "^3.0.0",
32
32
  "@gridui/theme": "^2.5.3",
33
33
  "@radix-ui/react-dropdown-menu": "2.2.1",
34
34
  "class-variance-authority": "0.7.1",
35
- "lucide-react": "1.69.0"
35
+ "lucide-react": "1.70.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@gridui-internal/configuration": "0.0.0-internal",
39
- "@gridui/button": "3.1.2",
39
+ "@gridui/button": "4.0.0",
40
40
  "@jest/globals": "30.5.2",
41
41
  "@storybook/react-vite": "10.6.6",
42
42
  "@types/jest": "30.0.0",
@@ -1,7 +0,0 @@
1
- /**
2
- * @author WMXPY
3
- * @package Dropdown Menu
4
- * @namespace DropdownMenuLabel
5
- * @description Style
6
- */
7
- export declare const dropdownLabelStyles: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
@@ -1,7 +0,0 @@
1
- /**
2
- * @author WMXPY
3
- * @package Dropdown Menu
4
- * @namespace DropdownMenuRadioItem
5
- * @description Style
6
- */
7
- export declare const dropdownIndicatorStyles: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
@@ -1,7 +0,0 @@
1
- /**
2
- * @author WMXPY
3
- * @package Dropdown Menu
4
- * @namespace Shared
5
- * @description Style
6
- */
7
- export declare const dropdownItemStyles: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;