@vendure/dashboard 3.3.5-master-202506250724 → 3.3.5-master-202506251305

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 (61) hide show
  1. package/dist/plugin/tests/barrel-exports.spec.js +1 -1
  2. package/dist/plugin/vite-plugin-config.js +1 -0
  3. package/dist/plugin/vite-plugin-dashboard-metadata.d.ts +1 -3
  4. package/dist/plugin/vite-plugin-dashboard-metadata.js +1 -8
  5. package/dist/plugin/vite-plugin-tailwind-source.d.ts +7 -0
  6. package/dist/plugin/vite-plugin-tailwind-source.js +49 -0
  7. package/dist/plugin/vite-plugin-vendure-dashboard.js +3 -1
  8. package/package.json +4 -4
  9. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +1 -1
  10. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +43 -34
  11. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +1 -1
  12. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +1 -1
  13. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +1 -1
  14. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +1 -1
  15. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +1 -1
  16. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +1 -1
  17. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +1 -1
  18. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +2 -5
  19. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +1 -1
  20. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +1 -1
  21. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +98 -0
  22. package/src/app/routes/_authenticated/_products/components/assign-to-channel-dialog.tsx +126 -0
  23. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +268 -0
  24. package/src/app/routes/_authenticated/_products/products.graphql.ts +64 -0
  25. package/src/app/routes/_authenticated/_products/products.tsx +31 -2
  26. package/src/app/routes/_authenticated/_products/products_.$id.tsx +14 -9
  27. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +1 -1
  28. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +1 -1
  29. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +1 -1
  30. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +1 -1
  31. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +1 -1
  32. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +1 -1
  33. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +1 -1
  34. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +1 -1
  35. package/src/app/styles.css +3 -0
  36. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +101 -0
  37. package/src/lib/components/data-table/data-table-bulk-actions.tsx +89 -0
  38. package/src/lib/components/data-table/data-table-filter-badge.tsx +16 -8
  39. package/src/lib/components/data-table/data-table-filter-dialog.tsx +4 -4
  40. package/src/lib/components/data-table/data-table-pagination.tsx +2 -2
  41. package/src/lib/components/data-table/data-table.tsx +50 -31
  42. package/src/lib/components/data-table/human-readable-operator.tsx +3 -3
  43. package/src/lib/components/shared/assigned-facet-values.tsx +1 -5
  44. package/src/lib/components/shared/paginated-list-data-table.tsx +47 -11
  45. package/src/lib/framework/data-table/data-table-extensions.ts +21 -0
  46. package/src/lib/framework/data-table/data-table-types.ts +25 -0
  47. package/src/lib/framework/extension-api/define-dashboard-extension.ts +11 -0
  48. package/src/lib/framework/extension-api/extension-api-types.ts +35 -0
  49. package/src/lib/framework/form-engine/use-generated-form.tsx +2 -5
  50. package/src/lib/framework/layout-engine/page-block-provider.tsx +6 -0
  51. package/src/lib/framework/layout-engine/page-layout.tsx +43 -33
  52. package/src/lib/framework/page/list-page.tsx +6 -8
  53. package/src/lib/framework/registry/registry-types.ts +4 -2
  54. package/src/lib/hooks/use-page-block.tsx +10 -0
  55. package/src/lib/index.ts +8 -1
  56. package/vite/tests/barrel-exports.spec.ts +13 -9
  57. package/vite/vite-plugin-config.ts +1 -0
  58. package/vite/vite-plugin-dashboard-metadata.ts +1 -9
  59. package/vite/vite-plugin-tailwind-source.ts +65 -0
  60. package/vite/vite-plugin-vendure-dashboard.ts +5 -3
  61. /package/src/lib/components/data-table/{data-table-types.ts → types.ts} +0 -0
@@ -0,0 +1,6 @@
1
+ import { PageBlockProps } from '@/framework/layout-engine/page-layout.js';
2
+ import { createContext } from 'react';
3
+
4
+ export type PageBlockContextValue = Pick<PageBlockProps, 'blockId' | 'column' | 'title' | 'description'>;
5
+
6
+ export const PageBlockContext = createContext<PageBlockContextValue | undefined>(undefined);
@@ -1,20 +1,21 @@
1
1
  import { CustomFieldsForm } from '@/components/shared/custom-fields-form.js';
2
+ import { NavigationConfirmation } from '@/components/shared/navigation-confirmation.js';
2
3
  import { PermissionGuard } from '@/components/shared/permission-guard.js';
