betterstart-cli 0.0.102 → 0.0.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/index.ts +0 -5
  2. package/dist/assets/adapters/next/templates/init/lib/actions/webhooks/send-test-webhook.ts +1 -1
  3. package/dist/assets/adapters/next/templates/renderers/commands/init/banner-art.ts +7 -0
  4. package/dist/assets/adapters/next/templates/renderers/commands/init/verify-database-reachable.ts +30 -0
  5. package/dist/assets/adapters/next/templates/renderers/commands/seed/build-seed-script.ts +171 -0
  6. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-authorship-alias-block.ts +4 -0
  7. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-authorship-data-fields.ts +4 -0
  8. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-format-action-date-source.ts +18 -0
  9. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-read-select-option-type.ts +6 -0
  10. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-relationship-data-types.ts +25 -0
  11. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/build-result-mapping.ts +62 -0
  12. package/dist/assets/adapters/next/templates/renderers/generators/actions/action-helpers/generate-populate-list-rels-function.ts +50 -0
  13. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/build-restore-many-to-many-statements.ts +27 -0
  14. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/build-select-option-types.ts +37 -0
  15. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-bulk-sort-order-content.ts +93 -0
  16. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-create-content.ts +157 -0
  17. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-create-select-option-content.ts +134 -0
  18. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-delete-bulk-content.ts +85 -0
  19. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-delete-content.ts +66 -0
  20. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-distinct-files.ts +45 -0
  21. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-by-id-content.ts +55 -0
  22. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-by-slug-content.ts +55 -0
  23. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-plural-content.ts +106 -0
  24. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-select-options-content.ts +55 -0
  25. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-get-versions-content.ts +19 -0
  26. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-m2m-files.ts +151 -0
  27. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-restore-content.ts +123 -0
  28. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/gen-update-content.ts +187 -0
  29. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-resolve-media-function.ts +40 -0
  30. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-slug-helpers.ts +73 -0
  31. package/dist/assets/adapters/next/templates/renderers/generators/actions/entity-file-contents/generate-version-snapshot-helpers.ts +104 -0
  32. package/dist/assets/adapters/next/templates/renderers/generators/actions/lifecycle-hook-emissions/lifecycle-context.ts +22 -0
  33. package/dist/assets/adapters/next/templates/renderers/generators/actions/lifecycle-hook-emissions/lifecycle-hook-import.ts +4 -0
  34. package/dist/assets/adapters/next/templates/renderers/generators/actions/markdown-renderer.ts +411 -0
  35. package/dist/assets/adapters/next/templates/renderers/generators/actions/select-fields-resolver.ts +99 -0
  36. package/dist/assets/adapters/next/templates/renderers/generators/actions/single-actions/generate-single-actions.ts +292 -0
  37. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-authorship-value.ts +8 -0
  38. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-column-def.ts +297 -0
  39. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-first-column-def.ts +483 -0
  40. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-image-cell-media.ts +38 -0
  41. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-image-element.ts +22 -0
  42. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-relationship-label.ts +26 -0
  43. package/dist/assets/adapters/next/templates/renderers/generators/columns/column-defs/generate-select-label.ts +17 -0
  44. package/dist/assets/adapters/next/templates/renderers/generators/columns/custom-cell.ts +24 -0
  45. package/dist/assets/adapters/next/templates/renderers/generators/columns/generate-columns.ts +55 -0
  46. package/dist/assets/adapters/next/templates/renderers/generators/create-page.ts +16 -0
  47. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-database.ts +5 -0
  48. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-junction-table.ts +27 -0
  49. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-select-options-table.ts +35 -0
  50. package/dist/assets/adapters/next/templates/renderers/generators/database/generate-table-definition.ts +25 -0
  51. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-entity-dev-mode-snippets.ts +180 -0
  52. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-form-dev-mode-snippets.ts +97 -0
  53. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/build-single-dev-mode-snippets.ts +60 -0
  54. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/create-dev-mode-integration-artifact.ts +89 -0
  55. package/dist/assets/adapters/next/templates/renderers/generators/dev-mode-integration/lifecycle-hook-code.ts +55 -0
  56. package/dist/assets/adapters/next/templates/renderers/generators/edit-page.ts +33 -0
  57. package/dist/assets/adapters/next/templates/renderers/generators/email-template/generate-email-template.ts +248 -0
  58. package/dist/assets/adapters/next/templates/renderers/generators/email-template/generate-field-value.ts +31 -0
  59. package/dist/assets/adapters/next/templates/renderers/generators/emitted-helpers.ts +16 -0
  60. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/generate-icon-postfix.ts +27 -0
  61. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-boolean-field.ts +47 -0
  62. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-creatable-select-field.ts +122 -0
  63. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-date-field.ts +47 -0
  64. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-default-field.ts +53 -0
  65. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-gallery-field.ts +46 -0
  66. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-group-field.ts +16 -0
  67. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-icon-field.ts +31 -0
  68. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-markdown-field.ts +50 -0
  69. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-media-field.ts +47 -0
  70. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-multi-relationship-field.ts +91 -0
  71. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-multi-select-field.ts +219 -0
  72. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-number-field.ts +48 -0
  73. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-richtext-field.ts +50 -0
  74. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-select-field.ts +61 -0
  75. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-separator-field.ts +16 -0
  76. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-single-relationship-field.ts +93 -0
  77. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx/render-textarea-field.ts +53 -0
  78. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-list-field.ts +163 -0
  79. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-nested-field.ts +164 -0
  80. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-nested-object-list-field.ts +59 -0
  81. package/dist/assets/adapters/next/templates/renderers/generators/form/field-jsx-nested/render-text-input-field.ts +27 -0
  82. package/dist/assets/adapters/next/templates/renderers/generators/form/form-entity/generate-form.ts +822 -0
  83. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/build-default-value-from-sync-functions.ts +41 -0
  84. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/build-ui-imports.ts +58 -0
  85. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/generate-default-value.ts +67 -0
  86. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/generate-nested-list-default-value.ts +13 -0
  87. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/label-with-description.ts +14 -0
  88. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/render-tabs-trigger.ts +18 -0
  89. package/dist/assets/adapters/next/templates/renderers/generators/form/form-shared/select-read-values-expression.ts +21 -0
  90. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-creatable-select-handlers.ts +67 -0
  91. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-creatable-select-state.ts +29 -0
  92. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-field-array-hooks.ts +13 -0
  93. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/build-group-fields-jsx.ts +30 -0
  94. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/generate-card-component.ts +129 -0
  95. package/dist/assets/adapters/next/templates/renderers/generators/form/form-single/generate-single-form.ts +66 -0
  96. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-columns/generate-column-def.ts +72 -0
  97. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-columns/generate-columns.ts +89 -0
  98. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-page/generate-page.ts +23 -0
  99. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-page-content.ts +246 -0
  100. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-submission-drawer.ts +216 -0
  101. package/dist/assets/adapters/next/templates/renderers/generators/form-admin/admin-table.ts +273 -0
  102. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-actions/exclusive-date-upper-bound-helper.ts +11 -0
  103. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-actions/generate-form-actions.ts +505 -0
  104. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-multistep/build-component-source.ts +197 -0
  105. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/build-field-error-helper.ts +16 -0
  106. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/error-message-line.ts +13 -0
  107. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-field-jsx.ts +226 -0
  108. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-file-upload-field-jsx.ts +41 -0
  109. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-list-field-jsx.ts +160 -0
  110. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-multiselect-field-jsx.ts +40 -0
  111. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-number-field-jsx.ts +41 -0
  112. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/generate-text-field-jsx.ts +39 -0
  113. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-shared/label-with-description-line.ts +14 -0
  114. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-component-single/build-single-step-form-component-source.ts +100 -0
  115. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-database.ts +29 -0
  116. package/dist/assets/adapters/next/templates/renderers/generators/form-pipeline/form-hook.ts +142 -0
  117. package/dist/assets/adapters/next/templates/renderers/generators/hook/generate-hook.ts +169 -0
  118. package/dist/assets/adapters/next/templates/renderers/generators/hook/generate-single-hook.ts +30 -0
  119. package/dist/assets/adapters/next/templates/renderers/generators/navigation-extract.ts +19 -0
  120. package/dist/assets/adapters/next/templates/renderers/generators/page-content/generate-page-content.ts +419 -0
  121. package/dist/assets/adapters/next/templates/renderers/generators/page.ts +24 -0
  122. package/dist/assets/adapters/next/templates/renderers/generators/row-actions-emitters/build-delete-dialog-source.ts +108 -0
  123. package/dist/assets/adapters/next/templates/renderers/generators/row-actions-emitters/build-row-actions-source.ts +61 -0
  124. package/dist/assets/adapters/next/templates/renderers/generators/single-page.ts +59 -0
  125. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sort-label-expr.ts +9 -0
  126. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sortable-header-button-jsx.ts +20 -0
  127. package/dist/assets/adapters/next/templates/renderers/generators/sortable-header/build-sortable-header-def.ts +14 -0
  128. package/dist/assets/adapters/next/templates/renderers/generators/table.ts +284 -0
  129. package/dist/assets/adapters/next/templates/renderers/generators/thankyou-email-template.ts +110 -0
  130. package/dist/assets/adapters/next/templates/renderers/generators/webhook-events/render-extract.ts +14 -0
  131. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/next-config/create-next-config-template.ts +48 -0
  132. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/tailwind/admin-shadow-input-utility.ts +9 -0
  133. package/dist/assets/adapters/next/templates/renderers/init/scaffolders/tailwind/admin-theme-block.ts +42 -0
  134. package/dist/assets/adapters/next/templates/renderers/init/templates/app/admin.ts +12 -0
  135. package/dist/assets/adapters/next/templates/renderers/integration-runtime/render-core-email-provider.ts +27 -0
  136. package/dist/assets/adapters/next/templates/renderers/integration-runtime/render-core-storage-provider.ts +27 -0
  137. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-db-barrel.ts +8 -0
  138. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-navigation-barrel.ts +63 -0
  139. package/dist/assets/adapters/next/templates/renderers/snapshots/barrels/render-webhook-events-barrel.ts +16 -0
  140. package/dist/{chunk-TIJEHWRF.js → chunk-OYU73Q2W.js} +1 -50
  141. package/dist/chunk-OYU73Q2W.js.map +1 -0
  142. package/dist/cli.js +8903 -4025
  143. package/dist/cli.js.map +1 -1
  144. package/dist/{read-namespaced-template-UXU7OCY3.js → read-namespaced-template-EIH2NPDJ.js} +2 -2
  145. package/package.json +1 -1
  146. package/dist/chunk-TIJEHWRF.js.map +0 -1
  147. /package/dist/{read-namespaced-template-UXU7OCY3.js.map → read-namespaced-template-EIH2NPDJ.js.map} +0 -0
