betterstart-cli 0.0.110 → 0.0.112

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 (57) hide show
  1. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode-integrate.tsx +2 -2
  2. package/dist/assets/adapters/next/templates/init/components/shared/entity-filters-bar.tsx +1 -1
  3. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-drawer.tsx +1 -1
  4. package/dist/assets/adapters/next/templates/init/components/shared/media/media-filters-bar.tsx +2 -2
  5. package/dist/assets/adapters/next/templates/init/components/shared/media/media-gallery-dialog.tsx +1 -1
  6. package/dist/assets/adapters/next/templates/init/components/shared/media/media-preview.tsx +1 -1
  7. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-color-highlight.ts +1 -3
  8. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor-media-insertion.ts +1 -3
  9. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor.ts +2 -6
  10. package/dist/assets/adapters/next/templates/init/pages/account-shell.tsx +1 -1
  11. package/dist/assets/adapters/next/templates/init/pages/auth-gate.tsx +1 -1
  12. package/dist/assets/adapters/next/templates/init/pages/forgot-password-form.tsx +4 -4
  13. package/dist/assets/adapters/next/templates/init/pages/forgot-password-page-skeleton.tsx +3 -3
  14. package/dist/assets/adapters/next/templates/init/pages/forgot-password-page.tsx +2 -2
  15. package/dist/assets/adapters/next/templates/init/pages/login-form.tsx +4 -4
  16. package/dist/assets/adapters/next/templates/init/pages/login-page-skeleton.tsx +3 -3
  17. package/dist/assets/adapters/next/templates/init/pages/login-page.tsx +2 -2
  18. package/dist/assets/adapters/next/templates/init/pages/media/media-page-content.tsx +1 -1
  19. package/dist/assets/adapters/next/templates/init/pages/reset-password-form.tsx +8 -8
  20. package/dist/assets/adapters/next/templates/init/pages/reset-password-page-skeleton.tsx +3 -3
  21. package/dist/assets/adapters/next/templates/init/pages/reset-password-page.tsx +2 -2
  22. package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-detail-drawer.tsx +1 -1
  23. package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-page.tsx +1 -1
  24. package/dist/assets/adapters/next/templates/init/pages/settings/forms/form-notifications-drawer.tsx +1 -1
  25. package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-page.tsx +1 -1
  26. package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/delete-webhook-dialog.tsx +1 -1
  27. package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhook-endpoint-dialog.tsx +1 -1
  28. package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-logs-page.tsx +1 -1
  29. package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-page.tsx +1 -1
  30. package/dist/assets/adapters/next/templates/init/pages/users/change-password-dialog.tsx +1 -1
  31. package/dist/assets/adapters/next/templates/init/pages/users/create-user-dialog.tsx +1 -1
  32. package/dist/assets/adapters/next/templates/init/pages/users/edit-role-dialog.tsx +1 -1
  33. package/dist/assets/shared-assets/react-admin/custom/content-editor/index.tsx +5 -30
  34. package/dist/assets/shared-assets/react-admin/custom/content-editor/main-toolbar-content.tsx +6 -28
  35. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-node/removable-image-node/removable-image-node.tsx +1 -1
  36. package/dist/assets/shared-assets/react-admin/custom/gallery-field.tsx +3 -3
  37. package/dist/assets/shared-assets/react-admin/ui/alert-dialog.tsx +6 -6
  38. package/dist/assets/shared-assets/react-admin/ui/alert.tsx +1 -1
  39. package/dist/assets/shared-assets/react-admin/ui/breadcrumb.tsx +1 -1
  40. package/dist/assets/shared-assets/react-admin/ui/calendar.tsx +1 -1
  41. package/dist/assets/shared-assets/react-admin/ui/card.tsx +1 -1
  42. package/dist/assets/shared-assets/react-admin/ui/dialog.tsx +2 -2
  43. package/dist/assets/shared-assets/react-admin/ui/drawer.tsx +2 -2
  44. package/dist/assets/shared-assets/react-admin/ui/field.tsx +2 -4
  45. package/dist/assets/shared-assets/react-admin/ui/input.tsx +1 -1
  46. package/dist/assets/shared-assets/react-admin/ui/pagination.tsx +2 -2
  47. package/dist/assets/shared-assets/react-admin/ui/sheet.tsx +1 -1
  48. package/dist/assets/shared-assets/react-admin/ui/sidebar.tsx +13 -63
  49. package/dist/assets/shared-assets/react-admin/ui/textarea.tsx +1 -1
  50. package/dist/cli.js +327 -466
  51. package/dist/cli.js.map +1 -1
  52. package/package.json +1 -1
  53. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor-mobile-toolbar.ts +0 -17
  54. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-is-breakpoint.ts +0 -24
  55. package/dist/assets/adapters/next/templates/init/hooks/use-mobile.ts +0 -19
  56. package/dist/assets/shared-assets/react-admin/custom/content-editor/mobile-toolbar-content.tsx +0 -56
  57. package/dist/assets/shared-assets/react-admin/ui/command.tsx +0 -180
