@arcfusionz/arc-primitive-ui 0.1.0 → 0.2.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 (135) hide show
  1. package/dist/components/AILoader/AILoader.d.ts +32 -0
  2. package/dist/components/AILoader/AILoader.js +157 -0
  3. package/dist/components/AILoader/index.d.ts +2 -0
  4. package/dist/components/AILoader/index.js +2 -0
  5. package/dist/components/Accordion/Accordion.d.ts +96 -0
  6. package/dist/components/Accordion/Accordion.js +149 -0
  7. package/dist/components/Accordion/index.d.ts +2 -0
  8. package/dist/components/Accordion/index.js +2 -0
  9. package/dist/components/Avatar/Avatar.d.ts +152 -0
  10. package/dist/components/Avatar/Avatar.js +216 -0
  11. package/dist/components/Avatar/index.d.ts +2 -0
  12. package/dist/components/Avatar/index.js +2 -0
  13. package/dist/components/Badge/Badge.d.ts +87 -0
  14. package/dist/components/Badge/Badge.js +118 -0
  15. package/dist/components/Badge/index.d.ts +2 -0
  16. package/dist/components/Badge/index.js +2 -0
  17. package/dist/components/Breadcrumb/Breadcrumb.d.ts +109 -0
  18. package/dist/components/Breadcrumb/Breadcrumb.js +182 -0
  19. package/dist/components/Breadcrumb/index.d.ts +2 -0
  20. package/dist/components/Breadcrumb/index.js +2 -0
  21. package/dist/components/Button/Button.d.ts +57 -0
  22. package/dist/components/Button/Button.js +177 -0
  23. package/dist/components/Button/index.d.ts +2 -0
  24. package/dist/components/Button/index.js +2 -0
  25. package/dist/components/Calendar/Calendar.d.ts +140 -0
  26. package/dist/components/Calendar/Calendar.js +468 -0
  27. package/dist/components/Calendar/index.d.ts +2 -0
  28. package/dist/components/Calendar/index.js +2 -0
  29. package/dist/components/Checkbox/Checkbox.d.ts +60 -0
  30. package/dist/components/Checkbox/Checkbox.js +129 -0
  31. package/dist/components/Checkbox/index.d.ts +2 -0
  32. package/dist/components/Checkbox/index.js +2 -0
  33. package/dist/components/Combobox/Combobox.d.ts +251 -0
  34. package/dist/components/Combobox/Combobox.js +354 -0
  35. package/dist/components/Combobox/index.d.ts +2 -0
  36. package/dist/components/Combobox/index.js +2 -0
  37. package/dist/components/ContextMenu/ContextMenu.d.ts +129 -0
  38. package/dist/components/ContextMenu/ContextMenu.js +93 -0
  39. package/dist/components/ContextMenu/index.d.ts +2 -0
  40. package/dist/components/ContextMenu/index.js +2 -0
  41. package/dist/components/DatePicker/DatePicker.d.ts +109 -0
  42. package/dist/components/DatePicker/DatePicker.js +145 -0
  43. package/dist/components/DatePicker/index.d.ts +2 -0
  44. package/dist/components/DatePicker/index.js +2 -0
  45. package/dist/components/DateRangePicker/DateRangePicker.d.ts +107 -0
  46. package/dist/components/DateRangePicker/DateRangePicker.js +161 -0
  47. package/dist/components/DateRangePicker/index.d.ts +2 -0
  48. package/dist/components/DateRangePicker/index.js +2 -0
  49. package/dist/components/Dialog/Dialog.d.ts +112 -0
  50. package/dist/components/Dialog/Dialog.js +141 -0
  51. package/dist/components/Dialog/index.d.ts +2 -0
  52. package/dist/components/Dialog/index.js +2 -0
  53. package/dist/components/Drawer/Drawer.d.ts +188 -0
  54. package/dist/components/Drawer/Drawer.js +268 -0
  55. package/dist/components/Drawer/index.d.ts +2 -0
  56. package/dist/components/Drawer/index.js +2 -0
  57. package/dist/components/Field/Field.d.ts +123 -0
  58. package/dist/components/Field/Field.js +241 -0
  59. package/dist/components/Field/FieldContext.d.ts +43 -0
  60. package/dist/components/Field/FieldContext.js +28 -0
  61. package/dist/components/Field/index.d.ts +3 -0
  62. package/dist/components/Field/index.js +3 -0
  63. package/dist/components/Fieldset/Fieldset.d.ts +43 -0
  64. package/dist/components/Fieldset/Fieldset.js +48 -0
  65. package/dist/components/Fieldset/index.d.ts +2 -0
  66. package/dist/components/Fieldset/index.js +2 -0
  67. package/dist/components/Form/Form.d.ts +54 -0
  68. package/dist/components/Form/Form.js +57 -0
  69. package/dist/components/Form/index.d.ts +2 -0
  70. package/dist/components/Form/index.js +2 -0
  71. package/dist/components/Input/Input.d.ts +64 -0
  72. package/dist/components/Input/Input.js +111 -0
  73. package/dist/components/Input/index.d.ts +2 -0
  74. package/dist/components/Input/index.js +2 -0
  75. package/dist/components/Menu/Menu.d.ts +212 -0
  76. package/dist/components/Menu/Menu.js +255 -0
  77. package/dist/components/Menu/index.d.ts +2 -0
  78. package/dist/components/Menu/index.js +2 -0
  79. package/dist/components/Popover/Popover.d.ts +122 -0
  80. package/dist/components/Popover/Popover.js +116 -0
  81. package/dist/components/Popover/index.d.ts +2 -0
  82. package/dist/components/Popover/index.js +2 -0
  83. package/dist/components/Progress/Progress.d.ts +87 -0
  84. package/dist/components/Progress/Progress.js +73 -0
  85. package/dist/components/Progress/index.d.ts +2 -0
  86. package/dist/components/Progress/index.js +2 -0
  87. package/dist/components/Radio/Radio.d.ts +65 -0
  88. package/dist/components/Radio/Radio.js +93 -0
  89. package/dist/components/Radio/index.d.ts +2 -0
  90. package/dist/components/Radio/index.js +2 -0
  91. package/dist/components/Select/Select.d.ts +136 -0
  92. package/dist/components/Select/Select.js +219 -0
  93. package/dist/components/Select/index.d.ts +2 -0
  94. package/dist/components/Select/index.js +2 -0
  95. package/dist/components/Skeleton/Skeleton.d.ts +39 -0
  96. package/dist/components/Skeleton/Skeleton.js +44 -0
  97. package/dist/components/Skeleton/index.d.ts +2 -0
  98. package/dist/components/Skeleton/index.js +2 -0
  99. package/dist/components/Stepper/Stepper.d.ts +161 -0
  100. package/dist/components/Stepper/Stepper.js +344 -0
  101. package/dist/components/Stepper/index.d.ts +2 -0
  102. package/dist/components/Stepper/index.js +2 -0
  103. package/dist/components/Switch/Switch.d.ts +56 -0
  104. package/dist/components/Switch/Switch.js +87 -0
  105. package/dist/components/Switch/index.d.ts +2 -0
  106. package/dist/components/Switch/index.js +2 -0
  107. package/dist/components/Table/Table.d.ts +116 -0
  108. package/dist/components/Table/Table.js +143 -0
  109. package/dist/components/Table/index.d.ts +2 -0
  110. package/dist/components/Table/index.js +2 -0
  111. package/dist/components/Tabs/Tabs.d.ts +116 -0
  112. package/dist/components/Tabs/Tabs.js +158 -0
  113. package/dist/components/Tabs/index.d.ts +2 -0
  114. package/dist/components/Tabs/index.js +2 -0
  115. package/dist/components/Timeline/Timeline.d.ts +137 -0
  116. package/dist/components/Timeline/Timeline.js +243 -0
  117. package/dist/components/Timeline/index.d.ts +2 -0
  118. package/dist/components/Timeline/index.js +2 -0
  119. package/dist/components/Toast/Toast.d.ts +135 -0
  120. package/dist/components/Toast/Toast.js +314 -0
  121. package/dist/components/Toast/index.d.ts +2 -0
  122. package/dist/components/Toast/index.js +2 -0
  123. package/dist/components/Tooltip/Tooltip.d.ts +104 -0
  124. package/dist/components/Tooltip/Tooltip.js +95 -0
  125. package/dist/components/Tooltip/index.d.ts +2 -0
  126. package/dist/components/Tooltip/index.js +2 -0
  127. package/dist/components/Typography/Typography.d.ts +38 -0
  128. package/dist/components/Typography/Typography.js +53 -0
  129. package/dist/components/Typography/index.d.ts +2 -0
  130. package/dist/components/Typography/index.js +2 -0
  131. package/dist/index.d.ts +66 -3398
  132. package/dist/index.js +34 -5343
  133. package/dist/lib/cn.d.ts +6 -0
  134. package/dist/lib/cn.js +9 -0
  135. package/package.json +6 -2
