@atscript/vue-form 0.1.103 → 0.1.104

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 (185) hide show
  1. package/dist/{as-action-lLooKipk.cjs → as-action-B712j9xf.cjs} +4 -0
  2. package/dist/{as-action-BoZtbaXt.mjs → as-action-CCjN5EFP.mjs} +4 -0
  3. package/dist/as-action.cjs +1 -1
  4. package/dist/as-action.d.cts +1 -1
  5. package/dist/as-action.d.mts +1 -1
  6. package/dist/as-action.mjs +1 -1
  7. package/dist/{as-action.vue-BCbopk0S.d.cts → as-action.vue-BL8_a0fE.d.cts} +1 -1
  8. package/dist/{as-action.vue-BtQX09n-.d.mts → as-action.vue-CcOPK2qI.d.mts} +1 -1
  9. package/dist/{as-array-4rQYVD9_.mjs → as-array-BGG38Y1L.mjs} +5 -1
  10. package/dist/{as-array-C6tCzZir.cjs → as-array-DVc9_ood.cjs} +5 -1
  11. package/dist/as-array.cjs +1 -1
  12. package/dist/as-array.d.cts +1 -1
  13. package/dist/as-array.d.mts +1 -1
  14. package/dist/as-array.mjs +1 -1
  15. package/dist/{as-array.vue-Ci4xO292.d.cts → as-array.vue-Be1tDTdH.d.cts} +1 -1
  16. package/dist/{as-array.vue-I42wuF6e.d.mts → as-array.vue-CtBBY2gF.d.mts} +1 -1
  17. package/dist/{as-checkbox-C3i6ZmRk.mjs → as-checkbox-DwLRHmXj.mjs} +5 -1
  18. package/dist/{as-checkbox-oxG8_Isu.cjs → as-checkbox-sgF16SuJ.cjs} +5 -1
  19. package/dist/as-checkbox.cjs +1 -1
  20. package/dist/as-checkbox.d.cts +1 -1
  21. package/dist/as-checkbox.d.mts +1 -1
  22. package/dist/as-checkbox.mjs +1 -1
  23. package/dist/{as-checkbox.vue-BoY72SV8.d.mts → as-checkbox.vue-B6zk5IbU.d.cts} +1 -1
  24. package/dist/{as-checkbox.vue-DqIm0ms2.d.cts → as-checkbox.vue-CXpsn_WG.d.mts} +1 -1
  25. package/dist/as-collapsible.d.cts +1 -18
  26. package/dist/as-collapsible.d.mts +1 -19
  27. package/dist/as-collapsible.vue-34S3TEq5.d.cts +20 -0
  28. package/dist/as-collapsible.vue-CIfMlTQ6.d.mts +20 -0
  29. package/dist/{as-date-BfISLr-e.mjs → as-date-CfCa2Kp1.mjs} +6 -2
  30. package/dist/{as-date-C7pJIpe-.cjs → as-date-hCCTd52o.cjs} +6 -2
  31. package/dist/as-date.cjs +1 -1
  32. package/dist/as-date.d.cts +1 -1
  33. package/dist/as-date.d.mts +1 -1
  34. package/dist/as-date.mjs +1 -1
  35. package/dist/{as-date.vue-BfSVrED7.d.mts → as-date.vue-BZiy1s5s.d.cts} +1 -1
  36. package/dist/{as-date.vue-SdlJH5fn.d.cts → as-date.vue-DWWoojir.d.mts} +1 -1
  37. package/dist/{as-datetime-F3In2A6l.mjs → as-datetime-B1I_zREk.mjs} +6 -2
  38. package/dist/{as-datetime-DFTI8Wcr.cjs → as-datetime-DDlWca2Q.cjs} +6 -2
  39. package/dist/as-datetime.cjs +1 -1
  40. package/dist/as-datetime.d.cts +1 -1
  41. package/dist/as-datetime.d.mts +1 -1
  42. package/dist/as-datetime.mjs +1 -1
  43. package/dist/{as-datetime.vue-B47V1siL.d.mts → as-datetime.vue-DYEHokj_.d.cts} +1 -1
  44. package/dist/{as-datetime.vue-DUp_TDOW.d.cts → as-datetime.vue-NblA-SVE.d.mts} +1 -1
  45. package/dist/{as-decimal-DIO8bD2Y.mjs → as-decimal-CQM5OfqB.mjs} +5 -1
  46. package/dist/{as-decimal-CJAHWYjW.cjs → as-decimal-DM10ycwv.cjs} +5 -1
  47. package/dist/as-decimal.cjs +1 -1
  48. package/dist/as-decimal.d.cts +1 -1
  49. package/dist/as-decimal.d.mts +1 -1
  50. package/dist/as-decimal.mjs +1 -1
  51. package/dist/{as-decimal.vue-Bhq4C1Ix.d.cts → as-decimal.vue-BoNNIhbL.d.mts} +1 -1
  52. package/dist/{as-decimal.vue-DitPZpS_.d.mts → as-decimal.vue-D3eGMvC0.d.cts} +1 -1
  53. package/dist/{as-field-DLW-csEu.mjs → as-field-5rz47opo.mjs} +10 -4
  54. package/dist/{as-field-shell-CW3DDHnq.cjs → as-field-shell-C4epFfvE.cjs} +29 -23
  55. package/dist/{as-field-shell-BHYEjGcn.mjs → as-field-shell-DLvPV8WS.mjs} +29 -23
  56. package/dist/as-field-shell.cjs +1 -1
  57. package/dist/as-field-shell.d.cts +1 -1
  58. package/dist/as-field-shell.d.mts +1 -1
  59. package/dist/as-field-shell.mjs +1 -1
  60. package/dist/{as-field-shell.vue-Ct1ixFqc.d.cts → as-field-shell.vue-CLDHaWN0.d.cts} +1 -1
  61. package/dist/{as-field-shell.vue-K4Flr3gw.d.mts → as-field-shell.vue-DssDDSal.d.mts} +1 -1
  62. package/dist/{as-field-BKa4D63r.cjs → as-field-vktmRs-V.cjs} +9 -3
  63. package/dist/as-field.cjs +1 -1
  64. package/dist/as-field.d.cts +1 -24
  65. package/dist/as-field.d.mts +1 -25
  66. package/dist/as-field.mjs +1 -1
  67. package/dist/as-field.vue-A2cJj-Ih.d.cts +26 -0
  68. package/dist/as-field.vue-CmjIDgQ5.d.mts +26 -0
  69. package/dist/{as-form-CrMA0HdQ.cjs → as-form-B4DKpAVk.cjs} +75 -37
  70. package/dist/{as-form-OsyP7m-A.mjs → as-form-me0zA-52.mjs} +77 -39
  71. package/dist/as-form.cjs +1 -1
  72. package/dist/as-form.d.cts +1 -1
  73. package/dist/as-form.d.mts +1 -1
  74. package/dist/as-form.mjs +1 -1
  75. package/dist/as-form.vue-D5d1Y2ff.d.cts +1425 -0
  76. package/dist/as-form.vue-DH3phgWP.d.mts +1425 -0
  77. package/dist/{as-input-CqxNYh5q.cjs → as-input-Bp1Ltp15.cjs} +6 -2
  78. package/dist/{as-input-D7aA22Yx.mjs → as-input-DF--i7kY.mjs} +6 -2
  79. package/dist/{as-input-control-BYo_dfQA.cjs → as-input-control-B7F2q99A.cjs} +4 -0
  80. package/dist/{as-input-control-Bx-isLZN.mjs → as-input-control-BofS4mCo.mjs} +4 -0
  81. package/dist/as-input.cjs +1 -1
  82. package/dist/as-input.d.cts +1 -1
  83. package/dist/as-input.d.mts +1 -1
  84. package/dist/as-input.mjs +1 -1
  85. package/dist/{as-input.vue-BHsVVncq.d.cts → as-input.vue-CCAEWqK8.d.mts} +1 -1
  86. package/dist/{as-input.vue-DgZrW4pc.d.mts → as-input.vue-Nc9Q3RPh.d.cts} +1 -1
  87. package/dist/{as-iterator-DsDKfpTh.cjs → as-iterator-Bd-bKTMY.cjs} +1 -1
  88. package/dist/{as-iterator-DW7giLlz.mjs → as-iterator-BjIF-O-J.mjs} +1 -1
  89. package/dist/as-iterator.cjs +1 -1
  90. package/dist/as-iterator.d.cts +1 -20
  91. package/dist/as-iterator.d.mts +1 -21
  92. package/dist/as-iterator.mjs +1 -1
  93. package/dist/as-iterator.vue-BZeozFr-.d.cts +22 -0
  94. package/dist/as-iterator.vue-C8HW6n25.d.mts +22 -0
  95. package/dist/{as-multi-select-DQUInqwY.cjs → as-multi-select-b1l34vP5.cjs} +5 -1
  96. package/dist/{as-multi-select-Bsf4Y_mv.mjs → as-multi-select-mp-aM3LV.mjs} +5 -1
  97. package/dist/as-multi-select.cjs +1 -1
  98. package/dist/as-multi-select.d.cts +1 -1
  99. package/dist/as-multi-select.d.mts +1 -1
  100. package/dist/as-multi-select.mjs +1 -1
  101. package/dist/{as-multi-select.vue--bavpcN-.d.cts → as-multi-select.vue-D9mseRFm.d.cts} +1 -1
  102. package/dist/{as-multi-select.vue-rsDUkzxa.d.mts → as-multi-select.vue-DKpOsOmM.d.mts} +1 -1
  103. package/dist/{as-number-B8MCg-ph.mjs → as-number-De9zTltV.mjs} +6 -2
  104. package/dist/{as-number-CFdK5xjM.cjs → as-number-joydTMcJ.cjs} +6 -2
  105. package/dist/as-number.cjs +1 -1
  106. package/dist/as-number.d.cts +1 -1
  107. package/dist/as-number.d.mts +1 -1
  108. package/dist/as-number.mjs +1 -1
  109. package/dist/{as-number.vue-D2DrbnQu.d.cts → as-number.vue-CZC0-zs8.d.cts} +1 -1
  110. package/dist/{as-number.vue-Oml2y6Nt.d.mts → as-number.vue-DrvjSOdq.d.mts} +1 -1
  111. package/dist/{as-object-CN3KZFXO.mjs → as-object-CQMTYtcY.mjs} +5 -1
  112. package/dist/{as-object-B4sF9sIh.cjs → as-object-DgeItRdH.cjs} +5 -1
  113. package/dist/as-object.cjs +1 -1
  114. package/dist/as-object.d.cts +1 -1
  115. package/dist/as-object.d.mts +1 -1
  116. package/dist/as-object.mjs +1 -1
  117. package/dist/{as-object.vue-BljKYrMo.d.cts → as-object.vue-BItO19fw.d.mts} +1 -1
  118. package/dist/{as-object.vue-DAq7Kha3.d.mts → as-object.vue-DbHog5M-.d.cts} +1 -1
  119. package/dist/{as-paragraph-GIGj6UgL.mjs → as-paragraph-BP3-0EY4.mjs} +4 -0
  120. package/dist/{as-paragraph-BA-c863H.cjs → as-paragraph-CPhDTH_V.cjs} +4 -0
  121. package/dist/as-paragraph.cjs +1 -1
  122. package/dist/as-paragraph.d.cts +1 -1
  123. package/dist/as-paragraph.d.mts +1 -1
  124. package/dist/as-paragraph.mjs +1 -1
  125. package/dist/{as-paragraph.vue-CBU_olev.d.mts → as-paragraph.vue-BGDpjceO.d.mts} +1 -1
  126. package/dist/{as-paragraph.vue-LxXA7VPD.d.cts → as-paragraph.vue-D36pdOoc.d.cts} +1 -1
  127. package/dist/{as-radio-BeOQdoeq.cjs → as-radio-Dlmxk1vr.cjs} +5 -1
  128. package/dist/{as-radio-CFaDbRPe.mjs → as-radio-SwpgM1xP.mjs} +5 -1
  129. package/dist/as-radio.cjs +1 -1
  130. package/dist/as-radio.d.cts +1 -1
  131. package/dist/as-radio.d.mts +1 -1
  132. package/dist/as-radio.mjs +1 -1
  133. package/dist/{as-radio.vue-Dk4nlz-d.d.cts → as-radio.vue-EfrhKcBF.d.cts} +1 -1
  134. package/dist/{as-radio.vue-TVMliE1e.d.mts → as-radio.vue-WywkI-zY.d.mts} +1 -1
  135. package/dist/{as-ref-CNQgr6zE.mjs → as-ref-8JnEuan0.mjs} +5 -1
  136. package/dist/{as-ref-RawBvR6v.cjs → as-ref-BCpvUq8E.cjs} +5 -1
  137. package/dist/as-ref.cjs +1 -1
  138. package/dist/as-ref.d.cts +1 -1
  139. package/dist/as-ref.d.mts +1 -1
  140. package/dist/as-ref.mjs +1 -1
  141. package/dist/{as-ref.vue-CUxxGqyg.d.mts → as-ref.vue-BD_vsu7I.d.mts} +1 -1
  142. package/dist/{as-ref.vue-CnzqRblA.d.cts → as-ref.vue-Cxg-A5QR.d.cts} +1 -1
  143. package/dist/{as-select-Cr00CPKf.mjs → as-select-C3ukCyGQ.mjs} +5 -1
  144. package/dist/{as-select-LJIvBPiv.cjs → as-select-CtSNZXtC.cjs} +5 -1
  145. package/dist/as-select.cjs +1 -1
  146. package/dist/as-select.d.cts +1 -1
  147. package/dist/as-select.d.mts +1 -1
  148. package/dist/as-select.mjs +1 -1
  149. package/dist/{as-select.vue-CKjAg-Y2.d.mts → as-select.vue-DoAG5njV.d.mts} +1 -1
  150. package/dist/{as-select.vue-ZZtjsmcO.d.cts → as-select.vue-hd94jaH_.d.cts} +1 -1
  151. package/dist/{as-time-CE2FaqZ3.mjs → as-time-QJ9YiVj9.mjs} +6 -2
  152. package/dist/{as-time-CqCF0pKQ.cjs → as-time-nAPtGL3t.cjs} +6 -2
  153. package/dist/as-time.cjs +1 -1
  154. package/dist/as-time.d.cts +1 -1
  155. package/dist/as-time.d.mts +1 -1
  156. package/dist/as-time.mjs +1 -1
  157. package/dist/{as-time.vue-BCEE4uCV.d.mts → as-time.vue-DMy_Au0C.d.cts} +1 -1
  158. package/dist/{as-time.vue-BUAvE5m3.d.cts → as-time.vue-DgW7qSAM.d.mts} +1 -1
  159. package/dist/{as-tuple-B3ysbvxB.cjs → as-tuple-CFn7aZYt.cjs} +5 -1
  160. package/dist/{as-tuple-CeJWgP6l.mjs → as-tuple-CJXpGGKj.mjs} +5 -1
  161. package/dist/as-tuple.cjs +1 -1
  162. package/dist/as-tuple.d.cts +1 -1
  163. package/dist/as-tuple.d.mts +1 -1
  164. package/dist/as-tuple.mjs +1 -1
  165. package/dist/{as-tuple.vue-WN7k43tv.d.mts → as-tuple.vue-BDwz5FeN.d.mts} +1 -1
  166. package/dist/{as-tuple.vue-cy0ThAGl.d.cts → as-tuple.vue-DZ2Soqyw.d.cts} +1 -1
  167. package/dist/{as-union-Djhjo69H.cjs → as-union-BDRNBacb.cjs} +4 -0
  168. package/dist/{as-union-BPlYyGVk.mjs → as-union-DZWgGqqM.mjs} +4 -0
  169. package/dist/as-union.cjs +1 -1
  170. package/dist/as-union.d.cts +1 -1
  171. package/dist/as-union.d.mts +1 -1
  172. package/dist/as-union.mjs +1 -1
  173. package/dist/{as-union.vue-AqH35ozq.d.cts → as-union.vue-D9Mh0M3_.d.mts} +1 -1
  174. package/dist/{as-union.vue-Ew3Bany8.d.mts → as-union.vue-DQKWNuhd.d.cts} +1 -1
  175. package/dist/index.cjs +22 -22
  176. package/dist/index.d.cts +24 -1081
  177. package/dist/index.d.mts +24 -1081
  178. package/dist/index.mjs +22 -22
  179. package/dist/{types-BYfe1QEF.d.cts → types-B8aPXWL5.d.cts} +13 -0
  180. package/dist/{types-CV9ss4UN.d.mts → types-nuUi10Kl.d.mts} +13 -0
  181. package/dist/{use-as-date-XLE8HBbo.mjs → use-as-date-B6RGkjjB.mjs} +4 -0
  182. package/dist/{use-as-date-DY8b1_V4.cjs → use-as-date-CslHBPmQ.cjs} +4 -0
  183. package/package.json +6 -6
  184. package/dist/as-form.vue-2NZSk1F9.d.mts +0 -285
  185. package/dist/as-form.vue-Dg_5GYWG.d.cts +0 -285
