@graundtech/fluent2-react-kit 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/dist/components/ui/accordion.d.ts +133 -0
  4. package/dist/components/ui/accordion.js +80 -0
  5. package/dist/components/ui/accordion.js.map +1 -0
  6. package/dist/components/ui/alert.d.ts +106 -0
  7. package/dist/components/ui/alert.js +73 -0
  8. package/dist/components/ui/alert.js.map +1 -0
  9. package/dist/components/ui/avatar.d.ts +42 -0
  10. package/dist/components/ui/avatar.js +55 -0
  11. package/dist/components/ui/avatar.js.map +1 -0
  12. package/dist/components/ui/badge.d.ts +36 -0
  13. package/dist/components/ui/badge.js +81 -0
  14. package/dist/components/ui/badge.js.map +1 -0
  15. package/dist/components/ui/breadcrumb.d.ts +53 -0
  16. package/dist/components/ui/breadcrumb.js +149 -0
  17. package/dist/components/ui/breadcrumb.js.map +1 -0
  18. package/dist/components/ui/button.d.ts +24 -0
  19. package/dist/components/ui/button.js +86 -0
  20. package/dist/components/ui/button.js.map +1 -0
  21. package/dist/components/ui/card.d.ts +51 -0
  22. package/dist/components/ui/card.js +97 -0
  23. package/dist/components/ui/card.js.map +1 -0
  24. package/dist/components/ui/checkbox.d.ts +101 -0
  25. package/dist/components/ui/checkbox.js +57 -0
  26. package/dist/components/ui/checkbox.js.map +1 -0
  27. package/dist/components/ui/combobox.d.ts +212 -0
  28. package/dist/components/ui/combobox.js +236 -0
  29. package/dist/components/ui/combobox.js.map +1 -0
  30. package/dist/components/ui/command.d.ts +187 -0
  31. package/dist/components/ui/command.js +225 -0
  32. package/dist/components/ui/command.js.map +1 -0
  33. package/dist/components/ui/dialog.d.ts +117 -0
  34. package/dist/components/ui/dialog.js +165 -0
  35. package/dist/components/ui/dialog.js.map +1 -0
  36. package/dist/components/ui/dropdown-menu.d.ts +155 -0
  37. package/dist/components/ui/dropdown-menu.js +295 -0
  38. package/dist/components/ui/dropdown-menu.js.map +1 -0
  39. package/dist/components/ui/input.d.ts +44 -0
  40. package/dist/components/ui/input.js +43 -0
  41. package/dist/components/ui/input.js.map +1 -0
  42. package/dist/components/ui/label.d.ts +39 -0
  43. package/dist/components/ui/label.js +30 -0
  44. package/dist/components/ui/label.js.map +1 -0
  45. package/dist/components/ui/link.d.ts +62 -0
  46. package/dist/components/ui/link.js +61 -0
  47. package/dist/components/ui/link.js.map +1 -0
  48. package/dist/components/ui/multi-select.d.ts +115 -0
  49. package/dist/components/ui/multi-select.js +133 -0
  50. package/dist/components/ui/multi-select.js.map +1 -0
  51. package/dist/components/ui/pagination.d.ts +46 -0
  52. package/dist/components/ui/pagination.js +164 -0
  53. package/dist/components/ui/pagination.js.map +1 -0
  54. package/dist/components/ui/popover.d.ts +117 -0
  55. package/dist/components/ui/popover.js +62 -0
  56. package/dist/components/ui/popover.js.map +1 -0
  57. package/dist/components/ui/progress.d.ts +98 -0
  58. package/dist/components/ui/progress.js +67 -0
  59. package/dist/components/ui/progress.js.map +1 -0
  60. package/dist/components/ui/radio-group.d.ts +94 -0
  61. package/dist/components/ui/radio-group.js +65 -0
  62. package/dist/components/ui/radio-group.js.map +1 -0
  63. package/dist/components/ui/select.d.ts +145 -0
  64. package/dist/components/ui/select.js +240 -0
  65. package/dist/components/ui/select.js.map +1 -0
  66. package/dist/components/ui/separator.d.ts +43 -0
  67. package/dist/components/ui/separator.js +27 -0
  68. package/dist/components/ui/separator.js.map +1 -0
  69. package/dist/components/ui/skeleton.d.ts +81 -0
  70. package/dist/components/ui/skeleton.js +24 -0
  71. package/dist/components/ui/skeleton.js.map +1 -0
  72. package/dist/components/ui/spinner.d.ts +56 -0
  73. package/dist/components/ui/spinner.js +83 -0
  74. package/dist/components/ui/spinner.js.map +1 -0
  75. package/dist/components/ui/switch.d.ts +60 -0
  76. package/dist/components/ui/switch.js +63 -0
  77. package/dist/components/ui/switch.js.map +1 -0
  78. package/dist/components/ui/tabs.d.ts +107 -0
  79. package/dist/components/ui/tabs.js +102 -0
  80. package/dist/components/ui/tabs.js.map +1 -0
  81. package/dist/components/ui/textarea.d.ts +28 -0
  82. package/dist/components/ui/textarea.js +36 -0
  83. package/dist/components/ui/textarea.js.map +1 -0
  84. package/dist/components/ui/toast.d.ts +185 -0
  85. package/dist/components/ui/toast.js +181 -0
  86. package/dist/components/ui/toast.js.map +1 -0
  87. package/dist/components/ui/tooltip.d.ts +115 -0
  88. package/dist/components/ui/tooltip.js +72 -0
  89. package/dist/components/ui/tooltip.js.map +1 -0
  90. package/dist/index.d.ts +55 -0
  91. package/dist/index.js +284 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/lib/utils.d.ts +9 -0
  94. package/dist/lib/utils.js +9 -0
  95. package/dist/lib/utils.js.map +1 -0
  96. package/package.json +77 -0
  97. package/src/styles/tokens.css +596 -0
  98. package/src/styles/tokens.test.ts +216 -0
