@ui-sdk/react 0.0.0-stage → 0.1.0-beta.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 (247) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +10 -2
  3. package/dist/accordion.d.ts +331 -0
  4. package/dist/accordion.js +25 -0
  5. package/dist/agent.d.ts +2 -0
  6. package/dist/agent.js +8 -0
  7. package/dist/alert-dialog.d.ts +56 -0
  8. package/dist/alert-dialog.js +45 -0
  9. package/dist/async-options.d.ts +22 -0
  10. package/dist/async-options.js +56 -0
  11. package/dist/autocomplete.d.ts +102 -0
  12. package/dist/autocomplete.js +195 -0
  13. package/dist/avatar.d.ts +301 -0
  14. package/dist/avatar.js +17 -0
  15. package/dist/button.d.ts +21 -0
  16. package/dist/button.js +45 -0
  17. package/dist/calendar-context.d.ts +10 -0
  18. package/dist/calendar-context.js +9 -0
  19. package/dist/calendar.d.ts +80 -0
  20. package/dist/calendar.js +257 -0
  21. package/dist/carousel.d.ts +52 -0
  22. package/dist/carousel.js +151 -0
  23. package/dist/checkbox.d.ts +24 -0
  24. package/dist/checkbox.js +98 -0
  25. package/dist/children.d.ts +38 -0
  26. package/dist/children.js +63 -0
  27. package/dist/collapsible.d.ts +302 -0
  28. package/dist/collapsible.js +19 -0
  29. package/dist/color-picker.d.ts +72 -0
  30. package/dist/color-picker.js +133 -0
  31. package/dist/color.d.ts +2 -0
  32. package/dist/color.js +22 -0
  33. package/dist/combobox.d.ts +152 -0
  34. package/dist/combobox.js +338 -0
  35. package/dist/command.d.ts +88 -0
  36. package/dist/command.js +233 -0
  37. package/dist/controller-target.d.ts +3 -0
  38. package/dist/controller-target.js +59 -0
  39. package/dist/date-input.d.ts +19 -0
  40. package/dist/date-input.js +58 -0
  41. package/dist/date-picker.d.ts +47 -0
  42. package/dist/date-picker.js +310 -0
  43. package/dist/date.d.ts +2 -0
  44. package/dist/date.js +60 -0
  45. package/dist/dialog-parts.d.ts +23 -0
  46. package/dist/dialog-parts.js +142 -0
  47. package/dist/dialog.d.ts +57 -0
  48. package/dist/dialog.js +32 -0
  49. package/dist/drawer.d.ts +70 -0
  50. package/dist/drawer.js +158 -0
  51. package/dist/editor-context.d.ts +4 -0
  52. package/dist/editor-context.js +9 -0
  53. package/dist/field-context.d.ts +47 -0
  54. package/dist/field-context.js +87 -0
  55. package/dist/field.d.ts +49 -0
  56. package/dist/field.js +169 -0
  57. package/dist/file-input.d.ts +46 -0
  58. package/dist/file-input.js +170 -0
  59. package/dist/form-inputs.d.ts +5 -0
  60. package/dist/form-inputs.js +22 -0
  61. package/dist/gesture.d.ts +1 -0
  62. package/dist/gesture.js +16 -0
  63. package/dist/history.d.ts +2 -0
  64. package/dist/history.js +12 -0
  65. package/dist/hover-card.d.ts +33 -0
  66. package/dist/hover-card.js +84 -0
  67. package/dist/image-cropper.d.ts +333 -0
  68. package/dist/image-cropper.js +37 -0
  69. package/dist/image.d.ts +2 -0
  70. package/dist/image.js +6 -0
  71. package/dist/input.d.ts +22 -0
  72. package/dist/input.js +51 -0
  73. package/dist/label.d.ts +294 -0
  74. package/dist/label.js +9 -0
  75. package/dist/list-items.d.ts +15 -0
  76. package/dist/list-items.js +39 -0
  77. package/dist/list-text.d.ts +4 -0
  78. package/dist/list-text.js +15 -0
  79. package/dist/listbox.d.ts +56 -0
  80. package/dist/listbox.js +122 -0
  81. package/dist/menu.d.ts +116 -0
  82. package/dist/menu.js +426 -0
  83. package/dist/menubar-context.d.ts +4 -0
  84. package/dist/menubar-context.js +7 -0
  85. package/dist/menubar.d.ts +11 -0
  86. package/dist/menubar.js +32 -0
  87. package/dist/meter.d.ts +312 -0
  88. package/dist/meter.js +30 -0
  89. package/dist/navigation-menu.d.ts +61 -0
  90. package/dist/navigation-menu.js +169 -0
  91. package/dist/number-input.d.ts +44 -0
  92. package/dist/number-input.js +185 -0
  93. package/dist/number.d.ts +2 -0
  94. package/dist/number.js +40 -0
  95. package/dist/observe.d.ts +2 -0
  96. package/dist/observe.js +8 -0
  97. package/dist/otp-input.d.ts +29 -0
  98. package/dist/otp-input.js +94 -0
  99. package/dist/overlays.d.ts +26 -0
  100. package/dist/overlays.js +82 -0
  101. package/dist/pagination.d.ts +336 -0
  102. package/dist/pagination.js +71 -0
  103. package/dist/password-input.d.ts +23 -0
  104. package/dist/password-input.js +65 -0
  105. package/dist/popover.d.ts +54 -0
  106. package/dist/popover.js +151 -0
  107. package/dist/popup.d.ts +41 -0
  108. package/dist/popup.js +180 -0
  109. package/dist/preferences.d.ts +35 -0
  110. package/dist/preferences.js +93 -0
  111. package/dist/primitive.d.ts +2 -0
  112. package/dist/primitive.js +14 -0
  113. package/dist/progress.d.ts +312 -0
  114. package/dist/progress.js +30 -0
  115. package/dist/radio.d.ts +22 -0
  116. package/dist/radio.js +86 -0
  117. package/dist/rating.d.ts +20 -0
  118. package/dist/rating.js +94 -0
  119. package/dist/render-element.d.ts +35 -0
  120. package/dist/render-element.js +103 -0
  121. package/dist/resizable.d.ts +302 -0
  122. package/dist/resizable.js +23 -0
  123. package/dist/scroll-area.d.ts +324 -0
  124. package/dist/scroll-area.js +49 -0
  125. package/dist/segmented-control.d.ts +24 -0
  126. package/dist/segmented-control.js +78 -0
  127. package/dist/segmented-input.d.ts +15 -0
  128. package/dist/segmented-input.js +48 -0
  129. package/dist/select.d.ts +125 -0
  130. package/dist/select.js +330 -0
  131. package/dist/separator.d.ts +290 -0
  132. package/dist/separator.js +9 -0
  133. package/dist/shortcuts.d.ts +32 -0
  134. package/dist/shortcuts.js +61 -0
  135. package/dist/slider.d.ts +38 -0
  136. package/dist/slider.js +163 -0
  137. package/dist/switch.d.ts +15 -0
  138. package/dist/switch.js +39 -0
  139. package/dist/tabs.d.ts +331 -0
  140. package/dist/tabs.js +28 -0
  141. package/dist/text-control.d.ts +22 -0
  142. package/dist/text-control.js +24 -0
  143. package/dist/text-match.d.ts +2 -0
  144. package/dist/text-match.js +8 -0
  145. package/dist/textarea.d.ts +10 -0
  146. package/dist/textarea.js +48 -0
  147. package/dist/time-input.d.ts +19 -0
  148. package/dist/time-input.js +63 -0
  149. package/dist/timeline.d.ts +327 -0
  150. package/dist/timeline.js +31 -0
  151. package/dist/toast-parts.d.ts +63 -0
  152. package/dist/toast-parts.js +144 -0
  153. package/dist/toast.d.ts +2 -0
  154. package/dist/toast.js +22 -0
  155. package/dist/toggle.d.ts +23 -0
  156. package/dist/toggle.js +76 -0
  157. package/dist/token-input.d.ts +35 -0
  158. package/dist/token-input.js +100 -0
  159. package/dist/toolbar-context.d.ts +6 -0
  160. package/dist/toolbar-context.js +16 -0
  161. package/dist/toolbar.d.ts +38 -0
  162. package/dist/toolbar.js +63 -0
  163. package/dist/tooltip.d.ts +39 -0
  164. package/dist/tooltip.js +108 -0
  165. package/dist/tree.d.ts +51 -0
  166. package/dist/tree.js +150 -0
  167. package/dist/trigger-menu.d.ts +83 -0
  168. package/dist/trigger-menu.js +167 -0
  169. package/dist/use-primitive.d.ts +178 -0
  170. package/dist/use-primitive.js +674 -0
  171. package/dist/waterfall.d.ts +80 -0
  172. package/dist/waterfall.js +108 -0
  173. package/docs/README.md +89 -0
  174. package/docs/agents.md +1523 -0
  175. package/docs/components/accordion.md +1391 -0
  176. package/docs/components/alert-dialog.md +850 -0
  177. package/docs/components/autocomplete.md +1963 -0
  178. package/docs/components/avatar.md +252 -0
  179. package/docs/components/button.md +444 -0
  180. package/docs/components/calendar.md +1687 -0
  181. package/docs/components/carousel.md +1244 -0
  182. package/docs/components/checkbox.md +1069 -0
  183. package/docs/components/collapsible.md +567 -0
  184. package/docs/components/color-picker.md +736 -0
  185. package/docs/components/combobox.md +3647 -0
  186. package/docs/components/command.md +1573 -0
  187. package/docs/components/date-input.md +608 -0
  188. package/docs/components/date-picker.md +1266 -0
  189. package/docs/components/dialog.md +1469 -0
  190. package/docs/components/drawer.md +1197 -0
  191. package/docs/components/field.md +549 -0
  192. package/docs/components/file-input.md +609 -0
  193. package/docs/components/hover-card.md +514 -0
  194. package/docs/components/image-cropper.md +579 -0
  195. package/docs/components/input.md +301 -0
  196. package/docs/components/label.md +217 -0
  197. package/docs/components/listbox.md +1130 -0
  198. package/docs/components/menu.md +1286 -0
  199. package/docs/components/menubar.md +455 -0
  200. package/docs/components/meter.md +304 -0
  201. package/docs/components/navigation-menu.md +1581 -0
  202. package/docs/components/number-input.md +1086 -0
  203. package/docs/components/otp-input.md +565 -0
  204. package/docs/components/pagination.md +648 -0
  205. package/docs/components/password-input.md +737 -0
  206. package/docs/components/popover.md +1552 -0
  207. package/docs/components/preferences.md +220 -0
  208. package/docs/components/progress.md +443 -0
  209. package/docs/components/radio.md +846 -0
  210. package/docs/components/rating.md +458 -0
  211. package/docs/components/resizable.md +982 -0
  212. package/docs/components/scroll-area.md +980 -0
  213. package/docs/components/segmented-control.md +465 -0
  214. package/docs/components/select.md +2133 -0
  215. package/docs/components/separator.md +243 -0
  216. package/docs/components/slider.md +1169 -0
  217. package/docs/components/switch.md +613 -0
  218. package/docs/components/tabs.md +1014 -0
  219. package/docs/components/textarea.md +318 -0
  220. package/docs/components/time-input.md +231 -0
  221. package/docs/components/timeline.md +677 -0
  222. package/docs/components/toast.md +1395 -0
  223. package/docs/components/toggle.md +541 -0
  224. package/docs/components/token-input.md +1007 -0
  225. package/docs/components/toolbar.md +787 -0
  226. package/docs/components/tooltip.md +884 -0
  227. package/docs/components/tree.md +1346 -0
  228. package/docs/components/trigger-menu.md +1257 -0
  229. package/docs/components/waterfall.md +754 -0
  230. package/docs/controllers.md +89 -0
  231. package/docs/core.md +8027 -0
  232. package/docs/custom-parts.md +120 -0
  233. package/docs/first-component.md +83 -0
  234. package/docs/forms.md +148 -0
  235. package/docs/hooks/async-options.md +366 -0
  236. package/docs/hooks/shortcuts.md +221 -0
  237. package/docs/installation.md +45 -0
  238. package/docs/introduction.md +32 -0
  239. package/docs/lists-and-menus.md +170 -0
  240. package/docs/llms.txt +1844 -0
  241. package/docs/parts-and-composition.md +93 -0
  242. package/docs/popups.md +117 -0
  243. package/docs/rendering.md +121 -0
  244. package/docs/server-rendering.md +253 -0
  245. package/docs/state-and-events.md +105 -0
  246. package/docs/styling-and-animation.md +176 -0
  247. package/package.json +333 -3
