betterstart-cli 0.0.111 → 0.0.113

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":
@@ -15636,7 +15626,14 @@ function buildUiImports(ctx) {
15636
15626
  if (ctx.hasSectionCardHeading) cardImports.push("CardHeader", "CardTitle");
15637
15627
  const formImports = [
15638
15628
  ctx.hasFormRoot === false ? "" : "Form",
15639
- ...ctx.hasFormControls === false ? [] : ["FormControl", "FormDescription", "FormField", "FormItem", "FormLabel", "FormMessage"]
15629
+ ...ctx.hasFormControls === false ? [] : [
15630
+ "FormControl",
15631
+ "FormDescription",
15632
+ "FormField",
15633
+ "FormItem",
15634
+ "FormLabel",
15635
+ ctx.hasFormMessage === false ? "" : "FormMessage"
15636
+ ]
15640
15637
  ].filter(Boolean);
15641
15638
  const uiImports = [
15642
15639
  `import { ${cardImports.join(", ")} } from '@admin/components/ui/card'`,
@@ -15668,26 +15665,24 @@ function buildUiImports(ctx) {
15668
15665
  );
15669
15666
  }
15670
15667
  if (ctx.hasRelationship || ctx.hasSelectCombobox) {
15671
- const commandImports = [
15672
- "Command",
15673
- "CommandEmpty",
15674
- "CommandGroup",
15675
- "CommandInput",
15676
- "CommandItem",
15677
- "CommandList",
15678
- ctx.hasCreatableSelect ? "CommandSeparator" : ""
15668
+ const comboboxImports = [
15669
+ "Combobox",
15670
+ "ComboboxContent",
15671
+ "ComboboxEmpty",
15672
+ "ComboboxInput",
15673
+ "ComboboxItem",
15674
+ "ComboboxList",
15675
+ ctx.hasCreatableSelect ? "ComboboxSeparator" : "",
15676
+ "ComboboxTrigger"
15679
15677
  ].filter(Boolean);
15680
15678
  uiImports.push(
15681
15679
  renderBuildUiImportsRenderer({
15682
- kind: "renderBuildUiImportsImportsDetailsBranchTemplate",
15680
+ kind: "renderComboboxImports",
15683
15681
  props: {
15684
- join: commandImports.join(",\n ")
15682
+ join: comboboxImports.join(",\n ")
15685
15683
  }
15686
15684
  })
15687
15685
  );
15688
- uiImports.push(
15689
- renderBuildUiImportsRenderer({ kind: "renderBuildUiImportsImportsDetailsBranchBodyTemplate" })
15690
- );
15691
15686
  }
15692
15687
  if (ctx.hasMultiSelect) {
15693
15688
  uiImports.push("import { Badge } from '@admin/components/ui/badge'");
@@ -16372,7 +16367,9 @@ ${defaultValues}
16372
16367
  defaultValues
16373
16368
  })
16374
16369
  const defaultValuesRef = React.useRef(defaultValues)
16375
- defaultValuesRef.current = defaultValues
16370
+ React.useEffect(() => {
16371
+ defaultValuesRef.current = defaultValues
16372
+ })
16376
16373
  React.useEffect(
16377
16374
  () => () => {
16378
16375
  form.reset(defaultValuesRef.current)
@@ -18149,69 +18146,69 @@ function renderMultiRelationshipFieldActionButtonsTemplate({
18149
18146
  return `${indent}<FormField
18150
18147
  ${indent} control={form.control}
18151
18148
  ${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"
18149
+ ${indent} render={({ field: formField }) => {
18150
+ ${indent} const options = (${dataArray} ?? [])
18151
+ ${indent} .filter((item) => item.id !== null)
18152
+ ${indent} .map((item) => {
18153
+ ${indent} const displayName = ${displayField}
18154
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18155
+ ${indent} return {
18156
+ ${indent} value: item.id,
18157
+ ${indent} label: displayName,
18158
+ ${indent} secondaryLabel: secondaryDisplayName
18159
+ ${indent} }
18160
+ ${indent} })
18161
+ ${indent} const selectedValues = formField.value ?? []
18162
+ ${indent} const selectedOptions = options.filter((option) => selectedValues.includes(option.value))
18163
+ ${indent} return (
18164
+ ${indent} <FormItem${formItemProps2}>
18165
+ ${indent} ${labelWithDescription2}
18166
+ ${indent} <Combobox
18167
+ ${indent} multiple
18168
+ ${indent} items={options}
18169
+ ${indent} value={selectedOptions}
18170
+ ${indent} open={${fieldName}Open}
18171
+ ${indent} onOpenChange={set${toPascalCase2}Open}
18172
+ ${indent} onValueChange={(nextOptions) => {
18173
+ ${indent} const nextValue = nextOptions.map((option) => option.value)
18174
+ ${defaultValueFromHandlerContent}
18175
+ ${indent} }}
18176
+ ${indent} >
18177
+ ${indent} <FormControl>
18178
+ ${indent} <ComboboxTrigger
18179
+ ${indent} render={<Button variant="outline" disabled={isPending} />}
18162
18180
  ${indent} className={cn("w-full justify-between", {
18163
- ${indent} "text-muted-foreground": !formField.value || formField.value.length === 0
18181
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
18164
18182
  ${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} )}
18183
+ ${indent} >
18184
+ ${indent} <span className="truncate">
18185
+ ${indent} {selectedOptions.length > 0
18186
+ ${indent} ? \`\${selectedOptions.length} selected\`
18187
+ ${indent} : "Select ${toLowerCase}"}
18188
+ ${indent} </span>
18189
+ ${indent} </ComboboxTrigger>
18190
+ ${indent} </FormControl>
18191
+ ${indent} <ComboboxContent align="start">
18192
+ ${indent} <ComboboxInput placeholder="Search ${toLowerCase}..." showTrigger={false} />
18193
+ ${indent} <ComboboxEmpty>No ${relSingular} found.</ComboboxEmpty>
18194
+ ${indent} <ComboboxList>
18195
+ ${indent} {(option) => (
18196
+ ${indent} <ComboboxItem key={option.value} value={option}>
18197
+ ${indent} <span className="flex min-w-0 flex-col text-left">
18198
+ ${indent} <span className="truncate">{option.label}</span>
18199
+ ${indent} {option.secondaryLabel ? (
18200
+ ${indent} <span className="truncate text-xs text-muted-foreground">{option.secondaryLabel}</span>
18201
+ ${indent} ) : null}
18202
+ ${indent} </span>
18203
+ ${indent} </ComboboxItem>
18204
+ ${indent} )}
18205
+ ${indent} </ComboboxList>
18206
+ ${indent} </ComboboxContent>
18207
+ ${indent} </Combobox>
18208
+ ${indent} <FormMessage />
18209
+ ${indent} </FormItem>
18210
+ ${indent} )
18211
+ ${indent} }}
18215
18212
  ${indent}/>`;
18216
18213
  }
18217
18214
 
@@ -18229,13 +18226,8 @@ function renderMultiRelationshipField(field, indent, label, hintJSX, displayFiel
18229
18226
  dataArray,
18230
18227
  displayField,
18231
18228
  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])`
18229
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValue)
18230
+ ${indent} formField.onChange(nextValue)` : `${indent} formField.onChange(nextValue)`
18239
18231
  });
18240
18232
  }