package/dist/cli.js CHANGED
@@ -2788,7 +2788,6 @@ var REACT_ADMIN_DEPS = [
2788
2788
  "@tiptap/starter-kit",
2789
2789
  "@uiw/codemirror-theme-github",
2790
2790
  "@uiw/react-codemirror",
2791
- "cmdk",
2792
2791
  "embla-carousel-react",
2793
2792
  "input-otp",
2794
2793
  "katex",
@@ -2849,9 +2848,7 @@ var STATIC_CUSTOM_DEPENDENCIES = {
2849
2848
  "use-content-editor",
2850
2849
  "use-content-editor-table-add-controls",
2851
2850
  "use-content-editor-source-mode",
2852
- "use-content-editor-mobile-toolbar",
2853
2851
  "use-content-editor-slash-menu",
2854
- "use-mobile",
2855
2852
  "tiptap",
2856
2853
  "tiptap-utils"
2857
2854
  ],
@@ -2935,11 +2932,6 @@ var STATIC_CUSTOM_DEPENDENCIES = {
2935
2932
  "tiptap-utils"
2936
2933
  ],
2937
2934
  "content-editor/media-gallery-block": ["media-field"],
2938
- "content-editor/mobile-toolbar-content": [
2939
- "content-editor/math-popover",
2940
- "content-editor/use-tiptap-editor",
2941
- "tiptap-utils"
2942
- ],
2943
2935
  "content-editor/selection-bubble-menu": ["content-editor/math-popover"],
2944
2936
  "content-editor/slash-command-menu": ["content-editor-slash-commands-utils", "tiptap-utils"],
2945
2937
  "content-editor/source-mode": [
@@ -2986,7 +2978,6 @@ var TIPTAP_TEMPLATE_DEPENDENCIES = [
2986
2978
  "use-blockquote",
2987
2979
  "use-code-block",
2988
2980
  "use-color-highlight",
2989
- "content-editor/use-is-breakpoint",
2990
2981
  "content-editor/use-menu-navigation",
2991
2982
  "content-editor/use-tiptap-editor",
2992
2983
  "use-content-editor-table-add-controls",
@@ -4690,7 +4681,7 @@ ${errorMessageLine2}
4690
4681
 
4691
4682
  // adapters/next/generators/form-pipeline/form-component-shared/input-class.ts
4692
4683
  function inputClass(height) {
4693
- const base = "h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
4684
+ const base = "h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50";
4694
4685
  return height === "fill" ? `${base} flex-1` : base;
4695
4686
  }
4696
4687
 
@@ -5112,7 +5103,7 @@ function generateNumberFieldJSX(name, label, placeholder, hintJSX, requiredStar,
5112
5103
 
5113
5104
  // adapters/next/generators/form-pipeline/form-component-shared/textarea-class.ts
5114
5105
  function textareaClass(height) {
5115
- const base = "min-h-24 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs outline-none transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
5106
+ const base = "min-h-24 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50";
5116
5107
  return height === "fill" ? `${base} flex-1` : base;
5117
5108
  }
5118
5109
 
@@ -5346,7 +5337,7 @@ function renderFieldsJSX(fields) {
5346
5337
  if (f.type === "group" && f.fields) {
5347
5338
  const cols = f.columns || 2;
5348
5339
  const innerJSX = renderFieldsJSX(f.fields);
5349
- const groupJSX = ` <div className="grid grid-cols-1 md:grid-cols-${cols} gap-5">
5340
+ const groupJSX = ` <div className="grid grid-cols-${cols} gap-5">
5350
5341
  ${innerJSX}
5351
5342
  </div>`;
5352
5343
  return f.showWhen ? wrapShowWhen(f, groupJSX) : groupJSX;
@@ -7199,7 +7190,7 @@ export function ${pascal}SubmissionDrawer({
7199
7190
 
7200
7191
  return (
7201
7192
  <Drawer swipeDirection="right" open={open} onOpenChange={onOpenChange} modal>
7202
- <DrawerContent className="h-full w-full overflow-hidden data-[swipe-direction=right]:sm:max-w-xl">
7193
+ <DrawerContent className="h-full w-full overflow-hidden data-[swipe-direction=right]:max-w-xl">
7203
7194
  <DrawerHeader>
7204
7195
  <DrawerTitle>${label} Submission</DrawerTitle>
7205
7196
  <DrawerDescription>{description}</DrawerDescription>
@@ -15030,30 +15021,7 @@ function generateDatabase(schema, dbDir, options = {}, relatedSchemas = /* @__PU
15030
15021
  };
15031
15022
  }
15032
15023
 
15033
- // adapters/next/templates/renderers/generators/edit-page.ts
15034
- function renderEditPageShellTemplate({
15035
- singular,
15036
- kebabSingular
15037
- }) {
15038
- return `import * as React from 'react'
15039
- import { Edit${singular}PageContent } from './edit-${kebabSingular}-page-content'
15040
- import { Edit${singular}PageSkeleton } from './edit-${kebabSingular}-page-skeleton'
15041
-
15042
- interface PageProps {
15043
- params: Promise<{
15044
- id: string
15045
- }>
15046
- }
15047
-
15048
- export default function Edit${singular}Page({ params }: PageProps) {
15049
- return (
15050
- <React.Suspense fallback={<Edit${singular}PageSkeleton />}>
15051
- <Edit${singular}PageContent params={params} />
15052
- </React.Suspense>
15053
- )
15054
- }
15055
- `;
15056
- }
15024
+ // adapters/next/templates/renderers/generators/edit-page-content.ts
15057
15025
  function renderEditPageContentTemplate({
15058
15026
  singular,
15059
15027
  actionImportPath,
@@ -15076,22 +15044,30 @@ export async function Edit${singular}PageContent({ params }: { params: Promise<{
15076
15044
  }
15077
15045
  `;
15078
15046
  }
15079
- function renderEditPageFiles({
15047
+
15048
+ // adapters/next/templates/renderers/generators/edit-page.ts
15049
+ function renderEditPageTemplate({
15080
15050
  singular,
15081
- actionImportPath,
15082
- kebabName,
15083
- kebabSingular,
15084
- camelSingular
15051
+ kebabSingular
15085
15052
  }) {
15086
- return {
15087
- page: renderEditPageShellTemplate({ singular, kebabSingular }),
15088
- content: renderEditPageContentTemplate({
15089
- singular,
15090
- actionImportPath,
15091
- kebabName,
15092
- camelSingular
15093
- })
15094
- };
15053
+ return `import * as React from 'react'
15054
+ import { Edit${singular}PageContent } from './edit-${kebabSingular}-page-content'
15055
+ import { Edit${singular}PageSkeleton } from './edit-${kebabSingular}-page-skeleton'
15056
+
15057
+ interface PageProps {
15058
+ params: Promise<{
15059
+ id: string
15060
+ }>
15061
+ }
15062
+
15063
+ export default function Edit${singular}Page({ params }: PageProps) {
15064
+ return (
15065
+ <React.Suspense fallback={<Edit${singular}PageSkeleton />}>
15066
+ <Edit${singular}PageContent params={params} />
15067
+ </React.Suspense>
15068
+ )
15069
+ }
15070
+ `;
15095
15071
  }
15096
15072
 
15097
15073
  // adapters/next/generators/edit-page.ts
@@ -15103,11 +15079,11 @@ function generateEditPage(schema, pagesDir, options = {}) {
15103
15079
  const kebabSingular = toKebabCase(singular);
15104
15080
  const actionImportPath = resolveSchemaActionImportPath(schema.name, options.outputNamespace);
15105
15081
  const displayNouns = resolveDisplayNouns(schema);
15106
- const { page, content } = renderEditPageFiles({
15082
+ const page = renderEditPageTemplate({ singular: Singular, kebabSingular });
15083
+ const content = renderEditPageContentTemplate({
15107
15084
  singular: Singular,
15108
15085
  actionImportPath,
15109
15086
  kebabName,
15110
- kebabSingular,
15111
15087
  camelSingular
15112
15088
  });
15113
15089
  const skeleton = buildLoadingSkeletonSource(`Edit${Singular}PageSkeleton`, displayNouns.singular);
@@ -15597,17 +15573,10 @@ function renderBuildUiImportsImportsDetailsTemplate() {
15597
15573
  SelectTrigger
15598
15574
  } from '@admin/components/ui/select'`;
15599
15575
  }
15600
- function renderBuildUiImportsImportsDetailsBranchTemplate({ join }) {
15576
+ function renderComboboxImports({ join }) {
15601
15577
  return `import {
15602
15578
  ${join}
15603
- } from '@admin/components/ui/command'`;
15604
- }
15605
- function renderBuildUiImportsImportsDetailsBranchBodyTemplate() {
15606
- return `import {
15607
- Popover,
15608
- PopoverContent,
15609
- PopoverTrigger
15610
- } from '@admin/components/ui/popover'`;
15579
+ } from '@admin/components/ui/combobox'`;
15611
15580
  }
15612
15581
  function renderTooltipImports() {
15613
15582
  return `import {
@@ -15638,10 +15607,8 @@ function renderBuildUiImportsRenderer(request) {
15638
15607
  return renderBuildUiImportsImportsTemplate(request.props);
15639
15608
  case "renderBuildUiImportsImportsDetailsTemplate":
15640
15609
  return renderBuildUiImportsImportsDetailsTemplate();
15641
- case "renderBuildUiImportsImportsDetailsBranchTemplate":
15642
- return renderBuildUiImportsImportsDetailsBranchTemplate(request.props);
15643
- case "renderBuildUiImportsImportsDetailsBranchBodyTemplate":
15644
- return renderBuildUiImportsImportsDetailsBranchBodyTemplate();
15610
+ case "renderComboboxImports":
15611
+ return renderComboboxImports(request.props);
15645
15612
  case "renderTooltipImports":
15646
15613
  return renderTooltipImports();
15647
15614
  case "renderTabsImports":
@@ -15691,26 +15658,24 @@ function buildUiImports(ctx) {
15691
15658
  );
15692
15659
  }
15693
15660
  if (ctx.hasRelationship || ctx.hasSelectCombobox) {
15694
- const commandImports = [
15695
- "Command",
15696
- "CommandEmpty",
15697
- "CommandGroup",
15698
- "CommandInput",
15699
- "CommandItem",
15700
- "CommandList",
15701
- ctx.hasCreatableSelect ? "CommandSeparator" : ""
15661
+ const comboboxImports = [
15662
+ "Combobox",
15663
+ "ComboboxContent",
15664
+ "ComboboxEmpty",
15665
+ "ComboboxInput",
15666
+ "ComboboxItem",
15667
+ "ComboboxList",
15668
+ ctx.hasCreatableSelect ? "ComboboxSeparator" : "",
15669
+ "ComboboxTrigger"
15702
15670
  ].filter(Boolean);
15703
15671
  uiImports.push(
15704
15672
  renderBuildUiImportsRenderer({
15705
- kind: "renderBuildUiImportsImportsDetailsBranchTemplate",
15673
+ kind: "renderComboboxImports",
15706
15674
  props: {
15707
- join: commandImports.join(",\n ")
15675
+ join: comboboxImports.join(",\n ")
15708
15676
  }
15709
15677
  })
15710
15678
  );
15711
- uiImports.push(
15712
- renderBuildUiImportsRenderer({ kind: "renderBuildUiImportsImportsDetailsBranchBodyTemplate" })
15713
- );
15714
15679
  }
15715
15680
  if (ctx.hasMultiSelect) {
15716
15681
  uiImports.push("import { Badge } from '@admin/components/ui/badge'");
@@ -16042,15 +16007,15 @@ ${join}
16042
16007
  }
16043
16008
  function renderFormLayoutDetailsTemplate() {
16044
16009
  return `className={initialData?.id != null
16045
- ? 'lg:sticky lg:top-32 space-y-4 pb-4'
16046
- : 'lg:sticky lg:top-14 space-y-4 pb-4'}`;
16010
+ ? 'sticky top-32 space-y-4 pb-4'
16011
+ : 'sticky top-14 space-y-4 pb-4'}`;
16047
16012
  }
16048
16013
  function renderFormCardContentGridTemplate({
16049
16014
  tabSidebarEntriesGrid,
16050
16015
  tabMainFieldsJsx,
16051
16016
  sidebarColumn
16052
16017
  }) {
16053
- return ` <div className="grid grid-cols-1 ${tabSidebarEntriesGrid}h-full min-h-0 gap-4 items-stretch">
16018
+ return ` <div className="grid ${tabSidebarEntriesGrid} h-full min-h-0 gap-4 items-stretch">
16054
16019
  <div className="h-full min-h-0 min-w-0">
16055
16020
  <Card className="min-h-0 min-w-0 h-full">
16056
16021
  <CardContent className="space-y-5 gap-0 h-full min-h-0">
@@ -16066,7 +16031,7 @@ function renderFormLayoutDetailsBranchTemplate() {
16066
16031
  className={cn(
16067
16032
  'grid grid-cols-1 gap-4 items-start h-full',
16068
16033
  {
16069
- 'lg:grid-cols-[1fr_360px]': hasVisibleSidebarFields
16034
+ 'grid-cols-[1fr_360px]': hasVisibleSidebarFields
16070
16035
  }
16071
16036
  )}
16072
16037
  >`;
@@ -16519,7 +16484,7 @@ function renderFormLayoutDetailsBranchBodyTemplate({
16519
16484
  return ` {initialData?.id != null && (
16520
16485
  <div
16521
16486
  className={cn(
16522
- 'sticky z-100 flex flex-col gap-1 px-4 bg-background h-14 xl:flex-row xl:items-center xl:justify-between top-14 transition-shadow overflow-x-clip',
16487
+ 'sticky z-100 flex flex-row items-center justify-between gap-1 px-4 bg-background h-14 top-14 transition-shadow overflow-x-clip',
16523
16488
  {
16524
16489
  'shadow-modal/2': hasScrolled,
16525
16490
  'border-b border-border/80': !hasScrolled
@@ -18172,69 +18137,69 @@ function renderMultiRelationshipFieldActionButtonsTemplate({
18172
18137
  return `${indent}<FormField
18173
18138
  ${indent} control={form.control}
18174
18139
  ${indent} name="${fieldName}"
18175
- ${indent} render={({ field: formField }) => (
18176
- ${indent} <FormItem${formItemProps2}>
18177
- ${indent} ${labelWithDescription2}
18178
- ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase2}Open}>
18179
- ${indent} <PopoverTrigger
18180
- ${indent} render={
18181
- ${indent} <FormControl>
18182
- ${indent} <Button
18183
- ${indent} variant="outline"
18184
- ${indent} role="combobox"
18140
+ ${indent} render={({ field: formField }) => {
18141
+ ${indent} const options = (${dataArray} ?? [])
18142
+ ${indent} .filter((item) => item.id !== null)
18143
+ ${indent} .map((item) => {
18144
+ ${indent} const displayName = ${displayField}
18145
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18146
+ ${indent} return {
18147
+ ${indent} value: item.id,
18148
+ ${indent} label: displayName,
18149
+ ${indent} secondaryLabel: secondaryDisplayName
18150
+ ${indent} }
18151
+ ${indent} })
18152
+ ${indent} const selectedValues = formField.value ?? []
18153
+ ${indent} const selectedOptions = options.filter((option) => selectedValues.includes(option.value))
18154
+ ${indent} return (
18155
+ ${indent} <FormItem${formItemProps2}>
18156
+ ${indent} ${labelWithDescription2}
18157
+ ${indent} <Combobox
18158
+ ${indent} multiple
18159
+ ${indent} items={options}
18160
+ ${indent} value={selectedOptions}
18161
+ ${indent} open={${fieldName}Open}
18162
+ ${indent} onOpenChange={set${toPascalCase2}Open}
18163
+ ${indent} onValueChange={(nextOptions) => {
18164
+ ${indent} const nextValue = nextOptions.map((option) => option.value)
18165
+ ${defaultValueFromHandlerContent}
18166
+ ${indent} }}
18167
+ ${indent} >
18168
+ ${indent} <FormControl>
18169
+ ${indent} <ComboboxTrigger
18170
+ ${indent} render={<Button variant="outline" disabled={isPending} />}
18185
18171
  ${indent} className={cn("w-full justify-between", {
18186
- ${indent} "text-muted-foreground": !formField.value || formField.value.length === 0
18172
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
18187
18173
  ${indent} })}
18188
- ${indent} disabled={isPending}
18189
- ${indent} >
18190
- ${indent} {(formField.value?.length ?? 0) > 0
18191
- ${indent} ? \`\${formField.value?.length ?? 0} selected\`
18192
- ${indent} : "Select ${toLowerCase}"}
18193
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18194
- ${indent} </Button>
18195
- ${indent} </FormControl>
18196
- ${indent} }
18197
- ${indent} />
18198
- ${indent} <PopoverContent className="w-full p-0" align="start">
18199
- ${indent} <Command>
18200
- ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
18201
- ${indent} <CommandList>
18202
- ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
18203
- ${indent} <CommandGroup>
18204
- ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
18205
- ${indent} const displayName = ${displayField}
18206
- ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18207
- ${indent} const isSelected = formField.value?.includes(item.id) || false
18208
- ${indent} return (
18209
- ${indent} <CommandItem
18210
- ${indent} key={item.id}
18211
- ${indent} value={displayName}
18212
- ${indent} onSelect={() => {
18213
- ${indent} const current = formField.value || []
18214
- ${defaultValueFromHandlerContent}
18215
- ${indent} }}
18216
- ${indent} >
18217
- ${indent} <Check className={cn("size-4", {
18218
- ${indent} "opacity-100": isSelected,
18219
- ${indent} "opacity-0": !isSelected
18220
- ${indent} })} />
18221
- ${indent} <span className="flex min-w-0 flex-col text-left">
18222
- ${indent} <span className="truncate">{displayName}</span>
18223
- ${indent} {secondaryDisplayName ? (
18224
- ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
18225
- ${indent} ) : null}
18226
- ${indent} </span>
18227
- ${indent} </CommandItem>
18228
- ${indent} )
18229
- ${indent} })}
18230
- ${indent} </CommandGroup>
18231
- ${indent} </CommandList>
18232
- ${indent} </Command>
18233
- ${indent} </PopoverContent>
18234
- ${indent} </Popover>
18235
- ${indent} <FormMessage />
18236
- ${indent} </FormItem>
18237
- ${indent} )}
18174
+ ${indent} >
18175
+ ${indent} <span className="truncate">
18176
+ ${indent} {selectedOptions.length > 0
18177
+ ${indent} ? \`\${selectedOptions.length} selected\`
18178
+ ${indent} : "Select ${toLowerCase}"}
18179
+ ${indent} </span>
18180
+ ${indent} </ComboboxTrigger>
18181
+ ${indent} </FormControl>
18182
+ ${indent} <ComboboxContent align="start">
18183
+ ${indent} <ComboboxInput placeholder="Search ${toLowerCase}..." showTrigger={false} />
18184
+ ${indent} <ComboboxEmpty>No ${relSingular} found.</ComboboxEmpty>
18185
+ ${indent} <ComboboxList>
18186
+ ${indent} {(option) => (
18187
+ ${indent} <ComboboxItem key={option.value} value={option}>
18188
+ ${indent} <span className="flex min-w-0 flex-col text-left">
18189
+ ${indent} <span className="truncate">{option.label}</span>
18190
+ ${indent} {option.secondaryLabel ? (
18191
+ ${indent} <span className="truncate text-xs text-muted-foreground">{option.secondaryLabel}</span>
18192
+ ${indent} ) : null}
18193
+ ${indent} </span>
18194
+ ${indent} </ComboboxItem>
18195
+ ${indent} )}
18196
+ ${indent} </ComboboxList>
18197
+ ${indent} </ComboboxContent>
18198
+ ${indent} </Combobox>
18199
+ ${indent} <FormMessage />
18200
+ ${indent} </FormItem>
18201
+ ${indent} )
18202
+ ${indent} }}
18238
18203
  ${indent}/>`;
18239
18204
  }
18240
18205
 
@@ -18252,13 +18217,8 @@ function renderMultiRelationshipField(field, indent, label, hintJSX, displayFiel
18252
18217
  dataArray,
18253
18218
  displayField,
18254
18219
  secondaryDisplayField,
18255
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} const nextValue = isSelected
18256
- ${indent} ? current.filter((id: string) => id !== item.id)
18257
- ${indent} : [...current, item.id]
18258
- ${indent} ${defaultValueFromHandler}(nextValue)
18259
- ${indent} formField.onChange(nextValue)` : `${indent} formField.onChange(isSelected
18260
- ${indent} ? current.filter((id: string) => id !== item.id)
18261
- ${indent} : [...current, item.id])`
18220
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValue)
18221
+ ${indent} formField.onChange(nextValue)` : `${indent} formField.onChange(nextValue)`
18262
18222
  });
18263
18223
  }
18264
18224
 
@@ -18279,71 +18239,64 @@ function renderSingleRelationshipFieldActionButtonsTemplate({
18279
18239
  return `${indent}<FormField
18280
18240
  ${indent} control={form.control}
18281
18241
  ${indent} name="${fieldName}"
18282
- ${indent} render={({ field: formField }) => (
18283
- ${indent} <FormItem${formItemProps2}>
18284
- ${indent} ${labelWithDescription2}
18285
- ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase2}Open}>
18286
- ${indent} <PopoverTrigger
18287
- ${indent} render={
18288
- ${indent} <FormControl>
18289
- ${indent} <Button
18290
- ${indent} variant="outline"
18291
- ${indent} role="combobox"
18242
+ ${indent} render={({ field: formField }) => {
18243
+ ${indent} const options = (${dataArray} ?? [])
18244
+ ${indent} .filter((item) => item.id !== null)
18245
+ ${indent} .map((item) => {
18246
+ ${indent} const displayName = ${displayField}
18247
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18248
+ ${indent} return {
18249
+ ${indent} value: String(item.id),
18250
+ ${indent} label: displayName,
18251
+ ${indent} secondaryLabel: secondaryDisplayName
18252
+ ${indent} }
18253
+ ${indent} })
18254
+ ${indent} const selectedOption = options.find((option) => option.value === formField.value) ?? null
18255
+ ${indent} return (
18256
+ ${indent} <FormItem${formItemProps2}>
18257
+ ${indent} ${labelWithDescription2}
18258
+ ${indent} <Combobox
18259
+ ${indent} items={options}
18260
+ ${indent} value={selectedOption}
18261
+ ${indent} open={${fieldName}Open}
18262
+ ${indent} onOpenChange={set${toPascalCase2}Open}
18263
+ ${indent} onValueChange={(option) => {
18264
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(option?.value ?? '')
18265
+ ${indent} }}
18266
+ ${indent} >
18267
+ ${indent} <FormControl>
18268
+ ${indent} <ComboboxTrigger
18269
+ ${indent} render={<Button variant="outline" disabled={isPending} />}
18292
18270
  ${indent} className={cn("w-full justify-between", {
18293
18271
  ${indent} "text-muted-foreground": !formField.value
18294
18272
  ${indent} })}
18295
- ${indent} disabled={isPending}
18296
- ${indent} >
18297
- ${indent} {formField.value
18298
- ${indent} ? (() => {
18299
- ${indent} const item = ${dataArray}?.find((item) => item.id !== null && String(item.id) === formField.value)
18300
- ${indent} return item ? (${displayField}) : "Select ${toLowerCase}"
18301
- ${indent} })()
18302
- ${indent} : "Select ${toLowerCase}"}
18303
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18304
- ${indent} </Button>
18305
- ${indent} </FormControl>
18306
- ${indent} }
18307
- ${indent} />
18308
- ${indent} <PopoverContent className="w-full p-0" align="start">
18309
- ${indent} <Command>
18310
- ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
18311
- ${indent} <CommandList>
18312
- ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
18313
- ${indent} <CommandGroup>
18314
- ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
18315
- ${indent} const displayName = ${displayField}
18316
- ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18317
- ${indent} return (
18318
- ${indent} <CommandItem
18319
- ${indent} key={item.id}
18320
- ${indent} value={displayName}
18321
- ${indent} onSelect={() => {
18322
- ${defaultValueFromHandlerContent}${indent} formField.onChange(String(item.id))
18323
- ${indent} set${toPascalCase2}Open(false)
18324
- ${indent} }}
18325
- ${indent} >
18326
- ${indent} <Check className={cn("size-4", {
18327
- ${indent} "opacity-100": formField.value === String(item.id),
18328
- ${indent} "opacity-0": formField.value !== String(item.id)
18329
- ${indent} })} />
18330
- ${indent} <span className="flex min-w-0 flex-col text-left">
18331
- ${indent} <span className="truncate">{displayName}</span>
18332
- ${indent} {secondaryDisplayName ? (
18333
- ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
18334
- ${indent} ) : null}
18335
- ${indent} </span>
18336
- ${indent} </CommandItem>
18337
- ${indent} )
18338
- ${indent} })}
18339
- ${indent} </CommandGroup>
18340
- ${indent} </CommandList>
18341
- ${indent} </Command>
18342
- ${indent} </PopoverContent>
18343
- ${indent} </Popover>
18344
- ${indent} <FormMessage />
18345
- ${indent} </FormItem>
18346
- ${indent} )}
18273
+ ${indent} >
18274
+ ${indent} <span className="truncate">
18275
+ ${indent} {selectedOption ? selectedOption.label : "Select ${toLowerCase}"}
18276
+ ${indent} </span>
18277
+ ${indent} </ComboboxTrigger>
18278
+ ${indent} </FormControl>
18279
+ ${indent} <ComboboxContent align="start">
18280
+ ${indent} <ComboboxInput placeholder="Search ${toLowerCase}..." showTrigger={false} />
18281
+ ${indent} <ComboboxEmpty>No ${relSingular} found.</ComboboxEmpty>
18282
+ ${indent} <ComboboxList>
18283
+ ${indent} {(option) => (
18284
+ ${indent} <ComboboxItem key={option.value} value={option}>
18285
+ ${indent} <span className="flex min-w-0 flex-col text-left">
18286
+ ${indent} <span className="truncate">{option.label}</span>
18287
+ ${indent} {option.secondaryLabel ? (
18288
+ ${indent} <span className="truncate text-xs text-muted-foreground">{option.secondaryLabel}</span>
18289
+ ${indent} ) : null}
18290
+ ${indent} </span>
18291
+ ${indent} </ComboboxItem>
18292
+ ${indent} )}
18293
+ ${indent} </ComboboxList>
18294
+ ${indent} </ComboboxContent>
18295
+ ${indent} </Combobox>
18296
+ ${indent} <FormMessage />
18297
+ ${indent} </FormItem>
18298
+ ${indent} )
18299
+ ${indent} }}
18347
18300
  ${indent}/>`;
18348
18301
  }
18349
18302
 
@@ -18361,7 +18314,7 @@ function renderSingleRelationshipField(field, indent, label, hintJSX, displayFie
18361
18314
  toLowerCase: label.toLowerCase(),
18362
18315
  relSingular,
18363
18316
  secondaryDisplayField,
18364
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(String(item.id))
18317
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18365
18318
  ` : ""
18366
18319
  });
18367
18320
  }
@@ -18557,7 +18510,7 @@ function renderCreatableSelectFieldActionButtonsTemplate({
18557
18510
  ${indent} control={form.control}
18558
18511
  ${indent} name="${fieldName}"
18559
18512
  ${indent} render={({ field: formField }) => {
18560
- ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value)
18513
+ ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value) ?? null
18561
18514
  ${indent} const createLabel = ${searchVar}.trim()
18562
18515
  ${indent} const canCreateOption =
18563
18516
  ${indent} createLabel.length > 0 &&
@@ -18570,76 +18523,58 @@ ${indent} )
18570
18523
  ${indent} return (
18571
18524
  ${indent} <FormItem${formItemProps2}>
18572
18525
  ${indent} ${labelWithDescription2}
18573
- ${indent} <Popover open={${openVar}} onOpenChange={${setOpenVar}}>
18574
- ${indent} <PopoverTrigger
18575
- ${indent} render={
18576
- ${indent} <FormControl>
18577
- ${indent} <Button
18578
- ${indent} type="button"
18579
- ${indent} variant="outline"
18580
- ${indent} role="combobox"
18581
- ${indent} aria-expanded={${openVar}}
18582
- ${indent} className={cn("w-full justify-between", {
18583
- ${indent} "text-muted-foreground": !selectedOption
18584
- ${indent} })}
18585
- ${indent} disabled={isPending}
18586
- ${indent} >
18587
- ${indent} <span className="truncate">{selectedOption?.label ?? ${stringify}}</span>
18588
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18589
- ${indent} </Button>
18590
- ${indent} </FormControl>
18591
- ${indent} }
18592
- ${indent} />
18593
- ${indent} <PopoverContent className="w-(--anchor-width) p-0" align="start">
18594
- ${indent} <Command>
18595
- ${indent} <CommandInput
18596
- ${indent} placeholder="Search ${lowerLabel}..."
18597
- ${indent} value={${searchVar}}
18598
- ${indent} onValueChange={${setSearchVar}}
18599
- ${indent} />
18600
- ${indent} <CommandList>
18601
- ${indent} <CommandEmpty>No ${lowerLabel} found.</CommandEmpty>
18602
- ${indent} <CommandGroup>
18603
- ${indent} {${optionsVar}.map((option) => (
18604
- ${indent} <CommandItem
18605
- ${indent} key={option.value}
18606
- ${indent} value={\`\${option.label} \${option.value}\`}
18607
- ${indent} onSelect={() => {
18608
- ${defaultValueFromHandlerContent}${indent} formField.onChange(option.value)
18609
- ${indent} ${setSearchVar}('')
18610
- ${indent} ${setOpenVar}(false)
18611
- ${indent} }}
18612
- ${indent} >
18613
- ${indent} <Check className={cn("size-4", {
18614
- ${indent} "opacity-100": formField.value === option.value,
18615
- ${indent} "opacity-0": formField.value !== option.value
18616
- ${indent} })} />
18617
- ${indent} <span className="truncate">{option.label}</span>
18618
- ${indent} </CommandItem>
18619
- ${indent} ))}
18620
- ${indent} </CommandGroup>
18621
- ${indent} </CommandList>
18622
- ${indent} {canCreateOption ? (
18623
- ${indent} <>
18624
- ${indent} <CommandSeparator />
18625
- ${indent} <div className="p-1">
18626
- ${indent} <Button
18627
- ${indent} type="button"
18628
- ${indent} variant="ghost"
18629
- ${indent} className="w-full justify-start"
18630
- ${indent} disabled={${pendingVar}}
18631
- ${indent} aria-busy={${pendingVar}}
18632
- ${indent} onClick={() => ${createHandler}(createLabel)}
18633
- ${indent} >
18634
- ${indent} <Plus className="size-4" />
18635
- ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18636
- ${indent} </Button>
18637
- ${indent} </div>
18638
- ${indent} </>
18639
- ${indent} ) : null}
18640
- ${indent} </Command>
18641
- ${indent} </PopoverContent>
18642
- ${indent} </Popover>
18526
+ ${indent} <Combobox
18527
+ ${indent} items={${optionsVar}}
18528
+ ${indent} value={selectedOption}
18529
+ ${indent} open={${openVar}}
18530
+ ${indent} onOpenChange={${setOpenVar}}
18531
+ ${indent} inputValue={${searchVar}}
18532
+ ${indent} onInputValueChange={${setSearchVar}}
18533
+ ${indent} onValueChange={(option) => {
18534
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(option?.value ?? '')
18535
+ ${indent} ${setSearchVar}('')
18536
+ ${indent} }}
18537
+ ${indent} >
18538
+ ${indent} <FormControl>
18539
+ ${indent} <ComboboxTrigger
18540
+ ${indent} render={<Button type="button" variant="outline" disabled={isPending} />}
18541
+ ${indent} className={cn("w-full justify-between", {
18542
+ ${indent} "text-muted-foreground": !selectedOption
18543
+ ${indent} })}
18544
+ ${indent} >
18545
+ ${indent} <span className="truncate">{selectedOption?.label ?? ${stringify}}</span>
18546
+ ${indent} </ComboboxTrigger>
18547
+ ${indent} </FormControl>
18548
+ ${indent} <ComboboxContent align="start">
18549
+ ${indent} <ComboboxInput placeholder="Search ${lowerLabel}..." showTrigger={false} />
18550
+ ${indent} <ComboboxEmpty>No ${lowerLabel} found.</ComboboxEmpty>
18551
+ ${indent} <ComboboxList>
18552
+ ${indent} {(option) => (
18553
+ ${indent} <ComboboxItem key={option.value} value={option}>
18554
+ ${indent} <span className="truncate">{option.label}</span>
18555
+ ${indent} </ComboboxItem>
18556
+ ${indent} )}
18557
+ ${indent} </ComboboxList>
18558
+ ${indent} {canCreateOption ? (
18559
+ ${indent} <>
18560
+ ${indent} <ComboboxSeparator />
18561
+ ${indent} <div className="p-1">
18562
+ ${indent} <Button
18563
+ ${indent} type="button"
18564
+ ${indent} variant="ghost"
18565
+ ${indent} className="w-full justify-start"
18566
+ ${indent} disabled={${pendingVar}}
18567
+ ${indent} aria-busy={${pendingVar}}
18568
+ ${indent} onClick={() => ${createHandler}(createLabel)}
18569
+ ${indent} >
18570
+ ${indent} <Plus className="size-4" />
18571
+ ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18572
+ ${indent} </Button>
18573
+ ${indent} </div>
18574
+ ${indent} </>
18575
+ ${indent} ) : null}
18576
+ ${indent} </ComboboxContent>
18577
+ ${indent} </Combobox>
18643
18578
  ${indent} <FormMessage />
18644
18579
  ${indent} </FormItem>
18645
18580
  ${indent} )
@@ -18676,7 +18611,7 @@ function renderCreatableSelectField(field, indent, label, hintJSX, context) {
18676
18611
  stringify: JSON.stringify(placeholder),
18677
18612
  lowerLabel,
18678
18613
  setSearchVar,
18679
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option.value)
18614
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18680
18615
  ` : "",
18681
18616
  pendingVar,
18682
18617
  createHandler
@@ -18691,17 +18626,14 @@ function renderMultiSelectFieldStaticOptionsTemplate({
18691
18626
  return `const staticOptions = ${staticOptions}
18692
18627
  ${indent} const options = staticOptions`;
18693
18628
  }
18694
- function renderMultiSelectFieldContentTemplate({
18629
+ function renderMultiSelectFieldSearchBindingTemplate({
18695
18630
  indent,
18696
- lowerLabel,
18697
18631
  searchVar,
18698
18632
  setSearchVar
18699
18633
  }) {
18700
- return `<CommandInput
18701
- ${indent} placeholder="Search ${lowerLabel}..."
18702
- ${indent} value={${searchVar}}
18703
- ${indent} onValueChange={${setSearchVar}}
18704
- ${indent} />`;
18634
+ return `
18635
+ ${indent} inputValue={${searchVar}}
18636
+ ${indent} onInputValueChange={${setSearchVar}}`;
18705
18637
  }
18706
18638
  function renderMultiSelectFieldCreateLabelTemplate({
18707
18639
  indent,
@@ -18724,29 +18656,28 @@ function renderMultiSelectFieldActionButtonsTemplate({
18724
18656
  createHandler
18725
18657
  }) {
18726
18658
  return `
18727
- ${indent} {canCreateOption ? (
18728
- ${indent} <>
18729
- ${indent} <CommandSeparator />
18730
- ${indent} <div className="p-1">
18731
- ${indent} <Button
18732
- ${indent} type="button"
18733
- ${indent} variant="ghost"
18734
- ${indent} className="w-full justify-start"
18735
- ${indent} disabled={${pendingVar}}
18736
- ${indent} aria-busy={${pendingVar}}
18737
- ${indent} onClick={() => ${createHandler}(createLabel)}
18738
- ${indent} >
18739
- ${indent} <Plus className="size-4" />
18740
- ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18741
- ${indent} </Button>
18742
- ${indent} </div>
18743
- ${indent} </>
18744
- ${indent} ) : null}`;
18659
+ ${indent} {canCreateOption ? (
18660
+ ${indent} <>
18661
+ ${indent} <ComboboxSeparator />
18662
+ ${indent} <div className="p-1">
18663
+ ${indent} <Button
18664
+ ${indent} type="button"
18665
+ ${indent} variant="ghost"
18666
+ ${indent} className="w-full justify-start"
18667
+ ${indent} disabled={${pendingVar}}
18668
+ ${indent} aria-busy={${pendingVar}}
18669
+ ${indent} onClick={() => ${createHandler}(createLabel)}
18670
+ ${indent} >
18671
+ ${indent} <Plus className="size-4" />
18672
+ ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18673
+ ${indent} </Button>
18674
+ ${indent} </div>
18675
+ ${indent} </>
18676
+ ${indent} ) : null}`;
18745
18677
  }
18746
18678
  function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18747
18679
  indent,
18748
18680
  fieldName,
18749
- optionsId,
18750
18681
  optionsDeclaration,
18751
18682
  createState,
18752
18683
  previewLimit,
@@ -18755,7 +18686,7 @@ function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18755
18686
  openVar,
18756
18687
  setOpenVar,
18757
18688
  stringify,
18758
- searchInput,
18689
+ searchBinding,
18759
18690
  lowerLabel,
18760
18691
  defaultValueFromHandlerContent,
18761
18692
  clearSearch,
@@ -18780,89 +18711,69 @@ ${indent} : []
18780
18711
  ${indent} return (
18781
18712
  ${indent} <FormItem${formItemProps2}>
18782
18713
  ${indent} ${labelWithDescription2}
18783
- ${indent} <Popover open={${openVar}} onOpenChange={${setOpenVar}}>
18784
- ${indent} <PopoverTrigger
18785
- ${indent} render={
18786
- ${indent} <FormControl>
18787
- ${indent} <Button
18788
- ${indent} type="button"
18789
- ${indent} variant="outline"
18790
- ${indent} role="combobox"
18791
- ${indent} aria-expanded={${openVar}}
18792
- ${indent} aria-controls="${optionsId}"
18793
- ${indent} className={cn("w-full justify-between gap-2", {
18794
- ${indent} "text-muted-foreground": selectedOptions.length === 0
18795
- ${indent} })}
18796
- ${indent} disabled={isPending}
18797
- ${indent} >
18798
- ${indent} <span className="flex min-w-0 flex-1 items-center gap-2 text-left">
18799
- ${indent} {selectedOptions.length > 0 ? (
18800
- ${indent} <>
18801
- ${indent} <span className="truncate">
18802
- ${indent} {visibleSelectedOptions.map((option) => option.label).join(', ')}
18803
- ${indent} </span>
18804
- ${indent} {hiddenSelectedOptions.length > 0 ? (
18805
- ${indent} <Tooltip>
18806
- ${indent} <TooltipTrigger
18807
- ${indent} render={<Badge variant="outline" className="h-5 shrink-0 tabular-nums" />}
18808
- ${indent} >
18809
- ${indent} {'+'}
18810
- ${indent} {hiddenSelectedOptions.length}{' '}
18811
- ${indent} {hiddenSelectedOptions.length === 1 ? 'other' : 'others'}
18812
- ${indent} </TooltipTrigger>
18813
- ${indent} <TooltipContent align="center" side="bottom" className="max-w-60 w-full">
18814
- ${indent} <div className="space-y-1">
18815
- ${indent} {hiddenSelectedOptions.map((option) => (
18816
- ${indent} <div key={option.value} className="truncate">
18817
- ${indent} {option.label}
18818
- ${indent} </div>
18819
- ${indent} ))}
18820
- ${indent} </div>
18821
- ${indent} </TooltipContent>
18822
- ${indent} </Tooltip>
18823
- ${indent} ) : null}
18824
- ${indent} </>
18825
- ${indent} ) : (
18826
- ${indent} <span className="truncate">{${stringify}}</span>
18827
- ${indent} )}
18828
- ${indent} </span>
18829
- ${indent} <ChevronsUpDown className="size-4 shrink-0 opacity-50" />
18830
- ${indent} </Button>
18831
- ${indent} </FormControl>
18832
- ${indent} }
18833
- ${indent} />
18834
- ${indent} <PopoverContent id="${optionsId}" className="w-(--anchor-width) p-0" align="start">
18835
- ${indent} <Command>
18836
- ${indent} ${searchInput}
18837
- ${indent} <CommandList>
18838
- ${indent} <CommandEmpty>No ${lowerLabel} found.</CommandEmpty>
18839
- ${indent} <CommandGroup>
18840
- ${indent} {options.map((option) => {
18841
- ${indent} const isSelected = selectedValues.includes(option.value)
18842
- ${indent} return (
18843
- ${indent} <CommandItem
18844
- ${indent} key={option.value}
18845
- ${indent} value={\`\${option.label} \${option.value}\`}
18846
- ${indent} onSelect={() => {
18847
- ${indent} const nextValues = isSelected
18848
- ${indent} ? selectedValues.filter((value: string) => value !== option.value)
18849
- ${indent} : [...selectedValues, option.value]
18850
- ${defaultValueFromHandlerContent}${indent} formField.onChange(nextValues)${clearSearch}
18851
- ${indent} }}
18852
- ${indent} >
18853
- ${indent} <Check className={cn("size-4", {
18854
- ${indent} "opacity-100": isSelected,
18855
- ${indent} "opacity-0": !isSelected
18856
- ${indent} })} />
18857
- ${indent} <span className="truncate">{option.label}</span>
18858
- ${indent} </CommandItem>
18859
- ${indent} )
18860
- ${indent} })}
18861
- ${indent} </CommandGroup>
18862
- ${indent} </CommandList>${createAction}
18863
- ${indent} </Command>
18864
- ${indent} </PopoverContent>
18865
- ${indent} </Popover>
18714
+ ${indent} <Combobox
18715
+ ${indent} multiple
18716
+ ${indent} items={options}
18717
+ ${indent} value={selectedOptions}
18718
+ ${indent} open={${openVar}}
18719
+ ${indent} onOpenChange={${setOpenVar}}${searchBinding}
18720
+ ${indent} onValueChange={(nextOptions) => {
18721
+ ${indent} const nextValues = nextOptions.map((option) => option.value)
18722
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(nextValues)${clearSearch}
18723
+ ${indent} }}
18724
+ ${indent} >
18725
+ ${indent} <FormControl>
18726
+ ${indent} <ComboboxTrigger
18727
+ ${indent} render={<Button type="button" variant="outline" disabled={isPending} />}
18728
+ ${indent} className={cn("w-full justify-between gap-2", {
18729
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
18730
+ ${indent} })}
18731
+ ${indent} >
18732
+ ${indent} <span className="flex min-w-0 flex-1 items-center gap-2 text-left">
18733
+ ${indent} {selectedOptions.length > 0 ? (
18734
+ ${indent} <>
18735
+ ${indent} <span className="truncate">
18736
+ ${indent} {visibleSelectedOptions.map((option) => option.label).join(', ')}
18737
+ ${indent} </span>
18738
+ ${indent} {hiddenSelectedOptions.length > 0 ? (
18739
+ ${indent} <Tooltip>
18740
+ ${indent} <TooltipTrigger
18741
+ ${indent} render={<Badge variant="outline" className="h-5 shrink-0 tabular-nums" />}
18742
+ ${indent} >
18743
+ ${indent} {'+'}
18744
+ ${indent} {hiddenSelectedOptions.length}{' '}
18745
+ ${indent} {hiddenSelectedOptions.length === 1 ? 'other' : 'others'}
18746
+ ${indent} </TooltipTrigger>
18747
+ ${indent} <TooltipContent align="center" side="bottom" className="max-w-60 w-full">
18748
+ ${indent} <div className="space-y-1">
18749
+ ${indent} {hiddenSelectedOptions.map((option) => (
18750
+ ${indent} <div key={option.value} className="truncate">
18751
+ ${indent} {option.label}
18752
+ ${indent} </div>
18753
+ ${indent} ))}
18754
+ ${indent} </div>
18755
+ ${indent} </TooltipContent>
18756
+ ${indent} </Tooltip>
18757
+ ${indent} ) : null}
18758
+ ${indent} </>
18759
+ ${indent} ) : (
18760
+ ${indent} <span className="truncate">{${stringify}}</span>
18761
+ ${indent} )}
18762
+ ${indent} </span>
18763
+ ${indent} </ComboboxTrigger>
18764
+ ${indent} </FormControl>
18765
+ ${indent} <ComboboxContent align="start">
18766
+ ${indent} <ComboboxInput placeholder="Search ${lowerLabel}..." showTrigger={false} />
18767
+ ${indent} <ComboboxEmpty>No ${lowerLabel} found.</ComboboxEmpty>
18768
+ ${indent} <ComboboxList>
18769
+ ${indent} {(option) => (
18770
+ ${indent} <ComboboxItem key={option.value} value={option}>
18771
+ ${indent} <span className="truncate">{option.label}</span>
18772
+ ${indent} </ComboboxItem>
18773
+ ${indent} )}
18774
+ ${indent} </ComboboxList>${createAction}
18775
+ ${indent} </ComboboxContent>
18776
+ ${indent} </Combobox>
18866
18777
  ${indent} <FormMessage />
18867
18778
  ${indent} </FormItem>
18868
18779
  ${indent} )
@@ -18873,8 +18784,8 @@ function renderMultiSelectFieldRenderer(request) {
18873
18784
  switch (request.kind) {
18874
18785
  case "renderMultiSelectFieldStaticOptionsTemplate":
18875
18786
  return renderMultiSelectFieldStaticOptionsTemplate(request.props);
18876
- case "renderMultiSelectFieldContentTemplate":
18877
- return renderMultiSelectFieldContentTemplate(request.props);
18787
+ case "renderMultiSelectFieldSearchBindingTemplate":
18788
+ return renderMultiSelectFieldSearchBindingTemplate(request.props);
18878
18789
  case "renderMultiSelectFieldCreateLabelTemplate":
18879
18790
  return renderMultiSelectFieldCreateLabelTemplate(request.props);
18880
18791
  case "renderMultiSelectFieldActionButtonsTemplate":
@@ -18901,7 +18812,6 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18901
18812
  const placeholder = field.placeholder || `Select ${label.toLowerCase()}`;
18902
18813
  const previewLimit = Math.max(1, Math.floor(field.previewLimit ?? 1));
18903
18814
  const lowerLabel = label.toLowerCase();
18904
- const optionsId = `${context.schemaName ? `${toKebabCase(singularize(context.schemaName))}-` : ""}${toKebabCase(field.name)}-options`;
18905
18815
  const optionsDeclaration = isCreatable ? `const options = ${optionsVar}` : renderMultiSelectFieldRenderer({
18906
18816
  kind: "renderMultiSelectFieldStaticOptionsTemplate",
18907
18817
  props: {
@@ -18909,15 +18819,14 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18909
18819
  indent
18910
18820
  }
18911
18821
  });
18912
- const searchInput = isCreatable ? renderMultiSelectFieldRenderer({
18913
- kind: "renderMultiSelectFieldContentTemplate",
18822
+ const searchBinding = isCreatable ? renderMultiSelectFieldRenderer({
18823
+ kind: "renderMultiSelectFieldSearchBindingTemplate",
18914
18824
  props: {
18915
18825
  indent,
18916
- lowerLabel,
18917
18826
  searchVar,
18918
18827
  setSearchVar
18919
18828
  }
18920
- }) : `<CommandInput placeholder="Search ${lowerLabel}..." />`;
18829
+ }) : "";
18921
18830
  const createState = isCreatable ? renderMultiSelectFieldRenderer({
18922
18831
  kind: "renderMultiSelectFieldCreateLabelTemplate",
18923
18832
  props: {
@@ -18934,13 +18843,12 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18934
18843
  }
18935
18844
  }) : "";
18936
18845
  const clearSearch = isCreatable ? `
18937
- ${indent} ${setSearchVar}('')` : "";
18846
+ ${indent} ${setSearchVar}('')` : "";
18938
18847
  return renderMultiSelectFieldRenderer({
18939
18848
  kind: "renderMultiSelectFieldActionButtonsSerializedValueTemplate",
18940
18849
  props: {
18941
18850
  indent,
18942
18851
  fieldName: field.name,
18943
- optionsId,
18944
18852
  optionsDeclaration,
18945
18853
  createState,
18946
18854
  previewLimit,
@@ -18953,9 +18861,9 @@ ${indent} ${setSearchVar}('')` : "";
18953
18861
  openVar,
18954
18862
  setOpenVar,
18955
18863
  stringify: JSON.stringify(placeholder),
18956
- searchInput,
18864
+ searchBinding,
18957
18865
  lowerLabel,
18958
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18866
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18959
18867
  ` : "",
18960
18868
  clearSearch,
18961
18869
  createAction
@@ -19409,7 +19317,7 @@ function buildEntityFormLayout({
19409
19317
  return renderEntityFormContentRenderer({
19410
19318
  kind: "renderFormContentClassNameTemplate",
19411
19319
  props: {
19412
- optionsScrollableClassName: options.scrollable ? 'className="relative h-fit max-h-full space-y-4 overflow-y-auto pb-4 lg:sticky lg:top-0"' : showMetadataWidget ? renderEntityFormContentRenderer({ kind: "renderFormLayoutDetailsTemplate" }) : 'className="lg:sticky lg:top-14 space-y-4 pb-4"',
19320
+ optionsScrollableClassName: options.scrollable ? 'className="relative h-fit max-h-full space-y-4 overflow-y-auto pb-4 sticky top-0"' : showMetadataWidget ? renderEntityFormContentRenderer({ kind: "renderFormLayoutDetailsTemplate" }) : 'className="sticky top-14 space-y-4 pb-4"',
19413
19321
  join: cards.join("\n")
19414
19322
  }
19415
19323
  });
@@ -19435,7 +19343,7 @@ function buildEntityFormLayout({
19435
19343
  return renderEntityFormContentRenderer({
19436
19344
  kind: "renderFormCardContentGridTemplate",
19437
19345
  props: {
19438
- tabSidebarEntriesGrid: tabSidebarEntries.length > 0 ? "lg:grid-cols-[1fr_360px] " : "",
19346
+ tabSidebarEntriesGrid: tabSidebarEntries.length > 0 ? "grid-cols-[1fr_360px]" : "grid-cols-1",
19439
19347
  tabMainFieldsJsx: tabMainFieldsJSX,
19440
19348
  sidebarColumn
19441
19349
  }
@@ -19491,7 +19399,7 @@ function buildEntityFormLayout({
19491
19399
  const sidebarVisibilityState = shouldGuardSidebarByTab ? `
19492
19400
  const hasVisibleSidebarFields = ${sidebarTabNames.map((tabName) => `activeTab === ${JSON.stringify(tabName)}`).join(" || ")}
19493
19401
  ` : "";
19494
- const formGridOpen = shouldGuardSidebarByTab ? renderEntityFormContentRenderer({ kind: "renderFormLayoutDetailsBranchTemplate" }) : ` <div className="grid grid-cols-1 ${hasSidebarFields ? "lg:grid-cols-[1fr_360px] " : ""}gap-4 items-start h-full">`;
19402
+ const formGridOpen = shouldGuardSidebarByTab ? renderEntityFormContentRenderer({ kind: "renderFormLayoutDetailsBranchTemplate" }) : ` <div className="grid ${hasSidebarFields ? "grid-cols-[1fr_360px]" : "grid-cols-1"} gap-4 items-start h-full">`;
19495
19403
  const sidebarCardJSX = !hasSidebarFields ? "" : shouldGuardSidebarByTab ? renderEntityFormContentRenderer({
19496
19404
  kind: "renderFormContentSidebarColumnTemplate",
19497
19405
  props: {
@@ -19766,7 +19674,6 @@ function generateForm(schema, pagesDir, options = {}) {
19766
19674
  }
19767
19675
  };
19768
19676
  addLucideIcons(...sectionHeadingIconNames, ...contentTabIconNames);
19769
- if (hasRelationship || hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
19770
19677
  if (hasCreatableSelect) addLucideIcons("Plus");
19771
19678
  if (hasNestedList) {
19772
19679
  addLucideIcons("Plus", "X");
@@ -23189,7 +23096,6 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23189
23096
  }
23190
23097
  };
23191
23098
  addLucideIcons(...collectTabIconNames(group2.fields));
23192
- if (hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
23193
23099
  if (hasCreatableSelect || hasNestedList) addLucideIcons("Plus");
23194
23100
  if (hasNestedList) addLucideIcons("X");
23195
23101
  const relationshipImports = Array.from(
@@ -31816,10 +31722,6 @@ function scaffoldComponents({ cwd, config }) {
31816
31722
  "hooks/content-editor/use-table-button.ts",
31817
31723
  readTemplate("hooks/content-editor/use-table-button.ts")
31818
31724
  );
31819
- write(
31820
- "hooks/content-editor/use-content-editor-mobile-toolbar.ts",
31821
- readTemplate("hooks/content-editor/use-content-editor-mobile-toolbar.ts")
31822
- );
31823
31725
  write(
31824
31726
  "hooks/content-editor/use-content-editor-slash-menu.ts",
31825
31727
  readTemplate("hooks/content-editor/use-content-editor-slash-menu.ts")
@@ -31829,10 +31731,6 @@ function scaffoldComponents({ cwd, config }) {
31829
31731
  "hooks/content-editor/use-heading-dropdown-menu.ts",
31830
31732
  readTemplate("hooks/content-editor/use-heading-dropdown-menu.ts")
31831
31733
  );
31832
- write(
31833
- "hooks/content-editor/use-is-breakpoint.ts",
31834
- readTemplate("hooks/content-editor/use-is-breakpoint.ts")
31835
- );
31836
31734
  write(
31837
31735
  "hooks/content-editor/use-link-popover.ts",
31838
31736
  readTemplate("hooks/content-editor/use-link-popover.ts")
@@ -31861,7 +31759,6 @@ function scaffoldComponents({ cwd, config }) {
31861
31759
  write("hooks/use-audit-log.ts", readTemplate("hooks/use-audit-log.ts"));
31862
31760
  write("hooks/use-users.ts", readTemplate("hooks/use-users.ts"));
31863
31761
  write("hooks/use-webhooks.ts", readTemplate("hooks/use-webhooks.ts"));
31864
- write("hooks/use-mobile.ts", readTemplate("hooks/use-mobile.ts"));
31865
31762
  write("hooks/use-failed-image-url.ts", readTemplate("hooks/use-failed-image-url.ts"));
31866
31763
  write("hooks/use-media.ts", readTemplate("hooks/use-media.ts"));
31867
31764
  write("hooks/use-entity-versions.ts", readTemplate("hooks/use-entity-versions.ts"));
@@ -36500,7 +36397,7 @@ var TEMPLATE_REGISTRY = {
36500
36397
  "role-gate": {
36501
36398
  relPath: "components/layouts/role-gate.tsx",
36502
36399
  content: () => readTemplate("components/layouts/role-gate.tsx"),
36503
- dependencies: ["auth-roles-utils", "auth-session"]
36400
+ dependencies: ["auth-session", "auth-types"]
36504
36401
  },
36505
36402
  "page-header": {
36506
36403
  relPath: "components/shared/page-header.tsx",
@@ -36766,7 +36663,6 @@ var TEMPLATE_REGISTRY = {
36766
36663
  "content-editor-editor-view-utils",
36767
36664
  "content-editor-table-bubble-utils",
36768
36665
  "use-content-editor-slash-menu",
36769
- "use-mobile",
36770
36666
  "tiptap",
36771
36667
  "tiptap-utils",
36772
36668
  "content-editor/media-gallery-block",
@@ -36776,11 +36672,7 @@ var TEMPLATE_REGISTRY = {
36776
36672
  "use-content-editor-media-insertion": {
36777
36673
  relPath: "hooks/content-editor/use-content-editor-media-insertion.ts",
36778
36674
  content: () => readTemplate("hooks/content-editor/use-content-editor-media-insertion.ts"),
36779
- dependencies: [
36780
- "content-editor/use-is-breakpoint",
36781
- "content-editor/use-tiptap-editor",
36782
- "tiptap-utils"
36783
- ]
36675
+ dependencies: ["content-editor/use-tiptap-editor", "tiptap-utils"]
36784
36676
  },
36785
36677
  "use-blockquote": {
36786
36678
  relPath: "hooks/content-editor/use-blockquote.ts",
@@ -36795,11 +36687,7 @@ var TEMPLATE_REGISTRY = {
36795
36687
  "use-color-highlight": {
36796
36688
  relPath: "hooks/content-editor/use-color-highlight.ts",
36797
36689
  content: () => readTemplate("hooks/content-editor/use-color-highlight.ts"),
36798
- dependencies: [
36799
- "content-editor/use-is-breakpoint",
36800
- "content-editor/use-tiptap-editor",
36801
- "tiptap-utils"
36802
- ]
36690
+ dependencies: ["content-editor/use-tiptap-editor", "tiptap-utils"]
36803
36691
  },
36804
36692
  "use-heading": {
36805
36693
  relPath: "hooks/content-editor/use-heading.ts",
@@ -36846,20 +36734,11 @@ var TEMPLATE_REGISTRY = {
36846
36734
  content: () => readTemplate("hooks/content-editor/use-table-button.ts"),
36847
36735
  dependencies: ["content-editor-table-input-utils", "tiptap-utils"]
36848
36736
  },
36849
- "use-content-editor-mobile-toolbar": {
36850
- relPath: "hooks/content-editor/use-content-editor-mobile-toolbar.ts",
36851
- content: () => readTemplate("hooks/content-editor/use-content-editor-mobile-toolbar.ts"),
36852
- dependencies: ["use-mobile"]
36853
- },
36854
36737
  "use-content-editor-slash-menu": {
36855
36738
  relPath: "hooks/content-editor/use-content-editor-slash-menu.ts",
36856
36739
  content: () => readTemplate("hooks/content-editor/use-content-editor-slash-menu.ts"),
36857
36740
  dependencies: ["content-editor-slash-commands-utils", "tiptap-utils"]
36858
36741
  },
36859
- "content-editor/use-is-breakpoint": {
36860
- relPath: "hooks/content-editor/use-is-breakpoint.ts",
36861
- content: () => readTemplate("hooks/content-editor/use-is-breakpoint.ts")
36862
- },
36863
36742
  "content-editor/use-menu-navigation": {
36864
36743
  relPath: "hooks/content-editor/use-menu-navigation.ts",
36865
36744
  content: () => readTemplate("hooks/content-editor/use-menu-navigation.ts")
@@ -36891,10 +36770,6 @@ var TEMPLATE_REGISTRY = {
36891
36770
  content: () => readTemplate("hooks/use-webhooks.ts"),
36892
36771
  dependencies: ["webhooks-action", "form-settings-action"]
36893
36772
  },
36894
- "use-mobile": {
36895
- relPath: "hooks/use-mobile.ts",
36896
- content: () => readTemplate("hooks/use-mobile.ts")
36897
- },
36898
36773
  "use-failed-image-url": {
36899
36774
  relPath: "hooks/use-failed-image-url.ts",
36900
36775
  content: () => readTemplate("hooks/use-failed-image-url.ts")
@@ -38117,7 +37992,7 @@ var TEMPLATE_REGISTRY = {
38117
37992
  relPath: "app/(admin)/admin/(account)/profile/profile-page-content.tsx",
38118
37993
  content: () => readTemplate("pages/profile/profile-page-content.tsx"),
38119
37994
  base: "cwd",
38120
- dependencies: ["auth-roles-utils", "auth-session", "page-header", "profile-form"]
37995
+ dependencies: ["auth-session", "auth-types", "page-header", "profile-form"]
38121
37996
  },
38122
37997
  "profile-page-skeleton": {
38123
37998
  relPath: "app/(admin)/admin/(account)/profile/profile-page-skeleton.tsx",
@@ -38246,8 +38121,7 @@ var TEMPLATE_REGISTRY = {
38246
38121
  content: () => readTemplate("pages/settings/forms/forms-settings-page.tsx"),
38247
38122
  base: "cwd",
38248
38123
  dependencies: [
38249
- "auth-roles-utils",
38250
- "auth-session",
38124
+ "auth-types",
38251
38125
  "role-gate",
38252
38126
  "forms-settings-page-skeleton",
38253
38127
  "forms-settings-page-content"
@@ -38299,13 +38173,7 @@ var TEMPLATE_REGISTRY = {
38299
38173
  relPath: "app/(admin)/admin/(authenticated)/settings/webhooks/page.tsx",
38300
38174
  content: () => readTemplate("pages/settings/webhooks/webhooks-page.tsx"),
38301
38175
  base: "cwd",
38302
- dependencies: [
38303
- "auth-roles-utils",
38304
- "auth-session",
38305
- "role-gate",
38306
- "webhooks-page-skeleton",
38307
- "webhooks-page-content"
38308
- ]
38176
+ dependencies: ["auth-types", "role-gate", "webhooks-page-skeleton", "webhooks-page-content"]
38309
38177
  },
38310
38178
  "webhooks-page-skeleton": {
38311
38179
  relPath: "app/(admin)/admin/(authenticated)/settings/webhooks/webhooks-page-skeleton.tsx",
@@ -38366,8 +38234,7 @@ var TEMPLATE_REGISTRY = {
38366
38234
  content: () => readTemplate("pages/settings/webhooks/webhooks-logs-page.tsx"),
38367
38235
  base: "cwd",
38368
38236
  dependencies: [
38369
- "auth-roles-utils",
38370
- "auth-session",
38237
+ "auth-types",
38371
38238
  "role-gate",
38372
38239
  "webhooks-logs-page-content",
38373
38240
  "webhooks-page-skeleton"
@@ -39055,13 +38922,7 @@ var TEMPLATE_REGISTRY = {
39055
38922
  relPath: "app/(admin)/admin/(authenticated)/settings/audit-log/page.tsx",
39056
38923
  content: () => readTemplate("pages/settings/audit-log/audit-log-page.tsx"),
39057
38924
  base: "cwd",
39058
- dependencies: [
39059
- "auth-roles-utils",
39060
- "auth-session",
39061
- "role-gate",
39062
- "audit-log-page-content",
39063
- "audit-log-page-skeleton"
39064
- ]
38925
+ dependencies: ["auth-types", "role-gate", "audit-log-page-content", "audit-log-page-skeleton"]
39065
38926
  },
39066
38927
  "audit-log-page-skeleton": {
39067
38928
  relPath: "app/(admin)/admin/(authenticated)/settings/audit-log/audit-log-page-skeleton.tsx",