@gridui/dropdown-menu 1.2.0 → 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 +23 -6
- package/dist/context-menu/context-menu.d.ts +2 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +24 -43
- package/dist/index.js.map +4 -4
- package/dist/styles.css +12 -69
- package/docs/catalog.json +2 -17
- package/docs/context-menu.md +12 -2
- package/package.json +4 -4
- package/dist/dropdown-menu-label/style.d.ts +0 -7
- package/dist/dropdown-menu-radio-item/style.d.ts +0 -7
- package/dist/shared/style.d.ts +0 -7
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
|
|
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
|
|
6
|
-
|
|
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
|
-
|
|
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
|
|
@@ -34,6 +42,15 @@ 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.
|
|
36
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
|
+
|
|
37
51
|
Set `morph` on `DropdownMenuContent` to expand the menu from its trigger
|
|
38
52
|
when opening. `respectReducedMotion` defaults to `true`. Set it to `false`
|
|
39
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 DropdownMenuProps } from "../dropdown-menu/dropdown-menu";
|
|
7
8
|
import type { MenuContentOptions } from "../shared/menu-content-options";
|
|
8
9
|
import { type FC, type ReactNode } from "react";
|
|
9
|
-
export type ContextMenuProps = Omit<MenuContentOptions, "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;
|
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,13 +20,13 @@ var DropdownMenu = (props) => {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
// src/dropdown-menu-content/style.ts
|
|
23
|
-
import {
|
|
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
|
-
|
|
27
|
+
overlayListStyles(),
|
|
28
28
|
"gridui-dropdown-content",
|
|
29
|
-
"gridui-u-
|
|
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
32
|
// src/dropdown-menu-content/use-menu-morph.ts
|
|
@@ -163,7 +163,7 @@ import { useEffect, useState as useState2 } from "react";
|
|
|
163
163
|
import { createPortal } from "react-dom";
|
|
164
164
|
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
165
165
|
var ContextMenu = (props) => {
|
|
166
|
-
const { x, y, label, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;
|
|
166
|
+
const { x, y, label, dir, children, onClose, onCloseAutoFocus, onKeyDown, onPointerUpCapture, ...contentProps } = props;
|
|
167
167
|
const [returnFocus] = useState2(() => {
|
|
168
168
|
return typeof document === "undefined" ? null : document.activeElement;
|
|
169
169
|
});
|
|
@@ -186,6 +186,7 @@ var ContextMenu = (props) => {
|
|
|
186
186
|
{
|
|
187
187
|
open: true,
|
|
188
188
|
modal: false,
|
|
189
|
+
dir,
|
|
189
190
|
onOpenChange: (open) => {
|
|
190
191
|
if (!open) {
|
|
191
192
|
onClose();
|
|
@@ -258,18 +259,9 @@ var ContextMenu = (props) => {
|
|
|
258
259
|
), document.body);
|
|
259
260
|
};
|
|
260
261
|
|
|
261
|
-
// src/shared/style.ts
|
|
262
|
-
import { cn as cn3 } from "@gridui/style-utils";
|
|
263
|
-
import { cva as cva2 } from "class-variance-authority";
|
|
264
|
-
var dropdownItemStyles = cva2(cn3(
|
|
265
|
-
"gridui-dropdown-item",
|
|
266
|
-
"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",
|
|
267
|
-
"gridui-u-data-[state=checked]:bg-brand-tint gridui-u-aria-selected:bg-brand-tint",
|
|
268
|
-
"gridui-u-data-disabled:opacity-50 gridui-u-data-disabled:pointer-events-none"
|
|
269
|
-
));
|
|
270
|
-
|
|
271
262
|
// src/dropdown-menu-item/dropdown-menu-item.tsx
|
|
272
|
-
import {
|
|
263
|
+
import { overlayListItemStyles } from "@gridui/overlay";
|
|
264
|
+
import { cn as cn3 } from "@gridui/style-utils";
|
|
273
265
|
import * as Primitive4 from "@radix-ui/react-dropdown-menu";
|
|
274
266
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
275
267
|
var DropdownMenuItem = (props) => {
|
|
@@ -281,21 +273,14 @@ var DropdownMenuItem = (props) => {
|
|
|
281
273
|
Primitive4.Item,
|
|
282
274
|
{
|
|
283
275
|
...restProps,
|
|
284
|
-
className:
|
|
276
|
+
className: cn3(overlayListItemStyles(), className)
|
|
285
277
|
}
|
|
286
278
|
);
|
|
287
279
|
};
|
|
288
280
|
|
|
289
|
-
// src/dropdown-menu-label/style.ts
|
|
290
|
-
import { cn as cn5 } from "@gridui/style-utils";
|
|
291
|
-
import { cva as cva3 } from "class-variance-authority";
|
|
292
|
-
var dropdownLabelStyles = cva3(cn5(
|
|
293
|
-
"gridui-dropdown-label",
|
|
294
|
-
"gridui-u-p-gridui-8 gridui-u-text-muted gridui-u-type-caption"
|
|
295
|
-
));
|
|
296
|
-
|
|
297
281
|
// src/dropdown-menu-label/dropdown-menu-label.tsx
|
|
298
|
-
import {
|
|
282
|
+
import { overlayListLabelStyles } from "@gridui/overlay";
|
|
283
|
+
import { cn as cn4 } from "@gridui/style-utils";
|
|
299
284
|
import * as Primitive5 from "@radix-ui/react-dropdown-menu";
|
|
300
285
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
301
286
|
var DropdownMenuLabel = (props) => {
|
|
@@ -307,7 +292,7 @@ var DropdownMenuLabel = (props) => {
|
|
|
307
292
|
Primitive5.Label,
|
|
308
293
|
{
|
|
309
294
|
...restProps,
|
|
310
|
-
className:
|
|
295
|
+
className: cn4(overlayListLabelStyles(), className)
|
|
311
296
|
}
|
|
312
297
|
);
|
|
313
298
|
};
|
|
@@ -324,16 +309,9 @@ var DropdownMenuRadioGroup = (props) => {
|
|
|
324
309
|
);
|
|
325
310
|
};
|
|
326
311
|
|
|
327
|
-
// src/dropdown-menu-radio-item/style.ts
|
|
328
|
-
import { cn as cn7 } from "@gridui/style-utils";
|
|
329
|
-
import { cva as cva4 } from "class-variance-authority";
|
|
330
|
-
var dropdownIndicatorStyles = cva4(cn7(
|
|
331
|
-
"gridui-dropdown-indicator",
|
|
332
|
-
"gridui-u-w-gridui-16 gridui-u-shrink-0 gridui-u-text-foreground"
|
|
333
|
-
));
|
|
334
|
-
|
|
335
312
|
// src/dropdown-menu-radio-item/dropdown-menu-radio-item.tsx
|
|
336
|
-
import {
|
|
313
|
+
import { overlayListIndicatorStyles, overlayListItemStyles as overlayListItemStyles2 } from "@gridui/overlay";
|
|
314
|
+
import { cn as cn5 } from "@gridui/style-utils";
|
|
337
315
|
import * as Primitive7 from "@radix-ui/react-dropdown-menu";
|
|
338
316
|
import { Check } from "lucide-react";
|
|
339
317
|
import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -347,12 +325,19 @@ var DropdownMenuRadioItem = (props) => {
|
|
|
347
325
|
Primitive7.RadioItem,
|
|
348
326
|
{
|
|
349
327
|
...restProps,
|
|
350
|
-
className:
|
|
328
|
+
className: cn5(overlayListItemStyles2(), className),
|
|
351
329
|
children: [
|
|
352
330
|
/* @__PURE__ */ jsx8(
|
|
353
331
|
"span",
|
|
354
332
|
{
|
|
355
|
-
className:
|
|
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()),
|
|
356
341
|
"aria-hidden": "true",
|
|
357
342
|
children: /* @__PURE__ */ jsx8(Primitive7.ItemIndicator, { children: /* @__PURE__ */ jsx8(
|
|
358
343
|
Check,
|
|
@@ -362,8 +347,7 @@ var DropdownMenuRadioItem = (props) => {
|
|
|
362
347
|
}
|
|
363
348
|
) })
|
|
364
349
|
}
|
|
365
|
-
)
|
|
366
|
-
children
|
|
350
|
+
)
|
|
367
351
|
]
|
|
368
352
|
}
|
|
369
353
|
);
|
|
@@ -377,9 +361,6 @@ export {
|
|
|
377
361
|
DropdownMenuRadioGroup,
|
|
378
362
|
DropdownMenuRadioItem,
|
|
379
363
|
DropdownMenuTrigger,
|
|
380
|
-
dropdownContentStyles
|
|
381
|
-
dropdownIndicatorStyles,
|
|
382
|
-
dropdownItemStyles,
|
|
383
|
-
dropdownLabelStyles
|
|
364
|
+
dropdownContentStyles
|
|
384
365
|
};
|
|
385
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/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/
|
|
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 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 } 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\"> & {\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": ";AAOA,SAAS,aAAa,uBAAuB;AAC7C,YAAY,eAAe;AAUnB;AALD,IAAM,eAAsC,CAAC,UAA6B;AAC7E,QAAM,QAAQ,gBAAgB,KAAK;AACnC,SAAQ;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACL,OAAO,MAAM;AAAA,MAEb;AAAA,QAAW;AAAA,QAAV;AAAA,UACI,GAAG;AAAA,UACH,GAAG;AAAA;AAAA,MACR;AAAA;AAAA,EACJ;AACJ;;;AChBA,SAAS,
|
|
6
|
-
"names": ["document", "OverlayOpen", "cn", "Primitive", "jsx", "Primitive", "jsx", "useState", "jsx", "cn", "
|
|
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
|
}
|
package/dist/styles.css
CHANGED
|
@@ -6,90 +6,33 @@
|
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
@layer utilities {
|
|
9
|
-
.gridui-u-
|
|
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-
|
|
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-
|
|
28
|
-
min-width:
|
|
18
|
+
.gridui-u-dropdown-menu--min-w-0 {
|
|
19
|
+
min-width: 0px;
|
|
29
20
|
}
|
|
30
|
-
.gridui-u-
|
|
31
|
-
|
|
21
|
+
.gridui-u-dropdown-menu--min-w-44 {
|
|
22
|
+
min-width: calc(var(--spacing) * 44);
|
|
32
23
|
}
|
|
33
|
-
.gridui-u-
|
|
34
|
-
|
|
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 {
|
package/docs/catalog.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"name": "@gridui/dropdown-menu",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"category": "core",
|
|
6
6
|
"description": "GridUI React dropdown menu",
|
|
7
|
-
"usage": "
|
|
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",
|
package/docs/context-menu.md
CHANGED
|
@@ -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
|
|
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": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "GridUI React dropdown menu",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"react-dom": "^19.2.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@gridui/overlay": "^
|
|
31
|
-
"@gridui/style-utils": "^
|
|
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",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@gridui-internal/configuration": "0.0.0-internal",
|
|
39
|
-
"@gridui/button": "
|
|
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",
|