betterstart-cli 0.0.111 → 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.
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",
@@ -15574,17 +15573,10 @@ function renderBuildUiImportsImportsDetailsTemplate() {
15574
15573
  SelectTrigger
15575
15574
  } from '@admin/components/ui/select'`;
15576
15575
  }
15577
- function renderBuildUiImportsImportsDetailsBranchTemplate({ join }) {
15576
+ function renderComboboxImports({ join }) {
15578
15577
  return `import {
15579
15578
  ${join}
15580
- } from '@admin/components/ui/command'`;
15581
- }
15582
- function renderBuildUiImportsImportsDetailsBranchBodyTemplate() {
15583
- return `import {
15584
- Popover,
15585
- PopoverContent,
15586
- PopoverTrigger
15587
- } from '@admin/components/ui/popover'`;
15579
+ } from '@admin/components/ui/combobox'`;
15588
15580
  }
15589
15581
  function renderTooltipImports() {
15590
15582
  return `import {
@@ -15615,10 +15607,8 @@ function renderBuildUiImportsRenderer(request) {
15615
15607
  return renderBuildUiImportsImportsTemplate(request.props);
15616
15608
  case "renderBuildUiImportsImportsDetailsTemplate":
15617
15609
  return renderBuildUiImportsImportsDetailsTemplate();
15618
- case "renderBuildUiImportsImportsDetailsBranchTemplate":
15619
- return renderBuildUiImportsImportsDetailsBranchTemplate(request.props);
15620
- case "renderBuildUiImportsImportsDetailsBranchBodyTemplate":
15621
- return renderBuildUiImportsImportsDetailsBranchBodyTemplate();
15610
+ case "renderComboboxImports":
15611
+ return renderComboboxImports(request.props);
15622
15612
  case "renderTooltipImports":
15623
15613
  return renderTooltipImports();
15624
15614
  case "renderTabsImports":
@@ -15668,26 +15658,24 @@ function buildUiImports(ctx) {
15668
15658
  );
15669
15659
  }
15670
15660
  if (ctx.hasRelationship || ctx.hasSelectCombobox) {
15671
- const commandImports = [
15672
- "Command",
15673
- "CommandEmpty",
15674
- "CommandGroup",
15675
- "CommandInput",
15676
- "CommandItem",
15677
- "CommandList",
15678
- ctx.hasCreatableSelect ? "CommandSeparator" : ""
15661
+ const comboboxImports = [
15662
+ "Combobox",
15663
+ "ComboboxContent",
15664
+ "ComboboxEmpty",
15665
+ "ComboboxInput",
15666
+ "ComboboxItem",
15667
+ "ComboboxList",
15668
+ ctx.hasCreatableSelect ? "ComboboxSeparator" : "",
15669
+ "ComboboxTrigger"
15679
15670
  ].filter(Boolean);
15680
15671
  uiImports.push(
15681
15672
  renderBuildUiImportsRenderer({
15682
- kind: "renderBuildUiImportsImportsDetailsBranchTemplate",
15673
+ kind: "renderComboboxImports",
15683
15674
  props: {
15684
- join: commandImports.join(",\n ")
15675
+ join: comboboxImports.join(",\n ")
15685
15676
  }
15686
15677
  })
15687
15678
  );
15688
- uiImports.push(
15689
- renderBuildUiImportsRenderer({ kind: "renderBuildUiImportsImportsDetailsBranchBodyTemplate" })
15690
- );
15691
15679
  }
15692
15680
  if (ctx.hasMultiSelect) {
15693
15681
  uiImports.push("import { Badge } from '@admin/components/ui/badge'");
@@ -18149,69 +18137,69 @@ function renderMultiRelationshipFieldActionButtonsTemplate({
18149
18137
  return `${indent}<FormField
18150
18138
  ${indent} control={form.control}
18151
18139
  ${indent} name="${fieldName}"
18152
- ${indent} render={({ field: formField }) => (
18153
- ${indent} <FormItem${formItemProps2}>
18154
- ${indent} ${labelWithDescription2}
18155
- ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase2}Open}>
18156
- ${indent} <PopoverTrigger
18157
- ${indent} render={
18158
- ${indent} <FormControl>
18159
- ${indent} <Button
18160
- ${indent} variant="outline"
18161
- ${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} />}
18162
18171
  ${indent} className={cn("w-full justify-between", {
18163
- ${indent} "text-muted-foreground": !formField.value || formField.value.length === 0
18172
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
18164
18173
  ${indent} })}
18165
- ${indent} disabled={isPending}
18166
- ${indent} >
18167
- ${indent} {(formField.value?.length ?? 0) > 0
18168
- ${indent} ? \`\${formField.value?.length ?? 0} selected\`
18169
- ${indent} : "Select ${toLowerCase}"}
18170
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18171
- ${indent} </Button>
18172
- ${indent} </FormControl>
18173
- ${indent} }
18174
- ${indent} />
18175
- ${indent} <PopoverContent className="w-full p-0" align="start">
18176
- ${indent} <Command>
18177
- ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
18178
- ${indent} <CommandList>
18179
- ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
18180
- ${indent} <CommandGroup>
18181
- ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
18182
- ${indent} const displayName = ${displayField}
18183
- ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18184
- ${indent} const isSelected = formField.value?.includes(item.id) || false
18185
- ${indent} return (
18186
- ${indent} <CommandItem
18187
- ${indent} key={item.id}
18188
- ${indent} value={displayName}
18189
- ${indent} onSelect={() => {
18190
- ${indent} const current = formField.value || []
18191
- ${defaultValueFromHandlerContent}
18192
- ${indent} }}
18193
- ${indent} >
18194
- ${indent} <Check className={cn("size-4", {
18195
- ${indent} "opacity-100": isSelected,
18196
- ${indent} "opacity-0": !isSelected
18197
- ${indent} })} />
18198
- ${indent} <span className="flex min-w-0 flex-col text-left">
18199
- ${indent} <span className="truncate">{displayName}</span>
18200
- ${indent} {secondaryDisplayName ? (
18201
- ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
18202
- ${indent} ) : null}
18203
- ${indent} </span>
18204
- ${indent} </CommandItem>
18205
- ${indent} )
18206
- ${indent} })}
18207
- ${indent} </CommandGroup>
18208
- ${indent} </CommandList>
18209
- ${indent} </Command>
18210
- ${indent} </PopoverContent>
18211
- ${indent} </Popover>
18212
- ${indent} <FormMessage />
18213
- ${indent} </FormItem>
18214
- ${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} }}
18215
18203
  ${indent}/>`;
18216
18204
  }
18217
18205
 
@@ -18229,13 +18217,8 @@ function renderMultiRelationshipField(field, indent, label, hintJSX, displayFiel
18229
18217
  dataArray,
18230
18218
  displayField,
18231
18219
  secondaryDisplayField,
18232
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} const nextValue = isSelected
18233
- ${indent} ? current.filter((id: string) => id !== item.id)
18234
- ${indent} : [...current, item.id]
18235
- ${indent} ${defaultValueFromHandler}(nextValue)
18236
- ${indent} formField.onChange(nextValue)` : `${indent} formField.onChange(isSelected
18237
- ${indent} ? current.filter((id: string) => id !== item.id)
18238
- ${indent} : [...current, item.id])`
18220
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValue)
18221
+ ${indent} formField.onChange(nextValue)` : `${indent} formField.onChange(nextValue)`
18239
18222
  });
