@vendure/dashboard 3.4.2-master-202509090229 → 3.4.2

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 (72) hide show
  1. package/package.json +4 -4
  2. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +3 -3
  3. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +4 -4
  4. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +3 -3
  5. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +3 -3
  6. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +3 -3
  7. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +4 -4
  8. package/src/app/routes/_authenticated/_facets/facets.tsx +5 -8
  9. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +3 -3
  10. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +3 -3
  11. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +3 -3
  12. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +3 -3
  13. package/src/app/routes/_authenticated/_products/products_.$id.tsx +3 -3
  14. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +4 -4
  15. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +3 -3
  16. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +3 -3
  17. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +3 -3
  18. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +3 -3
  19. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +3 -3
  20. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +4 -3
  21. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +3 -3
  22. package/src/lib/components/data-input/affixed-input.tsx +18 -0
  23. package/src/lib/components/data-input/boolean-input.tsx +7 -0
  24. package/src/lib/components/data-input/checkbox-input.tsx +7 -0
  25. package/src/lib/components/data-input/datetime-input.tsx +7 -0
  26. package/src/lib/components/data-input/money-input.tsx +8 -0
  27. package/src/lib/components/data-input/number-input.tsx +7 -0
  28. package/src/lib/components/data-input/password-input.tsx +7 -0
  29. package/src/lib/components/data-input/rich-text-input.tsx +7 -0
  30. package/src/lib/components/data-input/text-input.tsx +7 -0
  31. package/src/lib/components/data-input/textarea-input.tsx +7 -0
  32. package/src/lib/components/data-table/data-table-view-options.tsx +29 -26
  33. package/src/lib/components/data-table/data-table.tsx +20 -0
  34. package/src/lib/components/data-table/types.ts +39 -0
  35. package/src/lib/components/layout/channel-switcher.tsx +1 -3
  36. package/src/lib/components/shared/asset/asset-gallery.tsx +58 -0
  37. package/src/lib/components/shared/asset/asset-picker-dialog.tsx +39 -0
  38. package/src/lib/components/shared/detail-page-button.tsx +8 -22
  39. package/src/lib/components/shared/facet-value-chip.tsx +7 -0
  40. package/src/lib/components/shared/facet-value-selector.tsx +55 -0
  41. package/src/lib/components/shared/form-field-wrapper.tsx +51 -0
  42. package/src/lib/components/shared/paginated-list-data-table.tsx +128 -16
  43. package/src/lib/components/shared/permission-guard.tsx +30 -0
  44. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +1 -1
  45. package/src/lib/components/shared/translatable-form-field.tsx +52 -0
  46. package/src/lib/components/shared/vendure-image.tsx +114 -2
  47. package/src/lib/framework/extension-api/define-dashboard-extension.ts +25 -3
  48. package/src/lib/framework/extension-api/extension-api-types.ts +12 -3
  49. package/src/lib/framework/extension-api/types/alerts.ts +2 -3
  50. package/src/lib/framework/extension-api/types/data-table.ts +2 -2
  51. package/src/lib/framework/extension-api/types/detail-forms.ts +2 -2
  52. package/src/lib/framework/extension-api/types/form-components.ts +2 -2
  53. package/src/lib/framework/extension-api/types/layout.ts +24 -13
  54. package/src/lib/framework/extension-api/types/login.ts +6 -5
  55. package/src/lib/framework/extension-api/types/navigation.ts +3 -3
  56. package/src/lib/framework/extension-api/types/widgets.ts +7 -3
  57. package/src/lib/framework/form-engine/form-engine-types.ts +13 -7
  58. package/src/lib/framework/form-engine/use-generated-form.tsx +44 -0
  59. package/src/lib/framework/layout-engine/page-layout.tsx +94 -31
  60. package/src/lib/framework/page/detail-page.tsx +3 -5
  61. package/src/lib/framework/page/list-page.tsx +87 -5
  62. package/src/lib/framework/page/use-detail-page.ts +4 -5
  63. package/src/lib/graphql/api.ts +2 -2
  64. package/src/lib/graphql/graphql-env.d.ts +7 -16
  65. package/src/lib/hooks/use-auth.tsx +1 -3
  66. package/src/lib/hooks/use-channel.ts +4 -2
  67. package/src/lib/hooks/use-page-block.tsx +9 -0
  68. package/src/lib/hooks/use-permissions.ts +6 -2
  69. package/src/lib/index.ts +2 -0
  70. package/src/lib/providers/auth.tsx +34 -2
  71. package/src/lib/providers/channel-provider.tsx +22 -1
  72. package/src/lib/components/shared/table-cell/table-cell-types.ts +0 -33