18241
18233
 
@@ -18256,71 +18248,64 @@ function renderSingleRelationshipFieldActionButtonsTemplate({
18256
18248
  return `${indent}<FormField
18257
18249
  ${indent} control={form.control}
18258
18250
  ${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"
18251
+ ${indent} render={({ field: formField }) => {
18252
+ ${indent} const options = (${dataArray} ?? [])
18253
+ ${indent} .filter((item) => item.id !== null)
18254
+ ${indent} .map((item) => {
18255
+ ${indent} const displayName = ${displayField}
18256
+ ${indent} const secondaryDisplayName = ${secondaryDisplayField}
18257
+ ${indent} return {
18258
+ ${indent} value: String(item.id),
18259
+ ${indent} label: displayName,
18260
+ ${indent} secondaryLabel: secondaryDisplayName
18261
+ ${indent} }
18262
+ ${indent} })
18263
+ ${indent} const selectedOption = options.find((option) => option.value === formField.value) ?? null
18264
+ ${indent} return (
18265
+ ${indent} <FormItem${formItemProps2}>
18266
+ ${indent} ${labelWithDescription2}
18267
+ ${indent} <Combobox
18268
+ ${indent} items={options}
18269
+ ${indent} value={selectedOption}
18270
+ ${indent} open={${fieldName}Open}
18271
+ ${indent} onOpenChange={set${toPascalCase2}Open}
18272
+ ${indent} onValueChange={(option) => {
18273
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(option?.value ?? '')
18274
+ ${indent} }}
18275
+ ${indent} >
18276
+ ${indent} <FormControl>
18277
+ ${indent} <ComboboxTrigger
18278
+ ${indent} render={<Button variant="outline" disabled={isPending} />}
18269
18279
  ${indent} className={cn("w-full justify-between", {
18270
18280
  ${indent} "text-muted-foreground": !formField.value
18271
18281
  ${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} )}
18282
+ ${indent} >
18283
+ ${indent} <span className="truncate">
18284
+ ${indent} {selectedOption ? selectedOption.label : "Select ${toLowerCase}"}
18285
+ ${indent} </span>
18286
+ ${indent} </ComboboxTrigger>
18287
+ ${indent} </FormControl>
18288
+ ${indent} <ComboboxContent align="start">
18289
+ ${indent} <ComboboxInput placeholder="Search ${toLowerCase}..." showTrigger={false} />
18290
+ ${indent} <ComboboxEmpty>No ${relSingular} found.</ComboboxEmpty>
18291
+ ${indent} <ComboboxList>
18292
+ ${indent} {(option) => (
18293
+ ${indent} <ComboboxItem key={option.value} value={option}>
18294
+ ${indent} <span className="flex min-w-0 flex-col text-left">
18295
+ ${indent} <span className="truncate">{option.label}</span>
18296
+ ${indent} {option.secondaryLabel ? (
18297
+ ${indent} <span className="truncate text-xs text-muted-foreground">{option.secondaryLabel}</span>
18298
+ ${indent} ) : null}
18299
+ ${indent} </span>
18300
+ ${indent} </ComboboxItem>
18301
+ ${indent} )}
18302
+ ${indent} </ComboboxList>
18303
+ ${indent} </ComboboxContent>
18304
+ ${indent} </Combobox>
18305
+ ${indent} <FormMessage />
18306
+ ${indent} </FormItem>
18307
+ ${indent} )
18308
+ ${indent} }}
18324
18309
  ${indent}/>`;
18325
18310
  }
18326
18311
 
@@ -18338,7 +18323,7 @@ function renderSingleRelationshipField(field, indent, label, hintJSX, displayFie
18338
18323
  toLowerCase: label.toLowerCase(),
18339
18324
  relSingular,
18340
18325
  secondaryDisplayField,
18341
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(String(item.id))
18326
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18342
18327
  ` : ""
18343
18328
  });
18344
18329
  }
@@ -18534,7 +18519,7 @@ function renderCreatableSelectFieldActionButtonsTemplate({
18534
18519
  ${indent} control={form.control}
18535
18520
  ${indent} name="${fieldName}"
18536
18521
  ${indent} render={({ field: formField }) => {
18537
- ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value)
18522
+ ${indent} const selectedOption = ${optionsVar}.find((option) => option.value === formField.value) ?? null
18538
18523
  ${indent} const createLabel = ${searchVar}.trim()
18539
18524
  ${indent} const canCreateOption =
18540
18525
  ${indent} createLabel.length > 0 &&
@@ -18547,76 +18532,58 @@ ${indent} )
18547
18532
  ${indent} return (
18548
18533
  ${indent} <FormItem${formItemProps2}>
18549
18534
  ${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>
18535
+ ${indent} <Combobox
18536
+ ${indent} items={${optionsVar}}
18537
+ ${indent} value={selectedOption}
18538
+ ${indent} open={${openVar}}
18539
+ ${indent} onOpenChange={${setOpenVar}}
18540
+ ${indent} inputValue={${searchVar}}
18541
+ ${indent} onInputValueChange={${setSearchVar}}
18542
+ ${indent} onValueChange={(option) => {
18543
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(option?.value ?? '')
18544
+ ${indent} ${setSearchVar}('')
18545
+ ${indent} }}
18546
+ ${indent} >
18547
+ ${indent} <FormControl>
18548
+ ${indent} <ComboboxTrigger
18549
+ ${indent} render={<Button type="button" variant="outline" disabled={isPending} />}
18550
+ ${indent} className={cn("w-full justify-between", {
18551
+ ${indent} "text-muted-foreground": !selectedOption
18552
+ ${indent} })}
18553
+ ${indent} >
18554
+ ${indent} <span className="truncate">{selectedOption?.label ?? ${stringify}}</span>
18555
+ ${indent} </ComboboxTrigger>
18556
+ ${indent} </FormControl>
18557
+ ${indent} <ComboboxContent align="start">
18558
+ ${indent} <ComboboxInput placeholder="Search ${lowerLabel}..." showTrigger={false} />
18559
+ ${indent} <ComboboxEmpty>No ${lowerLabel} found.</ComboboxEmpty>
18560
+ ${indent} <ComboboxList>
18561
+ ${indent} {(option) => (
18562
+ ${indent} <ComboboxItem key={option.value} value={option}>
18563
+ ${indent} <span className="truncate">{option.label}</span>
18564
+ ${indent} </ComboboxItem>
18565
+ ${indent} )}
18566
+ ${indent} </ComboboxList>
18567
+ ${indent} {canCreateOption ? (
18568
+ ${indent} <>
18569
+ ${indent} <ComboboxSeparator />
18570
+ ${indent} <div className="p-1">
18571
+ ${indent} <Button
18572
+ ${indent} type="button"
18573
+ ${indent} variant="ghost"
18574
+ ${indent} className="w-full justify-start"
18575
+ ${indent} disabled={${pendingVar}}
18576
+ ${indent} aria-busy={${pendingVar}}
18577
+ ${indent} onClick={() => ${createHandler}(createLabel)}
18578
+ ${indent} >
18579
+ ${indent} <Plus className="size-4" />
18580
+ ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18581
+ ${indent} </Button>
18582
+ ${indent} </div>
18583
+ ${indent} </>
18584
+ ${indent} ) : null}
18585
+ ${indent} </ComboboxContent>
18586
+ ${indent} </Combobox>
18620
18587
  ${indent} <FormMessage />
18621
18588
  ${indent} </FormItem>
18622
18589
  ${indent} )
@@ -18653,7 +18620,7 @@ function renderCreatableSelectField(field, indent, label, hintJSX, context) {
18653
18620
  stringify: JSON.stringify(placeholder),
18654
18621
  lowerLabel,
18655
18622
  setSearchVar,
18656
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option.value)
18623
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(option?.value ?? '')
18657
18624
  ` : "",
18658
18625
  pendingVar,
18659
18626
  createHandler
@@ -18668,17 +18635,14 @@ function renderMultiSelectFieldStaticOptionsTemplate({
18668
18635
  return `const staticOptions = ${staticOptions}
18669
18636
  ${indent} const options = staticOptions`;
18670
18637
  }
18671
- function renderMultiSelectFieldContentTemplate({
18638
+ function renderMultiSelectFieldSearchBindingTemplate({
18672
18639
  indent,
18673
- lowerLabel,
18674
18640
  searchVar,
18675
18641
  setSearchVar
18676
18642
  }) {
18677
- return `<CommandInput
18678
- ${indent} placeholder="Search ${lowerLabel}..."
18679
- ${indent} value={${searchVar}}
18680
- ${indent} onValueChange={${setSearchVar}}
18681
- ${indent} />`;
18643
+ return `
18644
+ ${indent} inputValue={${searchVar}}
18645
+ ${indent} onInputValueChange={${setSearchVar}}`;
18682
18646
  }
18683
18647
  function renderMultiSelectFieldCreateLabelTemplate({
18684
18648
  indent,
@@ -18701,29 +18665,28 @@ function renderMultiSelectFieldActionButtonsTemplate({
18701
18665
  createHandler
18702
18666
  }) {
18703
18667
  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}`;
18668
+ ${indent} {canCreateOption ? (
18669
+ ${indent} <>
18670
+ ${indent} <ComboboxSeparator />
18671
+ ${indent} <div className="p-1">
18672
+ ${indent} <Button
18673
+ ${indent} type="button"
18674
+ ${indent} variant="ghost"
18675
+ ${indent} className="w-full justify-start"
18676
+ ${indent} disabled={${pendingVar}}
18677
+ ${indent} aria-busy={${pendingVar}}
18678
+ ${indent} onClick={() => ${createHandler}(createLabel)}
18679
+ ${indent} >
18680
+ ${indent} <Plus className="size-4" />
18681
+ ${indent} {${pendingVar} ? 'Creating\u2026' : \`Create "\${createLabel}"\`}
18682
+ ${indent} </Button>
18683
+ ${indent} </div>
18684
+ ${indent} </>
18685
+ ${indent} ) : null}`;
18722
18686
  }
18723
18687
  function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18724
18688
  indent,
18725
18689
  fieldName,
18726
- optionsId,
18727
18690
  optionsDeclaration,
18728
18691
  createState,
18729
18692
  previewLimit,
@@ -18732,7 +18695,7 @@ function renderMultiSelectFieldActionButtonsSerializedValueTemplate({
18732
18695
  openVar,
18733
18696
  setOpenVar,
18734
18697
  stringify,
18735
- searchInput,
18698
+ searchBinding,
18736
18699
  lowerLabel,
18737
18700
  defaultValueFromHandlerContent,
18738
18701
  clearSearch,
@@ -18757,89 +18720,69 @@ ${indent} : []
18757
18720
  ${indent} return (
18758
18721
  ${indent} <FormItem${formItemProps2}>
18759
18722
  ${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>
18723
+ ${indent} <Combobox
18724
+ ${indent} multiple
18725
+ ${indent} items={options}
18726
+ ${indent} value={selectedOptions}
18727
+ ${indent} open={${openVar}}
18728
+ ${indent} onOpenChange={${setOpenVar}}${searchBinding}
18729
+ ${indent} onValueChange={(nextOptions) => {
18730
+ ${indent} const nextValues = nextOptions.map((option) => option.value)
18731
+ ${defaultValueFromHandlerContent}${indent} formField.onChange(nextValues)${clearSearch}
18732
+ ${indent} }}
18733
+ ${indent} >
18734
+ ${indent} <FormControl>
18735
+ ${indent} <ComboboxTrigger
18736
+ ${indent} render={<Button type="button" variant="outline" disabled={isPending} />}
18737
+ ${indent} className={cn("w-full justify-between gap-2", {
18738
+ ${indent} "text-muted-foreground": selectedOptions.length === 0
18739
+ ${indent} })}
18740
+ ${indent} >
18741
+ ${indent} <span className="flex min-w-0 flex-1 items-center gap-2 text-left">
18742
+ ${indent} {selectedOptions.length > 0 ? (
18743
+ ${indent} <>
18744
+ ${indent} <span className="truncate">
18745
+ ${indent} {visibleSelectedOptions.map((option) => option.label).join(', ')}
18746
+ ${indent} </span>
18747
+ ${indent} {hiddenSelectedOptions.length > 0 ? (
18748
+ ${indent} <Tooltip>
18749
+ ${indent} <TooltipTrigger
18750
+ ${indent} render={<Badge variant="outline" className="h-5 shrink-0 tabular-nums" />}
18751
+ ${indent} >
18752
+ ${indent} {'+'}
18753
+ ${indent} {hiddenSelectedOptions.length}{' '}
18754
+ ${indent} {hiddenSelectedOptions.length === 1 ? 'other' : 'others'}
18755
+ ${indent} </TooltipTrigger>
18756
+ ${indent} <TooltipContent align="center" side="bottom" className="max-w-60 w-full">
18757
+ ${indent} <div className="space-y-1">
18758
+ ${indent} {hiddenSelectedOptions.map((option) => (
18759
+ ${indent} <div key={option.value} className="truncate">
18760
+ ${indent} {option.label}
18761
+ ${indent} </div>
18762
+ ${indent} ))}
18763
+ ${indent} </div>
18764
+ ${indent} </TooltipContent>
18765
+ ${indent} </Tooltip>
18766
+ ${indent} ) : null}
18767
+ ${indent} </>
18768
+ ${indent} ) : (
18769
+ ${indent} <span className="truncate">{${stringify}}</span>
18770
+ ${indent} )}
18771
+ ${indent} </span>
18772
+ ${indent} </ComboboxTrigger>
18773
+ ${indent} </FormControl>
18774
+ ${indent} <ComboboxContent align="start">
18775
+ ${indent} <ComboboxInput placeholder="Search ${lowerLabel}..." showTrigger={false} />
18776
+ ${indent} <ComboboxEmpty>No ${lowerLabel} found.</ComboboxEmpty>
18777
+ ${indent} <ComboboxList>
18778
+ ${indent} {(option) => (
18779
+ ${indent} <ComboboxItem key={option.value} value={option}>
18780
+ ${indent} <span className="truncate">{option.label}</span>
18781
+ ${indent} </ComboboxItem>
18782
+ ${indent} )}
18783
+ ${indent} </ComboboxList>${createAction}
18784
+ ${indent} </ComboboxContent>
18785
+ ${indent} </Combobox>
18843
18786
  ${indent} <FormMessage />
18844
18787
  ${indent} </FormItem>
18845
18788
  ${indent} )
@@ -18850,8 +18793,8 @@ function renderMultiSelectFieldRenderer(request) {
18850
18793
  switch (request.kind) {
18851
18794
  case "renderMultiSelectFieldStaticOptionsTemplate":
18852
18795
  return renderMultiSelectFieldStaticOptionsTemplate(request.props);
18853
- case "renderMultiSelectFieldContentTemplate":
18854
- return renderMultiSelectFieldContentTemplate(request.props);
18796
+ case "renderMultiSelectFieldSearchBindingTemplate":
18797
+ return renderMultiSelectFieldSearchBindingTemplate(request.props);
18855
18798
  case "renderMultiSelectFieldCreateLabelTemplate":
18856
18799
  return renderMultiSelectFieldCreateLabelTemplate(request.props);
18857
18800
  case "renderMultiSelectFieldActionButtonsTemplate":
@@ -18878,7 +18821,6 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18878
18821
  const placeholder = field.placeholder || `Select ${label.toLowerCase()}`;
18879
18822
  const previewLimit = Math.max(1, Math.floor(field.previewLimit ?? 1));
18880
18823
  const lowerLabel = label.toLowerCase();
18881
- const optionsId = `${context.schemaName ? `${toKebabCase(singularize(context.schemaName))}-` : ""}${toKebabCase(field.name)}-options`;
18882
18824
  const optionsDeclaration = isCreatable ? `const options = ${optionsVar}` : renderMultiSelectFieldRenderer({
18883
18825
  kind: "renderMultiSelectFieldStaticOptionsTemplate",
18884
18826
  props: {
@@ -18886,15 +18828,14 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18886
18828
  indent
18887
18829
  }
18888
18830
  });
18889
- const searchInput = isCreatable ? renderMultiSelectFieldRenderer({
18890
- kind: "renderMultiSelectFieldContentTemplate",
18831
+ const searchBinding = isCreatable ? renderMultiSelectFieldRenderer({
18832
+ kind: "renderMultiSelectFieldSearchBindingTemplate",
18891
18833
  props: {
18892
18834
  indent,
18893
- lowerLabel,
18894
18835
  searchVar,
18895
18836
  setSearchVar
18896
18837
  }
18897
- }) : `<CommandInput placeholder="Search ${lowerLabel}..." />`;
18838
+ }) : "";
18898
18839
  const createState = isCreatable ? renderMultiSelectFieldRenderer({
18899
18840
  kind: "renderMultiSelectFieldCreateLabelTemplate",
18900
18841
  props: {
@@ -18911,13 +18852,12 @@ function renderMultiSelectField(field, indent, label, hintJSX, context) {
18911
18852
  }
18912
18853
  }) : "";
18913
18854
  const clearSearch = isCreatable ? `
18914
- ${indent} ${setSearchVar}('')` : "";
18855
+ ${indent} ${setSearchVar}('')` : "";
18915
18856
  return renderMultiSelectFieldRenderer({
18916
18857
  kind: "renderMultiSelectFieldActionButtonsSerializedValueTemplate",
18917
18858
  props: {
18918
18859
  indent,
18919
18860
  fieldName: field.name,
18920
- optionsId,
18921
18861
  optionsDeclaration,
18922
18862
  createState,
18923
18863
  previewLimit,
@@ -18930,9 +18870,9 @@ ${indent} ${setSearchVar}('')` : "";
18930
18870
  openVar,
18931
18871
  setOpenVar,
18932
18872
  stringify: JSON.stringify(placeholder),
18933
- searchInput,
18873
+ searchBinding,
18934
18874
  lowerLabel,
18935
- defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18875
+ defaultValueFromHandlerContent: defaultValueFromHandler ? `${indent} ${defaultValueFromHandler}(nextValues)
18936
18876
  ` : "",
18937
18877
  clearSearch,
18938
18878
  createAction
@@ -19644,6 +19584,7 @@ function generateForm(schema, pagesDir, options = {}) {
19644
19584
  tabFieldNames
19645
19585
  });
19646
19586
  const formControlFreeFieldTypes = /* @__PURE__ */ new Set(["separator", "tabs"]);
19587
+ const formMessageFreeFieldTypes = /* @__PURE__ */ new Set(["boolean", "group", "section", "separator", "tabs"]);
19647
19588
  const inputFreeFieldTypes = /* @__PURE__ */ new Set([
19648
19589
  "boolean",
19649
19590
  "image",
@@ -19707,6 +19648,10 @@ function generateForm(schema, pagesDir, options = {}) {
19707
19648
  return false;
19708
19649
  };
19709
19650
  const contentHasRenderedIconPostfix = hasRenderedIconPostfix2(allFormFields);
19651
+ const contentUsesFormMessage = contentHasRenderedIconPostfix || flatFields.some((field) => {
19652
+ if (field.primaryKey || field.hidden) return false;
19653
+ return !formMessageFreeFieldTypes.has(field.type);
19654
+ });
19710
19655
  const uiImports = buildUiImports({
19711
19656
  hasBoolean,
19712
19657
  hasTextarea,
@@ -19734,6 +19679,7 @@ function generateForm(schema, pagesDir, options = {}) {
19734
19679
  hasFormRoot: true,
19735
19680
  hasButton: hasRelationship || hasSelectCombobox || hasNestedList,
19736
19681
  hasFormControls: contentUsesFormControls || contentHasRenderedIconPostfix,
19682
+ hasFormMessage: contentUsesFormMessage,
19737
19683
  hasInput: contentUsesInput
19738
19684
  });
19739
19685
  const lucideIcons = [];
@@ -19743,7 +19689,6 @@ function generateForm(schema, pagesDir, options = {}) {
19743
19689
  }
19744
19690
  };
19745
19691
  addLucideIcons(...sectionHeadingIconNames, ...contentTabIconNames);
19746
- if (hasRelationship || hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
19747
19692
  if (hasCreatableSelect) addLucideIcons("Plus");
19748
19693
  if (hasNestedList) {
19749
19694
  addLucideIcons("Plus", "X");
@@ -23080,6 +23025,7 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23080
23025
  "tabs"
23081
23026
  ]);
23082
23027
  const formControlFreeFieldTypes = /* @__PURE__ */ new Set(["separator", "tabs"]);
23028
+ const formMessageFreeFieldTypes = /* @__PURE__ */ new Set(["boolean", "group", "section", "separator", "tabs"]);
23083
23029
  const cardArtifacts = cardGroups.map((group2) => {
23084
23030
  const analysis = analyzeGroup(group2.fields);
23085
23031
  const groupFlatFields = group2.flatFields;
@@ -23110,6 +23056,10 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23110
23056
  if (field.type === "list" && (!field.fields || field.fields.length === 0)) return false;
23111
23057
  return !formControlFreeFieldTypes.has(field.type);
23112
23058
  }) || hasIconPostfix;
23059
+ const hasFormMessage = hasIconPostfix || groupFlatFields.some((field) => {
23060
+ if (field.primaryKey || field.hidden) return false;
23061
+ return !formMessageFreeFieldTypes.has(field.type);
23062
+ });
23113
23063
  const groupUiImports = buildUiImports({
23114
23064
  hasBoolean: hasFieldType(group2.fields, "boolean"),
23115
23065
  hasTextarea: hasFieldType(group2.fields, "text"),
@@ -23135,6 +23085,7 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23135
23085
  hasCardContent: true,
23136
23086
  hasSectionCardHeading: true,
23137
23087
  hasFormRoot: true,
23088
+ hasFormMessage,
23138
23089
  hasButton: true,
23139
23090
  hasFormControls,
23140
23091
  hasInput
@@ -23166,7 +23117,6 @@ function generateSingleForm(schema, pagesDir, options = {}) {
23166
23117
  }
23167
23118
  };
23168
23119
  addLucideIcons(...collectTabIconNames(group2.fields));
23169
- if (hasSelectCombobox) addLucideIcons("Check", "ChevronsUpDown");
23170
23120
  if (hasCreatableSelect || hasNestedList) addLucideIcons("Plus");
23171
23121
  if (hasNestedList) addLucideIcons("X");
23172
23122
  const relationshipImports = Array.from(
@@ -33138,7 +33088,12 @@ function scaffoldOxfmt(cwd, linter, adminDir) {
33138
33088
  "import/consistent-type-specifier-style": ["error", "prefer-top-level"]
33139
33089
  },
33140
33090
  // The generated admin vendors shadcn and Tiptap primitives whose a11y and hook shapes
33141
- // BetterStart owns, so the rest of the project stays fully linted.
33091
+ // BetterStart owns, so the rest of the project stays fully linted. TanStack Table/Virtual
33092
+ // and react-hook-form expose no React Compiler-compatible alternative to the APIs the admin
33093
+ // is built on, so `react/incompatible-library` is scoped off there rather than per call site.
33094
+ // Admin state that tracks Tiptap, CodeMirror, scroll position, and DOM measurements is
33095
+ // synchronised from effects, which is what effects are for, so `react/set-state-in-effect`
33096
+ // is scoped off there too.
33142
33097
  overrides: [
33143
33098
  {
33144
33099
  files: [`**/${admin}/**`, `**/(${namespace})/**`],
@@ -33147,6 +33102,8 @@ function scaffoldOxfmt(cwd, linter, adminDir) {
33147
33102
  "jsx-a11y/no-autofocus": "off",
33148
33103
  "jsx-a11y/anchor-has-content": "off",
33149
33104
  "react-hooks/exhaustive-deps": "off",
33105
+ "react/incompatible-library": "off",
33106
+ "react/set-state-in-effect": "off",
33150
33107
  "unicorn/no-new-array": "off",
33151
33108
  "unicorn/no-empty-file": "off"
33152
33109
  }
@@ -33154,7 +33111,8 @@ function scaffoldOxfmt(cwd, linter, adminDir) {
33154
33111
  {
33155
33112
  files: [`**/${admin}/components/ui/**`],
33156
33113
  rules: {
33157
- "react/no-multi-comp": "off"
33114
+ "react/no-multi-comp": "off",
33115
+ "react/set-state-in-effect": "off"
33158
33116
  }
33159
33117
  }
33160
33118
  ],