@@ -0,0 +1,13 @@
1
+ export function renderErrorMessageLineLayoutTemplate({
2
+ indent,
3
+ pathExpression
4
+ }: {
5
+ indent: string
6
+ pathExpression: string
7
+ }): string {
8
+ return `${indent}{getFieldErrorMessage(form.formState.errors, ${pathExpression}) ? (
9
+ ${indent} <p className="text-sm text-destructive">
10
+ ${indent} {getFieldErrorMessage(form.formState.errors, ${pathExpression})}
11
+ ${indent} </p>
12
+ ${indent}) : null}`
13
+ }
@@ -0,0 +1,226 @@
1
+ export function renderFieldJsxFieldControllerTemplate({
2
+ name,
3
+ fieldContainerClassFill,
4
+ formLabelWithDescriptionLine,
5
+ placeholder,
6
+ textareaClass,
7
+ errorMessageLine
8
+ }: {
9
+ name: string
10
+ fieldContainerClassFill: string
11
+ formLabelWithDescriptionLine: string
12
+ placeholder: string
13
+ textareaClass: string
14
+ errorMessageLine: string
15
+ }): string {
16
+ return ` <Controller
17
+ control={form.control}
18
+ name="${name}"
19
+ render={({ field }) => (
20
+ <div className="${fieldContainerClassFill}">
21
+ ${formLabelWithDescriptionLine}
22
+ <textarea
23
+ id="${name}"
24
+ placeholder="${placeholder}"
25
+ value={field.value ?? ''}
26
+ onChange={field.onChange}
27
+ onBlur={field.onBlur}
28
+ name={field.name}
29
+ ref={field.ref}
30
+ className="${textareaClass}"
31
+ />
32
+ ${errorMessageLine}
33
+ </div>
34
+ )}
35
+ />`
36
+ }
37
+
38
+ export function renderFieldJsxChangeHandlerTemplate({
39
+ escapeAttribute,
40
+ escapeAttributeText,
41
+ jsString,
42
+ escapeJsx
43
+ }: {
44
+ escapeAttribute: string
45
+ escapeAttributeText: string
46
+ jsString: string
47
+ escapeJsx: string
48
+ }): string {
49
+ return ` <label htmlFor="${escapeAttribute}" className="flex items-center gap-2 text-sm font-medium leading-none">
50
+ <input
51
+ type="radio"
52
+ id="${escapeAttribute}"
53
+ value="${escapeAttributeText}"
54
+ checked={field.value === ${jsString}}
55
+ onChange={() => field.onChange(${jsString})}
56
+ onBlur={field.onBlur}
57
+ name={field.name}
58
+ ref={field.ref}
59
+ className="size-4 accent-primary"
60
+ />
61
+ <span>${escapeJsx}</span>
62
+ </label>`
63
+ }
64
+
65
+ export function renderFieldJsxFieldControllerSpaceTemplate({
66
+ name,
67
+ fieldContainerClass,
68
+ formLabelWithDescriptionLine,
69
+ radioItems,
70
+ errorMessageLine
71
+ }: {
72
+ name: string
73
+ fieldContainerClass: string
74
+ formLabelWithDescriptionLine: string
75
+ radioItems: string
76
+ errorMessageLine: string
77
+ }): string {
78
+ return ` <Controller
79
+ control={form.control}
80
+ name="${name}"
81
+ render={({ field }) => (
82
+ <fieldset className="${fieldContainerClass}">
83
+ ${formLabelWithDescriptionLine}
84
+ <div className="flex flex-col gap-3">
85
+ ${radioItems}
86
+ </div>
87
+ ${errorMessageLine}
88
+ </fieldset>
89
+ )}
90
+ />`
91
+ }
92
+
93
+ export function renderFieldJsxFieldControllerEscapedJsxTemplate({
94
+ name,
95
+ fieldContainerClass,
96
+ formLabelWithDescriptionLine,
97
+ selectClass,
98
+ escapeJsx,
99
+ optionItems,
100
+ errorMessageLine
101
+ }: {
102
+ name: string
103
+ fieldContainerClass: string
104
+ formLabelWithDescriptionLine: string
105
+ selectClass: string
106
+ escapeJsx: string
107
+ optionItems: string
108
+ errorMessageLine: string
109
+ }): string {
110
+ return ` <Controller
111
+ control={form.control}
112
+ name="${name}"
113
+ render={({ field }) => (
114
+ <div className="${fieldContainerClass}">
115
+ ${formLabelWithDescriptionLine}
116
+ <select
117
+ id="${name}"
118
+ value={field.value ?? ''}
119
+ onChange={field.onChange}
120
+ onBlur={field.onBlur}
121
+ name={field.name}
122
+ ref={field.ref}
123
+ className="${selectClass}"
124
+ >
125
+ <option value="">${escapeJsx}</option>
126
+ ${optionItems}
127
+ </select>
128
+ ${errorMessageLine}
129
+ </div>
130
+ )}
131
+ />`
132
+ }
133
+
134
+ export function renderFieldJsxChangeHandlerEscapedJsxTemplate({
135
+ escapeAttribute,
136
+ jsString,
137
+ escapeJsx
138
+ }: {
139
+ escapeAttribute: string
140
+ jsString: string
141
+ escapeJsx: string
142
+ }): string {
143
+ return ` <label htmlFor="${escapeAttribute}" className="flex items-center gap-2 text-sm font-medium leading-none">
144
+ <input
145
+ type="checkbox"
146
+ id="${escapeAttribute}"
147
+ checked={Array.isArray(field.value) ? field.value.includes(${jsString}) : false}
148
+ onChange={(event) => {
149
+ const currentValue = Array.isArray(field.value) ? field.value : []
150
+ field.onChange(
151
+ event.target.checked
152
+ ? [...currentValue, ${jsString}]
153
+ : currentValue.filter((value) => value !== ${jsString})
154
+ )
155
+ }}
156
+ onBlur={field.onBlur}
157
+ name={field.name}
158
+ ref={field.ref}
159
+ className="mt-0.5 size-4 rounded border-input accent-primary"
160
+ />
161
+ <span>${escapeJsx}</span>
162
+ </label>`
163
+ }
164
+
165
+ export function renderFieldJsxFieldControllerSpaceBranchTemplate({
166
+ name,
167
+ fieldContainerClass,
168
+ formLabelWithDescriptionLine,
169
+ checkboxItems,
170
+ errorMessageLine
171
+ }: {
172
+ name: string
173
+ fieldContainerClass: string
174
+ formLabelWithDescriptionLine: string
175
+ checkboxItems: string
176
+ errorMessageLine: string
177
+ }): string {
178
+ return ` <Controller
179
+ control={form.control}
180
+ name="${name}"
181
+ render={({ field }) => (
182
+ <fieldset className="${fieldContainerClass}">
183
+ ${formLabelWithDescriptionLine}
184
+ <div className="flex flex-col gap-3">
185
+ ${checkboxItems}
186
+ </div>
187
+ ${errorMessageLine}
188
+ </fieldset>
189
+ )}
190
+ />`
191
+ }
192
+
193
+ export function renderFieldJsxFieldControllerFlexTemplate({
194
+ name,
195
+ fieldContainerClass,
196
+ formLabelWithDescriptionLine,
197
+ errorMessageLine
198
+ }: {
199
+ name: string
200
+ fieldContainerClass: string
201
+ formLabelWithDescriptionLine: string
202
+ errorMessageLine: string
203
+ }): string {
204
+ return ` <Controller
205
+ control={form.control}
206
+ name="${name}"
207
+ render={({ field }) => (
208
+ <div className="${fieldContainerClass}">
209
+ <input
210
+ type="checkbox"
211
+ id="${name}"
212
+ checked={Boolean(field.value)}
213
+ onChange={(event) => field.onChange(event.target.checked)}
214
+ onBlur={field.onBlur}
215
+ name={field.name}
216
+ ref={field.ref}
217
+ className="mt-1 size-4 rounded border-input accent-primary"
218
+ />
219
+ <div className="space-y-2 leading-none">
220
+ ${formLabelWithDescriptionLine}
221
+ ${errorMessageLine}
222
+ </div>
223
+ </div>
224
+ )}
225
+ />`
226
+ }
@@ -0,0 +1,41 @@
1
+ export function renderFileUploadFieldJsxFieldControllerTemplate({
2
+ name,
3
+ fieldContainerClass,
4
+ formLabelWithDescriptionLine,
5
+ escapeAttribute,
6
+ multiple,
7
+ inputClass,
8
+ errorMessageLine
9
+ }: {
10
+ name: string
11
+ fieldContainerClass: string
12
+ formLabelWithDescriptionLine: string
13
+ escapeAttribute: string
14
+ multiple: string
15
+ inputClass: string
16
+ errorMessageLine: string
17
+ }): string {
18
+ return ` <Controller
19
+ control={form.control}
20
+ name="${name}"
21
+ render={({ field }) => (
22
+ <div className="${fieldContainerClass}">
23
+ ${formLabelWithDescriptionLine}
24
+ <input
25
+ id="${name}"
26
+ type="file"
27
+ accept="${escapeAttribute}"${multiple}
28
+ onChange={(event) => {
29
+ const selectedFiles = Array.from(event.target.files ?? [])
30
+ field.onChange(selectedFiles.map((file) => file.name).join(', '))
31
+ }}
32
+ onBlur={field.onBlur}
33
+ name={field.name}
34
+ ref={field.ref}
35
+ className="${inputClass}"
36
+ />
37
+ ${errorMessageLine}
38
+ </div>
39
+ )}
40
+ />`
41
+ }
@@ -0,0 +1,160 @@
1
+ export function renderListFieldJsxFieldControllerTemplate({
2
+ name,
3
+ nfName,
4
+ nfLabelRaw,
5
+ selectClass,
6
+ escapeJsx,
7
+ selectItems,
8
+ errorMessageLine
9
+ }: {
10
+ name: string
11
+ nfName: string
12
+ nfLabelRaw: string
13
+ selectClass: string
14
+ escapeJsx: string
15
+ selectItems: string
16
+ errorMessageLine: string
17
+ }): string {
18
+ return ` <Controller
19
+ control={form.control}
20
+ name={\`${name}.\${index}.${nfName}\`}
21
+ render={({ field }) => (
22
+ <div className="flex-1 space-y-2">
23
+ <label htmlFor={field.name} className="text-sm font-medium leading-none">${nfLabelRaw}</label>
24
+ <select
25
+ id={field.name}
26
+ value={field.value ?? ''}
27
+ onChange={field.onChange}
28
+ onBlur={field.onBlur}
29
+ name={field.name}
30
+ ref={field.ref}
31
+ className="${selectClass}"
32
+ >
33
+ <option value="">${escapeJsx}</option>
34
+ ${selectItems}
35
+ </select>
36
+ ${errorMessageLine}
37
+ </div>
38
+ )}
39
+ />`
40
+ }
41
+
42
+ export function renderListFieldJsxFieldControllerFieldNameTemplate({
43
+ name,
44
+ nfName,
45
+ nfLabelRaw,
46
+ escapeAttribute,
47
+ inputClass,
48
+ errorMessageLine
49
+ }: {
50
+ name: string
51
+ nfName: string
52
+ nfLabelRaw: string
53
+ escapeAttribute: string
54
+ inputClass: string
55
+ errorMessageLine: string
56
+ }): string {
57
+ return ` <Controller
58
+ control={form.control}
59
+ name={\`${name}.\${index}.${nfName}\`}
60
+ render={({ field }) => (
61
+ <div className="flex-1 space-y-2">
62
+ <label htmlFor={field.name} className="text-sm font-medium leading-none">${nfLabelRaw}</label>
63
+ <input
64
+ id={field.name}
65
+ type="number"
66
+ placeholder="${escapeAttribute}"
67
+ value={field.value ?? ''}
68
+ onChange={(event) => {
69
+ const nextValue = event.target.value === '' ? undefined : event.target.valueAsNumber
70
+ const normalizedValue = Number.isNaN(nextValue) ? undefined : nextValue
71
+ field.onChange(normalizedValue)
72
+ }}
73
+ onBlur={field.onBlur}
74
+ name={field.name}
75
+ ref={field.ref}
76
+ className="${inputClass}"
77
+ />
78
+ ${errorMessageLine}
79
+ </div>
80
+ )}
81
+ />`
82
+ }
83
+
84
+ export function renderListFieldJsxFieldControllerFieldNameFieldTemplate({
85
+ name,
86
+ nfName,
87
+ nfLabelRaw,
88
+ escapeAttribute,
89
+ inputClass,
90
+ errorMessageLine
91
+ }: {
92
+ name: string
93
+ nfName: string
94
+ nfLabelRaw: string
95
+ escapeAttribute: string
96
+ inputClass: string
97
+ errorMessageLine: string
98
+ }): string {
99
+ return ` <Controller
100
+ control={form.control}
101
+ name={\`${name}.\${index}.${nfName}\`}
102
+ render={({ field }) => (
103
+ <div className="flex-1 space-y-2">
104
+ <label htmlFor={field.name} className="text-sm font-medium leading-none">${nfLabelRaw}</label>
105
+ <input
106
+ id={field.name}
107
+ type="text"
108
+ placeholder="${escapeAttribute}"
109
+ value={field.value ?? ''}
110
+ onChange={field.onChange}
111
+ onBlur={field.onBlur}
112
+ name={field.name}
113
+ ref={field.ref}
114
+ className="${inputClass}"
115
+ />
116
+ ${errorMessageLine}
117
+ </div>
118
+ )}
119
+ />`
120
+ }
121
+
122
+ export function renderListFieldJsxClickHandlerTemplate({
123
+ labelWithDescriptionLine,
124
+ name,
125
+ nestedFieldsJsx,
126
+ defaultObj,
127
+ singularLabel
128
+ }: {
129
+ labelWithDescriptionLine: string
130
+ name: string
131
+ nestedFieldsJsx: string
132
+ defaultObj: string
133
+ singularLabel: string
134
+ }): string {
135
+ return ` <div className="space-y-2">
136
+ ${labelWithDescriptionLine}
137
+ {${name}FieldArray.fields.map((item, index) => (
138
+ <div key={item.id} className="relative rounded-sm border p-4">
139
+ <button
140
+ type="button"
141
+ onClick={() => ${name}FieldArray.remove(index)}
142
+ className="absolute right-2 top-2 inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
143
+ >
144
+ <Trash2 className="size-4" />
145
+ <span className="sr-only">Remove</span>
146
+ </button>
147
+ <div className="space-y-4 pr-8">
148
+ ${nestedFieldsJsx}
149
+ </div>
150
+ </div>
151
+ ))}
152
+ <button
153
+ type="button"
154
+ onClick={() => ${name}FieldArray.append({ ${defaultObj} })}
155
+ className="inline-flex h-9 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium shadow-xs transition-colors hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50"
156
+ >
157
+ Add ${singularLabel}
158
+ </button>
159
+ </div>`
160
+ }
@@ -0,0 +1,40 @@
1
+ export function renderMultiselectFieldJsxFieldControllerTemplate({
2
+ name,
3
+ fieldContainerClass,
4
+ formLabelWithDescriptionLine,
5
+ selectClass,
6
+ optionItems,
7
+ errorMessageLine
8
+ }: {
9
+ name: string
10
+ fieldContainerClass: string
11
+ formLabelWithDescriptionLine: string
12
+ selectClass: string
13
+ optionItems: string
14
+ errorMessageLine: string
15
+ }): string {
16
+ return ` <Controller
17
+ control={form.control}
18
+ name="${name}"
19
+ render={({ field }) => (
20
+ <div className="${fieldContainerClass}">
21
+ ${formLabelWithDescriptionLine}
22
+ <select
23
+ id="${name}"
24
+ multiple
25
+ value={Array.isArray(field.value) ? field.value : []}
26
+ onChange={(event) => {
27
+ field.onChange(Array.from(event.target.selectedOptions, (option) => option.value))
28
+ }}
29
+ onBlur={field.onBlur}
30
+ name={field.name}
31
+ ref={field.ref}
32
+ className="${selectClass} min-h-24 py-2"
33
+ >
34
+ ${optionItems}
35
+ </select>
36
+ ${errorMessageLine}
37
+ </div>
38
+ )}
39
+ />`
40
+ }
@@ -0,0 +1,41 @@
1
+ export function renderNumberFieldJsxFieldControllerTemplate({
2
+ name,
3
+ fieldContainerClass,
4
+ formLabelWithDescriptionLine,
5
+ escapeAttribute,
6
+ inputClass,
7
+ errorMessageLine
8
+ }: {
9
+ name: string
10
+ fieldContainerClass: string
11
+ formLabelWithDescriptionLine: string
12
+ escapeAttribute: string
13
+ inputClass: string
14
+ errorMessageLine: string
15
+ }): string {
16
+ return ` <Controller
17
+ control={form.control}
18
+ name="${name}"
19
+ render={({ field }) => (
20
+ <div className="${fieldContainerClass}">
21
+ ${formLabelWithDescriptionLine}
22
+ <input
23
+ id="${name}"
24
+ type="number"
25
+ placeholder="${escapeAttribute}"
26
+ value={field.value ?? ''}
27
+ onChange={(event) => {
28
+ const nextValue = event.target.value === '' ? undefined : event.target.valueAsNumber
29
+ const normalizedValue = Number.isNaN(nextValue) ? undefined : nextValue
30
+ field.onChange(normalizedValue)
31
+ }}
32
+ onBlur={field.onBlur}
33
+ name={field.name}
34
+ ref={field.ref}
35
+ className="${inputClass}"
36
+ />
37
+ ${errorMessageLine}
38
+ </div>
39
+ )}
40
+ />`
41
+ }
@@ -0,0 +1,39 @@
1
+ export function renderTextFieldJsxFieldControllerTemplate({
2
+ name,
3
+ fieldContainerClass,
4
+ formLabelWithDescriptionLine,
5
+ inputType,
6
+ escapeAttribute,
7
+ inputClass,
8
+ errorMessageLine
9
+ }: {
10
+ name: string
11
+ fieldContainerClass: string
12
+ formLabelWithDescriptionLine: string
13
+ inputType: string
14
+ escapeAttribute: string
15
+ inputClass: string
16
+ errorMessageLine: string
17
+ }): string {
18
+ return ` <Controller
19
+ control={form.control}
20
+ name="${name}"
21
+ render={({ field }) => (
22
+ <div className="${fieldContainerClass}">
23
+ ${formLabelWithDescriptionLine}
24
+ <input
25
+ id="${name}"
26
+ type="${inputType}"
27
+ placeholder="${escapeAttribute}"
28
+ value={field.value ?? ''}
29
+ onChange={field.onChange}
30
+ onBlur={field.onBlur}
31
+ name={field.name}
32
+ ref={field.ref}
33
+ className="${inputClass}"
34
+ />
35
+ ${errorMessageLine}
36
+ </div>
37
+ )}
38
+ />`
39
+ }
@@ -0,0 +1,14 @@
1
+ export function renderLabelWithDescriptionLineLayoutTemplate({
2
+ indent,
3
+ labelJsx,
4
+ descriptionJsx
5
+ }: {
6
+ indent: string
7
+ labelJsx: string
8
+ descriptionJsx: string
9
+ }): string {
10
+ return `<div className="flex flex-col gap-1">
11
+ ${indent} ${labelJsx}
12
+ ${indent} ${descriptionJsx}
13
+ ${indent}</div>`
14
+ }
@@ -0,0 +1,100 @@
1
+ export function renderBuildSingleStepFormComponentSourceClientModuleTemplate({
2
+ lucideImport,
3
+ rhfImport,
4
+ pascal,
5
+ actionImportPath,
6
+ zodFields,
7
+ fieldErrorHelper,
8
+ defaults,
9
+ fieldArraySetup,
10
+ watchSetup,
11
+ successHandler,
12
+ successMessage,
13
+ fieldJsx,
14
+ submitText
15
+ }: {
16
+ lucideImport: string
17
+ rhfImport: string
18
+ pascal: string
19
+ actionImportPath: string
20
+ zodFields: string
21
+ fieldErrorHelper: string
22
+ defaults: string
23
+ fieldArraySetup: string
24
+ watchSetup: string
25
+ successHandler: string
26
+ successMessage: string
27
+ fieldJsx: string
28
+ submitText: string
29
+ }): string {
30
+ return `'use client'
31
+
32
+ import * as React from 'react'
33
+ import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'${lucideImport}
34
+ ${rhfImport}
35
+ import { z } from 'zod/v3'
36
+ import { create${pascal}Submission } from '@admin/actions/${actionImportPath}'
37
+
38
+ const formSchema = z.object({
39
+ ${zodFields}
40
+ })
41
+
42
+ type FormValues = z.infer<typeof formSchema>
43
+ ${fieldErrorHelper}
44
+
45
+ export function ${pascal}Form() {
46
+ const [submitted, setSubmitted] = React.useState(false)
47
+ const [submitting, startSubmitTransition] = React.useTransition()
48
+
49
+ const form = useForm<FormValues>({
50
+ resolver: standardSchemaResolver(formSchema),
51
+ defaultValues: {
52
+ ${defaults}
53
+ },
54
+ })
55
+ ${fieldArraySetup}${watchSetup}
56
+ function onSubmit(values: FormValues) {
57
+ startSubmitTransition(async () => {
58
+ try {
59
+ const result = await create${pascal}Submission(values)
60
+ if (result.success) {
61
+ ${successHandler}
62
+ } else {
63
+ form.setError('root', { message: result.error || 'Something went wrong' })
64
+ }
65
+ } catch {
66
+ form.setError('root', { message: 'Something went wrong. Please try again.' })
67
+ }
68
+ })
69
+ }
70
+
71
+ if (submitted) {
72
+ return (
73
+ <div className="rounded-sm border p-6 text-center">
74
+ <h3 className="text-lg font-semibold">Thank you!</h3>
75
+ <p className="mt-2 text-muted-foreground">${successMessage}</p>
76
+ </div>
77
+ )
78
+ }
79
+
80
+ return (
81
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
82
+ ${fieldJsx}
83
+
84
+ {form.formState.errors.root && (
85
+ <p className="text-sm text-destructive">{form.formState.errors.root.message}</p>
86
+ )}
87
+
88
+ <button
89
+ type="submit"
90
+ disabled={submitting}
91
+ aria-busy={submitting}
92
+ className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-xs transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
93
+ >
94
+ {submitting ? 'Submitting…' : ${submitText}}
95
+ </button>
96
+ </form>
97
+ )
98
+ }
99
+ `
100
+ }