@atscript/vue-form 0.1.58

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 (190) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/as-action-71f9E_bL.cjs +208 -0
  4. package/dist/as-action-DU17rykn.mjs +203 -0
  5. package/dist/as-action.cjs +2 -0
  6. package/dist/as-action.d.cts +2 -0
  7. package/dist/as-action.d.mts +2 -0
  8. package/dist/as-action.mjs +2 -0
  9. package/dist/as-action.vue-BdbAOZCL.d.cts +13 -0
  10. package/dist/as-action.vue-CmY3eil1.d.mts +13 -0
  11. package/dist/as-adornment-shell-9UmdNIPR.cjs +97 -0
  12. package/dist/as-adornment-shell-knFiB7Ct.mjs +92 -0
  13. package/dist/as-array-Bn27x9cq.cjs +466 -0
  14. package/dist/as-array-DwarTaKP.mjs +455 -0
  15. package/dist/as-array-clear-btn-DAGervXL.cjs +48 -0
  16. package/dist/as-array-clear-btn-DIhzCKC9.mjs +43 -0
  17. package/dist/as-array.cjs +11 -0
  18. package/dist/as-array.d.cts +2 -0
  19. package/dist/as-array.d.mts +2 -0
  20. package/dist/as-array.mjs +11 -0
  21. package/dist/as-array.vue-C5r_ycIa.d.mts +9 -0
  22. package/dist/as-array.vue-CeBZRVm7.d.cts +9 -0
  23. package/dist/as-checkbox-B_9mwla6.mjs +285 -0
  24. package/dist/as-checkbox-DXGTVHPE.cjs +296 -0
  25. package/dist/as-checkbox.cjs +6 -0
  26. package/dist/as-checkbox.d.cts +2 -0
  27. package/dist/as-checkbox.d.mts +2 -0
  28. package/dist/as-checkbox.mjs +6 -0
  29. package/dist/as-checkbox.vue-BL53Xjmi.d.mts +9 -0
  30. package/dist/as-checkbox.vue-Da1KVG5J.d.cts +9 -0
  31. package/dist/as-collapsible-CqxeJut7.cjs +148 -0
  32. package/dist/as-collapsible-DtNCofNT.mjs +143 -0
  33. package/dist/as-date-C7tFQDkh.mjs +253 -0
  34. package/dist/as-date-k3MW3dmA.cjs +258 -0
  35. package/dist/as-date.cjs +8 -0
  36. package/dist/as-date.d.cts +2 -0
  37. package/dist/as-date.d.mts +2 -0
  38. package/dist/as-date.mjs +8 -0
  39. package/dist/as-date.vue-C5JaS3Sd.d.mts +9 -0
  40. package/dist/as-date.vue-e2ewS_V4.d.cts +9 -0
  41. package/dist/as-datetime-C030mzI5.cjs +258 -0
  42. package/dist/as-datetime-elcOoDT5.mjs +253 -0
  43. package/dist/as-datetime.cjs +8 -0
  44. package/dist/as-datetime.d.cts +2 -0
  45. package/dist/as-datetime.d.mts +2 -0
  46. package/dist/as-datetime.mjs +8 -0
  47. package/dist/as-datetime.vue-ClsSnJSV.d.mts +9 -0
  48. package/dist/as-datetime.vue-vfHFsby6.d.cts +9 -0
  49. package/dist/as-decimal-BJIGgPXU.cjs +711 -0
  50. package/dist/as-decimal-DtXjFPhe.mjs +694 -0
  51. package/dist/as-decimal.cjs +7 -0
  52. package/dist/as-decimal.d.cts +2 -0
  53. package/dist/as-decimal.d.mts +2 -0
  54. package/dist/as-decimal.mjs +7 -0
  55. package/dist/as-decimal.vue-B1pEKdjM.d.cts +25 -0
  56. package/dist/as-decimal.vue-CSCtYRRa.d.mts +25 -0
  57. package/dist/as-field-CXVjrEPQ.mjs +481 -0
  58. package/dist/as-field-shell-B2iTn-iM.cjs +346 -0
  59. package/dist/as-field-shell-Pdy3sAvr.mjs +341 -0
  60. package/dist/as-field-shell.cjs +5 -0
  61. package/dist/as-field-shell.d.cts +2 -0
  62. package/dist/as-field-shell.d.mts +2 -0
  63. package/dist/as-field-shell.mjs +5 -0
  64. package/dist/as-field-shell.vue-Ddnp8KxY.d.mts +37 -0
  65. package/dist/as-field-shell.vue-Dmt05vGD.d.cts +37 -0
  66. package/dist/as-field-wLYoaZnT.cjs +498 -0
  67. package/dist/as-field.cjs +4 -0
  68. package/dist/as-field.d.cts +25 -0
  69. package/dist/as-field.d.mts +26 -0
  70. package/dist/as-field.mjs +4 -0
  71. package/dist/as-form-CWwgyvfw.mjs +425 -0
  72. package/dist/as-form-DAIkyt7H.cjs +448 -0
  73. package/dist/as-form.cjs +7 -0
  74. package/dist/as-form.d.cts +2 -0
  75. package/dist/as-form.d.mts +2 -0
  76. package/dist/as-form.mjs +7 -0
  77. package/dist/as-form.vue-B4Bn0pbC.d.cts +158 -0
  78. package/dist/as-form.vue-DRrb_yoj.d.mts +158 -0
  79. package/dist/as-input-CpbV2k3s.cjs +231 -0
  80. package/dist/as-input-DIa8BzLv.mjs +226 -0
  81. package/dist/as-input-control-BzELjheN.mjs +266 -0
  82. package/dist/as-input-control-C5-DelZT.cjs +271 -0
  83. package/dist/as-input.cjs +8 -0
  84. package/dist/as-input.d.cts +2 -0
  85. package/dist/as-input.d.mts +2 -0
  86. package/dist/as-input.mjs +8 -0
  87. package/dist/as-input.vue-11ldp9uT.d.cts +17 -0
  88. package/dist/as-input.vue-fUhcvfv2.d.mts +17 -0
  89. package/dist/as-iterator-BYMNe6UJ.cjs +61 -0
  90. package/dist/as-iterator-CT5y1jyn.mjs +56 -0
  91. package/dist/as-iterator.cjs +5 -0
  92. package/dist/as-iterator.d.cts +14 -0
  93. package/dist/as-iterator.d.mts +15 -0
  94. package/dist/as-iterator.mjs +5 -0
  95. package/dist/as-number-BA55JIq1.cjs +387 -0
  96. package/dist/as-number-JPEwPK8Q.mjs +376 -0
  97. package/dist/as-number.cjs +8 -0
  98. package/dist/as-number.d.cts +2 -0
  99. package/dist/as-number.d.mts +2 -0
  100. package/dist/as-number.mjs +8 -0
  101. package/dist/as-number.vue-Bk-W7Vwv.d.mts +26 -0
  102. package/dist/as-number.vue-C2Aih98s.d.cts +26 -0
  103. package/dist/as-object-CT6lNEqt.mjs +300 -0
  104. package/dist/as-object-qUL7l8V1.cjs +305 -0
  105. package/dist/as-object.cjs +11 -0
  106. package/dist/as-object.d.cts +2 -0
  107. package/dist/as-object.d.mts +2 -0
  108. package/dist/as-object.mjs +11 -0
  109. package/dist/as-object.vue-CKwMyM_F.d.cts +13 -0
  110. package/dist/as-object.vue-Cg52b61-.d.mts +13 -0
  111. package/dist/as-paragraph-BGO-j4US.cjs +203 -0
  112. package/dist/as-paragraph-jIG_dg7_.mjs +198 -0
  113. package/dist/as-paragraph.cjs +2 -0
  114. package/dist/as-paragraph.d.cts +2 -0
  115. package/dist/as-paragraph.d.mts +2 -0
  116. package/dist/as-paragraph.mjs +2 -0
  117. package/dist/as-paragraph.vue-BDt0pBG-.d.cts +9 -0
  118. package/dist/as-paragraph.vue-C3FgTEt5.d.mts +9 -0
  119. package/dist/as-radio-B1N-gmoI.mjs +242 -0
  120. package/dist/as-radio-U3OK7bTg.cjs +247 -0
  121. package/dist/as-radio.cjs +6 -0
  122. package/dist/as-radio.d.cts +2 -0
  123. package/dist/as-radio.d.mts +2 -0
  124. package/dist/as-radio.mjs +6 -0
  125. package/dist/as-radio.vue-D_fweoN1.d.mts +9 -0
  126. package/dist/as-radio.vue-ZC4kLBnT.d.cts +9 -0
  127. package/dist/as-ref-CIifSSCQ.mjs +337 -0
  128. package/dist/as-ref-SImaIrwK.cjs +342 -0
  129. package/dist/as-ref.cjs +7 -0
  130. package/dist/as-ref.d.cts +2 -0
  131. package/dist/as-ref.d.mts +2 -0
  132. package/dist/as-ref.mjs +7 -0
  133. package/dist/as-ref.vue-BNeQeQpO.d.cts +9 -0
  134. package/dist/as-ref.vue-Cr5jeNDn.d.mts +9 -0
  135. package/dist/as-select-BB3uxACS.cjs +246 -0
  136. package/dist/as-select-UBGCVhku.mjs +241 -0
  137. package/dist/as-select.cjs +6 -0
  138. package/dist/as-select.d.cts +2 -0
  139. package/dist/as-select.d.mts +2 -0
  140. package/dist/as-select.mjs +6 -0
  141. package/dist/as-select.vue-Dd7huPq2.d.cts +9 -0
  142. package/dist/as-select.vue-RYpbZbKt.d.mts +9 -0
  143. package/dist/as-time-C24rvslH.cjs +258 -0
  144. package/dist/as-time-CQsxUs8P.mjs +253 -0
  145. package/dist/as-time.cjs +8 -0
  146. package/dist/as-time.d.cts +2 -0
  147. package/dist/as-time.d.mts +2 -0
  148. package/dist/as-time.mjs +8 -0
  149. package/dist/as-time.vue-huLx2B4l.d.mts +9 -0
  150. package/dist/as-time.vue-nMEHLXke.d.cts +9 -0
  151. package/dist/as-tuple-BU--cuuI.cjs +351 -0
  152. package/dist/as-tuple-DkI9swlW.mjs +340 -0
  153. package/dist/as-tuple.cjs +11 -0
  154. package/dist/as-tuple.d.cts +2 -0
  155. package/dist/as-tuple.d.mts +2 -0
  156. package/dist/as-tuple.mjs +11 -0
  157. package/dist/as-tuple.vue-CQhzOJsn.d.mts +9 -0
  158. package/dist/as-tuple.vue-DyskCkf-.d.cts +9 -0
  159. package/dist/as-union-BGvdxr3G.mjs +351 -0
  160. package/dist/as-union-C0btoJn3.cjs +368 -0
  161. package/dist/as-union.cjs +6 -0
  162. package/dist/as-union.d.cts +2 -0
  163. package/dist/as-union.d.mts +2 -0
  164. package/dist/as-union.mjs +6 -0
  165. package/dist/as-union.vue-BjlDPZn0.d.mts +9 -0
  166. package/dist/as-union.vue-CqjU3O10.d.cts +9 -0
  167. package/dist/as-variant-picker-BVs0AvjK.mjs +96 -0
  168. package/dist/as-variant-picker-DObQZHmm.cjs +107 -0
  169. package/dist/index.cjs +173 -0
  170. package/dist/index.d.cts +966 -0
  171. package/dist/index.d.mts +966 -0
  172. package/dist/index.mjs +105 -0
  173. package/dist/types-C4HRSxgV.d.cts +233 -0
  174. package/dist/types-Czm-Gtud.d.mts +233 -0
  175. package/dist/use-as-date-B7CtcRQd.cjs +329 -0
  176. package/dist/use-as-date-C39i9mzE.mjs +318 -0
  177. package/dist/use-as-dropdown-BMnEm6jF.mjs +82 -0
  178. package/dist/use-as-dropdown-C-Qy7Vt0.cjs +105 -0
  179. package/dist/use-as-locale-BrFdAgnU.mjs +23 -0
  180. package/dist/use-as-locale-C4z5stwD.cjs +34 -0
  181. package/dist/use-as-nested-sections-store-jdMRxjBE.cjs +80 -0
  182. package/dist/use-as-nested-sections-store-lhi0z5z1.mjs +63 -0
  183. package/dist/use-as-optional-add-flow-CuXEir_i.mjs +43 -0
  184. package/dist/use-as-optional-add-flow-STOaQWo9.cjs +48 -0
  185. package/dist/use-as-value-help-CBykDEjZ.mjs +89 -0
  186. package/dist/use-as-value-help-uANI3zWa.cjs +100 -0
  187. package/dist/use-form-context-Dwr8Ai1v.cjs +207 -0
  188. package/dist/use-form-context-bAj7UoSe.mjs +106 -0
  189. package/package.json +180 -0
  190. package/styles.d.ts +2 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,105 @@
