@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
@@ -0,0 +1,674 @@
1
+ "use client";
2
+ // src/use-primitive.tsx
3
+ import {
4
+ attrs,
5
+ commit,
6
+ directNames,
7
+ handlers as partHandlers,
8
+ keep,
9
+ partState,
10
+ present,
11
+ ref,
12
+ release,
13
+ renderVersion,
14
+ sameSlotState,
15
+ sameValue,
16
+ schemaOf,
17
+ selectedKeys,
18
+ subscribe,
19
+ takeOwnId,
20
+ unwatched,
21
+ yieldToAuthor
22
+ } from "@ui-sdk/core/renderer";
23
+ import * as React from "react";
24
+ import {
25
+ mergeProps,
26
+ mergeRefs,
27
+ renderElement
28
+ } from "./render-element.js";
29
+ import { jsx } from "react/jsx-runtime";
30
+ var camelCase = (names, prefix = "") => Object.fromEntries(
31
+ names.split(" ").map((name) => [name.toLowerCase(), prefix + name])
32
+ );
33
+ var propNames = {
34
+ class: "className",
35
+ for: "htmlFor",
36
+ checked: "defaultChecked",
37
+ .../* @__PURE__ */ camelCase(
38
+ "tabIndex readOnly inputMode enterKeyHint autoComplete autoCapitalize autoCorrect spellCheck contentEditable maxLength minLength"
39
+ )
40
+ };
41
+ var booleans = /* @__PURE__ */ new Set([
42
+ "hidden",
43
+ "disabled",
44
+ "readonly",
45
+ "required",
46
+ "inert",
47
+ "checked",
48
+ "multiple"
49
+ ]);
50
+ var styles = /* @__PURE__ */ new Map();
51
+ function styleObject(css) {
52
+ let style = styles.get(css);
53
+ if (style) {
54
+ return style;
55
+ }
56
+ style = {};
57
+ for (const declaration of css.split(";")) {
58
+ const index = declaration.indexOf(":");
59
+ if (index === -1) {
60
+ continue;
61
+ }
62
+ const name = declaration.slice(0, index).trim();
63
+ style[name.startsWith("--") ? name : name.replace(/-(\w)/g, (_, char) => char.toUpperCase())] = declaration.slice(index + 1).trim();
64
+ }
65
+ if (styles.size >= 500) {
66
+ styles.clear();
67
+ }
68
+ styles.set(css, style);
69
+ return style;
70
+ }
71
+ var eventProps = /* @__PURE__ */ Object.assign(
72
+ /* @__PURE__ */ camelCase(
73
+ "Click KeyDown KeyUp ContextMenu PointerDown MouseDown PointerUp PointerMove",
74
+ "on"
75
+ ),
76
+ {
77
+ dblclick: "onDoubleClick",
78
+ focusin: "onFocus",
79
+ focusout: "onBlur",
80
+ input: "onChange",
81
+ submit: "onSubmit"
82
+ }
83
+ );
84
+ var host = {
85
+ by: "framework",
86
+ attaches: /* @__PURE__ */ Object.keys(eventProps)
87
+ };
88
+ function toReactProps(attrs2) {
89
+ const props = {};
90
+ for (const name in attrs2) {
91
+ const value = attrs2[name];
92
+ if (value === void 0) {
93
+ continue;
94
+ }
95
+ props[propNames[name] ?? name] = booleans.has(name) ? true : name === "style" ? styleObject(value) : value;
96
+ }
97
+ return props;
98
+ }
99
+ function usePrimitive(primitive, options) {
100
+ const id = `ui-sdk-${React.useId()}`;
101
+ const create = (from = {}) => unwatched(
102
+ () => primitive({
103
+ ...options,
104
+ ...from,
105
+ controller: void 0,
106
+ id
107
+ })
108
+ );
109
+ const [instance, setInstance] = React.useState(() => create());
110
+ React.useLayoutEffect(() => keep(instance), [instance]);
111
+ const next = { ...options, id };
112
+ const outers = outersOf(options);
113
+ const base = instance.get();
114
+ const state = within(outers, () => instance.preview(next));
115
+ const preview = state && {
116
+ options: next,
117
+ outers,
118
+ base,
119
+ state,
120
+ handed: false,
121
+ pending: /* @__PURE__ */ new Set()
122
+ };
123
+ React.useLayoutEffect(() => {
124
+ handOver(instance, next, preview, outers);
125
+ });
126
+ const life = React.useRef({ mounted: 0, destroyed: false });
127
+ React.useEffect(() => {
128
+ const own = life.current;
129
+ own.mounted++;
130
+ hidden.delete(instance);
131
+ owners?.unregister(own);
132
+ if (own.destroyed) {
133
+ own.destroyed = false;
134
+ setInstance(create(carried(primitive, instance, options)));
135
+ }
136
+ return () => {
137
+ own.mounted--;
138
+ queueMicrotask(() => {
139
+ if (own.mounted || own.destroyed) {
140
+ return;
141
+ }
142
+ release(instance);
143
+ const leave = () => {
144
+ own.destroyed = true;
145
+ instance.destroy();
146
+ };
147
+ if (!anchors.has(instance)) {
148
+ owners?.register(own, instance, own);
149
+ } else if (inPage(instance)) {
150
+ hide(instance, leave);
151
+ } else {
152
+ leave();
153
+ }
154
+ });
155
+ };
156
+ }, [instance]);
157
+ const stable = React.useMemo(() => {
158
+ const handle = {
159
+ primitive,
160
+ instance,
161
+ get state() {
162
+ return stateIn(this);
163
+ },
164
+ // Read when used, since reading it wakes an asleep instance.
165
+ get api() {
166
+ return instance.api;
167
+ }
168
+ };
169
+ return handle;
170
+ }, [instance]);
171
+ if (!preview) {
172
+ return stable;
173
+ }
174
+ const previewing = extendHandle(stable, {});
175
+ previews.set(previewing, preview);
176
+ return previewing;
177
+ }
178
+ var previews = /* @__PURE__ */ new WeakMap();
179
+ var handing;
180
+ function handOver(instance, options, preview, outers) {
181
+ if (preview) {
182
+ preview.handed = true;
183
+ }
184
+ const outer = handing;
185
+ handing = preview;
186
+ try {
187
+ within(outers, () => instance.setOptions(options));
188
+ } finally {
189
+ handing = outer;
190
+ }
191
+ }
192
+ var readers = /* @__PURE__ */ new WeakMap();
193
+ function reading(handle, read) {
194
+ readers.set(read, handle);
195
+ return read;
196
+ }
197
+ function outersOf(options) {
198
+ let outers;
199
+ for (const key in options) {
200
+ const outer = readers.get(options[key]);
201
+ if (outer) {
202
+ ;
203
+ (outers ??= []).push(outer);
204
+ }
205
+ }
206
+ return outers;
207
+ }
208
+ function within(outers, read) {
209
+ if (!outers) {
210
+ return read();
211
+ }
212
+ let run = read;
213
+ for (const outer of outers) {
214
+ const inner = run;
215
+ run = () => readIn(outer, inner);
216
+ }
217
+ return run();
218
+ }
219
+ function extendHandle(handle, extra) {
220
+ const copy = Object.defineProperties({}, {
221
+ ...Object.getOwnPropertyDescriptors(handle),
222
+ ...Object.getOwnPropertyDescriptors(extra),
223
+ state: { get: () => stateIn(copy), enumerable: true }
224
+ });
225
+ const preview = previews.get(handle);
226
+ if (preview) {
227
+ previews.set(copy, preview);
228
+ }
229
+ return copy;
230
+ }
231
+ function presentIn(handle, name, props) {
232
+ const part = handle.instance.part(name, props);
233
+ return readIn(handle, (showing) => present(part, part.props, showing));
234
+ }
235
+ function slotIn(handle, name, props, user = {}) {
236
+ const part = handle.instance.part(name, props);
237
+ return readIn(
238
+ handle,
239
+ (showing) => elementProps(part, part.props, user, showing)
240
+ );
241
+ }
242
+ function stateIn(handle) {
243
+ const { instance } = handle;
244
+ const current = instance.get();
245
+ const preview = previews.get(handle);
246
+ if (!preview || preview.handed) {
247
+ return current;
248
+ }
249
+ if (preview.base !== current) {
250
+ preview.base = current;
251
+ preview.state = within(
252
+ preview.outers,
253
+ () => instance.preview(preview.options)
254
+ );
255
+ }
256
+ return preview.state ?? current;
257
+ }
258
+ function readIn(handle, read, around) {
259
+ const state = stateIn(handle);
260
+ if (state === handle.instance.get() && !around) {
261
+ return read(state);
262
+ }
263
+ return handle.instance.view(state, () => read(state), around);
264
+ }
265
+ var anchors = /* @__PURE__ */ new WeakMap();
266
+ var inPage = (instance) => !!anchors.get(instance)?.isConnected;
267
+ var owners = typeof FinalizationRegistry === "undefined" ? void 0 : new FinalizationRegistry(
268
+ (instance) => instance.destroy()
269
+ );
270
+ var hidden = /* @__PURE__ */ new Map();
271
+ var sweeping;
272
+ function hide(instance, leave) {
273
+ hidden.set(instance, leave);
274
+ sweeping ??= setInterval(() => {
275
+ for (const [instance2, leave2] of hidden) {
276
+ if (inPage(instance2)) {
277
+ continue;
278
+ }
279
+ hidden.delete(instance2);
280
+ leave2();
281
+ }
282
+ if (hidden.size) {
283
+ return;
284
+ }
285
+ clearInterval(sweeping);
286
+ sweeping = void 0;
287
+ }, 1e3);
288
+ }
289
+ function carried(primitive, instance, options) {
290
+ const schema = schemaOf(primitive).options;
291
+ const state = instance.get();
292
+ const defaults = {};
293
+ for (const key in state) {
294
+ const fallback = `default${key[0].toUpperCase()}${key.slice(1)}`;
295
+ if (fallback in schema && options[key] === void 0) {
296
+ defaults[fallback] = state[key];
297
+ }
298
+ }
299
+ return defaults;
300
+ }
301
+ var heldRefs = /* @__PURE__ */ new WeakMap();
302
+ function heldRef(part) {
303
+ let held = heldRefs.get(part);
304
+ if (held) {
305
+ return held;
306
+ }
307
+ const bindTo = ref(part, host);
308
+ let releasing = false;
309
+ held = (el) => {
310
+ releasing = !el;
311
+ if (el) {
312
+ return bindTo(el);
313
+ }
314
+ queueMicrotask(() => {
315
+ if (releasing) {
316
+ bindTo(null);
317
+ }
318
+ });
319
+ };
320
+ heldRefs.set(part, held);
321
+ return held;
322
+ }
323
+ function elementProps(part, props, user, state) {
324
+ takeOwnId(part, user.id);
325
+ const handlers = {};
326
+ for (const [type, handler] of Object.entries(partHandlers(part))) {
327
+ const prop = eventProps[type];
328
+ if (!prop) {
329
+ continue;
330
+ }
331
+ handlers[prop] = (event) => {
332
+ handler(event.nativeEvent);
333
+ if (event.nativeEvent.defaultPrevented && !event.isDefaultPrevented()) {
334
+ event.preventDefault();
335
+ }
336
+ };
337
+ }
338
+ const own = yieldToAuthor(
339
+ attrs(part, props, state),
340
+ (name) => user[propNames[name] ?? name] != null
341
+ );
342
+ return mergeProps(handlers, user, toReactProps(own), {
343
+ id: user.id,
344
+ ref: heldRef(part)
345
+ });
346
+ }
347
+ function sameAttrs(a, b, skip = []) {
348
+ const keys = Object.keys(a);
349
+ return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key] || skip.includes(key));
350
+ }
351
+ var rechecks = /* @__PURE__ */ new WeakMap();
352
+ function changesValues(before, after) {
353
+ for (const key in { ...before, ...after }) {
354
+ if (typeof before[key] === "function" && typeof after[key] === "function") {
355
+ continue;
356
+ }
357
+ if (!sameValue(before[key], after[key])) {
358
+ return true;
359
+ }
360
+ }
361
+ return false;
362
+ }
363
+ function usePartState(handle, name, props, around) {
364
+ const { instance } = handle;
365
+ const [, rerender] = React.useReducer((count) => count + 1, 0);
366
+ const part = instance.part(name, props, true);
367
+ const rendered = readIn(
368
+ handle,
369
+ (showing) => ({
370
+ handle,
371
+ around,
372
+ props,
373
+ snapshot: partState(part, props, showing),
374
+ // The keys this render read, filled in as it reads them.
375
+ read: /* @__PURE__ */ new Set(),
376
+ attrs: attrs(part, props, showing),
377
+ present: present(part, props, showing),
378
+ version: renderVersion(instance)
379
+ }),
380
+ around
381
+ );
382
+ const state = new Proxy(rendered.snapshot, {
383
+ get(target, key) {
384
+ if (typeof key === "string") {
385
+ rendered.read.add(key);
386
+ }
387
+ return target[key];
388
+ }
389
+ });
390
+ const last = React.useRef(rendered);
391
+ const preview = previews.get(handle);
392
+ if (preview && !preview.handed) {
393
+ preview.pending.add(last);
394
+ }
395
+ const check = React.useCallback(
396
+ (full, props2 = false) => {
397
+ const shown = last.current;
398
+ const outdated = readIn(
399
+ shown.handle,
400
+ (now) => {
401
+ if (shown.read.size) {
402
+ const next = partState(
403
+ part,
404
+ shown.props,
405
+ now
406
+ );
407
+ for (const key of shown.read) {
408
+ if (sameSlotState(next[key], shown.snapshot[key])) {
409
+ continue;
410
+ }
411
+ shown.snapshot = next;
412
+ return true;
413
+ }
414
+ }
415
+ const shows = present(part, shown.props, now);
416
+ if (shows !== shown.present) {
417
+ return true;
418
+ }
419
+ if (renderVersion(instance) === shown.version && !props2) {
420
+ return false;
421
+ }
422
+ shown.version = renderVersion(instance);
423
+ return shows && !sameAttrs(
424
+ attrs(part, shown.props, now),
425
+ shown.attrs,
426
+ full ? void 0 : directNames(part)
427
+ );
428
+ },
429
+ shown.around
430
+ );
431
+ if (outdated) {
432
+ rerender();
433
+ }
434
+ },
435
+ [instance, part]
436
+ );
437
+ React.useLayoutEffect(() => {
438
+ const changed = part.props !== props && changesValues(part.props, props);
439
+ commit(part, props);
440
+ preview?.pending.delete(last);
441
+ if (part.el && !inPage(instance)) {
442
+ anchors.set(instance, part.el);
443
+ }
444
+ last.current = rendered;
445
+ check(true);
446
+ if (changed) {
447
+ rechecks.get(instance)?.forEach((recheck) => recheck());
448
+ }
449
+ });
450
+ const selected = selectedKeys(part, props);
451
+ React.useLayoutEffect(() => {
452
+ const recheck = () => check(true, true);
453
+ let all = rechecks.get(instance);
454
+ if (!all) {
455
+ rechecks.set(instance, all = /* @__PURE__ */ new Set());
456
+ }
457
+ all.add(recheck);
458
+ const unsubscribe = subscribe(
459
+ part,
460
+ () => {
461
+ if (!handing?.pending.has(last)) {
462
+ check(false);
463
+ }
464
+ },
465
+ last.current.props
466
+ );
467
+ return () => {
468
+ all.delete(recheck);
469
+ unsubscribe();
470
+ };
471
+ }, [part, selected, check]);
472
+ return state;
473
+ }
474
+ var kindOf = (spec) => typeof spec === "object" ? spec.kind : spec;
475
+ var fromOf = (spec, key) => {
476
+ if (typeof spec !== "object") {
477
+ return void 0;
478
+ }
479
+ const [slot, prop = key] = spec.from.split(".");
480
+ return { slot, prop };
481
+ };
482
+ var pascal = (name) => name.replace(/(^|-)(\w)/g, (_, _dash, char) => char.toUpperCase());
483
+ function split(props, schema) {
484
+ const named = {};
485
+ const rest = {};
486
+ for (const key in props) {
487
+ ;
488
+ (key in schema ? named : rest)[key] = props[key];
489
+ }
490
+ return [named, rest];
491
+ }
492
+ var scopes = /* @__PURE__ */ new WeakMap();
493
+ function scopeOf(primitive) {
494
+ let scope = scopes.get(primitive);
495
+ if (!scope) {
496
+ scopes.set(
497
+ primitive,
498
+ scope = {
499
+ context: React.createContext(null),
500
+ provides: /* @__PURE__ */ new Set(),
501
+ keyed: /* @__PURE__ */ new Set()
502
+ }
503
+ );
504
+ }
505
+ return scope;
506
+ }
507
+ function HandleScope({
508
+ handle,
509
+ children
510
+ }) {
511
+ const { context } = scopeOf(handle.primitive);
512
+ const scope = React.useMemo(() => ({ handle, around: {} }), [handle]);
513
+ return /* @__PURE__ */ jsx(context.Provider, { value: scope, children });
514
+ }
515
+ function useNearest(primitive) {
516
+ return React.useContext(scopeOf(primitive).context)?.handle;
517
+ }
518
+ function useHandle(primitive) {
519
+ const handle = useNearest(primitive);
520
+ if (!handle) {
521
+ throw new Error(
522
+ `The ${primitive.name} parts must be used inside their root.`
523
+ );
524
+ }
525
+ return handle;
526
+ }
527
+ function usePart(handle, slot, slotProps, props = {}, tag = "div") {
528
+ const primitive = typeof handle === "function" ? handle : handle.primitive;
529
+ const { context, provides, keyed } = scopeOf(primitive);
530
+ const scope = React.useContext(context);
531
+ const owner = typeof handle === "function" ? scope?.handle : handle;
532
+ if (!owner) {
533
+ throw new Error(
534
+ `The ${primitive.name} ${slot} part must be used inside its root.`
535
+ );
536
+ }
537
+ const { render, ...rest } = props;
538
+ const own = React.useMemo(
539
+ () => ({ handle: owner, around: {} }),
540
+ [owner]
541
+ );
542
+ const inside = scope?.handle === owner ? scope : own;
543
+ const around = keyed.has(slot) ? { ...slotProps, value: slotProps.id } : slotProps;
544
+ const provided = provides.has(slot) ? {
545
+ handle: owner,
546
+ around: { ...inside.around, [slot]: around },
547
+ shown: { ...inside.shown, [slot]: slotProps }
548
+ } : inside;
549
+ const state = usePartState(
550
+ owner,
551
+ slot,
552
+ slotProps,
553
+ provided.shown
554
+ );
555
+ const part = owner.instance.part(slot, slotProps, true);
556
+ React.useLayoutEffect(() => () => ref(part, host)(null), [part]);
557
+ const renderId = React.isValidElement(render) ? render.props.id : void 0;
558
+ const user = renderId === void 0 ? rest : { ...rest, id: renderId };
559
+ const merged = readIn(
560
+ owner,
561
+ (showing) => present(part, slotProps, showing) ? elementProps(part, slotProps, user, showing) : void 0,
562
+ provided.shown
563
+ );
564
+ const element = merged ? renderElement(tag, merged, render, state) : null;
565
+ if (provided === scope) {
566
+ return element;
567
+ }
568
+ return /* @__PURE__ */ jsx(context.Provider, { value: provided, children: element });
569
+ }
570
+ function createParts(primitive, tags) {
571
+ const schema = schemaOf(primitive);
572
+ const { context, provides, keyed } = scopeOf(primitive);
573
+ for (const [slot, props] of Object.entries(schema.slots)) {
574
+ for (const key in props) {
575
+ const from = fromOf(props[key], key);
576
+ if (from) {
577
+ provides.add(from.slot);
578
+ }
579
+ if (kindOf(props[key]) === "key") {
580
+ keyed.add(slot);
581
+ }
582
+ }
583
+ }
584
+ const name = pascal(primitive.name ?? "");
585
+ const parts = {};
586
+ function Root(props) {
587
+ const [options, rest] = split(props, schema.options);
588
+ const handle = usePrimitive(
589
+ primitive,
590
+ options
591
+ );
592
+ if (tags.root) {
593
+ return usePart(
594
+ handle,
595
+ "root",
596
+ ...split(rest, schema.slots.root ?? {}),
597
+ tags.root
598
+ );
599
+ }
600
+ return /* @__PURE__ */ jsx(HandleScope, { handle, children: props.children });
601
+ }
602
+ Root.displayName = name;
603
+ parts.Root = Root;
604
+ for (const [slot, tag] of Object.entries(tags)) {
605
+ if (slot === "root") {
606
+ continue;
607
+ }
608
+ const own = schema.slots[slot] ?? {};
609
+ const ids = Object.keys(own).filter((key2) => kindOf(own[key2]) === "id");
610
+ const key = Object.keys(own).find((key2) => kindOf(own[key2]) === "key");
611
+ const Part = (props) => {
612
+ const [slotProps, rest] = split(props, own);
613
+ if (props.id !== void 0) {
614
+ rest.id = props.id;
615
+ }
616
+ for (const key2 of ids) {
617
+ const id = React.useId();
618
+ slotProps[key2] ??= id;
619
+ }
620
+ const scope = React.useContext(context);
621
+ if (key) {
622
+ slotProps.id ??= scope?.handle.api?.internal.keyOf(slotProps[key]);
623
+ }
624
+ for (const prop in own) {
625
+ const spec = own[prop];
626
+ const from = fromOf(spec, prop);
627
+ if (!from || slotProps[prop] !== void 0) {
628
+ continue;
629
+ }
630
+ const around = scope?.around[from.slot];
631
+ if (!around && spec.required) {
632
+ throw new Error(
633
+ `<${Part.displayName}> must be used inside <${name}${pascal(from.slot)}>.`
634
+ );
635
+ }
636
+ slotProps[prop] = around?.[from.prop];
637
+ }
638
+ return usePart(
639
+ primitive,
640
+ slot,
641
+ slotProps,
642
+ rest,
643
+ tag
644
+ );
645
+ };
646
+ Part.displayName = name + pascal(slot);
647
+ parts[pascal(slot)] = Part;
648
+ }
649
+ return parts;
650
+ }
651
+ function useAround(primitive, slot) {
652
+ return React.useContext(scopeOf(primitive).context)?.around[slot];
653
+ }
654
+ function sharesProps(primitive, slot) {
655
+ scopeOf(primitive).provides.add(slot);
656
+ }
657
+ export {
658
+ HandleScope,
659
+ createParts,
660
+ extendHandle,
661
+ mergeProps,
662
+ mergeRefs,
663
+ presentIn,
664
+ readIn,
665
+ reading,
666
+ renderElement,
667
+ sharesProps,
668
+ slotIn,
669
+ useAround,
670
+ useHandle,
671
+ useNearest,
672
+ usePart,
673
+ usePrimitive
674
+ };