@@ -0,0 +1,1425 @@
1
+ import { c as TAsUnionContext, n as TAsChangeType, o as TAsComponentProps, s as TAsTypeComponents } from "./types-nuUi10Kl.mjs";
2
+ import * as vue from "vue";
3
+ import { Component, ComputedRef, MaybeRef, Ref, ShallowRef, WritableComputedRef } from "vue";
4
+ import * as _atscript_ui0 from "@atscript/ui";
5
+ import { ClientFactory, ClientFactory as ClientFactory$1, FormArrayFieldDef, FormDef, FormDiffOptions, FormDiffOptions as FormDiffOptions$1, FormFieldChange, FormFieldChange as FormFieldChange$1, FormFieldDef, FormRebaseOptions, FormRebaseOptions as FormRebaseOptions$1, FormTupleFieldDef, FormUnionFieldDef, FormUnionVariant, ResolvedValueHelp, ValueHelpInfo, getDefaultClientFactory, resetDefaultClientFactory, setDefaultClientFactory } from "@atscript/ui";
6
+ //#region ../../node_modules/.pnpm/@atscript+typescript@0.1.77_@atscript+core@0.1.77_@emnapi+core@1.10.0_@emnapi+runtime@1_3bfa7f91a63047efd8c9ebad2f514f7c/node_modules/@atscript/typescript/dist/utils.d.ts
7
+ interface TError {
8
+ path: string;
9
+ message: string;
10
+ details?: TError[];
11
+ }
12
+ /**
13
+ * A plugin function that can intercept validation.
14
+ *
15
+ * Return `true` to accept the value, `false` to reject it,
16
+ * or `undefined` to fall through to the default validation.
17
+ */
18
+ type TValidatorPlugin = (ctx: TValidatorPluginContext, def: TAtscriptAnnotatedType, value: any) => boolean | undefined;
19
+ /** Options for configuring {@link Validator} behavior. */
20
+ interface TValidatorOptions {
21
+ partial: boolean | 'deep' | ((type: TAtscriptAnnotatedType<TAtscriptTypeObject>, path: string) => boolean);
22
+ replace?: (type: TAtscriptAnnotatedType, path: string) => TAtscriptAnnotatedType;
23
+ plugins: TValidatorPlugin[];
24
+ unknownProps: 'strip' | 'ignore' | 'error';
25
+ errorLimit: number;
26
+ skipList?: Set<string>;
27
+ }
28
+ /** Context exposed to {@link TValidatorPlugin} functions. */
29
+ interface TValidatorPluginContext {
30
+ opts: Validator<any>['opts'];
31
+ validateAnnotatedType: Validator<any>['validateAnnotatedType'];
32
+ error: Validator<any>['error'];
33
+ path: Validator<any>['path'];
34
+ context: unknown;
35
+ }
36
+ /**
37
+ * Validates values against an {@link TAtscriptAnnotatedType} definition.
38
+ *
39
+ * `DataType` is automatically inferred from the type definition's phantom generic,
40
+ * enabling the {@link validate} method to act as a type guard.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * // From a generated interface class:
45
+ * const validator = new Validator(MyInterface)
46
+ * if (validator.validate(data, true)) {
47
+ * data // narrowed to MyInterface
48
+ * }
49
+ *
50
+ * // Or use the built-in factory:
51
+ * MyInterface.validator().validate(data)
52
+ * ```
53
+ *
54
+ * @typeParam T - The annotated type definition.
55
+ * @typeParam DataType - The TypeScript type that `validate` narrows to (auto-inferred).
56
+ */
57
+ declare class Validator<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>> {
58
+ protected readonly def: T;
59
+ protected opts: TValidatorOptions;
60
+ protected hasPlugins: boolean;
61
+ protected hasReplace: boolean;
62
+ private replaceCache?;
63
+ constructor(def: T, opts?: Partial<TValidatorOptions>);
64
+ /** Validation errors collected during the last {@link validate} call. */
65
+ errors: TError[];
66
+ protected stackErrors: Array<TError[] | null>;
67
+ protected pathSegments: string[];
68
+ protected depth: number;
69
+ protected limitExceeded: boolean;
70
+ protected context: unknown;
71
+ protected buildPath(): string;
72
+ protected push(name: string): void;
73
+ protected pop(saveErrors: boolean): TError[] | null | undefined;
74
+ protected clear(): void;
75
+ protected error(message: string, path?: string, details?: TError[]): void;
76
+ protected throw(): void;
77
+ /**
78
+ * Validates a value against the type definition.
79
+ *
80
+ * Acts as a TypeScript type guard — when it returns `true`, the value
81
+ * is narrowed to `DataType`.
82
+ *
83
+ * @param value - The value to validate.
84
+ * @param safe - If `true`, returns `false` on failure instead of throwing.
85
+ * @returns `true` if the value matches the type definition.
86
+ * @throws {ValidatorError} When validation fails and `safe` is not `true`.
87
+ */
88
+ validate<TT = DataType>(value: any, safe?: boolean, context?: unknown): value is TT;
89
+ protected validateSafe(def: TAtscriptAnnotatedType, value: any): boolean;
90
+ protected get path(): string;
91
+ protected validateAnnotatedType(def: TAtscriptAnnotatedType, value: any): boolean;
92
+ protected validateUnion(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
93
+ protected validateIntersection(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
94
+ protected validateTuple(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
95
+ protected validateArray(def: TAtscriptAnnotatedType<TAtscriptTypeArray>, value: any): boolean;
96
+ protected validateObject(def: TAtscriptAnnotatedType<TAtscriptTypeObject>, value: any): boolean;
97
+ protected validatePrimitive(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: any): boolean;
98
+ protected validateString(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: string): boolean;
99
+ protected validateNumber(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: number): boolean;
100
+ protected validateBoolean(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: boolean): boolean;
101
+ }
102
+ /** Error thrown by {@link Validator.validate} when validation fails. Contains structured error details. */
103
+ /** Type definition for union, intersection, or tuple types. */
104
+ interface TAtscriptTypeComplex<DataType = unknown> {
105
+ kind: 'union' | 'intersection' | 'tuple';
106
+ items: TAtscriptAnnotatedType[];
107
+ tags: Set<AtscriptPrimitiveTags>;
108
+ /** @internal phantom — carries the DataType at the type level, never set at runtime */
109
+ __dataType?: DataType;
110
+ }
111
+ /** Type definition for array types. */
112
+ interface TAtscriptTypeArray<DataType = unknown[]> {
113
+ kind: 'array';
114
+ of: TAtscriptAnnotatedType;
115
+ tags: Set<AtscriptPrimitiveTags>;
116
+ /** @internal phantom — carries the DataType at the type level, never set at runtime */
117
+ __dataType?: DataType;
118
+ }
119
+ /** Type definition for object types with named and pattern-matched properties. */
120
+ interface TAtscriptTypeObject<K extends string = string, DataType = Record<K, unknown>> {
121
+ kind: 'object';
122
+ props: Map<K, TAtscriptAnnotatedType>;
123
+ propsPatterns: Array<{
124
+ pattern: RegExp;
125
+ def: TAtscriptAnnotatedType;
126
+ }>;
127
+ tags: Set<AtscriptPrimitiveTags>;
128
+ /** @internal phantom — carries the DataType at the type level, never set at runtime */
129
+ __dataType?: DataType;
130
+ }
131
+ /** Type definition for primitive/literal types (string, number, boolean, null, etc.). */
132
+ interface TAtscriptTypeFinal<DataType = unknown> {
133
+ kind: '';
134
+ /**
135
+ * design type
136
+ */
137
+ designType: 'string' | 'number' | 'boolean' | 'undefined' | 'null' | 'object' | 'any' | 'never' | 'phantom' | 'decimal';
138
+ /**
139
+ * value for literals
140
+ */
141
+ value?: string | number | boolean;
142
+ tags: Set<AtscriptPrimitiveTags>;
143
+ /** @internal phantom — carries the DataType at the type level, never set at runtime */
144
+ __dataType?: DataType;
145
+ }
146
+ /**
147
+ * Extract DataType from a type def's phantom generic
148
+ */
149
+ type InferDataType<T> = T extends {
150
+ __dataType?: infer D;
151
+ } ? D : unknown;
152
+ /**
153
+ * Extract the DataType from a {@link TAtscriptAnnotatedType}.
154
+ *
155
+ * Resolves the phantom `__dataType` carried by the type definition.
156
+ * When `__dataType` is `unknown` (unset), falls back to the constructor
157
+ * instance type if `T` is also a class (i.e. a generated interface).
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * import type { TAtscriptDataType } from '@atscript/typescript/utils'
162
+ * import MyInterface from './my-interface.as'
163
+ *
164
+ * type Data = TAtscriptDataType<typeof MyInterface>
165
+ * ```
166
+ */
167
+ type TAtscriptDataType<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType> = T extends {
168
+ type: {
169
+ __dataType?: infer D;
170
+ };
171
+ } ? unknown extends D ? T extends (new (...args: any[]) => infer I) ? I : unknown : D : unknown;
172
+ /** Union of all possible type definition shapes. */
173
+ type TAtscriptTypeDef<DataType = unknown> = TAtscriptTypeComplex<DataType> | TAtscriptTypeFinal<DataType> | TAtscriptTypeArray<DataType> | TAtscriptTypeObject<string, DataType>;
174
+ /**
175
+ * Core annotated type — wraps a type definition with metadata and a validator factory.
176
+ *
177
+ * Generated `.as` files produce classes/namespaces that conform to this interface.
178
+ * The `DataType` phantom generic carries the TypeScript data shape for type-safe validation.
179
+ *
180
+ * @typeParam T - The underlying type definition (e.g. {@link TAtscriptTypeObject}).
181
+ * @typeParam DataType - The TypeScript type the validated data narrows to (auto-inferred from `T`).
182
+ */
183
+ interface TAtscriptAnnotatedType<T extends TAtscriptTypeDef = TAtscriptTypeDef, DataType = InferDataType<T>> {
184
+ __is_atscript_annotated_type: true;
185
+ type: T;
186
+ validator(opts?: Partial<TValidatorOptions>): Validator<this, DataType>;
187
+ metadata: TMetadataMap<AtscriptMetadata>;
188
+ optional?: boolean;
189
+ id?: string;
190
+ ref?: {
191
+ type: () => TAtscriptAnnotatedType;
192
+ field: string;
193
+ };
194
+ }
195
+ /** An annotated type that is also a class constructor (i.e. a generated interface class). */
196
+ /**
197
+ * Atscript Metadata Map with typed setters/getters
198
+ */
199
+ interface TMetadataMap<O extends object> extends Map<keyof O, O[keyof O]> {
200
+ get<K extends keyof O>(key: K): O[K] | undefined;
201
+ get(key: string): unknown;
202
+ set<K extends keyof O>(key: K, value: O[K]): this;
203
+ has<K extends keyof O>(key: K): boolean;
204
+ has(key: string): boolean;
205
+ }
206
+ /** Fluent builder handle returned by {@link defineAnnotatedType}. */
207
+ //#endregion
208
+ //#region src/composables/create-as-form-def.d.ts
209
+ /**
210
+ * Creates a reactive form definition and data object from an ATScript annotated type.
211
+ *
212
+ * @param type - An ATScript annotated type (imported from a `.as` file).
213
+ * @param context - Optional context object forwarded to `ui.fn.value` resolvers during data creation.
214
+ * Only effective when `@atscript/ui-fns` is installed (dynamic resolver).
215
+ * @returns `{ def, formData }` — the FormDef and a Vue reactive data object with defaults applied
216
+ */
217
+ declare function createAsFormDef<T extends TAtscriptAnnotatedType>(type: T, context?: Record<string, unknown>): {
218
+ def: _atscript_ui0.FormDef;
219
+ formData: {
220
+ value: vue.UnwrapRef<TAtscriptDataType<T>>;
221
+ };
222
+ };
223
+ //#endregion
224
+ //#region src/composables/create-default-types.d.ts
225
+ /**
226
+ * Returns a fresh type-to-component map pre-filled with all built-in defaults.
227
+ *
228
+ * Spread or assign additional entries to extend with custom field types:
229
+ * ```ts
230
+ * const types = { ...createDefaultTypes(), rating: MyRatingComponent }
231
+ * ```
232
+ */
233
+ declare function createDefaultTypes(): TAsTypeComponents;
234
+ //#endregion
235
+ //#region src/composables/types.d.ts
236
+ type TFormRule<TValue, TFormData, TContext> = (v: TValue, data?: TFormData, context?: TContext) => boolean | string;
237
+ interface TFormFieldCallbacks {
238
+ validate: () => boolean | string;
239
+ clearErrors: () => void;
240
+ reset: () => void;
241
+ setExternalError: (msg?: string) => void;
242
+ }
243
+ interface TFormFieldRegistration {
244
+ path: () => string;
245
+ callbacks: TFormFieldCallbacks;
246
+ }
247
+ interface TFormState {
248
+ firstSubmitHappened: boolean;
249
+ firstValidation: "on-change" | "touched-on-blur" | "on-blur" | "on-submit" | "none";
250
+ /**
251
+ * Fields registered AFTER `firstSubmitHappened` flipped to true. They stay
252
+ * in this set until either the user edits the field (model watch removes
253
+ * the id) or the next submit fires (set is cleared). Live validation is
254
+ * suppressed for these fields so a freshly-added array item doesn't render
255
+ * red required-field errors before the user has had a chance to type.
256
+ */
257
+ freshFields: Set<symbol>;
258
+ register: (id: symbol, registration: TFormFieldRegistration) => void;
259
+ unregister: (id: symbol) => void;
260
+ }
261
+ //#endregion
262
+ //#region src/composables/use-as-field.d.ts
263
+ interface UseAsFieldOptions<TValue = any, TFormData = any, TContext = any> {
264
+ getValue: () => TValue;
265
+ setValue: (v: TValue) => void;
266
+ rules?: TFormRule<TValue, TFormData, TContext>[];
267
+ path: () => string;
268
+ /** Value to set on reset. Defaults to `''`. Use `[]` for arrays, `{}` for objects. */
269
+ resetValue?: TValue;
270
+ }
271
+ interface UseAsFieldReturn<TValue = any> {
272
+ model: WritableComputedRef<TValue>;
273
+ error: ComputedRef<string | undefined>;
274
+ onBlur: () => void;
275
+ /**
276
+ * Reactive "changed-since-baseline" flag for THIS field. `true` when the
277
+ * form has `track-changes` enabled AND the field at `opts.path()` differs
278
+ * from the tracker's baseline. Recomputes whenever the change list does
279
+ * (delegates to the injected {@link AsFormPatchHandle.isDirtyPath}).
280
+ *
281
+ * Always `false` when tracking is off (no patch handle injected) — the
282
+ * handle is injected OPTIONALLY, so reading `isDirty` never throws.
283
+ * Granularity matches the change list: object/section containers light up
284
+ * via their leaves' prefix, whole-array fields via exact match; an
285
+ * array-ITEM leaf stays `false` (the array container lights up instead).
286
+ */
287
+ isDirty: ComputedRef<boolean>;
288
+ }
289
+ declare function useAsField<TValue = any, TFormData = any, TContext = any>(opts: UseAsFieldOptions<TValue, TFormData, TContext>): UseAsFieldReturn<TValue>;
290
+ //#endregion
291
+ //#region src/composables/use-as-state.d.ts
292
+ /** Custom form-level validator. Returns `Record<path, message>` (empty = passed). */
293
+ type TFormSubmitValidator = () => Record<string, string>;
294
+ interface UseAsStateReturn {
295
+ formState: TFormState;
296
+ clearErrors: () => void;
297
+ reset: () => Promise<void>;
298
+ submit: () => true | {
299
+ path: string;
300
+ message: string;
301
+ }[];
302
+ setErrors: (errors: Record<string, string>) => void;
303
+ }
304
+ declare function useAsState<TFormData, TContext>(opts: {
305
+ formData: MaybeRef<TFormData>;
306
+ formContext?: MaybeRef<TContext>;
307
+ firstValidation?: MaybeRef<TFormState["firstValidation"] | undefined>; /** When provided, replaces per-field iteration on submit. */
308
+ submitValidator?: TFormSubmitValidator;
309
+ }): UseAsStateReturn;
310
+ //#endregion
311
+ //#region src/composables/use-as-form-patch.d.ts
312
+ /**
313
+ * Result of {@link AsFormPatchHandle.rebaseOnto}. Aliases the `@atscript/ui`
314
+ * rebase shape (minus `next`, which is written into the live container rather
315
+ * than returned): the surviving local diff on top of the NEW baseline plus the
316
+ * conflict paths.
317
+ */
318
+ interface RebaseOntoResult {
319
+ /** Paths changed on both sides to different values, plus ancestor-clear paths. */
320
+ conflicts: string[];
321
+ /** Local edits that survive on top of the new (upstream) baseline. */
322
+ reapplied: FormFieldChange[];
323
+ }
324
+ /**
325
+ * Change-tracking handle for a single `<AsForm>`. Exposed three ways:
326
+ *
327
+ * 1. injected via {@link useAsFormPatch} inside any descendant component,
328
+ * 2. spread into every `<AsForm>` slot (`isDirty` / `changes` / `getPatch` /
329
+ * `getChanges` — so a footer slot can gate a Save button), and
330
+ * 3. `defineExpose`d on `<AsForm>` (so a parent template ref can call
331
+ * `asForm.value.getPatch()`).
332
+ *
333
+ * Built on `@atscript/ui`'s `buildFormDiff`, which diffs the form's CURRENT
334
+ * data against a BASELINE snapshot and produces both a per-field change list
335
+ * and an `@atscript/db` patch object (keyed-array `$update`/`$insert`/`$remove`,
336
+ * `$cas` optimistic-concurrency sibling, revert-aware).
337
+ */
338
+ interface AsFormPatchHandle {
339
+ /**
340
+ * Reactive dirtiness — `true` when current data differs from the baseline.
341
+ * Revert-aware: a value edited back to its baseline flips this back to
342
+ * `false`. Memoised by Vue; recomputes only when the form data changes.
343
+ */
344
+ isDirty: ComputedRef<boolean>;
345
+ /**
346
+ * Reactive per-field change list (revert-aware — reverted fields drop out).
347
+ * `before` / `after` hold live references into the baseline / current data.
348
+ */
349
+ changes: ComputedRef<FormFieldChange[]>;
350
+ /**
351
+ * Builds the `@atscript/db` patch object on demand against the baseline
352
+ * snapshot. Safe to call at submit time (a fresh re-snapshot point). Returns
353
+ * `{}` when nothing changed. Carries a top-level `$cas` sibling when the form
354
+ * has a `@db.column.version` column and `opts.cas` is on (default).
355
+ */
356
+ getPatch: (opts?: FormDiffOptions) => Record<string, unknown>;
357
+ /** Builds the per-field change list on demand (same data as `changes`). */
358
+ getChanges: () => FormFieldChange[];
359
+ /**
360
+ * Reactive per-field dirty predicate. `true` when the field at the dot-path
361
+ * `path` differs from the baseline. Reads the reactive {@link changes} list,
362
+ * so a per-field `isDirty` derived from this recomputes whenever the change
363
+ * list does.
364
+ *
365
+ * Granularity matches the change list (leaf-grained for scalars/objects,
366
+ * WHOLE-ARRAY for arrays): a field is dirty iff some change path equals
367
+ * `path` OR starts with `path + "."`. Object/section containers light up via
368
+ * the prefix branch; whole-array fields via exact match; an array-ITEM leaf
369
+ * (e.g. `items.0.qty`) returns `false` (the array container lights up
370
+ * instead — a known, documented limitation of the array diff). The empty
371
+ * root path `''` is dirty iff there are ANY changes. Backed by an O(1)
372
+ * `Set.has` against `@atscript/ui`'s `collectDirtyPaths` precompute, whose
373
+ * membership matches `isPathDirty` exactly (locked by an invariant test).
374
+ */
375
+ isDirtyPath: (path: string) => boolean;
376
+ /**
377
+ * Re-baseline to the current data. Call after a successful save so the form
378
+ * becomes clean again WITHOUT a remount. No-op when tracking is inactive.
379
+ */
380
+ rebase: () => void;
381
+ /**
382
+ * 3-way rebase onto a fresh upstream snapshot. Sets the baseline to
383
+ * `upstream` and rewrites the live form to `upstream` + the local diff
384
+ * (current vs. old baseline) reapplied on top:
385
+ *
386
+ * - fields the user never touched adopt `upstream`'s value,
387
+ * - local edits survive,
388
+ * - fields changed on both sides to a different value are conflicts, resolved
389
+ * by `opts.conflict` (`'ours'` default keeps local, `'theirs'` takes
390
+ * upstream).
391
+ *
392
+ * `upstream` is the WRAPPED form-data container (`{ value }`). The live form
393
+ * data is rewritten in a SINGLE mutation (the bound `:form-data` container
394
+ * identity is preserved, so the consumer's ref stays the same object). After
395
+ * the write the baseline becomes a deep clone of `upstream`, so a subsequent
396
+ * `getPatch()` carries exactly the surviving local diff (`reapplied`).
397
+ *
398
+ * Returns the conflict paths and the surviving local diff. No-op returning
399
+ * empty when tracking is inactive.
400
+ */
401
+ rebaseOnto: (upstream: Record<string, unknown>, opts?: FormRebaseOptions) => RebaseOntoResult;
402
+ }
403
+ /**
404
+ * Reactive read-only access to the form's change-tracking handle from any
405
+ * descendant of an `<AsForm track-changes>`. Mirrors the `useAsData` /
406
+ * `useAsPath` injector pattern.
407
+ *
408
+ * THROWS when called outside a form, or inside a form that did not enable
409
+ * `track-changes` — fail loud rather than silently report "not dirty".
410
+ *
411
+ * @example
412
+ * ```vue
413
+ * <script setup lang="ts">
414
+ * import { useAsFormPatch } from "@atscript/vue-form";
415
+ * const { isDirty, getPatch } = useAsFormPatch();
416
+ * </script>
417
+ * <template>
418
+ * <button :disabled="!isDirty" @click="save(getPatch())">Save</button>
419
+ * </template>
420
+ * ```
421
+ */
422
+ declare function useAsFormPatch(): AsFormPatchHandle;
423
+ //#endregion
424
+ //#region src/composables/use-as-form.d.ts
425
+ /**
426
+ * Options for {@link useAsForm}. Each reactive prop is supplied as a
427
+ * **getter** so the composable can subscribe to its changes without owning
428
+ * a `Ref`. Pass component-level `defineProps` accessors verbatim:
429
+ *
430
+ * ```ts
431
+ * useAsForm({
432
+ * def: () => props.def,
433
+ * formData: () => props.formData,
434
+ * types: () => props.types,
435
+ * // ...
436
+ * emits: { submit: (data) => emit("submit", data), ... },
437
+ * })
438
+ * ```
439
+ *
440
+ * Generic `TFormData` / `TFormContext` mirror the `<AsForm>` component
441
+ * generics. They flow through to emitted callbacks; if you build a custom
442
+ * form root with a known data shape, pin them at the call site.
443
+ */
444
+ interface UseAsFormOptions<TFormData = unknown, TFormContext = unknown> {
445
+ /** Form definition produced by `createAsFormDef(type)`. Reactive. */
446
+ def: () => FormDef;
447
+ /**
448
+ * Externally-managed form data container `{ value: domainData }`. When
449
+ * unset, the composable creates an internal one initialized to `{}`.
450
+ */
451
+ formData?: () => TFormData | undefined;
452
+ /** Reactive form context — exposed to validators, scope, slots, and emits. */
453
+ formContext?: () => TFormContext | undefined;
454
+ /** First-validation strategy. Defaults to `"on-change"`. */
455
+ firstValidation?: () => TFormState["firstValidation"] | undefined;
456
+ /** Custom field components keyed by field name (matches `Props.components`). */
457
+ components?: () => Record<string, Component<TAsComponentProps>> | undefined;
458
+ /** Type-to-component map keyed by field type (matches `Props.types`). */
459
+ types: () => TAsTypeComponents;
460
+ /** Server-supplied errors keyed by absolute dotted path (`__form` for form-level). */
461
+ errors?: () => Record<string, string | undefined> | undefined;
462
+ /** Per-form value-help client factory. Falls back to the app-wide default when unset. */
463
+ clientFactory?: () => ClientFactory | undefined;
464
+ /** Suppress the root field's title (use when the chrome already shows the form's label). */
465
+ hideRootTitle?: () => boolean | undefined;
466
+ /**
467
+ * Busy-state flag. When `true`, the form is locked (inert + overlay) and the
468
+ * default submit button is disabled. `<AsWfForm>` wires this to its
469
+ * server round-trip so consumers can drop their own submit overrides.
470
+ */
471
+ loading?: () => boolean | undefined;
472
+ /**
473
+ * Enable change tracking. When `true`, the composable captures a deep-clone
474
+ * baseline of the form data (the moment it becomes available) and exposes a
475
+ * {@link AsFormPatchHandle} via `slotProps`, the return value (`patch`), and
476
+ * `provide(FORM_PATCH_KEY)` (read with `useAsFormPatch()`). When falsy
477
+ * (default), there is ZERO overhead — no baseline, no deep watch, and
478
+ * `useAsFormPatch()` throws. Reactive.
479
+ */
480
+ trackChanges?: () => boolean | undefined;
481
+ /**
482
+ * Outbound callbacks. Customer form roots typically wire these to
483
+ * `defineEmits`; advanced uses can pass plain functions.
484
+ */
485
+ emits?: {
486
+ submit?: (data: TFormData) => void;
487
+ error?: (errors: {
488
+ path: string;
489
+ message: string;
490
+ }[]) => void;
491
+ action?: (name: string, data: TFormData) => void;
492
+ unsupportedAction?: (name: string, data: TFormData) => void;
493
+ change?: (type: TAsChangeType, path: string, value: unknown, formData: TFormData) => void;
494
+ };
495
+ }
496
+ interface UseAsFormReturn<TFormData = unknown, TFormContext = unknown> {
497
+ /** Reactive form-data container `{ value: domainData }`. */
498
+ data: ComputedRef<TFormData>;
499
+ /** Effective external errors (post-dismissal), excluding `__form`. */
500
+ errors: ComputedRef<Record<string, string | undefined> | undefined>;
501
+ /** Form-level error message (post banner-dismissal). */
502
+ formError: ComputedRef<string | undefined>;
503
+ /** Errors discovered by the local validator on the most-recent submit. */
504
+ internalErrors: Ref<Record<string, string>>;
505
+ /**
506
+ * Reset internal validator + dismissal state and re-run field defaults. When
507
+ * `trackChanges` is enabled, also re-baselines the change tracker to the
508
+ * post-reset state (the form becomes clean again).
509
+ */
510
+ reset: () => Promise<void>;
511
+ /** Imperatively clear errors (matches `useAsState().clearErrors`). */
512
+ clearErrors: () => void;
513
+ /** Imperatively set external-error messages by path. */
514
+ setErrors: (errors: Record<string, string>) => void;
515
+ /** Trigger submit. Emits `submit` on success and `error` on validation failure. */
516
+ onSubmit: () => void;
517
+ /** Resolved submit-button text (`@ui.form.submit.text` / fn variant). */
518
+ submitText: ComputedRef<string>;
519
+ /** Resolved submit-button disabled state (`@ui.form.fn.submitDisabled`). */
520
+ submitDisabled: ComputedRef<boolean>;
521
+ /** Resolved form-level title (`@ui.form.fn.title` / `@meta.label`); may be `undefined`. */
522
+ title: ComputedRef<string | undefined>;
523
+ /** Resolved form-level description (`@ui.form.fn.description` / `@meta.description`). */
524
+ description: ComputedRef<string | undefined>;
525
+ /** Unified slot-props bag spread onto every `<AsForm>` slot. */
526
+ slotProps: ComputedRef<{
527
+ title: string | undefined;
528
+ description: string | undefined;
529
+ data: TFormData;
530
+ errors: Record<string, string | undefined> | undefined;
531
+ formError: string | undefined;
532
+ disabled: boolean;
533
+ loading: boolean;
534
+ submitText: string;
535
+ submit: () => void;
536
+ reset: () => Promise<void>;
537
+ clearErrors: () => void;
538
+ setErrors: (errors: Record<string, string>) => void;
539
+ dismissError: (path: string) => void;
540
+ dismissFormError: () => void;
541
+ formContext: TFormContext | undefined; /** True when `track-changes` is on AND data differs from baseline. */
542
+ isDirty: boolean; /** Revert-aware per-field change list (empty when tracking is off). */
543
+ changes: readonly FormFieldChange[]; /** Build the `@atscript/db` patch on demand (`{}` when tracking is off). */
544
+ getPatch: (opts?: FormDiffOptions) => Record<string, unknown>; /** Build the per-field change list on demand (`[]` when tracking is off). */
545
+ getChanges: () => FormFieldChange[]; /** Per-field dirty predicate (`false` for every path when tracking is off). */
546
+ isDirtyPath: (path: string) => boolean;
547
+ }>;
548
+ /**
549
+ * Change-tracking handle — present ONLY when `trackChanges` is enabled.
550
+ * `undefined` otherwise. Read it from descendants with `useAsFormPatch()`.
551
+ */
552
+ patch: AsFormPatchHandle | undefined;
553
+ /**
554
+ * Remount key for the field subtree. Bound as `:key` on the root `<AsField>`.
555
+ * Bumped by `patch.rebaseOnto` only when a rebase lands a different union
556
+ * variant, forcing the variant picker to re-detect. `0` otherwise.
557
+ */
558
+ remountKey: Ref<number>;
559
+ /** Dispatch an action — invoked by `<AsAction>`. */
560
+ invokeAction: (name: string) => void;
561
+ /** Dismiss a single external leaf error. */
562
+ dismissError: (path: string) => void;
563
+ /** Dismiss the form-level banner. */
564
+ dismissFormError: () => void;
565
+ /** Form-context getter (mirrors `options.formContext()`). */
566
+ formContext: ComputedRef<TFormContext | undefined>;
567
+ /** Internal change-dispatcher used by `<AsField>` and structured components. */
568
+ handleChange: (type: TAsChangeType, path: string, value: unknown) => void;
569
+ }
570
+ /**
571
+ * Composable backing `<AsForm>`. Owns the entire form state machine —
572
+ * data container, internal validator, external-error dismissal, action
573
+ * routing, change merging, descendant counts, auto-open, and all
574
+ * provide/inject wiring. Customers building a custom form root can
575
+ * call this directly and render their own `<form>` template.
576
+ *
577
+ * MUST be called from a component's `<script setup>` (it issues
578
+ * `provide()` calls that need an active component instance).
579
+ */
580
+ declare function useAsForm<TFormData = unknown, TFormContext = unknown>(options: UseAsFormOptions<TFormData, TFormContext>): UseAsFormReturn<TFormData, TFormContext>;
581
+ //#endregion
582
+ //#region src/composables/use-as-external-errors.d.ts
583
+ /**
584
+ * Source of externally-supplied (server) errors. Reading this getter
585
+ * inside a Vue reactive scope subscribes the composable to identity
586
+ * changes — when the source returns a *different* object reference
587
+ * (typically a fresh server response), all locally-applied dismissals
588
+ * reset automatically.
589
+ */
590
+ interface UseAsExternalErrorsOptions {
591
+ source: () => Record<string, string | undefined> | undefined;
592
+ }
593
+ interface UseAsExternalErrorsReturn {
594
+ /**
595
+ * Errors map after leaf-path dismissals applied. The `__form` key is
596
+ * always omitted — render form-level errors via `formError`. Returns
597
+ * `undefined` when the source itself is `undefined` (no errors at all),
598
+ * so consumers can preserve the original "errors prop unset" semantics.
599
+ */
600
+ effective: ComputedRef<Record<string, string | undefined> | undefined>;
601
+ /** Top-level `__form` error (post banner-dismissal). `undefined` while dismissed or absent. */
602
+ formError: ComputedRef<string | undefined>;
603
+ /** Whether the form-level banner is currently dismissed. */
604
+ isFormDismissed: ComputedRef<boolean>;
605
+ /** Mark a leaf-field path as dismissed locally. Idempotent. */
606
+ dismissAt: (path: string) => void;
607
+ /** Dismiss the form-level banner. */
608
+ dismissForm: () => void;
609
+ /** Reset all dismissals (rarely needed; identity-change does this for you). */
610
+ reset: () => void;
611
+ }
612
+ /**
613
+ * Local dismissal state for externally-supplied errors.
614
+ *
615
+ * - `dismissAt(path)` hides a leaf error until either the user un-dismisses
616
+ * it or a *fresh* errors object arrives (new identity).
617
+ * - `dismissForm()` hides the `__form` banner. Same identity-reset rule, but
618
+ * never cleared by leaf calls.
619
+ * - In-place mutation of the source object does NOT reset dismissals; only
620
+ * identity changes do. A fresh response (`errors.value = { ... }`) re-arms
621
+ * everything, while in-place tweaks (rare) deliberately preserve them.
622
+ *
623
+ * The composable is pure — it does NOT call `provide()`. The owning form
624
+ * composable wires `dismissAt` into the form's inject contract.
625
+ */
626
+ declare function useAsExternalErrors(options: UseAsExternalErrorsOptions): UseAsExternalErrorsReturn;
627
+ //#endregion
628
+ //#region src/composables/use-as-array.d.ts
629
+ interface UseAsArrayReturn {
630
+ arrayValue: ComputedRef<unknown[]>;
631
+ itemKeys: string[];
632
+ isUnion: boolean;
633
+ unionVariants: FormUnionVariant[];
634
+ isOptional: boolean;
635
+ isEmpty: ComputedRef<boolean>;
636
+ getItemField: (index: number, name?: string) => FormFieldDef;
637
+ addItem: (variantIndex?: number) => void;
638
+ removeItem: (index: number) => void;
639
+ clear: () => void;
640
+ canAdd: ComputedRef<boolean>;
641
+ canRemove: ComputedRef<boolean>;
642
+ }
643
+ /**
644
+ * Composable for managing array field state.
645
+ *
646
+ * Manages stable keys, add/remove with constraints, and item field resolution.
647
+ * Union item types are handled transparently — AsUnion manages variant state locally.
648
+ * Used by the default `AsArray` component and available for custom array components.
649
+ */
650
+ declare function useAsArray(field: FormArrayFieldDef, disabled?: ComputedRef<boolean>): UseAsArrayReturn;
651
+ //#endregion
652
+ //#region src/composables/use-as-tuple.d.ts
653
+ interface UseAsTupleReturn {
654
+ itemFields: FormFieldDef[];
655
+ positionLabeled: boolean[];
656
+ isOptional: boolean;
657
+ isEmpty: ComputedRef<boolean>;
658
+ clear: () => void;
659
+ fillMissing: () => void;
660
+ }
661
+ /** Composable for managing tuple field state. Fixed-length, position-typed; auto-fills missing positions on mount unless optional. */
662
+ declare function useAsTuple(field: FormTupleFieldDef): UseAsTupleReturn;
663
+ //#endregion
664
+ //#region src/composables/use-as-union.d.ts
665
+ interface UseAsUnionReturn {
666
+ unionField: ComputedRef<FormUnionFieldDef | undefined>;
667
+ hasMultipleVariants: ComputedRef<boolean>;
668
+ localUnionIndex: Ref<number>;
669
+ innerField: ComputedRef<FormFieldDef | undefined>;
670
+ changeVariant: (newIndex: number) => void;
671
+ optionalEnabled: ComputedRef<boolean>;
672
+ }
673
+ /** Composable for union field state. Switching variants stashes per-index data so toggling back restores user's work instead of fresh defaults. */
674
+ declare function useAsUnion(props: TAsComponentProps): UseAsUnionReturn;
675
+ //#endregion
676
+ //#region src/composables/use-form-context.d.ts
677
+ /**
678
+ * Consume and clear the union context injection.
679
+ *
680
+ * Structured components (object, tuple, array, field-shell) call this to
681
+ * read the union context provided by `AsUnion` and immediately clear it
682
+ * so nested children don't inherit it.
683
+ */
684
+ declare function useAsUnionVariant(): TAsUnionContext | undefined;
685
+ /** Split a label into base + optional `#N` suffix for two-part rendering. */
686
+ declare function formatIndexedLabelParts(label: string | undefined, arrayIndex: number | undefined): {
687
+ base: string;
688
+ suffix?: string;
689
+ } | undefined;
690
+ //#endregion
691
+ //#region src/composables/use-as-value-help.d.ts
692
+ interface UseAsValueHelpOptions {
693
+ info: ValueHelpInfo;
694
+ model: {
695
+ value: unknown;
696
+ };
697
+ onBlur: () => void;
698
+ }
699
+ type UseAsValueHelpStatus = "loading" | "ready" | "error";
700
+ interface UseAsValueHelpReturn {
701
+ resolved: ShallowRef<ResolvedValueHelp | null>;
702
+ status: Ref<UseAsValueHelpStatus>;
703
+ searchText: Ref<string>;
704
+ results: ShallowRef<Record<string, unknown>[]>;
705
+ searching: Ref<boolean>;
706
+ labelIsFkValue: ComputedRef<boolean>;
707
+ kickoff: () => Promise<void>;
708
+ selectItem: (item: Record<string, unknown>) => void;
709
+ clear: () => void;
710
+ }
711
+ declare function useAsValueHelp(options: UseAsValueHelpOptions): UseAsValueHelpReturn;
712
+ //#endregion
713
+ //#region src/composables/use-as-dropdown.d.ts
714
+ declare function useAsDropdown(containerRef: Ref<HTMLElement | null>): {
715
+ isOpen: Ref<boolean, boolean>;
716
+ toggle: () => void;
717
+ close: () => void;
718
+ select: (callback: () => void) => void;
719
+ };
720
+ //#endregion
721
+ //#region src/composables/use-as-nested-sections-store.d.ts
722
+ /**
723
+ * Reactive open/closed registry for collapsible object sections rendered
724
+ * by `AsObject`. Provided once per `<AsForm>` so the entire form shares a
725
+ * single store; consumers (page chrome, devtools, dialogs) can `inject`
726
+ * the store via `useAsNestedSectionsStore()` to drive Expand-all /
727
+ * Collapse-all UI without prop drilling.
728
+ *
729
+ * **Default state is closed.** IDs only enter `open` when explicitly
730
+ * expanded (user click, native `<details>` toggle, programmatic
731
+ * `setOpen` / `expandAll`). The native `<details>` toggle event syncs
732
+ * back via `setOpen(id, open)` (idempotent, so browser find-in-page
733
+ * auto-opens don't fight the store).
734
+ */
735
+ interface AsNestedSectionsStore {
736
+ open: Ref<Set<string>>;
737
+ register: (id: string) => void;
738
+ unregister: (id: string) => void;
739
+ toggle: (id: string) => void;
740
+ setOpen: (id: string, open: boolean) => void;
741
+ isOpen: (id: string) => boolean;
742
+ expandAll: () => void;
743
+ collapseAll: () => void;
744
+ allOpen: () => boolean;
745
+ }
746
+ /**
747
+ * Create and provide a `AsNestedSectionsStore` to the current Vue subtree.
748
+ * Called automatically by `<AsForm>`, but exposed for cases where you
749
+ * want to scope a separate store (e.g. multiple independent forms in one
750
+ * page that should keep their open/closed state independent, or to drive
751
+ * page-level Expand-all / Collapse-all UI from above the form).
752
+ */
753
+ declare function provideAsNestedSectionsStore(): AsNestedSectionsStore;
754
+ /**
755
+ * Inject the nested-sections store provided by an ancestor `<AsForm>`
756
+ * (or by an explicit `provideAsNestedSectionsStore()` call). Returns
757
+ * `undefined` if no store is in scope.
758
+ */
759
+ declare function useAsNestedSectionsStore(): AsNestedSectionsStore | undefined;
760
+ //#endregion
761
+ //#region src/composables/focus-after-toggle.d.ts
762
+ /** Run an action, then focus the first focusable input descendant of `scope`. */
763
+ declare function focusFirstAfter(action: () => void, scope: () => HTMLElement | null | undefined, ticks?: number): Promise<void>;
764
+ /**
765
+ * Run an action, then focus the first focusable input that wasn't present
766
+ * before the action. Used by array Add buttons so the user lands on the
767
+ * just-added row's first input regardless of how many items already exist.
768
+ * Falls back to first focusable when nothing existed before (the typical
769
+ * "enable optional + add first item" flow).
770
+ */
771
+ declare function focusNewFocusableAfter(action: () => void, scope: () => HTMLElement | null | undefined, ticks?: number): Promise<void>;
772
+ /** Sugar over `focusFirstAfter` scoped to a template ref. */
773
+ declare function useAsFocusFirstAfter(onToggleOptional?: (enabled: boolean) => void): {
774
+ rootRef: Ref<HTMLElement | null>;
775
+ runAndFocus: (action: () => void, ticks?: number) => void;
776
+ runAndFocusNew: (action: () => void, ticks?: number) => void;
777
+ enableOptional: () => void;
778
+ };
779
+ //#endregion
780
+ //#region src/composables/use-as-optional-add-flow.d.ts
781
+ /**
782
+ * Options for `useAsOptionalAddFlow`.
783
+ *
784
+ * The composable consolidates the "toggle optional → register with the
785
+ * nested-sections store → focus first new field" choreography that
786
+ * structured-field defaults (AsObject, AsArray, AsTuple, AsUnion) repeat
787
+ * every time the user clicks an empty-state Add affordance, an Add Item
788
+ * button, or a variant picker.
789
+ */
790
+ interface UseAsOptionalAddFlowOptions {
791
+ /**
792
+ * Absolute dotted path to the field — used as the nested-sections-store
793
+ * key. Read via a getter so the composable always reads the latest value
794
+ * (the path can change when the field is rendered inside a union and the
795
+ * variant switches).
796
+ */
797
+ path: () => string | undefined;
798
+ }
799
+ interface UseAsOptionalAddFlowReturn {
800
+ /**
801
+ * Wrap a user-supplied action so that running it also expands the
802
+ * containing section in the nested-sections store. Pass the wrapped
803
+ * action to `AsCollapsible#runAndFocusNew` (which owns its own focus
804
+ * scope) so the focus query lands on the freshly mounted subtree.
805
+ *
806
+ * The wrapper is a no-op for the store-register step when no store is
807
+ * provided in scope (e.g. a custom default mounted standalone) — focus
808
+ * still happens via the host's `runAndFocusNew`.
809
+ */
810
+ composeAction: (action: () => void) => () => void;
811
+ /**
812
+ * Sugar for the case where the call site does not have an
813
+ * `AsCollapsible` to delegate focus to (e.g. AsUnion's empty-state
814
+ * picker, which mounts its own `<div>`). Wraps the action with
815
+ * store-open registration, then runs it inside `focusNewFocusableAfter`.
816
+ *
817
+ * Returns the same Promise `focusNewFocusableAfter` returns so callers
818
+ * can `await` if they need to.
819
+ */
820
+ runAndFocusNew: (scope: () => HTMLElement | null | undefined, action: () => void, ticks?: number) => Promise<void>;
821
+ }
822
+ /**
823
+ * Choreography composable for "enable-optional + add + focus-first-new"
824
+ * flows. The four built-in structured-field defaults consume it; custom
825
+ * implementations of object/array/tuple/union components can use it too
826
+ * to get the same UX (smooth focus handoff after an empty-state click)
827
+ * without re-implementing the choreography.
828
+ *
829
+ * Pairs with:
830
+ * - {@link useAsFocusFirstAfter} — focus mechanics (used by AsCollapsible)
831
+ * - {@link useAsNestedSectionsStore} — open/closed state registry
832
+ *
833
+ * Typical use, inside an `as-object.vue` swap component:
834
+ * ```ts
835
+ * const { composeAction } = useAsOptionalAddFlow({ path: () => props.path });
836
+ * function handleAddData() {
837
+ * collapsibleRef.value?.runAndFocusNew(
838
+ * composeAction(() => props.onToggleOptional?.(true)),
839
+ * 2,
840
+ * );
841
+ * }
842
+ * ```
843
+ */
844
+ declare function useAsOptionalAddFlow(options: UseAsOptionalAddFlowOptions): UseAsOptionalAddFlowReturn;
845
+ //#endregion
846
+ //#region src/composables/use-as-tri-state-checkbox.d.ts
847
+ /**
848
+ * Options for `useAsTriStateCheckbox`.
849
+ *
850
+ * Consolidates the "checked / unchecked / indeterminate" mechanics for
851
+ * boolean fields whose model can be `undefined` (optional booleans, or
852
+ * checkboxes that round-trip from a SQL NULL). HTML5's `indeterminate`
853
+ * is a property on the DOM element — not a reflectable attribute — so
854
+ * the composable wires it via a `watchEffect`.
855
+ */
856
+ interface UseAsTriStateCheckboxOptions {
857
+ /**
858
+ * Reactive getter for the current model value. `undefined` renders the
859
+ * indeterminate look; `true` / `false` render checked / unchecked.
860
+ */
861
+ modelValue: () => boolean | undefined;
862
+ /**
863
+ * Called when the user toggles the checkbox. Receives the new value as
864
+ * read off the input's `checked` property after the click.
865
+ */
866
+ onCommit: (value: boolean) => void;
867
+ }
868
+ interface UseAsTriStateCheckboxReturn {
869
+ /**
870
+ * Bind to `<input type="checkbox" :checked>`. Equivalent to
871
+ * `modelValue() === true`.
872
+ */
873
+ checked: ComputedRef<boolean>;
874
+ /**
875
+ * `true` when the model is `undefined` — render the indeterminate
876
+ * look (the composable also wires the DOM property via `watchEffect`).
877
+ */
878
+ indeterminate: ComputedRef<boolean>;
879
+ /**
880
+ * Template ref for the `<input>` element. The composable observes it
881
+ * and writes the `indeterminate` property whenever the model becomes
882
+ * `undefined`.
883
+ */
884
+ inputRef: Ref<HTMLInputElement | null>;
885
+ /** Bind to `@change`. Reads `e.target.checked` and forwards to `onCommit`. */
886
+ onChange: (e: Event) => void;
887
+ }
888
+ /**
889
+ * Tri-state checkbox helper. The visible state is derived from the
890
+ * model: `true` checked, `false` unchecked, `undefined` indeterminate.
891
+ * Clicking commits a boolean — never `undefined` — because browsers do
892
+ * not emit a "tri-state click". The "back to undefined" path stays a
893
+ * separate optional-clear affordance owned by the host component.
894
+ *
895
+ * Use this composable in a custom checkbox swap component to inherit the
896
+ * same a11y / DOM-sync behaviour as the built-in `AsCheckbox` without
897
+ * re-implementing the `watchEffect` plumbing or remembering that
898
+ * `indeterminate` is a property, not an attribute.
899
+ */
900
+ declare function useAsTriStateCheckbox(options: UseAsTriStateCheckboxOptions): UseAsTriStateCheckboxReturn;
901
+ //#endregion
902
+ //#region src/composables/use-as-locale.d.ts
903
+ declare function provideAsLocale(getter: () => string | undefined): void;
904
+ interface UseAsLocaleReturn {
905
+ /** Resolved locale; `undefined` when no provider is present (runtime locale). */
906
+ locale: ComputedRef<string | undefined>;
907
+ }
908
+ declare function useAsLocale(): UseAsLocaleReturn;
909
+ //#endregion
910
+ //#region src/composables/use-as-decimal.d.ts
911
+ interface UseAsDecimalOptions {
912
+ /** Read the current value. Storage shape is preserved on commit. */
913
+ modelValue: () => string | number | null | undefined;
914
+ /**
915
+ * Effective display + edit scale. Composables truncate user-typed values
916
+ * to this so a paste of "10.99" into a JPY field doesn't propagate the
917
+ * lost ".99". Resolution lives at AsField — see TAsComponentProps.scale.
918
+ */
919
+ scale?: () => number | undefined;
920
+ /**
921
+ * Storage cap (DB column scale). Outgoing strings are padded to this
922
+ * regardless of `scale` — display can be tighter than storage. When
923
+ * absent, falls back to `scale`.
924
+ */
925
+ storageScale?: () => number | undefined;
926
+ /** Locale override; defaults to `useAsLocale()` then runtime locale. */
927
+ locale?: () => string | undefined;
928
+ /** Commit handler — receives the new value in the same shape as `modelValue()`. */
929
+ onCommit: (value: string | number | null) => void;
930
+ }
931
+ interface UseAsDecimalReturn {
932
+ /** Effective display + edit scale. Defaults to 2 when neither scale nor storageScale provided. */
933
+ scale: ComputedRef<number>;
934
+ /** Storage cap (always populated; falls back to effective scale, then 2). */
935
+ storageScale: ComputedRef<number>;
936
+ decimalSeparator: ComputedRef<string>;
937
+ thousandsSeparator: ComputedRef<string>;
938
+ /** Single-input renderers: locale-formatted decimal "1,234.50" / "1 234,50". */
939
+ displayValue: ComputedRef<string>;
940
+ /** Canonical decimal "1234.50": no thousands, "." separator, padded to effective scale. */
941
+ rawValue: ComputedRef<string>;
942
+ /** Split renderers: integer is grouped per locale for display. */
943
+ parts: ComputedRef<{
944
+ sign: "" | "-";
945
+ integer: string;
946
+ decimal: string;
947
+ }>;
948
+ /** Renderer received a complete typed value (single-input swap). */
949
+ setFromInput: (raw: string) => void;
950
+ /** Renderer captured the two halves separately (default two-input SFC). */
951
+ setFromParts: (sign: "" | "-", integer: string, decimal: string) => void;
952
+ }
953
+ /**
954
+ * Reactive composable for decimal-typed inputs (the `AsDecimal` SFC and
955
+ * customer swaps built against `TAsComponentProps`).
956
+ *
957
+ * Currency-agnostic: the SFC owns prefix/suffix render concerns and
958
+ * resolves the effective scale via the `scale` prop set by AsField. This
959
+ * composable just operates on the model with the scale given to it.
960
+ *
961
+ * Storage shape is preserved on commit — string `modelValue` commits a
962
+ * string padded to `storageScale`; number `modelValue` commits a number.
963
+ * A change to the effective `scale` getter that shrinks it below the
964
+ * model's actual precision triggers a re-round + re-commit (the same
965
+ * "currency-change" behaviour as before).
966
+ */
967
+ declare function useAsDecimal(opts: UseAsDecimalOptions): UseAsDecimalReturn;
968
+ //#endregion
969
+ //#region src/composables/use-as-number.d.ts
970
+ interface UseAsNumberOptions {
971
+ /** Read the current value. May be a string when authored externally; commit is always a `number` or `null`. */
972
+ modelValue: () => string | number | null | undefined;
973
+ /** Locale override; defaults to `useAsLocale()` then runtime locale. */
974
+ locale?: () => string | undefined;
975
+ /** Commit handler — receives a parsed `number`, or `null` for empty input. */
976
+ onCommit: (value: number | null) => void;
977
+ }
978
+ interface UseAsNumberReturn {
979
+ decimalSeparator: ComputedRef<string>;
980
+ /**
981
+ * Single-input renderers: raw model value with the locale decimal
982
+ * separator swap. No Intl grouping, no padding, no truncation — numbers
983
+ * aren't precision-critical the way decimals are.
984
+ */
985
+ displayValue: ComputedRef<string>;
986
+ /** Canonical decimal ("." separator). Verbatim from the model — no scale enforcement. */
987
+ rawValue: ComputedRef<string>;
988
+ /** Renderer received a complete typed value. */
989
+ setFromInput: (raw: string) => void;
990
+ }
991
+ /**
992
+ * Reactive composable that powers the default `AsNumber` SFC. Single-
993
+ * input shape — currency-agnostic, scale-agnostic, just a plain number
994
+ * with optional prefix/suffix chrome owned by the SFC.
995
+ *
996
+ * Commit shape is always a `number` (or `null` for empty input).
997
+ * atscript `number` fields are primitive `number` in the model — there
998
+ * is no precision-preservation reason to ship a string the way decimals
999
+ * do. The SFC owns prefix/suffix render concerns; this composable only
1000
+ * knows about the value.
1001
+ */
1002
+ declare function useAsNumber(opts: UseAsNumberOptions): UseAsNumberReturn;
1003
+ //#endregion
1004
+ //#region src/composables/use-as-dual-input.d.ts
1005
+ /**
1006
+ * Keyboard plumbing for the bank-UX two-input pattern (integer + decimal
1007
+ * halves joined by a separator pill). Extracted from the original
1008
+ * AsAmount SFC so AsDecimal and any customer two-input renderer can
1009
+ * share the same arrow-bridge / digit-overwrite / paste-split behaviour.
1010
+ *
1011
+ * This composable is render-agnostic — the SFC owns the layout, the
1012
+ * shell chrome and the value model wiring. The composable just exposes
1013
+ * the input refs, edit-state, focus handlers and event handlers wired
1014
+ * to a `setFromParts` / `setFromInput` callback pair.
1015
+ */
1016
+ interface UseAsDualInputOptions {
1017
+ /** Effective scale (max digits in the decimal half). 0 → no decimal half. */
1018
+ scale: () => number;
1019
+ /** Locale-aware decimal separator (used for bridge-key detection). */
1020
+ decimalSeparator: () => string;
1021
+ /** Read the current parts. The composable owns NO model state. */
1022
+ parts: () => {
1023
+ sign: "" | "-";
1024
+ integer: string;
1025
+ decimal: string;
1026
+ };
1027
+ /** Read the canonical "X.YZ" string — used by paste/bridge to know current state. */
1028
+ rawValue: () => string;
1029
+ /** Commit a fresh split. Pure callback into the parent's state machine. */
1030
+ setFromParts: (sign: "" | "-", integer: string, decimal: string) => void;
1031
+ /** Commit a raw typed string (for paste). */
1032
+ setFromInput: (raw: string) => void;
1033
+ /** Called from `onBlurAll` after focus leaves both inputs. */
1034
+ onBlur?: () => void;
1035
+ }
1036
+ interface UseAsDualInputReturn {
1037
+ integerInput: Ref<HTMLInputElement | null>;
1038
+ decimalInput: Ref<HTMLInputElement | null>;
1039
+ /** Display string for the integer half — un-grouped while focused, grouped on blur. */
1040
+ integerDisplay: ComputedRef<string>;
1041
+ /** Display string for the decimal half — owns the suppression rules. */
1042
+ decimalDisplay: ComputedRef<string>;
1043
+ /** True while either input has focus. */
1044
+ focusActive: Ref<boolean>;
1045
+ onIntegerFocus: (e?: FocusEvent) => void;
1046
+ onDecimalFocus: (e?: FocusEvent) => void;
1047
+ onBlurAll: (e: FocusEvent) => void;
1048
+ onIntegerInput: (e: Event) => void;
1049
+ onIntegerKeydown: (e: KeyboardEvent) => void;
1050
+ onIntegerPaste: (e: ClipboardEvent) => void;
1051
+ onDecimalInput: (e: Event) => void;
1052
+ onDecimalKeydown: (e: KeyboardEvent) => void;
1053
+ onDecimalPaste: (e: ClipboardEvent) => void;
1054
+ }
1055
+ declare function useAsDualInput(opts: UseAsDualInputOptions): UseAsDualInputReturn;
1056
+ //#endregion
1057
+ //#region src/composables/use-as-date.d.ts
1058
+ /**
1059
+ * Storage convention — atscript marks date-bearing fields with the
1060
+ * `number.timestamp` primitive (epoch-ms numbers). The default form
1061
+ * components mirror the cell-side rule: accept `Date | number | string`
1062
+ * for read, commit back as `number` (epoch-ms) when storage is numeric,
1063
+ * else commit the raw ISO string.
1064
+ *
1065
+ * `<input type="date">` uses `YYYY-MM-DD`,
1066
+ * `<input type="datetime-local">` uses `YYYY-MM-DDTHH:mm`,
1067
+ * `<input type="time">` uses `HH:mm`. The HTML5 spec treats these as
1068
+ * locale-agnostic strings — we must produce them deterministically.
1069
+ */
1070
+ type ModelValue = number | string | Date | null | undefined;
1071
+ interface UseAsDateOptions {
1072
+ modelValue: () => ModelValue;
1073
+ /** Variant: `'date'` (default), `'datetime'`, `'time'`. Drives both parse and serialize. */
1074
+ kind: "date" | "datetime" | "time";
1075
+ /** Commit the parsed value. Numeric epoch-ms when the previous value was numeric, ISO string otherwise. `null` clears. */
1076
+ onCommit: (value: number | string | null) => void;
1077
+ }
1078
+ interface UseAsDateReturn {
1079
+ /** HTML5 input type — `'date' | 'datetime-local' | 'time'`. */
1080
+ inputType: "date" | "datetime-local" | "time";
1081
+ /** Bind to `<input :value>`. Empty string when no model. */
1082
+ displayValue: ComputedRef<string>;
1083
+ /** Bind to `@change` / `@input`. Parses the HTML5 string into the storage type. */
1084
+ setFromInput: (raw: string) => void;
1085
+ }
1086
+ /**
1087
+ * Composable backing `AsDate` / `AsDatetime` / `AsTime`. Pick the variant
1088
+ * via `kind`. Conversion direction:
1089
+ *
1090
+ * - `'date'`: epoch-ms ↔ `YYYY-MM-DD` (local TZ).
1091
+ * Empty input commits `null`. If previous value was a `string`,
1092
+ * commits a string (`YYYY-MM-DD`); otherwise commits epoch-ms (UTC
1093
+ * midnight on the picked date in local TZ — same as `new Date(str)`).
1094
+ * - `'datetime'`: epoch-ms ↔ `YYYY-MM-DDTHH:mm` (local TZ).
1095
+ * - `'time'`: prev-string ↔ `HH:mm`. Numeric storage isn't meaningful
1096
+ * for naked time-of-day, so we commit a string.
1097
+ */
1098
+ declare function useAsDate(opts: UseAsDateOptions): UseAsDateReturn;
1099
+ //#endregion
1100
+ //#region src/composables/use-as-path.d.ts
1101
+ interface UseAsPathReturn {
1102
+ path: ComputedRef<string>;
1103
+ }
1104
+ /**
1105
+ * Reactive read-only access to the absolute dotted path prefix at the
1106
+ * current point in the `<AsForm>` tree. Returns `''` when called outside
1107
+ * a form.
1108
+ */
1109
+ declare function useAsPath(): UseAsPathReturn;
1110
+ //#endregion
1111
+ //#region src/composables/use-as-type-map.d.ts
1112
+ interface UseAsTypeMapReturn {
1113
+ types: ComputedRef<Record<string, Component>>;
1114
+ }
1115
+ /**
1116
+ * Reactive read-only access to the type-to-component map provided by the
1117
+ * nearest `<AsForm>`. Returns an empty map when called outside a form so
1118
+ * call sites do not need a null-check.
1119
+ */
1120
+ declare function useAsTypeMap(): UseAsTypeMapReturn;
1121
+ //#endregion
1122
+ //#region src/composables/use-as-data.d.ts
1123
+ interface UseAsDataReturn {
1124
+ /** Domain data (the unwrapped inner value of the form's `{ value }` container). */
1125
+ rootData: ComputedRef<unknown>;
1126
+ /** Read the value at an absolute dotted path inside the form. */
1127
+ getValueAt: (path: string) => ComputedRef<unknown>;
1128
+ /** Read a sibling field's value relative to the current `useAsPath()` prefix. */
1129
+ siblingValue: <T = unknown>(name: string) => ComputedRef<T | undefined>;
1130
+ }
1131
+ /**
1132
+ * Reactive read-only access to form data at any point in the
1133
+ * `<AsForm>` tree. Outside a form, all readers return `undefined`.
1134
+ *
1135
+ * Call sites get a `ComputedRef` so they can compose it directly with
1136
+ * other reactive primitives without an extra `computed()` wrapper.
1137
+ */
1138
+ declare function useAsData(): UseAsDataReturn;
1139
+ //#endregion
1140
+ //#region src/composables/use-as-error-dismiss.d.ts
1141
+ /**
1142
+ * Imperative dismissal of an external (server-supplied) error at a given
1143
+ * absolute path. Calling this is equivalent to the user editing that
1144
+ * field — useful for custom field components that commit a value through
1145
+ * a side-channel (e.g. a date picker dialog) and want to hide the
1146
+ * server's error before the next round-trip.
1147
+ */
1148
+ type AsErrorDismiss = (path: string) => void;
1149
+ /**
1150
+ * Returns the `dismissExternalAt` callback provided by the nearest
1151
+ * ancestor `<AsForm>`. Outside a form the result is a no-op so calling
1152
+ * it from a leaf component does not throw.
1153
+ */
1154
+ declare function useAsErrorDismiss(): AsErrorDismiss;
1155
+ //#endregion
1156
+ //#region src/components/as-form.vue.d.ts
1157
+ interface Props<TF, TC> {
1158
+ def: FormDef;
1159
+ formData?: TF;
1160
+ formContext?: TC;
1161
+ firstValidation?: TFormState["firstValidation"];
1162
+ components?: Record<string, Component<TAsComponentProps>>;
1163
+ /**
1164
+ * Type-to-component map for field rendering. Maps field types to Vue components.
1165
+ * Must include entries for all built-in field types. Use `createDefaultTypes()`
1166
+ * for a pre-filled map, or supply your own.
1167
+ */
1168
+ types: TAsTypeComponents;
1169
+ errors?: Record<string, string | undefined>;
1170
+ /**
1171
+ * Per-form client factory override. Creates `Client` instances from URL paths
1172
+ * for FK value-help pickers inside this form. Falls back to the app-wide
1173
+ * default (`setDefaultClientFactory`) and then to the built-in `new Client(url)`
1174
+ * factory when unset.
1175
+ */
1176
+ clientFactory?: ClientFactory;
1177
+ /**
1178
+ * Suppress the root field's title rendering. Use when the form is mounted
1179
+ * inside a chrome that already shows the form's `@meta.label` (e.g. a
1180
+ * dialog header). Nested fields keep their own headings.
1181
+ */
1182
+ hideRootTitle?: boolean;
1183
+ /**
1184
+ * Suppress the default submit button. Use when the host chrome owns the
1185
+ * submit affordance (e.g. a dialog footer with its own submit button
1186
+ * wired via HTML5 `<button form="...">`). Vue 3 treats an empty
1187
+ * `<template #form.submit />` as "slot not provided" and falls back to
1188
+ * the default button — this prop is the explicit way to skip it.
1189
+ */
1190
+ hideSubmit?: boolean;
1191
+ /**
1192
+ * When true, freezes the form: the body becomes `inert` (blocks pointer
1193
+ * events + keyboard focus) and a loading overlay paints over the entire
1194
+ * form area. Used by `<AsWfForm>` to lock interaction during a server
1195
+ * round-trip so the user can't edit a field whose response is racing in.
1196
+ * Visual is shared with `<AsTable>`'s query overlay via vunor
1197
+ * `inner-loading`.
1198
+ */
1199
+ loading?: boolean;
1200
+ /**
1201
+ * Enable change tracking. When set, the form captures a deep-clone baseline
1202
+ * of its data and surfaces both a changed-fields list and an `@atscript/db`
1203
+ * patch object. The tracking surface (`isDirty` / `changes` / `getPatch` /
1204
+ * `getChanges`) is spread into every slot AND exposed on the component
1205
+ * instance (template ref → `asForm.value.getPatch()`); descendants read it
1206
+ * with `useAsFormPatch()`. Off by default — zero overhead when unset.
1207
+ */
1208
+ trackChanges?: boolean;
1209
+ }
1210
+ 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<{
1211
+ props: vue.PublicProps & __VLS_PrettifyLocal<Props<TFormData, TFormContext> & {
1212
+ onError?: ((errors: {
1213
+ path: string;
1214
+ message: string;
1215
+ }[]) => any) | undefined;
1216
+ onAction?: ((name: string, data: TFormData) => any) | undefined;
1217
+ onSubmit?: ((data: TFormData) => any) | undefined;
1218
+ "onUnsupported-action"?: ((name: string, data: TFormData) => any) | undefined;
1219
+ onChange?: ((type: TAsChangeType, path: string, value: unknown, formData: TFormData) => any) | undefined;
1220
+ }> & (typeof globalThis extends {
1221
+ __VLS_PROPS_FALLBACK: infer P;
1222
+ } ? P : {});
1223
+ expose: (exposed: vue.ShallowUnwrapRef<{
1224
+ submit: () => void;
1225
+ reset: () => Promise<void>; /** True when `track-changes` is on AND data differs from baseline. */
1226
+ readonly isDirty: boolean; /** Revert-aware per-field change list (empty when tracking is off). */
1227
+ readonly changes: FormFieldChange[]; /** Build the `@atscript/db` patch object on demand (`{}` when off). */
1228
+ getPatch: ((opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>) | (() => {}); /** Build the per-field change list on demand (`[]` when off). */
1229
+ getChanges: () => FormFieldChange[];
1230
+ /**
1231
+ * Per-field dirty predicate — `true` when the field at `path` differs from
1232
+ * the baseline (`false` for every path when tracking is off).
1233
+ */
1234
+ isDirtyPath: (path: string) => boolean; /** Re-baseline to current data after a successful save (no-op when off). */
1235
+ rebase: () => void;
1236
+ /**
1237
+ * 3-way rebase onto a fresh upstream snapshot (sets baseline := upstream,
1238
+ * reapplies the local diff). Pure no-op returning empty when tracking is off
1239
+ * — NO side effects, mirroring `rebase`/`getPatch`.
1240
+ */
1241
+ rebaseOnto: (upstream: Record<string, unknown>, opts?: _atscript_ui0.FormRebaseOptions) => RebaseOntoResult;
1242
+ }>) => void;
1243
+ attrs: any;
1244
+ slots: {
1245
+ 'form.header'?: (props: {
1246
+ title: string | undefined;
1247
+ description: string | undefined;
1248
+ data: TFormData;
1249
+ errors: Record<string, string | undefined> | undefined;
1250
+ formError: string | undefined;
1251
+ disabled: boolean;
1252
+ loading: boolean;
1253
+ submitText: string;
1254
+ submit: () => void;
1255
+ reset: () => Promise<void>;
1256
+ clearErrors: () => void;
1257
+ setErrors: (errors: Record<string, string>) => void;
1258
+ dismissError: (path: string) => void;
1259
+ dismissFormError: () => void;
1260
+ formContext: TFormContext | undefined;
1261
+ isDirty: boolean;
1262
+ changes: readonly FormFieldChange[];
1263
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1264
+ getChanges: () => FormFieldChange[];
1265
+ isDirtyPath: (path: string) => boolean;
1266
+ }) => any;
1267
+ } & {
1268
+ 'form.before'?: (props: {
1269
+ title: string | undefined;
1270
+ description: string | undefined;
1271
+ data: TFormData;
1272
+ errors: Record<string, string | undefined> | undefined;
1273
+ formError: string | undefined;
1274
+ disabled: boolean;
1275
+ loading: boolean;
1276
+ submitText: string;
1277
+ submit: () => void;
1278
+ reset: () => Promise<void>;
1279
+ clearErrors: () => void;
1280
+ setErrors: (errors: Record<string, string>) => void;
1281
+ dismissError: (path: string) => void;
1282
+ dismissFormError: () => void;
1283
+ formContext: TFormContext | undefined;
1284
+ isDirty: boolean;
1285
+ changes: readonly FormFieldChange[];
1286
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1287
+ getChanges: () => FormFieldChange[];
1288
+ isDirtyPath: (path: string) => boolean;
1289
+ }) => any;
1290
+ } & {
1291
+ 'form.after'?: (props: {
1292
+ title: string | undefined;
1293
+ description: string | undefined;
1294
+ data: TFormData;
1295
+ errors: Record<string, string | undefined> | undefined;
1296
+ formError: string | undefined;
1297
+ disabled: boolean;
1298
+ loading: boolean;
1299
+ submitText: string;
1300
+ submit: () => void;
1301
+ reset: () => Promise<void>;
1302
+ clearErrors: () => void;
1303
+ setErrors: (errors: Record<string, string>) => void;
1304
+ dismissError: (path: string) => void;
1305
+ dismissFormError: () => void;
1306
+ formContext: TFormContext | undefined;
1307
+ isDirty: boolean;
1308
+ changes: readonly FormFieldChange[];
1309
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1310
+ getChanges: () => FormFieldChange[];
1311
+ isDirtyPath: (path: string) => boolean;
1312
+ }) => any;
1313
+ } & {
1314
+ 'form.error'?: (props: {
1315
+ message: string;
1316
+ dismiss: () => void;
1317
+ title: string | undefined;
1318
+ description: string | undefined;
1319
+ data: TFormData;
1320
+ errors: Record<string, string | undefined> | undefined;
1321
+ formError: string | undefined;
1322
+ disabled: boolean;
1323
+ loading: boolean;
1324
+ submitText: string;
1325
+ submit: () => void;
1326
+ reset: () => Promise<void>;
1327
+ clearErrors: () => void;
1328
+ setErrors: (errors: Record<string, string>) => void;
1329
+ dismissError: (path: string) => void;
1330
+ dismissFormError: () => void;
1331
+ formContext: TFormContext | undefined;
1332
+ isDirty: boolean;
1333
+ changes: readonly FormFieldChange[];
1334
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1335
+ getChanges: () => FormFieldChange[];
1336
+ isDirtyPath: (path: string) => boolean;
1337
+ }) => any;
1338
+ } & {
1339
+ 'form.submit'?: (props: {
1340
+ text: string;
1341
+ title: string | undefined;
1342
+ description: string | undefined;
1343
+ data: TFormData;
1344
+ errors: Record<string, string | undefined> | undefined;
1345
+ formError: string | undefined;
1346
+ disabled: boolean;
1347
+ loading: boolean;
1348
+ submitText: string;
1349
+ submit: () => void;
1350
+ reset: () => Promise<void>;
1351
+ clearErrors: () => void;
1352
+ setErrors: (errors: Record<string, string>) => void;
1353
+ dismissError: (path: string) => void;
1354
+ dismissFormError: () => void;
1355
+ formContext: TFormContext | undefined;
1356
+ isDirty: boolean;
1357
+ changes: readonly FormFieldChange[];
1358
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1359
+ getChanges: () => FormFieldChange[];
1360
+ isDirtyPath: (path: string) => boolean;
1361
+ }) => any;
1362
+ } & {
1363
+ 'form.footer'?: (props: {
1364
+ title: string | undefined;
1365
+ description: string | undefined;
1366
+ data: TFormData;
1367
+ errors: Record<string, string | undefined> | undefined;
1368
+ formError: string | undefined;
1369
+ disabled: boolean;
1370
+ loading: boolean;
1371
+ submitText: string;
1372
+ submit: () => void;
1373
+ reset: () => Promise<void>;
1374
+ clearErrors: () => void;
1375
+ setErrors: (errors: Record<string, string>) => void;
1376
+ dismissError: (path: string) => void;
1377
+ dismissFormError: () => void;
1378
+ formContext: TFormContext | undefined;
1379
+ isDirty: boolean;
1380
+ changes: readonly FormFieldChange[];
1381
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1382
+ getChanges: () => FormFieldChange[];
1383
+ isDirtyPath: (path: string) => boolean;
1384
+ }) => any;
1385
+ } & {
1386
+ 'form.loading'?: (props: {
1387
+ title: string | undefined;
1388
+ description: string | undefined;
1389
+ data: TFormData;
1390
+ errors: Record<string, string | undefined> | undefined;
1391
+ formError: string | undefined;
1392
+ disabled: boolean;
1393
+ loading: boolean;
1394
+ submitText: string;
1395
+ submit: () => void;
1396
+ reset: () => Promise<void>;
1397
+ clearErrors: () => void;
1398
+ setErrors: (errors: Record<string, string>) => void;
1399
+ dismissError: (path: string) => void;
1400
+ dismissFormError: () => void;
1401
+ formContext: TFormContext | undefined;
1402
+ isDirty: boolean;
1403
+ changes: readonly FormFieldChange[];
1404
+ getPatch: (opts?: _atscript_ui0.FormDiffOptions) => Record<string, unknown>;
1405
+ getChanges: () => FormFieldChange[];
1406
+ isDirtyPath: (path: string) => boolean;
1407
+ }) => any;
1408
+ };
1409
+ emit: {
1410
+ (e: "submit", data: TFormData): void;
1411
+ (e: "error", errors: {
1412
+ path: string;
1413
+ message: string;
1414
+ }[]): void;
1415
+ (e: "action", name: string, data: TFormData): void;
1416
+ (e: "unsupported-action", name: string, data: TFormData): void;
1417
+ (e: "change", type: TAsChangeType, path: string, value: unknown, formData: TFormData): void;
1418
+ };
1419
+ }>) => vue.VNode & {
1420
+ __ctx?: Awaited<typeof __VLS_setup>;
1421
+ };
1422
+ declare const _default: typeof __VLS_export;
1423
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
1424
+ //#endregion
1425
+ export { UseAsTupleReturn as $, UseAsLocaleReturn as A, focusNewFocusableAfter as B, useAsDualInput as C, createAsFormDef as Ct, UseAsDecimalOptions as D, useAsNumber as E, useAsTriStateCheckbox as F, useAsDropdown as G, AsNestedSectionsStore as H, UseAsOptionalAddFlowOptions as I, useAsValueHelp as J, UseAsValueHelpOptions as K, UseAsOptionalAddFlowReturn as L, useAsLocale as M, UseAsTriStateCheckboxOptions as N, UseAsDecimalReturn as O, UseAsTriStateCheckboxReturn as P, useAsUnion as Q, useAsOptionalAddFlow as R, UseAsDualInputReturn as S, createDefaultTypes as St, UseAsNumberReturn as T, provideAsNestedSectionsStore as U, useAsFocusFirstAfter as V, useAsNestedSectionsStore as W, useAsUnionVariant as X, formatIndexedLabelParts as Y, UseAsUnionReturn as Z, useAsPath as _, useAsField as _t, FormFieldChange$1 as a, useAsExternalErrors as at, useAsDate as b, TFormRule as bt, resetDefaultClientFactory as c, useAsForm as ct, useAsErrorDismiss as d, useAsFormPatch as dt, useAsTuple as et, UseAsDataReturn as f, TFormSubmitValidator as ft, UseAsPathReturn as g, UseAsFieldReturn as gt, useAsTypeMap as h, UseAsFieldOptions as ht, FormDiffOptions$1 as i, UseAsExternalErrorsReturn as it, provideAsLocale as j, useAsDecimal as k, setDefaultClientFactory as l, AsFormPatchHandle as lt, UseAsTypeMapReturn as m, useAsState as mt, _default as n, useAsArray as nt, FormRebaseOptions$1 as o, UseAsFormOptions as ot, useAsData as p, UseAsStateReturn as pt, UseAsValueHelpReturn as q, ClientFactory$1 as r, UseAsExternalErrorsOptions as rt, getDefaultClientFactory as s, UseAsFormReturn as st, Props as t, UseAsArrayReturn as tt, AsErrorDismiss as u, RebaseOntoResult as ut, UseAsDateOptions as v, TFormFieldCallbacks as vt, UseAsNumberOptions as w, UseAsDualInputOptions as x, TFormState as xt, UseAsDateReturn as y, TFormFieldRegistration as yt, focusFirstAfter as z };