1
+ import { m as PATH_PREFIX_KEY, n as useAsUnionVariant, s as DISMISS_EXTERNAL_AT_KEY, t as formatIndexedLabelParts } from "./use-form-context-bAj7UoSe.mjs";
2
+ import { n as provideAsNestedSectionsStore, r as useAsNestedSectionsStore } from "./use-as-nested-sections-store-lhi0z5z1.mjs";
3
+ import { n as useAsValueHelp } from "./use-as-value-help-CBykDEjZ.mjs";
4
+ import { i as useAsExternalErrors, n as useAsForm, r as useAsState, t as as_form_default } from "./as-form-CWwgyvfw.mjs";
5
+ import { n as useAsData, r as useAsField, t as as_field_default } from "./as-field-CXVjrEPQ.mjs";
6
+ import { n as useAsLocale, t as provideAsLocale } from "./use-as-locale-BrFdAgnU.mjs";
7
+ import { t as as_iterator_default } from "./as-iterator-CT5y1jyn.mjs";
8
+ import { i as useAsFocusFirstAfter, n as focusFirstAfter, r as focusNewFocusableAfter, t as useAsDropdown } from "./use-as-dropdown-BMnEm6jF.mjs";
9
+ import { t as as_field_shell_default } from "./as-field-shell-Pdy3sAvr.mjs";
10
+ import "./as-variant-picker-BVs0AvjK.mjs";
11
+ import "./as-input-control-BzELjheN.mjs";
12
+ import "./as-adornment-shell-knFiB7Ct.mjs";
13
+ import { t as as_input_default } from "./as-input-DIa8BzLv.mjs";
14
+ import { t as as_select_default } from "./as-select-UBGCVhku.mjs";
15
+ import { t as as_radio_default } from "./as-radio-B1N-gmoI.mjs";
16
+ import { n as useAsTriStateCheckbox, t as as_checkbox_default } from "./as-checkbox-B_9mwla6.mjs";
17
+ import { t as as_paragraph_default } from "./as-paragraph-jIG_dg7_.mjs";
18
+ import { t as as_action_default } from "./as-action-DU17rykn.mjs";
19
+ import { t as useAsOptionalAddFlow } from "./use-as-optional-add-flow-CuXEir_i.mjs";
20
+ import "./as-collapsible-DtNCofNT.mjs";
21
+ import { t as as_object_default } from "./as-object-CT6lNEqt.mjs";
22
+ import { n as useAsArray, t as as_array_default } from "./as-array-DwarTaKP.mjs";
23
+ import "./as-array-clear-btn-DIhzCKC9.mjs";
24
+ import { n as useAsTypeMap, r as useAsUnion, t as as_union_default } from "./as-union-BGvdxr3G.mjs";
25
+ import { n as useAsTuple, t as as_tuple_default } from "./as-tuple-DkI9swlW.mjs";
26
+ import { t as as_ref_default } from "./as-ref-CIifSSCQ.mjs";
27
+ import { n as useAsDualInput, r as useAsDecimal, t as as_decimal_default } from "./as-decimal-DtXjFPhe.mjs";
28
+ import { n as useAsNumber, t as as_number_default } from "./as-number-JPEwPK8Q.mjs";
29
+ import { t as useAsDate } from "./use-as-date-C39i9mzE.mjs";
30
+ import { t as as_date_default } from "./as-date-C7tFQDkh.mjs";
31
+ import { t as as_datetime_default } from "./as-datetime-elcOoDT5.mjs";
32
+ import { t as as_time_default } from "./as-time-CQsxUs8P.mjs";
33
+ import { computed, inject, reactive } from "vue";
34
+ import { createFormData, createFormDef, createFormValueResolver, getDefaultClientFactory, resetDefaultClientFactory, setDefaultClientFactory } from "@atscript/ui";
35
+ //#region src/composables/create-as-form-def.ts
36
+ /**
37
+ * Creates a reactive form definition and data object from an ATScript annotated type.
38
+ *
39
+ * @param type - An ATScript annotated type (imported from a `.as` file).
40
+ * @param context - Optional context object forwarded to `ui.fn.value` resolvers during data creation.
41
+ * Only effective when `@atscript/ui-fns` is installed (dynamic resolver).
42
+ * @returns `{ def, formData }` — the FormDef and a Vue reactive data object with defaults applied
43
+ */
44
+ function createAsFormDef(type, context) {
45
+ return {
46
+ def: createFormDef(type),
47
+ formData: reactive(createFormData(type, context ? createFormValueResolver({}, context) : void 0))
48
+ };
49
+ }
50
+ //#endregion
51
+ //#region src/composables/create-default-types.ts
52
+ /**
53
+ * Returns a fresh type-to-component map pre-filled with all built-in defaults.
54
+ *
55
+ * Spread or assign additional entries to extend with custom field types:
56
+ * ```ts
57
+ * const types = { ...createDefaultTypes(), rating: MyRatingComponent }
58
+ * ```
59
+ */
60
+ function createDefaultTypes() {
61
+ return {
62
+ text: as_input_default,
63
+ textarea: as_input_default,
64
+ password: as_input_default,
65
+ number: as_number_default,
66
+ decimal: as_decimal_default,
67
+ select: as_select_default,
68
+ radio: as_radio_default,
69
+ checkbox: as_checkbox_default,
70
+ paragraph: as_paragraph_default,
71
+ action: as_action_default,
72
+ object: as_object_default,
73
+ array: as_array_default,
74
+ union: as_union_default,
75
+ tuple: as_tuple_default,
76
+ ref: as_ref_default,
77
+ date: as_date_default,
78
+ datetime: as_datetime_default,
79
+ time: as_time_default
80
+ };
81
+ }
82
+ //#endregion
83
+ //#region src/composables/use-as-path.ts
84
+ const EMPTY_PATH = computed(() => "");
85
+ /**
86
+ * Reactive read-only access to the absolute dotted path prefix at the
87
+ * current point in the `<AsForm>` tree. Returns `''` when called outside
88
+ * a form.
89
+ */
90
+ function useAsPath() {
91
+ return { path: inject(PATH_PREFIX_KEY, EMPTY_PATH) };
92
+ }
93
+ //#endregion
94
+ //#region src/composables/use-as-error-dismiss.ts
95
+ const NOOP = () => {};
96
+ /**
97
+ * Returns the `dismissExternalAt` callback provided by the nearest
98
+ * ancestor `<AsForm>`. Outside a form the result is a no-op so calling
99
+ * it from a leaf component does not throw.
100
+ */
101
+ function useAsErrorDismiss() {
102
+ return inject(DISMISS_EXTERNAL_AT_KEY, null) ?? NOOP;
103
+ }
104
+ //#endregion
105
+ export { as_action_default as AsAction, as_array_default as AsArray, as_checkbox_default as AsCheckbox, as_date_default as AsDate, as_datetime_default as AsDatetime, as_decimal_default as AsDecimal, as_field_default as AsField, as_field_shell_default as AsFieldShell, as_form_default as AsForm, as_input_default as AsInput, as_iterator_default as AsIterator, as_number_default as AsNumber, as_object_default as AsObject, as_paragraph_default as AsParagraph, as_radio_default as AsRadio, as_ref_default as AsRef, as_select_default as AsSelect, as_time_default as AsTime, as_tuple_default as AsTuple, as_union_default as AsUnion, createAsFormDef, createDefaultTypes, focusFirstAfter, focusNewFocusableAfter, formatIndexedLabelParts, getDefaultClientFactory, provideAsLocale, provideAsNestedSectionsStore, resetDefaultClientFactory, setDefaultClientFactory, useAsArray, useAsData, useAsDate, useAsDecimal, useAsDropdown, useAsDualInput, useAsErrorDismiss, useAsExternalErrors, useAsField, useAsFocusFirstAfter, useAsForm, useAsLocale, useAsNestedSectionsStore, useAsNumber, useAsOptionalAddFlow, useAsPath, useAsState, useAsTriStateCheckbox, useAsTuple, useAsTypeMap, useAsUnion, useAsUnionVariant, useAsValueHelp };
@@ -0,0 +1,233 @@
1
+ import { Component, Ref } from "vue";
2
+ import { FormFieldDef, FormUnionVariant, TFormAction, TFormEntryOptions, ValueHelpInfo } from "@atscript/ui";
3
+
4
+ //#region src/components/types.d.ts
5
+ /**
6
+ * Shared base props available to all custom form components.
7
+ */
8
+ interface TAsBaseComponentProps {
9
+ /** Whether this component is disabled. */
10
+ disabled?: boolean;
11
+ /** Whether this component is hidden. */
12
+ hidden?: boolean;
13
+ }
14
+ /**
15
+ * Props contract for custom field components used with `AsForm` / `AsField`.
16
+ *
17
+ * Implement this interface in your UI components so that `AsField` can pass
18
+ * all resolved field state (value, label, validation errors, etc.) as props.
19
+ *
20
+ * @typeParam V - The field value type
21
+ * @typeParam TFormData - The full form data object type
22
+ * @typeParam TFormContext - The external context object type
23
+ */
24
+ interface TAsComponentProps<V = unknown> extends TAsBaseComponentProps {
25
+ /** Called on field blur — triggers validation. */
26
+ onBlur: () => void;
27
+ /** Validation error message for this field, if any. */
28
+ error?: string;
29
+ /** Reactive model wrapping the field value. Bind with `v-model="model.value"`. */
30
+ model: {
31
+ value: V;
32
+ };
33
+ /** Phantom field display value from `@meta.default` / `@ui.form.fn.value` (paragraphs, actions). `undefined` for data fields. */
34
+ value?: unknown;
35
+ /** Resolved field label from `@meta.label` or `@ui.form.fn.label`. */
36
+ label?: string;
37
+ /** Resolved field description from `@meta.description` or `@ui.form.fn.description`. */
38
+ description?: string;
39
+ /** Resolved hint text from `@ui.form.hint` or `@ui.form.fn.hint`. */
40
+ hint?: string;
41
+ /** Resolved placeholder from `@ui.form.placeholder` or `@ui.form.fn.placeholder`. */
42
+ placeholder?: string;
43
+ /** Resolved CSS class painting the prefix icon glyph from `@ui.form.prefix.icon`. Consumer manages safelist / preset coverage. Rendered as the leftmost adornment, before the `prefix` text. */
44
+ prefixIcon?: string;
45
+ /** Resolved CSS class painting the suffix icon glyph from `@ui.form.suffix.icon`. Consumer manages safelist / preset coverage. Rendered as the rightmost adornment, after the `suffix` text. */
46
+ suffixIcon?: string;
47
+ /** CSS class(es) from `@ui.form.classes` or `@ui.form.fn.classes`. */
48
+ class?: Record<string, boolean> | string;
49
+ /** Inline styles from `@ui.form.styles` or `@ui.form.fn.styles`. */
50
+ style?: Record<string, string> | string;
51
+ /** Whether the field is optional (not required). */
52
+ optional?: boolean | undefined;
53
+ /** Toggle an optional field on/off. `true` sets default value; `false` sets `undefined`. Only present when `optional` is true. */
54
+ onToggleOptional?: (enabled: boolean) => void;
55
+ /** Whether the field is required (inverse of optional). */
56
+ required?: boolean | undefined;
57
+ /** Whether the field is read-only. */
58
+ readonly?: boolean | undefined;
59
+ /** The resolved field input type (e.g., `'text'`, `'select'`, `'checkbox'`). */
60
+ type: string;
61
+ /** Form action from `@ui.form.action`. Contains the action id and display label. */
62
+ formAction?: TFormAction;
63
+ /** The field name (last segment of the dot-separated path). */
64
+ name?: string;
65
+ /** The full FormFieldDef for advanced use cases. */
66
+ field?: FormFieldDef;
67
+ /** Resolved options for select/radio/checkbox fields. */
68
+ options?: TFormEntryOptions[];
69
+ /** Max length constraint from `@expect.maxLength`. */
70
+ maxLength?: number;
71
+ /** Autocomplete hint from `@ui.form.autocomplete`. */
72
+ autocomplete?: string;
73
+ /** Resolved title from `@ui.form.fn.title` / `@meta.label` for structure/array fields. */
74
+ title?: string;
75
+ /** Nesting level for structure/array fields. Root structure is 0, each nested structure/array increments by 1. */
76
+ level?: number;
77
+ /** Callback to remove this item from its parent array. Present when rendered inside an array. */
78
+ onRemove?: () => void;
79
+ /** Whether removal is allowed (respects minLength constraints). */
80
+ canRemove?: boolean;
81
+ /** Label for the remove button (from `@ui.array.remove.label`). */
82
+ removeLabel?: string;
83
+ /** Zero-based index when rendered as a direct array item. `undefined` otherwise. */
84
+ arrayIndex?: number;
85
+ /** Absolute dotted path to this field inside the form data. Empty string at the root. */
86
+ path: string;
87
+ /** Resolved value-help descriptor for FK ref fields (`@db.rel.FK` → `@db.http.path`). */
88
+ valueHelp?: ValueHelpInfo;
89
+ /** Singular label for array fields (`@ui.form.label.singular`) — used in "Add <singular>" affordances. */
90
+ singularLabel?: string;
91
+ /** Stable input element id, suitable for `<label :for>`. Co-resolved with `errorId` / `descId` so a11y wiring is consistent. Always populated by AsField. */
92
+ inputId: string;
93
+ /** Stable id for the error/hint container. Pair with `aria-describedby` (already resolved as `ariaDescribedBy`). Always populated by AsField. */
94
+ errorId: string;
95
+ /** Stable id for the description container. Always populated by AsField. */
96
+ descId: string;
97
+ /** Pre-resolved `aria-describedby` target — `errorId` when error/hint is present, else `descId`, else `undefined`. */
98
+ ariaDescribedBy?: string;
99
+ /**
100
+ * Resolved currency code (post-sibling resolution).
101
+ *
102
+ * Resolution chain at AsField: `@db.amount.currency 'EUR'` literal →
103
+ * `@db.amount.currency.ref 'fieldName'` sibling-field read → `undefined`.
104
+ * Useful for tooltips/titles (e.g. hovering an AsDecimal shell shows
105
+ * "USD"). Note: when `prefix` is also resolved from currency, the
106
+ * `currencyCode` here is the symbolic identifier; `prefix` carries
107
+ * the locale-aware narrow symbol.
108
+ */
109
+ currencyCode?: string;
110
+ /**
111
+ * Resolved unit-of-measure code (post-sibling resolution).
112
+ *
113
+ * Resolution chain at AsField: `@db.unit 'kg'` literal →
114
+ * `@db.unit.ref 'fieldName'` sibling-field read → `undefined`. Useful
115
+ * for tooltips. Note: when `suffix` is also resolved from `@db.unit*`,
116
+ * `unitCode` and `suffix` carry the same string.
117
+ */
118
+ unitCode?: string;
119
+ /**
120
+ * Decimal scale storage cap (the DB column's fractional-digit limit) —
121
+ * raw second arg of `@db.column.precision precision, scale`. The
122
+ * composables pad outgoing strings to this; for display, use `scale`
123
+ * (which may be tighter due to currency natural digits).
124
+ */
125
+ precisionScale?: number;
126
+ /**
127
+ * Resolved input prefix adornment.
128
+ *
129
+ * Resolution chain at AsField: explicit `@ui.form.prefix 'value'` →
130
+ * `@ui.form.prefix.ref 'fieldName'` sibling-field read → currency
131
+ * symbol (locale-narrow form, when currency is resolved) → `undefined`.
132
+ * Applied by AsInput, AsNumber, AsDecimal.
133
+ */
134
+ prefix?: string;
135
+ /**
136
+ * Resolved input suffix adornment.
137
+ *
138
+ * Resolution chain at AsField: explicit `@ui.form.suffix 'value'` →
139
+ * `@ui.form.suffix.ref 'fieldName'` sibling-field read → unit code
140
+ * (resolved `unitCode`) → `undefined`. Applied by AsInput, AsNumber,
141
+ * AsDecimal.
142
+ */
143
+ suffix?: string;
144
+ /**
145
+ * Effective display scale (fractional digits) — composables enforce
146
+ * this when editing decimals.
147
+ *
148
+ * Resolution: `min(currencyDecimals, precisionScale)` when currency is
149
+ * resolved, else `currencyDecimals` (currency only), else
150
+ * `precisionScale` (DB only), else `undefined`. Smaller than
151
+ * `precisionScale` is fine — storage stays at the DB cap, display
152
+ * truncates to this.
153
+ */
154
+ scale?: number;
155
+ /**
156
+ * Whether AsField found at least one adornment-driving annotation on
157
+ * this field (`@db.amount.currency*`, `@db.unit*`, `@ui.form.prefix*`,
158
+ * `@ui.form.suffix*`). Used by AsNumber / AsDecimal to keep the
159
+ * merged-chrome shell visible even when a sibling-ref source is
160
+ * currently empty — without this flag, the shell would flicker as
161
+ * the user picks a source value.
162
+ *
163
+ * Always populated by AsField; defaults to `false` when no adornment
164
+ * annotation is present on the prop.
165
+ */
166
+ hasAdornment?: boolean;
167
+ }
168
+ /**
169
+ * Public emits contract for custom field components used with `AsForm` /
170
+ * `AsField`. Type your `defineEmits` against this interface so the
171
+ * action-button surface stays compatible with the framework.
172
+ *
173
+ * `_V` is reserved for forward-compat with value-typed emits in Phase 4
174
+ * (e.g. `(e: 'change-value', value: _V)`); the underscore prefix marks it
175
+ * as deliberately unused under both biome and eslint conventions.
176
+ *
177
+ * @typeParam _V - The field value type (reserved for future emits)
178
+ */
179
+ interface TAsComponentEmits<_V = unknown> {
180
+ /**
181
+ * Action invocation — emitted by phantom action buttons. The form
182
+ * routes the named action through its `@action` handler.
183
+ */
184
+ (e: "action", name: string): void;
185
+ }
186
+ /**
187
+ * Discriminated type for the `change` event emitted by `AsForm`.
188
+ *
189
+ * - `'update'` — leaf field value committed (blur)
190
+ * - `'array-add'` — array item added
191
+ * - `'array-remove'` — array item removed
192
+ * - `'union-switch'` — union variant switched
193
+ */
194
+ type TAsChangeType = "update" | "array-add" | "array-remove" | "union-switch";
195
+ /**
196
+ * Type-to-component map for `AsForm`. Lists all built-in field types as
197
+ * required keys and accepts additional custom types via index signature.
198
+ *
199
+ * Use {@link createDefaultTypes} to get a pre-built map with all defaults.
200
+ */
201
+ type TAsTypeComponents = {
202
+ text: Component;
203
+ select: Component;
204
+ radio: Component;
205
+ checkbox: Component;
206
+ paragraph: Component;
207
+ action: Component;
208
+ object: Component;
209
+ array: Component;
210
+ union: Component;
211
+ tuple: Component;
212
+ ref: Component;
213
+ decimal: Component;
214
+ number: Component;
215
+ date: Component;
216
+ datetime: Component;
217
+ time: Component;
218
+ } & Record<string, Component>;
219
+ /**
220
+ * Union context provided by `AsUnion` via `UNION_CONTEXT_KEY`.
221
+ * Consumed by `AsFieldShell` to render the variant picker inline with the
222
+ * item's own header.
223
+ */
224
+ interface TAsUnionContext {
225
+ /** All available union variant branches. */
226
+ variants: FormUnionVariant[];
227
+ /** Reactive index of the currently selected variant. */
228
+ currentIndex: Ref<number>;
229
+ /** Switch to a different variant (rewrites model data). */
230
+ changeVariant: (index: number) => void;
231
+ }
232
+ //#endregion
233
+ export { TAsTypeComponents as a, TAsComponentProps as i, TAsChangeType as n, TAsUnionContext as o, TAsComponentEmits as r, TAsBaseComponentProps as t };
@@ -0,0 +1,233 @@
1
+ import { Component, Ref } from "vue";
2
+ import { FormFieldDef, FormUnionVariant, TFormAction, TFormEntryOptions, ValueHelpInfo } from "@atscript/ui";
3
+
4
+ //#region src/components/types.d.ts
5
+ /**
6
+ * Shared base props available to all custom form components.
7
+ */
8
+ interface TAsBaseComponentProps {
9
+ /** Whether this component is disabled. */
10
+ disabled?: boolean;
11
+ /** Whether this component is hidden. */
12
+ hidden?: boolean;
13
+ }
14
+ /**
15
+ * Props contract for custom field components used with `AsForm` / `AsField`.
16
+ *
17
+ * Implement this interface in your UI components so that `AsField` can pass
18
+ * all resolved field state (value, label, validation errors, etc.) as props.
19
+ *
20
+ * @typeParam V - The field value type
21
+ * @typeParam TFormData - The full form data object type
22
+ * @typeParam TFormContext - The external context object type
23
+ */
24
+ interface TAsComponentProps<V = unknown> extends TAsBaseComponentProps {
25
+ /** Called on field blur — triggers validation. */
26
+ onBlur: () => void;
27
+ /** Validation error message for this field, if any. */
28
+ error?: string;
29
+ /** Reactive model wrapping the field value. Bind with `v-model="model.value"`. */
30
+ model: {
31
+ value: V;
32
+ };
33
+ /** Phantom field display value from `@meta.default` / `@ui.form.fn.value` (paragraphs, actions). `undefined` for data fields. */
34
+ value?: unknown;
35
+ /** Resolved field label from `@meta.label` or `@ui.form.fn.label`. */
36
+ label?: string;
37
+ /** Resolved field description from `@meta.description` or `@ui.form.fn.description`. */
38
+ description?: string;
39
+ /** Resolved hint text from `@ui.form.hint` or `@ui.form.fn.hint`. */
40
+ hint?: string;
41
+ /** Resolved placeholder from `@ui.form.placeholder` or `@ui.form.fn.placeholder`. */
42
+ placeholder?: string;
43
+ /** Resolved CSS class painting the prefix icon glyph from `@ui.form.prefix.icon`. Consumer manages safelist / preset coverage. Rendered as the leftmost adornment, before the `prefix` text. */
44
+ prefixIcon?: string;
45
+ /** Resolved CSS class painting the suffix icon glyph from `@ui.form.suffix.icon`. Consumer manages safelist / preset coverage. Rendered as the rightmost adornment, after the `suffix` text. */
46
+ suffixIcon?: string;
47
+ /** CSS class(es) from `@ui.form.classes` or `@ui.form.fn.classes`. */
48
+ class?: Record<string, boolean> | string;
49
+ /** Inline styles from `@ui.form.styles` or `@ui.form.fn.styles`. */
50
+ style?: Record<string, string> | string;
51
+ /** Whether the field is optional (not required). */
52
+ optional?: boolean | undefined;
53
+ /** Toggle an optional field on/off. `true` sets default value; `false` sets `undefined`. Only present when `optional` is true. */
54
+ onToggleOptional?: (enabled: boolean) => void;
55
+ /** Whether the field is required (inverse of optional). */
56
+ required?: boolean | undefined;
57
+ /** Whether the field is read-only. */
58
+ readonly?: boolean | undefined;
59
+ /** The resolved field input type (e.g., `'text'`, `'select'`, `'checkbox'`). */
60
+ type: string;
61
+ /** Form action from `@ui.form.action`. Contains the action id and display label. */
62
+ formAction?: TFormAction;
63
+ /** The field name (last segment of the dot-separated path). */
64
+ name?: string;
65
+ /** The full FormFieldDef for advanced use cases. */
66
+ field?: FormFieldDef;
67
+ /** Resolved options for select/radio/checkbox fields. */
68
+ options?: TFormEntryOptions[];
69
+ /** Max length constraint from `@expect.maxLength`. */
70
+ maxLength?: number;
71
+ /** Autocomplete hint from `@ui.form.autocomplete`. */
72
+ autocomplete?: string;
73
+ /** Resolved title from `@ui.form.fn.title` / `@meta.label` for structure/array fields. */
74
+ title?: string;
75
+ /** Nesting level for structure/array fields. Root structure is 0, each nested structure/array increments by 1. */
76
+ level?: number;
77
+ /** Callback to remove this item from its parent array. Present when rendered inside an array. */
78
+ onRemove?: () => void;
79
+ /** Whether removal is allowed (respects minLength constraints). */
80
+ canRemove?: boolean;
81
+ /** Label for the remove button (from `@ui.array.remove.label`). */
82
+ removeLabel?: string;
83
+ /** Zero-based index when rendered as a direct array item. `undefined` otherwise. */
84
+ arrayIndex?: number;
85
+ /** Absolute dotted path to this field inside the form data. Empty string at the root. */
86
+ path: string;
87
+ /** Resolved value-help descriptor for FK ref fields (`@db.rel.FK` → `@db.http.path`). */
88
+ valueHelp?: ValueHelpInfo;
89
+ /** Singular label for array fields (`@ui.form.label.singular`) — used in "Add <singular>" affordances. */
90
+ singularLabel?: string;
91
+ /** Stable input element id, suitable for `<label :for>`. Co-resolved with `errorId` / `descId` so a11y wiring is consistent. Always populated by AsField. */
92
+ inputId: string;
93
+ /** Stable id for the error/hint container. Pair with `aria-describedby` (already resolved as `ariaDescribedBy`). Always populated by AsField. */
94
+ errorId: string;
95
+ /** Stable id for the description container. Always populated by AsField. */
96
+ descId: string;
97
+ /** Pre-resolved `aria-describedby` target — `errorId` when error/hint is present, else `descId`, else `undefined`. */
98
+ ariaDescribedBy?: string;
99
+ /**
100
+ * Resolved currency code (post-sibling resolution).
101
+ *
102
+ * Resolution chain at AsField: `@db.amount.currency 'EUR'` literal →
103
+ * `@db.amount.currency.ref 'fieldName'` sibling-field read → `undefined`.
104
+ * Useful for tooltips/titles (e.g. hovering an AsDecimal shell shows
105
+ * "USD"). Note: when `prefix` is also resolved from currency, the
106
+ * `currencyCode` here is the symbolic identifier; `prefix` carries
107
+ * the locale-aware narrow symbol.
108
+ */
109
+ currencyCode?: string;
110
+ /**
111
+ * Resolved unit-of-measure code (post-sibling resolution).
112
+ *
113
+ * Resolution chain at AsField: `@db.unit 'kg'` literal →
114
+ * `@db.unit.ref 'fieldName'` sibling-field read → `undefined`. Useful
115
+ * for tooltips. Note: when `suffix` is also resolved from `@db.unit*`,
116
+ * `unitCode` and `suffix` carry the same string.
117
+ */
118
+ unitCode?: string;
119
+ /**
120
+ * Decimal scale storage cap (the DB column's fractional-digit limit) —
121
+ * raw second arg of `@db.column.precision precision, scale`. The
122
+ * composables pad outgoing strings to this; for display, use `scale`
123
+ * (which may be tighter due to currency natural digits).
124
+ */
125
+ precisionScale?: number;
126
+ /**
127
+ * Resolved input prefix adornment.
128
+ *
129
+ * Resolution chain at AsField: explicit `@ui.form.prefix 'value'` →
130
+ * `@ui.form.prefix.ref 'fieldName'` sibling-field read → currency
131
+ * symbol (locale-narrow form, when currency is resolved) → `undefined`.
132
+ * Applied by AsInput, AsNumber, AsDecimal.
133
+ */
134
+ prefix?: string;
135
+ /**
136
+ * Resolved input suffix adornment.
137
+ *
138
+ * Resolution chain at AsField: explicit `@ui.form.suffix 'value'` →
139
+ * `@ui.form.suffix.ref 'fieldName'` sibling-field read → unit code
140
+ * (resolved `unitCode`) → `undefined`. Applied by AsInput, AsNumber,
141
+ * AsDecimal.
142
+ */
143
+ suffix?: string;
144
+ /**
145
+ * Effective display scale (fractional digits) — composables enforce
146
+ * this when editing decimals.
147
+ *
148
+ * Resolution: `min(currencyDecimals, precisionScale)` when currency is
149
+ * resolved, else `currencyDecimals` (currency only), else
150
+ * `precisionScale` (DB only), else `undefined`. Smaller than
151
+ * `precisionScale` is fine — storage stays at the DB cap, display
152
+ * truncates to this.
153
+ */
154
+ scale?: number;
155
+ /**
156
+ * Whether AsField found at least one adornment-driving annotation on
157
+ * this field (`@db.amount.currency*`, `@db.unit*`, `@ui.form.prefix*`,
158
+ * `@ui.form.suffix*`). Used by AsNumber / AsDecimal to keep the
159
+ * merged-chrome shell visible even when a sibling-ref source is
160
+ * currently empty — without this flag, the shell would flicker as
161
+ * the user picks a source value.
162
+ *
163
+ * Always populated by AsField; defaults to `false` when no adornment
164
+ * annotation is present on the prop.
165
+ */
166
+ hasAdornment?: boolean;
167
+ }
168
+ /**
169
+ * Public emits contract for custom field components used with `AsForm` /
170
+ * `AsField`. Type your `defineEmits` against this interface so the
171
+ * action-button surface stays compatible with the framework.
172
+ *
173
+ * `_V` is reserved for forward-compat with value-typed emits in Phase 4
174
+ * (e.g. `(e: 'change-value', value: _V)`); the underscore prefix marks it
175
+ * as deliberately unused under both biome and eslint conventions.
176
+ *
177
+ * @typeParam _V - The field value type (reserved for future emits)
178
+ */
179
+ interface TAsComponentEmits<_V = unknown> {
180
+ /**
181
+ * Action invocation — emitted by phantom action buttons. The form
182
+ * routes the named action through its `@action` handler.
183
+ */
184
+ (e: "action", name: string): void;
185
+ }
186
+ /**
187
+ * Discriminated type for the `change` event emitted by `AsForm`.
188
+ *
189
+ * - `'update'` — leaf field value committed (blur)
190
+ * - `'array-add'` — array item added
191
+ * - `'array-remove'` — array item removed
192
+ * - `'union-switch'` — union variant switched
193
+ */
194
+ type TAsChangeType = "update" | "array-add" | "array-remove" | "union-switch";
195
+ /**
196
+ * Type-to-component map for `AsForm`. Lists all built-in field types as
197
+ * required keys and accepts additional custom types via index signature.
198
+ *
199
+ * Use {@link createDefaultTypes} to get a pre-built map with all defaults.
200
+ */
201
+ type TAsTypeComponents = {
202
+ text: Component;
203
+ select: Component;
204
+ radio: Component;
205
+ checkbox: Component;
206
+ paragraph: Component;
207
+ action: Component;
208
+ object: Component;
209
+ array: Component;
210
+ union: Component;
211
+ tuple: Component;
212
+ ref: Component;
213
+ decimal: Component;
214
+ number: Component;
215
+ date: Component;
216
+ datetime: Component;
217
+ time: Component;
218
+ } & Record<string, Component>;
219
+ /**
220
+ * Union context provided by `AsUnion` via `UNION_CONTEXT_KEY`.
221
+ * Consumed by `AsFieldShell` to render the variant picker inline with the
222
+ * item's own header.
223
+ */
224
+ interface TAsUnionContext {
225
+ /** All available union variant branches. */
226
+ variants: FormUnionVariant[];
227
+ /** Reactive index of the currently selected variant. */
228
+ currentIndex: Ref<number>;
229
+ /** Switch to a different variant (rewrites model data). */
230
+ changeVariant: (index: number) => void;
231
+ }
232
+ //#endregion
233
+ export { TAsTypeComponents as a, TAsComponentProps as i, TAsChangeType as n, TAsUnionContext as o, TAsComponentEmits as r, TAsBaseComponentProps as t };