@vendure/dashboard 3.5.2-master-202512020233 → 3.5.2-master-202512170238

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/plugin/constants.js +2 -2
  2. package/dist/vite/constants.js +1 -0
  3. package/lingui.config.js +1 -0
  4. package/package.json +7 -7
  5. package/src/app/routeTree.gen.ts +1221 -0
  6. package/src/app/routes/_authenticated/_customers/components/customer-history/index.ts +0 -1
  7. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +1 -1
  8. package/src/app/routes/_authenticated/_orders/components/add-surcharge-form.tsx +139 -0
  9. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +3 -0
  10. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +3 -3
  11. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +49 -11
  12. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +9 -0
  13. package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +23 -0
  14. package/src/app/routes/_authenticated/_product-variants/components/add-currency-dropdown.tsx +3 -3
  15. package/src/app/routes/_authenticated/_product-variants/components/add-stock-location-dropdown.tsx +2 -2
  16. package/src/app/routes/_authenticated/_products/products.graphql.ts +1 -0
  17. package/src/i18n/locales/bg.po +3436 -0
  18. package/src/lib/components/data-input/datetime-input.tsx +1 -1
  19. package/src/lib/components/data-input/relation-selector.tsx +1 -1
  20. package/src/lib/components/data-input/struct-form-input.tsx +175 -174
  21. package/src/lib/components/data-table/data-table.tsx +1 -0
  22. package/src/lib/components/layout/manage-languages-dialog.tsx +2 -25
  23. package/src/lib/components/shared/custom-fields-form.tsx +13 -8
  24. package/src/lib/components/ui/carousel.tsx +2 -2
  25. package/src/lib/components/ui/chart.tsx +1 -1
  26. package/src/lib/components/ui/context-menu.tsx +1 -1
  27. package/src/lib/components/ui/drawer.tsx +1 -1
  28. package/src/lib/components/ui/grid-layout.tsx +1 -1
  29. package/src/lib/components/ui/input-group.tsx +1 -0
  30. package/src/lib/components/ui/input-otp.tsx +1 -1
  31. package/src/lib/components/ui/menubar.tsx +1 -1
  32. package/src/lib/components/ui/navigation-menu.tsx +1 -1
  33. package/src/lib/components/ui/progress.tsx +1 -1
  34. package/src/lib/components/ui/radio-group.tsx +1 -1
  35. package/src/lib/components/ui/resizable.tsx +1 -1
  36. package/src/lib/components/ui/select.tsx +1 -1
  37. package/src/lib/components/ui/slider.tsx +1 -1
  38. package/src/lib/components/ui/toggle-group.tsx +2 -2
  39. package/src/lib/components/ui/toggle.tsx +1 -1
  40. package/src/lib/framework/component-registry/component-registry.tsx +2 -6
  41. package/src/lib/framework/extension-api/display-component-extensions.tsx +4 -3
  42. package/src/lib/framework/extension-api/logic/detail-forms.ts +0 -13
  43. package/src/lib/framework/extension-api/types/data-table.ts +4 -2
  44. package/src/lib/framework/extension-api/types/navigation.ts +2 -2
  45. package/src/lib/framework/form-engine/use-generated-form.tsx +7 -1
  46. package/src/lib/framework/layout-engine/page-layout.tsx +1 -1
  47. package/src/lib/framework/nav-menu/nav-menu-extensions.ts +1 -1
  48. package/src/lib/framework/page/detail-page-route-loader.tsx +1 -1
  49. package/src/lib/framework/page/page-api.ts +1 -1
  50. package/src/lib/framework/page/use-detail-page.ts +4 -2
  51. package/src/lib/framework/page/use-extended-router.tsx +20 -16
  52. package/src/lib/framework/registry/registry-types.ts +2 -1
  53. package/src/lib/graphql/graphql-env.d.ts +8 -12
  54. package/src/lib/providers/channel-provider.tsx +11 -7
  55. package/LICENSE.md +0 -42
  56. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +0 -129
  57. /package/src/{app/routes/_authenticated/_global-settings → lib}/utils/global-languages.ts +0 -0
