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,50 @@
1
+ export function renderMarkdownFieldChangeHandlerTemplate({
2
+ indent,
3
+ defaultValueFromHandler
4
+ }: {
5
+ indent: string
6
+ defaultValueFromHandler: string
7
+ }): string {
8
+ return `(value) => {
9
+ ${indent} ${defaultValueFromHandler}(value)
10
+ ${indent} formField.onChange(value)
11
+ ${indent} }`
12
+ }
13
+
14
+ export function renderMarkdownFieldFormFieldTemplate({
15
+ indent,
16
+ fieldName,
17
+ fillFormItemProps,
18
+ labelWithDescription,
19
+ onChange,
20
+ fillControlClass,
21
+ toLowerCase
22
+ }: {
23
+ indent: string
24
+ fieldName: string
25
+ fillFormItemProps: string
26
+ labelWithDescription: string
27
+ onChange: string
28
+ fillControlClass: string
29
+ toLowerCase: string
30
+ }): string {
31
+ return `${indent}<FormField
32
+ ${indent} control={form.control}
33
+ ${indent} name="${fieldName}"
34
+ ${indent} render={({ field: formField }) => (
35
+ ${indent} <FormItem${fillFormItemProps}>
36
+ ${indent} ${labelWithDescription}
37
+ ${indent} <FormControl>
38
+ ${indent} <ContentEditor
39
+ ${indent} value={formField.value}
40
+ ${indent} onChange={${onChange}}
41
+ ${indent} defaultMode="source"
42
+ ${indent} className="${fillControlClass}"
43
+ ${indent} placeholder="Enter ${toLowerCase}"
44
+ ${indent} />
45
+ ${indent} </FormControl>
46
+ ${indent} <FormMessage />
47
+ ${indent} </FormItem>
48
+ ${indent} )}
49
+ ${indent}/>`
50
+ }
@@ -0,0 +1,47 @@
1
+ export function renderMediaFieldChangeHandlerTemplate({
2
+ indent,
3
+ defaultValueFromHandler
4
+ }: {
5
+ indent: string
6
+ defaultValueFromHandler: string
7
+ }): string {
8
+ return `(value) => {
9
+ ${indent} ${defaultValueFromHandler}(value)
10
+ ${indent} formField.onChange(value)
11
+ ${indent} }`
12
+ }
13
+
14
+ export function renderMediaFieldFormFieldTemplate({
15
+ indent,
16
+ fieldName,
17
+ formItemProps,
18
+ labelWithDescription,
19
+ onChange,
20
+ acceptProp
21
+ }: {
22
+ indent: string
23
+ fieldName: string
24
+ formItemProps: string
25
+ labelWithDescription: string
26
+ onChange: string
27
+ acceptProp: string
28
+ }): string {
29
+ return `${indent}<FormField
30
+ ${indent} control={form.control}
31
+ ${indent} name="${fieldName}"
32
+ ${indent} render={({ field: formField }) => (
33
+ ${indent} <FormItem${formItemProps}>
34
+ ${indent} ${labelWithDescription}
35
+ ${indent} <FormControl>
36
+ ${indent} <MediaField
37
+ ${indent} value={formField.value}
38
+ ${indent} onChange={${onChange}}
39
+ ${indent} onBlur={formField.onBlur}
40
+ ${indent} disabled={isPending}${acceptProp}
41
+ ${indent} />
42
+ ${indent} </FormControl>
43
+ ${indent} <FormMessage />
44
+ ${indent} </FormItem>
45
+ ${indent} )}
46
+ ${indent}/>`
47
+ }
@@ -0,0 +1,91 @@
1
+ export function renderMultiRelationshipFieldActionButtonsTemplate({
2
+ indent,
3
+ fieldName,
4
+ formItemProps,
5
+ labelWithDescription,
6
+ toPascalCase,
7
+ toLowerCase,
8
+ relSingular,
9
+ dataArray,
10
+ displayField,
11
+ secondaryDisplayField,
12
+ defaultValueFromHandlerContent
13
+ }: {
14
+ indent: string
15
+ fieldName: string
16
+ formItemProps: string
17
+ labelWithDescription: string
18
+ toPascalCase: string
19
+ toLowerCase: string
20
+ relSingular: string
21
+ dataArray: string
22
+ displayField: string
23
+ secondaryDisplayField: string
24
+ defaultValueFromHandlerContent: string
25
+ }): string {
26
+ return `${indent}<FormField
27
+ ${indent} control={form.control}
28
+ ${indent} name="${fieldName}"
29
+ ${indent} render={({ field: formField }) => (
30
+ ${indent} <FormItem${formItemProps}>
31
+ ${indent} ${labelWithDescription}
32
+ ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase}Open}>
33
+ ${indent} <PopoverTrigger asChild>
34
+ ${indent} <FormControl>
35
+ ${indent} <Button
36
+ ${indent} variant="outline"
37
+ ${indent} role="combobox"
38
+ ${indent} className={cn("w-full justify-between", {
39
+ ${indent} "text-muted-foreground": !formField.value || formField.value.length === 0
40
+ ${indent} })}
41
+ ${indent} disabled={isPending}
42
+ ${indent} >
43
+ ${indent} {(formField.value?.length ?? 0) > 0
44
+ ${indent} ? \`\${formField.value?.length ?? 0} selected\`
45
+ ${indent} : "Select ${toLowerCase}"}
46
+ ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
47
+ ${indent} </Button>
48
+ ${indent} </FormControl>
49
+ ${indent} </PopoverTrigger>
50
+ ${indent} <PopoverContent className="w-full p-0" align="start">
51
+ ${indent} <Command>
52
+ ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
53
+ ${indent} <CommandList>
54
+ ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
55
+ ${indent} <CommandGroup>
56
+ ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
57
+ ${indent} const displayName = ${displayField}
58
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
59
+ ${indent} const isSelected = formField.value?.includes(item.id) || false
60
+ ${indent} return (
61
+ ${indent} <CommandItem
62
+ ${indent} key={item.id}
63
+ ${indent} value={displayName}
64
+ ${indent} onSelect={() => {
65
+ ${indent} const current = formField.value || []
66
+ ${defaultValueFromHandlerContent}
67
+ ${indent} }}
68
+ ${indent} >
69
+ ${indent} <Check className={cn("size-4", {
70
+ ${indent} "opacity-100": isSelected,
71
+ ${indent} "opacity-0": !isSelected
72
+ ${indent} })} />
73
+ ${indent} <span className="flex min-w-0 flex-col text-left">
74
+ ${indent} <span className="truncate">{displayName}</span>
75
+ ${indent} {secondaryDisplayName ? (
76
+ ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
77
+ ${indent} ) : null}
78
+ ${indent} </span>
79
+ ${indent} </CommandItem>
80
+ ${indent} )
81
+ ${indent} })}
82
+ ${indent} </CommandGroup>
83
+ ${indent} </CommandList>
84
+ ${indent} </Command>
85
+ ${indent} </PopoverContent>
86
+ ${indent} </Popover>
87
+ ${indent} <FormMessage />
88
+ ${indent} </FormItem>
89
+ ${indent} )}
90
+ ${indent}/>`
91
+ }
@@ -0,0 +1,219 @@
1
+ export function renderMultiSelectFieldStaticOptionsTemplate({
2
+ staticOptions,
3
+ indent
4
+ }: {
5
+ staticOptions: string
6
+ indent: string
7
+ }): string {
8
+ return `const staticOptions = ${staticOptions}
9
+ ${indent} const options = staticOptions`
10
+ }
11
+
12
+ export function renderMultiSelectFieldContentTemplate({
13
+ indent,
14
+ lowerLabel,
15
+ searchVar,
16
+ setSearchVar
17
+ }: {
18
+ indent: string
19
+ lowerLabel: string
20
+ searchVar: string
21
+ setSearchVar: string
22
+ }): string {
23
+ return `<CommandInput
24
+ ${indent} placeholder="Search ${lowerLabel}..."
25
+ ${indent} value={${searchVar}}
26
+ ${indent} onValueChange={${setSearchVar}}
27
+ ${indent} />`
28
+ }
29
+
30
+ export function renderMultiSelectFieldCreateLabelTemplate({
31
+ indent,
32
+ searchVar
33
+ }: {
34
+ indent: string
35
+ searchVar: string
36
+ }): string {
37
+ return `
38
+ ${indent} const createLabel = ${searchVar}.trim()
39
+ ${indent} const canCreateOption =
40
+ ${indent} createLabel.length > 0 &&
41
+ ${indent} !options.some(
42
+ ${indent} (option) =>
43
+ ${indent} option.label.toLowerCase() === createLabel.toLowerCase() ||
44
+ ${indent} option.value.toLowerCase() === createLabel.toLowerCase()
45
+ ${indent} )
46
+ `
47
+ }
48
+
49
+ export function renderMultiSelectFieldActionButtonsTemplate({
50
+ indent,
51
+ pendingVar,
52
+ createHandler
53
+ }: {
54
+ indent: string
55
+ pendingVar: string
56
+ createHandler: string
57
+ }): string {
58
+ return `
59
+ ${indent} {canCreateOption ? (
60
+ ${indent} <>
61
+ ${indent} <CommandSeparator />
62
+ ${indent} <div className="p-1">
63
+ ${indent} <Button
64
+ ${indent} type="button"
65
+ ${indent} variant="ghost"
66
+ ${indent} className="w-full justify-start"
67
+ ${indent} disabled={${pendingVar}}
68
+ ${indent} aria-busy={${pendingVar}}
69
+ ${indent} onClick={() => ${createHandler}(createLabel)}
70
+ ${indent} >
71
+ ${indent} <Plus className="size-4" />
72
+ ${indent} {${pendingVar} ? 'Creating…' : \`Create "\${createLabel}"\`}
73
+ ${indent} </Button>
74
+ ${indent} </div>
75
+ ${indent} </>
76
+ ${indent} ) : null}`
77
+ }
78
+
79
+ export function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
80
+ indent,
81
+ fieldName,
82
+ optionsDeclaration,
83
+ createState,
84
+ previewLimit,
85
+ formItemProps,
86
+ labelWithDescription,
87
+ openVar,
88
+ setOpenVar,
89
+ stringify,
90
+ searchInput,
91
+ lowerLabel,
92
+ defaultValueFromHandlerContent,
93
+ clearSearch,
94
+ createAction
95
+ }: {
96
+ indent: string
97
+ fieldName: string
98
+ optionsDeclaration: string
99
+ createState: string
100
+ previewLimit: string
101
+ formItemProps: string
102
+ labelWithDescription: string
103
+ openVar: string
104
+ setOpenVar: string
105
+ stringify: string
106
+ searchInput: string
107
+ lowerLabel: string
108
+ defaultValueFromHandlerContent: string
109
+ clearSearch: string
110
+ createAction: string
111
+ }): string {
112
+ return `${indent}<FormField
113
+ ${indent} control={form.control}
114
+ ${indent} name="${fieldName}"
115
+ ${indent} render={({ field: formField }) => {
116
+ ${indent} ${optionsDeclaration}
117
+ ${indent} const selectedValues = Array.isArray(formField.value) ? formField.value : []
118
+ ${indent} const selectedOptions = options.filter((option) => selectedValues.includes(option.value))${createState}
119
+ ${indent} const previewLimit = ${previewLimit}
120
+ ${indent} const shouldCollapseSelectedOptions =
121
+ ${indent} selectedOptions.length > Math.max(previewLimit, 2)
122
+ ${indent} const visibleSelectedOptions = shouldCollapseSelectedOptions
123
+ ${indent} ? selectedOptions.slice(0, previewLimit)
124
+ ${indent} : selectedOptions
125
+ ${indent} const hiddenSelectedOptions = shouldCollapseSelectedOptions
126
+ ${indent} ? selectedOptions.slice(previewLimit)
127
+ ${indent} : []
128
+ ${indent} return (
129
+ ${indent} <FormItem${formItemProps}>
130
+ ${indent} ${labelWithDescription}
131
+ ${indent} <Popover open={${openVar}} onOpenChange={${setOpenVar}}>
132
+ ${indent} <PopoverTrigger asChild>
133
+ ${indent} <FormControl>
134
+ ${indent} <Button
135
+ ${indent} type="button"
136
+ ${indent} variant="outline"
137
+ ${indent} role="combobox"
138
+ ${indent} aria-expanded={${openVar}}
139
+ ${indent} className={cn("w-full justify-between gap-2", {
140
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
141
+ ${indent} })}
142
+ ${indent} disabled={isPending}
143
+ ${indent} >
144
+ ${indent} <span className="flex min-w-0 flex-1 items-center gap-2 text-left">
145
+ ${indent} {selectedOptions.length > 0 ? (
146
+ ${indent} <>
147
+ ${indent} <span className="truncate">
148
+ ${indent} {visibleSelectedOptions.map((option) => option.label).join(', ')}
149
+ ${indent} </span>
150
+ ${indent} {hiddenSelectedOptions.length > 0 ? (
151
+ ${indent} <Tooltip>
152
+ ${indent} <TooltipTrigger asChild>
153
+ ${indent} <Badge
154
+ ${indent} variant="outline"
155
+ ${indent} className="h-5 shrink-0 tabular-nums"
156
+ ${indent} >
157
+ ${indent} {'+'}
158
+ ${indent} {hiddenSelectedOptions.length}{' '}
159
+ ${indent} {hiddenSelectedOptions.length === 1 ? 'other' : 'others'}
160
+ ${indent} </Badge>
161
+ ${indent} </TooltipTrigger>
162
+ ${indent} <TooltipContent align="center" side="bottom" className="max-w-60 w-full">
163
+ ${indent} <div className="space-y-1">
164
+ ${indent} {hiddenSelectedOptions.map((option) => (
165
+ ${indent} <div key={option.value} className="truncate">
166
+ ${indent} {option.label}
167
+ ${indent} </div>
168
+ ${indent} ))}
169
+ ${indent} </div>
170
+ ${indent} </TooltipContent>
171
+ ${indent} </Tooltip>
172
+ ${indent} ) : null}
173
+ ${indent} </>
174
+ ${indent} ) : (
175
+ ${indent} <span className="truncate">{${stringify}}</span>
176
+ ${indent} )}
177
+ ${indent} </span>
178
+ ${indent} <ChevronsUpDown className="size-4 shrink-0 opacity-50" />
179
+ ${indent} </Button>
180
+ ${indent} </FormControl>
181
+ ${indent} </PopoverTrigger>
182
+ ${indent} <PopoverContent className="w-(--radix-popover-trigger-width) p-0" align="start">
183
+ ${indent} <Command>
184
+ ${indent} ${searchInput}
185
+ ${indent} <CommandList>
186
+ ${indent} <CommandEmpty>No ${lowerLabel} found.</CommandEmpty>
187
+ ${indent} <CommandGroup>
188
+ ${indent} {options.map((option) => {
189
+ ${indent} const isSelected = selectedValues.includes(option.value)
190
+ ${indent} return (
191
+ ${indent} <CommandItem
192
+ ${indent} key={option.value}
193
+ ${indent} value={\`\${option.label} \${option.value}\`}
194
+ ${indent} onSelect={() => {
195
+ ${indent} const nextValues = isSelected
196
+ ${indent} ? selectedValues.filter((value: string) => value !== option.value)
197
+ ${indent} : [...selectedValues, option.value]
198
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(nextValues)${clearSearch}
199
+ ${indent} }}
200
+ ${indent} >
201
+ ${indent} <Check className={cn("size-4", {
202
+ ${indent} "opacity-100": isSelected,
203
+ ${indent} "opacity-0": !isSelected
204
+ ${indent} })} />
205
+ ${indent} <span className="truncate">{option.label}</span>
206
+ ${indent} </CommandItem>
207
+ ${indent} )
208
+ ${indent} })}
209
+ ${indent} </CommandGroup>
210
+ ${indent} </CommandList>${createAction}
211
+ ${indent} </Command>
212
+ ${indent} </PopoverContent>
213
+ ${indent} </Popover>
214
+ ${indent} <FormMessage />
215
+ ${indent} </FormItem>
216
+ ${indent} )
217
+ ${indent} }}
218
+ ${indent}/>`
219
+ }
@@ -0,0 +1,48 @@
1
+ export function renderNumberFieldFormFieldTemplate({
2
+ indent,
3
+ fieldName,
4
+ formItemProps,
5
+ labelWithDescription,
6
+ fieldType,
7
+ stepProp,
8
+ toLowerCase,
9
+ emptyValue,
10
+ applyDefaultValueFrom
11
+ }: {
12
+ indent: string
13
+ fieldName: string
14
+ formItemProps: string
15
+ labelWithDescription: string
16
+ fieldType: string
17
+ stepProp: string
18
+ toLowerCase: string
19
+ emptyValue: string
20
+ applyDefaultValueFrom: string
21
+ }): string {
22
+ return `${indent}<FormField
23
+ ${indent} control={form.control}
24
+ ${indent} name="${fieldName}"
25
+ ${indent} render={({ field: formField }) => (
26
+ ${indent} <FormItem${formItemProps}>
27
+ ${indent} ${labelWithDescription}
28
+ ${indent} <FormControl>
29
+ ${indent} <Input
30
+ ${indent} type="${fieldType}"${stepProp}
31
+ ${indent} placeholder="Enter ${toLowerCase}"
32
+ ${indent} disabled={isPending}
33
+ ${indent} value={formField.value ?? ''}
34
+ ${indent} onChange={(event) => {
35
+ ${indent} const nextValue = event.target.value === '' ? ${emptyValue} : event.target.valueAsNumber
36
+ ${indent} const normalizedValue = Number.isNaN(nextValue) ? ${emptyValue} : nextValue
37
+ ${applyDefaultValueFrom}${indent} formField.onChange(normalizedValue)
38
+ ${indent} }}
39
+ ${indent} onBlur={formField.onBlur}
40
+ ${indent} name={formField.name}
41
+ ${indent} ref={formField.ref}
42
+ ${indent} />
43
+ ${indent} </FormControl>
44
+ ${indent} <FormMessage />
45
+ ${indent} </FormItem>
46
+ ${indent} )}
47
+ ${indent}/>`
48
+ }
@@ -0,0 +1,50 @@
1
+ export function renderRichtextFieldChangeHandlerTemplate({
2
+ indent,
3
+ defaultValueFromHandler
4
+ }: {
5
+ indent: string
6
+ defaultValueFromHandler: string
7
+ }): string {
8
+ return `(value) => {
9
+ ${indent} ${defaultValueFromHandler}(value)
10
+ ${indent} formField.onChange(value)
11
+ ${indent} }`
12
+ }
13
+
14
+ export function renderRichtextFieldFormFieldTemplate({
15
+ indent,
16
+ fieldName,
17
+ fillFormItemProps,
18
+ labelWithDescription,
19
+ onChange,
20
+ fillControlClass,
21
+ toLowerCase
22
+ }: {
23
+ indent: string
24
+ fieldName: string
25
+ fillFormItemProps: string
26
+ labelWithDescription: string
27
+ onChange: string
28
+ fillControlClass: string
29
+ toLowerCase: string
30
+ }): string {
31
+ return `${indent}<FormField
32
+ ${indent} control={form.control}
33
+ ${indent} name="${fieldName}"
34
+ ${indent} render={({ field: formField }) => (
35
+ ${indent} <FormItem${fillFormItemProps}>
36
+ ${indent} ${labelWithDescription}
37
+ ${indent} <FormControl>
38
+ ${indent} <ContentEditor
39
+ ${indent} value={formField.value}
40
+ ${indent} onChange={${onChange}}
41
+ ${indent} defaultMode="rich"
42
+ ${indent} className="${fillControlClass}"
43
+ ${indent} placeholder="Enter ${toLowerCase}"
44
+ ${indent} />
45
+ ${indent} </FormControl>
46
+ ${indent} <FormMessage />
47
+ ${indent} </FormItem>
48
+ ${indent} )}
49
+ ${indent}/>`
50
+ }
@@ -0,0 +1,61 @@
1
+ export function renderSelectFieldChangeHandlerTemplate({
2
+ indent,
3
+ defaultValueFromHandler
4
+ }: {
5
+ indent: string
6
+ defaultValueFromHandler: string
7
+ }): string {
8
+ return `(value) => {
9
+ ${indent} ${defaultValueFromHandler}(value)
10
+ ${indent} formField.onChange(value)
11
+ ${indent} }`
12
+ }
13
+
14
+ export function renderSelectFieldFormFieldTemplate({
15
+ indent,
16
+ fieldName,
17
+ formItemProps,
18
+ labelWithDescription,
19
+ validValuesExpression,
20
+ onValueChange,
21
+ selectedLabelExpression,
22
+ stringify,
23
+ optionsJsx
24
+ }: {
25
+ indent: string
26
+ fieldName: string
27
+ formItemProps: string
28
+ labelWithDescription: string
29
+ validValuesExpression: string
30
+ onValueChange: string
31
+ selectedLabelExpression: string
32
+ stringify: string
33
+ optionsJsx: string
34
+ }): string {
35
+ return `${indent}<FormField
36
+ ${indent} control={form.control}
37
+ ${indent} name="${fieldName}"
38
+ ${indent} render={({ field: formField }) => (
39
+ ${indent} <FormItem${formItemProps}>
40
+ ${indent} ${labelWithDescription}
41
+ ${indent} <FormControl>
42
+ ${indent} <Select
43
+ ${indent} value={typeof formField.value === "string" && ${validValuesExpression}.includes(formField.value) ? formField.value : undefined}
44
+ ${indent} onValueChange={${onValueChange}}
45
+ ${indent} disabled={isPending}
46
+ ${indent} >
47
+ ${indent} <SelectTrigger className="w-full">
48
+ ${indent} <span data-slot="select-value" className="pointer-events-none">
49
+ ${indent} {(${selectedLabelExpression}) ?? ${stringify}}
50
+ ${indent} </span>
51
+ ${indent} </SelectTrigger>
52
+ ${indent} <SelectContent position="popper" align="start">
53
+ ${optionsJsx}
54
+ ${indent} </SelectContent>
55
+ ${indent} </Select>
56
+ ${indent} </FormControl>
57
+ ${indent} <FormMessage />
58
+ ${indent} </FormItem>
59
+ ${indent} )}
60
+ ${indent}/>`
61
+ }
@@ -0,0 +1,16 @@
1
+ export function renderSeparatorFieldLayoutTemplate({
2
+ indent,
3
+ fieldLabel
4
+ }: {
5
+ indent: string
6
+ fieldLabel: string
7
+ }): string {
8
+ return `${indent}<div className="relative my-4">
9
+ ${indent} <div className="absolute inset-0 flex items-center">
10
+ ${indent} <Separator className="w-full" />
11
+ ${indent} </div>
12
+ ${indent} <div className="relative flex justify-center text-xs uppercase">
13
+ ${indent} <span className="bg-background px-2 text-muted-foreground">${fieldLabel}</span>
14
+ ${indent} </div>
15
+ ${indent}</div>`
16
+ }
@@ -0,0 +1,93 @@
1
+ export function renderSingleRelationshipFieldActionButtonsTemplate({
2
+ indent,
3
+ fieldName,
4
+ formItemProps,
5
+ labelWithDescription,
6
+ toPascalCase,
7
+ dataArray,
8
+ displayField,
9
+ toLowerCase,
10
+ relSingular,
11
+ secondaryDisplayField,
12
+ defaultValueFromHandlerContent
13
+ }: {
14
+ indent: string
15
+ fieldName: string
16
+ formItemProps: string
17
+ labelWithDescription: string
18
+ toPascalCase: string
19
+ dataArray: string
20
+ displayField: string
21
+ toLowerCase: string
22
+ relSingular: string
23
+ secondaryDisplayField: string
24
+ defaultValueFromHandlerContent: string
25
+ }): string {
26
+ return `${indent}<FormField
27
+ ${indent} control={form.control}
28
+ ${indent} name="${fieldName}"
29
+ ${indent} render={({ field: formField }) => (
30
+ ${indent} <FormItem${formItemProps}>
31
+ ${indent} ${labelWithDescription}
32
+ ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase}Open}>
33
+ ${indent} <PopoverTrigger asChild>
34
+ ${indent} <FormControl>
35
+ ${indent} <Button
36
+ ${indent} variant="outline"
37
+ ${indent} role="combobox"
38
+ ${indent} className={cn("w-full justify-between", {
39
+ ${indent} "text-muted-foreground": !formField.value
40
+ ${indent} })}
41
+ ${indent} disabled={isPending}
42
+ ${indent} >
43
+ ${indent} {formField.value
44
+ ${indent} ? (() => {
45
+ ${indent} const item = ${dataArray}?.find((item) => item.id !== null && String(item.id) === formField.value)
46
+ ${indent} return item ? (${displayField}) : "Select ${toLowerCase}"
47
+ ${indent} })()
48
+ ${indent} : "Select ${toLowerCase}"}
49
+ ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
50
+ ${indent} </Button>
51
+ ${indent} </FormControl>
52
+ ${indent} </PopoverTrigger>
53
+ ${indent} <PopoverContent className="w-full p-0" align="start">
54
+ ${indent} <Command>
55
+ ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
56
+ ${indent} <CommandList>
57
+ ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
58
+ ${indent} <CommandGroup>
59
+ ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
60
+ ${indent} const displayName = ${displayField}
61
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
62
+ ${indent} return (
63
+ ${indent} <CommandItem
64
+ ${indent} key={item.id}
65
+ ${indent} value={displayName}
66
+ ${indent} onSelect={() => {
67
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(String(item.id))
68
+ ${indent} set${toPascalCase}Open(false)
69
+ ${indent} }}
70
+ ${indent} >
71
+ ${indent} <Check className={cn("size-4", {
72
+ ${indent} "opacity-100": formField.value === String(item.id),
73
+ ${indent} "opacity-0": formField.value !== String(item.id)
74
+ ${indent} })} />
75
+ ${indent} <span className="flex min-w-0 flex-col text-left">
76
+ ${indent} <span className="truncate">{displayName}</span>
77
+ ${indent} {secondaryDisplayName ? (
78
+ ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
79
+ ${indent} ) : null}
80
+ ${indent} </span>
81
+ ${indent} </CommandItem>
82
+ ${indent} )
83
+ ${indent} })}
84
+ ${indent} </CommandGroup>
85
+ ${indent} </CommandList>
86
+ ${indent} </Command>
87
+ ${indent} </PopoverContent>
88
+ ${indent} </Popover>
89
+ ${indent} <FormMessage />
90
+ ${indent} </FormItem>
91
+ ${indent} )}
92
+ ${indent}/>`
93
+ }