@ui-sdk/vue 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 (262) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +10 -2
  3. package/dist/accordion.d.ts +561 -0
  4. package/dist/accordion.js +24 -0
  5. package/dist/agent.d.ts +2 -0
  6. package/dist/agent.js +7 -0
  7. package/dist/alert-dialog.d.ts +231 -0
  8. package/dist/alert-dialog.js +33 -0
  9. package/dist/async-options.d.ts +18 -0
  10. package/dist/async-options.js +40 -0
  11. package/dist/autocomplete.d.ts +384 -0
  12. package/dist/autocomplete.js +344 -0
  13. package/dist/avatar.d.ts +40 -0
  14. package/dist/avatar.js +28 -0
  15. package/dist/button.d.ts +52 -0
  16. package/dist/button.js +43 -0
  17. package/dist/calendar-context.d.ts +10 -0
  18. package/dist/calendar-context.js +7 -0
  19. package/dist/calendar.d.ts +311 -0
  20. package/dist/calendar.js +349 -0
  21. package/dist/carousel.d.ts +236 -0
  22. package/dist/carousel.js +204 -0
  23. package/dist/checkbox.d.ts +211 -0
  24. package/dist/checkbox.js +151 -0
  25. package/dist/children.d.ts +41 -0
  26. package/dist/children.js +135 -0
  27. package/dist/collapsible.d.ts +54 -0
  28. package/dist/collapsible.js +18 -0
  29. package/dist/color-picker.d.ts +187 -0
  30. package/dist/color-picker.js +158 -0
  31. package/dist/color.d.ts +2 -0
  32. package/dist/color.js +21 -0
  33. package/dist/combobox.d.ts +517 -0
  34. package/dist/combobox.js +531 -0
  35. package/dist/command.d.ts +322 -0
  36. package/dist/command.js +345 -0
  37. package/dist/controller-target.d.ts +49 -0
  38. package/dist/controller-target.js +112 -0
  39. package/dist/create-parts.d.ts +126 -0
  40. package/dist/create-parts.js +206 -0
  41. package/dist/date-input.d.ts +133 -0
  42. package/dist/date-input.js +31 -0
  43. package/dist/date-picker.d.ts +328 -0
  44. package/dist/date-picker.js +354 -0
  45. package/dist/date.d.ts +2 -0
  46. package/dist/date.js +59 -0
  47. package/dist/dialog-parts.d.ts +259 -0
  48. package/dist/dialog-parts.js +300 -0
  49. package/dist/dialog.d.ts +251 -0
  50. package/dist/dialog.js +25 -0
  51. package/dist/drawer.d.ts +304 -0
  52. package/dist/drawer.js +373 -0
  53. package/dist/editor-context.d.ts +4 -0
  54. package/dist/editor-context.js +5 -0
  55. package/dist/field-context.d.ts +26 -0
  56. package/dist/field-context.js +44 -0
  57. package/dist/field.d.ts +154 -0
  58. package/dist/field.js +240 -0
  59. package/dist/file-input.d.ts +212 -0
  60. package/dist/file-input.js +255 -0
  61. package/dist/form-inputs.d.ts +16 -0
  62. package/dist/form-inputs.js +25 -0
  63. package/dist/gesture.d.ts +1 -0
  64. package/dist/gesture.js +15 -0
  65. package/dist/history.d.ts +2 -0
  66. package/dist/history.js +11 -0
  67. package/dist/hover-card.d.ts +137 -0
  68. package/dist/hover-card.js +153 -0
  69. package/dist/image-cropper.d.ts +74 -0
  70. package/dist/image-cropper.js +36 -0
  71. package/dist/image.d.ts +2 -0
  72. package/dist/image.js +5 -0
  73. package/dist/index.d.ts +59 -0
  74. package/dist/index.js +60 -0
  75. package/dist/input.d.ts +120 -0
  76. package/dist/input.js +73 -0
  77. package/dist/item-icon.d.ts +34 -0
  78. package/dist/item-icon.js +63 -0
  79. package/dist/label.d.ts +16 -0
  80. package/dist/label.js +8 -0
  81. package/dist/lifecycle.d.ts +11 -0
  82. package/dist/lifecycle.js +91 -0
  83. package/dist/list-items.d.ts +38 -0
  84. package/dist/list-items.js +59 -0
  85. package/dist/list-text.d.ts +7 -0
  86. package/dist/list-text.js +15 -0
  87. package/dist/listbox.d.ts +273 -0
  88. package/dist/listbox.js +126 -0
  89. package/dist/menu.d.ts +678 -0
  90. package/dist/menu.js +607 -0
  91. package/dist/menubar-context.d.ts +5 -0
  92. package/dist/menubar-context.js +5 -0
  93. package/dist/menubar.d.ts +61 -0
  94. package/dist/menubar.js +48 -0
  95. package/dist/meter.d.ts +41 -0
  96. package/dist/meter.js +37 -0
  97. package/dist/navigation-menu.d.ts +228 -0
  98. package/dist/navigation-menu.js +195 -0
  99. package/dist/number-input.d.ts +176 -0
  100. package/dist/number-input.js +231 -0
  101. package/dist/number.d.ts +2 -0
  102. package/dist/number.js +39 -0
  103. package/dist/nuxt/entries.json +977 -0
  104. package/dist/nuxt/module.d.ts +18 -0
  105. package/dist/nuxt/module.js +31 -0
  106. package/dist/nuxt/registrations.d.ts +22 -0
  107. package/dist/nuxt/registrations.js +22 -0
  108. package/dist/observe.d.ts +2 -0
  109. package/dist/observe.js +7 -0
  110. package/dist/otp-input.d.ts +142 -0
  111. package/dist/otp-input.js +130 -0
  112. package/dist/overlays.d.ts +40 -0
  113. package/dist/overlays.js +118 -0
  114. package/dist/pagination.d.ts +201 -0
  115. package/dist/pagination.js +146 -0
  116. package/dist/password-input.d.ts +144 -0
  117. package/dist/password-input.js +134 -0
  118. package/dist/popover.d.ts +211 -0
  119. package/dist/popover.js +258 -0
  120. package/dist/popup.d.ts +60 -0
  121. package/dist/popup.js +89 -0
  122. package/dist/preferences.d.ts +44 -0
  123. package/dist/preferences.js +102 -0
  124. package/dist/primitive.d.ts +2 -0
  125. package/dist/primitive.js +11 -0
  126. package/dist/progress.d.ts +41 -0
  127. package/dist/progress.js +37 -0
  128. package/dist/radio.d.ts +164 -0
  129. package/dist/radio.js +145 -0
  130. package/dist/rating.d.ts +149 -0
  131. package/dist/rating.js +146 -0
  132. package/dist/renderless.d.ts +4 -0
  133. package/dist/renderless.js +28 -0
  134. package/dist/resizable.d.ts +54 -0
  135. package/dist/resizable.js +22 -0
  136. package/dist/scroll-area.d.ts +72 -0
  137. package/dist/scroll-area.js +77 -0
  138. package/dist/segmented-control.d.ts +151 -0
  139. package/dist/segmented-control.js +110 -0
  140. package/dist/segmented-input.d.ts +76 -0
  141. package/dist/segmented-input.js +115 -0
  142. package/dist/select.d.ts +458 -0
  143. package/dist/select.js +468 -0
  144. package/dist/separator.d.ts +14 -0
  145. package/dist/separator.js +8 -0
  146. package/dist/shortcuts.d.ts +32 -0
  147. package/dist/shortcuts.js +56 -0
  148. package/dist/slider.d.ts +65 -0
  149. package/dist/slider.js +194 -0
  150. package/dist/switch.d.ts +103 -0
  151. package/dist/switch.js +71 -0
  152. package/dist/tabs.d.ts +338 -0
  153. package/dist/tabs.js +27 -0
  154. package/dist/text-control.d.ts +89 -0
  155. package/dist/text-control.js +51 -0
  156. package/dist/text-match.d.ts +2 -0
  157. package/dist/text-match.js +7 -0
  158. package/dist/textarea.d.ts +106 -0
  159. package/dist/textarea.js +68 -0
  160. package/dist/time-input.d.ts +131 -0
  161. package/dist/time-input.js +32 -0
  162. package/dist/timeline.d.ts +81 -0
  163. package/dist/timeline.js +30 -0
  164. package/dist/toast-parts.d.ts +203 -0
  165. package/dist/toast-parts.js +270 -0
  166. package/dist/toast.d.ts +2 -0
  167. package/dist/toast.js +21 -0
  168. package/dist/toggle-props.d.ts +22 -0
  169. package/dist/toggle-props.js +14 -0
  170. package/dist/toggle.d.ts +199 -0
  171. package/dist/toggle.js +129 -0
  172. package/dist/token-input.d.ts +136 -0
  173. package/dist/token-input.js +214 -0
  174. package/dist/toolbar-context.d.ts +7 -0
  175. package/dist/toolbar-context.js +20 -0
  176. package/dist/toolbar.d.ts +120 -0
  177. package/dist/toolbar.js +77 -0
  178. package/dist/tooltip.d.ts +160 -0
  179. package/dist/tooltip.js +224 -0
  180. package/dist/tree.d.ts +300 -0
  181. package/dist/tree.js +209 -0
  182. package/dist/trigger-menu.d.ts +452 -0
  183. package/dist/trigger-menu.js +254 -0
  184. package/dist/use-primitive.d.ts +132 -0
  185. package/dist/use-primitive.js +462 -0
  186. package/dist/waterfall.d.ts +201 -0
  187. package/dist/waterfall.js +171 -0
  188. package/docs/README.md +89 -0
  189. package/docs/agents.md +1523 -0
  190. package/docs/components/accordion.md +1369 -0
  191. package/docs/components/alert-dialog.md +799 -0
  192. package/docs/components/autocomplete.md +1857 -0
  193. package/docs/components/avatar.md +272 -0
  194. package/docs/components/button.md +435 -0
  195. package/docs/components/calendar.md +1589 -0
  196. package/docs/components/carousel.md +1171 -0
  197. package/docs/components/checkbox.md +1008 -0
  198. package/docs/components/collapsible.md +536 -0
  199. package/docs/components/color-picker.md +706 -0
  200. package/docs/components/combobox.md +3504 -0
  201. package/docs/components/command.md +1481 -0
  202. package/docs/components/date-input.md +536 -0
  203. package/docs/components/date-picker.md +1244 -0
  204. package/docs/components/dialog.md +1397 -0
  205. package/docs/components/drawer.md +1166 -0
  206. package/docs/components/field.md +538 -0
  207. package/docs/components/file-input.md +611 -0
  208. package/docs/components/hover-card.md +505 -0
  209. package/docs/components/image-cropper.md +556 -0
  210. package/docs/components/input.md +306 -0
  211. package/docs/components/label.md +203 -0
  212. package/docs/components/listbox.md +1004 -0
  213. package/docs/components/menu.md +1229 -0
  214. package/docs/components/menubar.md +443 -0
  215. package/docs/components/meter.md +315 -0
  216. package/docs/components/navigation-menu.md +1523 -0
  217. package/docs/components/number-input.md +1029 -0
  218. package/docs/components/otp-input.md +512 -0
  219. package/docs/components/pagination.md +613 -0
  220. package/docs/components/password-input.md +649 -0
  221. package/docs/components/popover.md +1448 -0
  222. package/docs/components/preferences.md +208 -0
  223. package/docs/components/progress.md +423 -0
  224. package/docs/components/radio.md +785 -0
  225. package/docs/components/rating.md +416 -0
  226. package/docs/components/resizable.md +910 -0
  227. package/docs/components/scroll-area.md +915 -0
  228. package/docs/components/segmented-control.md +435 -0
  229. package/docs/components/select.md +2015 -0
  230. package/docs/components/separator.md +229 -0
  231. package/docs/components/slider.md +1084 -0
  232. package/docs/components/switch.md +565 -0
  233. package/docs/components/tabs.md +944 -0
  234. package/docs/components/textarea.md +299 -0
  235. package/docs/components/time-input.md +224 -0
  236. package/docs/components/timeline.md +654 -0
  237. package/docs/components/toast.md +1224 -0
  238. package/docs/components/toggle.md +500 -0
  239. package/docs/components/token-input.md +953 -0
  240. package/docs/components/toolbar.md +739 -0
  241. package/docs/components/tooltip.md +818 -0
  242. package/docs/components/tree.md +1306 -0
  243. package/docs/components/trigger-menu.md +1223 -0
  244. package/docs/components/waterfall.md +717 -0
  245. package/docs/controllers.md +71 -0
  246. package/docs/core.md +8027 -0
  247. package/docs/custom-parts.md +89 -0
  248. package/docs/first-component.md +83 -0
  249. package/docs/forms.md +122 -0
  250. package/docs/installation.md +72 -0
  251. package/docs/introduction.md +32 -0
  252. package/docs/lists-and-menus.md +122 -0
  253. package/docs/llms.txt +1502 -0
  254. package/docs/parts-and-composition.md +85 -0
  255. package/docs/popups.md +108 -0
  256. package/docs/rendering.md +56 -0
  257. package/docs/server-rendering.md +180 -0
  258. package/docs/state-and-events.md +100 -0
  259. package/docs/styling-and-animation.md +148 -0
  260. package/docs/utilities/async-options.md +348 -0
  261. package/docs/utilities/shortcuts.md +159 -0
  262. package/package.json +352 -3
