@webiny/app-admin 6.3.0-beta.2 → 6.3.0-beta.3

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 (234) hide show
  1. package/base/Base/DefaultFieldRenderers.js +69 -5
  2. package/base/Base/DefaultFieldRenderers.js.map +1 -1
  3. package/base/Base/DefaultLayoutRenderers.js +5 -1
  4. package/base/Base/DefaultLayoutRenderers.js.map +1 -1
  5. package/base/Base/FieldRenderers/CheckboxesRenderer.d.ts +13 -0
  6. package/base/Base/FieldRenderers/CheckboxesRenderer.js +28 -0
  7. package/base/Base/FieldRenderers/CheckboxesRenderer.js.map +1 -0
  8. package/base/Base/FieldRenderers/CodeEditorRenderer.d.ts +15 -0
  9. package/base/Base/FieldRenderers/CodeEditorRenderer.js +17 -0
  10. package/base/Base/FieldRenderers/CodeEditorRenderer.js.map +1 -0
  11. package/base/Base/FieldRenderers/DateTimeInputsRenderer.d.ts +17 -0
  12. package/base/Base/FieldRenderers/DateTimeInputsRenderer.js +66 -0
  13. package/base/Base/FieldRenderers/DateTimeInputsRenderer.js.map +1 -0
  14. package/base/Base/FieldRenderers/DateTimeRenderer.d.ts +21 -0
  15. package/base/Base/FieldRenderers/DateTimeRenderer.js +46 -0
  16. package/base/Base/FieldRenderers/DateTimeRenderer.js.map +1 -0
  17. package/base/Base/FieldRenderers/FilePickerRenderer.d.ts +12 -0
  18. package/base/Base/FieldRenderers/FilePickerRenderer.js +47 -0
  19. package/base/Base/FieldRenderers/FilePickerRenderer.js.map +1 -0
  20. package/base/Base/FieldRenderers/FileUrlPickerRenderer.d.ts +12 -0
  21. package/base/Base/FieldRenderers/FileUrlPickerRenderer.js +25 -0
  22. package/base/Base/FieldRenderers/FileUrlPickerRenderer.js.map +1 -0
  23. package/base/Base/FieldRenderers/HiddenRenderer.d.ts +12 -0
  24. package/base/Base/FieldRenderers/HiddenRenderer.js +5 -0
  25. package/base/Base/FieldRenderers/HiddenRenderer.js.map +1 -0
  26. package/base/Base/FieldRenderers/HorizontalTabsRenderer.d.ts +5 -0
  27. package/base/Base/FieldRenderers/HorizontalTabsRenderer.js +27 -0
  28. package/base/Base/FieldRenderers/HorizontalTabsRenderer.js.map +1 -0
  29. package/base/Base/FieldRenderers/InputRenderer.d.ts +4 -7
  30. package/base/Base/FieldRenderers/InputRenderer.js +2 -2
  31. package/base/Base/FieldRenderers/InputRenderer.js.map +1 -1
  32. package/base/Base/FieldRenderers/NumberInputRenderer.d.ts +12 -0
  33. package/base/Base/FieldRenderers/NumberInputRenderer.js +23 -0
  34. package/base/Base/FieldRenderers/NumberInputRenderer.js.map +1 -0
  35. package/base/Base/FieldRenderers/NumberInputsRenderer.d.ts +14 -0
  36. package/base/Base/FieldRenderers/NumberInputsRenderer.js +49 -0
  37. package/base/Base/FieldRenderers/NumberInputsRenderer.js.map +1 -0
  38. package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.d.ts +14 -0
  39. package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js +20 -0
  40. package/base/Base/FieldRenderers/ObjectRenderer/DynamicZoneRenderer.js.map +1 -0
  41. package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.d.ts +14 -0
  42. package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.js +65 -0
  43. package/base/Base/FieldRenderers/ObjectRenderer/KeyValueTagsRenderer.js.map +1 -0
  44. package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.d.ts +10 -0
  45. package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.js +109 -0
  46. package/base/Base/FieldRenderers/ObjectRenderer/MultiValueDynamicZone.js.map +1 -0
  47. package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.d.ts +17 -0
  48. package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js +55 -0
  49. package/base/Base/FieldRenderers/ObjectRenderer/ObjectAccordionMultipleRenderer.js.map +1 -0
  50. package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.d.ts +7 -3
  51. package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js +15 -19
  52. package/base/Base/FieldRenderers/ObjectRenderer/ObjectFieldComponents.js.map +1 -1
  53. package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.d.ts +5 -8
  54. package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js +7 -50
  55. package/base/Base/FieldRenderers/ObjectRenderer/ObjectRenderer.js.map +1 -1
  56. package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.d.ts +10 -0
  57. package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js +64 -0
  58. package/base/Base/FieldRenderers/ObjectRenderer/SingleValueDynamicZone.js.map +1 -0
  59. package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.d.ts +10 -0
  60. package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js +85 -0
  61. package/base/Base/FieldRenderers/ObjectRenderer/TemplatePicker.js.map +1 -0
  62. package/base/Base/FieldRenderers/PassthroughRenderer.d.ts +3 -6
  63. package/base/Base/FieldRenderers/PassthroughRenderer.js +9 -23
  64. package/base/Base/FieldRenderers/PassthroughRenderer.js.map +1 -1
  65. package/base/Base/FieldRenderers/RadioButtonsRenderer.d.ts +13 -0
  66. package/base/Base/FieldRenderers/RadioButtonsRenderer.js +27 -0
  67. package/base/Base/FieldRenderers/RadioButtonsRenderer.js.map +1 -0
  68. package/base/Base/FieldRenderers/SelectRenderer.d.ts +6 -8
  69. package/base/Base/FieldRenderers/SelectRenderer.js +8 -5
  70. package/base/Base/FieldRenderers/SelectRenderer.js.map +1 -1
  71. package/base/Base/FieldRenderers/SwitchRenderer.d.ts +12 -0
  72. package/base/Base/FieldRenderers/SwitchRenderer.js +19 -0
  73. package/base/Base/FieldRenderers/SwitchRenderer.js.map +1 -0
  74. package/base/Base/FieldRenderers/TagsRenderer.d.ts +12 -0
  75. package/base/Base/FieldRenderers/TagsRenderer.js +21 -0
  76. package/base/Base/FieldRenderers/TagsRenderer.js.map +1 -0
  77. package/base/Base/FieldRenderers/TextInputsRenderer.d.ts +14 -0
  78. package/base/Base/FieldRenderers/TextInputsRenderer.js +48 -0
  79. package/base/Base/FieldRenderers/TextInputsRenderer.js.map +1 -0
  80. package/base/Base/FieldRenderers/TextareaRenderer.d.ts +3 -6
  81. package/base/Base/FieldRenderers/TextareaRenderer.js +3 -4
  82. package/base/Base/FieldRenderers/TextareaRenderer.js.map +1 -1
  83. package/base/Base/FieldRenderers/TextareasRenderer.d.ts +14 -0
  84. package/base/Base/FieldRenderers/TextareasRenderer.js +51 -0
  85. package/base/Base/FieldRenderers/TextareasRenderer.js.map +1 -0
  86. package/base/Base/FieldRenderers/VerticalTabsRenderer.js +2 -2
  87. package/base/Base/FieldRenderers/VerticalTabsRenderer.js.map +1 -1
  88. package/base/Base/Menus.js +5 -64
  89. package/base/Base/Menus.js.map +1 -1
  90. package/base/Base/RoutesConfig.js +6 -0
  91. package/base/Base/RoutesConfig.js.map +1 -1
  92. package/exports/admin/build-params.d.ts +2 -0
  93. package/exports/admin/build-params.js +3 -0
  94. package/exports/admin/build-params.js.map +1 -1
  95. package/exports/admin/form.d.ts +5 -0
  96. package/exports/admin/form.js +8 -0
  97. package/exports/admin/form.js.map +1 -1
  98. package/exports/admin/ui.d.ts +1 -0
  99. package/exports/admin/ui.js +1 -0
  100. package/exports/admin/ui.js.map +1 -1
  101. package/exports/admin.d.ts +3 -1
  102. package/exports/admin.js +3 -1
  103. package/exports/admin.js.map +1 -1
  104. package/features/formModel/ConditionRuleEvaluator.d.ts +9 -0
  105. package/features/formModel/ConditionRuleEvaluator.js +56 -0
  106. package/features/formModel/ConditionRuleEvaluator.js.map +1 -0
  107. package/features/formModel/Field.d.ts +50 -4
  108. package/features/formModel/Field.js +254 -35
  109. package/features/formModel/Field.js.map +1 -1
  110. package/features/formModel/FieldBuilder.d.ts +17 -35
  111. package/features/formModel/FieldBuilder.js +63 -100
  112. package/features/formModel/FieldBuilder.js.map +1 -1
  113. package/features/formModel/FieldBuilder.test.js +127 -13
  114. package/features/formModel/FieldBuilder.test.js.map +1 -1
  115. package/features/formModel/FieldBuilderRegistry.d.ts +4 -0
  116. package/features/formModel/FieldBuilderRegistry.js +31 -0
  117. package/features/formModel/FieldBuilderRegistry.js.map +1 -0
  118. package/features/formModel/FocusManager.d.ts +14 -0
  119. package/features/formModel/FocusManager.js +109 -0
  120. package/features/formModel/FocusManager.js.map +1 -0
  121. package/features/formModel/FormModel.d.ts +27 -31
  122. package/features/formModel/FormModel.js +210 -403
  123. package/features/formModel/FormModel.js.map +1 -1
  124. package/features/formModel/FormModel.test.js +2044 -193
  125. package/features/formModel/FormModel.test.js.map +1 -1
  126. package/features/formModel/FormModelFactory.d.ts +4 -2
  127. package/features/formModel/FormModelFactory.js +13 -3
  128. package/features/formModel/FormModelFactory.js.map +1 -1
  129. package/features/formModel/FormView.d.ts +2 -0
  130. package/features/formModel/FormView.js +44 -37
  131. package/features/formModel/FormView.js.map +1 -1
  132. package/features/formModel/LayoutBuilderFactory.d.ts +61 -0
  133. package/features/formModel/LayoutBuilderFactory.js +386 -0
  134. package/features/formModel/LayoutBuilderFactory.js.map +1 -0
  135. package/features/formModel/LayoutMutator.d.ts +11 -0
  136. package/features/formModel/LayoutMutator.js +136 -0
  137. package/features/formModel/LayoutMutator.js.map +1 -0
  138. package/features/formModel/LayoutResolver.d.ts +26 -0
  139. package/features/formModel/LayoutResolver.js +239 -0
  140. package/features/formModel/LayoutResolver.js.map +1 -0
  141. package/features/formModel/ObjectField.d.ts +55 -4
  142. package/features/formModel/ObjectField.js +499 -82
  143. package/features/formModel/ObjectField.js.map +1 -1
  144. package/features/formModel/Rules.test.d.ts +1 -0
  145. package/features/formModel/Rules.test.js +289 -0
  146. package/features/formModel/Rules.test.js.map +1 -0
  147. package/features/formModel/abstractions.d.ts +402 -52
  148. package/features/formModel/abstractions.js +55 -0
  149. package/features/formModel/abstractions.js.map +1 -1
  150. package/features/formModel/createFieldRenderer.d.ts +20 -0
  151. package/features/formModel/createFieldRenderer.js +15 -0
  152. package/features/formModel/createFieldRenderer.js.map +1 -0
  153. package/features/formModel/demo/FieldRenderersDemoPresenter.d.ts +18 -0
  154. package/features/formModel/demo/FieldRenderersDemoPresenter.js +225 -0
  155. package/features/formModel/demo/FieldRenderersDemoPresenter.js.map +1 -0
  156. package/features/formModel/demo/FormModelDemo.d.ts +4 -0
  157. package/features/formModel/demo/FormModelDemo.js +230 -0
  158. package/features/formModel/demo/FormModelDemo.js.map +1 -0
  159. package/features/formModel/demo/FormModelDemoPresenter.d.ts +22 -0
  160. package/features/formModel/demo/FormModelDemoPresenter.js +121 -0
  161. package/features/formModel/demo/FormModelDemoPresenter.js.map +1 -0
  162. package/features/formModel/demo/FormModelPhase11Presenter.d.ts +25 -0
  163. package/features/formModel/demo/FormModelPhase11Presenter.js +104 -0
  164. package/features/formModel/demo/FormModelPhase11Presenter.js.map +1 -0
  165. package/features/formModel/demo/FormModelPhase8c1Presenter.d.ts +23 -0
  166. package/features/formModel/demo/FormModelPhase8c1Presenter.js +62 -0
  167. package/features/formModel/demo/FormModelPhase8c1Presenter.js.map +1 -0
  168. package/features/formModel/feature.js +12 -0
  169. package/features/formModel/feature.js.map +1 -1
  170. package/features/formModel/fieldTypes/BooleanFieldType.d.ts +19 -0
  171. package/features/formModel/fieldTypes/BooleanFieldType.js +23 -0
  172. package/features/formModel/fieldTypes/BooleanFieldType.js.map +1 -0
  173. package/features/formModel/fieldTypes/DateTimeFieldType.d.ts +173 -0
  174. package/features/formModel/fieldTypes/DateTimeFieldType.js +369 -0
  175. package/features/formModel/fieldTypes/DateTimeFieldType.js.map +1 -0
  176. package/features/formModel/fieldTypes/FileFieldType.d.ts +18 -0
  177. package/features/formModel/fieldTypes/FileFieldType.js +20 -0
  178. package/features/formModel/fieldTypes/FileFieldType.js.map +1 -0
  179. package/features/formModel/fieldTypes/FileUrlFieldType.d.ts +18 -0
  180. package/features/formModel/fieldTypes/FileUrlFieldType.js +20 -0
  181. package/features/formModel/fieldTypes/FileUrlFieldType.js.map +1 -0
  182. package/features/formModel/fieldTypes/NumberFieldType.d.ts +19 -0
  183. package/features/formModel/fieldTypes/NumberFieldType.js +27 -0
  184. package/features/formModel/fieldTypes/NumberFieldType.js.map +1 -0
  185. package/features/formModel/fieldTypes/ObjectFieldType.d.ts +34 -0
  186. package/features/formModel/fieldTypes/ObjectFieldType.js +109 -0
  187. package/features/formModel/fieldTypes/ObjectFieldType.js.map +1 -0
  188. package/features/formModel/fieldTypes/TextFieldType.d.ts +18 -0
  189. package/features/formModel/fieldTypes/TextFieldType.js +20 -0
  190. package/features/formModel/fieldTypes/TextFieldType.js.map +1 -0
  191. package/features/formModel/fieldTypes/index.d.ts +7 -0
  192. package/features/formModel/fieldTypes/index.js +9 -0
  193. package/features/formModel/fieldTypes/index.js.map +1 -0
  194. package/features/formModel/index.d.ts +13 -4
  195. package/features/formModel/index.js +21 -2
  196. package/features/formModel/index.js.map +1 -1
  197. package/features/formModel/renderers.d.ts +15 -1
  198. package/features/formModel/renderers.js +15 -1
  199. package/features/formModel/renderers.js.map +1 -1
  200. package/features/tools/LexicalContext/LexicalContext.d.ts +14 -0
  201. package/features/tools/LexicalContext/LexicalContext.js +22 -0
  202. package/features/tools/LexicalContext/LexicalContext.js.map +1 -0
  203. package/features/tools/LexicalContext/abstractions.d.ts +11 -0
  204. package/features/tools/LexicalContext/abstractions.js +4 -0
  205. package/features/tools/LexicalContext/abstractions.js.map +1 -0
  206. package/features/tools/LexicalContext/index.d.ts +2 -0
  207. package/features/tools/LexicalContext/index.js +3 -0
  208. package/features/tools/LexicalContext/index.js.map +1 -0
  209. package/features/tools/feature.js +2 -0
  210. package/features/tools/feature.js.map +1 -1
  211. package/features/tools/index.d.ts +1 -0
  212. package/features/tools/index.js +1 -0
  213. package/features/tools/index.js.map +1 -1
  214. package/index.d.ts +8 -1
  215. package/index.js +7 -0
  216. package/index.js.map +1 -1
  217. package/package.json +30 -24
  218. package/presentation/installation/components/SystemInstaller/steps/AdminUserStep/createPasswordValidator.js +1 -1
  219. package/presentation/installation/components/SystemInstaller/steps/AdminUserStep/createPasswordValidator.js.map +1 -1
  220. package/presentation/lexicalContext/useLexicalContext.d.ts +3 -0
  221. package/presentation/lexicalContext/useLexicalContext.js +14 -0
  222. package/presentation/lexicalContext/useLexicalContext.js.map +1 -0
  223. package/presentation/textToLexicalTool/TextToLexicalTool.d.ts +3 -0
  224. package/presentation/textToLexicalTool/TextToLexicalTool.js +6 -2
  225. package/presentation/textToLexicalTool/TextToLexicalTool.js.map +1 -1
  226. package/presentation/textToLexicalTool/textToLexicalState.d.ts +2 -1
  227. package/presentation/textToLexicalTool/textToLexicalState.js +15 -3
  228. package/presentation/textToLexicalTool/textToLexicalState.js.map +1 -1
  229. package/routes.d.ts +1 -0
  230. package/routes.js +4 -0
  231. package/routes.js.map +1 -1
  232. package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.d.ts +0 -21
  233. package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.js +0 -28
  234. package/base/Base/FieldRenderers/ObjectRenderer/ObjectListFlatRenderer.js.map +0 -1