@@ -185,7 +185,7 @@ function bcpTagToDatePickerLocale(
185
185
  case 'pt-BR':
186
186
  return module.ptBR;
187
187
  default: {
188
- const lang = tag.split('-').at(0);
188
+ const lang = tag.split('-')[0];
189
189
  return lang ? module[lang as keyof typeof module] : undefined;
190
190
  }
191
191
  }
@@ -28,7 +28,7 @@ export interface RelationSelectorConfig<T = any> {
28
28
  /** Number of items to load per page */
29
29
  pageSize?: number;
30
30
  /** Placeholder text for the search input */
31
- placeholder?: React.ReactNode;
31
+ placeholder?: string;
32
32
  /** Whether to enable multi-select mode */
33
33
  multiple?: boolean;
34
34
  /** Custom filter function for search */
@@ -20,7 +20,7 @@ import {
20
20
  StructCustomFieldConfig,
21
21
  StructField,
22
22
  } from '@/vdb/framework/form-engine/form-engine-types.js';
23
- import { isStructFieldConfig } from '@/vdb/framework/form-engine/utils.js';
23
+ import { isReadonlyField, isStructFieldConfig } from '@/vdb/framework/form-engine/utils.js';
24
24
  import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
25
25
  import { CustomFieldListInput } from './custom-field-list-input.js';
26
26
  import { DateTimeInput } from './datetime-input.js';
@@ -98,185 +98,61 @@ export function StructFormInput({ fieldDef, ...field }: Readonly<DashboardFormCo
98
98
  return input?.find(t => t.languageCode === displayLanguage)?.value;
99
99
  };
100
100
 
101
- const isReadonly = fieldDef?.readonly === true;
102
-
103
- // Helper function to render individual struct field inputs
104
- const renderStructFieldInput = (
105
- structField: StructField,
106
- inputField: ControllerRenderProps<any, any>,
107
- ) => {
108
- const isList = structField.list ?? false;
109
-
110
- // Helper function to render single input for a struct field
111
- const renderSingleStructInput = (singleField: ControllerRenderProps<any, any>) => {
112
- switch (structField.type) {
113
- case 'string': {
114
- // Check if the field has options (dropdown)
115
- const stringField = structField as any; // GraphQL union types need casting
116
- if (stringField.options && stringField.options.length > 0) {
117
- return (
118
- <SelectWithOptions {...singleField} fieldDef={stringField} isListField={false} />
119
- );
120
- }
121
- return (
122
- <Input
123
- value={singleField.value ?? ''}
124
- onChange={e => singleField.onChange(e.target.value)}
125
- onBlur={singleField.onBlur}
126
- name={singleField.name}
127
- disabled={isReadonly}
128
- />
129
- );
130
- }
131
- case 'int':
132
- case 'float': {
133
- const isFloat = structField.type === 'float';
134
- const numericField = structField as any; // GraphQL union types need casting
135
- const min = isFloat ? numericField.floatMin : numericField.intMin;
136
- const max = isFloat ? numericField.floatMax : numericField.intMax;
137
- const step = isFloat ? numericField.floatStep : numericField.intStep;
138
-
139
- return (
140
- <Input
141
- type="number"
142
- value={singleField.value ?? ''}
143
- onChange={e => {
144
- const value = e.target.valueAsNumber;
145
- singleField.onChange(isNaN(value) ? undefined : value);
146
- }}
147
- onBlur={singleField.onBlur}
148
- name={singleField.name}
149
- disabled={isReadonly}
150
- min={min}
151
- max={max}
152
- step={step}
153
- />
154
- );
155
- }
156
- case 'boolean':
157
- return (
158
- <Switch
159
- checked={singleField.value}
160
- onCheckedChange={singleField.onChange}
161
- disabled={isReadonly}
162
- />
163
- );
164
- case 'datetime':
165
- return <DateTimeInput {...singleField} />;
166
- default:
167
- return (
168
- <Input
169
- value={singleField.value ?? ''}
170
- onChange={e => singleField.onChange(e.target.value)}
171
- onBlur={singleField.onBlur}
172
- name={singleField.name}
173
- disabled={isReadonly}
174
- />
175
- );
176
- }
177
- };
178
-
179
- // Handle string fields with options (dropdown) - already handles list case with multi-select
180
- if (structField.type === 'string') {
181
- const stringField = structField as any; // GraphQL union types need casting
182
- if (stringField.options && stringField.options.length > 0) {
183
- return (
184
- <SelectWithOptions
185
- {...inputField}
186
- fieldDef={stringField}
187
- disabled={isReadonly}
188
- isListField={isList}
189
- />
190
- );
191
- }
192
- }
193
-
194
- // For list struct fields, wrap with list input
195
- if (isList) {
196
- const getDefaultValue = () => {
197
- switch (structField.type) {
198
- case 'string':
199
- return '';
200
- case 'int':
201
- case 'float':
202
- return 0;
203
- case 'boolean':
204
- return false;
205
- case 'datetime':
206
- return '';
207
- default:
208
- return '';
209
- }
210
- };
211
-
212
- // Determine if the field type needs full width
213
- const needsFullWidth = structField.type === 'text' || structField.type === 'localeText';
214
-
215
- return (
216
- <CustomFieldListInput
217
- {...inputField}
218
- disabled={isReadonly}
219
- renderInput={(index, listItemField) => renderSingleStructInput(listItemField)}
220
- defaultValue={getDefaultValue()}
221
- />
222
- );
223
- }
224
-
225
- // For non-list fields, render directly
226
- return renderSingleStructInput(inputField);
227
- };
101
+ const isReadonly = isReadonlyField(fieldDef);
228
102
 
229
103
  // Edit mode - memoized to prevent focus loss from re-renders
230
104
  const EditMode = useMemo(
231
- () => (
232
- <div className="space-y-4 border rounded-md p-4">
233
- {!isReadonly && (
234
- <div className="flex justify-end">
235
- <Button
236
- variant="ghost"
237
- size="sm"
238
- onClick={() => setIsEditing(false)}
239
- className="h-8 w-8 p-0 text-muted-foreground hover:text-foreground"
240
- >
241
- <CheckIcon className="h-4 w-4" />
242
- <span className="sr-only">Done</span>
243
- </Button>
244
- </div>
245
- )}
246
- {fieldDef?.fields?.map(structField => (
247
- <FormField
248
- key={structField.name}
249
- control={control}
250
- name={`${field.name}.${structField.name}`}
251
- render={({ field: structInputField }) => (
252
- <FormItem>
253
- <div className="flex items-baseline gap-4">
254
- <div className="flex-1">
255
- <FormLabel>
256
- {getTranslation(structField.label) ?? structField.name}
257
- </FormLabel>
258
- {getTranslation(structField.description) && (
259
- <FormDescription>
260
- {getTranslation(structField.description)}
261
- </FormDescription>
262
- )}
105
+ () =>
106
+ fieldDef && isStructFieldConfig(fieldDef) ? (
107
+ <div className="space-y-4 border rounded-md p-4">
108
+ {!isReadonly && (
109
+ <div className="flex justify-end">
110
+ <Button
111
+ variant="ghost"
112
+ size="sm"
113
+ onClick={() => setIsEditing(false)}
114
+ className="h-8 w-8 p-0 text-muted-foreground hover:text-foreground"
115
+ >
116
+ <CheckIcon className="h-4 w-4" />
117
+ <span className="sr-only">Done</span>
118
+ </Button>
119
+ </div>
120
+ )}
121
+ {fieldDef?.fields.map(structField => (
122
+ <FormField
123
+ key={structField.name}
124
+ control={control}
125
+ name={`${field.name}.${structField.name}`}
126
+ render={({ field: structInputField }) => (
127
+ <FormItem>
128
+ <div className="flex items-baseline gap-4">
129
+ <div className="flex-1">
130
+ <FormLabel>
131
+ {getTranslation(structField.label) ?? structField.name}
132
+ </FormLabel>
133
+ {getTranslation(structField.description) && (
134
+ <FormDescription>
135
+ {getTranslation(structField.description)}
136
+ </FormDescription>
137
+ )}
138
+ </div>
139
+ <div className="flex-[2]">
140
+ <FormControl>
141
+ {renderStructFieldInput(structField, structInputField)}
142
+ </FormControl>
143
+ <FormMessage />
144
+ </div>
263
145
  </div>
264
- <div className="flex-[2]">
265
- <FormControl>
266
- {renderStructFieldInput(structField, structInputField)}
267
- </FormControl>
268
- <FormMessage />
269
- </div>
270
- </div>
271
- </FormItem>
272
- )}
273
- />
274
- ))}
275
- </div>
276
- ),
277
- [fieldDef, control, field.name, getTranslation, renderStructFieldInput, isReadonly],
146
+ </FormItem>
147
+ )}
148
+ />
149
+ ))}
150
+ </div>
151
+ ) : null,
152
+ [fieldDef, control, field.name, getTranslation, isReadonly],
278
153
  );
279
154
 
155
+ // Early return if not a struct field config
280
156
  if (!fieldDef || !isStructFieldConfig(fieldDef)) {
281
157
  return null;
282
158
  }
@@ -317,3 +193,128 @@ export function StructFormInput({ fieldDef, ...field }: Readonly<DashboardFormCo
317
193
  />
318
194
  );
319
195
  }