@@ -0,0 +1,165 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
4
+ import { DismissRegular } from "@fluentui/react-icons";
5
+ import { cn } from "../../lib/utils.js";
6
+ function Dialog(props) {
7
+ return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...props });
8
+ }
9
+ function DialogTrigger({
10
+ className,
11
+ ...props
12
+ }) {
13
+ return /* @__PURE__ */ jsx(
14
+ DialogPrimitive.Trigger,
15
+ {
16
+ "data-slot": "dialog-trigger",
17
+ className: cn(className),
18
+ ...props
19
+ }
20
+ );
21
+ }
22
+ function DialogPortal(props) {
23
+ return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
24
+ }
25
+ function DialogOverlay({
26
+ className,
27
+ ...props
28
+ }) {
29
+ return /* @__PURE__ */ jsx(
30
+ DialogPrimitive.Backdrop,
31
+ {
32
+ "data-slot": "dialog-overlay",
33
+ className: cn(
34
+ "fixed inset-0 z-50 bg-black/40",
35
+ // motion — fade on open (enter) / close (exit)
36
+ "transition-opacity duration-normal ease-decelerate-mid",
37
+ "data-starting-style:opacity-0",
38
+ "data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid",
39
+ className
40
+ ),
41
+ ...props
42
+ }
43
+ );
44
+ }
45
+ function DialogContent({
46
+ className,
47
+ children,
48
+ showCloseButton = true,
49
+ ...props
50
+ }) {
51
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [
52
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
53
+ /* @__PURE__ */ jsxs(
54
+ DialogPrimitive.Popup,
55
+ {
56
+ "data-slot": "dialog-content",
57
+ className: cn(
58
+ // layout — centered fixed surface, dialog radius + elevation
59
+ "fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border bg-background p-6 text-foreground shadow-64 outline-none",
60
+ // motion — fade + slight zoom; `scale`, not `transform` (see doc note)
61
+ "transition-[opacity,scale] duration-normal ease-decelerate-mid",
62
+ "data-starting-style:scale-95 data-starting-style:opacity-0",
63
+ "data-ending-style:scale-95 data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid",
64
+ className
65
+ ),
66
+ ...props,
67
+ children: [
68
+ children,
69
+ showCloseButton && /* @__PURE__ */ jsxs(
70
+ DialogPrimitive.Close,
71
+ {
72
+ "data-slot": "dialog-close",
73
+ className: cn(
74
+ "absolute top-4 right-4 flex size-8 items-center justify-center rounded-md text-muted-foreground",
75
+ "cursor-pointer outline-none transition-colors duration-fast ease-ease",
76
+ "hover:bg-accent hover:text-accent-foreground active:bg-accent/80 dark:hover:bg-accent/50 dark:active:bg-accent/70",
77
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
78
+ "disabled:pointer-events-none disabled:opacity-50"
79
+ ),
80
+ children: [
81
+ /* @__PURE__ */ jsx(DismissRegular, { className: "size-4" }),
82
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
83
+ ]
84
+ }
85
+ )
86
+ ]
87
+ }
88
+ )
89
+ ] });
90
+ }
91
+ function DialogHeader({ className, ...props }) {
92
+ return /* @__PURE__ */ jsx(
93
+ "div",
94
+ {
95
+ "data-slot": "dialog-header",
96
+ className: cn("flex flex-col gap-1.5 text-center sm:text-left", className),
97
+ ...props
98
+ }
99
+ );
100
+ }
101
+ function DialogFooter({ className, ...props }) {
102
+ return /* @__PURE__ */ jsx(
103
+ "div",
104
+ {
105
+ "data-slot": "dialog-footer",
106
+ className: cn(
107
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
108
+ className
109
+ ),
110
+ ...props
111
+ }
112
+ );
113
+ }
114
+ function DialogTitle({
115
+ className,
116
+ ...props
117
+ }) {
118
+ return /* @__PURE__ */ jsx(
119
+ DialogPrimitive.Title,
120
+ {
121
+ "data-slot": "dialog-title",
122
+ className: cn("text-xl font-semibold", className),
123
+ ...props
124
+ }
125
+ );
126
+ }
127
+ function DialogDescription({
128
+ className,
129
+ ...props
130
+ }) {
131
+ return /* @__PURE__ */ jsx(
132
+ DialogPrimitive.Description,
133
+ {
134
+ "data-slot": "dialog-description",
135
+ className: cn("text-sm text-muted-foreground", className),
136
+ ...props
137
+ }
138
+ );
139
+ }
140
+ function DialogClose({
141
+ className,
142
+ ...props
143
+ }) {
144
+ return /* @__PURE__ */ jsx(
145
+ DialogPrimitive.Close,
146
+ {
147
+ "data-slot": "dialog-close",
148
+ className: cn(className),
149
+ ...props
150
+ }
151
+ );
152
+ }
153
+ export {
154
+ Dialog,
155
+ DialogClose,
156
+ DialogContent,
157
+ DialogDescription,
158
+ DialogFooter,
159
+ DialogHeader,
160
+ DialogOverlay,
161
+ DialogPortal,
162
+ DialogTitle,
163
+ DialogTrigger
164
+ };
165
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/ui/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\";\nimport { DismissRegular } from \"@fluentui/react-icons\";\nimport type { ComponentProps } from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\n/**\n * Dialog — Fluent 2-styled, shadcn-API modal dialog.\n *\n * Follows the overlay patterns set by `select.tsx` (portal → popup surface,\n * `data-starting-style`/`data-ending-style` motion with token durations and\n * easings) with dialog-specific elevation: `shadow-64` + `rounded-xl`\n * (conventions §3.4/§3.6 — dialogs are the kit's highest floating surface).\n *\n * ## Base UI mapping (conventions §9)\n * Behavior — focus trapping, portalling, open/close state, scroll locking,\n * outside-press and Escape dismissal — genuinely needs a primitive, so the\n * parts wrap `@base-ui/react/dialog` (namespace import, matching the actual\n * export shape in node_modules, exactly like `select.tsx`). shadcn part names\n * are mapped onto Base UI's model:\n *\n * | Exported (shadcn name) | Base UI primitive |\n * | ---------------------- | --------------------------------------------------- |\n * | `Dialog` | `Dialog.Root` |\n * | `DialogTrigger` | `Dialog.Trigger` |\n * | `DialogPortal` | `Dialog.Portal` |\n * | `DialogOverlay` | `Dialog.Backdrop` ← see divergence 1 |\n * | `DialogContent` | `Dialog.Portal` + `Dialog.Backdrop` + `Dialog.Popup` (+ built-in ✕ `Dialog.Close`) |\n * | `DialogHeader` | plain `<div>` (shadcn parity — no Base UI part) |\n * | `DialogFooter` | plain `<div>` (shadcn parity — no Base UI part) |\n * | `DialogTitle` | `Dialog.Title` (renders `<h2>`) |\n * | `DialogDescription` | `Dialog.Description` (renders `<p>`) |\n * | `DialogClose` | `Dialog.Close` |\n *\n * Base UI wires the popup's `aria-labelledby` to `DialogTitle` and\n * `aria-describedby` to `DialogDescription` automatically — no manual ids.\n *\n * ## Divergences from the shadcn/Radix Dialog API (all deliberate)\n * 1. **`DialogOverlay` wraps Base UI `Dialog.Backdrop`, not a Radix `Overlay`.**\n * Same role (the dimming layer under the popup), different primitive name.\n * Note Base UI skips rendering the backdrop for *nested* dialogs unless\n * `forceRender` is set — parent smoke already covers the viewport.\n * 2. **`modal` defaults to `true`** (focus trap + page scroll lock + outside\n * pointer interactions disabled), matching Radix. Base UI adds a third mode,\n * `modal=\"trap-focus\"` (trap focus without scroll lock), which passes\n * straight through.\n * 3. **`DialogContent` composes `Portal` + `Backdrop` + `Popup`** and appends a\n * top-right ✕ close button (shadcn parity — shadcn composes the same three\n * Radix parts). Pass `showCloseButton={false}` to omit the ✕ (matching\n * current shadcn's `DialogContent` prop).\n * 4. **No `asChild`.** Base UI composes via the `render` prop instead — e.g.\n * `<DialogTrigger render={<Button variant=\"secondary\" />}>Open</DialogTrigger>`.\n * Every part forwards it.\n * 5. **`onOpenChange(open, eventDetails)`** — Base UI passes a second\n * `eventDetails` argument (reason + native event). The first argument is the\n * boolean Radix passes, so existing shadcn call sites work unchanged.\n * 6. **`Dialog.Viewport` is not re-exported.** It's a Base UI layout helper for\n * scrollable full-viewport dialogs with no shadcn equivalent; the kit centers\n * the popup with fixed positioning like shadcn. Compose it manually from\n * `@base-ui/react/dialog` if you need it.\n *\n * ## Smoke layer (`bg-black/40`) — sanctioned hardcoded color\n * The backdrop is black at 40% opacity in *both* themes, per Fluent's smoke\n * layer (it dims light and dark surfaces alike). Conventions §3.7 bans\n * hardcoded colors so a shade can't drift from the token set, but the smoke\n * layer is intentionally theme-invariant — there is no token for it and\n * inventing one would imply it re-points in dark mode, which it must not.\n * `bg-black/40` is the sanctioned exception here.\n *\n * ## Motion note — the popup zoom animates `scale`, not `transform`\n * Tailwind v4 emits `translate-*` and `scale-*` as the independent CSS\n * `translate:`/`scale:` properties (not a shared `transform:`), so the\n * -50%/-50% centering translate and the open/close zoom coexist without\n * clobbering each other — but it also means the popup's transition must target\n * `transition-[opacity,scale]` (a `transition-[transform,opacity]` list would\n * leave the zoom snapping — every popup in the kit uses `[opacity,scale]` for\n * this reason).\n *\n * ## `\"use client\"` — required\n * Two reasons. The Base UI Dialog parts manage client state (each part module\n * carries its own `'use client'`), and — decisively — `DismissRegular` from\n * `@fluentui/react-icons` must stay inside a client boundary: the package's\n * shared icon-sizing module calls `@griffel/react`'s client-only `__styles()`\n * at module scope without its own directive, so importing an icon from a\n * Server Component breaks `next build`. See conventions §9; `select.tsx` and\n * `checkbox.tsx` are the precedents.\n *\n * ## data-slot note\n * `Dialog` (Root) renders no DOM element of its own, so it carries no\n * `data-slot`. Every part that renders an element does — `dialog-trigger`,\n * `dialog-overlay`, `dialog-content`, etc.\n */\n\nfunction Dialog<Payload>(props: DialogPrimitive.Root.Props<Payload>) {\n return <DialogPrimitive.Root {...props} />;\n}\n\nfunction DialogTrigger({\n className,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Trigger>) {\n return (\n <DialogPrimitive.Trigger\n data-slot=\"dialog-trigger\"\n className={cn(className)}\n {...props}\n />\n );\n}\n\nfunction DialogPortal(props: ComponentProps<typeof DialogPrimitive.Portal>) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\n/**\n * Overlay — Fluent's smoke layer: black at 40% opacity over the full viewport\n * in both themes (see the smoke-layer note above), fading in/out via Base UI's\n * `data-starting-style`/`data-ending-style` hooks with token durations/easings.\n */\nfunction DialogOverlay({\n className,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Backdrop>) {\n return (\n <DialogPrimitive.Backdrop\n data-slot=\"dialog-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/40\",\n // motion — fade on open (enter) / close (exit)\n \"transition-opacity duration-normal ease-decelerate-mid\",\n \"data-starting-style:opacity-0\",\n \"data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid\",\n className\n )}\n {...props}\n />\n );\n}\n\n/**\n * Content — the modal surface: `Portal` → `Backdrop` → `Popup`, centered with\n * fixed positioning, on `bg-background` with `rounded-xl` + `shadow-64`\n * (dialog elevation, conventions §3.6). A fade + slight zoom rides the\n * `data-starting-style`/`data-ending-style` hooks; the zoom animates the CSS\n * `scale` property (see the motion note above). The built-in ✕ close button\n * sits top-right (`showCloseButton={false}` omits it).\n */\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Popup> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Popup\n data-slot=\"dialog-content\"\n className={cn(\n // layout — centered fixed surface, dialog radius + elevation\n \"fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border bg-background p-6 text-foreground shadow-64 outline-none\",\n // motion — fade + slight zoom; `scale`, not `transform` (see doc note)\n \"transition-[opacity,scale] duration-normal ease-decelerate-mid\",\n \"data-starting-style:scale-95 data-starting-style:opacity-0\",\n \"data-ending-style:scale-95 data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className={cn(\n \"absolute top-4 right-4 flex size-8 items-center justify-center rounded-md text-muted-foreground\",\n \"cursor-pointer outline-none transition-colors duration-fast ease-ease\",\n \"hover:bg-accent hover:text-accent-foreground active:bg-accent/80 dark:hover:bg-accent/50 dark:active:bg-accent/70\",\n \"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n \"disabled:pointer-events-none disabled:opacity-50\"\n )}\n >\n <DismissRegular className=\"size-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-1.5 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-xl font-semibold\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogClose({\n className,\n ...props\n}: ComponentProps<typeof DialogPrimitive.Close>) {\n return (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className={cn(className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogTrigger,\n DialogPortal,\n DialogOverlay,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n DialogClose,\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,155 @@
1
+ import * as react from 'react';
2
+ import { ComponentProps } from 'react';
3
+ import { Menu } from '@base-ui/react/menu';
4
+
5
+ /**
6
+ * DropdownMenu — Fluent 2-styled, shadcn-API dropdown menu.
7
+ *
8
+ * Second overlay component in the kit, so it deliberately reuses every pattern
9
+ * `select.tsx` established (portal + positioner + popup surface, `shadow-16`
10
+ * flyout elevation, 32px `data-highlighted` item rows, scale+fade motion via
11
+ * `data-starting-style`/`data-ending-style`). Its popup surface and item rows
12
+ * are visually identical to Select's — same tokens, same radii.
13
+ *
14
+ * ## Base UI mapping (conventions §9)
15
+ * Behavior — focus management, portalling, open/close state, roving tabindex,
16
+ * type-ahead, collision-aware positioning, submenu orchestration — genuinely
17
+ * needs a primitive, so the parts wrap `@base-ui/react/menu` (namespace import,
18
+ * matching the actual export shape in node_modules, exactly like `select.tsx`).
19
+ * shadcn part names are mapped onto Base UI's model:
20
+ *
21
+ * | Exported (shadcn name) | Base UI primitive |
22
+ * | -------------------------- | ------------------------------------------------------ |
23
+ * | `DropdownMenu` | `Menu.Root` |
24
+ * | `DropdownMenuTrigger` | `Menu.Trigger` |
25
+ * | `DropdownMenuContent` | `Menu.Portal` + `Menu.Positioner` + `Menu.Popup` |
26
+ * | `DropdownMenuGroup` | `Menu.Group` |
27
+ * | `DropdownMenuLabel` | `Menu.GroupLabel` ← see divergence 1 |
28
+ * | `DropdownMenuItem` | `Menu.Item` |
29
+ * | `DropdownMenuCheckboxItem` | `Menu.CheckboxItem` (+ `Menu.CheckboxItemIndicator`) |
30
+ * | `DropdownMenuRadioGroup` | `Menu.RadioGroup` |
31
+ * | `DropdownMenuRadioItem` | `Menu.RadioItem` (+ `Menu.RadioItemIndicator`) |
32
+ * | `DropdownMenuSeparator` | `Menu.Separator` |
33
+ * | `DropdownMenuShortcut` | plain `<span>` (no Base UI part) ← see divergence 4 |
34
+ * | `DropdownMenuSub` | `Menu.SubmenuRoot` ← see divergence 2 |
35
+ * | `DropdownMenuSubTrigger` | `Menu.SubmenuTrigger` (+ `ChevronRightRegular`) |
36
+ * | `DropdownMenuSubContent` | `Menu.Portal` + `Menu.Positioner` + `Menu.Popup` |
37
+ *
38
+ * ## Divergences from the shadcn/Radix DropdownMenu API (all deliberate)
39
+ * 1. **`DropdownMenuLabel` maps to Base UI `Menu.GroupLabel`.** Like `select.tsx`,
40
+ * the label part is the heading *inside* a `DropdownMenuGroup` (Base UI
41
+ * associates it with the group for screen readers). It is styled to match
42
+ * `SelectLabel` (muted `text-xs` caption) rather than shadcn's darker
43
+ * `text-sm`, keeping every group heading in the kit visually consistent. It
44
+ * still honours shadcn's `inset` prop (`data-[inset]:pl-8`).
45
+ * 2. **`DropdownMenuSub` is Base UI `Menu.SubmenuRoot`, not a Radix `Sub`.** Base
46
+ * UI models a submenu as its own nested root; `DropdownMenuSubContent`
47
+ * therefore re-composes `Portal` → `Positioner` → `Popup` (Radix's
48
+ * `SubContent` is a single part). Submenus open to the side and Base UI
49
+ * positions them collision-aware; the trigger stays highlighted while its
50
+ * submenu is open via `data-[popup-open]`.
51
+ * 3. **Composition uses Base UI's `render` prop, not `asChild`.** shadcn's
52
+ * `<DropdownMenuTrigger asChild>` has no analogue here — Base UI parts take a
53
+ * `render` prop for polymorphism. To use the kit `Button` as the trigger,
54
+ * pass `render={<Button>…</Button>}`. The wrapper forwards `render` straight
55
+ * through, so the honest Base UI model is preserved (same reasoning as
56
+ * `select.tsx` keeping `SelectValue`'s render-function child).
57
+ * 4. **`DropdownMenuShortcut` is a plain `<span>`** (shadcn parity — it is not a
58
+ * Base UI part, just a right-aligned muted caption for a keyboard hint).
59
+ * 5. **`DropdownMenuItem` keeps shadcn's `inset` + `variant` props.** `variant`
60
+ * is surfaced as `data-variant` (mirrors `Button`'s `data-variant` hook); the
61
+ * `"destructive"` value tints the row and its icons with the `destructive`
62
+ * token (never a hardcoded red), and its highlight uses `destructive/10`
63
+ * (`/20` in dark) so the destructive intent survives the hover state.
64
+ *
65
+ * ## `"use client"` — required (same root cause as `select.tsx`)
66
+ * Every Base UI Menu part module carries its own `'use client'`, so on that
67
+ * basis this wrapper could stay server-renderable. But `CheckmarkRegular` /
68
+ * `ChevronRightRegular` from `@fluentui/react-icons` force the directive: the
69
+ * package's shared icon-sizing module (`createFluentIcon.styles.js`) calls
70
+ * `@griffel/react`'s `__styles()` at module scope *without* its own
71
+ * `'use client'`, even though `__styles` is client-only. Rendering any of these
72
+ * icons from a Server Component pulls that module into the server's RSC graph,
73
+ * and `next build` (Turbopack) fails collecting page data with "Attempted to
74
+ * call __styles() from the server but __styles is on the client" — reproduced
75
+ * against `@fluentui/react-icons@2.0.333` / `@griffel/react@1.7.5`, and it
76
+ * poisons every route sharing Turbopack's chunk for those icons. `"use client"`
77
+ * here keeps the icon imports inside a client boundary. `select.tsx` and
78
+ * `checkbox.tsx` carry the same fix (their doc comments explain it inline).
79
+ *
80
+ * ## data-slot note
81
+ * `DropdownMenu` (Root) and `DropdownMenuSub` (SubmenuRoot) render no DOM element
82
+ * of their own, so they carry no `data-slot`. Every part that renders an element
83
+ * does — `dropdown-menu-trigger`, `dropdown-menu-content`, `dropdown-menu-item`,
84
+ * etc. — which is what tests/consumers hook onto.
85
+ */
86
+ declare function DropdownMenu<Payload>(props: Menu.Root.Props<Payload>): react.JSX.Element;
87
+ declare function DropdownMenuTrigger({ className, ...props }: ComponentProps<typeof Menu.Trigger>): react.JSX.Element;
88
+ declare function DropdownMenuGroup({ className, ...props }: ComponentProps<typeof Menu.Group>): react.JSX.Element;
89
+ /**
90
+ * Content — the floating flyout: `Portal` → `Positioner` → `Popup`. Surface is
91
+ * `bg-popover` + `border` + `shadow-16` (Fluent flyout elevation, conventions
92
+ * §3.6), `rounded-md`, `min-w-[8rem]` (menus size to content, unlike Select
93
+ * which matches the anchor width). A subtle scale+fade open/close animation
94
+ * rides Base UI's `data-starting-style`/`data-ending-style` hooks with token
95
+ * durations/easings — the exact lines from `SelectContent`.
96
+ */
97
+ declare function DropdownMenuContent({ className, sideOffset, align, side, ...props }: ComponentProps<typeof Menu.Popup> & Pick<ComponentProps<typeof Menu.Positioner>, "side" | "align" | "sideOffset">): react.JSX.Element;
98
+ /**
99
+ * Label — a heading for a `DropdownMenuGroup` (Base UI `Menu.GroupLabel`, see
100
+ * divergence 1). Small muted caption, matched to `SelectLabel`. `inset` shifts
101
+ * it to line up with items that carry a leading indicator.
102
+ */
103
+ declare function DropdownMenuLabel({ className, inset, ...props }: ComponentProps<typeof Menu.GroupLabel> & {
104
+ inset?: boolean;
105
+ }): react.JSX.Element;
106
+ /**
107
+ * Item — one command row. 32px tall (`h-8`) with the Fluent 4px list radius,
108
+ * matching `SelectItem`. Highlight (keyboard focus or hover) rides Base UI's
109
+ * `data-highlighted` → `bg-accent`/`text-accent-foreground`. `inset` adds the
110
+ * leading gutter used by checkbox/radio rows; `variant="destructive"` tints the
111
+ * text/icons with the `destructive` token and gives the highlight a destructive
112
+ * wash. Icons follow `SelectItem`'s size-only rules (no muting).
113
+ */
114
+ declare function DropdownMenuItem({ className, inset, variant, ...props }: ComponentProps<typeof Menu.Item> & {
115
+ inset?: boolean;
116
+ variant?: "default" | "destructive";
117
+ }): react.JSX.Element;
118
+ /**
119
+ * CheckboxItem — a toggleable row. The check (`CheckmarkRegular`) sits in a
120
+ * left gutter (`pl-8`), inside `Menu.CheckboxItemIndicator`, which Base UI only
121
+ * mounts while checked. Base UI keeps the menu open on toggle (its
122
+ * `closeOnClick` defaults to `false` for checkbox items).
123
+ */
124
+ declare function DropdownMenuCheckboxItem({ className, children, checked, ...props }: ComponentProps<typeof Menu.CheckboxItem>): react.JSX.Element;
125
+ declare function DropdownMenuRadioGroup({ className, ...props }: ComponentProps<typeof Menu.RadioGroup>): react.JSX.Element;
126
+ /**
127
+ * RadioItem — one option in a `DropdownMenuRadioGroup`. The selected marker is a
128
+ * small filled circle (an inline `<svg>` using `fill-current`, so it inherits
129
+ * the row's text color and needs no extra icon import — same rationale as the
130
+ * kit `RadioGroup` dot). `Menu.RadioItemIndicator` only mounts while selected.
131
+ */
132
+ declare function DropdownMenuRadioItem({ className, children, ...props }: ComponentProps<typeof Menu.RadioItem>): react.JSX.Element;
133
+ declare function DropdownMenuSeparator({ className, ...props }: ComponentProps<typeof Menu.Separator>): react.JSX.Element;
134
+ /**
135
+ * Shortcut — a right-aligned keyboard hint caption. Plain `<span>` (divergence
136
+ * 4), shadcn parity: `ml-auto text-xs tracking-widest text-muted-foreground`.
137
+ */
138
+ declare function DropdownMenuShortcut({ className, ...props }: ComponentProps<"span">): react.JSX.Element;
139
+ declare function DropdownMenuSub(props: Menu.SubmenuRoot.Props): react.JSX.Element;
140
+ /**
141
+ * SubTrigger — an item that opens a submenu, with a trailing `ChevronRightRegular`.
142
+ * Same row treatment as `DropdownMenuItem`; stays highlighted while its submenu
143
+ * is open via Base UI's `data-[popup-open]`. Honours `inset`.
144
+ */
145
+ declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: ComponentProps<typeof Menu.SubmenuTrigger> & {
146
+ inset?: boolean;
147
+ }): react.JSX.Element;
148
+ /**
149
+ * SubContent — a submenu's floating surface. Same `Portal` → `Positioner` →
150
+ * `Popup` composition and surface as `DropdownMenuContent`, but defaults to
151
+ * opening on the inline-end side (Base UI still flips it collision-aware).
152
+ */
153
+ declare function DropdownMenuSubContent({ className, sideOffset, align, ...props }: ComponentProps<typeof Menu.Popup> & Pick<ComponentProps<typeof Menu.Positioner>, "side" | "align" | "sideOffset">): react.JSX.Element;
154
+
155
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger };
@@ -0,0 +1,295 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu";
4
+ import { CheckmarkRegular, ChevronRightRegular } from "@fluentui/react-icons";
5
+ import { cn } from "../../lib/utils.js";
6
+ function DropdownMenu(props) {
7
+ return /* @__PURE__ */ jsx(MenuPrimitive.Root, { ...props });
8
+ }
9
+ function DropdownMenuTrigger({
10
+ className,
11
+ ...props
12
+ }) {
13
+ return /* @__PURE__ */ jsx(
14
+ MenuPrimitive.Trigger,
15
+ {
16
+ "data-slot": "dropdown-menu-trigger",
17
+ className: cn(className),
18
+ ...props
19
+ }
20
+ );
21
+ }
22
+ function DropdownMenuGroup({
23
+ className,
24
+ ...props
25
+ }) {
26
+ return /* @__PURE__ */ jsx(
27
+ MenuPrimitive.Group,
28
+ {
29
+ "data-slot": "dropdown-menu-group",
30
+ className: cn(className),
31
+ ...props
32
+ }
33
+ );
34
+ }
35
+ function DropdownMenuContent({
36
+ className,
37
+ sideOffset = 4,
38
+ align = "start",
39
+ side = "bottom",
40
+ ...props
41
+ }) {
42
+ return /* @__PURE__ */ jsx(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
43
+ MenuPrimitive.Positioner,
44
+ {
45
+ "data-slot": "dropdown-menu-positioner",
46
+ sideOffset,
47
+ align,
48
+ side,
49
+ className: "z-50 outline-none",
50
+ children: /* @__PURE__ */ jsx(
51
+ MenuPrimitive.Popup,
52
+ {
53
+ "data-slot": "dropdown-menu-content",
54
+ className: cn(
55
+ "min-w-[8rem] origin-[var(--transform-origin)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-1 text-popover-foreground shadow-16 outline-none",
56
+ "max-h-[var(--available-height)]",
57
+ // motion — subtle scale + fade on open (enter) / close (exit)
58
+ "transition-[opacity,scale] duration-fast ease-decelerate-mid",
59
+ "data-starting-style:scale-95 data-starting-style:opacity-0",
60
+ "data-ending-style:scale-95 data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid",
61
+ className
62
+ ),
63
+ ...props
64
+ }
65
+ )
66
+ }
67
+ ) });
68
+ }
69
+ function DropdownMenuLabel({
70
+ className,
71
+ inset,
72
+ ...props
73
+ }) {
74
+ return /* @__PURE__ */ jsx(
75
+ MenuPrimitive.GroupLabel,
76
+ {
77
+ "data-slot": "dropdown-menu-label",
78
+ "data-inset": inset || void 0,
79
+ className: cn(
80
+ // Fluent Menu section header — Caption 1 Stronger (12px bold) in
81
+ // NeutralForeground2, per the Figma "Menu section" symbol; deliberately
82
+ // heavier than SelectLabel's muted caption (Figma validation pass 2).
83
+ "px-2 py-1.5 text-xs font-bold text-foreground-2 select-none",
84
+ "data-[inset]:pl-8",
85
+ className
86
+ ),
87
+ ...props
88
+ }
89
+ );
90
+ }
91
+ function DropdownMenuItem({
92
+ className,
93
+ inset,
94
+ variant = "default",
95
+ ...props
96
+ }) {
97
+ return /* @__PURE__ */ jsx(
98
+ MenuPrimitive.Item,
99
+ {
100
+ "data-slot": "dropdown-menu-item",
101
+ "data-inset": inset || void 0,
102
+ "data-variant": variant,
103
+ className: cn(
104
+ // layout — Fluent 32px row, 4px list radius
105
+ "relative flex h-8 cursor-default items-center gap-2 rounded-md px-2 text-sm outline-none select-none",
106
+ // rest text is NeutralForeground2, darkening to accent-foreground on
107
+ // highlight (Figma validation: Fluent list rows rest at #424242)
108
+ "text-foreground-2 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
109
+ // disabled item — muted + non-interactive
110
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
111
+ // inset — leading gutter to align with indicator rows
112
+ "data-[inset]:pl-8",
113
+ // destructive variant — token-tinted text, icons, and highlight wash
114
+ "data-[variant=destructive]:text-destructive",
115
+ "data-[variant=destructive]:data-[highlighted]:bg-destructive/10 data-[variant=destructive]:data-[highlighted]:text-destructive dark:data-[variant=destructive]:data-[highlighted]:bg-destructive/20",
116
+ "data-[variant=destructive]:[&_svg:not([class*='text-'])]:text-destructive",
117
+ // icons — size only (matches SelectItem)
118
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
119
+ className
120
+ ),
121
+ ...props
122
+ }
123
+ );
124
+ }
125
+ function DropdownMenuCheckboxItem({
126
+ className,
127
+ children,
128
+ checked,
129
+ ...props
130
+ }) {
131
+ return /* @__PURE__ */ jsxs(
132
+ MenuPrimitive.CheckboxItem,
133
+ {
134
+ "data-slot": "dropdown-menu-checkbox-item",
135
+ checked,
136
+ className: cn(
137
+ "relative flex h-8 cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-8 text-sm outline-none select-none",
138
+ "text-foreground-2 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
139
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
140
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
141
+ className
142
+ ),
143
+ ...props,
144
+ children: [
145
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsx(MenuPrimitive.CheckboxItemIndicator, { children: /* @__PURE__ */ jsx(CheckmarkRegular, { className: "size-4" }) }) }),
146
+ children
147
+ ]
148
+ }
149
+ );
150
+ }
151
+ function DropdownMenuRadioGroup({
152
+ className,
153
+ ...props
154
+ }) {
155
+ return /* @__PURE__ */ jsx(
156
+ MenuPrimitive.RadioGroup,
157
+ {
158
+ "data-slot": "dropdown-menu-radio-group",
159
+ className: cn(className),
160
+ ...props
161
+ }
162
+ );
163
+ }
164
+ function DropdownMenuRadioItem({
165
+ className,
166
+ children,
167
+ ...props
168
+ }) {
169
+ return /* @__PURE__ */ jsxs(
170
+ MenuPrimitive.RadioItem,
171
+ {
172
+ "data-slot": "dropdown-menu-radio-item",
173
+ className: cn(
174
+ "relative flex h-8 cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-8 text-sm outline-none select-none",
175
+ "text-foreground-2 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
176
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
177
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
178
+ className
179
+ ),
180
+ ...props,
181
+ children: [
182
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex size-4 items-center justify-center", children: /* @__PURE__ */ jsx(MenuPrimitive.RadioItemIndicator, { children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 8 8", className: "size-2 fill-current", "aria-hidden": true, children: /* @__PURE__ */ jsx("circle", { cx: "4", cy: "4", r: "4" }) }) }) }),
183
+ children
184
+ ]
185
+ }
186
+ );
187
+ }
188
+ function DropdownMenuSeparator({
189
+ className,
190
+ ...props
191
+ }) {
192
+ return /* @__PURE__ */ jsx(
193
+ MenuPrimitive.Separator,
194
+ {
195
+ "data-slot": "dropdown-menu-separator",
196
+ className: cn("pointer-events-none -mx-1 my-1 h-px bg-border", className),
197
+ ...props
198
+ }
199
+ );
200
+ }
201
+ function DropdownMenuShortcut({
202
+ className,
203
+ ...props
204
+ }) {
205
+ return /* @__PURE__ */ jsx(
206
+ "span",
207
+ {
208
+ "data-slot": "dropdown-menu-shortcut",
209
+ className: cn(
210
+ "ml-auto text-xs tracking-widest text-muted-foreground",
211
+ className
212
+ ),
213
+ ...props
214
+ }
215
+ );
216
+ }
217
+ function DropdownMenuSub(props) {
218
+ return /* @__PURE__ */ jsx(MenuPrimitive.SubmenuRoot, { ...props });
219
+ }
220
+ function DropdownMenuSubTrigger({
221
+ className,
222
+ inset,
223
+ children,
224
+ ...props
225
+ }) {
226
+ return /* @__PURE__ */ jsxs(
227
+ MenuPrimitive.SubmenuTrigger,
228
+ {
229
+ "data-slot": "dropdown-menu-sub-trigger",
230
+ "data-inset": inset || void 0,
231
+ className: cn(
232
+ "relative flex h-8 cursor-default items-center gap-2 rounded-md px-2 text-sm outline-none select-none",
233
+ "text-foreground-2 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground",
234
+ "data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground",
235
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
236
+ "data-[inset]:pl-8",
237
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
238
+ className
239
+ ),
240
+ ...props,
241
+ children: [
242
+ children,
243
+ /* @__PURE__ */ jsx(ChevronRightRegular, { className: "ml-auto size-4 text-muted-foreground" })
244
+ ]
245
+ }
246
+ );
247
+ }
248
+ function DropdownMenuSubContent({
249
+ className,
250
+ sideOffset = 4,
251
+ align = "start",
252
+ ...props
253
+ }) {
254
+ return /* @__PURE__ */ jsx(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
255
+ MenuPrimitive.Positioner,
256
+ {
257
+ "data-slot": "dropdown-menu-sub-positioner",
258
+ sideOffset,
259
+ align,
260
+ className: "z-50 outline-none",
261
+ children: /* @__PURE__ */ jsx(
262
+ MenuPrimitive.Popup,
263
+ {
264
+ "data-slot": "dropdown-menu-sub-content",
265
+ className: cn(
266
+ "min-w-[8rem] origin-[var(--transform-origin)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-1 text-popover-foreground shadow-16 outline-none",
267
+ "max-h-[var(--available-height)]",
268
+ "transition-[opacity,scale] duration-fast ease-decelerate-mid",
269
+ "data-starting-style:scale-95 data-starting-style:opacity-0",
270
+ "data-ending-style:scale-95 data-ending-style:opacity-0 data-ending-style:ease-accelerate-mid",
271
+ className
272
+ ),
273
+ ...props
274
+ }
275
+ )
276
+ }
277
+ ) });
278
+ }
279
+ export {
280
+ DropdownMenu,
281
+ DropdownMenuCheckboxItem,
282
+ DropdownMenuContent,
283
+ DropdownMenuGroup,
284
+ DropdownMenuItem,
285
+ DropdownMenuLabel,
286
+ DropdownMenuRadioGroup,
287
+ DropdownMenuRadioItem,
288
+ DropdownMenuSeparator,
289
+ DropdownMenuShortcut,
290
+ DropdownMenuSub,
291
+ DropdownMenuSubContent,
292
+ DropdownMenuSubTrigger,
293
+ DropdownMenuTrigger
294
+ };
295
+ //# sourceMappingURL=dropdown-menu.js.map