@@ -0,0 +1,268 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { createContext, forwardRef, useContext, useMemo } from "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Drawer } from "@base-ui/react/drawer";
5
+ //#region src/components/Drawer/Drawer.tsx
6
+ const sideToSwipeDirection = {
7
+ top: "up",
8
+ right: "right",
9
+ bottom: "down",
10
+ left: "left"
11
+ };
12
+ const DrawerSideContext = createContext({
13
+ side: "right",
14
+ hasSnapPoints: false
15
+ });
16
+ /**
17
+ * Groups all parts of the drawer and owns its state. Renders no DOM.
18
+ *
19
+ * Wraps Base UI's `Drawer.Root`, deriving `swipeDirection` from `side` (pass
20
+ * `swipeDirection` yourself only to decouple them). Every other root feature
21
+ * passes through: `open`/`defaultOpen`/`onOpenChange(open, details)`,
22
+ * `snapPoints` with `snapPoint`/`defaultSnapPoint`/`onSnapPointChange`,
23
+ * `modal` (`true` | `false` | `"trap-focus"`), `disablePointerDismissal`,
24
+ * `onOpenChangeComplete`, `actionsRef`, and detached triggers via
25
+ * `createDrawerHandle()` payloads.
26
+ */
27
+ function Drawer$1({ side = "right", swipeDirection, ...rest }) {
28
+ const hasSnapPoints = (rest.snapPoints?.length ?? 0) > 0;
29
+ const context = useMemo(() => ({
30
+ side,
31
+ hasSnapPoints
32
+ }), [side, hasSnapPoints]);
33
+ return /* @__PURE__ */ jsx(DrawerSideContext.Provider, {
34
+ value: context,
35
+ children: /* @__PURE__ */ jsx(Drawer.Root, {
36
+ swipeDirection: swipeDirection ?? sideToSwipeDirection[side],
37
+ ...rest
38
+ })
39
+ });
40
+ }
41
+ Drawer$1.displayName = "Drawer";
42
+ /**
43
+ * Opens the drawer. Renders an unstyled `<button>` and exposes
44
+ * `data-popup-open` while its drawer is open — compose it with Button for
45
+ * the usual look: `<DrawerTrigger render={<Button>Open</Button>} />`.
46
+ */
47
+ const DrawerTrigger = forwardRef((props, ref) => /* @__PURE__ */ jsx(Drawer.Trigger, {
48
+ ref,
49
+ ...props
50
+ }));
51
+ DrawerTrigger.displayName = "DrawerTrigger";
52
+ /**
53
+ * Closes the drawer. Renders an unstyled `<button>` — compose it with
54
+ * Button for footer actions:
55
+ * `<DrawerClose render={<Button variant="outline">Cancel</Button>} />`.
56
+ */
57
+ const DrawerClose = forwardRef((props, ref) => /* @__PURE__ */ jsx(Drawer.Close, {
58
+ ref,
59
+ ...props
60
+ }));
61
+ DrawerClose.displayName = "DrawerClose";
62
+ const backdropClasses = "fixed inset-0 z-50 min-h-dvh bg-overlay supports-[-webkit-touch-callout:none]:absolute opacity-[calc(1_-_var(--drawer-swipe-progress,0))] motion-safe:transition-opacity motion-safe:duration-[450ms] motion-safe:ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:duration-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*400ms)] data-starting-style:opacity-0 data-ending-style:opacity-0";
63
+ const viewportBaseClasses = "pointer-events-none fixed inset-0 z-50 flex";
64
+ const viewportSideClasses = {
65
+ top: "items-start justify-center",
66
+ right: "justify-end",
67
+ bottom: "items-end justify-center",
68
+ left: "justify-start"
69
+ };
70
+ const popupBaseClasses = "pointer-events-auto relative flex flex-col border-border bg-background font-sans text-foreground shadow-lg outline-none touch-none will-change-transform data-closed:pointer-events-none scale-[calc(1_-_0.05*var(--nested-drawers,0))] before:pointer-events-none before:absolute before:bg-inherit after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:bg-slate-950/5 after:opacity-0 data-nested-drawer-open:after:opacity-100 motion-safe:transition-[transform,scale] motion-safe:duration-[450ms] motion-safe:ease-[cubic-bezier(0.32,0.72,0,1)] motion-safe:after:transition-opacity motion-safe:after:duration-[450ms] data-swiping:select-none data-swiping:duration-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength,1)*400ms)]";
71
+ const popupSideClasses = {
72
+ top: "w-full origin-top rounded-b-md border-b before:inset-x-0 before:bottom-full before:h-12 [transform:translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))] data-starting-style:[transform:translateY(calc(-100%_-_2px))] data-ending-style:[transform:translateY(calc(-100%_-_2px))]",
73
+ right: "h-full origin-right border-l before:inset-y-0 before:left-full before:w-12 [transform:translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:[transform:translateX(calc(100%_+_2px))] data-ending-style:[transform:translateX(calc(100%_+_2px))]",
74
+ bottom: "w-full origin-bottom rounded-t-md border-t before:inset-x-0 before:top-full before:h-12 [transform:translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))] data-starting-style:[transform:translateY(calc(100%_+_2px))] data-ending-style:[transform:translateY(calc(100%_+_2px))]",
75
+ left: "h-full origin-left border-r before:inset-y-0 before:right-full before:w-12 [transform:translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:[transform:translateX(calc(-100%_-_2px))] data-ending-style:[transform:translateX(calc(-100%_-_2px))]"
76
+ };
77
+ const horizontalSizeClasses = {
78
+ sm: "w-80 max-w-[calc(100vw_-_3rem)]",
79
+ md: "w-96 max-w-[calc(100vw_-_3rem)]",
80
+ lg: "w-[32rem] max-w-[calc(100vw_-_3rem)]",
81
+ full: "w-screen border-none shadow-none"
82
+ };
83
+ const verticalSizeClasses = {
84
+ sm: "max-h-[40dvh]",
85
+ md: "max-h-[75dvh]",
86
+ lg: "max-h-[90dvh]",
87
+ full: "h-dvh rounded-none border-none shadow-none"
88
+ };
89
+ const snapPointPaddingClasses = "[padding-bottom:max(0px,calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))]";
90
+ const contentClasses = "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto overscroll-contain touch-auto p-6";
91
+ const contentBottomSafeAreaClasses = "pb-[calc(1.5rem_+_env(safe-area-inset-bottom,0px))]";
92
+ const closeClearanceClasses = "[&>[data-drawer-header]]:pr-8 [&>[data-drawer-title]]:pr-8";
93
+ const cornerCloseClasses = "absolute top-4 right-4 inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground active:bg-slate-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
94
+ const handleBaseClasses = "shrink-0 rounded-full bg-slate-300";
95
+ const handleSideClasses = {
96
+ top: "order-last mx-auto mb-3 h-1 w-10",
97
+ right: "absolute top-1/2 left-2 h-10 w-1 -translate-y-1/2",
98
+ bottom: "mx-auto mt-3 h-1 w-10",
99
+ left: "absolute top-1/2 right-2 h-10 w-1 -translate-y-1/2"
100
+ };
101
+ function XIcon(props) {
102
+ return /* @__PURE__ */ jsx("svg", {
103
+ viewBox: "0 0 16 16",
104
+ fill: "none",
105
+ stroke: "currentColor",
106
+ strokeWidth: 1.5,
107
+ strokeLinecap: "round",
108
+ "aria-hidden": "true",
109
+ className: "size-4",
110
+ ...props,
111
+ children: /* @__PURE__ */ jsx("path", { d: "m3.5 3.5 9 9m-9 0 9-9" })
112
+ });
113
+ }
114
+ /**
115
+ * Class list for the drawer surface itself. Useful when composing Base UI's
116
+ * drawer parts directly (custom viewports, snap-point layouts) while keeping
117
+ * the ArcFusion look.
118
+ */
119
+ function drawerPopupVariants({ side = "right", size = "md", className } = {}) {
120
+ const sizeClasses = side === "left" || side === "right" ? horizontalSizeClasses : verticalSizeClasses;
121
+ return cn(popupBaseClasses, popupSideClasses[side], sizeClasses[size], className);
122
+ }
123
+ /**
124
+ * The drawer surface. Bundles Base UI's Portal, Backdrop, Viewport, Popup,
125
+ * and Content parts into one styled component positioned on the root's
126
+ * `side`; `initialFocus`/`finalFocus` and every other Base UI popup prop
127
+ * pass straight through. Children render inside the scrollable content
128
+ * region while the handle and corner close stay pinned to the frame.
129
+ */
130
+ const DrawerPopup = forwardRef(({ size = "md", showCloseButton = true, closeLabel = "Close", showHandle = false, showBackdrop = true, keepMounted = false, virtualKeyboard = false, container, className, children, ...rest }, ref) => {
131
+ const { side, hasSnapPoints } = useContext(DrawerSideContext);
132
+ const portal = /* @__PURE__ */ jsxs(Drawer.Portal, {
133
+ keepMounted,
134
+ container,
135
+ children: [showBackdrop && /* @__PURE__ */ jsx(Drawer.Backdrop, { className: backdropClasses }), /* @__PURE__ */ jsx(Drawer.Viewport, {
136
+ className: cn(viewportBaseClasses, viewportSideClasses[side]),
137
+ children: /* @__PURE__ */ jsxs(Drawer.Popup, {
138
+ ref,
139
+ className: cn(drawerPopupVariants({
140
+ side,
141
+ size
142
+ }), hasSnapPoints && side === "bottom" && snapPointPaddingClasses, className),
143
+ ...rest,
144
+ children: [
145
+ showHandle && /* @__PURE__ */ jsx("span", {
146
+ "aria-hidden": "true",
147
+ className: cn(handleBaseClasses, handleSideClasses[side])
148
+ }),
149
+ /* @__PURE__ */ jsx(Drawer.Content, {
150
+ className: cn(contentClasses, side === "bottom" && contentBottomSafeAreaClasses, showCloseButton && closeClearanceClasses),
151
+ children
152
+ }),
153
+ showCloseButton && /* @__PURE__ */ jsx(Drawer.Close, {
154
+ "aria-label": closeLabel,
155
+ className: cornerCloseClasses,
156
+ children: /* @__PURE__ */ jsx(XIcon, {})
157
+ })
158
+ ]
159
+ })
160
+ })]
161
+ });
162
+ return virtualKeyboard ? /* @__PURE__ */ jsx(Drawer.VirtualKeyboardProvider, { children: portal }) : portal;
163
+ });
164
+ DrawerPopup.displayName = "DrawerPopup";
165
+ /** Groups the title and description with standard spacing at the top of the drawer. */
166
+ const DrawerHeader = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx("div", {
167
+ ref,
168
+ "data-drawer-header": "",
169
+ className: cn("flex flex-col gap-1.5", className),
170
+ ...rest
171
+ }));
172
+ DrawerHeader.displayName = "DrawerHeader";
173
+ /**
174
+ * Action row: right-aligned on desktop, stacked with the primary action on
175
+ * top on small screens. As a direct child of the popup it pins to the
176
+ * drawer's bottom edge when the content is shorter than a full-height panel.
177
+ */
178
+ const DrawerFooter = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx("div", {
179
+ ref,
180
+ className: cn("mt-auto flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-end", className),
181
+ ...rest
182
+ }));
183
+ DrawerFooter.displayName = "DrawerFooter";
184
+ /**
185
+ * Labels the drawer — Base UI wires it to the popup's `aria-labelledby`.
186
+ * Renders an `<h2>`; every drawer should have one (or an `aria-label` on
187
+ * the popup) so the panel announces meaningfully.
188
+ */
189
+ const DrawerTitle = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx(Drawer.Title, {
190
+ ref,
191
+ "data-drawer-title": "",
192
+ className: cn("font-heading text-xl font-semibold text-foreground", className),
193
+ ...rest
194
+ }));
195
+ DrawerTitle.displayName = "DrawerTitle";
196
+ /** Supporting copy announced when the drawer opens — wired to `aria-describedby`. */
197
+ const DrawerDescription = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx(Drawer.Description, {
198
+ ref,
199
+ className: cn("font-sans text-sm text-muted-foreground", className),
200
+ ...rest
201
+ }));
202
+ DrawerDescription.displayName = "DrawerDescription";
203
+ const swipeAreaSideClasses = {
204
+ top: "inset-x-0 top-0 h-6",
205
+ right: "inset-y-0 right-0 w-6",
206
+ bottom: "inset-x-0 bottom-0 h-6",
207
+ left: "inset-y-0 left-0 w-6"
208
+ };
209
+ /**
210
+ * Invisible strip along the drawer's edge that opens it with a swipe-in
211
+ * gesture (mobile-navigation pattern). Positions itself on the root's
212
+ * `side` with a 24px hit area — pass `className` to widen it or add a
213
+ * visible affordance as children. Keep a regular `DrawerTrigger` too:
214
+ * edge swipes are invisible to most users and unavailable to keyboards.
215
+ */
216
+ const DrawerSwipeArea = forwardRef(({ className, ...rest }, ref) => {
217
+ const { side } = useContext(DrawerSideContext);
218
+ return /* @__PURE__ */ jsx(Drawer.SwipeArea, {
219
+ ref,
220
+ className: cn("fixed z-40", swipeAreaSideClasses[side], className),
221
+ ...rest
222
+ });
223
+ });
224
+ DrawerSwipeArea.displayName = "DrawerSwipeArea";
225
+ /**
226
+ * Shares drawer state across the app shell so `DrawerIndent` /
227
+ * `DrawerIndentBackground` can react to any drawer opening. Renders no DOM —
228
+ * wrap it around the app root only when using the indent effect.
229
+ */
230
+ const DrawerProvider = Drawer.Provider;
231
+ /**
232
+ * Keyboard-aware focus and scroll handling for bottom sheets that contain
233
+ * form fields. Prefer the `virtualKeyboard` prop on `DrawerPopup`; this raw
234
+ * part exists for custom compositions and MUST render inside a `Drawer`
235
+ * (it reads the root's context), wrapping the drawer's parts. Exposes
236
+ * `--drawer-keyboard-inset` on the viewport. Renders no DOM.
237
+ */
238
+ const DrawerVirtualKeyboardProvider = Drawer.VirtualKeyboardProvider;
239
+ /**
240
+ * Creates a handle that connects detached `DrawerTrigger`s (or imperative
241
+ * `open`/`close` calls) to a `Drawer` rendered elsewhere — e.g. opening a
242
+ * drawer from a menu item. Pass it to both as the `handle` prop.
243
+ */
244
+ const createDrawerHandle = Drawer.createHandle;
245
+ /**
246
+ * Wrapper for the app's main UI inside a `DrawerProvider`; gets
247
+ * `data-active` while any drawer is open. Unstyled on purpose — the app
248
+ * shell owns the effect, e.g.
249
+ * `className="motion-safe:transition-transform data-active:scale-[0.98]"`
250
+ * for the iOS-style recede.
251
+ */
252
+ const DrawerIndent = forwardRef((props, ref) => /* @__PURE__ */ jsx(Drawer.Indent, {
253
+ ref,
254
+ ...props
255
+ }));
256
+ DrawerIndent.displayName = "DrawerIndent";
257
+ /**
258
+ * Backdrop layer rendered behind `DrawerIndent` (place it just before) so
259
+ * the receded app has something to sit on — style it with `data-active`
260
+ * like the indent itself. Unstyled on purpose.
261
+ */
262
+ const DrawerIndentBackground = forwardRef((props, ref) => /* @__PURE__ */ jsx(Drawer.IndentBackground, {
263
+ ref,
264
+ ...props
265
+ }));
266
+ DrawerIndentBackground.displayName = "DrawerIndentBackground";
267
+ //#endregion
268
+ export { Drawer$1 as Drawer, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerIndent, DrawerIndentBackground, DrawerPopup, DrawerProvider, DrawerSwipeArea, DrawerTitle, DrawerTrigger, DrawerVirtualKeyboardProvider, createDrawerHandle, drawerPopupVariants };
@@ -0,0 +1,2 @@
1
+ import { Drawer, DrawerClose, DrawerCloseProps, DrawerDescription, DrawerDescriptionProps, DrawerFooter, DrawerFooterProps, DrawerHeader, DrawerHeaderProps, DrawerIndent, DrawerIndentBackground, DrawerIndentBackgroundProps, DrawerIndentProps, DrawerPopup, DrawerPopupProps, DrawerPopupVariantsOptions, DrawerProps, DrawerProvider, DrawerSide, DrawerSize, DrawerSwipeArea, DrawerSwipeAreaProps, DrawerTitle, DrawerTitleProps, DrawerTrigger, DrawerTriggerProps, DrawerVirtualKeyboardProvider, createDrawerHandle, drawerPopupVariants } from "./Drawer.js";
2
+ export { Drawer, DrawerClose, type DrawerCloseProps, DrawerDescription, type DrawerDescriptionProps, DrawerFooter, type DrawerFooterProps, DrawerHeader, type DrawerHeaderProps, DrawerIndent, DrawerIndentBackground, type DrawerIndentBackgroundProps, type DrawerIndentProps, DrawerPopup, type DrawerPopupProps, type DrawerPopupVariantsOptions, type DrawerProps, DrawerProvider, type DrawerSide, type DrawerSize, DrawerSwipeArea, type DrawerSwipeAreaProps, DrawerTitle, type DrawerTitleProps, DrawerTrigger, type DrawerTriggerProps, DrawerVirtualKeyboardProvider, createDrawerHandle, drawerPopupVariants };
@@ -0,0 +1,2 @@
1
+ import { Drawer, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerIndent, DrawerIndentBackground, DrawerPopup, DrawerProvider, DrawerSwipeArea, DrawerTitle, DrawerTrigger, DrawerVirtualKeyboardProvider, createDrawerHandle, drawerPopupVariants } from "./Drawer.js";
2
+ export { Drawer, DrawerClose, DrawerDescription, DrawerFooter, DrawerHeader, DrawerIndent, DrawerIndentBackground, DrawerPopup, DrawerProvider, DrawerSwipeArea, DrawerTitle, DrawerTrigger, DrawerVirtualKeyboardProvider, createDrawerHandle, drawerPopupVariants };
@@ -0,0 +1,123 @@
1
+ import { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
2
+ import { Field } from "@base-ui/react/field";
3
+ import { Control, FieldPath, FieldValues } from "react-hook-form";
4
+ //#region src/components/Field/Field.d.ts
5
+ type FieldOrientation = "vertical" | "horizontal";
6
+ type BaseFieldRootProps = ComponentPropsWithoutRef<typeof Field.Root>;
7
+ interface FieldProps<TFieldValues extends FieldValues = FieldValues> extends Omit<BaseFieldRootProps, "className" | "name"> {
8
+ /**
9
+ * Identifies the field: the submitted name in native forms, the registered
10
+ * path when connected to React Hook Form. With an explicit `control`, the
11
+ * name is type-checked against the form's values.
12
+ */
13
+ name?: FieldPath<TFieldValues>;
14
+ /**
15
+ * React Hook Form `control` for connecting this field explicitly. Inside a
16
+ * `<Form form={…}>` it is read from context instead, so most fields only
17
+ * need `name`. A field with a `name` and a reachable control is
18
+ * "connected": it subscribes to that field's state via `useController`,
19
+ * shows `FieldError` messages automatically, and wires the `Input` inside
20
+ * it (value, change/blur handlers, focus ref) with no extra props.
21
+ */
22
+ control?: Control<TFieldValues>;
23
+ /**
24
+ * Marks the field as required: the label gains a decorative asterisk and
25
+ * the control is announced as required (`aria-required` when connected —
26
+ * the schema owns actual enforcement — or the native `required` attribute
27
+ * in static fields).
28
+ */
29
+ required?: boolean;
30
+ /**
31
+ * `vertical` (default) stacks label, control, and supporting text.
32
+ * `horizontal` puts the label in a leading column, baseline-aligned with
33
+ * the control — for dense, label-left form layouts. Checkbox/switch rows
34
+ * are a different pattern: wrap the control with `FieldLabel` instead.
35
+ */
36
+ orientation?: FieldOrientation;
37
+ className?: string;
38
+ }
39
+ interface FieldComponent {
40
+ <TFieldValues extends FieldValues = FieldValues>(props: FieldProps<TFieldValues> & {
41
+ ref?: Ref<HTMLDivElement>;
42
+ }): ReactNode;
43
+ displayName?: string;
44
+ }
45
+ /**
46
+ * Labelling + validation wrapper for a single form control, built on Base UI's
47
+ * Field. It associates `FieldLabel`, `FieldDescription`, and `FieldError`
48
+ * with the control automatically (ids, `aria-describedby`) and exposes state
49
+ * data-attributes (`data-invalid`, `data-touched`, `data-dirty`,
50
+ * `data-filled`, `data-focused`) on every part for styling.
51
+ *
52
+ * Give it a `name` inside `<Form form={…}>` (or pass `control`) to connect it
53
+ * to React Hook Form — validation state then flows in from the form and the
54
+ * `Input` inside is wired automatically. Without a form library it works as a
55
+ * native field: constraint attributes plus the `validate`/`validationMode`
56
+ * props drive `FieldError` via its `match` prop.
57
+ */
58
+ declare const Field$1: FieldComponent;
59
+ interface FieldLabelVariantsOptions {
60
+ className?: string;
61
+ }
62
+ /**
63
+ * Class list for an element styled as a field label — for labelling controls
64
+ * that live outside a `Field` (e.g. a filter Select in a toolbar) so every
65
+ * label in the product shares one look.
66
+ */
67
+ declare function fieldLabelVariants({ className }?: FieldLabelVariantsOptions): string;
68
+ interface FieldLabelProps extends Omit<ComponentPropsWithoutRef<typeof Field.Label>, "className"> {
69
+ className?: string;
70
+ }
71
+ /**
72
+ * Visible label, automatically associated with the field's control — clicking
73
+ * it focuses the control. When the `Field` is `required`, a decorative
74
+ * asterisk (hidden from assistive technology, which hears the control's
75
+ * required state instead) is appended. For checkbox/radio/switch rows, wrap
76
+ * the control instead: `<FieldLabel><Switch /> Notifications</FieldLabel>`.
77
+ * When the control is button-based (Select, Combobox triggers), pass
78
+ * `nativeLabel={false}` — the label then renders as a `<div>` wired via
79
+ * `aria-labelledby`, so hovering or clicking it doesn't act on the button.
80
+ */
81
+ declare const FieldLabel: import("react").ForwardRefExoticComponent<FieldLabelProps & import("react").RefAttributes<HTMLLabelElement>>;
82
+ interface FieldDescriptionProps extends Omit<ComponentPropsWithoutRef<typeof Field.Description>, "className"> {
83
+ className?: string;
84
+ }
85
+ /**
86
+ * Persistent supporting copy for the field, announced via `aria-describedby`.
87
+ * It stays visible while an error shows — the hint is exactly what the user
88
+ * needs to fix the problem. Order it in the children wherever the design
89
+ * calls for (before or after the control); the association is automatic.
90
+ */
91
+ declare const FieldDescription: import("react").ForwardRefExoticComponent<FieldDescriptionProps & import("react").RefAttributes<HTMLParagraphElement>>;
92
+ interface FieldErrorProps extends Omit<ComponentPropsWithoutRef<typeof Field.Error>, "className"> {
93
+ className?: string;
94
+ }
95
+ /**
96
+ * Validation message for the field, wired into `aria-describedby` and
97
+ * announced on appearance (`role="alert"`). In a connected field it renders
98
+ * the form error automatically — the message (or a list when
99
+ * `criteriaMode: "all"` reports several), shown exactly while the field is
100
+ * invalid; `children` replace the message text. In static fields it follows
101
+ * Base UI's native behavior: `match` picks a ValidityState condition (e.g.
102
+ * `match="valueMissing"`) and `children` provide the message.
103
+ */
104
+ declare const FieldError: import("react").ForwardRefExoticComponent<FieldErrorProps & import("react").RefAttributes<HTMLDivElement>>;
105
+ interface FieldItemProps extends Omit<ComponentPropsWithoutRef<typeof Field.Item>, "className"> {
106
+ className?: string;
107
+ }
108
+ /**
109
+ * Groups one option of a checkbox or radio group with its own label and
110
+ * description — inside it, `FieldLabel`/`FieldDescription` attach to that
111
+ * option's control instead of the whole field. Compose with `Fieldset`
112
+ * (legend = the group's name) per option.
113
+ */
114
+ declare const FieldItem: import("react").ForwardRefExoticComponent<FieldItemProps & import("react").RefAttributes<HTMLDivElement>>;
115
+ type FieldValidityProps = ComponentPropsWithoutRef<typeof Field.Validity>;
116
+ /**
117
+ * Render-prop over the field's native ValidityState — for custom validity UI
118
+ * such as inline requirement checklists. Renders no element of its own.
119
+ * Base UI's `Field.Validity`, re-exported unchanged.
120
+ */
121
+ declare const FieldValidity: import("react").FC<import("@base-ui/react").FieldValidityProps>;
122
+ //#endregion
123
+ export { Field$1 as Field, FieldDescription, FieldDescriptionProps, FieldError, FieldErrorProps, FieldItem, FieldItemProps, FieldLabel, FieldLabelProps, FieldLabelVariantsOptions, FieldOrientation, FieldProps, FieldValidity, FieldValidityProps, fieldLabelVariants };
@@ -0,0 +1,241 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { FieldContext } from "./FieldContext.js";
3
+ import { forwardRef, useContext, useMemo } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { Field } from "@base-ui/react/field";
6
+ import { useController, useFormContext } from "react-hook-form";
7
+ //#region src/components/Field/Field.tsx
8
+ const orientationClasses = {
9
+ vertical: "flex min-w-0 flex-col items-stretch gap-1.5",
10
+ horizontal: "grid min-w-0 grid-cols-[auto_minmax(0,1fr)] items-baseline gap-x-3 gap-y-1.5"
11
+ };
12
+ function orientationAttribute(orientation) {
13
+ return { "data-orientation": orientation };
14
+ }
15
+ const EMPTY_MESSAGES = [];
16
+ function StaticField({ forwardedRef, control: _control, required = false, orientation = "vertical", invalid, className, ...rest }) {
17
+ const contextValue = useMemo(() => ({
18
+ required,
19
+ invalid: invalid ?? false,
20
+ control: null,
21
+ errorMessage: null,
22
+ errorMessages: EMPTY_MESSAGES
23
+ }), [required, invalid]);
24
+ return /* @__PURE__ */ jsx(FieldContext.Provider, {
25
+ value: contextValue,
26
+ children: /* @__PURE__ */ jsx(Field.Root, {
27
+ ref: forwardedRef,
28
+ invalid,
29
+ className: cn(orientationClasses[orientation], className),
30
+ ...orientationAttribute(orientation),
31
+ ...rest
32
+ })
33
+ });
34
+ }
35
+ function ConnectedField({ forwardedRef, control, name, required = false, orientation = "vertical", disabled, invalid, touched, dirty, className, ...rest }) {
36
+ const { field, fieldState } = useController({
37
+ name,
38
+ control
39
+ });
40
+ const resolvedInvalid = invalid ?? Boolean(fieldState.error);
41
+ const errorMessage = fieldState.error?.message ?? null;
42
+ const errorMessages = useMemo(() => {
43
+ const error = fieldState.error;
44
+ if (!error) return EMPTY_MESSAGES;
45
+ const messages = /* @__PURE__ */ new Set();
46
+ if (error.message) messages.add(error.message);
47
+ if (error.types) {
48
+ for (const typeMessage of Object.values(error.types)) if (typeof typeMessage === "string") messages.add(typeMessage);
49
+ else if (Array.isArray(typeMessage)) {
50
+ for (const message of typeMessage) if (typeof message === "string") messages.add(message);
51
+ }
52
+ }
53
+ return [...messages];
54
+ }, [fieldState.error]);
55
+ const contextValue = useMemo(() => ({
56
+ required,
57
+ invalid: resolvedInvalid,
58
+ control: {
59
+ name: field.name,
60
+ value: field.value,
61
+ disabled: field.disabled || disabled || void 0,
62
+ onChange: field.onChange,
63
+ onBlur: field.onBlur,
64
+ ref: field.ref
65
+ },
66
+ errorMessage,
67
+ errorMessages
68
+ }), [
69
+ required,
70
+ resolvedInvalid,
71
+ field.name,
72
+ field.value,
73
+ field.disabled,
74
+ field.onChange,
75
+ field.onBlur,
76
+ field.ref,
77
+ disabled,
78
+ errorMessage,
79
+ errorMessages
80
+ ]);
81
+ return /* @__PURE__ */ jsx(FieldContext.Provider, {
82
+ value: contextValue,
83
+ children: /* @__PURE__ */ jsx(Field.Root, {
84
+ ref: forwardedRef,
85
+ name: field.name,
86
+ invalid: resolvedInvalid,
87
+ touched: touched ?? fieldState.isTouched,
88
+ dirty: dirty ?? fieldState.isDirty,
89
+ disabled,
90
+ className: cn(orientationClasses[orientation], className),
91
+ ...orientationAttribute(orientation),
92
+ ...rest
93
+ })
94
+ });
95
+ }
96
+ const FieldImpl = forwardRef((props, ref) => {
97
+ const formContext = useFormContext();
98
+ return props.name != null && (props.control ?? formContext) != null ? /* @__PURE__ */ jsx(ConnectedField, {
99
+ ...props,
100
+ forwardedRef: ref
101
+ }) : /* @__PURE__ */ jsx(StaticField, {
102
+ ...props,
103
+ forwardedRef: ref
104
+ });
105
+ });
106
+ FieldImpl.displayName = "Field";
107
+ /**
108
+ * Labelling + validation wrapper for a single form control, built on Base UI's
109
+ * Field. It associates `FieldLabel`, `FieldDescription`, and `FieldError`
110
+ * with the control automatically (ids, `aria-describedby`) and exposes state
111
+ * data-attributes (`data-invalid`, `data-touched`, `data-dirty`,
112
+ * `data-filled`, `data-focused`) on every part for styling.
113
+ *
114
+ * Give it a `name` inside `<Form form={…}>` (or pass `control`) to connect it
115
+ * to React Hook Form — validation state then flows in from the form and the
116
+ * `Input` inside is wired automatically. Without a form library it works as a
117
+ * native field: constraint attributes plus the `validate`/`validationMode`
118
+ * props drive `FieldError` via its `match` prop.
119
+ */
120
+ const Field$1 = FieldImpl;
121
+ Field$1.displayName = "Field";
122
+ const labelClasses = "font-sans text-sm font-medium text-foreground data-disabled:opacity-50";
123
+ /**
124
+ * Class list for an element styled as a field label — for labelling controls
125
+ * that live outside a `Field` (e.g. a filter Select in a toolbar) so every
126
+ * label in the product shares one look.
127
+ */
128
+ function fieldLabelVariants({ className } = {}) {
129
+ return cn(labelClasses, className);
130
+ }
131
+ /**
132
+ * Visible label, automatically associated with the field's control — clicking
133
+ * it focuses the control. When the `Field` is `required`, a decorative
134
+ * asterisk (hidden from assistive technology, which hears the control's
135
+ * required state instead) is appended. For checkbox/radio/switch rows, wrap
136
+ * the control instead: `<FieldLabel><Switch /> Notifications</FieldLabel>`.
137
+ * When the control is button-based (Select, Combobox triggers), pass
138
+ * `nativeLabel={false}` — the label then renders as a `<div>` wired via
139
+ * `aria-labelledby`, so hovering or clicking it doesn't act on the button.
140
+ */
141
+ const FieldLabel = forwardRef(({ className, children, nativeLabel, render, ...rest }, ref) => {
142
+ const context = useContext(FieldContext);
143
+ return /* @__PURE__ */ jsxs(Field.Label, {
144
+ ref,
145
+ nativeLabel,
146
+ render: render ?? (nativeLabel === false ? /* @__PURE__ */ jsx("div", {}) : void 0),
147
+ className: cn(labelClasses, className),
148
+ ...rest,
149
+ children: [children, context?.required ? /* @__PURE__ */ jsx("span", {
150
+ "aria-hidden": "true",
151
+ className: "ms-0.5 text-destructive",
152
+ children: "*"
153
+ }) : null]
154
+ });
155
+ });
156
+ FieldLabel.displayName = "FieldLabel";
157
+ const descriptionClasses = "col-start-2 font-sans text-xs text-muted-foreground data-disabled:opacity-50";
158
+ /**
159
+ * Persistent supporting copy for the field, announced via `aria-describedby`.
160
+ * It stays visible while an error shows — the hint is exactly what the user
161
+ * needs to fix the problem. Order it in the children wherever the design
162
+ * calls for (before or after the control); the association is automatic.
163
+ */
164
+ const FieldDescription = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx(Field.Description, {
165
+ ref,
166
+ className: cn(descriptionClasses, className),
167
+ ...rest
168
+ }));
169
+ FieldDescription.displayName = "FieldDescription";
170
+ const errorClasses = "col-start-2 flex items-start gap-1.5 font-sans text-xs font-medium text-error-700 motion-safe:transition-opacity motion-safe:duration-150 motion-safe:data-starting-style:opacity-0";
171
+ function ErrorIcon() {
172
+ return /* @__PURE__ */ jsxs("svg", {
173
+ viewBox: "0 0 24 24",
174
+ fill: "none",
175
+ stroke: "currentColor",
176
+ strokeWidth: 2,
177
+ strokeLinecap: "round",
178
+ "aria-hidden": "true",
179
+ className: "mt-px size-3.5 shrink-0",
180
+ children: [
181
+ /* @__PURE__ */ jsx("circle", {
182
+ cx: "12",
183
+ cy: "12",
184
+ r: "10"
185
+ }),
186
+ /* @__PURE__ */ jsx("path", { d: "M12 8v4" }),
187
+ /* @__PURE__ */ jsx("path", { d: "M12 16h.01" })
188
+ ]
189
+ });
190
+ }
191
+ /**
192
+ * Validation message for the field, wired into `aria-describedby` and
193
+ * announced on appearance (`role="alert"`). In a connected field it renders
194
+ * the form error automatically — the message (or a list when
195
+ * `criteriaMode: "all"` reports several), shown exactly while the field is
196
+ * invalid; `children` replace the message text. In static fields it follows
197
+ * Base UI's native behavior: `match` picks a ValidityState condition (e.g.
198
+ * `match="valueMissing"`) and `children` provide the message.
199
+ */
200
+ const FieldError = forwardRef(({ className, children, match, ...rest }, ref) => {
201
+ const context = useContext(FieldContext);
202
+ const connected = context?.control != null;
203
+ const connectedMessage = connected && context ? context.errorMessages.length > 1 ? /* @__PURE__ */ jsx("ul", {
204
+ className: "flex list-disc flex-col gap-0.5 ps-4",
205
+ children: context.errorMessages.map((message) => /* @__PURE__ */ jsx("li", { children: message }, message))
206
+ }) : context.errorMessage : void 0;
207
+ const content = children ?? connectedMessage;
208
+ const resolvedMatch = match ?? (connected && context ? context.invalid && content != null : void 0);
209
+ return /* @__PURE__ */ jsx(Field.Error, {
210
+ ref,
211
+ role: "alert",
212
+ match: resolvedMatch,
213
+ className: cn(errorClasses, className),
214
+ ...rest,
215
+ children: content != null ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ErrorIcon, {}), /* @__PURE__ */ jsx("span", {
216
+ className: "min-w-0",
217
+ children: content
218
+ })] }) : void 0
219
+ });
220
+ });
221
+ FieldError.displayName = "FieldError";
222
+ /**
223
+ * Groups one option of a checkbox or radio group with its own label and
224
+ * description — inside it, `FieldLabel`/`FieldDescription` attach to that
225
+ * option's control instead of the whole field. Compose with `Fieldset`
226
+ * (legend = the group's name) per option.
227
+ */
228
+ const FieldItem = forwardRef(({ className, ...rest }, ref) => /* @__PURE__ */ jsx(Field.Item, {
229
+ ref,
230
+ className: cn("flex min-w-0 flex-col gap-1", className),
231
+ ...rest
232
+ }));
233
+ FieldItem.displayName = "FieldItem";
234
+ /**
235
+ * Render-prop over the field's native ValidityState — for custom validity UI
236
+ * such as inline requirement checklists. Renders no element of its own.
237
+ * Base UI's `Field.Validity`, re-exported unchanged.
238
+ */
239
+ const FieldValidity = Field.Validity;
240
+ //#endregion
241
+ export { Field$1 as Field, FieldDescription, FieldError, FieldItem, FieldLabel, FieldValidity, fieldLabelVariants };