196
+
197
+ // Helper function to render individual struct field inputs
198
+ const renderStructFieldInput = (
199
+ structField: StructField,
200
+ inputField: ControllerRenderProps<any, any>,
201
+ isReadonly: boolean = false,
202
+ ) => {
203
+ const isList = structField.list ?? false;
204
+
205
+ // Helper function to render single input for a struct field
206
+ const renderSingleStructInput = (singleField: ControllerRenderProps<any, any>) => {
207
+ switch (structField.type) {
208
+ case 'string': {
209
+ // Check if the field has options (dropdown)
210
+ const stringField = structField as any; // GraphQL union types need casting
211
+ if (stringField.options && stringField.options.length > 0) {
212
+ return <SelectWithOptions {...singleField} fieldDef={stringField} isListField={false} />;
213
+ }
214
+ return (
215
+ <Input
216
+ value={singleField.value ?? ''}
217
+ onChange={e => singleField.onChange(e.target.value)}
218
+ onBlur={singleField.onBlur}
219
+ name={singleField.name}
220
+ disabled={isReadonly}
221
+ />
222
+ );
223
+ }
224
+ case 'int':
225
+ case 'float': {
226
+ const isFloat = structField.type === 'float';
227
+ const numericField = structField as any; // GraphQL union types need casting
228
+ const min = isFloat ? numericField.floatMin : numericField.intMin;
229
+ const max = isFloat ? numericField.floatMax : numericField.intMax;
230
+ const step = isFloat ? numericField.floatStep : numericField.intStep;
231
+
232
+ return (
233
+ <Input
234
+ type="number"
235
+ value={singleField.value ?? ''}
236
+ onChange={e => {
237
+ const value = e.target.valueAsNumber;
238
+ singleField.onChange(isNaN(value) ? undefined : value);
239
+ }}
240
+ onBlur={singleField.onBlur}
241
+ name={singleField.name}
242
+ disabled={isReadonly}
243
+ min={min}
244
+ max={max}
245
+ step={step}
246
+ />
247
+ );
248
+ }
249
+ case 'boolean':
250
+ return (
251
+ <Switch
252
+ checked={singleField.value}
253
+ onCheckedChange={singleField.onChange}
254
+ disabled={isReadonly}
255
+ />
256
+ );
257
+ case 'datetime':
258
+ return <DateTimeInput {...singleField} />;
259
+ default:
260
+ return (
261
+ <Input
262
+ value={singleField.value ?? ''}
263
+ onChange={e => singleField.onChange(e.target.value)}
264
+ onBlur={singleField.onBlur}
265
+ name={singleField.name}
266
+ disabled={isReadonly}
267
+ />
268
+ );
269
+ }
270
+ };
271
+
272
+ // Handle string fields with options (dropdown) - already handles list case with multi-select
273
+ if (structField.type === 'string') {
274
+ const stringField = structField as any; // GraphQL union types need casting
275
+ if (stringField.options && stringField.options.length > 0) {
276
+ return (
277
+ <SelectWithOptions
278
+ {...inputField}
279
+ fieldDef={stringField}
280
+ disabled={isReadonly}
281
+ isListField={isList}
282
+ />
283
+ );
284
+ }
285
+ }
286
+
287
+ // For list struct fields, wrap with list input
288
+ if (isList) {
289
+ const getDefaultValue = () => {
290
+ switch (structField.type) {
291
+ case 'string':
292
+ return '';
293
+ case 'int':
294
+ case 'float':
295
+ return 0;
296
+ case 'boolean':
297
+ return false;
298
+ case 'datetime':
299
+ return '';
300
+ default:
301
+ return '';
302
+ }
303
+ };
304
+
305
+ // Determine if the field type needs full width
306
+ const needsFullWidth = structField.type === 'text' || structField.type === 'localeText';
307
+
308
+ return (
309
+ <CustomFieldListInput
310
+ {...inputField}
311
+ disabled={isReadonly}
312
+ renderInput={(index, listItemField) => renderSingleStructInput(listItemField)}
313
+ defaultValue={getDefaultValue()}
314
+ />
315
+ );
316
+ }
317
+
318
+ // For non-list fields, render directly
319
+ return renderSingleStructInput(inputField);
320
+ };
@@ -254,6 +254,7 @@ export function DataTable<TData>({
254
254
  title={filter?.title}
255
255
  options={filter?.options}
256
256
  optionsFn={filter?.optionsFn}
257
+ icon={filter?.icon}
257
258
  />
258
259
  ))}