18240
18223
  }
18241
18224
 
@@ -18256,71 +18239,64 @@ function renderSingleRelationshipFieldActionButtonsTemplate({
18256
18239
  return `${indent}<FormField
18257
18240
  ${indent} control={form.control}
18258
18241
  ${indent} name="${fieldName}"
18259
- ${indent} render={({ field: formField }) => (
18260
- ${indent} <FormItem${formItemProps2}>
18261
- ${indent} ${labelWithDescription2}
18262
- ${indent} <Popover open={${fieldName}Open} onOpenChange={set${toPascalCase2}Open}>
18263
- ${indent} <PopoverTrigger
18264
- ${indent} render={
18265
- ${indent} <FormControl>
18266
- ${indent} <Button
18267
- ${indent} variant="outline"
18268
- ${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} />}
18269
18270
  ${indent} className={cn("w-full justify-between", {
18270
18271
  ${indent} "text-muted-foreground": !formField.value
18271
18272
  ${indent} })}
18272
- ${indent} disabled={isPending}
18273
- ${indent} >
18274
- ${indent} {formField.value
18275
- ${indent} ? (() => {
18276
- ${indent} const item = ${dataArray}?.find((item) => item.id !== null && String(item.id) === formField.value)
18277
- ${indent} return item ? (${displayField}) : "Select ${toLowerCase}"
18278
- ${indent} })()
18279
- ${indent} : "Select ${toLowerCase}"}
18280
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18281
- ${indent} </Button>
18282
- ${indent} </FormControl>
18283
- ${indent} }
18284
- ${indent} />
18285
- ${indent} <PopoverContent className="w-full p-0" align="start">
18286
- ${indent} <Command>
18287
- ${indent} <CommandInput placeholder="Search ${toLowerCase}..." />
18288
- ${indent} <CommandList>
18289
- ${indent} <CommandEmpty>No ${relSingular} found.</CommandEmpty>
18290
- ${indent} <CommandGroup>
18291
- ${indent} {${dataArray}?.filter((item) => item.id !== null).map((item) => {
18292
- ${indent} const displayName = ${displayField}
18293
- ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18294
- ${indent} return (
18295
- ${indent} <CommandItem
18296
- ${indent} key={item.id}
18297
- ${indent} value={displayName}
18298
- ${indent} onSelect={() => {
18299
- ${defaultValueFromHandlerContent}${indent} formField.onChange(String(item.id))
18300
- ${indent} set${toPascalCase2}Open(false)
18301
- ${indent} }}
18302
- ${indent} >
18303
- ${indent} <Check className={cn("size-4", {
18304
- ${indent} "opacity-100": formField.value === String(item.id),
18305
- ${indent} "opacity-0": formField.value !== String(item.id)
18306
- ${indent} })} />
18307
- ${indent} <span className="flex min-w-0 flex-col text-left">
18308
- ${indent} <span className="truncate">{displayName}</span>
18309
- ${indent} {secondaryDisplayName ? (
18310
- ${indent} <span className="truncate text-xs text-muted-foreground">{secondaryDisplayName}</span>
18311
- ${indent} ) : null}
18312
- ${indent} </span>
18313
- ${indent} </CommandItem>
18314
- ${indent} )
18315
- ${indent} })}
18316
- ${indent} </CommandGroup>
18317
- ${indent} </CommandList>
18318
- ${indent} </Command>
18319
- ${indent} </PopoverContent>
18320
- ${indent} </Popover>
18321
- ${indent} <FormMessage />
18322
- ${indent} </FormItem>
18323
- ${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} }}
18324
18300
  ${indent}/>`;
18325
18301
  }
18326
18302
 
@@ -18338,7 +18314,7 @@ function renderSingleRelationshipField(field, indent, label, hintJSX, displayFie
18338
18314
  toLowerCase: label.toLowerCase(),
18339
18315
  relSingular,
18340
18316
  secondaryDisplayField,
18341
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(String(item.id))
18317
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18342
18318
  ` : ""
18343
18319
  });
18344
18320
  }
@@ -18534,7 +18510,7 @@ function renderCreatableSelectFieldActionButtonsTemplate({
18534
18510
  ${indent} control={form.control}
18535
18511
  ${indent} name="${fieldName}"
18536
18512
  ${indent} render={({ field: formField }) => {
18537
- ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value)
18513
+ ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value) ?? null
18538
18514
  ${indent} const createLabel = ${searchVar}.trim()
18539
18515
  ${indent} const canCreateOption =
18540
18516
  ${indent} createLabel.length > 0 &&
@@ -18547,76 +18523,58 @@ ${indent} )
18547
18523
  ${indent} return (
18548
18524
  ${indent} <FormItem${formItemProps2}>
18549
18525
  ${indent} ${labelWithDescription2}
18550
- ${indent} <Popover open={${openVar}} onOpenChange={${setOpenVar}}>
18551
- ${indent} <PopoverTrigger
18552
- ${indent} render={
18553
- ${indent} <FormControl>
18554
- ${indent} <Button
18555
- ${indent} type="button"
18556
- ${indent} variant="outline"
18557
- ${indent} role="combobox"
18558
- ${indent} aria-expanded={${openVar}}
18559
- ${indent} className={cn("w-full justify-between", {
18560
- ${indent} "text-muted-foreground": !selectedOption
18561
- ${indent} })}
18562
- ${indent} disabled={isPending}
18563
- ${indent} >
18564
- ${indent} <span className="truncate">{selectedOption?.label ?? ${stringify}}</span>
18565
- ${indent} <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
18566
- ${indent} </Button>
18567
- ${indent} </FormControl>
18568
- ${indent} }
18569
- ${indent} />
18570
- ${indent} <PopoverContent className="w-(--anchor-width) p-0" align="start">
18571
- ${indent} <Command>
18572
- ${indent} <CommandInput
18573
- ${indent} placeholder="Search ${lowerLabel}..."
18574
- ${indent} value={${searchVar}}
18575
- ${indent} onValueChange={${setSearchVar}}
18576
- ${indent} />
18577
- ${indent} <CommandList>
18578
- ${indent} <CommandEmpty>No ${lowerLabel} found.</CommandEmpty>
18579
- ${indent} <CommandGroup>
18580
- ${indent} {${optionsVar}.map((option) => (
18581
- ${indent} <CommandItem
18582
- ${indent} key={option.value}
18583
- ${indent} value={\`\${option.label} \${option.value}\`}
18584
- ${indent} onSelect={() => {
18585
- ${defaultValueFromHandlerContent}${indent} formField.onChange(option.value)
18586
- ${indent} ${setSearchVar}('')
18587
- ${indent} ${setOpenVar}(false)
18588
- ${indent} }}
18589
- ${indent} >
18590
- ${indent} <Check className={cn("size-4", {
18591
- ${indent} "opacity-100": formField.value === option.value,
18592
- ${indent} "opacity-0": formField.value !== option.value
18593
- ${indent} })} />
18594
- ${indent} <span className="truncate">{option.label}</span>
18595
- ${indent} </CommandItem>
18596
- ${indent} ))}
18597
- ${indent} </CommandGroup>
18598
- ${indent} </CommandList>
18599
- ${indent} {canCreateOption ? (
18600
- ${indent} <>
18601
- ${indent} <CommandSeparator />
18602
- ${indent} <div className="p-1">
18603
- ${indent} <Button
18604
- ${indent} type="button"
18605
- ${indent} variant="ghost"
18606
- ${indent} className="w-full justify-start"
18607
- ${indent} disabled={${pendingVar}}
18608
- ${indent} aria-busy={${pendingVar}}
18609
- ${indent} onClick={() => ${createHandler}(createLabel)}
18610
- ${indent} >
18611
- ${indent} <Plus className="size-4" />
18612
- ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18613
- ${indent} </Button>
18614
- ${indent} </div>
18615
- ${indent} </>
18616
- ${indent} ) : null}
18617
- ${indent} </Command>
18618
- ${indent} </PopoverContent>
18619
- ${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>
18620
18578
  ${indent} <FormMessage />
18621
18579
  ${indent} </FormItem>
18622
18580
  ${indent} )
@@ -18653,7 +18611,7 @@ function renderCreatableSelectField(field, indent, label, hintJSX, context) {
18653
18611
  stringify: JSON.stringify(placeholder),
18654
18612
  lowerLabel,
18655
18613
  setSearchVar,
18656
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option.value)
18614
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18657
18615
  ` : "",
18658
18616
  pendingVar,
18659
18617
  createHandler
@@ -18668,17 +18626,14 @@ function renderMultiSelectFieldStaticOptionsTemplate({
18668
18626
  return `const staticOptions = ${staticOptions}
18669
18627
  ${indent} const options = staticOptions`;
18670
18628
  }
18671
- function renderMultiSelectFieldContentTemplate({
18629
+ function renderMultiSelectFieldSearchBindingTemplate({
18672
18630
  indent,
18673
- lowerLabel,
18674
18631
  searchVar,
18675
18632
  setSearchVar
18676
18633
  }) {
18677
- return `<CommandInput
18678
- ${indent} placeholder="Search ${lowerLabel}..."
18679
- ${indent} value={${searchVar}}
18680
- ${indent} onValueChange={${setSearchVar}}
18681
- ${indent} />`;
18634
+ return `
18635
+ ${indent} inputValue={${searchVar}}
18636
+ ${indent} onInputValueChange={${setSearchVar}}`;
18682
18637
  }
18683
18638
  function renderMultiSelectFieldCreateLabelTemplate({
18684
18639
  indent,
@@ -18701,29 +18656,28 @@ function renderMultiSelectFieldActionButtonsTemplate({
18701
18656
  createHandler
18702
18657
  }) {
18703
18658
  return `
18704
- ${indent} {canCreateOption ? (
18705
- ${indent} <>
18706
- ${indent} <CommandSeparator />
18707
- ${indent} <div className="p-1">
18708
- ${indent} <Button
18709
- ${indent} type="button"
18710
- ${indent} variant="ghost"
18711
- ${indent} className="w-full justify-start"
18712
- ${indent} disabled={${pendingVar}}
18713
- ${indent} aria-busy={${pendingVar}}
18714
- ${indent} onClick={() => ${createHandler}(createLabel)}
18715
- ${indent} >
18716
- ${indent} <Plus className="size-4" />
18717
- ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18718
- ${indent} </Button>
18719
- ${indent} </div>
18720
- ${indent} </>
18721
- ${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}`;
18722
18677
  }
18723
18678
  function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18724
18679
  indent,
18725
18680
  fieldName,
18726
- optionsId,
18727
18681
  optionsDeclaration,
18728
18682
  createState,
18729
18683
  previewLimit,
@@ -18732,7 +18686,7 @@ function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18732
18686
  openVar,
18733
18687
  setOpenVar,
18734
18688
  stringify,
18735
- searchInput,
18689
+ searchBinding,
18736
18690
  lowerLabel,
18737
18691
  defaultValueFromHandlerContent,
18738
18692
  clearSearch,
@@ -18757,89 +18711,69 @@ ${indent} : []
18757
18711
  ${indent} return (
18758
18712
  ${indent} <FormItem${formItemProps2}>
18759
18713
  ${indent} ${labelWithDescription2}
18760
- ${indent} <Popover open={${openVar}} onOpenChange={${setOpenVar}}>
18761
- ${indent} <PopoverTrigger
18762
- ${indent} render={
18763
- ${indent} <FormControl>
18764
- ${indent} <Button
18765
- ${indent} type="button"
18766
- ${indent} variant="outline"
18767
- ${indent} role="combobox"
18768
- ${indent} aria-expanded={${openVar}}
18769
- ${indent} aria-controls="${optionsId}"
18770
- ${indent} className={cn("w-full justify-between gap-2", {
18771
- ${indent} "text-muted-foreground": selectedOptions.length === 0
18772
- ${indent} })}
18773
- ${indent} disabled={isPending}
18774
- ${indent} >
18775
- ${indent} <span className="flex min-w-0 flex-1 items-center gap-2 text-left">
18776
- ${indent} {selectedOptions.length > 0 ? (
18777
- ${indent} <>
18778
- ${indent} <span className="truncate">
18779
- ${indent} {visibleSelectedOptions.map((option) => option.label).join(', ')}
18780
- ${indent} </span>
18781
- ${indent} {hiddenSelectedOptions.length > 0 ? (
18782
- ${indent} <Tooltip>
18783
- ${indent} <TooltipTrigger
18784
- ${indent} render={<Badge variant="outline" className="h-5 shrink-0 tabular-nums" />}
18785
- ${indent} >
18786
- ${indent} {'+'}
18787
- ${indent} {hiddenSelectedOptions.length}{' '}
18788
- ${indent} {hiddenSelectedOptions.length === 1 ? 'other' : 'others'}
18789
- ${indent} </TooltipTrigger>
18790
- ${indent} <TooltipContent align="center" side="bottom" className="max-w-60 w-full">
18791
- ${indent} <div className="space-y-1">
18792
- ${indent} {hiddenSelectedOptions.map((option) => (
18793
- ${indent} <div key={option.value} className="truncate">
18794
- ${indent} {option.label}
18795
- ${indent} </div>
18796
- ${indent} ))}
18797
- ${indent} </div>
18798
- ${indent} </TooltipContent>
18799
- ${indent} </Tooltip>
18800
- ${indent} ) : null}
18801
- ${indent} </>
18802
- ${indent} ) : (
18803
- ${indent} <span className="truncate">{${stringify}}</span>
18804
- ${indent} )}
18805
- ${indent} </span>
18806
- ${indent} <ChevronsUpDown className="size-4 shrink-0 opacity-50" />
18807
- ${indent} </Button>
18808
- ${indent} </FormControl>
18809
- ${indent} }
18810
- ${indent} />
18811
- ${indent} <PopoverContent id="${optionsId}" className="w-(--anchor-width) p-0" align="start">
18812
- ${indent} <Command>
18813
- ${indent} ${searchInput}
18814
- ${indent} <CommandList>
18815
- ${indent} <CommandEmpty>No ${lowerLabel} found.</CommandEmpty>
18816
- ${indent} <CommandGroup>
18817
- ${indent} {options.map((option) => {
18818
- ${indent} const isSelected = selectedValues.includes(option.value)
18819
- ${indent} return (
18820
- ${indent} <CommandItem
18821
- ${indent} key={option.value}
18822
- ${indent} value={\`\${option.label} \${option.value}\`}
18823
- ${indent} onSelect={() => {
18824
- ${indent} const nextValues = isSelected
18825
- ${indent} ? selectedValues.filter((value: string) => value !== option.value)
18826
- ${indent} : [...selectedValues, option.value]
18827
- ${defaultValueFromHandlerContent}${indent} formField.onChange(nextValues)${clearSearch}
18828
- ${indent} }}
18829
- ${indent} >
18830
- ${indent} <Check className={cn("size-4", {
18831
- ${indent} "opacity-100": isSelected,
18832
- ${indent} "opacity-0": !isSelected
18833
- ${indent} })} />
18834
- ${indent} <span className="truncate">{option.label}</span>
18835
- ${indent} </CommandItem>
18836
- ${indent} )
18837
- ${indent} })}
18838
- ${indent} </CommandGroup>
18839
- ${indent} </CommandList>${createAction}
18840
- ${indent} </Command>
18841
- ${indent} </PopoverContent>
18842
- ${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>
18843
18777
  ${indent} <FormMessage />
18844
18778
  ${indent} </FormItem>
18845
18779
  ${indent} )
@@ -18850,8 +18784,8 @@ function renderMultiSelectFieldRenderer(request) {
18850
18784
  switch (request.kind) {
18851
18785
  case "renderMultiSelectFieldStaticOptionsTemplate":
18852
18786
  return renderMultiSelectFieldStaticOptionsTemplate(request.props);
18853
- case "renderMultiSelectFieldContentTemplate":
18854
- return renderMultiSelectFieldContentTemplate(request.props);
18787
+ case "renderMultiSelectFieldSearchBindingTemplate":
18788
+ return renderMultiSelectFieldSearchBindingTemplate(request.props);
18855
18789
  case "renderMultiSelectFieldCreateLabelTemplate":
18856
18790
  return renderMultiSelectFieldCreateLabelTemplate(request.props);
18857
18791
  case "renderMultiSelectFieldActionButtonsTemplate":
@@ -18878,7 +18812,6 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18878
18812
  const placeholder = field.placeholder || `Select ${label.toLowerCase()}`;
18879
18813
  const previewLimit = Math.max(1, Math.floor(field.previewLimit ?? 1));
18880
18814
  const lowerLabel = label.toLowerCase();
18881
- const optionsId = `${context.schemaName ? `${toKebabCase(singularize(context.schemaName))}-` : ""}${toKebabCase(field.name)}-options`;
18882
18815
  const optionsDeclaration = isCreatable ? `const options = ${optionsVar}` : renderMultiSelectFieldRenderer({
18883
18816
  kind: "renderMultiSelectFieldStaticOptionsTemplate",
18884
18817
  props: {
@@ -18886,15 +18819,14 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18886
18819
  indent
18887
18820
  }
18888
18821
  });
18889
- const searchInput = isCreatable ? renderMultiSelectFieldRenderer({
18890
- kind: "renderMultiSelectFieldContentTemplate",
18822
+ const searchBinding = isCreatable ? renderMultiSelectFieldRenderer({
18823
+ kind: "renderMultiSelectFieldSearchBindingTemplate",
18891
18824
  props: {
18892
18825
  indent,
18893
- lowerLabel,
18894
18826
  searchVar,
18895
18827
  setSearchVar
18896
18828
  }
18897
- }) : `<CommandInput placeholder="Search ${lowerLabel}..." />`;
18829
+ }) : "";
18898
18830
  const createState = isCreatable ? renderMultiSelectFieldRenderer({
18899
18831
  kind: "renderMultiSelectFieldCreateLabelTemplate",
18900
18832
  props: {
@@ -18911,13 +18843,12 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18911
18843
  }
18912
18844
  }) : "";
18913
18845
  const clearSearch = isCreatable ? `
18914
- ${indent} ${setSearchVar}('')` : "";
18846
+ ${indent} ${setSearchVar}('')` : "";
18915
18847
  return renderMultiSelectFieldRenderer({
18916
18848
  kind: "renderMultiSelectFieldActionButtonsSerializedValueTemplate",
18917
18849
  props: {
18918
18850
  indent,
18919
18851
  fieldName: field.name,
18920
- optionsId,
18921
18852
  optionsDeclaration,
18922
18853
  createState,
18923
18854
  previewLimit,
@@ -18930,9 +18861,9 @@ ${indent} ${setSearchVar}('')` : "";
18930
18861
  openVar,
18931
18862
  setOpenVar,
18932
18863
  stringify: JSON.stringify(placeholder),
18933
- searchInput,
18864
+ searchBinding,
18934
18865
  lowerLabel,
18935
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18866
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18936
18867
  ` : "",
18937
18868
  clearSearch,
18938
18869
  createAction
@@ -19743,7 +19674,6 @@ function generateForm(schema, pagesDir, options = {}) {
19743
19674
  }
19744
19675
  };
19745
19676
  addLucideIcons(...sectionHeadingIconNames, ...contentTabIconNames);
19746
- if (hasRelationship || hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
19747
19677
  if (hasCreatableSelect) addLucideIcons("Plus");
19748
19678
  if (hasNestedList) {
19749
19679
  addLucideIcons("Plus", "X");
@@ -23166,7 +23096,6 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23166
23096
  }
23167
23097
  };
23168
23098
  addLucideIcons(...collectTabIconNames(group2.fields));
23169
- if (hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
23170
23099
  if (hasCreatableSelect || hasNestedList) addLucideIcons("Plus");
23171
23100
  if (hasNestedList) addLucideIcons("X");
23172
23101
  const relationshipImports = Array.from(