@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.
- package/dist/plugin/tests/barrel-exports.spec.js +1 -1
- package/dist/plugin/vite-plugin-config.js +1 -0
- package/dist/plugin/vite-plugin-dashboard-metadata.d.ts +1 -3
- package/dist/plugin/vite-plugin-dashboard-metadata.js +1 -8
- package/dist/plugin/vite-plugin-tailwind-source.d.ts +7 -0
- package/dist/plugin/vite-plugin-tailwind-source.js +49 -0
- package/dist/plugin/vite-plugin-vendure-dashboard.js +3 -1
- package/package.json +4 -4
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +43 -34
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +2 -5
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +98 -0
- package/src/app/routes/_authenticated/_products/components/assign-to-channel-dialog.tsx +126 -0
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +268 -0
- package/src/app/routes/_authenticated/_products/products.graphql.ts +64 -0
- package/src/app/routes/_authenticated/_products/products.tsx +31 -2
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +14 -9
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +1 -1
- package/src/app/styles.css +3 -0
- package/src/lib/components/data-table/data-table-bulk-action-item.tsx +101 -0
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +89 -0
- package/src/lib/components/data-table/data-table-filter-badge.tsx +16 -8
- package/src/lib/components/data-table/data-table-filter-dialog.tsx +4 -4
- package/src/lib/components/data-table/data-table-pagination.tsx +2 -2
- package/src/lib/components/data-table/data-table.tsx +50 -31
- package/src/lib/components/data-table/human-readable-operator.tsx +3 -3
- package/src/lib/components/shared/assigned-facet-values.tsx +1 -5
- package/src/lib/components/shared/paginated-list-data-table.tsx +47 -11
- package/src/lib/framework/data-table/data-table-extensions.ts +21 -0
- package/src/lib/framework/data-table/data-table-types.ts +25 -0
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +11 -0
- package/src/lib/framework/extension-api/extension-api-types.ts +35 -0
- package/src/lib/framework/form-engine/use-generated-form.tsx +2 -5
- package/src/lib/framework/layout-engine/page-block-provider.tsx +6 -0
- package/src/lib/framework/layout-engine/page-layout.tsx +43 -33
- package/src/lib/framework/page/list-page.tsx +6 -8
- package/src/lib/framework/registry/registry-types.ts +4 -2
- package/src/lib/hooks/use-page-block.tsx +10 -0
- package/src/lib/index.ts +8 -1
- package/vite/tests/barrel-exports.spec.ts +13 -9
- package/vite/vite-plugin-config.ts +1 -0
- package/vite/vite-plugin-dashboard-metadata.ts +1 -9
- package/vite/vite-plugin-tailwind-source.ts +65 -0
- package/vite/vite-plugin-vendure-dashboard.ts +5 -3
- /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({
|
|
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({
|
|
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
|
-
|
|
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
|
-
<
|
|
355
|
-
{
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
387
|
+
children,
|
|
388
|
+
className,
|
|
389
|
+
blockId,
|
|
390
|
+
}: Pick<PageBlockProps, 'children' | 'className' | 'blockId'>) {
|
|
383
391
|
return (
|
|
384
392
|
<LocationWrapper blockId={blockId}>
|
|
385
|
-
<
|
|
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
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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(
|
|
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 {
|
|
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 {
|
|
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(
|
|
135
|
+
dashboardMetadataPlugin(),
|
|
134
136
|
uiConfigPlugin({ adminUiConfig: options.adminUiConfig }),
|
|
135
137
|
...(options.gqlTadaOutputPath
|
|
136
138
|
? [gqlTadaPlugin({ gqlTadaOutputPath: options.gqlTadaOutputPath, tempDir, packageRoot })]
|
|
File without changes
|