@@ -0,0 +1,49 @@
1
+ import type { Primitive } from "@ui-sdk/core";
2
+ import { type Slots } from "vue";
3
+ import { type PrimitiveHandle } from "./use-primitive.js";
4
+ /**
5
+ * The component a part of `primitive` connects to: the one its controller is
6
+ * attached to, from anywhere on the page, or else the one it sits in. So a
7
+ * trigger inside one dialog that names another's controller opens the other,
8
+ * once that one mounts. Reading it in a render tracks it, so a part renders
9
+ * again once the component mounts. Call in `setup`.
10
+ */
11
+ declare function useControllerTarget<P extends Primitive>(primitive: P, controller: () => object | undefined): () => PrimitiveHandle<P> | undefined;
12
+ declare function useControllerEntry(controller: () => object | undefined, value: unknown): void;
13
+ /**
14
+ * Shares the component a trigger connects to through its controller with the
15
+ * parts inside the trigger, like a select's value, in its default slot or its
16
+ * `render` slot. Call in the trigger's `setup`.
17
+ */
18
+ declare function provideConnected<P extends Primitive>(primitive: P, handle: () => PrimitiveHandle<P> | undefined): void;
19
+ /**
20
+ * The component of a part that may sit inside a trigger: the one the trigger
21
+ * connects to, undefined until that one mounts, or else its root's. Render it
22
+ * with `useConnectedPart`. Throws outside both, like `useHandle`. Call in `setup`.
23
+ */
24
+ declare function useConnectedHandle<P extends Primitive>(primitive: P): () => PrimitiveHandle<P> | undefined;
25
+ /**
26
+ * A part whose component isn't known yet, like a trigger a controller
27
+ * connects before its popup mounts: its element without a part, rendered the
28
+ * way a part renders, with a neutral `state` for its slots and `children`, its
29
+ * own content, like a value's placeholder.
30
+ */
31
+ declare function renderUnbound<State extends object>(tag: string, props: Record<string, unknown>, { slots, state, children, }: {
32
+ slots: Slots;
33
+ state: State;
34
+ children?: (state: State) => unknown;
35
+ }): import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
36
+ [key: string]: any;
37
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
38
+ [key: string]: any;
39
+ }>[];
40
+ /**
41
+ * Renders a part that may find its component through a controller, like a
42
+ * trigger outside its popup: `unbound` until `handle()` gives a component,
43
+ * then the render `bind` makes for that component, the way `usePart` makes
44
+ * one in setup. Both render from this one component, which binds again when
45
+ * the component changes, so the element, and the focus on it, stay. Call in
46
+ * `setup`; it returns the render function.
47
+ */
48
+ declare function useConnectedPart<H extends PrimitiveHandle<Primitive>>(handle: () => H | undefined, bind: (handle: H) => () => unknown, unbound: () => unknown): () => unknown;
49
+ export { provideConnected, renderUnbound, useConnectedHandle, useConnectedPart, useControllerEntry, useControllerTarget, };
@@ -0,0 +1,112 @@
1
+ // src/controller-target.ts
2
+ import {
3
+ effectScope,
4
+ inject,
5
+ onScopeDispose,
6
+ provide,
7
+ shallowRef,
8
+ watchPostEffect
9
+ } from "vue";
10
+ import {
11
+ renderElement,
12
+ useHandle,
13
+ useScope
14
+ } from "./use-primitive.js";
15
+ var controlled = /* @__PURE__ */ new WeakMap();
16
+ function controlledRef(controller) {
17
+ let current = controlled.get(controller);
18
+ if (!current) {
19
+ controlled.set(controller, current = shallowRef(void 0));
20
+ }
21
+ return current;
22
+ }
23
+ function useControllerTarget(primitive, controller) {
24
+ const nearest = useScope(primitive)?.handle;
25
+ return () => {
26
+ const current = controller();
27
+ return (current && controlledRef(current).value) ?? nearest;
28
+ };
29
+ }
30
+ function useControllerEntry(controller, value) {
31
+ watchPostEffect((onCleanup) => {
32
+ const current = controller();
33
+ if (!current) {
34
+ return;
35
+ }
36
+ const entry = controlledRef(current);
37
+ entry.value = value;
38
+ onCleanup(() => {
39
+ if (entry.value === value) {
40
+ entry.value = void 0;
41
+ }
42
+ });
43
+ });
44
+ }
45
+ var connectedKeys = /* @__PURE__ */ new WeakMap();
46
+ function connectedKey(primitive) {
47
+ let key = connectedKeys.get(primitive);
48
+ if (!key) {
49
+ connectedKeys.set(primitive, key = /* @__PURE__ */ Symbol(`${primitive.name}-connected`));
50
+ }
51
+ return key;
52
+ }
53
+ function provideConnected(primitive, handle) {
54
+ provide(
55
+ connectedKey(primitive),
56
+ handle
57
+ );
58
+ }
59
+ function useConnectedHandle(primitive) {
60
+ const connected = inject(connectedKey(primitive), null);
61
+ if (connected) {
62
+ return connected;
63
+ }
64
+ const handle = useHandle(primitive);
65
+ return () => handle;
66
+ }
67
+ function renderUnbound(tag, props, {
68
+ slots,
69
+ state,
70
+ children
71
+ }) {
72
+ return renderElement(props, slots, state, { tag, children });
73
+ }
74
+ function watchedRefs(handle) {
75
+ let lastRef;
76
+ const watched = Object.create(handle);
77
+ watched.slot = (name, props, user) => {
78
+ const result = handle.slot(name, props, user);
79
+ lastRef = result.ref;
80
+ return result;
81
+ };
82
+ return { handle: watched, release: () => lastRef?.(null) };
83
+ }
84
+ function useConnectedPart(handle, bind, unbound) {
85
+ let current;
86
+ let bound;
87
+ onScopeDispose(() => bound?.scope.stop());
88
+ return () => {
89
+ const next = handle();
90
+ if (next !== current) {
91
+ current = next;
92
+ bound?.release();
93
+ bound?.scope.stop();
94
+ bound = next && bindTo(next, bind);
95
+ }
96
+ return bound ? bound.render() : unbound();
97
+ };
98
+ }
99
+ function bindTo(handle, bind) {
100
+ const scope = effectScope(true);
101
+ const watched = watchedRefs(handle);
102
+ const render = scope.run(() => bind(watched.handle));
103
+ return { scope, render, release: watched.release };
104
+ }
105
+ export {
106
+ provideConnected,
107
+ renderUnbound,
108
+ useConnectedHandle,
109
+ useConnectedPart,
110
+ useControllerEntry,
111
+ useControllerTarget
112
+ };
@@ -0,0 +1,126 @@
1
+ import type { OptionsOf, Primitive, PropsOf, SlotName, StateOf, TypesOf } from "@ui-sdk/core";
2
+ import { type PrimitiveGeneric } from "@ui-sdk/core/renderer";
3
+ import { type DefineSetupFnComponent, type EmitsToProps, type HTMLAttributes, type IntrinsicElementAttributes, type PublicProps, type SlotsType, type VNode } from "vue";
4
+ import { type StateSlots } from "./use-primitive.js";
5
+ type Pascal<Name extends string> = Name extends `${infer Head}-${infer Tail}` ? `${Capitalize<Head>}${Pascal<Tail>}` : Capitalize<Name>;
6
+ type CallbackKeys<Props> = {
7
+ [Key in keyof Props & `on${string}`]-?: NonNullable<Props[Key]> extends (...args: never[]) => unknown ? Key : never;
8
+ }[keyof Props & `on${string}`];
9
+ type CallbackArgs<Props, Key extends keyof Props> = Parameters<Extract<NonNullable<Props[Key]>, (...args: never[]) => unknown>>;
10
+ /**
11
+ * A part's events: `<name>` for each `on<Name>` prop, and `update:<key>` for
12
+ * each `on<Key>Change` when there's a `<key>` prop, for `v-model:<key>`.
13
+ */
14
+ type Emits<Props> = {
15
+ [Key in CallbackKeys<Props> as Key extends `on${infer Name}` ? Uncapitalize<Name> : never]: (...args: CallbackArgs<Props, Key>) => true;
16
+ } & {
17
+ [Key in CallbackKeys<Props> as Key extends `on${infer Model}Change` ? Uncapitalize<Model> extends keyof Props ? `update:${Uncapitalize<Model>}` : never : never]: (value: CallbackArgs<Props, Key>[0]) => true;
18
+ };
19
+ type ModelKey<Props, Keys = ["value", "checked", "pressed", "open", "page", "layout"]> = Keys extends [infer Key extends string, ...infer Rest] ? Key extends keyof Props ? `on${Capitalize<Key>}Change` extends CallbackKeys<Props> ? Key : ModelKey<Props, Rest> : ModelKey<Props, Rest> : never;
20
+ type Model<Props> = [ModelKey<Props>] extends [never] ? {} : {
21
+ modelValue?: Props[ModelKey<Props> & keyof Props];
22
+ };
23
+ type ModelEmits<Props> = [ModelKey<Props>] extends [never] ? {} : {
24
+ "update:modelValue": (value: CallbackArgs<Props, `on${Capitalize<ModelKey<Props>>}Change` & CallbackKeys<Props>>[0]) => true;
25
+ };
26
+ /**
27
+ * The attributes and events of the element `Tag`, which fall through to a part
28
+ * that renders it, with `data-*` attributes, which a template hands a
29
+ * component in camel case.
30
+ */
31
+ type ElementAttributes<Tag extends string> = (Tag extends keyof IntrinsicElementAttributes ? IntrinsicElementAttributes[Tag] : HTMLAttributes) & {
32
+ [attribute: `data${Capitalize<string>}`]: unknown;
33
+ };
34
+ type FallthroughOf<Tag extends string, Props> = Omit<ElementAttributes<Tag>, keyof Props>;
35
+ type Component = new (...args: any[]) => {
36
+ $props: object;
37
+ };
38
+ /**
39
+ * A part that also takes the attributes and events of the element `Tag` it
40
+ * renders, under strict templates too. One construct signature, so a template
41
+ * and `InstanceType` both see them.
42
+ */
43
+ type ElementPart<Part extends Component, Tag extends string> = Pick<Part, keyof Part> & ElementConstructor<Part, Tag>;
44
+ interface ElementConstructor<Part extends Component, Tag extends string> {
45
+ new (...args: any[]): ElementInstance<Part, Tag>;
46
+ }
47
+ type ElementInstance<Part extends Component, Tag extends string> = InstanceType<Part> & {
48
+ $props: FallthroughOf<Tag, InstanceType<Part>["$props"]>;
49
+ };
50
+ /**
51
+ * Types a part written by hand to take the attributes and events of the
52
+ * element it renders, the way `createParts` types its parts.
53
+ */
54
+ declare function withElement<Tag extends string, Part extends Component>(_tag: Tag, part: Part): ElementPart<Part, Tag>;
55
+ type PartComponent<Props, State, Tag extends string> = ElementPart<DefineSetupFnComponent<Omit<Props, CallbackKeys<Props>>, Emits<Props>, StateSlots<State>>, Tag>;
56
+ type GenericProps<Props, Tag extends string = never> = Props & EmitsToProps<Emits<Props>> & PublicProps & ([Tag] extends [never] ? {} : FallthroughOf<Tag, Props>);
57
+ type GenericRootProps<Props, Tag extends string = never> = GenericProps<Props, Tag> & Model<Props> & EmitsToProps<ModelEmits<Props>>;
58
+ /**
59
+ * A hand-written root's component type, for one generic over its value like
60
+ * `createParts`' roots: `new <T>(props: RootPropsOf<Options<T>>) => RootInstanceOf<Options<T>>`.
61
+ * Callbacks are events and plain `v-model` binds the main value. A union of
62
+ * options, like one shape per `multiple`, keeps each shape's own.
63
+ */
64
+ type RootPropsOf<Props, Tag extends string = never> = GenericRootProps<Props, Tag>;
65
+ type RootInstanceOf<Props, State = {}, Tag extends string = never> = InstanceType<RootPart<Props, State, Tag>>;
66
+ type RenderableWith<Props, State = {}, Tag extends string = never> = new (props: never) => RootInstanceOf<Props, State, Tag>;
67
+ type RootSlot<P extends Primitive> = "root" & SlotName<P>;
68
+ type GenericOf<P> = P extends {
69
+ generic?: infer G extends PrimitiveGeneric;
70
+ } ? G : never;
71
+ type Applied<G, T, U> = G & {
72
+ T: T;
73
+ U: U;
74
+ };
75
+ type DefaultOf<G extends PrimitiveGeneric, K extends "T" | "U"> = G extends {
76
+ defaults: Record<K, infer D>;
77
+ } ? D & G[K] : G[K];
78
+ type StateIn<P extends Primitive, S extends SlotName<P>, A> = A extends {
79
+ state: Record<S, infer State>;
80
+ } ? State : StateOf<P, S>;
81
+ type RootProps<P extends Primitive, Options, Tag extends string> = Options & ([Tag] extends [never] ? {} : PropsOf<P, RootSlot<P>>);
82
+ type RootSlots<State, HasTag> = HasTag extends true ? StateSlots<State> : SlotsType<{
83
+ default?: () => VNode[];
84
+ }>;
85
+ type RootComponent<Props, State, HasTag> = DefineSetupFnComponent<Omit<Props, CallbackKeys<Props>> & Model<Props>, Emits<Props> & ModelEmits<Props>, RootSlots<State, HasTag>>;
86
+ type RootPart<Props, State, Tag extends string> = [Tag] extends [never] ? RootComponent<Props, State, false> : ElementPart<RootComponent<Props, State, true>, Tag>;
87
+ type RootOf<P extends Primitive, Tag extends string> = [GenericOf<P>] extends [
88
+ never
89
+ ] ? RootPart<RootProps<P, OptionsOf<P>, Tag>, StateOf<P, RootSlot<P>>, Tag> : new <A extends GenericOf<P>["T"] = DefaultOf<GenericOf<P>, "T">, B extends GenericOf<P>["U"] = DefaultOf<GenericOf<P>, "U">>(props: GenericRootProps<RootProps<P, Applied<GenericOf<P>, A, B>["options"], Tag>, Tag>) => RootInstanceOf<RootProps<P, Applied<GenericOf<P>, A, B>["options"], Tag>, StateIn<P, RootSlot<P>, Applied<GenericOf<P>, A, B>>, Tag>;
90
+ type PartOf<P extends Primitive, S extends SlotName<P>, Tag extends string> = [
91
+ GenericOf<P>
92
+ ] extends [never] ? PartComponent<PropsOf<P, S>, StateOf<P, S>, Tag> : GenericOf<P> extends {
93
+ props: Record<S, unknown>;
94
+ } ? new <A extends GenericOf<P>["T"] = DefaultOf<GenericOf<P>, "T">>(props: GenericProps<GenericPartProps<P, S, A>, Tag>) => InstanceType<PartComponent<GenericPartProps<P, S, A>, StateIn<P, S, Applied<GenericOf<P>, A, unknown>>, Tag>> : PartComponent<PropsOf<P, S>, StateIn<P, S, GenericOf<P>>, Tag>;
95
+ type GenericPartProps<P extends Primitive, S extends SlotName<P>, A> = (Applied<GenericOf<P>, A, unknown>["props"] & Record<S, unknown>)[S];
96
+ /**
97
+ * The components `createParts` makes: `Root`, and one per tagged slot, named in Pascal case.
98
+ * @stable
99
+ */
100
+ type Parts<P extends Primitive, Tags extends {
101
+ [S in SlotName<P>]?: string;
102
+ }> = {
103
+ Root: RootOf<P, Tags extends {
104
+ root: infer Tag extends string;
105
+ } ? Tag : never>;
106
+ } & {
107
+ [S in keyof TypesOf<P>["slots"] as S extends Exclude<keyof Tags, "root"> & string ? Pascal<S> : never]: PartOf<P, S & SlotName<P>, Tags[S & keyof Tags] & string>;
108
+ };
109
+ /**
110
+ * Every part of a primitive as a component, typed from it. `Root` makes the
111
+ * instance from the primitive's options and shares it with the parts inside
112
+ * it. Each slot named in `tags` becomes a component that renders that tag,
113
+ * named in Pascal case, like `TabIcon` for `tab-icon`. Without a `root` tag,
114
+ * `Root` renders only its default slot. Callbacks are events, and
115
+ * `on<Key>Change` also emits `update:<key>`, so `v-model:<key>` works. Every
116
+ * part takes the attributes and events of its tag and a `render` slot, and its
117
+ * default slot receives its state.
118
+ *
119
+ * @example
120
+ * const { Root: Playlist, Track: PlaylistTrack } = createParts(playlist, { root: "ul", track: "li" })
121
+ * @stable
122
+ */
123
+ declare function createParts<P extends Primitive, const Tags extends {
124
+ [S in SlotName<P>]?: string;
125
+ }>(primitive: P, tags: Tags): Parts<P, Tags>;
126
+ export { createParts, type ElementAttributes, type ElementConstructor, type ElementInstance, type ElementPart, type Parts, type RenderableWith, type RootInstanceOf, type RootPropsOf, withElement, };
@@ -0,0 +1,206 @@
1
+ // src/create-parts.ts
2
+ import { schemaOf } from "@ui-sdk/core/renderer";
3
+ import {
4
+ defineComponent,
5
+ useId
6
+ } from "vue";
7
+ import {
8
+ optionalBoolean,
9
+ pascal,
10
+ provideProps,
11
+ usePart,
12
+ usePrimitive,
13
+ useScope
14
+ } from "./use-primitive.js";
15
+ import { warnAttributes } from "./renderless.js";
16
+ var kindOf = (spec) => typeof spec === "string" ? spec : typeof spec === "object" ? spec.kind : "value";
17
+ var fromOf = (spec, key) => {
18
+ if (typeof spec !== "object") {
19
+ return void 0;
20
+ }
21
+ const [slot, prop = key] = spec.from.split(".");
22
+ return { slot, prop };
23
+ };
24
+ var propTypes = {
25
+ string: String,
26
+ number: Number,
27
+ boolean: optionalBoolean,
28
+ list: [Array, String],
29
+ value: null,
30
+ id: null,
31
+ key: null,
32
+ action: Function
33
+ };
34
+ function runtimeProps(...schemas) {
35
+ const props = {};
36
+ for (const schema of schemas) {
37
+ for (const key in schema) {
38
+ const kind = kindOf(schema[key]);
39
+ if (kind !== "callback") {
40
+ props[key] = propTypes[kind];
41
+ }
42
+ }
43
+ }
44
+ return props;
45
+ }
46
+ function eventsOf(schema) {
47
+ return Object.keys(schema).filter((key) => kindOf(schema[key]) === "callback").map((key) => {
48
+ const event = key[2].toLowerCase() + key.slice(3);
49
+ const model = event.endsWith("Change") ? event.slice(0, -"Change".length) : "";
50
+ return {
51
+ key,
52
+ event,
53
+ update: model in schema ? `update:${model}` : void 0
54
+ };
55
+ });
56
+ }
57
+ var models = ["value", "checked", "pressed", "open", "page", "layout"];
58
+ var modelOf = (events) => models.find((key) => events.some(({ update }) => update === `update:${key}`));
59
+ var emitsOf = (events) => events.flatMap(({ event, update }) => update ? [event, update] : [event]);
60
+ function emitters(events, emit) {
61
+ const callbacks = {};
62
+ for (const { key, event, update } of events) {
63
+ callbacks[key] = (...args) => {
64
+ emit(event, ...args);
65
+ if (update && !args[1]?.canceled) {
66
+ emit(update, args[0]);
67
+ }
68
+ };
69
+ }
70
+ return callbacks;
71
+ }
72
+ // @__NO_SIDE_EFFECTS__
73
+ function withElement(_tag, part) {
74
+ return part;
75
+ }
76
+ function createParts(primitive, tags) {
77
+ const schema = schemaOf(primitive);
78
+ const name = pascal(primitive.name);
79
+ const tagOf = tags;
80
+ const provides = new Set(
81
+ Object.values(schema.slots).flatMap(
82
+ (props) => Object.entries(props).flatMap(
83
+ ([key, spec]) => fromOf(spec, key)?.slot ?? []
84
+ )
85
+ )
86
+ );
87
+ const keyed = new Set(
88
+ Object.entries(schema.slots).flatMap(
89
+ ([slot, props]) => Object.values(props).some((spec) => kindOf(spec) === "key") ? [slot] : []
90
+ )
91
+ );
92
+ const options = Object.keys(schema.options).filter(
93
+ (option) => kindOf(schema.options[option]) !== "callback"
94
+ );
95
+ const rootSchema = tagOf.root ? schema.slots.root ?? {} : {};
96
+ const rootEvents = eventsOf({ ...schema.options, ...rootSchema });
97
+ const model = modelOf(rootEvents);
98
+ function useSlotProps(slot, props, callbacks, model2) {
99
+ const scope = useScope(primitive);
100
+ const around = scope?.around ?? {};
101
+ const fields = Object.entries(schema.slots[slot] ?? {}).filter(([, spec]) => kindOf(spec) !== "callback").map(([prop, spec]) => {
102
+ const from = fromOf(spec, prop);
103
+ if (from && !around[from.slot] && spec.required) {
104
+ throw new Error(
105
+ `<${name}${pascal(slot)}> must be used inside <${name}${pascal(from.slot)}>.`
106
+ );
107
+ }
108
+ return {
109
+ prop,
110
+ id: kindOf(spec) === "id" ? useId() : void 0,
111
+ from,
112
+ key: kindOf(spec) === "key"
113
+ };
114
+ });
115
+ return () => {
116
+ const result = { ...callbacks };
117
+ for (const { prop, id, from, key } of fields) {
118
+ let value = props[prop];
119
+ if (value === void 0 && prop === model2) {
120
+ value = props.modelValue;
121
+ }
122
+ if (value === void 0) {
123
+ value = id ?? (from && around[from.slot]?.()[from.prop]);
124
+ }
125
+ result[prop] = value;
126
+ if (key) {
127
+ result.id = (scope?.handle.api).internal.keyOf(value);
128
+ }
129
+ }
130
+ return result;
131
+ };
132
+ }
133
+ const Root = defineComponent({
134
+ name,
135
+ inheritAttrs: false,
136
+ props: {
137
+ ...runtimeProps(schema.options, rootSchema),
138
+ ...model ? { modelValue: null } : {}
139
+ },
140
+ emits: [...emitsOf(rootEvents), ...model ? ["update:modelValue"] : []],
141
+ setup(props, { slots, emit, attrs }) {
142
+ const callbacks = emitters(rootEvents, (event, ...args) => {
143
+ emit(event, ...args);
144
+ if (event === `update:${model}`) {
145
+ emit("update:modelValue", ...args);
146
+ }
147
+ });
148
+ const handle = usePrimitive(primitive, () => {
149
+ const current = { ...callbacks };
150
+ for (const option of options) {
151
+ current[option] = props[option];
152
+ }
153
+ if (model && current[model] === void 0) {
154
+ current[model] = props.modelValue;
155
+ }
156
+ return current;
157
+ });
158
+ if (!tagOf.root) {
159
+ warnAttributes(name, attrs);
160
+ return () => slots.default?.();
161
+ }
162
+ return usePart(
163
+ handle,
164
+ "root",
165
+ useSlotProps("root", props, callbacks, model),
166
+ void 0,
167
+ tagOf.root
168
+ );
169
+ }
170
+ });
171
+ const parts = { Root };
172
+ for (const slot in tagOf) {
173
+ if (slot === "root") {
174
+ continue;
175
+ }
176
+ const partName = `${name}${pascal(slot)}`;
177
+ const slotSchema = schema.slots[slot] ?? {};
178
+ const events = eventsOf(slotSchema);
179
+ parts[pascal(slot)] = defineComponent({
180
+ name: partName,
181
+ inheritAttrs: false,
182
+ props: runtimeProps(slotSchema),
183
+ emits: emitsOf(events),
184
+ setup(props, { emit, attrs }) {
185
+ if (!useScope(primitive)) {
186
+ throw new Error(`<${partName}> must be used inside <${name}>.`);
187
+ }
188
+ const slotProps = useSlotProps(slot, props, emitters(events, emit));
189
+ if (provides.has(slot)) {
190
+ provideProps(
191
+ primitive,
192
+ slot,
193
+ keyed.has(slot) ? () => ({ ...slotProps(), value: slotProps().id }) : slotProps
194
+ );
195
+ }
196
+ const user = "id" in slotSchema ? () => props.id == null ? attrs : { ...attrs, id: props.id } : void 0;
197
+ return usePart(primitive, slot, slotProps, user, tagOf[slot]);
198
+ }
199
+ });
200
+ }
201
+ return parts;
202
+ }
203
+ export {
204
+ createParts,
205
+ withElement
206
+ };
@@ -0,0 +1,133 @@
1
+ import { type DateMatchers } from "@ui-sdk/core/date-input";
2
+ import { type PropType } from "vue";
3
+ import type { PartSlots } from "./use-primitive.js";
4
+ /**
5
+ * A segment, like the month: an input arrow keys step and digits fill, named
6
+ * by its unit. The text between segments renders as a span.
7
+ * @stable
8
+ */
9
+ declare const DateInputSegment: import("./create-parts.js").ElementPart<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
10
+ segment: {
11
+ type: PropType<import("@ui-sdk/core/date-input").DateInputSegmentData>;
12
+ required: true;
13
+ };
14
+ }>, (() => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
15
+ [key: string]: any;
16
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
17
+ [key: string]: any;
18
+ }>[] | null) & {
19
+ state: NoInfer<import("@ui-sdk/core/date-input").DateInputSegmentState>;
20
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
21
+ segment: {
22
+ type: PropType<import("@ui-sdk/core/date-input").DateInputSegmentData>;
23
+ required: true;
24
+ };
25
+ }>> & Readonly<{}>, {}, PartSlots<import("@ui-sdk/core/date-input").DateInputPrimitive, "segment">, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, "input">;
26
+ /**
27
+ * The root: a group of segments the locale orders, like month, day and year,
28
+ * and the hidden input the ISO value submits with. Without content it renders
29
+ * every segment; its default slot gets `state`, whose `segments` it can render.
30
+ * @stable
31
+ */
32
+ declare const DateInput: import("./create-parts.js").ElementPart<import("vue").DefineComponent<import("vue").ExtractPropTypes<{
33
+ unavailable: PropType<DateMatchers>;
34
+ value: {
35
+ type: PropType<string | null>;
36
+ default: undefined;
37
+ };
38
+ modelValue: {
39
+ type: PropType<string | null>;
40
+ default: undefined;
41
+ };
42
+ defaultValue: {
43
+ type: PropType<string | null>;
44
+ default: undefined;
45
+ };
46
+ granularity: PropType<"day" | "hour" | "minute" | "second">;
47
+ hourCycle: PropType<import("@ui-sdk/core/date-input").HourCycle>;
48
+ min: StringConstructor;
49
+ max: StringConstructor;
50
+ locale: StringConstructor;
51
+ disabled: {
52
+ type: BooleanConstructor;
53
+ default: undefined;
54
+ };
55
+ readOnly: {
56
+ type: BooleanConstructor;
57
+ default: undefined;
58
+ };
59
+ required: {
60
+ type: BooleanConstructor;
61
+ default: undefined;
62
+ };
63
+ name: StringConstructor;
64
+ form: StringConstructor;
65
+ controller: PropType<import("@ui-sdk/core/date-input").DateInputController>;
66
+ debug: {
67
+ type: BooleanConstructor;
68
+ default: undefined;
69
+ };
70
+ }>, (() => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
71
+ [key: string]: any;
72
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
73
+ [key: string]: any;
74
+ }>[] | null) & {
75
+ state: NoInfer<import("@ui-sdk/core/date-input").DateInputState>;
76
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
77
+ "update:value": (_value: string | null) => boolean;
78
+ "update:modelValue": (_value: string | null) => boolean;
79
+ valueChange: (_value: string | null, _details: import("@ui-sdk/core").ChangeDetails<import("@ui-sdk/core/date-input").DateInputValueChangeReason>) => boolean;
80
+ }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
81
+ unavailable: PropType<DateMatchers>;
82
+ value: {
83
+ type: PropType<string | null>;
84
+ default: undefined;
85
+ };
86
+ modelValue: {
87
+ type: PropType<string | null>;
88
+ default: undefined;
89
+ };
90
+ defaultValue: {
91
+ type: PropType<string | null>;
92
+ default: undefined;
93
+ };
94
+ granularity: PropType<"day" | "hour" | "minute" | "second">;
95
+ hourCycle: PropType<import("@ui-sdk/core/date-input").HourCycle>;
96
+ min: StringConstructor;
97
+ max: StringConstructor;
98
+ locale: StringConstructor;
99
+ disabled: {
100
+ type: BooleanConstructor;
101
+ default: undefined;
102
+ };
103
+ readOnly: {
104
+ type: BooleanConstructor;
105
+ default: undefined;
106
+ };
107
+ required: {
108
+ type: BooleanConstructor;
109
+ default: undefined;
110
+ };
111
+ name: StringConstructor;
112
+ form: StringConstructor;
113
+ controller: PropType<import("@ui-sdk/core/date-input").DateInputController>;
114
+ debug: {
115
+ type: BooleanConstructor;
116
+ default: undefined;
117
+ };
118
+ }>> & Readonly<{
119
+ "onUpdate:modelValue"?: ((_value: string | null) => any) | undefined;
120
+ "onUpdate:value"?: ((_value: string | null) => any) | undefined;
121
+ onValueChange?: ((_value: string | null, _details: import("@ui-sdk/core").ChangeDetails<import("@ui-sdk/core/date-input").DateInputValueChangeReason>) => any) | undefined;
122
+ }>, {
123
+ value: string | null;
124
+ disabled: boolean;
125
+ debug: boolean;
126
+ defaultValue: string | null;
127
+ required: boolean;
128
+ readOnly: boolean;
129
+ modelValue: string | null;
130
+ }, PartSlots<import("@ui-sdk/core/date-input").DateInputPrimitive, "root">, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, "div">;
131
+ export { createDateInputController } from "@ui-sdk/core/date-input";
132
+ export type { DateInputApi, DateInputChangeOptions, DateInputController, DateInputGranularity, DateInputOptions, DateInputPrimitive, DateInputSegmentData, DateInputSegmentProps, DateInputSegmentState, DateInputSegmentType, DateInputState, DateInputValueChangeReason, DateMatcher, DateMatchers, HourCycle, } from "@ui-sdk/core/date-input";
133
+ export { DateInput, DateInputSegment };
@@ -0,0 +1,31 @@
1
+ // src/date-input.ts
2
+ import { dateInput } from "@ui-sdk/core/date-input";
3
+ import { defineComponent } from "vue";
4
+ import { withElement } from "./create-parts.js";
5
+ import {
6
+ defineSegment,
7
+ rootEmits,
8
+ rootProps,
9
+ setupRoot
10
+ } from "./segmented-input.js";
11
+ import { createDateInputController } from "@ui-sdk/core/date-input";
12
+ var DateInputSegment = defineSegment(dateInput, "DateInputSegment");
13
+ var DateInput = withElement(
14
+ "div",
15
+ defineComponent({
16
+ name: "DateInput",
17
+ inheritAttrs: false,
18
+ props: {
19
+ ...rootProps,
20
+ unavailable: null
21
+ },
22
+ emits: rootEmits,
23
+ slots: Object,
24
+ setup: (props, context) => setupRoot(dateInput, DateInputSegment, props, context)
25
+ })
26
+ );
27
+ export {
28
+ DateInput,
29
+ DateInputSegment,
30
+ createDateInputController
31
+ };