@vendure/dashboard 3.5.0-minor-202510071456 → 3.5.0-minor-202510161257
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/dashboard.plugin.js +1 -1
- package/dist/vite/utils/ast-utils.spec.js +3 -3
- package/dist/vite/vite-plugin-hmr.d.ts +8 -0
- package/dist/vite/vite-plugin-hmr.js +34 -0
- package/dist/vite/vite-plugin-theme.js +6 -6
- package/dist/vite/vite-plugin-transform-index.js +6 -1
- package/dist/vite/vite-plugin-vendure-dashboard.d.ts +31 -4
- package/dist/vite/vite-plugin-vendure-dashboard.js +89 -34
- package/package.json +17 -5
- package/src/app/app-providers.tsx +4 -1
- package/src/app/common/map-faceted-filter-fields.ts +21 -0
- package/src/app/main.tsx +3 -1
- package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_administrators/administrators.tsx +13 -3
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +6 -13
- package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/assets.tsx +17 -1
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -0
- package/src/app/routes/_authenticated/_collections/collections.tsx +5 -0
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +0 -1
- package/src/app/routes/_authenticated/_customers/customers.tsx +9 -5
- package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +0 -6
- package/src/app/routes/_authenticated/_facets/components/facet-value-bulk-actions.tsx +16 -0
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +43 -12
- package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +14 -5
- package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +117 -92
- package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +2 -1
- package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +26 -27
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +5 -3
- package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +6 -9
- package/src/app/routes/_authenticated/_orders/orders.graphql.ts +17 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +48 -281
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +59 -40
- package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +73 -0
- package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +312 -0
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +4 -0
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +0 -6
- package/src/app/routes/_authenticated/_products/products.tsx +6 -2
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +4 -8
- package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +0 -10
- package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_promotions/promotions.tsx +12 -0
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +6 -2
- package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +4 -0
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +4 -10
- package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +2 -2
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +9 -0
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +1 -0
- package/src/app/routes/_authenticated/_zones/zones.graphql.ts +2 -2
- package/src/app/routes/login.tsx +2 -2
- package/src/i18n/locales/ar.po +420 -289
- package/src/i18n/locales/cs.po +420 -289
- package/src/i18n/locales/de.po +420 -289
- package/src/i18n/locales/en.po +420 -289
- package/src/i18n/locales/es.po +420 -289
- package/src/i18n/locales/fa.po +420 -289
- package/src/i18n/locales/fr.po +468 -337
- package/src/i18n/locales/he.po +420 -289
- package/src/i18n/locales/hr.po +420 -289
- package/src/i18n/locales/it.po +420 -289
- package/src/i18n/locales/ja.po +420 -289
- package/src/i18n/locales/nb.po +420 -289
- package/src/i18n/locales/ne.po +420 -289
- package/src/i18n/locales/pl.po +420 -289
- package/src/i18n/locales/pt_BR.po +420 -289
- package/src/i18n/locales/pt_PT.po +420 -289
- package/src/i18n/locales/ru.po +420 -289
- package/src/i18n/locales/sv.po +420 -289
- package/src/i18n/locales/tr.po +420 -289
- package/src/i18n/locales/uk.po +420 -289
- package/src/i18n/locales/zh_Hans.po +420 -289
- package/src/i18n/locales/zh_Hant.po +420 -289
- package/src/lib/components/data-input/affixed-input.stories.tsx +93 -0
- package/src/lib/components/data-input/affixed-input.tsx +5 -2
- package/src/lib/components/data-input/boolean-input.stories.tsx +102 -0
- package/src/lib/components/data-input/checkbox-input.stories.tsx +61 -0
- package/src/lib/components/data-input/datetime-input.stories.tsx +62 -0
- package/src/lib/components/data-input/datetime-input.tsx +27 -13
- package/src/lib/components/data-input/default-relation-input.tsx +18 -12
- package/src/lib/components/data-input/money-input.stories.tsx +88 -0
- package/src/lib/components/data-input/number-input.stories.tsx +103 -0
- package/src/lib/components/data-input/number-input.tsx +10 -4
- package/src/lib/components/data-input/password-input.stories.tsx +65 -0
- package/src/lib/components/data-input/rich-text-input.stories.tsx +92 -0
- package/src/lib/components/data-input/slug-input.stories.tsx +232 -0
- package/src/lib/components/data-input/slug-input.tsx +9 -10
- package/src/lib/components/data-input/text-input.stories.tsx +52 -0
- package/src/lib/components/data-input/textarea-input.stories.tsx +55 -0
- package/src/lib/components/data-table/add-filter-menu.tsx +6 -1
- package/src/lib/components/data-table/column-header-wrapper.tsx +106 -0
- package/src/lib/components/data-table/data-table-bulk-action-item.tsx +11 -9
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
- package/src/lib/components/data-table/data-table-column-header.tsx +17 -14
- package/src/lib/components/data-table/data-table-faceted-filter.tsx +33 -11
- package/src/lib/components/data-table/data-table-filter-badge-editable.tsx +35 -0
- package/src/lib/components/data-table/data-table-filter-badge.tsx +23 -16
- package/src/lib/components/data-table/data-table-filter-dialog.tsx +28 -8
- package/src/lib/components/data-table/data-table-pagination.tsx +23 -7
- package/src/lib/components/data-table/data-table.stories.tsx +249 -0
- package/src/lib/components/data-table/data-table.tsx +37 -9
- package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +79 -34
- package/src/lib/components/data-table/use-generated-columns.tsx +55 -27
- package/src/lib/components/layout/nav-user.tsx +19 -13
- package/src/lib/components/login/login-form.tsx +39 -123
- package/src/lib/components/shared/alerts.tsx +29 -17
- package/src/lib/components/shared/asset/asset-bulk-actions.tsx +3 -3
- package/src/lib/components/shared/asset/asset-gallery.stories.tsx +76 -0
- package/src/lib/components/shared/asset/asset-gallery.tsx +147 -113
- package/src/lib/components/shared/asset/asset-picker-dialog.stories.tsx +58 -0
- package/src/lib/components/shared/customer-group-selector.tsx +5 -2
- package/src/lib/components/shared/detail-page-button.stories.tsx +52 -0
- package/src/lib/components/shared/facet-value-selector.stories.tsx +48 -0
- package/src/lib/components/shared/facet-value-selector.tsx +130 -34
- package/src/lib/components/shared/paginated-list-data-table.stories.tsx +212 -0
- package/src/lib/components/shared/paginated-list-data-table.tsx +12 -12
- package/src/lib/components/shared/permission-guard.stories.tsx +46 -0
- package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +2 -0
- package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +8 -4
- package/src/lib/components/shared/rich-text-editor/rich-text-editor.tsx +1 -0
- package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +40 -0
- package/src/lib/components/shared/vendure-image.stories.tsx +167 -0
- package/src/lib/components/shared/vendure-image.tsx +6 -7
- package/src/lib/components/ui/accordion.stories.tsx +33 -0
- package/src/lib/components/ui/alert-dialog.stories.tsx +48 -0
- package/src/lib/components/ui/alert.stories.tsx +35 -0
- package/src/lib/components/ui/aspect-ratio.stories.tsx +28 -0
- package/src/lib/components/ui/badge.stories.tsx +28 -0
- package/src/lib/components/ui/breadcrumb.stories.tsx +41 -0
- package/src/lib/components/ui/button.stories.tsx +38 -0
- package/src/lib/components/ui/calendar.stories.tsx +22 -0
- package/src/lib/components/ui/card.stories.tsx +28 -0
- package/src/lib/components/ui/carousel.stories.tsx +34 -0
- package/src/lib/components/ui/checkbox.stories.tsx +31 -0
- package/src/lib/components/ui/collapsible.stories.tsx +39 -0
- package/src/lib/components/ui/command.stories.tsx +44 -0
- package/src/lib/components/ui/context-menu.stories.tsx +38 -0
- package/src/lib/components/ui/dialog.stories.tsx +52 -0
- package/src/lib/components/ui/drawer.stories.tsx +50 -0
- package/src/lib/components/ui/dropdown-menu.stories.tsx +41 -0
- package/src/lib/components/ui/hover-card.stories.tsx +38 -0
- package/src/lib/components/ui/input-group.tsx +148 -0
- package/src/lib/components/ui/input-otp.stories.tsx +30 -0
- package/src/lib/components/ui/input.stories.tsx +38 -0
- package/src/lib/components/ui/label.stories.tsx +24 -0
- package/src/lib/components/ui/menubar.stories.tsx +53 -0
- package/src/lib/components/ui/navigation-menu.stories.tsx +54 -0
- package/src/lib/components/ui/pagination.stories.tsx +51 -0
- package/src/lib/components/ui/password-input.stories.tsx +32 -0
- package/src/lib/components/ui/password-input.tsx +33 -0
- package/src/lib/components/ui/popover.stories.tsx +33 -0
- package/src/lib/components/ui/progress.stories.tsx +27 -0
- package/src/lib/components/ui/radio-group.stories.tsx +34 -0
- package/src/lib/components/ui/resizable.stories.tsx +32 -0
- package/src/lib/components/ui/scroll-area.stories.tsx +31 -0
- package/src/lib/components/ui/select.stories.tsx +36 -0
- package/src/lib/components/ui/separator.stories.tsx +35 -0
- package/src/lib/components/ui/sheet.stories.tsx +50 -0
- package/src/lib/components/ui/sidebar-context.ts +16 -0
- package/src/lib/components/ui/sidebar.tsx +2 -13
- package/src/lib/components/ui/skeleton.stories.tsx +26 -0
- package/src/lib/components/ui/slider.stories.tsx +37 -0
- package/src/lib/components/ui/switch.stories.tsx +31 -0
- package/src/lib/components/ui/table.stories.tsx +52 -0
- package/src/lib/components/ui/tabs.stories.tsx +29 -0
- package/src/lib/components/ui/textarea.stories.tsx +32 -0
- package/src/lib/components/ui/toggle-group.stories.tsx +31 -0
- package/src/lib/components/ui/toggle.stories.tsx +39 -0
- package/src/lib/components/ui/tooltip.stories.tsx +30 -0
- package/src/lib/components/ui/tooltip.tsx +2 -2
- package/src/lib/framework/alert/alert-extensions.tsx +0 -11
- package/src/lib/framework/alert/alert-item.tsx +14 -19
- package/src/lib/framework/alert/alerts-indicator.tsx +14 -15
- package/src/lib/framework/alert/search-index-buffer-alert/search-index-buffer-alert.ts +41 -0
- package/src/lib/framework/component-registry/component-registry.tsx +3 -14
- package/src/lib/framework/dashboard-widget/base-widget.tsx +18 -9
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +12 -11
- package/src/lib/framework/defaults.ts +9 -13
- package/src/lib/framework/extension-api/input-component-extensions.tsx +6 -1
- package/src/lib/framework/extension-api/logic/alerts.ts +3 -2
- package/src/lib/framework/extension-api/types/alerts.ts +12 -6
- package/src/lib/framework/extension-api/types/data-table.ts +5 -2
- package/src/lib/framework/extension-api/types/login.ts +0 -21
- package/src/lib/framework/layout-engine/custom-form-page.stories.tsx +344 -0
- package/src/lib/framework/layout-engine/page-layout.tsx +11 -9
- package/src/lib/framework/layout-engine/page.stories.tsx +275 -0
- package/src/lib/framework/nav-menu/nav-menu-extensions.ts +32 -19
- package/src/lib/framework/page/detail-page.stories.tsx +151 -0
- package/src/lib/framework/page/list-page.stories.tsx +217 -0
- package/src/lib/framework/page/list-page.tsx +8 -1
- package/src/lib/graphql/api.ts +18 -1
- package/src/lib/graphql/graphql-env.d.ts +1 -1
- package/src/lib/hooks/use-alerts.ts +84 -0
- package/src/lib/hooks/use-floating-bulk-actions.ts +2 -3
- package/src/lib/index.ts +12 -5
- package/src/lib/providers/alerts-provider.tsx +60 -0
- package/src/lib/providers/theme-provider.tsx +6 -3
|
@@ -4,6 +4,8 @@ import { Badge } from '@/vdb/components/ui/badge.js';
|
|
|
4
4
|
import { Button } from '@/vdb/components/ui/button.js';
|
|
5
5
|
import { useDynamicTranslations } from '@/vdb/hooks/use-dynamic-translations.js';
|
|
6
6
|
import { Link } from '@tanstack/react-router';
|
|
7
|
+
import { ChevronDown, ChevronUp } from 'lucide-react';
|
|
8
|
+
import { useMemo, useState } from 'react';
|
|
7
9
|
|
|
8
10
|
type CustomerCellData = {
|
|
9
11
|
customer: {
|
|
@@ -38,3 +40,41 @@ export const OrderMoneyCell: DataTableCellComponent<{ currencyCode: string }> =
|
|
|
38
40
|
const currencyCode = row.original.currencyCode;
|
|
39
41
|
return <Money value={value} currency={currencyCode} />;
|
|
40
42
|
};
|
|
43
|
+
|
|
44
|
+
export const RichTextDescriptionCell: DataTableCellComponent<{ description: string }> = ({ cell }) => {
|
|
45
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
46
|
+
const value = cell.getValue();
|
|
47
|
+
|
|
48
|
+
// Strip HTML tags and decode HTML entities
|
|
49
|
+
const textContent = useMemo(() => {
|
|
50
|
+
const stripped = value?.replace(/<[^>]*>/g, '') || '';
|
|
51
|
+
const textArea = document.createElement('textarea');
|
|
52
|
+
textArea.innerHTML = stripped;
|
|
53
|
+
return textArea.value;
|
|
54
|
+
}, [value]);
|
|
55
|
+
|
|
56
|
+
const shortLength = 100;
|
|
57
|
+
const maxLength = 500;
|
|
58
|
+
const isTooLong = textContent.length > shortLength;
|
|
59
|
+
|
|
60
|
+
const displayText = isExpanded ? textContent.slice(0, maxLength) : textContent.slice(0, shortLength);
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div>
|
|
64
|
+
<div>
|
|
65
|
+
{displayText}
|
|
66
|
+
{!isExpanded && isTooLong && '...'}
|
|
67
|
+
</div>
|
|
68
|
+
{!isExpanded && isTooLong && (
|
|
69
|
+
<Button onClick={() => setIsExpanded(true)} variant="ghost" size="xs">
|
|
70
|
+
<ChevronDown />
|
|
71
|
+
</Button>
|
|
72
|
+
)}
|
|
73
|
+
{isExpanded && (
|
|
74
|
+
<Button onClick={() => setIsExpanded(false)} variant="ghost" size="xs">
|
|
75
|
+
<ChevronUp />
|
|
76
|
+
</Button>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { withDescription } from '../../../../.storybook/with-description.js';
|
|
3
|
+
import type { AssetLike } from './vendure-image.js';
|
|
4
|
+
import { VendureImage } from './vendure-image.js';
|
|
5
|
+
|
|
6
|
+
// Mock asset data for demonstrations
|
|
7
|
+
const mockAsset: AssetLike = {
|
|
8
|
+
id: '1',
|
|
9
|
+
preview: 'https://demo.vendure.io/assets/preview/ed/chuttersnap-584518-unsplash__preview.jpg',
|
|
10
|
+
name: 'Sample Image',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const mockAssetWithFocalPoint: AssetLike = {
|
|
14
|
+
id: '2',
|
|
15
|
+
preview: 'https://demo.vendure.io/assets/preview/ed/chuttersnap-584518-unsplash__preview.jpg',
|
|
16
|
+
name: 'Image with Focal Point',
|
|
17
|
+
focalPoint: { x: 0.75, y: 0.25 },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const meta = {
|
|
21
|
+
title: 'Components/VendureImage',
|
|
22
|
+
component: VendureImage,
|
|
23
|
+
...withDescription(import.meta.url, './vendure-image.js'),
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: 'centered',
|
|
26
|
+
},
|
|
27
|
+
tags: ['autodocs'],
|
|
28
|
+
argTypes: {
|
|
29
|
+
preset: {
|
|
30
|
+
control: 'select',
|
|
31
|
+
options: ['tiny', 'thumb', 'small', 'medium', 'large', 'full', null],
|
|
32
|
+
description: 'The preset to use for the image',
|
|
33
|
+
},
|
|
34
|
+
mode: {
|
|
35
|
+
control: 'select',
|
|
36
|
+
options: ['crop', 'resize', null],
|
|
37
|
+
description: 'The crop/resize mode to use',
|
|
38
|
+
},
|
|
39
|
+
width: {
|
|
40
|
+
control: 'number',
|
|
41
|
+
description: 'Custom width in pixels',
|
|
42
|
+
},
|
|
43
|
+
height: {
|
|
44
|
+
control: 'number',
|
|
45
|
+
description: 'Custom height in pixels',
|
|
46
|
+
},
|
|
47
|
+
format: {
|
|
48
|
+
control: 'select',
|
|
49
|
+
options: ['jpg', 'jpeg', 'png', 'webp', 'avif', null],
|
|
50
|
+
description: 'The image format',
|
|
51
|
+
},
|
|
52
|
+
quality: {
|
|
53
|
+
control: { type: 'range', min: 1, max: 100, step: 1 },
|
|
54
|
+
description: 'Image quality (1-100)',
|
|
55
|
+
},
|
|
56
|
+
useFocalPoint: {
|
|
57
|
+
control: 'boolean',
|
|
58
|
+
description: 'Whether to use the focal point in crop mode',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
} satisfies Meta<typeof VendureImage>;
|
|
62
|
+
|
|
63
|
+
export default meta;
|
|
64
|
+
type Story = StoryObj<typeof meta>;
|
|
65
|
+
|
|
66
|
+
export const Playground: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
asset: mockAsset,
|
|
69
|
+
preset: 'medium',
|
|
70
|
+
useFocalPoint: true,
|
|
71
|
+
},
|
|
72
|
+
render: args => {
|
|
73
|
+
return <VendureImage {...args} />;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const PresetSizes: Story = {
|
|
78
|
+
render: () => {
|
|
79
|
+
return (
|
|
80
|
+
<div className="space-y-4">
|
|
81
|
+
<div className="space-y-2">
|
|
82
|
+
<div className="text-sm font-medium">Tiny (50x50)</div>
|
|
83
|
+
<VendureImage asset={mockAsset} preset="tiny" />
|
|
84
|
+
</div>
|
|
85
|
+
<div className="space-y-2">
|
|
86
|
+
<div className="text-sm font-medium">Thumb (150x150)</div>
|
|
87
|
+
<VendureImage asset={mockAsset} preset="thumb" />
|
|
88
|
+
</div>
|
|
89
|
+
<div className="space-y-2">
|
|
90
|
+
<div className="text-sm font-medium">Small (300x300)</div>
|
|
91
|
+
<VendureImage asset={mockAsset} preset="small" />
|
|
92
|
+
</div>
|
|
93
|
+
<div className="space-y-2">
|
|
94
|
+
<div className="text-sm font-medium">Medium (500x500)</div>
|
|
95
|
+
<VendureImage asset={mockAsset} preset="medium" />
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const CustomDimensions: Story = {
|
|
103
|
+
render: () => {
|
|
104
|
+
return (
|
|
105
|
+
<div className="space-y-4">
|
|
106
|
+
<div className="space-y-2">
|
|
107
|
+
<div className="text-sm font-medium">200x200 - Crop Mode</div>
|
|
108
|
+
<VendureImage asset={mockAsset} width={200} height={200} mode="crop" />
|
|
109
|
+
</div>
|
|
110
|
+
<div className="space-y-2">
|
|
111
|
+
<div className="text-sm font-medium">300x150 - Crop Mode</div>
|
|
112
|
+
<VendureImage asset={mockAsset} width={300} height={150} mode="crop" />
|
|
113
|
+
</div>
|
|
114
|
+
<div className="space-y-2">
|
|
115
|
+
<div className="text-sm font-medium">200x200 - Resize Mode</div>
|
|
116
|
+
<VendureImage asset={mockAsset} width={200} height={200} mode="resize" />
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const Formats: Story = {
|
|
124
|
+
render: () => {
|
|
125
|
+
return (
|
|
126
|
+
<div className="space-y-4">
|
|
127
|
+
<div className="space-y-2">
|
|
128
|
+
<div className="text-sm font-medium">WebP Format</div>
|
|
129
|
+
<VendureImage asset={mockAsset} preset="thumb" format="webp" />
|
|
130
|
+
</div>
|
|
131
|
+
<div className="space-y-2">
|
|
132
|
+
<div className="text-sm font-medium">AVIF Format</div>
|
|
133
|
+
<VendureImage asset={mockAsset} preset="thumb" format="avif" />
|
|
134
|
+
</div>
|
|
135
|
+
<div className="space-y-2">
|
|
136
|
+
<div className="text-sm font-medium">JPEG Format with Quality 50</div>
|
|
137
|
+
<VendureImage asset={mockAsset} preset="thumb" format="jpeg" quality={50} />
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const Fallbacks: Story = {
|
|
145
|
+
render: () => {
|
|
146
|
+
return (
|
|
147
|
+
<div className="space-y-4">
|
|
148
|
+
<div className="space-y-2">
|
|
149
|
+
<div className="text-sm font-medium">No Asset - Default Placeholder</div>
|
|
150
|
+
<VendureImage asset={null} preset="thumb" />
|
|
151
|
+
</div>
|
|
152
|
+
<div className="space-y-2">
|
|
153
|
+
<div className="text-sm font-medium">No Asset - Custom Fallback</div>
|
|
154
|
+
<VendureImage
|
|
155
|
+
asset={null}
|
|
156
|
+
preset="thumb"
|
|
157
|
+
fallback={
|
|
158
|
+
<div className="w-[150px] h-[150px] bg-gray-200 flex items-center justify-center rounded-sm">
|
|
159
|
+
<span className="text-gray-500">Custom Fallback</span>
|
|
160
|
+
</div>
|
|
161
|
+
}
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
);
|
|
166
|
+
},
|
|
167
|
+
};
|
|
@@ -99,9 +99,9 @@ export interface VendureImageProps extends React.ImgHTMLAttributes<HTMLImageElem
|
|
|
99
99
|
useFocalPoint?: boolean;
|
|
100
100
|
/**
|
|
101
101
|
* @description
|
|
102
|
-
* The fallback to show if no asset is provided. If no fallback is provided,
|
|
102
|
+
* The fallback to show if no asset is provided. If no fallback is provided,
|
|
103
103
|
* a default placeholder will be shown.
|
|
104
|
-
*/
|
|
104
|
+
*/
|
|
105
105
|
fallback?: React.ReactNode;
|
|
106
106
|
/**
|
|
107
107
|
* @description
|
|
@@ -113,9 +113,9 @@ export interface VendureImageProps extends React.ImgHTMLAttributes<HTMLImageElem
|
|
|
113
113
|
/**
|
|
114
114
|
* @description
|
|
115
115
|
* A component for displaying an image from a Vendure asset.
|
|
116
|
-
*
|
|
116
|
+
*
|
|
117
117
|
* Supports the following features:
|
|
118
|
-
*
|
|
118
|
+
*
|
|
119
119
|
* * Presets
|
|
120
120
|
* * Cropping
|
|
121
121
|
* * Resizing
|
|
@@ -123,7 +123,7 @@ export interface VendureImageProps extends React.ImgHTMLAttributes<HTMLImageElem
|
|
|
123
123
|
* * Quality
|
|
124
124
|
* * Focal point
|
|
125
125
|
* * Fallback
|
|
126
|
-
*
|
|
126
|
+
*
|
|
127
127
|
* @example
|
|
128
128
|
* ```tsx
|
|
129
129
|
* <VendureImage
|
|
@@ -154,14 +154,13 @@ export function VendureImage({
|
|
|
154
154
|
ref,
|
|
155
155
|
...imgProps
|
|
156
156
|
}: VendureImageProps) {
|
|
157
|
-
if (!asset) {
|
|
157
|
+
if (!asset || !asset.preview) {
|
|
158
158
|
return fallback ? (
|
|
159
159
|
<>{fallback}</>
|
|
160
160
|
) : (
|
|
161
161
|
<PlaceholderImage preset={preset} width={width} height={height} className={className} />
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
|
-
|
|
165
164
|
// Build the URL with query parameters
|
|
166
165
|
const url = new URL(asset.preview);
|
|
167
166
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Accordion',
|
|
6
|
+
component: Accordion,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
} satisfies Meta<typeof Accordion>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
export const Playground: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<Accordion type="single" collapsible className="w-[400px]">
|
|
19
|
+
<AccordionItem value="item-1">
|
|
20
|
+
<AccordionTrigger>Item 1</AccordionTrigger>
|
|
21
|
+
<AccordionContent>Content for item 1</AccordionContent>
|
|
22
|
+
</AccordionItem>
|
|
23
|
+
<AccordionItem value="item-2">
|
|
24
|
+
<AccordionTrigger>Item 2</AccordionTrigger>
|
|
25
|
+
<AccordionContent>Content for item 2</AccordionContent>
|
|
26
|
+
</AccordionItem>
|
|
27
|
+
<AccordionItem value="item-3">
|
|
28
|
+
<AccordionTrigger>Item 3</AccordionTrigger>
|
|
29
|
+
<AccordionContent>Content for item 3</AccordionContent>
|
|
30
|
+
</AccordionItem>
|
|
31
|
+
</Accordion>
|
|
32
|
+
),
|
|
33
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
AlertDialog,
|
|
5
|
+
AlertDialogAction,
|
|
6
|
+
AlertDialogCancel,
|
|
7
|
+
AlertDialogContent,
|
|
8
|
+
AlertDialogDescription,
|
|
9
|
+
AlertDialogFooter,
|
|
10
|
+
AlertDialogHeader,
|
|
11
|
+
AlertDialogTitle,
|
|
12
|
+
AlertDialogTrigger,
|
|
13
|
+
} from './alert-dialog.js';
|
|
14
|
+
import { Button } from './button.js';
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: 'UI/Alert Dialog',
|
|
18
|
+
component: AlertDialog,
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: 'centered',
|
|
21
|
+
},
|
|
22
|
+
tags: ['autodocs'],
|
|
23
|
+
} satisfies Meta<typeof AlertDialog>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
export const Playground: Story = {
|
|
29
|
+
render: () => (
|
|
30
|
+
<AlertDialog>
|
|
31
|
+
<AlertDialogTrigger asChild>
|
|
32
|
+
<Button variant="destructive">Delete Item</Button>
|
|
33
|
+
</AlertDialogTrigger>
|
|
34
|
+
<AlertDialogContent>
|
|
35
|
+
<AlertDialogHeader>
|
|
36
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
37
|
+
<AlertDialogDescription>
|
|
38
|
+
This action cannot be undone. This will permanently delete your item.
|
|
39
|
+
</AlertDialogDescription>
|
|
40
|
+
</AlertDialogHeader>
|
|
41
|
+
<AlertDialogFooter>
|
|
42
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
43
|
+
<AlertDialogAction>Continue</AlertDialogAction>
|
|
44
|
+
</AlertDialogFooter>
|
|
45
|
+
</AlertDialogContent>
|
|
46
|
+
</AlertDialog>
|
|
47
|
+
),
|
|
48
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { AlertCircle } from 'lucide-react';
|
|
3
|
+
import { Alert, AlertDescription, AlertTitle } from './alert.js';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'UI/Alert',
|
|
7
|
+
component: Alert,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
},
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: 'select',
|
|
15
|
+
options: ['default', 'destructive'],
|
|
16
|
+
description: 'Alert variant',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
} satisfies Meta<typeof Alert>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
|
|
24
|
+
export const Playground: Story = {
|
|
25
|
+
render: args => (
|
|
26
|
+
<Alert {...args} className="w-[400px]">
|
|
27
|
+
<AlertCircle className="h-4 w-4" />
|
|
28
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
29
|
+
<AlertDescription>You can add components to your app using the cli.</AlertDescription>
|
|
30
|
+
</Alert>
|
|
31
|
+
),
|
|
32
|
+
args: {
|
|
33
|
+
variant: 'default',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { AspectRatio } from './aspect-ratio.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Aspect Ratio',
|
|
6
|
+
component: AspectRatio,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
} satisfies Meta<typeof AspectRatio>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
export const Playground: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<div className="w-[400px]">
|
|
19
|
+
<AspectRatio ratio={16 / 9}>
|
|
20
|
+
<img
|
|
21
|
+
src="https://images.unsplash.com/photo-1588345921523-c2dcdb7f1dcd?w=800&dpr=2&q=80"
|
|
22
|
+
alt="Photo"
|
|
23
|
+
className="rounded-md object-cover w-full h-full"
|
|
24
|
+
/>
|
|
25
|
+
</AspectRatio>
|
|
26
|
+
</div>
|
|
27
|
+
),
|
|
28
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Badge } from './badge.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Badge',
|
|
6
|
+
component: Badge,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
variant: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
options: ['default', 'secondary', 'destructive', 'outline'],
|
|
15
|
+
description: 'Badge variant',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
} satisfies Meta<typeof Badge>;
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof meta>;
|
|
22
|
+
|
|
23
|
+
export const Playground: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
variant: 'default',
|
|
26
|
+
children: 'Badge',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import {
|
|
3
|
+
Breadcrumb,
|
|
4
|
+
BreadcrumbItem,
|
|
5
|
+
BreadcrumbLink,
|
|
6
|
+
BreadcrumbList,
|
|
7
|
+
BreadcrumbPage,
|
|
8
|
+
BreadcrumbSeparator,
|
|
9
|
+
} from './breadcrumb.js';
|
|
10
|
+
|
|
11
|
+
const meta = {
|
|
12
|
+
title: 'UI/Breadcrumb',
|
|
13
|
+
component: Breadcrumb,
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: 'centered',
|
|
16
|
+
},
|
|
17
|
+
tags: ['autodocs'],
|
|
18
|
+
} satisfies Meta<typeof Breadcrumb>;
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof meta>;
|
|
22
|
+
|
|
23
|
+
export const Playground: Story = {
|
|
24
|
+
render: () => (
|
|
25
|
+
<Breadcrumb>
|
|
26
|
+
<BreadcrumbList>
|
|
27
|
+
<BreadcrumbItem>
|
|
28
|
+
<BreadcrumbLink href="/">Home</BreadcrumbLink>
|
|
29
|
+
</BreadcrumbItem>
|
|
30
|
+
<BreadcrumbSeparator />
|
|
31
|
+
<BreadcrumbItem>
|
|
32
|
+
<BreadcrumbLink href="/products">Products</BreadcrumbLink>
|
|
33
|
+
</BreadcrumbItem>
|
|
34
|
+
<BreadcrumbSeparator />
|
|
35
|
+
<BreadcrumbItem>
|
|
36
|
+
<BreadcrumbPage>Current Page</BreadcrumbPage>
|
|
37
|
+
</BreadcrumbItem>
|
|
38
|
+
</BreadcrumbList>
|
|
39
|
+
</Breadcrumb>
|
|
40
|
+
),
|
|
41
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Button } from './button.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Button',
|
|
6
|
+
component: Button,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
variant: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
|
|
15
|
+
description: 'Button variant',
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
control: 'select',
|
|
19
|
+
options: ['default', 'sm', 'lg', 'icon'],
|
|
20
|
+
description: 'Button size',
|
|
21
|
+
},
|
|
22
|
+
disabled: {
|
|
23
|
+
control: 'boolean',
|
|
24
|
+
description: 'Whether the button is disabled',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
} satisfies Meta<typeof Button>;
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Playground: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
variant: 'default',
|
|
35
|
+
size: 'default',
|
|
36
|
+
children: 'Button',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Calendar } from './calendar.js';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'UI/Calendar',
|
|
7
|
+
component: Calendar,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
},
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
} satisfies Meta<typeof Calendar>;
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof meta>;
|
|
16
|
+
|
|
17
|
+
export const Playground: Story = {
|
|
18
|
+
render: () => {
|
|
19
|
+
const [date, setDate] = useState<Date | undefined>(new Date());
|
|
20
|
+
return <Calendar mode="single" selected={date} onSelect={setDate} className="rounded-md border" />;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './card.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Card',
|
|
6
|
+
component: Card,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
} satisfies Meta<typeof Card>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
export const Playground: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<Card className="w-[350px]">
|
|
19
|
+
<CardHeader>
|
|
20
|
+
<CardTitle>Card Title</CardTitle>
|
|
21
|
+
<CardDescription>Card description goes here</CardDescription>
|
|
22
|
+
</CardHeader>
|
|
23
|
+
<CardContent>
|
|
24
|
+
<p>Card content goes here</p>
|
|
25
|
+
</CardContent>
|
|
26
|
+
</Card>
|
|
27
|
+
),
|
|
28
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from './carousel.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Carousel',
|
|
6
|
+
component: Carousel,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
} satisfies Meta<typeof Carousel>;
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
15
|
+
|
|
16
|
+
export const Playground: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<Carousel className="w-full max-w-xs">
|
|
19
|
+
<CarouselContent>
|
|
20
|
+
{Array.from({ length: 5 }).map((_, index) => (
|
|
21
|
+
<CarouselItem key={index}>
|
|
22
|
+
<div className="p-1">
|
|
23
|
+
<div className="flex aspect-square items-center justify-center p-6 border rounded-lg">
|
|
24
|
+
<span className="text-4xl font-semibold">{index + 1}</span>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</CarouselItem>
|
|
28
|
+
))}
|
|
29
|
+
</CarouselContent>
|
|
30
|
+
<CarouselPrevious />
|
|
31
|
+
<CarouselNext />
|
|
32
|
+
</Carousel>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Checkbox } from './checkbox.js';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/Checkbox',
|
|
6
|
+
component: Checkbox,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
disabled: {
|
|
13
|
+
control: 'boolean',
|
|
14
|
+
description: 'Whether the checkbox is disabled',
|
|
15
|
+
},
|
|
16
|
+
checked: {
|
|
17
|
+
control: 'boolean',
|
|
18
|
+
description: 'Whether the checkbox is checked',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof Checkbox>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
export const Playground: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
checked: false,
|
|
29
|
+
disabled: false,
|
|
30
|
+
},
|
|
31
|
+
};
|