259
260
  </Suspense>
@@ -18,6 +18,7 @@ import { useChannel } from '@/vdb/hooks/use-channel.js';
18
18
  import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
19
19
  import { usePermissions } from '@/vdb/hooks/use-permissions.js';
20
20
  import { useSortedLanguages } from '@/vdb/hooks/use-sorted-languages.js';
21
+ import { globalLanguageCodes } from '@/vdb/utils/global-languages.js';
21
22
  import { Trans } from '@lingui/react/macro';
22
23
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
23
24
  import { AlertCircle, Lock } from 'lucide-react';
@@ -68,36 +69,12 @@ const updateChannelDocument = graphql(`
68
69
  }
69
70
  `);
70
71
 
71
- // All possible language codes for global settings - includes more than what might be globally enabled
72
- const ALL_LANGUAGE_CODES = [
73
- 'en',
74
- 'es',
75
- 'fr',
76
- 'de',
77
- 'it',
78
- 'pt',
79
- 'nl',
80
- 'pl',
81
- 'ru',
82
- 'ja',
83
- 'zh',
84
- 'ko',
85
- 'ar',
86
- 'hi',
87
- 'sv',
88
- 'da',
89
- 'nb',
90
- 'nn',
91
- 'fi',
92
- ];
93
-
94
72
  interface ManageLanguagesDialogProps {
95
73
  open: boolean;
96
74
  onClose: () => void;
97
75
  }
