@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
@@ -0,0 +1,230 @@
1
+ import React, { useMemo } from "react";
2
+ import { observer } from "mobx-react-lite";
3
+ import { useFeature } from "@webiny/app";
4
+ import { Button } from "@webiny/admin-ui";
5
+ import { FormView } from "../FormView.js";
6
+ import { FormModelFeature } from "../feature.js";
7
+ import { FieldRenderersDemoPresenter } from "./FieldRenderersDemoPresenter.js";
8
+ import { FormModelDemoPresenter } from "./FormModelDemoPresenter.js";
9
+ import { FormModelPhase8c1Presenter } from "./FormModelPhase8c1Presenter.js";
10
+ import { FormModelPhase11Presenter } from "./FormModelPhase11Presenter.js";
11
+ export const FormModelDemo = observer(() => {
12
+ const {
13
+ formModelFactory
14
+ } = useFeature(FormModelFeature);
15
+ const presenter = useMemo(() => new FormModelDemoPresenter(formModelFactory), [formModelFactory]);
16
+ const {
17
+ form,
18
+ data,
19
+ lastSubmitted,
20
+ isSubmitting,
21
+ runtimeTemplateAdded,
22
+ textTemplateRemoved
23
+ } = presenter.vm;
24
+ return /*#__PURE__*/React.createElement("div", {
25
+ className: "p-lg flex flex-col gap-2xl max-w-4xl mx-auto"
26
+ }, /*#__PURE__*/React.createElement(FieldRenderersSection, null), /*#__PURE__*/React.createElement("div", {
27
+ className: "flex flex-col gap-lg"
28
+ }, /*#__PURE__*/React.createElement("div", {
29
+ className: "flex flex-col gap-sm"
30
+ }, /*#__PURE__*/React.createElement("h2", {
31
+ className: "text-xl font-semibold"
32
+ }, "FormModel Demo \u2014 Phase 8"), /*#__PURE__*/React.createElement("p", {
33
+ className: "text-sm text-neutral-strong"
34
+ }, "Exercises the full Phase 8 surface: single-object templates (\"Content Block\"), templated lists (\"Page Sections\"), per-template layouts (Hero spans two rows; Rich Text uses a single row; templates without a layout entry fall back to default), and runtime template management via", " ", /*#__PURE__*/React.createElement("code", null, "field.templates.add/remove"), ". Change Plan to", " ", /*#__PURE__*/React.createElement("code", null, "enterprise"), " to reveal the \"Premium Widget\" template in the Content Block picker.")), /*#__PURE__*/React.createElement(FormView, {
35
+ form: form
36
+ }), /*#__PURE__*/React.createElement("div", {
37
+ className: "flex flex-wrap gap-sm"
38
+ }, /*#__PURE__*/React.createElement(Button, {
39
+ text: isSubmitting ? "Submitting…" : "Submit",
40
+ variant: "primary",
41
+ onClick: () => presenter.submit(),
42
+ disabled: isSubmitting
43
+ }), /*#__PURE__*/React.createElement(Button, {
44
+ text: "Reset",
45
+ variant: "secondary",
46
+ onClick: () => presenter.reset(),
47
+ disabled: isSubmitting
48
+ }), /*#__PURE__*/React.createElement(Button, {
49
+ text: runtimeTemplateAdded ? 'Remove "Runtime Banner" from sections' : 'Add "Runtime Banner" to sections',
50
+ variant: "tertiary",
51
+ onClick: () => presenter.toggleRuntimeTemplate()
52
+ }), /*#__PURE__*/React.createElement(Button, {
53
+ text: textTemplateRemoved ? 'Restore "Rich Text" on content' : 'Remove "Rich Text" from content',
54
+ variant: "tertiary",
55
+ onClick: () => presenter.toggleTextTemplate()
56
+ })), /*#__PURE__*/React.createElement("div", {
57
+ className: "grid grid-cols-2 gap-md"
58
+ }, /*#__PURE__*/React.createElement(DataPanel, {
59
+ title: "Current getData()",
60
+ data: data
61
+ }), /*#__PURE__*/React.createElement(DataPanel, {
62
+ title: "Last submitted",
63
+ data: lastSubmitted
64
+ }))), /*#__PURE__*/React.createElement(Phase8c1Section, null), /*#__PURE__*/React.createElement(Phase11Section, null));
65
+ });
66
+ const FieldRenderersSection = observer(() => {
67
+ const {
68
+ formModelFactory
69
+ } = useFeature(FormModelFeature);
70
+ const presenter = useMemo(() => new FieldRenderersDemoPresenter(formModelFactory), [formModelFactory]);
71
+ const {
72
+ form,
73
+ data,
74
+ lastSubmitted,
75
+ isSubmitting,
76
+ formErrors
77
+ } = presenter.vm;
78
+ return /*#__PURE__*/React.createElement("div", {
79
+ className: "flex flex-col gap-lg"
80
+ }, /*#__PURE__*/React.createElement("div", {
81
+ className: "flex flex-col gap-sm"
82
+ }, /*#__PURE__*/React.createElement("h2", {
83
+ className: "text-xl font-semibold"
84
+ }, "Field Renderers Showcase"), /*#__PURE__*/React.createElement("p", {
85
+ className: "text-sm text-neutral-strong"
86
+ }, "All field renderer variants: text, number, boolean, select (dropdown/radio/checkboxes), date/time (4 variants), tags, textarea, multi-value lists, hidden, and dynamic zones. Renderers not yet implemented show nothing (console warning).")), /*#__PURE__*/React.createElement(FormView, {
87
+ form: form
88
+ }), formErrors.length > 0 && /*#__PURE__*/React.createElement("div", {
89
+ className: "flex flex-col gap-xs"
90
+ }, /*#__PURE__*/React.createElement("div", {
91
+ className: "text-sm font-medium"
92
+ }, "Form errors"), /*#__PURE__*/React.createElement("ul", {
93
+ className: "text-xs text-error-strong list-disc pl-md"
94
+ }, formErrors.map((e, i) => /*#__PURE__*/React.createElement("li", {
95
+ key: i
96
+ }, e.path ? /*#__PURE__*/React.createElement("button", {
97
+ type: "button",
98
+ className: "underline cursor-pointer hover:text-error-default",
99
+ onClick: () => presenter.focusField(e.path)
100
+ }, /*#__PURE__*/React.createElement("code", null, e.path)) : null, " ", e.message)))), /*#__PURE__*/React.createElement("div", {
101
+ className: "flex flex-wrap gap-sm"
102
+ }, /*#__PURE__*/React.createElement(Button, {
103
+ text: isSubmitting ? "Submitting…" : "Submit",
104
+ variant: "primary",
105
+ onClick: () => presenter.submit(),
106
+ disabled: isSubmitting
107
+ }), /*#__PURE__*/React.createElement(Button, {
108
+ text: "Reset",
109
+ variant: "secondary",
110
+ onClick: () => presenter.reset(),
111
+ disabled: isSubmitting
112
+ })), /*#__PURE__*/React.createElement("div", {
113
+ className: "grid grid-cols-2 gap-md"
114
+ }, /*#__PURE__*/React.createElement(DataPanel, {
115
+ title: "Current getData()",
116
+ data: data
117
+ }), /*#__PURE__*/React.createElement(DataPanel, {
118
+ title: "Last submitted",
119
+ data: lastSubmitted
120
+ })));
121
+ });
122
+ const Phase8c1Section = observer(() => {
123
+ const {
124
+ formModelFactory
125
+ } = useFeature(FormModelFeature);
126
+ const presenter = useMemo(() => new FormModelPhase8c1Presenter(formModelFactory), [formModelFactory]);
127
+ const {
128
+ form,
129
+ data,
130
+ lastSubmitted,
131
+ isSubmitting
132
+ } = presenter.vm;
133
+ return /*#__PURE__*/React.createElement("div", {
134
+ className: "flex flex-col gap-lg border-t border-neutral-dimmed pt-lg"
135
+ }, /*#__PURE__*/React.createElement("div", {
136
+ className: "flex flex-col gap-sm"
137
+ }, /*#__PURE__*/React.createElement("h2", {
138
+ className: "text-xl font-semibold"
139
+ }, "FormModel Demo \u2014 Phase 8c.1"), /*#__PURE__*/React.createElement("p", {
140
+ className: "text-sm text-neutral-strong"
141
+ }, "Nested object layouts. A top-level ", /*#__PURE__*/React.createElement("code", null, "page"), " object whose inner layout is split across tabs (General / SEO). The SEO tab contains a nested", " ", /*#__PURE__*/React.createElement("code", null, "layout.object(\"seo\", ...)"), " with its own row layout, and the SEO object itself contains another nested", " ", /*#__PURE__*/React.createElement("code", null, "layout.object(\"og\", ...)"), " for the Open Graph fields. Phase 8c.1 walks the inner layout (including across tabs) and forwards each nested", " ", /*#__PURE__*/React.createElement("code", null, "layout.object()"), " to the matching child at build time.")), /*#__PURE__*/React.createElement(FormView, {
142
+ form: form
143
+ }), /*#__PURE__*/React.createElement("div", {
144
+ className: "flex flex-wrap gap-sm"
145
+ }, /*#__PURE__*/React.createElement(Button, {
146
+ text: isSubmitting ? "Submitting…" : "Submit",
147
+ variant: "primary",
148
+ onClick: () => presenter.submit(),
149
+ disabled: isSubmitting
150
+ }), /*#__PURE__*/React.createElement(Button, {
151
+ text: "Reset",
152
+ variant: "secondary",
153
+ onClick: () => presenter.reset(),
154
+ disabled: isSubmitting
155
+ })), /*#__PURE__*/React.createElement("div", {
156
+ className: "grid grid-cols-2 gap-md"
157
+ }, /*#__PURE__*/React.createElement(DataPanel, {
158
+ title: "Current getData()",
159
+ data: data
160
+ }), /*#__PURE__*/React.createElement(DataPanel, {
161
+ title: "Last submitted",
162
+ data: lastSubmitted
163
+ })));
164
+ });
165
+ const Phase11Section = observer(() => {
166
+ const {
167
+ formModelFactory
168
+ } = useFeature(FormModelFeature);
169
+ const presenter = useMemo(() => new FormModelPhase11Presenter(formModelFactory), [formModelFactory]);
170
+ const {
171
+ form,
172
+ data,
173
+ lastSubmitted,
174
+ isSubmitting,
175
+ formErrors
176
+ } = presenter.vm;
177
+ return /*#__PURE__*/React.createElement("div", {
178
+ className: "flex flex-col gap-lg border-t border-neutral-dimmed pt-lg"
179
+ }, /*#__PURE__*/React.createElement("div", {
180
+ className: "flex flex-col gap-sm"
181
+ }, /*#__PURE__*/React.createElement("h2", {
182
+ className: "text-xl font-semibold"
183
+ }, "FormModel Demo \u2014 Phase 11"), /*#__PURE__*/React.createElement("p", {
184
+ className: "text-sm text-neutral-strong"
185
+ }, "Conditional required (", /*#__PURE__*/React.createElement("code", null, "requiredWhen"), " on Seats \u2014 chained builder + modifier rules), derived fields (", /*#__PURE__*/React.createElement("code", null, "computed"), " Full Name and", " ", /*#__PURE__*/React.createElement("code", null, "computedUntilDirty"), " Slug), modifier-style child addition via", " ", /*#__PURE__*/React.createElement("code", null, "field.as(\"object\").fields()"), " adding Company/Bio to Profile, form-level rules (", /*#__PURE__*/React.createElement("code", null, "addRule"), " with a Zod refinement for password match plus an imperative slug-length rule), and a layout assembled via", " ", /*#__PURE__*/React.createElement("code", null, "setLayout"), ".")), /*#__PURE__*/React.createElement(FormView, {
186
+ form: form
187
+ }), formErrors.length > 0 && /*#__PURE__*/React.createElement("div", {
188
+ className: "flex flex-col gap-xs"
189
+ }, /*#__PURE__*/React.createElement("div", {
190
+ className: "text-sm font-medium"
191
+ }, "Form errors"), /*#__PURE__*/React.createElement("ul", {
192
+ className: "text-xs text-error-strong list-disc pl-md"
193
+ }, formErrors.map((e, i) => /*#__PURE__*/React.createElement("li", {
194
+ key: i
195
+ }, e.path ? /*#__PURE__*/React.createElement("code", null, e.path) : null, " ", e.message)))), /*#__PURE__*/React.createElement("div", {
196
+ className: "flex flex-wrap gap-sm"
197
+ }, /*#__PURE__*/React.createElement(Button, {
198
+ text: isSubmitting ? "Submitting…" : "Submit",
199
+ variant: "primary",
200
+ onClick: () => presenter.submit(),
201
+ disabled: isSubmitting
202
+ }), /*#__PURE__*/React.createElement(Button, {
203
+ text: "Reset",
204
+ variant: "secondary",
205
+ onClick: () => presenter.reset(),
206
+ disabled: isSubmitting
207
+ })), /*#__PURE__*/React.createElement("div", {
208
+ className: "grid grid-cols-2 gap-md"
209
+ }, /*#__PURE__*/React.createElement(DataPanel, {
210
+ title: "Current getData()",
211
+ data: data
212
+ }), /*#__PURE__*/React.createElement(DataPanel, {
213
+ title: "Last submitted",
214
+ data: lastSubmitted
215
+ })));
216
+ });
217
+ const DataPanel = ({
218
+ title,
219
+ data
220
+ }) => {
221
+ return /*#__PURE__*/React.createElement("div", {
222
+ className: "flex flex-col gap-xs"
223
+ }, /*#__PURE__*/React.createElement("div", {
224
+ className: "text-sm font-medium"
225
+ }, title), /*#__PURE__*/React.createElement("pre", {
226
+ className: "text-xs bg-neutral-subtle p-sm rounded border border-neutral-dimmed overflow-auto"
227
+ }, data === null ? "null" : JSON.stringify(data, null, 2)));
228
+ };
229
+
230
+ //# sourceMappingURL=FormModelDemo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useMemo","observer","useFeature","Button","FormView","FormModelFeature","FieldRenderersDemoPresenter","FormModelDemoPresenter","FormModelPhase8c1Presenter","FormModelPhase11Presenter","FormModelDemo","formModelFactory","presenter","form","data","lastSubmitted","isSubmitting","runtimeTemplateAdded","textTemplateRemoved","vm","createElement","className","FieldRenderersSection","text","variant","onClick","submit","disabled","reset","toggleRuntimeTemplate","toggleTextTemplate","DataPanel","title","Phase8c1Section","Phase11Section","formErrors","length","map","e","i","key","path","type","focusField","message","JSON","stringify"],"sources":["FormModelDemo.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useFeature } from \"@webiny/app\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { FormView } from \"../FormView.js\";\nimport { FormModelFeature } from \"../feature.js\";\nimport { FieldRenderersDemoPresenter } from \"./FieldRenderersDemoPresenter.js\";\nimport { FormModelDemoPresenter } from \"./FormModelDemoPresenter.js\";\nimport { FormModelPhase8c1Presenter } from \"./FormModelPhase8c1Presenter.js\";\nimport { FormModelPhase11Presenter } from \"./FormModelPhase11Presenter.js\";\n\nexport const FormModelDemo = observer(() => {\n const { formModelFactory } = useFeature(FormModelFeature);\n const presenter = useMemo(\n () => new FormModelDemoPresenter(formModelFactory),\n [formModelFactory]\n );\n\n const { form, data, lastSubmitted, isSubmitting, runtimeTemplateAdded, textTemplateRemoved } =\n presenter.vm;\n\n return (\n <div className={\"p-lg flex flex-col gap-2xl max-w-4xl mx-auto\"}>\n <FieldRenderersSection />\n\n <div className={\"flex flex-col gap-lg\"}>\n <div className={\"flex flex-col gap-sm\"}>\n <h2 className={\"text-xl font-semibold\"}>FormModel Demo — Phase 8</h2>\n <p className={\"text-sm text-neutral-strong\"}>\n Exercises the full Phase 8 surface: single-object templates (&quot;Content\n Block&quot;), templated lists (&quot;Page Sections&quot;), per-template\n layouts (Hero spans two rows; Rich Text uses a single row; templates without\n a layout entry fall back to default), and runtime template management via{\" \"}\n <code>field.templates.add/remove</code>. Change Plan to{\" \"}\n <code>enterprise</code> to reveal the &quot;Premium Widget&quot; template in\n the Content Block picker.\n </p>\n </div>\n\n <FormView form={form} />\n\n <div className={\"flex flex-wrap gap-sm\"}>\n <Button\n text={isSubmitting ? \"Submitting…\" : \"Submit\"}\n variant={\"primary\"}\n onClick={() => presenter.submit()}\n disabled={isSubmitting}\n />\n <Button\n text={\"Reset\"}\n variant={\"secondary\"}\n onClick={() => presenter.reset()}\n disabled={isSubmitting}\n />\n <Button\n text={\n runtimeTemplateAdded\n ? 'Remove \"Runtime Banner\" from sections'\n : 'Add \"Runtime Banner\" to sections'\n }\n variant={\"tertiary\"}\n onClick={() => presenter.toggleRuntimeTemplate()}\n />\n <Button\n text={\n textTemplateRemoved\n ? 'Restore \"Rich Text\" on content'\n : 'Remove \"Rich Text\" from content'\n }\n variant={\"tertiary\"}\n onClick={() => presenter.toggleTextTemplate()}\n />\n </div>\n\n <div className={\"grid grid-cols-2 gap-md\"}>\n <DataPanel title={\"Current getData()\"} data={data} />\n <DataPanel title={\"Last submitted\"} data={lastSubmitted} />\n </div>\n </div>\n\n <Phase8c1Section />\n\n <Phase11Section />\n </div>\n );\n});\n\nconst FieldRenderersSection = observer(() => {\n const { formModelFactory } = useFeature(FormModelFeature);\n const presenter = useMemo(\n () => new FieldRenderersDemoPresenter(formModelFactory),\n [formModelFactory]\n );\n\n const { form, data, lastSubmitted, isSubmitting, formErrors } = presenter.vm;\n\n return (\n <div className={\"flex flex-col gap-lg\"}>\n <div className={\"flex flex-col gap-sm\"}>\n <h2 className={\"text-xl font-semibold\"}>Field Renderers Showcase</h2>\n <p className={\"text-sm text-neutral-strong\"}>\n All field renderer variants: text, number, boolean, select\n (dropdown/radio/checkboxes), date/time (4 variants), tags, textarea, multi-value\n lists, hidden, and dynamic zones. Renderers not yet implemented show nothing\n (console warning).\n </p>\n </div>\n\n <FormView form={form} />\n\n {formErrors.length > 0 && (\n <div className={\"flex flex-col gap-xs\"}>\n <div className={\"text-sm font-medium\"}>Form errors</div>\n <ul className={\"text-xs text-error-strong list-disc pl-md\"}>\n {formErrors.map((e, i) => (\n <li key={i}>\n {e.path ? (\n <button\n type={\"button\"}\n className={\n \"underline cursor-pointer hover:text-error-default\"\n }\n onClick={() => presenter.focusField(e.path)}\n >\n <code>{e.path}</code>\n </button>\n ) : null}{\" \"}\n {e.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div className={\"flex flex-wrap gap-sm\"}>\n <Button\n text={isSubmitting ? \"Submitting…\" : \"Submit\"}\n variant={\"primary\"}\n onClick={() => presenter.submit()}\n disabled={isSubmitting}\n />\n <Button\n text={\"Reset\"}\n variant={\"secondary\"}\n onClick={() => presenter.reset()}\n disabled={isSubmitting}\n />\n </div>\n\n <div className={\"grid grid-cols-2 gap-md\"}>\n <DataPanel title={\"Current getData()\"} data={data} />\n <DataPanel title={\"Last submitted\"} data={lastSubmitted} />\n </div>\n </div>\n );\n});\n\nconst Phase8c1Section = observer(() => {\n const { formModelFactory } = useFeature(FormModelFeature);\n const presenter = useMemo(\n () => new FormModelPhase8c1Presenter(formModelFactory),\n [formModelFactory]\n );\n\n const { form, data, lastSubmitted, isSubmitting } = presenter.vm;\n\n return (\n <div className={\"flex flex-col gap-lg border-t border-neutral-dimmed pt-lg\"}>\n <div className={\"flex flex-col gap-sm\"}>\n <h2 className={\"text-xl font-semibold\"}>FormModel Demo — Phase 8c.1</h2>\n <p className={\"text-sm text-neutral-strong\"}>\n Nested object layouts. A top-level <code>page</code> object whose inner layout\n is split across tabs (General / SEO). The SEO tab contains a nested{\" \"}\n <code>layout.object(&quot;seo&quot;, ...)</code> with its own row layout, and\n the SEO object itself contains another nested{\" \"}\n <code>layout.object(&quot;og&quot;, ...)</code> for the Open Graph fields. Phase\n 8c.1 walks the inner layout (including across tabs) and forwards each nested{\" \"}\n <code>layout.object()</code> to the matching child at build time.\n </p>\n </div>\n\n <FormView form={form} />\n\n <div className={\"flex flex-wrap gap-sm\"}>\n <Button\n text={isSubmitting ? \"Submitting…\" : \"Submit\"}\n variant={\"primary\"}\n onClick={() => presenter.submit()}\n disabled={isSubmitting}\n />\n <Button\n text={\"Reset\"}\n variant={\"secondary\"}\n onClick={() => presenter.reset()}\n disabled={isSubmitting}\n />\n </div>\n\n <div className={\"grid grid-cols-2 gap-md\"}>\n <DataPanel title={\"Current getData()\"} data={data} />\n <DataPanel title={\"Last submitted\"} data={lastSubmitted} />\n </div>\n </div>\n );\n});\n\nconst Phase11Section = observer(() => {\n const { formModelFactory } = useFeature(FormModelFeature);\n const presenter = useMemo(\n () => new FormModelPhase11Presenter(formModelFactory),\n [formModelFactory]\n );\n\n const { form, data, lastSubmitted, isSubmitting, formErrors } = presenter.vm;\n\n return (\n <div className={\"flex flex-col gap-lg border-t border-neutral-dimmed pt-lg\"}>\n <div className={\"flex flex-col gap-sm\"}>\n <h2 className={\"text-xl font-semibold\"}>FormModel Demo — Phase 11</h2>\n <p className={\"text-sm text-neutral-strong\"}>\n Conditional required (<code>requiredWhen</code> on Seats — chained builder +\n modifier rules), derived fields (<code>computed</code> Full Name and{\" \"}\n <code>computedUntilDirty</code> Slug), modifier-style child addition via{\" \"}\n <code>field.as(&quot;object&quot;).fields()</code> adding Company/Bio to\n Profile, form-level rules (<code>addRule</code> with a Zod refinement for\n password match plus an imperative slug-length rule), and a layout assembled via{\" \"}\n <code>setLayout</code>.\n </p>\n </div>\n\n <FormView form={form} />\n\n {formErrors.length > 0 && (\n <div className={\"flex flex-col gap-xs\"}>\n <div className={\"text-sm font-medium\"}>Form errors</div>\n <ul className={\"text-xs text-error-strong list-disc pl-md\"}>\n {formErrors.map((e, i) => (\n <li key={i}>\n {e.path ? <code>{e.path}</code> : null} {e.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n <div className={\"flex flex-wrap gap-sm\"}>\n <Button\n text={isSubmitting ? \"Submitting…\" : \"Submit\"}\n variant={\"primary\"}\n onClick={() => presenter.submit()}\n disabled={isSubmitting}\n />\n <Button\n text={\"Reset\"}\n variant={\"secondary\"}\n onClick={() => presenter.reset()}\n disabled={isSubmitting}\n />\n </div>\n\n <div className={\"grid grid-cols-2 gap-md\"}>\n <DataPanel title={\"Current getData()\"} data={data} />\n <DataPanel title={\"Last submitted\"} data={lastSubmitted} />\n </div>\n </div>\n );\n});\n\nconst DataPanel = ({ title, data }: { title: string; data: unknown }) => {\n return (\n <div className={\"flex flex-col gap-xs\"}>\n <div className={\"text-sm font-medium\"}>{title}</div>\n <pre\n className={\n \"text-xs bg-neutral-subtle p-sm rounded border border-neutral-dimmed overflow-auto\"\n }\n >\n {data === null ? \"null\" : JSON.stringify(data, null, 2)}\n </pre>\n </div>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,OAAO,QAAQ,OAAO;AACtC,SAASC,QAAQ,QAAQ,iBAAiB;AAC1C,SAASC,UAAU,QAAQ,aAAa;AACxC,SAASC,MAAM,QAAQ,kBAAkB;AACzC,SAASC,QAAQ;AACjB,SAASC,gBAAgB;AACzB,SAASC,2BAA2B;AACpC,SAASC,sBAAsB;AAC/B,SAASC,0BAA0B;AACnC,SAASC,yBAAyB;AAElC,OAAO,MAAMC,aAAa,GAAGT,QAAQ,CAAC,MAAM;EACxC,MAAM;IAAEU;EAAiB,CAAC,GAAGT,UAAU,CAACG,gBAAgB,CAAC;EACzD,MAAMO,SAAS,GAAGZ,OAAO,CACrB,MAAM,IAAIO,sBAAsB,CAACI,gBAAgB,CAAC,EAClD,CAACA,gBAAgB,CACrB,CAAC;EAED,MAAM;IAAEE,IAAI;IAAEC,IAAI;IAAEC,aAAa;IAAEC,YAAY;IAAEC,oBAAoB;IAAEC;EAAoB,CAAC,GACxFN,SAAS,CAACO,EAAE;EAEhB,oBACIpB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA+C,gBAC3DtB,KAAA,CAAAqB,aAAA,CAACE,qBAAqB,MAAE,CAAC,eAEzBvB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAAwB,GAAC,+BAA4B,CAAC,eACrEtB,KAAA,CAAAqB,aAAA;IAAGC,SAAS,EAAE;EAA8B,GAAC,2RAIgC,EAAC,GAAG,eAC7EtB,KAAA,CAAAqB,aAAA,eAAM,4BAAgC,CAAC,oBAAgB,EAAC,GAAG,eAC3DrB,KAAA,CAAAqB,aAAA,eAAM,YAAgB,CAAC,2EAExB,CACF,CAAC,eAENrB,KAAA,CAAAqB,aAAA,CAAChB,QAAQ;IAACS,IAAI,EAAEA;EAAK,CAAE,CAAC,eAExBd,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAwB,gBACpCtB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAEP,YAAY,GAAG,aAAa,GAAG,QAAS;IAC9CQ,OAAO,EAAE,SAAU;IACnBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACc,MAAM,CAAC,CAAE;IAClCC,QAAQ,EAAEX;EAAa,CAC1B,CAAC,eACFjB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAE,OAAQ;IACdC,OAAO,EAAE,WAAY;IACrBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACgB,KAAK,CAAC,CAAE;IACjCD,QAAQ,EAAEX;EAAa,CAC1B,CAAC,eACFjB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EACAN,oBAAoB,GACd,uCAAuC,GACvC,kCACT;IACDO,OAAO,EAAE,UAAW;IACpBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACiB,qBAAqB,CAAC;EAAE,CACpD,CAAC,eACF9B,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EACAL,mBAAmB,GACb,gCAAgC,GAChC,iCACT;IACDM,OAAO,EAAE,UAAW;IACpBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACkB,kBAAkB,CAAC;EAAE,CACjD,CACA,CAAC,eAEN/B,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA0B,gBACtCtB,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,mBAAoB;IAAClB,IAAI,EAAEA;EAAK,CAAE,CAAC,eACrDf,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,gBAAiB;IAAClB,IAAI,EAAEC;EAAc,CAAE,CACzD,CACJ,CAAC,eAENhB,KAAA,CAAAqB,aAAA,CAACa,eAAe,MAAE,CAAC,eAEnBlC,KAAA,CAAAqB,aAAA,CAACc,cAAc,MAAE,CAChB,CAAC;AAEd,CAAC,CAAC;AAEF,MAAMZ,qBAAqB,GAAGrB,QAAQ,CAAC,MAAM;EACzC,MAAM;IAAEU;EAAiB,CAAC,GAAGT,UAAU,CAACG,gBAAgB,CAAC;EACzD,MAAMO,SAAS,GAAGZ,OAAO,CACrB,MAAM,IAAIM,2BAA2B,CAACK,gBAAgB,CAAC,EACvD,CAACA,gBAAgB,CACrB,CAAC;EAED,MAAM;IAAEE,IAAI;IAAEC,IAAI;IAAEC,aAAa;IAAEC,YAAY;IAAEmB;EAAW,CAAC,GAAGvB,SAAS,CAACO,EAAE;EAE5E,oBACIpB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAAwB,GAAC,0BAA4B,CAAC,eACrEtB,KAAA,CAAAqB,aAAA;IAAGC,SAAS,EAAE;EAA8B,GAAC,6OAK1C,CACF,CAAC,eAENtB,KAAA,CAAAqB,aAAA,CAAChB,QAAQ;IAACS,IAAI,EAAEA;EAAK,CAAE,CAAC,EAEvBsB,UAAU,CAACC,MAAM,GAAG,CAAC,iBAClBrC,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAsB,GAAC,aAAgB,CAAC,eACxDtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAA4C,GACtDc,UAAU,CAACE,GAAG,CAAC,CAACC,CAAC,EAAEC,CAAC,kBACjBxC,KAAA,CAAAqB,aAAA;IAAIoB,GAAG,EAAED;EAAE,GACND,CAAC,CAACG,IAAI,gBACH1C,KAAA,CAAAqB,aAAA;IACIsB,IAAI,EAAE,QAAS;IACfrB,SAAS,EACL,mDACH;IACDI,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAAC+B,UAAU,CAACL,CAAC,CAACG,IAAI;EAAE,gBAE5C1C,KAAA,CAAAqB,aAAA,eAAOkB,CAAC,CAACG,IAAW,CAChB,CAAC,GACT,IAAI,EAAE,GAAG,EACZH,CAAC,CAACM,OACH,CACP,CACD,CACH,CACR,eAED7C,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAwB,gBACpCtB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAEP,YAAY,GAAG,aAAa,GAAG,QAAS;IAC9CQ,OAAO,EAAE,SAAU;IACnBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACc,MAAM,CAAC,CAAE;IAClCC,QAAQ,EAAEX;EAAa,CAC1B,CAAC,eACFjB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAE,OAAQ;IACdC,OAAO,EAAE,WAAY;IACrBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACgB,KAAK,CAAC,CAAE;IACjCD,QAAQ,EAAEX;EAAa,CAC1B,CACA,CAAC,eAENjB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA0B,gBACtCtB,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,mBAAoB;IAAClB,IAAI,EAAEA;EAAK,CAAE,CAAC,eACrDf,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,gBAAiB;IAAClB,IAAI,EAAEC;EAAc,CAAE,CACzD,CACJ,CAAC;AAEd,CAAC,CAAC;AAEF,MAAMkB,eAAe,GAAGhC,QAAQ,CAAC,MAAM;EACnC,MAAM;IAAEU;EAAiB,CAAC,GAAGT,UAAU,CAACG,gBAAgB,CAAC;EACzD,MAAMO,SAAS,GAAGZ,OAAO,CACrB,MAAM,IAAIQ,0BAA0B,CAACG,gBAAgB,CAAC,EACtD,CAACA,gBAAgB,CACrB,CAAC;EAED,MAAM;IAAEE,IAAI;IAAEC,IAAI;IAAEC,aAAa;IAAEC;EAAa,CAAC,GAAGJ,SAAS,CAACO,EAAE;EAEhE,oBACIpB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA4D,gBACxEtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAAwB,GAAC,kCAA+B,CAAC,eACxEtB,KAAA,CAAAqB,aAAA;IAAGC,SAAS,EAAE;EAA8B,GAAC,qCACN,eAAAtB,KAAA,CAAAqB,aAAA,eAAM,MAAU,CAAC,kGACe,EAAC,GAAG,eACvErB,KAAA,CAAAqB,aAAA,eAAM,6BAAyC,CAAC,+EACH,EAAC,GAAG,eACjDrB,KAAA,CAAAqB,aAAA,eAAM,4BAAwC,CAAC,kHAC6B,EAAC,GAAG,eAChFrB,KAAA,CAAAqB,aAAA,eAAM,iBAAqB,CAAC,yCAC7B,CACF,CAAC,eAENrB,KAAA,CAAAqB,aAAA,CAAChB,QAAQ;IAACS,IAAI,EAAEA;EAAK,CAAE,CAAC,eAExBd,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAwB,gBACpCtB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAEP,YAAY,GAAG,aAAa,GAAG,QAAS;IAC9CQ,OAAO,EAAE,SAAU;IACnBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACc,MAAM,CAAC,CAAE;IAClCC,QAAQ,EAAEX;EAAa,CAC1B,CAAC,eACFjB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAE,OAAQ;IACdC,OAAO,EAAE,WAAY;IACrBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACgB,KAAK,CAAC,CAAE;IACjCD,QAAQ,EAAEX;EAAa,CAC1B,CACA,CAAC,eAENjB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA0B,gBACtCtB,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,mBAAoB;IAAClB,IAAI,EAAEA;EAAK,CAAE,CAAC,eACrDf,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,gBAAiB;IAAClB,IAAI,EAAEC;EAAc,CAAE,CACzD,CACJ,CAAC;AAEd,CAAC,CAAC;AAEF,MAAMmB,cAAc,GAAGjC,QAAQ,CAAC,MAAM;EAClC,MAAM;IAAEU;EAAiB,CAAC,GAAGT,UAAU,CAACG,gBAAgB,CAAC;EACzD,MAAMO,SAAS,GAAGZ,OAAO,CACrB,MAAM,IAAIS,yBAAyB,CAACE,gBAAgB,CAAC,EACrD,CAACA,gBAAgB,CACrB,CAAC;EAED,MAAM;IAAEE,IAAI;IAAEC,IAAI;IAAEC,aAAa;IAAEC,YAAY;IAAEmB;EAAW,CAAC,GAAGvB,SAAS,CAACO,EAAE;EAE5E,oBACIpB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA4D,gBACxEtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAAwB,GAAC,gCAA6B,CAAC,eACtEtB,KAAA,CAAAqB,aAAA;IAAGC,SAAS,EAAE;EAA8B,GAAC,wBACnB,eAAAtB,KAAA,CAAAqB,aAAA,eAAM,cAAkB,CAAC,wEACd,eAAArB,KAAA,CAAAqB,aAAA,eAAM,UAAc,CAAC,kBAAc,EAAC,GAAG,eACxErB,KAAA,CAAAqB,aAAA,eAAM,oBAAwB,CAAC,6CAAyC,EAAC,GAAG,eAC5ErB,KAAA,CAAAqB,aAAA,eAAM,+BAA2C,CAAC,sDACvB,eAAArB,KAAA,CAAAqB,aAAA,eAAM,SAAa,CAAC,8GACgC,EAAC,GAAG,eACnFrB,KAAA,CAAAqB,aAAA,eAAM,WAAe,CAAC,KACvB,CACF,CAAC,eAENrB,KAAA,CAAAqB,aAAA,CAAChB,QAAQ;IAACS,IAAI,EAAEA;EAAK,CAAE,CAAC,EAEvBsB,UAAU,CAACC,MAAM,GAAG,CAAC,iBAClBrC,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAsB,GAAC,aAAgB,CAAC,eACxDtB,KAAA,CAAAqB,aAAA;IAAIC,SAAS,EAAE;EAA4C,GACtDc,UAAU,CAACE,GAAG,CAAC,CAACC,CAAC,EAAEC,CAAC,kBACjBxC,KAAA,CAAAqB,aAAA;IAAIoB,GAAG,EAAED;EAAE,GACND,CAAC,CAACG,IAAI,gBAAG1C,KAAA,CAAAqB,aAAA,eAAOkB,CAAC,CAACG,IAAW,CAAC,GAAG,IAAI,EAAC,GAAC,EAACH,CAAC,CAACM,OAC3C,CACP,CACD,CACH,CACR,eAED7C,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAwB,gBACpCtB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAEP,YAAY,GAAG,aAAa,GAAG,QAAS;IAC9CQ,OAAO,EAAE,SAAU;IACnBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACc,MAAM,CAAC,CAAE;IAClCC,QAAQ,EAAEX;EAAa,CAC1B,CAAC,eACFjB,KAAA,CAAAqB,aAAA,CAACjB,MAAM;IACHoB,IAAI,EAAE,OAAQ;IACdC,OAAO,EAAE,WAAY;IACrBC,OAAO,EAAEA,CAAA,KAAMb,SAAS,CAACgB,KAAK,CAAC,CAAE;IACjCD,QAAQ,EAAEX;EAAa,CAC1B,CACA,CAAC,eAENjB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAA0B,gBACtCtB,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,mBAAoB;IAAClB,IAAI,EAAEA;EAAK,CAAE,CAAC,eACrDf,KAAA,CAAAqB,aAAA,CAACW,SAAS;IAACC,KAAK,EAAE,gBAAiB;IAAClB,IAAI,EAAEC;EAAc,CAAE,CACzD,CACJ,CAAC;AAEd,CAAC,CAAC;AAEF,MAAMgB,SAAS,GAAGA,CAAC;EAAEC,KAAK;EAAElB;AAAuC,CAAC,KAAK;EACrE,oBACIf,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAuB,gBACnCtB,KAAA,CAAAqB,aAAA;IAAKC,SAAS,EAAE;EAAsB,GAAEW,KAAW,CAAC,eACpDjC,KAAA,CAAAqB,aAAA;IACIC,SAAS,EACL;EACH,GAEAP,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG+B,IAAI,CAACC,SAAS,CAAChC,IAAI,EAAE,IAAI,EAAE,CAAC,CACrD,CACJ,CAAC;AAEd,CAAC","ignoreList":[]}
@@ -0,0 +1,22 @@
1
+ import type { IFormModelFactory, IFormVM } from "../abstractions.js";
2
+ export interface FormModelDemoVM {
3
+ form: IFormVM;
4
+ data: Record<string, unknown>;
5
+ lastSubmitted: Record<string, unknown> | null;
6
+ isSubmitting: boolean;
7
+ runtimeTemplateAdded: boolean;
8
+ textTemplateRemoved: boolean;
9
+ }
10
+ export declare class FormModelDemoPresenter {
11
+ private form;
12
+ private lastSubmitted;
13
+ private isSubmitting;
14
+ private runtimeTemplateAdded;
15
+ private textTemplateRemoved;
16
+ constructor(formFactory: IFormModelFactory);
17
+ get vm(): FormModelDemoVM;
18
+ submit(): Promise<void>;
19
+ reset(): void;
20
+ toggleRuntimeTemplate(): void;
21
+ toggleTextTemplate(): void;
22
+ }
@@ -0,0 +1,121 @@
1
+ import { makeAutoObservable, toJS } from "mobx";
2
+ const RUNTIME_TEMPLATE_ID = "runtimeBanner";
3
+ export class FormModelDemoPresenter {
4
+ lastSubmitted = null;
5
+ isSubmitting = false;
6
+ runtimeTemplateAdded = false;
7
+ textTemplateRemoved = false;
8
+ constructor(formFactory) {
9
+ this.form = formFactory.create({
10
+ fields: fields => ({
11
+ title: fields.text().label("Title").required("Title is required"),
12
+ content: fields.object().label("Content Block").required("Pick a template").template("hero", t => {
13
+ t.label("Hero Banner").fields(f => ({
14
+ heading: f.text().label("Heading").required("Required"),
15
+ subheading: f.text().label("Subheading"),
16
+ image: f.text().label("Image URL"),
17
+ cta: f.text().label("Call To Action")
18
+ }));
19
+ }).template("text", t => {
20
+ t.label("Rich Text").fields(f => ({
21
+ body: f.text().label("Body").required("Required")
22
+ }));
23
+ }).template("premium", t => {
24
+ t.label("Premium Widget").visible(form => form.field("plan").getValue() === "enterprise").fields(f => ({
25
+ config: f.text().label("Widget Config")
26
+ }));
27
+ }),
28
+ sections: fields.object().label("Page Sections").list().template("hero", t => {
29
+ t.label("Hero Banner").fields(f => ({
30
+ heading: f.text().label("Heading").required("Required"),
31
+ subheading: f.text().label("Subheading"),
32
+ image: f.text().label("Image URL")
33
+ }));
34
+ }).template("text", t => {
35
+ t.label("Rich Text").fields(f => ({
36
+ body: f.text().label("Body").required("Required")
37
+ }));
38
+ }).template("cta", t => {
39
+ t.label("Call To Action").fields(f => ({
40
+ label: f.text().label("Button Label").required("Required"),
41
+ url: f.text().label("Link URL")
42
+ }));
43
+ }),
44
+ plan: fields.text().label("Plan").defaultValue("free").options([{
45
+ label: "Free",
46
+ value: "free"
47
+ }, {
48
+ label: "Pro",
49
+ value: "pro"
50
+ }, {
51
+ label: "Enterprise",
52
+ value: "enterprise"
53
+ }])
54
+ }),
55
+ layout: layout => [layout.row("title"), layout.row("plan"), layout.object("content", {
56
+ hero: l => [l.row("heading", "subheading"), l.row("image"), l.row("cta")],
57
+ text: l => [l.row("body")]
58
+ }), layout.object("sections", {
59
+ hero: l => [l.row("heading", "subheading"), l.row("image")],
60
+ cta: l => [l.row("label", "url")]
61
+ })]
62
+ });
63
+ makeAutoObservable(this);
64
+ }
65
+ get vm() {
66
+ return {
67
+ form: this.form.vm,
68
+ data: toJS(this.form.getData()),
69
+ lastSubmitted: this.lastSubmitted,
70
+ isSubmitting: this.isSubmitting,
71
+ runtimeTemplateAdded: this.runtimeTemplateAdded,
72
+ textTemplateRemoved: this.textTemplateRemoved
73
+ };
74
+ }
75
+ async submit() {
76
+ this.isSubmitting = true;
77
+ try {
78
+ const result = await this.form.submit();
79
+ if (result !== false) {
80
+ this.lastSubmitted = toJS(result);
81
+ }
82
+ } finally {
83
+ this.isSubmitting = false;
84
+ }
85
+ }
86
+ reset() {
87
+ this.form.reset();
88
+ this.lastSubmitted = null;
89
+ }
90
+ toggleRuntimeTemplate() {
91
+ const sections = this.form.field("sections").as("object");
92
+ if (this.runtimeTemplateAdded) {
93
+ sections.templates.remove(RUNTIME_TEMPLATE_ID);
94
+ this.runtimeTemplateAdded = false;
95
+ } else {
96
+ sections.templates.add(RUNTIME_TEMPLATE_ID, t => {
97
+ t.label("Runtime Banner").fields(f => ({
98
+ headline: f.text().label("Headline").required("Required"),
99
+ note: f.text().label("Note")
100
+ }));
101
+ });
102
+ this.runtimeTemplateAdded = true;
103
+ }
104
+ }
105
+ toggleTextTemplate() {
106
+ const content = this.form.field("content").as("object");
107
+ if (this.textTemplateRemoved) {
108
+ content.templates.add("text", t => {
109
+ t.label("Rich Text").fields(f => ({
110
+ body: f.text().label("Body").required("Required")
111
+ }));
112
+ });
113
+ this.textTemplateRemoved = false;
114
+ } else {
115
+ content.templates.remove("text");
116
+ this.textTemplateRemoved = true;
117
+ }
118
+ }
119
+ }
120
+
121
+ //# sourceMappingURL=FormModelDemoPresenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["makeAutoObservable","toJS","RUNTIME_TEMPLATE_ID","FormModelDemoPresenter","lastSubmitted","isSubmitting","runtimeTemplateAdded","textTemplateRemoved","constructor","formFactory","form","create","fields","title","text","label","required","content","object","template","t","f","heading","subheading","image","cta","body","visible","field","getValue","config","sections","list","url","plan","defaultValue","options","value","layout","row","hero","l","vm","data","getData","submit","result","reset","toggleRuntimeTemplate","as","templates","remove","add","headline","note","toggleTextTemplate"],"sources":["FormModelDemoPresenter.ts"],"sourcesContent":["import { makeAutoObservable, toJS } from \"mobx\";\nimport type { IFormModel, IFormModelFactory, IFormVM } from \"../abstractions.js\";\n\nexport interface FormModelDemoVM {\n form: IFormVM;\n data: Record<string, unknown>;\n lastSubmitted: Record<string, unknown> | null;\n isSubmitting: boolean;\n runtimeTemplateAdded: boolean;\n textTemplateRemoved: boolean;\n}\n\nconst RUNTIME_TEMPLATE_ID = \"runtimeBanner\";\n\nexport class FormModelDemoPresenter {\n private form: IFormModel;\n private lastSubmitted: Record<string, unknown> | null = null;\n private isSubmitting = false;\n private runtimeTemplateAdded = false;\n private textTemplateRemoved = false;\n\n constructor(formFactory: IFormModelFactory) {\n this.form = formFactory.create({\n fields: fields => ({\n title: fields.text().label(\"Title\").required(\"Title is required\"),\n content: fields\n .object()\n .label(\"Content Block\")\n .required(\"Pick a template\")\n .template(\"hero\", t => {\n t.label(\"Hero Banner\").fields(f => ({\n heading: f.text().label(\"Heading\").required(\"Required\"),\n subheading: f.text().label(\"Subheading\"),\n image: f.text().label(\"Image URL\"),\n cta: f.text().label(\"Call To Action\")\n }));\n })\n .template(\"text\", t => {\n t.label(\"Rich Text\").fields(f => ({\n body: f.text().label(\"Body\").required(\"Required\")\n }));\n })\n .template(\"premium\", t => {\n t.label(\"Premium Widget\")\n .visible(form => form.field(\"plan\").getValue() === \"enterprise\")\n .fields(f => ({\n config: f.text().label(\"Widget Config\")\n }));\n }),\n sections: fields\n .object()\n .label(\"Page Sections\")\n .list()\n .template(\"hero\", t => {\n t.label(\"Hero Banner\").fields(f => ({\n heading: f.text().label(\"Heading\").required(\"Required\"),\n subheading: f.text().label(\"Subheading\"),\n image: f.text().label(\"Image URL\")\n }));\n })\n .template(\"text\", t => {\n t.label(\"Rich Text\").fields(f => ({\n body: f.text().label(\"Body\").required(\"Required\")\n }));\n })\n .template(\"cta\", t => {\n t.label(\"Call To Action\").fields(f => ({\n label: f.text().label(\"Button Label\").required(\"Required\"),\n url: f.text().label(\"Link URL\")\n }));\n }),\n plan: fields\n .text()\n .label(\"Plan\")\n .defaultValue(\"free\")\n .options([\n { label: \"Free\", value: \"free\" },\n { label: \"Pro\", value: \"pro\" },\n { label: \"Enterprise\", value: \"enterprise\" }\n ])\n }),\n layout: layout => [\n layout.row(\"title\"),\n layout.row(\"plan\"),\n layout.object(\"content\", {\n hero: l => [l.row(\"heading\", \"subheading\"), l.row(\"image\"), l.row(\"cta\")],\n text: l => [l.row(\"body\")]\n }),\n layout.object(\"sections\", {\n hero: l => [l.row(\"heading\", \"subheading\"), l.row(\"image\")],\n cta: l => [l.row(\"label\", \"url\")]\n })\n ]\n });\n\n makeAutoObservable(this);\n }\n\n get vm(): FormModelDemoVM {\n return {\n form: this.form.vm,\n data: toJS(this.form.getData()),\n lastSubmitted: this.lastSubmitted,\n isSubmitting: this.isSubmitting,\n runtimeTemplateAdded: this.runtimeTemplateAdded,\n textTemplateRemoved: this.textTemplateRemoved\n };\n }\n\n async submit(): Promise<void> {\n this.isSubmitting = true;\n try {\n const result = await this.form.submit<Record<string, unknown>>();\n if (result !== false) {\n this.lastSubmitted = toJS(result);\n }\n } finally {\n this.isSubmitting = false;\n }\n }\n\n reset(): void {\n this.form.reset();\n this.lastSubmitted = null;\n }\n\n toggleRuntimeTemplate(): void {\n const sections = this.form.field(\"sections\").as(\"object\");\n if (this.runtimeTemplateAdded) {\n sections.templates.remove(RUNTIME_TEMPLATE_ID);\n this.runtimeTemplateAdded = false;\n } else {\n sections.templates.add(RUNTIME_TEMPLATE_ID, t => {\n t.label(\"Runtime Banner\").fields(f => ({\n headline: f.text().label(\"Headline\").required(\"Required\"),\n note: f.text().label(\"Note\")\n }));\n });\n this.runtimeTemplateAdded = true;\n }\n }\n\n toggleTextTemplate(): void {\n const content = this.form.field(\"content\").as(\"object\");\n if (this.textTemplateRemoved) {\n content.templates.add(\"text\", t => {\n t.label(\"Rich Text\").fields(f => ({\n body: f.text().label(\"Body\").required(\"Required\")\n }));\n });\n this.textTemplateRemoved = false;\n } else {\n content.templates.remove(\"text\");\n this.textTemplateRemoved = true;\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,25 @@
1
+ import type { IFormModelFactory, IFormVM } from "../abstractions.js";
2
+ export interface FormModelPhase11VM {
3
+ form: IFormVM;
4
+ data: Record<string, unknown>;
5
+ lastSubmitted: Record<string, unknown> | null;
6
+ isSubmitting: boolean;
7
+ formErrors: {
8
+ path: string;
9
+ message: string;
10
+ }[];
11
+ }
12
+ /**
13
+ * Demo presenter exercising Phase 11 features: requiredWhen (builder + modifier
14
+ * chaining), computed/computedUntilDirty, .extend() on object fields, form-level
15
+ * addRule (Zod + imperative), and setLayout.
16
+ */
17
+ export declare class FormModelPhase11Presenter {
18
+ private form;
19
+ private lastSubmitted;
20
+ private isSubmitting;
21
+ constructor(formFactory: IFormModelFactory);
22
+ get vm(): FormModelPhase11VM;
23
+ submit(): Promise<void>;
24
+ reset(): void;
25
+ }
@@ -0,0 +1,104 @@
1
+ import { makeAutoObservable, toJS } from "mobx";
2
+ import { z } from "zod";
3
+ /**
4
+ * Demo presenter exercising Phase 11 features: requiredWhen (builder + modifier
5
+ * chaining), computed/computedUntilDirty, .extend() on object fields, form-level
6
+ * addRule (Zod + imperative), and setLayout.
7
+ */
8
+ export class FormModelPhase11Presenter {
9
+ lastSubmitted = null;
10
+ isSubmitting = false;
11
+ constructor(formFactory) {
12
+ this.form = formFactory.create({
13
+ fields: fields => ({
14
+ first: fields.text().label("First name").defaultValue("Ada"),
15
+ last: fields.text().label("Last name").defaultValue("Lovelace"),
16
+ fullName: fields.text().label("Full name (computed)").computed(f => `${f.field("first").getValue()} ${f.field("last").getValue()}`),
17
+ slug: fields.text().label("Slug (computed until you edit it)").computedUntilDirty(f => {
18
+ const full = `${f.field("first").getValue()} ${f.field("last").getValue()}`;
19
+ return full.trim().toLowerCase().replace(/\s+/g, "-");
20
+ }),
21
+ plan: fields.text().label("Plan").defaultValue("free").options([{
22
+ label: "Free",
23
+ value: "free"
24
+ }, {
25
+ label: "Pro",
26
+ value: "pro"
27
+ }, {
28
+ label: "Enterprise",
29
+ value: "enterprise"
30
+ }]),
31
+ seats: fields.text().label("Number of seats").help("Required when plan is pro or enterprise").requiredWhen(f => f.field("plan").getValue() === "pro", "Pro plan needs a seat count"),
32
+ profile: fields.object().label("Profile").fields(f => ({
33
+ title: f.text().label("Title")
34
+ })),
35
+ password: fields.text().label("Password"),
36
+ confirm: fields.text().label("Confirm password")
37
+ })
38
+ });
39
+
40
+ // Modifier-style: add children to the existing "profile" object field.
41
+ this.form.field("profile").as("object").fields(f => ({
42
+ company: f.text().label("Company"),
43
+ bio: f.text().label("Short bio")
44
+ }));
45
+
46
+ // Modifier-style requiredWhen: chains with the builder-defined one above.
47
+ // First truthy callback wins.
48
+ this.form.field("seats").addRequiredWhen(f => f.field("plan").getValue() === "enterprise", "Enterprise plan needs a seat count too");
49
+
50
+ // Form-level Zod rule: confirm must match password.
51
+ this.form.addRule(z.object({
52
+ password: z.string().nullable(),
53
+ confirm: z.string().nullable()
54
+ }).refine(d => d.password === d.confirm || !d.password && !d.confirm, {
55
+ message: "Passwords must match",
56
+ path: ["confirm"]
57
+ }));
58
+
59
+ // Imperative form-level rule.
60
+ this.form.addRule(f => {
61
+ const slug = String(f.field("slug").getValue() ?? "");
62
+ if (slug.length > 0 && slug.length < 3) {
63
+ return [{
64
+ path: "slug",
65
+ message: "Slug must be at least 3 characters"
66
+ }];
67
+ }
68
+ return [];
69
+ });
70
+
71
+ // setLayout — full replacement.
72
+ this.form.setLayout(layout => [layout.row("first", "last"), layout.row("fullName"), layout.row("slug"), layout.separator(), layout.row("plan", "seats"), layout.separator(), layout.object("profile", l => [l.row("title"), l.row("company"), l.row("bio")]), layout.separator(), layout.row("password", "confirm")]);
73
+ makeAutoObservable(this);
74
+ }
75
+ get vm() {
76
+ return {
77
+ form: this.form.vm,
78
+ data: toJS(this.form.getData()),
79
+ lastSubmitted: this.lastSubmitted,
80
+ isSubmitting: this.isSubmitting,
81
+ formErrors: this.form.errors.map(e => ({
82
+ path: e.path,
83
+ message: e.message
84
+ }))
85
+ };
86
+ }
87
+ async submit() {
88
+ this.isSubmitting = true;
89
+ try {
90
+ const result = await this.form.submit();
91
+ if (result !== false) {
92
+ this.lastSubmitted = toJS(result);
93
+ }
94
+ } finally {
95
+ this.isSubmitting = false;
96
+ }
97
+ }
98
+ reset() {
99
+ this.form.reset();
100
+ this.lastSubmitted = null;
101
+ }
102
+ }
103
+
104
+ //# sourceMappingURL=FormModelPhase11Presenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["makeAutoObservable","toJS","z","FormModelPhase11Presenter","lastSubmitted","isSubmitting","constructor","formFactory","form","create","fields","first","text","label","defaultValue","last","fullName","computed","f","field","getValue","slug","computedUntilDirty","full","trim","toLowerCase","replace","plan","options","value","seats","help","requiredWhen","profile","object","title","password","confirm","as","company","bio","addRequiredWhen","addRule","string","nullable","refine","d","message","path","String","length","setLayout","layout","row","separator","l","vm","data","getData","formErrors","errors","map","e","submit","result","reset"],"sources":["FormModelPhase11Presenter.ts"],"sourcesContent":["import { makeAutoObservable, toJS } from \"mobx\";\nimport { z } from \"zod\";\nimport type { IFormModel, IFormModelFactory, IFormVM } from \"../abstractions.js\";\n\nexport interface FormModelPhase11VM {\n form: IFormVM;\n data: Record<string, unknown>;\n lastSubmitted: Record<string, unknown> | null;\n isSubmitting: boolean;\n formErrors: { path: string; message: string }[];\n}\n\n/**\n * Demo presenter exercising Phase 11 features: requiredWhen (builder + modifier\n * chaining), computed/computedUntilDirty, .extend() on object fields, form-level\n * addRule (Zod + imperative), and setLayout.\n */\nexport class FormModelPhase11Presenter {\n private form: IFormModel;\n private lastSubmitted: Record<string, unknown> | null = null;\n private isSubmitting = false;\n\n constructor(formFactory: IFormModelFactory) {\n this.form = formFactory.create({\n fields: fields => ({\n first: fields.text().label(\"First name\").defaultValue(\"Ada\"),\n last: fields.text().label(\"Last name\").defaultValue(\"Lovelace\"),\n fullName: fields\n .text()\n .label(\"Full name (computed)\")\n .computed(f => `${f.field(\"first\").getValue()} ${f.field(\"last\").getValue()}`),\n slug: fields\n .text()\n .label(\"Slug (computed until you edit it)\")\n .computedUntilDirty(f => {\n const full = `${f.field(\"first\").getValue()} ${f.field(\"last\").getValue()}`;\n return full.trim().toLowerCase().replace(/\\s+/g, \"-\");\n }),\n plan: fields\n .text()\n .label(\"Plan\")\n .defaultValue(\"free\")\n .options([\n { label: \"Free\", value: \"free\" },\n { label: \"Pro\", value: \"pro\" },\n { label: \"Enterprise\", value: \"enterprise\" }\n ]),\n seats: fields\n .text()\n .label(\"Number of seats\")\n .help(\"Required when plan is pro or enterprise\")\n .requiredWhen(\n f => f.field(\"plan\").getValue() === \"pro\",\n \"Pro plan needs a seat count\"\n ),\n profile: fields\n .object()\n .label(\"Profile\")\n .fields(f => ({\n title: f.text().label(\"Title\")\n })),\n password: fields.text().label(\"Password\"),\n confirm: fields.text().label(\"Confirm password\")\n })\n });\n\n // Modifier-style: add children to the existing \"profile\" object field.\n this.form\n .field(\"profile\")\n .as(\"object\")\n .fields(f => ({\n company: f.text().label(\"Company\"),\n bio: f.text().label(\"Short bio\")\n }));\n\n // Modifier-style requiredWhen: chains with the builder-defined one above.\n // First truthy callback wins.\n this.form\n .field(\"seats\")\n .addRequiredWhen(\n f => f.field(\"plan\").getValue() === \"enterprise\",\n \"Enterprise plan needs a seat count too\"\n );\n\n // Form-level Zod rule: confirm must match password.\n this.form.addRule(\n z\n .object({\n password: z.string().nullable(),\n confirm: z.string().nullable()\n })\n .refine(d => d.password === d.confirm || (!d.password && !d.confirm), {\n message: \"Passwords must match\",\n path: [\"confirm\"]\n })\n );\n\n // Imperative form-level rule.\n this.form.addRule(f => {\n const slug = String(f.field(\"slug\").getValue() ?? \"\");\n if (slug.length > 0 && slug.length < 3) {\n return [{ path: \"slug\", message: \"Slug must be at least 3 characters\" }];\n }\n return [];\n });\n\n // setLayout — full replacement.\n this.form.setLayout(layout => [\n layout.row(\"first\", \"last\"),\n layout.row(\"fullName\"),\n layout.row(\"slug\"),\n layout.separator(),\n layout.row(\"plan\", \"seats\"),\n layout.separator(),\n layout.object(\"profile\", l => [l.row(\"title\"), l.row(\"company\"), l.row(\"bio\")]),\n layout.separator(),\n layout.row(\"password\", \"confirm\")\n ]);\n\n makeAutoObservable(this);\n }\n\n get vm(): FormModelPhase11VM {\n return {\n form: this.form.vm,\n data: toJS(this.form.getData()),\n lastSubmitted: this.lastSubmitted,\n isSubmitting: this.isSubmitting,\n formErrors: this.form.errors.map(e => ({\n path: e.path,\n message: e.message\n }))\n };\n }\n\n async submit(): Promise<void> {\n this.isSubmitting = true;\n try {\n const result = await this.form.submit<Record<string, unknown>>();\n if (result !== false) {\n this.lastSubmitted = toJS(result);\n }\n } finally {\n this.isSubmitting = false;\n }\n }\n\n reset(): void {\n this.form.reset();\n this.lastSubmitted = null;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ import type { IFormModelFactory, IFormVM } from "../abstractions.js";
2
+ export interface FormModelPhase8c1VM {
3
+ form: IFormVM;
4
+ data: Record<string, unknown>;
5
+ lastSubmitted: Record<string, unknown> | null;
6
+ isSubmitting: boolean;
7
+ }
8
+ /**
9
+ * Demo presenter exercising Phase 8c.1: nested object layouts. The form has a
10
+ * top-level `page` object whose inner layout contains tabs, and one of those
11
+ * tabs contains a nested `seo` object with its own row layout. The Phase 8c.1
12
+ * registrar walks the inner layout (including tabs) and forwards the nested
13
+ * `layout.object("seo", ...)` to the seo field at build time.
14
+ */
15
+ export declare class FormModelPhase8c1Presenter {
16
+ private form;
17
+ private lastSubmitted;
18
+ private isSubmitting;
19
+ constructor(formFactory: IFormModelFactory);
20
+ get vm(): FormModelPhase8c1VM;
21
+ submit(): Promise<void>;
22
+ reset(): void;
23
+ }