3
4
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card.js';
4
5
  import { Form } from '@/components/ui/form.js';
5
6
  import { useCustomFieldConfig } from '@/hooks/use-custom-field-config.js';
6
7
  import { usePage } from '@/hooks/use-page.js';
7
8
  import { cn } from '@/lib/utils.js';
8
- import { NavigationConfirmation } from '@/components/shared/navigation-confirmation.js';
9
9
  import { useMediaQuery } from '@uidotdev/usehooks';
10
10
  import React, { ComponentProps } from 'react';
11
11
  import { Control, UseFormReturn } from 'react-hook-form';
12
12
 
13
13
  import { DashboardActionBarItem } from '../extension-api/extension-api-types.js';
14
14
 
15
+ import { PageBlockContext } from '@/framework/layout-engine/page-block-provider.js';
16
+ import { PageContext, PageContextValue } from '@/framework/layout-engine/page-provider.js';
15
17
  import { getDashboardActionBarItems, getDashboardPageBlocks } from './layout-extensions.js';
16
18
  import { LocationWrapper } from './location-wrapper.js';
17
- import { PageContext, PageContextValue } from '@/framework/layout-engine/page-provider.js';
18
19
 
19
20
  export interface PageProps extends ComponentProps<'div'> {
20
21
  pageId?: string;
@@ -45,9 +46,7 @@ export function Page({ children, pageId, entity, form, submitHandler, ...props }
45
46
  const childArray = React.Children.toArray(children);
46
47
 
47
48
  const pageTitle = childArray.find(child => React.isValidElement(child) && child.type === PageTitle);
48
- const pageActionBar = childArray.find(
49
- child => isOfType(child, PageActionBar),
50
- );
49
+ const pageActionBar = childArray.find(child => isOfType(child, PageActionBar));
51
50
 
52
51
  const pageContent = childArray.filter(
53
52
  child => !isOfType(child, PageTitle) && !isOfType(child, PageActionBar),
@@ -73,7 +72,13 @@ export function Page({ children, pageId, entity, form, submitHandler, ...props }
73
72
  );
74
73
  }
75
74
 
76
- function PageContent({ pageHeader, pageContent, form, submitHandler, ...props }: {
75
+ function PageContent({
76
+ pageHeader,
77
+ pageContent,
78
+ form,
79
+ submitHandler,
80
+ ...props
81
+ }: {
77
82
  pageHeader: React.ReactNode;
78
83
  pageContent: React.ReactNode;
79
84
  form?: UseFormReturn<any>;
@@ -94,9 +99,14 @@ function PageContent({ pageHeader, pageContent, form, submitHandler, ...props }:
94
99
  );
95
100
  }
96
101
 
97
- export function PageContentWithOptionalForm({ form, pageHeader, pageContent, submitHandler }: {
102
+ export function PageContentWithOptionalForm({
103
+ form,
104
+ pageHeader,
105
+ pageContent,
106
+ submitHandler,
107
+ }: {
98
108
  form?: UseFormReturn<any>;
99
- pageHeader: React.ReactNode
109
+ pageHeader: React.ReactNode;
100
110
  pageContent: React.ReactNode;
101
111
  submitHandler?: any;
102
112
  }) {
@@ -261,12 +271,8 @@ export function PageTitle({ children }: { children: React.ReactNode }) {
261
271
  export function PageActionBar({ children }: { children: React.ReactNode }) {
262
272
  let childArray = React.Children.toArray(children);
263
273
 
264
- const leftContent = childArray.filter(
265
- child => isOfType(child, PageActionBarLeft),
266
- );
267
- const rightContent = childArray.filter(
268
- child => isOfType(child, PageActionBarRight),
269
- );
274
+ const leftContent = childArray.filter(child => isOfType(child, PageActionBarLeft));
275
+ const rightContent = childArray.filter(child => isOfType(child, PageActionBarRight));
270
276
 
271
277
  return (
272
278
  <div className={cn('flex gap-2', leftContent.length > 0 ? 'justify-between' : 'justify-end')}>
@@ -348,18 +354,20 @@ export type PageBlockProps = {
348
354
  * @docsWeight 0
349
355
  * @since 3.3.0
350
356
  */
351
- export function PageBlock({ children, title, description, className, blockId }: PageBlockProps) {
357
+ export function PageBlock({ children, title, description, className, blockId, column }: PageBlockProps) {
352
358
  return (
353
359
  <LocationWrapper blockId={blockId}>
354
- <Card className={cn('w-full', className)}>
355
- {title || description ? (
356
- <CardHeader>
357
- {title && <CardTitle>{title}</CardTitle>}
358
- {description && <CardDescription>{description}</CardDescription>}
359
- </CardHeader>
360
- ) : null}
361
- <CardContent className={cn(!title ? 'pt-6' : '')}>{children}</CardContent>
362
- </Card>
360
+ <PageBlockContext.Provider value={{ blockId, title, description, column }}>
361
+ <Card className={cn('w-full', className)}>
362
+ {title || description ? (
363
+ <CardHeader>
364
+ {title && <CardTitle>{title}</CardTitle>}
365
+ {description && <CardDescription>{description}</CardDescription>}
366
+ </CardHeader>
367
+ ) : null}
368
+ <CardContent className={cn(!title ? 'pt-6' : '')}>{children}</CardContent>
369
+ </Card>
370
+ </PageBlockContext.Provider>
363
371
  </LocationWrapper>
364
372
  );
365
373
  }
@@ -376,13 +384,15 @@ export function PageBlock({ children, title, description, className, blockId }:
376
384
  * @since 3.3.0
377
385
  */
378
386
  export function FullWidthPageBlock({
379
- children,
380
- className,
381
- blockId,
382
- }: Pick<PageBlockProps, 'children' | 'className' | 'blockId'>) {
387
+ children,
388
+ className,
389
+ blockId,
390
+ }: Pick<PageBlockProps, 'children' | 'className' | 'blockId'>) {
383
391
  return (
384
392
  <LocationWrapper blockId={blockId}>
385
- <div className={cn('w-full', className)}>{children}</div>
393
+ <PageBlockContext.Provider value={{ blockId, column: 'main' }}>
394
+ <div className={cn('w-full', className)}>{children}</div>
395
+ </PageBlockContext.Provider>
386
396
  </LocationWrapper>
387
397
  );
388
398
  }
@@ -398,10 +408,10 @@ export function FullWidthPageBlock({
398
408
  * @since 3.3.0
399
409
  */
400
410
  export function CustomFieldsPageBlock({
401
- column,
402
- entityType,
403
- control,
404
- }: {
411
+ column,
412
+ entityType,
413
+ control,
414
+ }: {
405
415
  column: 'main' | 'side';
406
416
  entityType: string;
407
417
  control: Control<any, any>;
@@ -3,12 +3,13 @@ import {
3
3
  CustomFieldKeysOfItem,
4
4
  CustomizeColumnConfig,
5
5
  FacetedFilterConfig,
6
+ ListQueryFields,
6
7
  ListQueryOptionsShape,
7
8
  ListQueryShape,
8
- ListQueryFields,
9
9
  PaginatedListDataTable,
10
10
  RowAction,
11
11
  } from '@/components/shared/paginated-list-data-table.js';
12
+ import { BulkAction } from '@/framework/data-table/data-table-types.js';
12
13
  import { useUserSettings } from '@/hooks/use-user-settings.js';
13
14
  import { TypedDocumentNode } from '@graphql-typed-document-node/core';
14
15
  import { AnyRoute, AnyRouter, useNavigate } from '@tanstack/react-router';
@@ -16,13 +17,7 @@ import { ColumnFiltersState, SortingState, Table } from '@tanstack/react-table';
16
17
  import { TableOptions } from '@tanstack/table-core';
17
18
 
18
19
  import { addCustomFields } from '../document-introspection/add-custom-fields.js';
19
- import {
20
- FullWidthPageBlock,
21
- Page,
22
- PageActionBar,
23
- PageLayout,
24
- PageTitle,
25
- } from '../layout-engine/page-layout.js';
20
+ import { FullWidthPageBlock, Page, PageActionBar, PageLayout, PageTitle } from '../layout-engine/page-layout.js';
26
21
 
27
22
  /**
28
23
  * @description
@@ -57,6 +52,7 @@ export interface ListPageProps<
57
52
  rowActions?: RowAction<ListQueryFields<T>>[];
58
53
  transformData?: (data: any[]) => any[];
59
54
  setTableOptions?: (table: TableOptions<any>) => TableOptions<any>;
55
+ bulkActions?: BulkAction[];
60
56
  }
61
57
 
62
58
  /**
@@ -93,6 +89,7 @@ export function ListPage<
93
89
  rowActions,
94
90
  transformData,
95
91
  setTableOptions,
92
+ bulkActions,
96
93
  }: ListPageProps<T, U, V, AC>) {
97
94
  const route = typeof routeOrFn === 'function' ? routeOrFn() : routeOrFn;
98
95
  const routeSearch = route.useSearch();
@@ -191,6 +188,7 @@ export function ListPage<
191
188
  }}
192
189
  facetedFilters={facetedFilters}
193
190
  rowActions={rowActions}
191
+ bulkActions={bulkActions}
194
192
  setTableOptions={setTableOptions}
195
193
  transformData={transformData}
196
194
  />
@@ -1,5 +1,8 @@
1
+ import React from 'react';
2
+
1
3
  import { DashboardAlertDefinition } from '../alert/types.js';
2
4
  import { DashboardWidgetDefinition } from '../dashboard-widget/types.js';
5
+ import { BulkAction } from '../data-table/data-table-types.js';
3
6
  import {
4
7
  DashboardActionBarItem,
5
8
  DashboardPageBlockDefinition,
@@ -16,6 +19,5 @@ export interface GlobalRegistryContents {
16
19
  dashboardWidgetRegistry: Map<string, DashboardWidgetDefinition>;
17
20
  dashboardAlertRegistry: Map<string, DashboardAlertDefinition>;
18
21
  customFormComponents: Map<string, React.FunctionComponent<CustomFormComponentInputProps>>;
22
+ bulkActionsRegistry: Map<string, BulkAction[]>;
19
23
  }
20
-
21
- export type GlobalRegistryKey = keyof GlobalRegistryContents;
@@ -0,0 +1,10 @@
1
+ import { PageBlockContext } from '@/framework/layout-engine/page-block-provider.js';
2
+ import { useContext } from 'react';
3
+
4
+ export function usePageBlock() {
5
+ const pageBlock = useContext(PageBlockContext);
6
+ if (!pageBlock) {
7
+ throw new Error('PageBlockProvider not found');
8
+ }
9
+ return pageBlock;
10
+ }
package/src/lib/index.ts CHANGED
@@ -11,12 +11,13 @@ export * from './components/data-input/facet-value-input.js';
11
11
  export * from './components/data-input/money-input.js';
12
12
  export * from './components/data-input/richt-text-input.js';
13
13
  export * from './components/data-table/add-filter-menu.js';
14
+ export * from './components/data-table/data-table-bulk-action-item.js';
15
+ export * from './components/data-table/data-table-bulk-actions.js';
14
16
  export * from './components/data-table/data-table-column-header.js';
15
17
  export * from './components/data-table/data-table-faceted-filter.js';
16
18
  export * from './components/data-table/data-table-filter-badge.js';
17
19
  export * from './components/data-table/data-table-filter-dialog.js';
18
20
  export * from './components/data-table/data-table-pagination.js';
19
- export * from './components/data-table/data-table-types.js';
20
21
  export * from './components/data-table/data-table-view-options.js';
21
22
  export * from './components/data-table/data-table.js';
22
23
  export * from './components/data-table/filters/data-table-boolean-filter.js';
@@ -26,6 +27,7 @@ export * from './components/data-table/filters/data-table-number-filter.js';
26
27
  export * from './components/data-table/filters/data-table-string-filter.js';
27
28
  export * from './components/data-table/human-readable-operator.js';
28
29
  export * from './components/data-table/refresh-button.js';
30
+ export * from './components/data-table/types.js';
29
31
  export * from './components/layout/app-layout.js';
30
32
  export * from './components/layout/app-sidebar.js';
31
33
  export * from './components/layout/channel-switcher.js';
@@ -137,6 +139,8 @@ export * from './framework/dashboard-widget/orders-summary/index.js';
137
139
  export * from './framework/dashboard-widget/orders-summary/order-summary-widget.graphql.js';
138
140
  export * from './framework/dashboard-widget/types.js';
139
141
  export * from './framework/dashboard-widget/widget-extensions.js';
142
+ export * from './framework/data-table/data-table-extensions.js';
143
+ export * from './framework/data-table/data-table-types.js';
140
144
  export * from './framework/defaults.js';
141
145
  export * from './framework/document-introspection/add-custom-fields.js';
142
146
  export * from './framework/document-introspection/get-document-structure.js';
@@ -150,6 +154,7 @@ export * from './framework/form-engine/form-schema-tools.js';
150
154
  export * from './framework/form-engine/use-generated-form.js';
151
155
  export * from './framework/layout-engine/layout-extensions.js';
152
156
  export * from './framework/layout-engine/location-wrapper.js';
157
+ export * from './framework/layout-engine/page-block-provider.js';
153
158
  export * from './framework/layout-engine/page-layout.js';
154
159
  export * from './framework/layout-engine/page-provider.js';
155
160
  export * from './framework/nav-menu/nav-menu-extensions.js';
@@ -164,12 +169,14 @@ export * from './framework/registry/global-registry.js';
164
169
  export * from './framework/registry/registry-types.js';
165
170
  export * from './graphql/api.js';
166
171
  export * from './graphql/fragments.js';
172
+ export * from './graphql/graphql.js';
167
173
  export * from './hooks/use-auth.js';
168
174
  export * from './hooks/use-channel.js';
169
175
  export * from './hooks/use-custom-field-config.js';
170
176
  export * from './hooks/use-grouped-permissions.js';
171
177
  export * from './hooks/use-local-format.js';
172
178
  export * from './hooks/use-mobile.js';
179
+ export * from './hooks/use-page-block.js';
173
180
  export * from './hooks/use-page.js';
174
181
  export * from './hooks/use-permissions.js';
175
182
  export * from './hooks/use-server-config.js';
@@ -4,14 +4,18 @@ import { describe, expect, it } from 'vitest';
4
4
  import { loadVendureConfig } from '../utils/config-loader.js';
5
5
 
6
6
  describe('detecting plugins in barrel exports', () => {
7
- it('should detect plugins in barrel exports', async () => {
8
- const result = await loadVendureConfig({
9
- tempDir: join(__dirname, './__temp'),
10
- vendureConfigPath: join(__dirname, 'barrel-exports', 'vendure-config.ts'),
11
- });
7
+ it(
8
+ 'should detect plugins in barrel exports',
9
+ async () => {
10
+ const result = await loadVendureConfig({
11
+ tempDir: join(__dirname, './__temp'),
12
+ vendureConfigPath: join(__dirname, 'barrel-exports', 'vendure-config.ts'),
13
+ });
12
14
 
13
- expect(result.pluginInfo).toHaveLength(1);
14
- expect(result.pluginInfo[0].name).toBe('MyPlugin');
15
- expect(result.pluginInfo[0].dashboardEntryPath).toBe('./dashboard/index.tsx');
16
- });
15
+ expect(result.pluginInfo).toHaveLength(1);
16
+ expect(result.pluginInfo[0].name).toBe('MyPlugin');
17
+ expect(result.pluginInfo[0].dashboardEntryPath).toBe('./dashboard/index.tsx');
18
+ },
19
+ { timeout: 10_000 },
20
+ );
17
21
  });
@@ -63,6 +63,7 @@ export function viteConfigPlugin({ packageRoot }: { packageRoot: string }): Plug
63
63
  ...(config.optimizeDeps?.include || []),
64
64
  '@/components > recharts',
65
65
  '@/components > react-dropzone',
66
+ '@vendure/common/lib/generated-types',
66
67
  ],
67
68
  };
68
69
  return config;
@@ -12,7 +12,7 @@ const resolvedVirtualModuleId = `\0${virtualModuleId}`;
12
12
  * generates an import statement for each one, wrapped up in a `runDashboardExtensions()`
13
13
  * function which can then be imported and executed in the Dashboard app.
14
14
  */
15
- export function dashboardMetadataPlugin(options: { rootDir: string }): Plugin {
15
+ export function dashboardMetadataPlugin(): Plugin {
16
16
  let configLoaderApi: ConfigLoaderApi;
17
17
  let loadVendureConfigResult: LoadVendureConfigResult;
18
18
  return {
@@ -52,11 +52,3 @@ export function dashboardMetadataPlugin(options: { rootDir: string }): Plugin {
52
52
  },
53
53
  };
54
54
  }
55
-
56
- /**
57
- * Converts an import path to a normalized path relative to the rootDir.
58
- */
59
- function normalizeImportPath(rootDir: string, importPath: string): string {
60
- const relativePath = path.relative(rootDir, importPath).replace(/\\/g, '/');
61
- return relativePath.replace(/\.tsx?$/, '.js');
62
- }
@@ -0,0 +1,65 @@
1
+ import path from 'path';
2
+ import { Plugin } from 'vite';
3
+
4
+ import { LoadVendureConfigResult } from './utils/config-loader.js';
5
+ import { ConfigLoaderApi, getConfigLoaderApi } from './vite-plugin-config-loader.js';
6
+
7
+ /**
8
+ * This Vite plugin transforms the `app/styles.css` file to include a `@source` directive
9
+ * for each dashboard extension's source directory. This allows Tailwind CSS to
10
+ * include styles from these extensions when processing the CSS.
11
+ */
12
+ export function dashboardTailwindSourcePlugin(): Plugin {
13
+ let configLoaderApi: ConfigLoaderApi;
14
+ let loadVendureConfigResult: LoadVendureConfigResult;
15
+ return {
16
+ name: 'vendure:dashboard-tailwind-source',
17
+ // Ensure this plugin runs before Tailwind CSS processing
18
+ enforce: 'pre',
19
+ configResolved({ plugins }) {
20
+ configLoaderApi = getConfigLoaderApi(plugins);
21
+ },
22
+ async transform(src, id) {
23
+ if (/app\/styles.css$/.test(id)) {
24
+ if (!loadVendureConfigResult) {
25
+ loadVendureConfigResult = await configLoaderApi.getVendureConfig();
26
+ }
27
+ const { pluginInfo } = loadVendureConfigResult;
28
+ const dashboardExtensionDirs =
29
+ pluginInfo
30
+ ?.map(
31
+ ({ dashboardEntryPath, pluginPath }) =>
32
+ dashboardEntryPath && path.join(pluginPath, path.dirname(dashboardEntryPath)),
33
+ )
34
+ .filter(x => x != null) ?? [];
35
+ const sources = dashboardExtensionDirs
36
+ .map(extension => {
37
+ return `@source '${extension}';`;
38
+ })
39
+ .join('\n');
40
+
41
+ // Find the line with the specific comment and insert sources after it
42
+ const lines = src.split('\n');
43
+ const sourceCommentIndex = lines.findIndex(line =>
44
+ line.includes(
45
+ '/* @source rules from extensions will be added here by the dashboardTailwindSourcePlugin */',
46
+ ),
47
+ );
48
+
49
+ if (sourceCommentIndex !== -1) {
50
+ // Insert the sources after the comment line
51
+ lines.splice(sourceCommentIndex + 1, 0, sources);
52
+ const modifiedSrc = lines.join('\n');
53
+ return {
54
+ code: modifiedSrc,
55
+ };
56
+ }
57
+
58
+ // If the comment is not found, append sources at the end
59
+ return {
60
+ code: src + '\n' + sources,
61
+ };
62
+ }
63
+ },
64
+ };
65
+ }
@@ -10,9 +10,10 @@ import { configLoaderPlugin } from './vite-plugin-config-loader.js';
10
10
  import { viteConfigPlugin } from './vite-plugin-config.js';
11
11
  import { dashboardMetadataPlugin } from './vite-plugin-dashboard-metadata.js';
12
12
  import { gqlTadaPlugin } from './vite-plugin-gql-tada.js';
13
- import { ThemeVariablesPluginOptions, themeVariablesPlugin } from './vite-plugin-theme.js';
13
+ import { dashboardTailwindSourcePlugin } from './vite-plugin-tailwind-source.js';
14
+ import { themeVariablesPlugin, ThemeVariablesPluginOptions } from './vite-plugin-theme.js';
14
15
  import { transformIndexHtmlPlugin } from './vite-plugin-transform-index.js';
15
- import { UiConfigPluginOptions, uiConfigPlugin } from './vite-plugin-ui-config.js';
16
+ import { uiConfigPlugin, UiConfigPluginOptions } from './vite-plugin-ui-config.js';
16
17
 
17
18
  /**
18
19
  * @description
@@ -121,6 +122,7 @@ export function vendureDashboardPlugin(options: VitePluginVendureDashboardOption
121
122
  // },
122
123
  }),
123
124
  themeVariablesPlugin({ theme: options.theme }),
125
+ dashboardTailwindSourcePlugin(),
124
126
  tailwindcss(),
125
127
  configLoaderPlugin({
126
128
  vendureConfigPath: normalizedVendureConfigPath,
@@ -130,7 +132,7 @@ export function vendureDashboardPlugin(options: VitePluginVendureDashboardOption
130
132
  }),
131
133
  viteConfigPlugin({ packageRoot }),
132
134
  adminApiSchemaPlugin(),
133
- dashboardMetadataPlugin({ rootDir: tempDir }),
135
+ dashboardMetadataPlugin(),
134
136
  uiConfigPlugin({ adminUiConfig: options.adminUiConfig }),
135
137
  ...(options.gqlTadaOutputPath
136
138
  ? [gqlTadaPlugin({ gqlTadaOutputPath: options.gqlTadaOutputPath, tempDir, packageRoot })]