98
76
 
99
77
  export function ManageLanguagesDialog({ open, onClose }: ManageLanguagesDialogProps) {
100
- const { formatLanguageName } = useLocalFormat();
101
78
  const { activeChannel } = useChannel();
102
79
  const { hasPermissions } = usePermissions();
103
80
  const queryClient = useQueryClient();
@@ -309,7 +286,7 @@ export function ManageLanguagesDialog({ open, onClose }: ManageLanguagesDialogPr
309
286
  value={globalLanguages}
310
287
  onChange={handleGlobalLanguagesChange}
311
288
  multiple={true}
312
- availableLanguageCodes={ALL_LANGUAGE_CODES}
289
+ availableLanguageCodes={globalLanguageCodes}
313
290
  />
314
291
  </div>
315
292
  <p className="text-xs text-muted-foreground">
@@ -10,6 +10,7 @@ import {
10
10
  } from '@/vdb/components/ui/form.js';
11
11
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/vdb/components/ui/tabs.js';
12
12
  import { CustomFormComponent } from '@/vdb/framework/form-engine/custom-form-component.js';
13
+ import { ConfigurableFieldDef } from '@/vdb/framework/form-engine/form-engine-types.js';
13
14
  import { useCustomFieldConfig } from '@/vdb/hooks/use-custom-field-config.js';
14
15
  import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
15
16
  import { customFieldConfigFragment } from '@/vdb/providers/server-config.js';
@@ -20,7 +21,7 @@ import { Control } from 'react-hook-form';
20
21
  import { FormControlAdapter } from '../../framework/form-engine/form-control-adapter.js';
21
22
  import { TranslatableFormField } from './translatable-form-field.js';
22
23
 
23
- type CustomFieldConfig = ResultOf<typeof customFieldConfigFragment>;
24
+ type CustomFieldConfig = Omit<ResultOf<typeof customFieldConfigFragment>, '__typename'>;
24
25
 
25
26
  interface CustomFieldsFormProps {
26
27
  entityType: string;
@@ -120,8 +121,8 @@ export function CustomFieldsForm({ entityType, control, formPathPrefix }: Readon
120
121
  }
121
122
 
122
123
  interface CustomFieldItemProps {
123
- fieldDef: CustomFieldConfig;
124
- control: Control<any, any>;
124
+ fieldDef: ConfigurableFieldDef;
125
+ control: Control<any>;
125
126
  fieldName: string;
126
127
  }
127
128
 
@@ -130,14 +131,19 @@ function CustomFieldItem({ fieldDef, control, fieldName }: Readonly<CustomFieldI
130
131
  settings: { displayLanguage },
131
132
  } = useUserSettings();
132
133
 
133
- const getTranslation = (input: Array<{ languageCode: string; value: string }> | null | undefined) => {
134
+ const getTranslation = (
135
+ input: string | Array<{ languageCode: string; value: string }> | null | undefined,
136
+ ) => {
137
+ if (typeof input === 'string') {
138
+ return input;
139
+ }
134
140
  return input?.find(t => t.languageCode === displayLanguage)?.value;
135
141
  };
136
142
  const hasCustomFormComponent = fieldDef.ui?.component;
137
143
  const isLocaleField = fieldDef.type === 'localeString' || fieldDef.type === 'localeText';
138
144
  const shouldBeFullWidth = fieldDef.ui?.fullWidth === true;
139
145
  const containerClassName = shouldBeFullWidth ? 'col-span-2' : '';
140
- const isReadonly = fieldDef.readonly ?? false;
146
+ const isReadonly = (fieldDef as CustomFieldConfig).readonly ?? false;
141
147
 
142
148
  // For locale fields, always use TranslatableFormField regardless of custom components
143
149
  if (isLocaleField) {
@@ -212,7 +218,6 @@ function CustomFieldItem({ fieldDef, control, fieldName }: Readonly<CustomFieldI
212
218
  <StructFormInput {...inputField} fieldDef={fieldDef} />
213
219
  )}
214
220
  defaultValue={{}} // Empty struct object as default
215
- isFullWidth={true} // Structs should always be full-width
216
221
  />
217
222
  </FormControl>
218
223
  <FormDescription>{getTranslation(fieldDef.description)}</FormDescription>
@@ -266,9 +271,9 @@ function CustomFieldItem({ fieldDef, control, fieldName }: Readonly<CustomFieldI
266
271
  }
267
272
 
268
273
  interface CustomFieldFormItemProps {
269
- fieldDef: CustomFieldConfig;
274
+ fieldDef: ConfigurableFieldDef;
270
275
  getTranslation: (
271
- input: Array<{ languageCode: string; value: string }> | null | undefined,
276
+ input: string | Array<{ languageCode: string; value: string }> | null | undefined,
272
277
  ) => string | undefined;
273
278
  fieldName: string;
274
279
  children: React.ReactNode;
@@ -6,8 +6,8 @@ import useEmblaCarousel, {
6
6
  } from "embla-carousel-react"
7
7
  import { ArrowLeft, ArrowRight } from "lucide-react"
8
8
 
9
- import { cn } from "@/vdb/lib/utils"
10
- import { Button } from "@/vdb/components/ui/button"
9
+ import { cn } from "@/vdb/lib/utils.js"
10
+ import { Button } from "@/vdb/components/ui/button.js"
11
11
 
12
12
  type CarouselApi = UseEmblaCarouselType[1]
13
13
  type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
@@ -1,7 +1,7 @@
1
1
  import * as React from "react"
2
2
  import * as RechartsPrimitive from "recharts"
3
3
 
4
- import { cn } from "@/vdb/lib/utils"
4
+ import { cn } from "@/vdb/lib/utils.js"
5
5
 
6
6
  // Format: { THEME_NAME: CSS_SELECTOR }
7
7
  const THEMES = { light: "", dark: ".dark" } as const
@@ -4,7 +4,7 @@ import * as React from "react"
4
4
  import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
5
5
  import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
6
6
 
7
- import { cn } from "@/vdb/lib/utils"
7
+ import { cn } from "@/vdb/lib/utils.js"
8
8
 
9
9
  function ContextMenu({
10
10
  ...props
@@ -1,7 +1,7 @@
1
1
  import * as React from "react"
2
2
  import { Drawer as DrawerPrimitive } from "vaul"
3
3
 
4
- import { cn } from "@/vdb/lib/utils"
4
+ import { cn } from "@/vdb/lib/utils.js"
5
5
 
6
6
  function Drawer({
7
7
  ...props
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { useState, useRef, useCallback, useEffect } from "react";
3
- import { cn } from "@/vdb/lib/utils";
3
+ import { cn } from "@/vdb/lib/utils.js";
4
4
 
5
5
  export interface GridLayout {
6
6
  x: number;
@@ -127,6 +127,7 @@ function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>)
127
127
  'flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent',
128
128
  className,
129
129
  )}
130
+ value={props.value}
130
131
  {...props}
131
132
  />
132
133
  );
@@ -4,7 +4,7 @@ import * as React from "react"
4
4
  import { OTPInput, OTPInputContext } from "input-otp"
5
5
  import { MinusIcon } from "lucide-react"
6
6
 
7
- import { cn } from "@/vdb/lib/utils"
7
+ import { cn } from "@/vdb/lib/utils.js"
8
8
 
9
9
  function InputOTP({
10
10
  className,
@@ -2,7 +2,7 @@ import * as React from "react"
2
2
  import * as MenubarPrimitive from "@radix-ui/react-menubar"
3
3
  import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
4
4
 
5
- import { cn } from "@/vdb/lib/utils"
5
+ import { cn } from "@/vdb/lib/utils.js"
6
6
 
7
7
  function Menubar({
8
8
  className,
@@ -3,7 +3,7 @@ import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
3
3
  import { cva } from "class-variance-authority"
4
4
  import { ChevronDownIcon } from "lucide-react"
5
5
 
6
- import { cn } from "@/vdb/lib/utils"
6
+ import { cn } from "@/vdb/lib/utils.js"
7
7
 
8
8
  function NavigationMenu({
9
9
  className,
@@ -1,7 +1,7 @@
1
1
  import * as React from "react"
2
2
  import * as ProgressPrimitive from "@radix-ui/react-progress"
3
3
 
4
- import { cn } from "@/vdb/lib/utils"
4
+ import { cn } from "@/vdb/lib/utils.js"
5
5
 
6
6
  function Progress({
7
7
  className,
@@ -4,7 +4,7 @@ import * as React from "react"
4
4
  import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
5
5
  import { CircleIcon } from "lucide-react"
6
6
 
7
- import { cn } from "@/vdb/lib/utils"
7
+ import { cn } from "@/vdb/lib/utils.js"
8
8
 
9
9
  function RadioGroup({
10
10
  className,
@@ -2,7 +2,7 @@ import * as React from "react"
2
2
  import { GripVerticalIcon } from "lucide-react"
3
3
  import * as ResizablePrimitive from "react-resizable-panels"
4
4
 
5
- import { cn } from "@/vdb/lib/utils"
5
+ import { cn } from "@/vdb/lib/utils.js"
6
6
 
7
7
  function ResizablePanelGroup({
8
8
  className,
@@ -2,7 +2,7 @@ import * as React from "react"
2
2
  import * as SelectPrimitive from "@radix-ui/react-select"
3
3
  import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
4
4
 
5
- import { cn } from "@/vdb/lib/utils"
5
+ import { cn } from "@/vdb/lib/utils.js"
6
6
 
7
7
  function Select({
8
8
  ...props