package/dist/drawer.js ADDED
@@ -0,0 +1,158 @@
1
+ "use client";
2
+ // src/drawer.tsx
3
+ import {
4
+ drawer
5
+ } from "@ui-sdk/core/drawer";
6
+ import * as React from "react";
7
+ import {
8
+ Connected,
9
+ renderPopup,
10
+ sheetViewport,
11
+ useControllerEntry,
12
+ useOwnContainer,
13
+ usePopupContainer
14
+ } from "./popup.js";
15
+ import {
16
+ createParts,
17
+ HandleScope,
18
+ renderElement,
19
+ useHandle,
20
+ useNearest,
21
+ usePart,
22
+ usePrimitive
23
+ } from "./use-primitive.js";
24
+ import { createDrawerController, sheetPhysics } from "@ui-sdk/core/drawer";
25
+ import { jsx } from "react/jsx-runtime";
26
+ var parts = createParts(drawer, {
27
+ trigger: "button",
28
+ handle: "button",
29
+ title: "h2",
30
+ description: "p",
31
+ close: "button",
32
+ outlet: "div"
33
+ });
34
+ var ContainerContext = React.createContext(void 0);
35
+ var TriggerContext = React.createContext(null);
36
+ function Drawer({ children, container, ...options }) {
37
+ const handle = usePrimitive(drawer, options);
38
+ useControllerEntry(options.controller, handle);
39
+ return /* @__PURE__ */ jsx(HandleScope, { handle, children: /* @__PURE__ */ jsx(ContainerContext.Provider, { value: container, children }) });
40
+ }
41
+ function DrawerTrigger({ controller, ...props }) {
42
+ const {
43
+ disabled,
44
+ focusableWhenDisabled,
45
+ payload: _,
46
+ shortcut,
47
+ render,
48
+ ...rest
49
+ } = props;
50
+ const unconnected = () => renderElement(
51
+ "button",
52
+ {
53
+ type: "button",
54
+ disabled: disabled && !focusableWhenDisabled,
55
+ "aria-disabled": disabled && focusableWhenDisabled || void 0,
56
+ ...rest
57
+ },
58
+ render,
59
+ {
60
+ open: false,
61
+ disabled: !!disabled
62
+ }
63
+ );
64
+ return /* @__PURE__ */ jsx(TriggerContext.Provider, { value: { shortcut }, children: /* @__PURE__ */ jsx(
65
+ Connected,
66
+ {
67
+ primitive: drawer,
68
+ controller,
69
+ fallback: unconnected,
70
+ children: /* @__PURE__ */ jsx(parts.Trigger, { ...props })
71
+ }
72
+ ) });
73
+ }
74
+ function DrawerBackdrop(props) {
75
+ const target = usePopupContainer(React.useContext(ContainerContext));
76
+ const element = usePart(drawer, "backdrop", {}, props);
77
+ return element && renderPopup(element, target);
78
+ }
79
+ function DrawerContent({
80
+ initialFocus,
81
+ finalFocus,
82
+ keepMounted,
83
+ container,
84
+ render,
85
+ ...props
86
+ }) {
87
+ const handle = useHandle(drawer);
88
+ const target = usePopupContainer(useOwnContainer(container, ContainerContext));
89
+ const partProps = {
90
+ ...props,
91
+ render: sheetViewport(handle, render)
92
+ };
93
+ const element = usePart(
94
+ handle,
95
+ "content",
96
+ { initialFocus, finalFocus, keepMounted },
97
+ partProps
98
+ );
99
+ return element && renderPopup(element, target);
100
+ }
101
+ var DrawerHandle = parts.Handle;
102
+ var DrawerTitle = parts.Title;
103
+ var DrawerDescription = parts.Description;
104
+ var DrawerClose = parts.Close;
105
+ function DrawerShortcut(props) {
106
+ const trigger = React.useContext(TriggerContext);
107
+ if (useNearest(drawer)) {
108
+ return /* @__PURE__ */ jsx(ShortcutPart, { inherited: trigger?.shortcut, ...props });
109
+ }
110
+ if (trigger) {
111
+ return null;
112
+ }
113
+ throw new Error("Drawer parts must be used inside <Drawer>.");
114
+ }
115
+ var text = (state) => state.text;
116
+ function ShortcutPart({
117
+ inherited,
118
+ shortcut,
119
+ children = text,
120
+ ...props
121
+ }) {
122
+ return usePart(
123
+ drawer,
124
+ "shortcut",
125
+ { shortcut: shortcut ?? inherited },
126
+ { ...props, children },
127
+ "span"
128
+ );
129
+ }
130
+ function DrawerOutlet({
131
+ controller,
132
+ ...props
133
+ }) {
134
+ const { keyframes: _, render, ...rest } = props;
135
+ return /* @__PURE__ */ jsx(
136
+ Connected,
137
+ {
138
+ primitive: drawer,
139
+ controller,
140
+ fallback: () => renderElement("div", rest, render, { open: false }),
141
+ children: /* @__PURE__ */ jsx(parts.Outlet, { ...props })
142
+ }
143
+ );
144
+ }
145
+ export {
146
+ Drawer,
147
+ DrawerBackdrop,
148
+ DrawerClose,
149
+ DrawerContent,
150
+ DrawerDescription,
151
+ DrawerHandle,
152
+ DrawerOutlet,
153
+ DrawerShortcut,
154
+ DrawerTitle,
155
+ DrawerTrigger,
156
+ createDrawerController,
157
+ sheetPhysics
158
+ };
@@ -0,0 +1,4 @@
1
+ import type { TextEditorAdapter } from "@ui-sdk/core/trigger-menu";
2
+ import * as React from "react";
3
+ declare const EditorContext: React.Context<TextEditorAdapter | undefined>;
4
+ export { EditorContext };
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ // src/editor-context.ts
3
+ import * as React from "react";
4
+ var EditorContext = React.createContext(
5
+ void 0
6
+ );
7
+ export {
8
+ EditorContext
9
+ };
@@ -0,0 +1,47 @@
1
+ import type { field } from "@ui-sdk/core/field";
2
+ import * as React from "react";
3
+ import { type PartProps, type PrimitiveHandle, type RenderProp } from "./use-primitive.js";
4
+ type FieldContextValue = PrimitiveHandle<typeof field> & {
5
+ name?: string;
6
+ disabled?: boolean;
7
+ };
8
+ declare const FieldContext: React.Context<FieldContextValue | null>;
9
+ /**
10
+ * Controls inside a field take its name and disabled state, and its ids and
11
+ * validity through the field's control slot. Null outside a field. The control
12
+ * re-renders when the field changes, like when its label or errors appear.
13
+ * The control takes the field's id, so the label points at it from the
14
+ * server's HTML on, unless its own props give one. A control whose component
15
+ * makes the id it renders, like a select's trigger, passes those props as `own`.
16
+ * @stable
17
+ */
18
+ declare function useFieldControl(own?: {
19
+ id?: string;
20
+ }): {
21
+ name: string | undefined;
22
+ disabled: boolean | undefined;
23
+ props: (props: Record<string, any>) => {
24
+ "aria-labelledby": any;
25
+ "data-slot": any;
26
+ };
27
+ } | null;
28
+ declare function useJoinField(field: FieldContextValue | null, own?: {
29
+ id?: string;
30
+ }): {
31
+ name: string | undefined;
32
+ disabled: boolean | undefined;
33
+ props: (props: Record<string, any>) => {
34
+ "aria-labelledby": any;
35
+ "data-slot": any;
36
+ };
37
+ } | null;
38
+ declare function ownDescription<Props extends Record<string, any>, Render>(props: Props, render: Render): readonly [Props, Render];
39
+ /**
40
+ * A control's `render`: its element, with the field's attributes for its
41
+ * control merged in when it's in a field, and then `after`, like the hidden
42
+ * native input of a checkbox.
43
+ */
44
+ declare function controlRender<State>(field: ReturnType<typeof useFieldControl>, tag: string, render?: RenderProp<State>, after?: React.ReactNode): RenderProp<State> | ((props: Record<string, any>, state: State) => React.FunctionComponentElement<React.FragmentProps>) | undefined;
45
+ type ButtonControlProps<State> = Omit<PartProps<"button", State>, "value" | "name" | "form" | "defaultChecked" | "defaultValue" | "onChange" | "onSelect">;
46
+ declare function useFieldControlId(): string | undefined;
47
+ export { type ButtonControlProps, controlRender, FieldContext, type FieldContextValue, ownDescription, useFieldControl, useFieldControlId, useJoinField, };
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ // src/field-context.ts
3
+ import { fieldControlId, madeLabel, renderVersion } from "@ui-sdk/core/renderer";
4
+ import * as React from "react";
5
+ import {
6
+ renderElement,
7
+ slotIn
8
+ } from "./use-primitive.js";
9
+ var FieldContext = React.createContext(null);
10
+ var noop = () => () => {
11
+ };
12
+ var zero = () => 0;
13
+ function useFieldControl(own) {
14
+ return useJoinField(React.useContext(FieldContext), own);
15
+ }
16
+ function useJoinField(field, own) {
17
+ const version = field ? () => renderVersion(field.instance) : zero;
18
+ React.useSyncExternalStore(
19
+ field ? field.instance.subscribe : noop,
20
+ version,
21
+ version
22
+ );
23
+ if (!field) {
24
+ return null;
25
+ }
26
+ return {
27
+ name: field.name,
28
+ disabled: field.disabled,
29
+ // Merges the field's attributes for its control into the control's props,
30
+ // keeping the control's own description ahead of the field's. The field
31
+ // decides the id.
32
+ props: (props) => {
33
+ const label = props["aria-labelledby"];
34
+ const merged = slotIn(
35
+ field,
36
+ "control",
37
+ { id: (own ?? props).id, describedBy: props["aria-describedby"] },
38
+ {
39
+ ...props,
40
+ id: void 0,
41
+ "aria-labelledby": madeLabel(label) ? void 0 : label
42
+ }
43
+ );
44
+ return {
45
+ ...merged,
46
+ "aria-labelledby": merged["aria-labelledby"] ?? label,
47
+ "data-slot": props["data-slot"]
48
+ };
49
+ }
50
+ };
51
+ }
52
+ function ownDescription(props, render) {
53
+ const own = React.isValidElement(render) ? render.props["aria-describedby"] : void 0;
54
+ if (own === void 0 || !React.isValidElement(render)) {
55
+ return [props, render];
56
+ }
57
+ const element = React.cloneElement(render, {
58
+ "aria-describedby": void 0
59
+ });
60
+ return [{ ...props, "aria-describedby": own }, element];
61
+ }
62
+ function controlRender(field, tag, render, after) {
63
+ if (!field && !after) {
64
+ return render;
65
+ }
66
+ return (props, state) => {
67
+ const [own, element] = field ? ownDescription(props, render) : [props, render];
68
+ return React.createElement(
69
+ React.Fragment,
70
+ null,
71
+ renderElement(tag, field ? field.props(own) : own, element, state),
72
+ after
73
+ );
74
+ };
75
+ }
76
+ function useFieldControlId() {
77
+ const field = React.useContext(FieldContext);
78
+ return field ? fieldControlId(field.api.id) : void 0;
79
+ }
80
+ export {
81
+ FieldContext,
82
+ controlRender,
83
+ ownDescription,
84
+ useFieldControl,
85
+ useFieldControlId,
86
+ useJoinField
87
+ };
@@ -0,0 +1,49 @@
1
+ import { type FieldDescriptionState, type FieldErrorProps, type FieldErrorState, type FieldOptions, type FieldSetOptions, type FieldSetState, type FieldState } from "@ui-sdk/core/field";
2
+ import * as React from "react";
3
+ import { type PartProps } from "./use-primitive.js";
4
+ /**
5
+ * Ties a form control to its label, description and error messages.
6
+ * @stable
7
+ */
8
+ declare function Field({ name, disabled, invalid, debug, ...props }: FieldOptions & PartProps<"div", FieldState>): React.JSX.Element;
9
+ /**
10
+ * The field's label, which names its control. Outside a Field it's a plain
11
+ * <label>, which labels the control inside it, like a card around a whole Field.
12
+ * @stable
13
+ */
14
+ declare function FieldLabel(props: PartProps<"label", FieldState>): React.JSX.Element;
15
+ /**
16
+ * Describes its Field. Right inside a FieldSet, outside any Field, it describes
17
+ * the group, so screen readers say it as focus enters the group.
18
+ * @stable
19
+ */
20
+ declare function FieldDescription(props: PartProps<"p", FieldDescriptionState>): React.JSX.Element;
21
+ /**
22
+ * Shows while the field shows as invalid. Without children, it shows the
23
+ * browser's message for the current problem.
24
+ * @stable
25
+ */
26
+ declare function FieldError({ match, children, ...props }: PartProps<"div", FieldErrorState> & FieldErrorProps): React.JSX.Element | null;
27
+ /**
28
+ * A native control: an <input> by default, or anything through `render`.
29
+ * @stable
30
+ */
31
+ declare function FieldControl({ name, render, ...rest }: PartProps<"input", FieldState>): React.JSX.Element;
32
+ /**
33
+ * A native <fieldset>, so `disabled` disables every control inside it.
34
+ * @stable
35
+ */
36
+ declare function FieldSet({ disabled, debug, ...props }: FieldSetOptions & Omit<PartProps<"fieldset", FieldSetState>, "disabled">): React.JSX.Element;
37
+ /**
38
+ * Names the field set. Keep it the set's first child, where a <legend> names it natively.
39
+ * @stable
40
+ */
41
+ declare function FieldLegend(props: PartProps<"legend", FieldSetState>): React.JSX.Element | null;
42
+ /**
43
+ * Lays fields out. It has no role: a FieldSet is what names and disables a group.
44
+ * @stable
45
+ */
46
+ declare function FieldGroup(props: PartProps<"div">): React.JSX.Element | null;
47
+ export { Field, FieldControl, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSet, };
48
+ export type { FieldApi, FieldDescriptionState, FieldErrorProps, FieldErrorState, FieldGroupPrimitive, FieldOptions, FieldPrimitive, FieldSetOptions, FieldSetPrimitive, FieldSetState, FieldState, ValidityKey, } from "@ui-sdk/core/field";
49
+ export { useFieldControl } from "./field-context.js";
package/dist/field.js ADDED
@@ -0,0 +1,169 @@
1
+ "use client";
2
+ // src/field.tsx
3
+ import {
4
+ fieldGroup,
5
+ field as fieldPrimitive,
6
+ fieldSet
7
+ } from "@ui-sdk/core/field";
8
+ import {
9
+ checkFieldOutside,
10
+ fieldOutsideAttrs,
11
+ fieldOutsideErrorShown,
12
+ fieldOutsideState
13
+ } from "@ui-sdk/core/renderer";
14
+ import * as React from "react";
15
+ import { FieldContext, ownDescription } from "./field-context.js";
16
+ import {
17
+ extendHandle,
18
+ mergeProps,
19
+ renderElement,
20
+ usePart,
21
+ usePrimitive
22
+ } from "./use-primitive.js";
23
+ import { useFieldControl } from "./field-context.js";
24
+ import { jsx } from "react/jsx-runtime";
25
+ var DescribedContext = React.createContext(null);
26
+ var outsideRefs = {
27
+ label: (el) => checkFieldOutside(
28
+ el,
29
+ "label",
30
+ "Put the control inside it, or point its `htmlFor` at the control."
31
+ ),
32
+ control: (el) => checkFieldOutside(el, "control")
33
+ };
34
+ function outside(slot, tag, { render, ...props }) {
35
+ const ref = outsideRefs[slot];
36
+ return renderElement(
37
+ tag,
38
+ mergeProps(fieldOutsideAttrs(slot), props, { ref }),
39
+ render,
40
+ fieldOutsideState
41
+ );
42
+ }
43
+ function InField({
44
+ field,
45
+ slot,
46
+ part,
47
+ props,
48
+ tag
49
+ }) {
50
+ return usePart(field, slot, part, props, tag);
51
+ }
52
+ function Field({
53
+ name,
54
+ disabled,
55
+ invalid,
56
+ debug,
57
+ ...props
58
+ }) {
59
+ const field = usePrimitive(fieldPrimitive, { name, disabled, invalid, debug });
60
+ const context = React.useMemo(
61
+ () => extendHandle(field, { name, disabled }),
62
+ [field, name, disabled]
63
+ );
64
+ return /* @__PURE__ */ jsx(FieldContext.Provider, { value: context, children: /* @__PURE__ */ jsx(DescribedContext.Provider, { value: field, children: usePart(field, "root", {}, props, "div") }) });
65
+ }
66
+ function FieldLabel(props) {
67
+ const field = React.useContext(FieldContext);
68
+ if (!field) {
69
+ return outside("label", "label", props);
70
+ }
71
+ return /* @__PURE__ */ jsx(
72
+ InField,
73
+ {
74
+ field,
75
+ slot: "label",
76
+ part: { id: props.id },
77
+ props,
78
+ tag: "label"
79
+ }
80
+ );
81
+ }
82
+ function FieldDescription(props) {
83
+ const described = React.useContext(DescribedContext);
84
+ if (!described) {
85
+ return outside("description", "p", props);
86
+ }
87
+ const owner = described;
88
+ return /* @__PURE__ */ jsx(
89
+ InField,
90
+ {
91
+ field: owner,
92
+ slot: "description",
93
+ part: { id: props.id },
94
+ props,
95
+ tag: "p"
96
+ }
97
+ );
98
+ }
99
+ function FieldError({
100
+ match,
101
+ children = message,
102
+ ...props
103
+ }) {
104
+ const field = React.useContext(FieldContext);
105
+ const made = React.useId();
106
+ if (!field) {
107
+ return fieldOutsideErrorShown({ match }) ? outside("error", "div", { ...props, children }) : null;
108
+ }
109
+ const id = props.id ?? (match === void 0 ? void 0 : made);
110
+ return /* @__PURE__ */ jsx(
111
+ InField,
112
+ {
113
+ field,
114
+ slot: "error",
115
+ part: { id, match },
116
+ props: { ...props, children },
117
+ tag: "div"
118
+ }
119
+ );
120
+ }
121
+ var message = (state) => state.message;
122
+ function FieldControl({
123
+ name,
124
+ render,
125
+ ...rest
126
+ }) {
127
+ const field = React.useContext(FieldContext);
128
+ if (!field) {
129
+ return outside("control", "input", { ...rest, name, render });
130
+ }
131
+ const [props, element] = ownDescription(rest, render);
132
+ const control = { id: props.id, describedBy: props["aria-describedby"] };
133
+ const user = { ...props, render: element, name: name ?? field.name };
134
+ return /* @__PURE__ */ jsx(
135
+ InField,
136
+ {
137
+ field,
138
+ slot: "control",
139
+ part: control,
140
+ props: user,
141
+ tag: "input"
142
+ }
143
+ );
144
+ }
145
+ function FieldSet({
146
+ disabled,
147
+ debug,
148
+ ...props
149
+ }) {
150
+ const set = usePrimitive(fieldSet, { disabled, debug });
151
+ return /* @__PURE__ */ jsx(DescribedContext.Provider, { value: set, children: usePart(set, "set", {}, props, "fieldset") });
152
+ }
153
+ function FieldLegend(props) {
154
+ return usePart(fieldSet, "legend", { id: props.id }, props, "legend");
155
+ }
156
+ function FieldGroup(props) {
157
+ return usePart(usePrimitive(fieldGroup, {}), "group", {}, props, "div");
158
+ }
159
+ export {
160
+ Field,
161
+ FieldControl,
162
+ FieldDescription,
163
+ FieldError,
164
+ FieldGroup,
165
+ FieldLabel,
166
+ FieldLegend,
167
+ FieldSet,
168
+ useFieldControl
169
+ };
@@ -0,0 +1,46 @@
1
+ import { type FileInputItemProps, type FileInputItemRemoveState, type FileInputItemState, type FileInputOptions, type FileInputState, type FileInputTriggerProps } from "@ui-sdk/core/file-input";
2
+ import * as React from "react";
3
+ import { type PartProps } from "./use-primitive.js";
4
+ type DivProps<State> = Omit<PartProps<"div", State>, "defaultValue" | "onChange" | "onSelect" | "onDrop">;
5
+ type ButtonProps<State> = Omit<PartProps<"button", State>, "name" | "form" | "value" | "onSelect">;
6
+ /**
7
+ * The root: it holds the files, and renders the hidden file input that opens
8
+ * the picker and that a form submits.
9
+ * @stable
10
+ */
11
+ declare function FileInput({ value, defaultValue, onValueChange, onReject, accept, multiple, directory, capture, maxFiles, maxSize, minSize, validate, name, form, required, disabled, announcement, controller, debug, children, ...props }: FileInputOptions & DivProps<FileInputState>): React.JSX.Element | null;
12
+ /**
13
+ * Opens the file picker. Inside a Field, the field's label names it with the
14
+ * button's own text. Outside the file input, it connects through `controller`.
15
+ * @stable
16
+ */
17
+ declare function FileInputTrigger({ controller, render, ...props }: ButtonProps<FileInputState> & FileInputTriggerProps): React.JSX.Element;
18
+ /**
19
+ * Takes dropped and pasted files. Put the trigger inside it, which is how
20
+ * keyboard and screen reader users choose files.
21
+ * @stable
22
+ */
23
+ declare const FileInputDropzone: import("./use-primitive.js").PartComponent<import("@ui-sdk/core/file-input").FileInputPrimitive, "dropzone", "div">;
24
+ /**
25
+ * The files, as a list. Its children render once for each file, so put a
26
+ * FileInputItem in it.
27
+ * @stable
28
+ */
29
+ declare function FileInputList({ children, ...props }: Omit<DivProps<FileInputState>, "children"> & {
30
+ children?: React.ReactNode;
31
+ }): React.JSX.Element | null;
32
+ /**
33
+ * One file. Its render state has the file, for its name, size and preview.
34
+ * Arrow keys move between items, and Backspace or Delete removes the focused one.
35
+ * @stable
36
+ */
37
+ declare function FileInputItem({ file: own, ...props }: DivProps<FileInputItemState> & Partial<FileInputItemProps>): React.JSX.Element;
38
+ /**
39
+ * Removes its item's file, or the `file` it's given. It's named "Remove <file
40
+ * name>" unless you name it.
41
+ * @stable
42
+ */
43
+ declare function FileInputItemRemove({ file: own, ...props }: ButtonProps<FileInputItemRemoveState> & Partial<FileInputItemProps>): React.JSX.Element | null;
44
+ export { createFileInputController, formatFileSize, relativePath, } from "@ui-sdk/core/file-input";
45
+ export type { FileInputApi, FileInputChange, FileInputChangeOptions, FileInputController, FileInputDropzoneProps, FileInputDropzoneState, FileInputDropzoneTarget, FileInputItemProps, FileInputItemRemoveState, FileInputItemState, FileInputOptions, FileInputPasteTarget, FileInputPrimitive, FileInputState, FileInputTriggerProps, FileInputValueChangeDetails, FileInputValueChangeReason, FileLike, FileRejection, FileRejectionReason, FileRules, } from "@ui-sdk/core/file-input";
46
+ export { FileInput, FileInputDropzone, FileInputItem, FileInputItemRemove, FileInputList, FileInputTrigger, };