@@ -2,6 +2,13 @@ import { Checkbox } from '../ui/checkbox.js';
2
2
  import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
3
3
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
4
4
 
5
+ /**
6
+ * @description
7
+ * Displays a boolean value as a checkbox.
8
+ *
9
+ * @docsCategory form-components
10
+ * @docsPage CheckboxInput
11
+ */
5
12
  export function CheckboxInput({ value, onChange, fieldDef }: Readonly<DashboardFormComponentProps>) {
6
13
  const readOnly = isReadonlyField(fieldDef);
7
14
  return <Checkbox checked={value} onCheckedChange={onChange} disabled={readOnly} />;
@@ -12,6 +12,13 @@ import { cn } from '@/vdb/lib/utils.js';
12
12
  import { CalendarClock } from 'lucide-react';
13
13
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
14
14
 
15
+ /**
16
+ * @description
17
+ * A component for selecting a date and time.
18
+ *
19
+ * @docsCategory form-components
20
+ * @docsPage DateTimeInput
21
+ */
15
22
  export function DateTimeInput({ value, onChange, fieldDef }: Readonly<DashboardFormComponentProps>) {
16
23
  const readOnly = isReadonlyField(fieldDef);
17
24
  const date = value && value instanceof Date ? value.toISOString() : (value ?? '');
@@ -11,6 +11,14 @@ export interface MoneyInputProps extends DashboardFormComponentProps {
11
11
  currency?: string;
12
12
  }
13
13
 
14
+ /**
15
+ * @description
16
+ * A component for displaying a money value. The `currency` can be specified, but otherwise
17
+ * will be taken from the active channel's default currency.
18
+ *
19
+ * @docsCategory form-components
20
+ * @docsPage MoneyInput
21
+ */
14
22
  export function MoneyInput(props: Readonly<MoneyInputProps>) {
15
23
  const { value, onChange, currency, ...rest } = props;
16
24
  const { activeChannel } = useChannel();
@@ -4,6 +4,13 @@ import { Input } from '@/vdb/components/ui/input.js';
4
4
  import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
5
5
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
6
6
 
7
+ /**
8
+ * @description
9
+ * A component for displaying a numeric value.
10
+ *
11
+ * @docsCategory form-components
12
+ * @docsPage NumberInput
13
+ */
7
14
  export function NumberInput({ fieldDef, onChange, ...fieldProps }: Readonly<DashboardFormComponentProps>) {
8
15
  const readOnly = fieldProps.disabled || isReadonlyField(fieldDef);
9
16
  const isFloat = fieldDef ? fieldDef.type === 'float' : false;
@@ -2,6 +2,13 @@ import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-en
2
2
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
3
3
  import { Input } from '../ui/input.js';
4
4
 
5
+ /**
6
+ * @description
7
+ * A component for displaying a password input.
8
+ *
9
+ * @docsCategory form-components
10
+ * @docsPage PasswordInput
11
+ */
5
12
  export function PasswordInput(props: Readonly<DashboardFormComponentProps>) {
6
13
  const readOnly = props.disabled || isReadonlyField(props.fieldDef);
7
14
  return (
@@ -22,6 +22,13 @@ const extensions = [
22
22
  }),
23
23
  ];
24
24
 
25
+ /**
26
+ * @description
27
+ * A component for displaying a rich text editor. Internally uses ProseMirror (rich text editor) under the hood.
28
+ *
29
+ * @docsCategory form-components
30
+ * @docsPage RichTextInput
31
+ */
25
32
  export function RichTextInput({ value, onChange, fieldDef }: Readonly<DashboardFormComponentProps>) {
26
33
  const readOnly = isReadonlyField(fieldDef);
27
34
  const isInternalUpdate = useRef(false);
@@ -3,6 +3,13 @@ import { Input } from '@/vdb/components/ui/input.js';
3
3
  import { DashboardFormComponent } from '@/vdb/framework/form-engine/form-engine-types.js';
4
4
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
5
5
 
6
+ /**
7
+ * @description
8
+ * A component for displaying a text input.
9
+ *
10
+ * @docsCategory form-components
11
+ * @docsPage TextInput
12
+ */
6
13
  export const TextInput: DashboardFormComponent = ({ value, onChange, fieldDef }) => {
7
14
  const readOnly = isReadonlyField(fieldDef);
8
15
  return <Input value={value || ''} onChange={e => onChange(e.target.value)} disabled={readOnly} />;
@@ -2,6 +2,13 @@ import { Textarea } from '@/vdb/components/ui/textarea.js';
2
2
  import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
3
3
  import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
4
4
 
5
+ /**
6
+ * @description
7
+ * A component for displaying a textarea input.
8
+ *
9
+ * @docsCategory form-components
10
+ * @docsPage TextareaInput
11
+ */
5
12
  export function TextareaInput(props: Readonly<DashboardFormComponentProps>) {
6
13
  const readOnly = props.disabled || isReadonlyField(props.fieldDef);
7
14
  return (
@@ -16,6 +16,7 @@ import {
16
16
  DropdownMenuSeparator,
17
17
  DropdownMenuTrigger,
18
18
  } from '@/vdb/components/ui/dropdown-menu.js';
19
+ import { ScrollArea } from '@/vdb/components/ui/scroll-area.js';
19
20
  import { usePage } from '@/vdb/hooks/use-page.js';
20
21
  import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
21
22
  import { Trans } from '@/vdb/lib/trans.js';
@@ -76,39 +77,41 @@ export function DataTableViewOptions<TData>({ table }: DataTableViewOptionsProps
76
77
 
77
78
  return (
78
79
  <div className="flex items-center gap-2">
79
- <DropdownMenu>
80
+ <DropdownMenu modal={false}>
80
81
  <DropdownMenuTrigger asChild>
81
82
  <Button variant="ghost" size="sm" className="ml-auto hidden h-8 lg:flex">
82
83
  <Settings2 />
83
84
  <Trans>Columns</Trans>
84
85
  </Button>
85
86
  </DropdownMenuTrigger>
86
- <DropdownMenuContent align="end">
87
- <DndContext
88
- collisionDetection={closestCenter}
89
- onDragEnd={handleDragEnd}
90
- modifiers={[restrictToVerticalAxis]}
91
- >
92
- <SortableContext
93
- items={columns.map(col => col.id)}
94
- strategy={verticalListSortingStrategy}
87
+ <DropdownMenuContent align="end" className="overflow-auto">
88
+ <ScrollArea className="max-h-[60vh]" type="always">
89
+ <DndContext
90
+ collisionDetection={closestCenter}
91
+ onDragEnd={handleDragEnd}
92
+ modifiers={[restrictToVerticalAxis]}
95
93
  >
96
- {columns.map(column => (
97
- <SortableItem key={column.id} id={column.id}>
98
- <DropdownMenuCheckboxItem
99
- className="capitalize"
100
- checked={column.getIsVisible()}
101
- onCheckedChange={value => column.toggleVisibility(!!value)}
102
- onSelect={e => e.preventDefault()}
103
- >
104
- {column.id}
105
- </DropdownMenuCheckboxItem>
106
- </SortableItem>
107
- ))}
108
- </SortableContext>
109
- </DndContext>
110
- <DropdownMenuSeparator />
111
- <DropdownMenuItem onClick={handleReset}>Reset</DropdownMenuItem>
94
+ <SortableContext
95
+ items={columns.map(col => col.id)}
96
+ strategy={verticalListSortingStrategy}
97
+ >
98
+ {columns.map(column => (
99
+ <SortableItem key={column.id} id={column.id}>
100
+ <DropdownMenuCheckboxItem
101
+ className="capitalize"
102
+ checked={column.getIsVisible()}
103
+ onCheckedChange={value => column.toggleVisibility(!!value)}
104
+ onSelect={e => e.preventDefault()}
105
+ >
106
+ {column.id}
107
+ </DropdownMenuCheckboxItem>
108
+ </SortableItem>
109
+ ))}
110
+ </SortableContext>
111
+ </DndContext>
112
+ <DropdownMenuSeparator />
113
+ <DropdownMenuItem onClick={handleReset}>Reset</DropdownMenuItem>
114
+ </ScrollArea>
112
115
  </DropdownMenuContent>
113
116
  </DropdownMenu>
114
117
  </div>
@@ -35,6 +35,14 @@ export interface FacetedFilter {
35
35
  options?: DataTableFacetedFilterOption[];
36
36
  }
37
37
 
38
+ /**
39
+ * @description
40
+ * Props for configuring the {@link DataTable}.
41
+ *
42
+ * @docsCategory list-views
43
+ * @docsPage DataTable
44
+ * @since 3.4.0
45
+ */
38
46
  interface DataTableProps<TData> {
39
47
  children?: React.ReactNode;
40
48
  columns: ColumnDef<TData, any>[];
@@ -55,6 +63,7 @@ interface DataTableProps<TData> {
55
63
  disableViewOptions?: boolean;
56
64
  bulkActions?: BulkAction[];
57
65
  /**
66
+ * @description
58
67
  * This property allows full control over _all_ features of TanStack Table
59
68
  * when needed.
60
69
  */
@@ -62,6 +71,17 @@ interface DataTableProps<TData> {
62
71
  onRefresh?: () => void;
63
72
  }
64
73
 
74
+ /**
75
+ * @description
76
+ * A data table which includes sorting, filtering, pagination, bulk actions, column controls etc.
77
+ *
78
+ * This is the building block of all data tables in the Dashboard.
79
+ *
80
+ * @docsCategory list-views
81
+ * @docsPage DataTable
82
+ * @since 3.4.0
83
+ * @docsWeight 0
84
+ */
65
85
  export function DataTable<TData>({
66
86
  children,
67
87
  columns,
@@ -1 +1,40 @@
1
+ import { CellContext } from '@tanstack/table-core';
2
+
1
3
  export type ColumnDataType = 'String' | 'Int' | 'Float' | 'DateTime' | 'Boolean' | 'ID' | 'Money';
4
+
5
+ /**
6
+ * @description
7
+ * This type is used to define re-usable components that can render a table cell in a
8
+ * DataTable.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { DataTableCellComponent } from '\@vendure/dashboard';
13
+ *
14
+ * type CustomerCellData = {
15
+ * customer: {
16
+ * id: string;
17
+ * firstName: string;
18
+ * lastName: string;
19
+ * } | null;
20
+ * };
21
+ *
22
+ * export const CustomerCell: DataTableCellComponent<CustomerCellData> = ({ row }) => {
23
+ * const value = row.original.customer;
24
+ * if (!value) {
25
+ * return null;
26
+ * }
27
+ * return (
28
+ * <Button asChild variant="ghost">
29
+ * <Link to={`/customers/${value.id}`}>
30
+ * {value.firstName} {value.lastName}
31
+ * </Link>
32
+ * </Button>
33
+ * );
34
+ * };
35
+ * ```
36
+ *
37
+ * @docsCategory list-views
38
+ * @since 3.4.0
39
+ */
40
+ export type DataTableCellComponent<T> = <Data extends T>(context: CellContext<Data, any>) => any;
@@ -54,9 +54,7 @@ export function ChannelSwitcher() {
54
54
  setContentLanguage,
55
55
  } = useUserSettings();
56
56
  const [showManageLanguagesDialog, setShowManageLanguagesDialog] = useState(false);
57
-
58
- // Use the selected channel if available, otherwise fall back to the active channel
59
- const displayChannel = activeChannel || activeChannel;
57
+ const displayChannel = activeChannel;
60
58
 
61
59
  // Get available languages from server config
62
60
  const availableLanguages = serverConfig?.availableLanguages || [];
@@ -71,6 +71,13 @@ const AssetType = {
71
71
 
72
72
  export type Asset = AssetFragment;
73
73
 
74
+ /**
75
+ * @description
76
+ * Props for the {@link AssetGallery} component.
77
+ *
78
+ * @docsCategory components
79
+ * @docsPage AssetGallery
80
+ */
74
81
  export interface AssetGalleryProps {
75
82
  onSelect?: (assets: Asset[]) => void;
76
83
  selectable?: boolean;
@@ -82,16 +89,67 @@ export interface AssetGalleryProps {
82
89
  * If set to 'manual', multiple selection will occur only if the user holds down the control/cmd key.
83
90
  */
84
91
  multiSelect?: 'auto' | 'manual';
92
+ /**
93
+ * @description
94
+ * The initial assets that should be selected.
95
+ */
85
96
  initialSelectedAssets?: Asset[];
97
+ /**
98
+ * @description
99
+ * The number of assets to display per page.
100
+ */
86
101
  pageSize?: number;
102
+ /**
103
+ * @description
104
+ * Whether the gallery should have a fixed height.
105
+ */
87
106
  fixedHeight?: boolean;
107
+ /**
108
+ * @description
109
+ * Whether the gallery should show a header.
110
+ */
88
111
  showHeader?: boolean;
112
+ /**
113
+ * @description
114
+ * The class name to apply to the gallery.
115
+ */
89
116
  className?: string;
117
+ /**
118
+ * @description
119
+ * The function to call when files are dropped.
120
+ */
90
121
  onFilesDropped?: (files: File[]) => void;
122
+ /**
123
+ * @description
124
+ * The bulk actions to display in the gallery.
125
+ */
91
126
  bulkActions?: AssetBulkAction[];
127
+ /**
128
+ * @description
129
+ * Whether the gallery should display bulk actions.
130
+ */
92
131
  displayBulkActions?: boolean;
93
132
  }
94
133
 
134
+ /**
135
+ * @description
136
+ * A component for displaying a gallery of assets.
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * <AssetGallery
141
+ onSelect={handleAssetSelect}
142
+ multiSelect="manual"
143
+ initialSelectedAssets={initialSelectedAssets}
144
+ fixedHeight={false}
145
+ displayBulkActions={false}
146
+ />
147
+ * ```
148
+ *
149
+ * @docsCategory components
150
+ * @docsPage AssetGallery
151
+ * @docsWeight 0
152
+ */
95
153
  export function AssetGallery({
96
154
  onSelect,
97
155
  selectable = true,
@@ -9,15 +9,54 @@ import {
9
9
  import { useState } from 'react';
10
10
  import { Asset, AssetGallery } from './asset-gallery.js';
11
11
 
12
+ /**
13
+ * @description
14
+ * Props for the {@link AssetPickerDialog} component.
15
+ *
16
+ * @docsCategory components
17
+ * @docsPage AssetPickerDialog
18
+ */
12
19
  interface AssetPickerDialogProps {
20
+ /**
21
+ * @description
22
+ * Whether the dialog is open.
23
+ */
13
24
  open: boolean;
25
+ /**
26
+ * @description
27
+ * The function to call when the dialog is closed.
28
+ */
14
29
  onClose: () => void;
30
+ /**
31
+ * @description
32
+ * The function to call when assets are selected.
33
+ */
15
34
  onSelect: (assets: Asset[]) => void;
35
+ /**
36
+ * @description
37
+ * Whether multiple assets can be selected.
38
+ */
16
39
  multiSelect?: boolean;
40
+ /**
41
+ * @description
42
+ * The initial assets that should be selected.
43
+ */
17
44
  initialSelectedAssets?: Asset[];
45
+ /**
46
+ * @description
47
+ * The title of the dialog.
48
+ */
18
49
  title?: string;
19
50
  }
20
51
 
52
+ /**
53
+ * @description
54
+ * A dialog which allows the creation and selection of assets.
55
+ *
56
+ * @docsCategory components
57
+ * @docsPage AssetPickerDialog
58
+ * @docsWeight 0
59
+ */
21
60
  export function AssetPickerDialog({
22
61
  open,
23
62
  onClose,
@@ -3,46 +3,32 @@ import { ChevronRight } from 'lucide-react';
3
3
  import { Button } from '../ui/button.js';
4
4
 
5
5
  /**
6
+ * @description
6
7
  * DetailPageButton is a reusable navigation component designed to provide consistent UX
7
8
  * across list views when linking to detail pages. It renders as a ghost button with
8
9
  * a chevron indicator, making it easy for users to identify clickable links that
9
10
  * navigate to detail views.
10
11
  *
11
- * @component
12
12
  * @example
13
+ * ```tsx
13
14
  * // Basic usage with ID (relative navigation)
14
15
  * <DetailPageButton id="123" label="Product Name" />
16
+ *
15
17
  *
16
18
  * @example
19
+ * ```tsx
17
20
  * // Custom href with search params
18
21
  * <DetailPageButton
19
22
  * href="/products/detail/456"
20
23
  * label="Custom Product"
21
24
  * search={{ tab: 'variants' }}
22
25
  * />
26
+ * ```
23
27
  *
24
- * @example
25
- * // Disabled state
26
- * <DetailPageButton
27
- * id="789"
28
- * label="Unavailable Item"
29
- * disabled={true}
30
- * />
31
- *
32
- * @param {Object} props - Component props
33
- * @param {string|React.ReactNode} props.label - The text or content to display in the button
34
- * @param {string} [props.id] - The ID for relative navigation (creates href as `./${id}`)
35
- * @param {string} [props.href] - Custom href for navigation (takes precedence over id)
36
- * @param {boolean} [props.disabled=false] - Whether the button is disabled (prevents navigation)
37
- * @param {Record<string, string>} [props.search] - Search parameters to include in the navigation
38
- *
39
- * @returns {React.ReactElement} A styled button component that navigates to detail pages
40
28
  *
41
- * @remarks
42
- * - Uses TanStack Router's Link component for client-side navigation
43
- * - Includes a chevron icon (hidden when disabled) to indicate navigation
44
- * - Preloading is disabled by default for performance optimization
45
- * - Styled as a ghost button variant for subtle, consistent appearance
29
+ * @docsCategory components
30
+ * @docsPage DetailPageButton
31
+ * @since 3.4.0
46
32
  */
47
33
  export function DetailPageButton({
48
34
  id,
@@ -20,6 +20,13 @@ interface FacetValueChipProps {
20
20
  onRemove?: (id: string) => void;
21
21
  }
22
22
 
23
+ /**
24
+ * @description
25
+ * A component for displaying a facet value as a chip.
26
+ *
27
+ * @docsCategory components
28
+ * @since 3.4.0
29
+ */
23
30
  export function FacetValueChip({
24
31
  facetValue,
25
32
  removable = true,
@@ -29,10 +29,51 @@ export interface Facet {
29
29
  code: string;
30
30
  }
31
31
 
32
+ /**
33
+ * @description
34
+ * A component for selecting facet values.
35
+ *
36
+ * @docsCategory components
37
+ * @docsPage FacetValueSelector
38
+ * @since 3.4.0
39
+ */
32
40
  interface FacetValueSelectorProps {
41
+ /**
42
+ * @description
43
+ * The function to call when a facet value is selected.
44
+ *
45
+ * The `value` will have the following structure:
46
+ *
47
+ * ```ts
48
+ * {
49
+ * id: string;
50
+ * name: string;
51
+ * code: string;
52
+ * facet: {
53
+ * id: string;
54
+ * name: string;
55
+ * code: string;
56
+ * };
57
+ * }
58
+ * ```
59
+ */
33
60
  onValueSelect: (value: FacetValue) => void;
61
+ /**
62
+ * @description
63
+ * Whether the selector is disabled.
64
+ */
34
65
  disabled?: boolean;
66
+ /**
67
+ * @description
68
+ * The placeholder text for the selector.
69
+ */
35
70
  placeholder?: string;
71
+ /**
72
+ * @description
73
+ * The number of facet values to display per page.
74
+ *
75
+ * @default 4
76
+ */
36
77
  pageSize?: number;
37
78
  }
38
79
 
@@ -85,6 +126,20 @@ const getFacetValuesForFacetDocument = graphql(`
85
126
  }
86
127
  `);
87
128
 
129
+ /**
130
+ * @description
131
+ * A component for selecting facet values.
132
+ *
133
+ * @example
134
+ * ```tsx
135
+ * <FacetValueSelector onValueSelect={onValueSelectHandler} disabled={disabled} />
136
+ * ```
137
+ *
138
+ * @docsCategory components
139
+ * @docsPage FacetValueSelector
140
+ * @docsWeight 0
141
+ * @since 3.4.0
142
+ */
88
143
  export function FacetValueSelector({
89
144
  onValueSelect,
90
145
  disabled,
@@ -3,11 +3,27 @@ import { LocationWrapper } from '@/vdb/framework/layout-engine/location-wrapper.
3
3
  import { FieldPath, FieldValues } from 'react-hook-form';
4
4
  import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '../ui/form.js';
5
5
 
6
+ /**
7
+ * @description
8
+ * The props for the FormFieldWrapper component.
9
+ *
10
+ * @docsCategory form-components
11
+ * @docsPage FormFieldWrapper
12
+ * @since 3.4.0
13
+ */
6
14
  export type FormFieldWrapperProps<
7
15
  TFieldValues extends FieldValues = FieldValues,
8
16
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
9
17
  > = React.ComponentProps<typeof FormField<TFieldValues, TName>> & {
18
+ /**
19
+ * @description
20
+ * The label for the form field.
21
+ */
10
22
  label?: React.ReactNode;
23
+ /**
24
+ * @description
25
+ * The description for the form field.
26
+ */
11
27
  description?: React.ReactNode;
12
28
  /**
13
29
  * @description
@@ -15,11 +31,46 @@ export type FormFieldWrapperProps<
15
31
  * If false, the form control will not be rendered.
16
32
  * This is useful when you want to render the form control in a custom way, e.g. for <Select/> components,
17
33
  * where the FormControl needs to nested in the root component.
34
+ *
18
35
  * @default true
19
36
  */
20
37
  renderFormControl?: boolean;
21
38
  };
22
39
 
40
+ /**
41
+ * @description
42
+ * This is a wrapper that can be used in all forms to wrap the actual form control, and provide a label, description and error message.
43
+ *
44
+ * Use this instead of the default Shadcn FormField (etc.) components, as it also supports
45
+ * overridden form components.
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * <PageBlock column="main" blockId="main-form">
50
+ * <DetailFormGrid>
51
+ * <FormFieldWrapper
52
+ * control={form.control}
53
+ * name="description"
54
+ * label={<Trans>Description</Trans>}
55
+ * render={({ field }) => <Input {...field} />}
56
+ * />
57
+ * <FormFieldWrapper
58
+ * control={form.control}
59
+ * name="code"
60
+ * label={<Trans>Code</Trans>}
61
+ * render={({ field }) => <Input {...field} />}
62
+ * />
63
+ * </DetailFormGrid>
64
+ * </PageBlock>
65
+ * ```
66
+ *
67
+ * If you are dealing with translatable fields, use the {@link TranslatableFormFieldWrapper} component instead.
68
+ *
69
+ * @docsCategory form-components
70
+ * @docsPage FormFieldWrapper
71
+ * @docsWeight 0
72
+ * @since 3.4.0
73
+ */
23
74
  export function FormFieldWrapper<
24
75
  TFieldValues extends FieldValues = FieldValues,
25
76
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,