@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
@@ -0,0 +1,448 @@
1
+ const require_use_form_context = require("./use-form-context-Dwr8Ai1v.cjs");
2
+ const require_use_as_nested_sections_store = require("./use-as-nested-sections-store-jdMRxjBE.cjs");
3
+ const require_use_as_value_help = require("./use-as-value-help-uANI3zWa.cjs");
4
+ const require_as_field = require("./as-field-wLYoaZnT.cjs");
5
+ let vue = require("vue");
6
+ let _atscript_ui = require("@atscript/ui");
7
+ //#region src/composables/use-as-external-errors.ts
8
+ /**
9
+ * Local dismissal state for externally-supplied errors.
10
+ *
11
+ * - `dismissAt(path)` hides a leaf error until either the user un-dismisses
12
+ * it or a *fresh* errors object arrives (new identity).
13
+ * - `dismissForm()` hides the `__form` banner. Same identity-reset rule, but
14
+ * never cleared by leaf calls.
15
+ * - In-place mutation of the source object does NOT reset dismissals; only
16
+ * identity changes do. A fresh response (`errors.value = { ... }`) re-arms
17
+ * everything, while in-place tweaks (rare) deliberately preserve them.
18
+ *
19
+ * The composable is pure — it does NOT call `provide()`. The owning form
20
+ * composable wires `dismissAt` into the form's inject contract.
21
+ */
22
+ function useAsExternalErrors(options) {
23
+ const dismissedPaths = (0, vue.ref)(/* @__PURE__ */ new Set());
24
+ const formDismissed = (0, vue.ref)(false);
25
+ function reset() {
26
+ if (dismissedPaths.value.size > 0) dismissedPaths.value = /* @__PURE__ */ new Set();
27
+ if (formDismissed.value) formDismissed.value = false;
28
+ }
29
+ (0, vue.watch)(() => options.source(), reset);
30
+ const effective = (0, vue.computed)(() => {
31
+ const errs = options.source();
32
+ if (!errs) return void 0;
33
+ const dismissed = dismissedPaths.value;
34
+ if (dismissed.size === 0 && errs.__form === void 0) return errs;
35
+ const out = {};
36
+ for (const k in errs) {
37
+ if (k === "__form") continue;
38
+ if (dismissed.has(k)) continue;
39
+ out[k] = errs[k];
40
+ }
41
+ return out;
42
+ });
43
+ const formError = (0, vue.computed)(() => {
44
+ if (formDismissed.value) return void 0;
45
+ return options.source()?.__form;
46
+ });
47
+ const isFormDismissed = (0, vue.computed)(() => formDismissed.value);
48
+ function dismissAt(path) {
49
+ if (!path) return;
50
+ if (dismissedPaths.value.has(path)) return;
51
+ const next = new Set(dismissedPaths.value);
52
+ next.add(path);
53
+ dismissedPaths.value = next;
54
+ }
55
+ function dismissForm() {
56
+ if (!formDismissed.value) formDismissed.value = true;
57
+ }
58
+ return {
59
+ effective,
60
+ formError,
61
+ isFormDismissed,
62
+ dismissAt,
63
+ dismissForm,
64
+ reset
65
+ };
66
+ }
67
+ //#endregion
68
+ //#region src/composables/use-as-state.ts
69
+ function useAsState(opts) {
70
+ const fieldsById = /* @__PURE__ */ new Map();
71
+ const register = (id, registration) => {
72
+ fieldsById.set(id, registration);
73
+ if (formState.firstSubmitHappened) formState.freshFields.add(id);
74
+ };
75
+ const unregister = (id) => {
76
+ fieldsById.delete(id);
77
+ formState.freshFields.delete(id);
78
+ };
79
+ const formState = (0, vue.reactive)({
80
+ firstSubmitHappened: false,
81
+ firstValidation: (0, vue.toValue)(opts.firstValidation) ?? "on-change",
82
+ freshFields: /* @__PURE__ */ new Set(),
83
+ register,
84
+ unregister
85
+ });
86
+ (0, vue.watchEffect)(() => {
87
+ const v = (0, vue.toValue)(opts.firstValidation) ?? "on-change";
88
+ if (formState.firstValidation !== v) formState.firstValidation = v;
89
+ });
90
+ (0, vue.provide)(require_use_form_context.FORM_STATE_KEY, formState);
91
+ (0, vue.provide)(require_use_form_context.FORM_DATA_KEY, (0, vue.computed)(() => (0, vue.toValue)(opts.formData)));
92
+ (0, vue.provide)(require_use_form_context.FORM_CONTEXT_KEY, (0, vue.computed)(() => opts.formContext ? (0, vue.toValue)(opts.formContext) : void 0));
93
+ function clearErrors() {
94
+ formState.firstSubmitHappened = false;
95
+ formState.freshFields.clear();
96
+ for (const reg of fieldsById.values()) reg.callbacks.clearErrors();
97
+ }
98
+ async function reset() {
99
+ for (const reg of fieldsById.values()) reg.callbacks.reset();
100
+ await (0, vue.nextTick)();
101
+ clearErrors();
102
+ }
103
+ function submit() {
104
+ formState.firstSubmitHappened = true;
105
+ formState.freshFields.clear();
106
+ if (formState.firstValidation === "none") return true;
107
+ if (opts.submitValidator) {
108
+ const errors = opts.submitValidator();
109
+ const entries = Object.entries(errors);
110
+ if (entries.length === 0) return true;
111
+ setErrors(errors);
112
+ return entries.map(([path, message]) => ({
113
+ path,
114
+ message
115
+ }));
116
+ }
117
+ const errors = [];
118
+ for (const reg of fieldsById.values()) {
119
+ const result = reg.callbacks.validate();
120
+ if (result !== true) {
121
+ const path = reg.path();
122
+ errors.push({
123
+ path,
124
+ message: result
125
+ });
126
+ }
127
+ }
128
+ return errors.length > 0 ? errors : true;
129
+ }
130
+ function setErrors(errors) {
131
+ for (const reg of fieldsById.values()) {
132
+ const p = reg.path();
133
+ reg.callbacks.setExternalError(errors[p]);
134
+ }
135
+ }
136
+ return {
137
+ clearErrors,
138
+ reset,
139
+ submit,
140
+ setErrors,
141
+ formState
142
+ };
143
+ }
144
+ //#endregion
145
+ //#region src/composables/use-as-form.ts
146
+ /**
147
+ * Composable backing `<AsForm>`. Owns the entire form state machine —
148
+ * data container, internal validator, external-error dismissal, action
149
+ * routing, change merging, descendant counts, auto-open, and all
150
+ * provide/inject wiring. Customers building a custom form root can
151
+ * call this directly and render their own `<form>` template.
152
+ *
153
+ * MUST be called from a component's `<script setup>` (it issues
154
+ * `provide()` calls that need an active component instance).
155
+ */
156
+ function useAsForm(options) {
157
+ const _data = (0, vue.ref)({});
158
+ const data = (0, vue.computed)(() => {
159
+ return options.formData?.() ?? _data.value;
160
+ });
161
+ /**
162
+ * Unwraps domain data from the form data container. Form data is
163
+ * `{ value: domainData }` — getByPath/setByPath handle this wrapper
164
+ * automatically, but scope/validator callers need the inner value.
165
+ */
166
+ function getDomainData() {
167
+ return data.value.value;
168
+ }
169
+ const domainData = () => (0, vue.toRaw)(getDomainData());
170
+ const formContext = (0, vue.computed)(() => options.formContext?.());
171
+ const formValidator = (0, vue.computed)(() => (0, _atscript_ui.getFormValidator)(options.def(), { errorLimit: Number.MAX_SAFE_INTEGER }));
172
+ const { clearErrors, reset: resetState, submit, setErrors } = useAsState({
173
+ formData: data,
174
+ formContext,
175
+ firstValidation: (0, vue.computed)(() => options.firstValidation?.()),
176
+ submitValidator: () => formValidator.value({
177
+ data: getDomainData(),
178
+ context: formContext.value ?? {}
179
+ })
180
+ });
181
+ (0, vue.provide)(require_use_form_context.ROOT_DATA_KEY, data);
182
+ (0, vue.provide)(require_use_form_context.PATH_PREFIX_KEY, (0, vue.computed)(() => ""));
183
+ (0, vue.provide)(require_use_form_context.TYPES_KEY, (0, vue.computed)(() => options.types()));
184
+ (0, vue.provide)(require_use_form_context.COMPONENTS_KEY, (0, vue.computed)(() => options.components?.()));
185
+ (0, vue.provide)(require_use_form_context.HIDE_ROOT_TITLE_KEY, options.hideRootTitle?.() === true);
186
+ const ext = useAsExternalErrors({ source: () => options.errors?.() });
187
+ (0, vue.provide)(require_use_form_context.ERRORS_KEY, ext.effective);
188
+ (0, vue.provide)(require_use_form_context.DISMISS_EXTERNAL_AT_KEY, ext.dismissAt);
189
+ const sectionsStore = require_use_as_nested_sections_store.useAsNestedSectionsStore() ?? require_use_as_nested_sections_store.provideAsNestedSectionsStore();
190
+ const cf = options.clientFactory?.();
191
+ if (cf) (0, vue.provide)(require_use_as_value_help.CLIENT_FACTORY_KEY, cf);
192
+ const internalErrors = (0, vue.ref)({});
193
+ const allErrors = (0, vue.computed)(() => (0, _atscript_ui.mergeErrorMaps)(ext.effective.value, internalErrors.value));
194
+ (0, vue.provide)(require_use_as_nested_sections_store.DESCENDANT_ERROR_COUNTS_KEY, (0, vue.computed)(() => (0, _atscript_ui.buildDescendantErrorCounts)(allErrors.value)));
195
+ (0, vue.watch)(allErrors, (errors) => {
196
+ for (const errPath of Object.keys(errors)) for (const ancestor of (0, _atscript_ui.iteratePathAncestors)(errPath)) sectionsStore.setOpen(ancestor, true);
197
+ }, {
198
+ immediate: true,
199
+ flush: "post"
200
+ });
201
+ const ctx = (0, vue.computed)(() => ({
202
+ v: void 0,
203
+ data: getDomainData(),
204
+ context: formContext.value ?? {},
205
+ entry: void 0
206
+ }));
207
+ const submitText = (0, vue.computed)(() => (0, _atscript_ui.resolveFormProp)(options.def().type, _atscript_ui.UI_FORM_FN_SUBMIT_TEXT, _atscript_ui.UI_FORM_SUBMIT_TEXT, ctx.value) ?? "Submit");
208
+ const submitDisabled = (0, vue.computed)(() => (0, _atscript_ui.resolveFormProp)(options.def().type, _atscript_ui.UI_FORM_FN_SUBMIT_DISABLED, void 0, ctx.value) ?? false);
209
+ function supportsAction(def, actionId) {
210
+ return def.fields.some((f) => {
211
+ if ((0, _atscript_ui.getFieldMeta)(f.prop, _atscript_ui.UI_FORM_ACTION)?.id === actionId) return true;
212
+ return (0, _atscript_ui.getFieldMeta)(f.prop, _atscript_ui.WF_ACTION_WITH_DATA) === actionId;
213
+ });
214
+ }
215
+ function invokeAction(name) {
216
+ if (supportsAction(options.def(), name)) options.emits?.action?.(name, domainData());
217
+ else options.emits?.unsupportedAction?.(name, domainData());
218
+ }
219
+ (0, vue.provide)(require_use_form_context.ACTION_HANDLER_KEY, invokeAction);
220
+ function handleChange(type, path, value) {
221
+ ext.dismissAt(path);
222
+ const errors = internalErrors.value;
223
+ let stale = null;
224
+ let next = null;
225
+ for (const key in errors) {
226
+ if (!stale) stale = new Set((0, _atscript_ui.iteratePathAncestors)(path));
227
+ if (stale.has(key)) {
228
+ if (!next) next = { ...errors };
229
+ delete next[key];
230
+ }
231
+ }
232
+ if (next) {
233
+ internalErrors.value = next;
234
+ setErrors(next);
235
+ }
236
+ options.emits?.change?.(type, path, value, domainData());
237
+ }
238
+ (0, vue.provide)(require_use_form_context.CHANGE_HANDLER_KEY, handleChange);
239
+ function onSubmit() {
240
+ const result = submit();
241
+ if (result === true) {
242
+ internalErrors.value = {};
243
+ options.emits?.submit?.(domainData());
244
+ } else {
245
+ const errs = {};
246
+ for (const e of result) errs[e.path] = e.message;
247
+ internalErrors.value = errs;
248
+ options.emits?.error?.(result);
249
+ }
250
+ }
251
+ return {
252
+ data,
253
+ errors: ext.effective,
254
+ formError: ext.formError,
255
+ internalErrors,
256
+ reset: resetState,
257
+ clearErrors,
258
+ setErrors,
259
+ onSubmit,
260
+ submitText,
261
+ submitDisabled,
262
+ invokeAction,
263
+ dismissError: ext.dismissAt,
264
+ dismissFormError: ext.dismissForm,
265
+ formContext,
266
+ handleChange
267
+ };
268
+ }
269
+ //#endregion
270
+ //#region src/components/as-form.vue?vue&type=script&setup=true&lang.ts
271
+ const _hoisted_1 = ["inert"];
272
+ const _hoisted_2 = {
273
+ role: "alert",
274
+ class: "as-form-error"
275
+ };
276
+ const _hoisted_3 = { class: "as-form-error-message" };
277
+ const _hoisted_4 = ["disabled"];
278
+ const _hoisted_5 = {
279
+ key: 2,
280
+ class: "as-form-overlay"
281
+ };
282
+ //#endregion
283
+ //#region src/components/as-form.vue
284
+ var as_form_default = /* @__PURE__ */ (0, vue.defineComponent)({
285
+ __name: "as-form",
286
+ props: {
287
+ def: {
288
+ type: Object,
289
+ required: true
290
+ },
291
+ formData: {
292
+ type: null,
293
+ required: false
294
+ },
295
+ formContext: {
296
+ type: null,
297
+ required: false
298
+ },
299
+ firstValidation: {
300
+ type: String,
301
+ required: false
302
+ },
303
+ components: {
304
+ type: Object,
305
+ required: false
306
+ },
307
+ types: {
308
+ type: Object,
309
+ required: true
310
+ },
311
+ errors: {
312
+ type: Object,
313
+ required: false
314
+ },
315
+ clientFactory: {
316
+ type: Function,
317
+ required: false
318
+ },
319
+ hideRootTitle: {
320
+ type: Boolean,
321
+ required: false
322
+ },
323
+ hideSubmit: {
324
+ type: Boolean,
325
+ required: false
326
+ },
327
+ loading: {
328
+ type: Boolean,
329
+ required: false
330
+ }
331
+ },
332
+ emits: [
333
+ "submit",
334
+ "error",
335
+ "action",
336
+ "unsupported-action",
337
+ "change"
338
+ ],
339
+ setup(__props, { emit: __emit }) {
340
+ const props = __props;
341
+ const emit = __emit;
342
+ const form = useAsForm({
343
+ def: () => props.def,
344
+ formData: () => props.formData,
345
+ formContext: () => props.formContext,
346
+ firstValidation: () => props.firstValidation,
347
+ components: () => props.components,
348
+ types: () => props.types,
349
+ errors: () => props.errors,
350
+ clientFactory: () => props.clientFactory,
351
+ hideRootTitle: () => props.hideRootTitle,
352
+ emits: {
353
+ submit: (data) => emit("submit", data),
354
+ error: (errors) => emit("error", errors),
355
+ action: (name, data) => emit("action", name, data),
356
+ unsupportedAction: (name, data) => emit("unsupported-action", name, data),
357
+ change: (type, path, value, formData) => emit("change", type, path, value, formData)
358
+ }
359
+ });
360
+ return (_ctx, _cache) => {
361
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("form", {
362
+ class: "as-form",
363
+ inert: __props.loading,
364
+ onSubmit: _cache[1] || (_cache[1] = (0, vue.withModifiers)((...args) => (0, vue.unref)(form).onSubmit && (0, vue.unref)(form).onSubmit(...args), ["prevent"]))
365
+ }, [
366
+ (0, vue.renderSlot)(_ctx.$slots, "form.header", {
367
+ clearErrors: (0, vue.unref)(form).clearErrors,
368
+ reset: (0, vue.unref)(form).reset,
369
+ setErrors: (0, vue.unref)(form).setErrors,
370
+ formContext: __props.formContext,
371
+ disabled: (0, vue.unref)(form).submitDisabled.value
372
+ }),
373
+ (0, vue.renderSlot)(_ctx.$slots, "form.before", {
374
+ clearErrors: (0, vue.unref)(form).clearErrors,
375
+ reset: (0, vue.unref)(form).reset,
376
+ setErrors: (0, vue.unref)(form).setErrors,
377
+ formContext: __props.formContext,
378
+ disabled: (0, vue.unref)(form).submitDisabled.value
379
+ }),
380
+ (0, vue.createVNode)(require_as_field.as_field_default, { field: __props.def.rootField }, null, 8, ["field"]),
381
+ (0, vue.renderSlot)(_ctx.$slots, "form.after", {
382
+ clearErrors: (0, vue.unref)(form).clearErrors,
383
+ reset: (0, vue.unref)(form).reset,
384
+ setErrors: (0, vue.unref)(form).setErrors,
385
+ disabled: (0, vue.unref)(form).submitDisabled.value,
386
+ formContext: __props.formContext
387
+ }),
388
+ (0, vue.unref)(form).formError.value ? (0, vue.renderSlot)(_ctx.$slots, "form.error", {
389
+ key: 0,
390
+ message: (0, vue.unref)(form).formError.value,
391
+ dismiss: (0, vue.unref)(form).dismissFormError
392
+ }, () => [(0, vue.createElementVNode)("div", _hoisted_2, [(0, vue.createElementVNode)("span", _hoisted_3, (0, vue.toDisplayString)((0, vue.unref)(form).formError.value), 1), (0, vue.createElementVNode)("button", {
393
+ type: "button",
394
+ class: "as-form-error-dismiss",
395
+ onClick: _cache[0] || (_cache[0] = (...args) => (0, vue.unref)(form).dismissFormError && (0, vue.unref)(form).dismissFormError(...args))
396
+ }, " Dismiss ")])]) : (0, vue.createCommentVNode)("v-if", true),
397
+ !__props.hideSubmit ? (0, vue.renderSlot)(_ctx.$slots, "form.submit", {
398
+ key: 1,
399
+ disabled: (0, vue.unref)(form).submitDisabled.value,
400
+ text: (0, vue.unref)(form).submitText.value,
401
+ clearErrors: (0, vue.unref)(form).clearErrors,
402
+ reset: (0, vue.unref)(form).reset,
403
+ setErrors: (0, vue.unref)(form).setErrors,
404
+ formContext: __props.formContext
405
+ }, () => [(0, vue.createElementVNode)("button", {
406
+ class: "as-submit-btn",
407
+ disabled: (0, vue.unref)(form).submitDisabled.value
408
+ }, (0, vue.toDisplayString)((0, vue.unref)(form).submitText.value), 9, _hoisted_4)]) : (0, vue.createCommentVNode)("v-if", true),
409
+ (0, vue.renderSlot)(_ctx.$slots, "form.footer", {
410
+ disabled: (0, vue.unref)(form).submitDisabled.value,
411
+ clearErrors: (0, vue.unref)(form).clearErrors,
412
+ reset: (0, vue.unref)(form).reset,
413
+ setErrors: (0, vue.unref)(form).setErrors,
414
+ formContext: __props.formContext
415
+ }),
416
+ __props.loading ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_5, [(0, vue.renderSlot)(_ctx.$slots, "form.loading", {}, () => [_cache[2] || (_cache[2] = (0, vue.createElementVNode)("span", {
417
+ class: "as-form-overlay-icon",
418
+ "aria-hidden": "true"
419
+ }, null, -1))])])) : (0, vue.createCommentVNode)("v-if", true)
420
+ ], 40, _hoisted_1);
421
+ };
422
+ }
423
+ });
424
+ //#endregion
425
+ Object.defineProperty(exports, "as_form_default", {
426
+ enumerable: true,
427
+ get: function() {
428
+ return as_form_default;
429
+ }
430
+ });
431
+ Object.defineProperty(exports, "useAsExternalErrors", {
432
+ enumerable: true,
433
+ get: function() {
434
+ return useAsExternalErrors;
435
+ }
436
+ });
437
+ Object.defineProperty(exports, "useAsForm", {
438
+ enumerable: true,
439
+ get: function() {
440
+ return useAsForm;
441
+ }
442
+ });
443
+ Object.defineProperty(exports, "useAsState", {
444
+ enumerable: true,
445
+ get: function() {
446
+ return useAsState;
447
+ }
448
+ });
@@ -0,0 +1,7 @@
1
+ require("./use-form-context-Dwr8Ai1v.cjs");
2
+ require("./use-as-nested-sections-store-jdMRxjBE.cjs");
3
+ require("./use-as-value-help-uANI3zWa.cjs");
4
+ const require_as_form = require("./as-form-DAIkyt7H.cjs");
5
+ require("./as-field-wLYoaZnT.cjs");
6
+ require("./use-as-locale-C4z5stwD.cjs");
7
+ module.exports = require_as_form.as_form_default;
@@ -0,0 +1,2 @@
1
+ import { n as _default, t as Props } from "./as-form.vue-B4Bn0pbC.cjs";
2
+ export { Props, _default as default };
@@ -0,0 +1,2 @@
1
+ import { n as _default, t as Props } from "./as-form.vue-DRrb_yoj.mjs";
2
+ export { Props, _default as default };
@@ -0,0 +1,7 @@
1
+ import "./use-form-context-bAj7UoSe.mjs";
2
+ import "./use-as-nested-sections-store-lhi0z5z1.mjs";
3
+ import "./use-as-value-help-CBykDEjZ.mjs";
4
+ import { t as as_form_default } from "./as-form-CWwgyvfw.mjs";
5
+ import "./as-field-CXVjrEPQ.mjs";
6
+ import "./use-as-locale-BrFdAgnU.mjs";
7
+ export { as_form_default as default };
@@ -0,0 +1,158 @@
1
+ import { a as TAsTypeComponents, i as TAsComponentProps, n as TAsChangeType } from "./types-C4HRSxgV.cjs";
2
+ import * as vue from "vue";
3
+ import { Component } from "vue";
4
+ import { ClientFactory, FormDef } from "@atscript/ui";
5
+
6
+ //#region src/composables/types.d.ts
7
+ type TFormRule<TValue, TFormData, TContext> = (v: TValue, data?: TFormData, context?: TContext) => boolean | string;
8
+ interface TFormFieldCallbacks {
9
+ validate: () => boolean | string;
10
+ clearErrors: () => void;
11
+ reset: () => void;
12
+ setExternalError: (msg?: string) => void;
13
+ }
14
+ interface TFormFieldRegistration {
15
+ path: () => string;
16
+ callbacks: TFormFieldCallbacks;
17
+ }
18
+ interface TFormState {
19
+ firstSubmitHappened: boolean;
20
+ firstValidation: "on-change" | "touched-on-blur" | "on-blur" | "on-submit" | "none";
21
+ /**
22
+ * Fields registered AFTER `firstSubmitHappened` flipped to true. They stay
23
+ * in this set until either the user edits the field (model watch removes
24
+ * the id) or the next submit fires (set is cleared). Live validation is
25
+ * suppressed for these fields so a freshly-added array item doesn't render
26
+ * red required-field errors before the user has had a chance to type.
27
+ */
28
+ freshFields: Set<symbol>;
29
+ register: (id: symbol, registration: TFormFieldRegistration) => void;
30
+ unregister: (id: symbol) => void;
31
+ }
32
+ //#endregion
33
+ //#region src/components/as-form.vue.d.ts
34
+ interface Props<TF, TC> {
35
+ def: FormDef;
36
+ formData?: TF;
37
+ formContext?: TC;
38
+ firstValidation?: TFormState["firstValidation"];
39
+ components?: Record<string, Component<TAsComponentProps>>;
40
+ /**
41
+ * Type-to-component map for field rendering. Maps field types to Vue components.
42
+ * Must include entries for all built-in field types. Use `createDefaultTypes()`
43
+ * for a pre-filled map, or supply your own.
44
+ */
45
+ types: TAsTypeComponents;
46
+ errors?: Record<string, string | undefined>;
47
+ /**
48
+ * Per-form client factory override. Creates `Client` instances from URL paths
49
+ * for FK value-help pickers inside this form. Falls back to the app-wide
50
+ * default (`setDefaultClientFactory`) and then to the built-in `new Client(url)`
51
+ * factory when unset.
52
+ */
53
+ clientFactory?: ClientFactory;
54
+ /**
55
+ * Suppress the root field's title rendering. Use when the form is mounted
56
+ * inside a chrome that already shows the form's `@meta.label` (e.g. a
57
+ * dialog header). Nested fields keep their own headings.
58
+ */
59
+ hideRootTitle?: boolean;
60
+ /**
61
+ * Suppress the default submit button. Use when the host chrome owns the
62
+ * submit affordance (e.g. a dialog footer with its own submit button
63
+ * wired via HTML5 `<button form="...">`). Vue 3 treats an empty
64
+ * `<template #form.submit />` as "slot not provided" and falls back to
65
+ * the default button — this prop is the explicit way to skip it.
66
+ */
67
+ hideSubmit?: boolean;
68
+ /**
69
+ * When true, freezes the form: the body becomes `inert` (blocks pointer
70
+ * events + keyboard focus) and a loading overlay paints over the entire
71
+ * form area. Used by `<AsWfForm>` to lock interaction during a server
72
+ * round-trip so the user can't edit a field whose response is racing in.
73
+ * Visual is shared with `<AsTable>`'s query overlay via vunor
74
+ * `inner-loading`.
75
+ */
76
+ loading?: boolean;
77
+ }
78
+ declare const __VLS_export: <TFormData = any, TFormContext = any>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
79
+ props: vue.PublicProps & __VLS_PrettifyLocal<Props<TFormData, TFormContext> & {
80
+ onError?: ((errors: {
81
+ path: string;
82
+ message: string;
83
+ }[]) => any) | undefined;
84
+ onAction?: ((name: string, data: TFormData) => any) | undefined;
85
+ onSubmit?: ((data: TFormData) => any) | undefined;
86
+ "onUnsupported-action"?: ((name: string, data: TFormData) => any) | undefined;
87
+ onChange?: ((type: TAsChangeType, path: string, value: unknown, formData: TFormData) => any) | undefined;
88
+ }> & (typeof globalThis extends {
89
+ __VLS_PROPS_FALLBACK: infer P;
90
+ } ? P : {});
91
+ expose: (exposed: {}) => void;
92
+ attrs: any;
93
+ slots: {
94
+ 'form.header'?: (props: {
95
+ clearErrors: () => void;
96
+ reset: () => Promise<void>;
97
+ setErrors: (errors: Record<string, string>) => void;
98
+ formContext: TFormContext | undefined;
99
+ disabled: boolean;
100
+ }) => any;
101
+ } & {
102
+ 'form.before'?: (props: {
103
+ clearErrors: () => void;
104
+ reset: () => Promise<void>;
105
+ setErrors: (errors: Record<string, string>) => void;
106
+ formContext: TFormContext | undefined;
107
+ disabled: boolean;
108
+ }) => any;
109
+ } & {
110
+ 'form.after'?: (props: {
111
+ clearErrors: () => void;
112
+ reset: () => Promise<void>;
113
+ setErrors: (errors: Record<string, string>) => void;
114
+ disabled: boolean;
115
+ formContext: TFormContext | undefined;
116
+ }) => any;
117
+ } & {
118
+ 'form.error'?: (props: {
119
+ message: string;
120
+ dismiss: () => void;
121
+ }) => any;
122
+ } & {
123
+ 'form.submit'?: (props: {
124
+ disabled: boolean;
125
+ text: string;
126
+ clearErrors: () => void;
127
+ reset: () => Promise<void>;
128
+ setErrors: (errors: Record<string, string>) => void;
129
+ formContext: TFormContext | undefined;
130
+ }) => any;
131
+ } & {
132
+ 'form.footer'?: (props: {
133
+ disabled: boolean;
134
+ clearErrors: () => void;
135
+ reset: () => Promise<void>;
136
+ setErrors: (errors: Record<string, string>) => void;
137
+ formContext: TFormContext | undefined;
138
+ }) => any;
139
+ } & {
140
+ 'form.loading'?: (props: {}) => any;
141
+ };
142
+ emit: {
143
+ (e: "submit", data: TFormData): void;
144
+ (e: "error", errors: {
145
+ path: string;
146
+ message: string;
147
+ }[]): void;
148
+ (e: "action", name: string, data: TFormData): void;
149
+ (e: "unsupported-action", name: string, data: TFormData): void;
150
+ (e: "change", type: TAsChangeType, path: string, value: unknown, formData: TFormData): void;
151
+ };
152
+ }>) => vue.VNode & {
153
+ __ctx?: Awaited<typeof __VLS_setup>;
154
+ };
155
+ declare const _default: typeof __VLS_export;
156
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
157
+ //#endregion
158
+ export { TFormRule as a, TFormFieldRegistration as i, _default as n, TFormState as o, TFormFieldCallbacks as r, Props as t };