@@ -1,8 +1,13 @@
1
1
  import type { z } from "zod";
2
+ import type { Icon } from "../../components/IconPicker/types.js";
2
3
  export interface IFieldRendererRegistry {
3
4
  }
4
- export type FieldRendererName<TType extends string = string> = string extends TType ? keyof IFieldRendererRegistry & string : {
5
- [K in keyof IFieldRendererRegistry]: TType extends IFieldRendererRegistry[K]["fieldType"] ? K : never;
5
+ export type FieldRendererName<TType extends string = string, TOptions extends boolean = boolean> = string extends TType ? keyof IFieldRendererRegistry & string : {
6
+ [K in keyof IFieldRendererRegistry]: TType extends IFieldRendererRegistry[K]["fieldType"] ? boolean extends TOptions ? K : TOptions extends true ? IFieldRendererRegistry[K] extends {
7
+ options: true;
8
+ } ? K : never : IFieldRendererRegistry[K] extends {
9
+ options: true;
10
+ } ? never : K : never;
6
11
  }[keyof IFieldRendererRegistry] & string;
7
12
  export type FieldRendererSettings<TName extends string> = TName extends keyof IFieldRendererRegistry ? IFieldRendererRegistry[TName]["settings"] : Record<string, unknown> | undefined;
8
13
  export interface IFieldConfig {
@@ -16,22 +21,50 @@ export interface IFieldConfig {
16
21
  defaultValue?: unknown;
17
22
  renderer?: string;
18
23
  rendererSettings?: Record<string, unknown>;
24
+ isList?: boolean;
19
25
  hidden: boolean;
20
26
  required: boolean;
21
27
  requiredMessage?: string;
22
28
  disabled: boolean;
23
29
  schema?: z.ZodTypeAny;
24
30
  options?: IValueOption[] | ((form: IFormModel) => IValueOption[]);
31
+ normalizeValue?: (value: unknown) => unknown;
25
32
  beforeChangeCallbacks?: BeforeChangeCallback[];
26
33
  afterChangeCallbacks?: AfterChangeCallback[];
27
34
  afterSetValueCallbacks?: AfterSetValueCallback[];
28
35
  onBlurCallbacks?: OnBlurCallback[];
36
+ requiredWhenCallbacks?: RequiredWhenCallback[];
37
+ computed?: ComputedFieldCallback;
38
+ computedUntilDirty?: ComputedFieldCallback;
39
+ tags?: string[];
40
+ cloneValue?: CloneValueCallback;
41
+ rules?: IRule[];
42
+ }
43
+ export interface IRequiredWhenCallbackConfig {
44
+ fn: (form: IFormModel) => boolean;
45
+ message?: string;
46
+ }
47
+ export type RequiredWhenCallback = IRequiredWhenCallbackConfig;
48
+ export type ComputedFieldCallback = (form: IFormModel) => unknown;
49
+ export type RuleAction = "hide" | "disable";
50
+ export type RuleOperator = "eq" | "neq" | "isEmpty" | "isNotEmpty" | "isTruthy" | "isFalsy" | "matches";
51
+ export interface IRule {
52
+ type: string;
53
+ target: string;
54
+ operator: RuleOperator | (string & {});
55
+ value: string | null;
56
+ action: RuleAction;
57
+ }
58
+ export interface IRuleEvaluator {
59
+ canEvaluate(rule: IRule): boolean;
60
+ evaluate(rule: IRule, form: IFormModel): boolean;
29
61
  }
30
- export interface IValueOption {
62
+ export interface IValueOption<V extends string | number = string | number> {
31
63
  label: string;
32
- value: string;
64
+ value: V;
33
65
  disabled?: boolean;
34
66
  }
67
+ export type OptionValueType<TType extends string> = TType extends "number" ? number : string;
35
68
  export interface IFieldValidation {
36
69
  isValid: boolean | null;
37
70
  message?: string;
@@ -46,36 +79,82 @@ export interface IFieldVM {
46
79
  placeholder?: string;
47
80
  value: unknown;
48
81
  validation: IFieldValidation;
82
+ validating: boolean;
49
83
  required: boolean;
84
+ visible: boolean;
50
85
  disabled: boolean;
51
86
  renderer?: string;
52
87
  rendererSettings?: Record<string, unknown>;
88
+ isList?: boolean;
53
89
  options?: IValueOption[];
54
90
  onChange: (value: unknown) => void;
55
91
  onBlur: () => void;
92
+ addItem: (value?: unknown) => void;
93
+ removeItem: (index: number) => void;
94
+ focusRequested: boolean;
95
+ clearFocusRequest: () => void;
56
96
  }
57
97
  export interface IObjectFieldVM extends IFieldVM {
58
98
  type: "object";
59
99
  isList: boolean;
60
100
  /** Child field VMs for non-list object fields. */
61
101
  fields: IFieldVM[];
102
+ /**
103
+ * Resolved layout for non-list object fields. For templated objects, resolves
104
+ * against the active template's per-template layout (if registered via
105
+ * `layout.object()`), otherwise defaults to one row per visible child.
106
+ * For list-mode fields, see `items[].layout`.
107
+ */
108
+ layout: LayoutNodeVM[];
62
109
  /** Items for list-mode object fields. */
63
110
  items: IObjectFieldItemVM[];
64
- addItem: () => void;
65
- removeItem: (index: number) => void;
111
+ /** Append a new item. Templated lists require a template id. */
112
+ addItem: (value?: unknown) => void;
66
113
  moveItem: (fromIndex: number, toIndex: number) => void;
114
+ /** Duplicate a list item (including its `_templateId` when templated) and insert it after the source. */
115
+ duplicateItem: (index: number) => void;
116
+ /** True when the object has templates defined. */
117
+ isTemplated: boolean;
118
+ /** Templates visible in the picker (filtered by each template's reactive `visible`). */
119
+ availableTemplates: ITemplateVM[];
120
+ /** Currently active template id (single-object mode), or null if no template picked. */
121
+ activeTemplateId: string | null;
122
+ /** Switch to a different template. Discards values not present in the new template. */
123
+ setTemplate: (templateId: string) => void;
67
124
  }
68
125
  export interface IObjectFieldItemVM {
69
126
  key: string;
70
127
  fields: IFieldVM[];
128
+ /**
129
+ * Resolved layout for this item. For templated lists, resolves against the
130
+ * item's template-specific layout (if registered via `layout.object()`),
131
+ * otherwise defaults to one row per visible child.
132
+ */
133
+ layout: LayoutNodeVM[];
71
134
  remove: () => void;
72
135
  moveUp: () => void;
73
136
  moveDown: () => void;
137
+ duplicate: () => void;
138
+ /** The template id of this item, if the parent list is templated. */
139
+ templateId?: string;
140
+ }
141
+ /**
142
+ * VM exposed for each available template in the picker.
143
+ */
144
+ export interface ITemplateIcon {
145
+ type: string;
146
+ name: string;
147
+ }
148
+ export interface ITemplateVM {
149
+ id: string;
150
+ label: string;
151
+ icon?: ITemplateIcon;
74
152
  }
75
153
  export interface IField {
76
154
  readonly name: string;
77
155
  readonly type: string;
78
156
  readonly visible: boolean;
157
+ readonly disabled: boolean;
79
158
  readonly vm: IFieldVM;
80
159
  readonly config: IFieldConfig;
81
160
  getValue<T = unknown>(): T;
@@ -83,60 +162,154 @@ export interface IField {
83
162
  setValueSilent(value: unknown): void;
84
163
  setDisabled(value: boolean): void;
85
164
  setVisible(value: boolean): void;
86
- setForm(form: IFormModel): void;
165
+ setForm(form: IFormModel, parentPath?: string): void;
166
+ setAncestorRules(rules: IRule[]): void;
87
167
  setValidation(validation: IFieldValidation): void;
88
168
  resetValidation(): void;
89
- validate(): Promise<boolean>;
169
+ validate(options?: {
170
+ force?: boolean;
171
+ }): Promise<boolean>;
90
172
  remove(): void;
91
173
  addBeforeChange(cb: BeforeChangeCallback): void;
92
174
  addAfterChange(cb: AfterChangeCallback): void;
93
175
  addAfterSetValue(cb: AfterSetValueCallback): void;
94
176
  addOnBlur(cb: OnBlurCallback): void;
177
+ /**
178
+ * Append a conditional required check. Multiple callbacks chain additively;
179
+ * the first one returning `true` makes the field required for the current
180
+ * form state. The built-in `.required()` flag (if set) always counts as a
181
+ * truthy check and cannot be overridden.
182
+ */
183
+ addRequiredWhen(fn: (form: IFormModel) => boolean, message?: string): void;
184
+ /**
185
+ * Mark this field as a derived value computed from `fn(form)`. The field
186
+ * stays editable (no auto-disable) and is excluded from `isDirty` while
187
+ * still tracking the computed value. Validation continues to apply.
188
+ */
189
+ setComputed(fn: ComputedFieldCallback): void;
190
+ /**
191
+ * Same as `setComputed`, but the field switches to manual mode the first
192
+ * time the user edits its value. After that, the computed callback no
193
+ * longer overrides user input.
194
+ */
195
+ setComputedUntilDirty(fn: ComputedFieldCallback): void;
95
196
  blur(): void;
96
197
  as<T extends keyof FieldTypeMap>(type: T): FieldTypeMap[T];
198
+ readonly qualifiedName: string;
199
+ focus(): void;
200
+ requestFocus(): void;
201
+ clearFocusRequest(): void;
97
202
  }
98
203
  /**
99
204
  * Maps field type strings to their typed field interfaces.
100
205
  * Extended via module augmentation when new field types are registered.
101
206
  */
102
- export interface FieldTypeMap {
103
- text: IField;
104
- select: ISelectField;
105
- object: IObjectField;
106
- }
107
- export interface ISelectField extends IField {
108
- readonly config: IFieldConfig & {
109
- options?: IValueOption[] | ((form: IFormModel) => IValueOption[]);
110
- };
207
+ export interface ITypedField<V> extends IField {
208
+ getValue<T = V>(): T;
111
209
  }
210
+ type InferFieldTypeMap = {
211
+ [K in keyof IFieldBuilderRegistry]: ReturnType<IFieldBuilderRegistry[K]> extends IObjectFieldBuilder ? IObjectField : ReturnType<IFieldBuilderRegistry[K]> extends {
212
+ readonly __valueType?: infer V;
213
+ } ? ITypedField<V> : IField;
214
+ };
215
+ export type FieldTypeMap = {
216
+ [K in keyof InferFieldTypeMap]: InferFieldTypeMap[K];
217
+ };
218
+ export type FileValue = {
219
+ id: string;
220
+ name: string;
221
+ size: number;
222
+ mimeType: string;
223
+ src: string;
224
+ width: number | undefined;
225
+ height: number | undefined;
226
+ };
112
227
  export interface IObjectFieldConfig extends IFieldConfig {
113
228
  childBuilders: Record<string, IFieldBuilder>;
114
229
  isList: boolean;
115
230
  listSchema?: z.ZodTypeAny;
231
+ templates?: ITemplateConfig[];
232
+ }
233
+ export interface ITemplateBuilder {
234
+ label(text: string): this;
235
+ icon(icon: ITemplateIcon): this;
236
+ fields(factory: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder>): this;
237
+ visible(predicate: (form: IFormModel) => boolean): this;
238
+ }
239
+ export interface ITemplateConfig {
240
+ id: string;
241
+ label: string;
242
+ icon?: ITemplateIcon;
243
+ childBuilders: Record<string, IFieldBuilder>;
244
+ visible?: (form: IFormModel) => boolean;
116
245
  }
117
- export interface IObjectField extends IField {
246
+ export interface IObjectField extends ITypedField<Record<string, unknown> | null> {
118
247
  readonly isList: boolean;
119
248
  readonly children: Map<string, IField>;
120
249
  readonly items: IListItemField[];
121
- addItem(data?: Record<string, unknown>): void;
250
+ readonly isTemplated: boolean;
251
+ readonly activeTemplateId: string | null;
252
+ readonly availableTemplates: ITemplateVM[];
253
+ /**
254
+ * Add, replace, or remove children on this object field at runtime.
255
+ * Mirrors `form.fields()` but scoped to this object's children. Existing
256
+ * keys are replaced; new keys are appended; passing `undefined` removes.
257
+ * Throws on templated objects — each template owns its own fields.
258
+ */
259
+ fields(factory: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder | undefined>): void;
260
+ /**
261
+ * Register an inner layout used by the field's VM (`field.layout` for
262
+ * single objects, `item.layout` for list items).
263
+ *
264
+ * Pass `LayoutNode[]` for non-templated objects (the layout applies to the
265
+ * single object or every list item). Pass `Record<templateId, LayoutNode[]>`
266
+ * for templated objects (each entry applies when that template is active
267
+ * or for each list item with that template). Templates without an entry
268
+ * fall back to default one-row-per-visible-child.
269
+ */
270
+ setInnerLayout(layout: LayoutNode[] | Record<string, LayoutNode[]>): void;
271
+ /**
272
+ * Append a new list item.
273
+ * - Non-templated list: `addItem(data?)` — data hydrates the new item.
274
+ * - Templated list: `addItem(templateId, data?)` — templateId picks the variant.
275
+ */
276
+ addItem(templateIdOrData?: string | Record<string, unknown>, data?: Record<string, unknown>): void;
122
277
  removeItem(index: number): void;
123
278
  moveItem(fromIndex: number, toIndex: number): void;
279
+ /** Duplicate a list item (including its `_templateId`) and insert after the source. */
280
+ duplicateItem(index: number): void;
281
+ setTemplate(templateId: string): void;
282
+ /**
283
+ * Runtime template management. Available on every object field but throws
284
+ * when called on a non-templated field (`isTemplated === false`).
285
+ */
286
+ readonly templates: IObjectFieldTemplates;
287
+ getInnerLayout(): LayoutNode[] | null;
124
288
  getData(): Record<string, unknown> | Record<string, unknown>[];
125
289
  }
290
+ export interface IObjectFieldTemplates {
291
+ add(id: string, configure: (t: ITemplateBuilder) => void): void;
292
+ remove(templateId: string): void;
293
+ }
126
294
  export interface IListItemField {
127
295
  readonly key: string;
128
296
  readonly children: Map<string, IField>;
297
+ readonly templateId?: string;
129
298
  getData(): Record<string, unknown>;
130
299
  }
131
300
  export type BeforeChangeCallback = (value: unknown, form: IFormModel) => unknown;
132
301
  export type AfterChangeCallback = (value: unknown, form: IFormModel) => void;
133
302
  export type AfterSetValueCallback = (value: unknown, form: IFormModel) => void;
134
303
  export type OnBlurCallback = (value: unknown, form: IFormModel) => void;
135
- export type LayoutNode = IRowNode | ISeparatorNode | ITabsNode | IElementNode;
304
+ export type CloneValueCallback = (value: unknown) => unknown;
305
+ export type LayoutNode = IRowNode | ISeparatorNode | ITabsNode | IElementNode | IObjectNode;
136
306
  export interface IRowNode {
137
307
  type: "row";
138
308
  fieldIds: string[];
309
+ position?: LayoutPosition;
139
310
  }
311
+ /** @deprecated Use IRowBuilder instead */
312
+ export type IRowNodeHandle = IRowBuilder;
140
313
  export interface ISeparatorNode {
141
314
  type: "separator";
142
315
  }
@@ -144,14 +317,29 @@ export interface ITabDefinition {
144
317
  id: string;
145
318
  label: string;
146
319
  description?: string;
147
- icon?: string;
320
+ icon?: Icon;
148
321
  layout: LayoutNode[];
322
+ rules?: IRule[];
323
+ }
324
+ /**
325
+ * User-facing tab spec accepted by `layout.tabs(...)`. The layout is supplied
326
+ * as a callback receiving the layout builder, mirroring `layout.object(...)`.
327
+ * Resolved to `ITabDefinition` (with `layout: LayoutNode[]`) at build time.
328
+ */
329
+ export interface ITabDefinitionInput {
330
+ id: string;
331
+ label: string;
332
+ description?: string;
333
+ icon?: Icon;
334
+ layout: (layout: ILayoutBuilder) => ILayoutNodeBuilder[];
335
+ rules?: IRule[];
149
336
  }
150
337
  export interface ITabsNode {
151
338
  type: "tabs";
152
339
  id?: string;
153
340
  renderer?: string;
154
341
  tabs: ITabDefinition[];
342
+ rules?: IRule[];
155
343
  }
156
344
  export interface IElementNode {
157
345
  type: "element";
@@ -159,6 +347,55 @@ export interface IElementNode {
159
347
  renderer: string;
160
348
  props?: Record<string, unknown>;
161
349
  }
350
+ /**
351
+ * Layout node that references an object field and registers an inner layout
352
+ * on it. Resolved as a single-field row in the outer layout — the inner
353
+ * layout is exposed on the field's VM (`field.layout` for single objects,
354
+ * `item.layout` for list items).
355
+ *
356
+ * - For non-templated objects, `inner` is `LayoutNode[]` (one layout, applied
357
+ * to the single object or every list item).
358
+ * - For templated objects, `inner` is `Record<templateId, LayoutNode[]>` —
359
+ * each entry is the layout used when that template is active (or for each
360
+ * list item with that template).
361
+ */
362
+ export interface IObjectNode {
363
+ type: "object";
364
+ fieldName: string;
365
+ inner: LayoutNode[] | Record<string, LayoutNode[]>;
366
+ }
367
+ export interface ILayoutNodeBuilder {
368
+ build(): LayoutNode;
369
+ }
370
+ export interface IRowBuilder extends ILayoutNodeBuilder {
371
+ before(target: string): IRowBuilder;
372
+ after(target: string): IRowBuilder;
373
+ build(): IRowNode;
374
+ }
375
+ export interface ISeparatorBuilder extends ILayoutNodeBuilder {
376
+ build(): ISeparatorNode;
377
+ }
378
+ export interface ITabBuilder {
379
+ label(text: string): this;
380
+ description(text: string): this;
381
+ icon(icon: Icon): this;
382
+ layout(factory: (l: ILayoutBuilder) => ILayoutNodeBuilder[]): this;
383
+ rules(rules: IRule[]): this;
384
+ }
385
+ export interface ITabsBuilder extends ILayoutNodeBuilder {
386
+ renderer(name: string): this;
387
+ tab(id: string, configure: (tab: ITabBuilder) => void): this;
388
+ before(target: string): this;
389
+ after(target: string): this;
390
+ rules(rules: IRule[]): this;
391
+ build(): ITabsNode;
392
+ }
393
+ export interface IElementBuilder extends ILayoutNodeBuilder {
394
+ build(): IElementNode;
395
+ }
396
+ export interface IObjectBuilder extends ILayoutNodeBuilder {
397
+ build(): IObjectNode;
398
+ }
162
399
  export type LayoutNodeVM = IRowNodeVM | ISeparatorNodeVM | ITabsNodeVM | IElementNodeVM;
163
400
  export interface IRowNodeVM {
164
401
  type: "row";
@@ -171,8 +408,9 @@ export interface ITabDefinitionVM {
171
408
  id: string;
172
409
  label: string;
173
410
  description?: string;
174
- icon?: string;
411
+ icon?: Icon;
175
412
  hasErrors: boolean;
413
+ disabled: boolean;
176
414
  layout: LayoutNodeVM[];
177
415
  }
178
416
  export interface ITabsNodeVM {
@@ -180,6 +418,7 @@ export interface ITabsNodeVM {
180
418
  id?: string;
181
419
  renderer?: string;
182
420
  tabs: ITabDefinitionVM[];
421
+ disabled: boolean;
183
422
  activeTabId: string;
184
423
  setActiveTab: (id: string) => void;
185
424
  }
@@ -211,18 +450,18 @@ export interface ILayoutNodeHandle extends IPositionedLayoutNode {
211
450
  after(target: string): IPositionedLayoutNode;
212
451
  replace(target: string): IPositionedLayoutNode;
213
452
  }
214
- export interface ITabsHandle {
215
- tab(definition: ITabDefinition): ITabHandle;
216
- tab(id: string): ITabHandle;
217
- }
218
- export interface ITabHandle {
219
- layout(factory: (layout: ILayoutBuilder) => LayoutNode[]): void;
220
- before(target: string): void;
221
- after(target: string): void;
453
+ export interface LayoutNodeHandleMap {
454
+ tabs: ITabsBuilder;
455
+ element: IElementNode;
456
+ object: IObjectNode;
222
457
  }
223
458
  export interface ILayoutNodeAccessHandle {
224
- as(type: "tabs"): ITabsHandle;
459
+ as<T extends keyof LayoutNodeHandleMap>(type: T): LayoutNodeHandleMap[T];
225
460
  }
461
+ /** @deprecated Use ITabsBuilder instead */
462
+ export type ITabsHandle = ITabsBuilder;
463
+ /** @deprecated Use ITabBuilder instead */
464
+ export type ITabHandle = ITabBuilder;
226
465
  export interface IFormModifier {
227
466
  modify(form: IFormModel): void;
228
467
  }
@@ -232,9 +471,12 @@ export interface ILayoutModifier {
232
471
  tabs(config: {
233
472
  id?: string;
234
473
  renderer?: string;
235
- tabs: ITabDefinition[];
474
+ tabs: ITabDefinitionInput[];
475
+ rules?: IRule[];
236
476
  }): ILayoutNodeHandle;
237
477
  element(renderer: string, props?: Record<string, unknown>): ILayoutNodeHandle;
478
+ object(fieldName: string, layout: (layout: ILayoutBuilder) => ILayoutNodeBuilder[]): ILayoutNodeHandle;
479
+ object(fieldName: string, templateLayouts: Record<string, (layout: ILayoutBuilder) => ILayoutNodeBuilder[]>): ILayoutNodeHandle;
238
480
  remove(target: string): void;
239
481
  }
240
482
  export interface IFormError {
@@ -248,20 +490,52 @@ export interface IFormVM {
248
490
  isDirty: boolean;
249
491
  isValid: boolean | null;
250
492
  }
493
+ /**
494
+ * Imperative form-level rule. Receives the live form and may return a flat
495
+ * list of errors (sync or async). Errors are merged into `form.errors` and
496
+ * surfaced on per-field validation when their `path` matches a known field.
497
+ */
498
+ export type FormRuleFn = (form: IFormModel) => IFormError[] | undefined | void | Promise<IFormError[] | undefined | void>;
499
+ /**
500
+ * A form-level rule. Either a Zod schema (validated against `form.getData()`)
501
+ * or an imperative function returning an error list.
502
+ */
503
+ export type FormRule = z.ZodTypeAny | FormRuleFn;
251
504
  export interface IFormModel<T = Record<string, any>> {
252
505
  field(name: string): IField;
253
506
  fields(factory: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder | undefined>): void;
254
507
  layout(factory: (layout: ILayoutModifier) => (LayoutNode | IPositionedLayoutNode)[]): void;
255
508
  layout(nodeId: string): ILayoutNodeAccessHandle;
509
+ /**
510
+ * Replace the entire layout. Re-registers per-field inner layouts and
511
+ * propagates ancestor rules. Use `layout()` (modifier form) for additive
512
+ * changes.
513
+ */
514
+ setLayout(factory: (layout: ILayoutBuilder) => ILayoutNodeBuilder[]): void;
515
+ /**
516
+ * Append a form-level validation rule. Runs after per-field validation.
517
+ * Accepts a Zod schema (validated against `getData()`) or an imperative
518
+ * function returning a list of errors.
519
+ */
520
+ addRule(rule: FormRule): void;
256
521
  getData(): T;
257
522
  setData(data: T): void;
258
523
  reset(): void;
259
524
  validate(): Promise<boolean>;
260
525
  submit<T = Record<string, unknown>>(): Promise<T | false>;
526
+ evaluateRules(rules: IRule[] | undefined): {
527
+ visible: boolean;
528
+ disabled: boolean;
529
+ };
530
+ focusField(name: string): void;
261
531
  readonly isDirty: boolean;
262
532
  readonly isValid: boolean | null;
533
+ readonly submitted: boolean;
263
534
  readonly errors: IFormError[];
264
535
  readonly vm: IFormVM;
536
+ getFieldBuilders(predicate?: (builder: IFieldBuilder) => boolean): IFieldBuilder[];
537
+ resolveChildLayout(layout: LayoutNode[], children: Map<string, IField>): LayoutNodeVM[];
538
+ readonly registry: IFieldBuilderRegistry;
265
539
  }
266
540
  export declare namespace FormModel {
267
541
  type FieldConfig = IFieldConfig;
@@ -269,50 +543,83 @@ export declare namespace FormModel {
269
543
  type FieldValidation = IFieldValidation;
270
544
  type FieldVM = IFieldVM;
271
545
  type Field = IField;
272
- type SelectField = ISelectField;
273
546
  type ObjectField = IObjectField;
274
547
  type ObjectFieldConfig = IObjectFieldConfig;
275
548
  type BeforeChange = BeforeChangeCallback;
276
549
  type AfterChange = AfterChangeCallback;
277
550
  type AfterSetValue = AfterSetValueCallback;
278
551
  type OnBlur = OnBlurCallback;
552
+ type CloneValue = CloneValueCallback;
553
+ type LayoutNodeBuilder = ILayoutNodeBuilder;
554
+ type RowBuilder = IRowBuilder;
555
+ type SeparatorBuilder = ISeparatorBuilder;
556
+ type TabBuilder = ITabBuilder;
557
+ type TabsBuilder = ITabsBuilder;
558
+ type ElementBuilder = IElementBuilder;
559
+ type ObjectBuilder = IObjectBuilder;
279
560
  type RowNode = IRowNode;
561
+ /** @deprecated Use RowBuilder instead */
562
+ type RowNodeHandle = IRowNodeHandle;
280
563
  type RowNodeVM = IRowNodeVM;
281
564
  type SeparatorNode = ISeparatorNode;
282
565
  type SeparatorNodeVM = ISeparatorNodeVM;
283
566
  type TabsNode = ITabsNode;
284
567
  type TabDefinition = ITabDefinition;
568
+ type TabDefinitionInput = ITabDefinitionInput;
285
569
  type TabsNodeVM = ITabsNodeVM;
286
570
  type TabDefinitionVM = ITabDefinitionVM;
571
+ type TabIcon = Icon;
287
572
  type ElementNode = IElementNode;
288
573
  type ElementNodeVM = IElementNodeVM;
574
+ type ObjectNode = IObjectNode;
289
575
  type ObjectFieldVM = IObjectFieldVM;
290
576
  type ObjectFieldItemVM = IObjectFieldItemVM;
577
+ type TemplateBuilder = ITemplateBuilder;
578
+ type TemplateConfig = ITemplateConfig;
579
+ type TemplateIcon = ITemplateIcon;
580
+ type TemplateVM = ITemplateVM;
581
+ type ObjectFieldTemplatesAPI = IObjectFieldTemplates;
291
582
  type FormError = IFormError;
292
583
  type FormVM = IFormVM;
293
584
  type Interface<T = Record<string, any>> = IFormModel<T>;
294
585
  type Modifier = IFormModifier;
295
586
  type LayoutModifier = ILayoutModifier;
587
+ type Rule = IRule;
588
+ type Action = RuleAction;
589
+ type RuleEvaluator = IRuleEvaluator;
590
+ type FormRuleFunction = FormRuleFn;
591
+ type FormRuleType = FormRule;
592
+ type RequiredWhen = (form: IFormModel) => boolean;
593
+ type Computed = ComputedFieldCallback;
296
594
  }
297
595
  export interface IFormModelFactory {
298
596
  create<T = Record<string, any>>(config: IFormModelConfig): IFormModel<T>;
299
597
  }
300
598
  export interface IFormModelConfig {
301
599
  fields: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder>;
302
- layout?: (layout: ILayoutBuilder) => LayoutNode[];
600
+ layout?: (layout: ILayoutBuilder) => ILayoutNodeBuilder[];
303
601
  validateOnSubmit?: boolean;
602
+ ruleEvaluators?: IRuleEvaluator[];
304
603
  }
305
604
  export interface ILayoutBuilder {
306
- row(...fieldIds: string[]): IRowNode;
307
- separator(): ISeparatorNode;
308
- tabs(config: {
309
- id?: string;
310
- renderer?: string;
311
- tabs: ITabDefinition[];
312
- }): ITabsNode;
313
- element(renderer: string, props?: Record<string, unknown>): IElementNode;
314
- }
315
- export interface IFieldBuilder<TType extends string = string> {
605
+ row(...fieldIds: string[]): IRowBuilder;
606
+ separator(): ISeparatorBuilder;
607
+ tabs(id?: string): ITabsBuilder;
608
+ element(renderer: string, props?: Record<string, unknown>): IElementBuilder;
609
+ /**
610
+ * Reference an object field and register its inner layout.
611
+ *
612
+ * Non-templated: pass a single layout factory; the layout applies to the
613
+ * single object or to every list item. Templated: pass a map of factories
614
+ * keyed by template id; each entry applies when that template is active
615
+ * (or for each list item with that template). Templates without an entry
616
+ * fall back to default one-row-per-visible-child.
617
+ */
618
+ object(fieldName: string, layout: (layout: ILayoutBuilder) => ILayoutNodeBuilder[]): IObjectBuilder;
619
+ object(fieldName: string, templateLayouts: Record<string, (layout: ILayoutBuilder) => ILayoutNodeBuilder[]>): IObjectBuilder;
620
+ }
621
+ export interface IFieldBuilder<TType extends string = string, TOptions extends boolean = false, TValue = unknown> {
622
+ readonly __valueType?: TValue;
316
623
  label(text: string): this;
317
624
  help(text: string): this;
318
625
  description(text: string): this;
@@ -320,28 +627,64 @@ export interface IFieldBuilder<TType extends string = string> {
320
627
  placeholder(text: string): this;
321
628
  schema(zodSchema: z.ZodTypeAny): this;
322
629
  defaultValue(value: unknown): this;
323
- renderer<TName extends FieldRendererName<TType>>(name: TName, ...args: undefined extends FieldRendererSettings<TName> ? [settings?: FieldRendererSettings<TName>] : FieldRendererSettings<TName> extends undefined ? [] : [settings: FieldRendererSettings<TName>]): this;
630
+ renderer<TName extends FieldRendererName<TType, TOptions>>(name: TName, ...args: undefined extends FieldRendererSettings<TName> ? [settings?: FieldRendererSettings<TName>] : FieldRendererSettings<TName> extends undefined ? [] : [settings: FieldRendererSettings<TName>]): this;
324
631
  hidden(): this;
325
632
  required(message?: string): this;
633
+ /**
634
+ * Conditional required check. Multiple `requiredWhen()` calls chain — the
635
+ * first one to return `true` for the current form state makes the field
636
+ * required. Built-in `.required()` (if set) is evaluated alongside.
637
+ */
638
+ requiredWhen(fn: (form: IFormModel) => boolean, message?: string): this;
639
+ list(): this;
326
640
  disabled(value?: boolean): this;
641
+ rules(rules: IRule[]): this;
327
642
  beforeChange(fn: BeforeChangeCallback): this;
328
643
  afterChange(fn: AfterChangeCallback): this;
329
644
  afterSetValue(fn: AfterSetValueCallback): this;
330
645
  onBlur(fn: OnBlurCallback): this;
646
+ cloneValue(fn: CloneValueCallback): this;
647
+ getTags(): string[];
648
+ tags(tags: string[]): this;
649
+ /**
650
+ * Mark this field as a derived value computed from `fn(form)`. The field
651
+ * stays editable; user edits are accepted but the computed value continues
652
+ * to flow whenever a dependency changes. To make the user "win", use
653
+ * `computedUntilDirty()` instead.
654
+ */
655
+ computed(fn: ComputedFieldCallback): this;
656
+ /**
657
+ * Same as `computed`, but the field switches to manual mode the first time
658
+ * its value is changed via the UI. After that, `fn(form)` no longer
659
+ * overrides user input.
660
+ */
661
+ computedUntilDirty(fn: ComputedFieldCallback): this;
331
662
  build(name: string): IFieldConfig;
332
663
  }
333
- export interface ISelectFieldBuilder extends IFieldBuilder<"select"> {
334
- options(opts: IValueOption[] | ((form: IFormModel) => IValueOption[])): this;
664
+ export interface IOptionsFieldBuilder<TType extends string, TValue = unknown> extends IFieldBuilder<TType, false, TValue> {
665
+ options(opts: IValueOption<OptionValueType<TType>>[] | ((form: IFormModel) => IValueOption<OptionValueType<TType>>[])): IFieldBuilder<TType, true, TValue>;
335
666
  }
336
- export interface IObjectFieldBuilder extends IFieldBuilder<"object"> {
667
+ export interface IObjectFieldBuilder extends IFieldBuilder<"object", false, Record<string, unknown> | null> {
337
668
  fields(fn: (registry: IFieldBuilderRegistry) => Record<string, IFieldBuilder>): this;
338
669
  list(): this;
339
670
  listSchema(schema: z.ZodTypeAny): this;
671
+ template(id: string, configure: (t: ITemplateBuilder) => void): this;
340
672
  }
341
673
  export interface IFieldBuilderRegistry {
342
- text(): IFieldBuilder<"text">;
343
- select(): ISelectFieldBuilder;
344
- object(): IObjectFieldBuilder;
674
+ }
675
+ export interface IFieldTypeFactory {
676
+ readonly type: string;
677
+ create(registry: IFieldBuilderRegistry): IFieldBuilder;
678
+ }
679
+ export declare const FieldType: import("@webiny/di").Abstraction<IFieldTypeFactory>;
680
+ export declare namespace FieldType {
681
+ type Interface = IFieldTypeFactory;
682
+ type FieldBuilder = IFieldBuilder;
683
+ type FieldBuilderRegistry = IFieldBuilderRegistry;
684
+ }
685
+ export declare const FieldBuilderRegistry: import("@webiny/di").Abstraction<IFieldBuilderRegistry>;
686
+ export declare namespace FieldBuilderRegistry {
687
+ type Interface = IFieldBuilderRegistry;
345
688
  }
346
689
  export declare const FormModelFactory: import("@webiny/di").Abstraction<IFormModelFactory>;
347
690
  export declare namespace FormModelFactory {
@@ -349,7 +692,14 @@ export declare namespace FormModelFactory {
349
692
  type Config = IFormModelConfig;
350
693
  type LayoutBuilder = ILayoutBuilder;
351
694
  type FieldBuilder = IFieldBuilder;
352
- type SelectFieldBuilder = ISelectFieldBuilder;
695
+ type OptionsFieldBuilder<TType extends string> = IOptionsFieldBuilder<TType>;
353
696
  type ObjectFieldBuilder = IObjectFieldBuilder;
354
697
  type FieldBuilderRegistry = IFieldBuilderRegistry;
355
698
  }
699
+ export declare const RuleEvaluator: import("@webiny/di").Abstraction<IRuleEvaluator>;
700
+ export declare namespace RuleEvaluator {
701
+ type Interface = IRuleEvaluator;
702
+ type Rule = IRule;
703
+ type Action = RuleAction;
704
+ }
705
+ export {};