@enadhq/enad-react-sdk 1.1.0 → 1.3.0
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/client/cart/components/cart-drawer.mjs +3 -3
- package/dist/client/cart/components/cart-drawer.mjs.map +1 -1
- package/dist/client/cart/components/cart-trigger.mjs +1 -1
- package/dist/client/cart/components/cart-trigger.mjs.map +1 -1
- package/dist/client/storefront/blocks/card-video.mjs +1 -1
- package/dist/client/storefront/blocks/card-video.mjs.map +1 -1
- package/dist/client/storefront/blocks/gallery-with-link-blocks.d.ts.map +1 -1
- package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs +13 -5
- package/dist/client/storefront/blocks/gallery-with-link-blocks.mjs.map +1 -1
- package/dist/client/storefront/blocks/gallery.d.ts +10 -1
- package/dist/client/storefront/blocks/gallery.d.ts.map +1 -1
- package/dist/client/storefront/blocks/gallery.mjs +51 -27
- package/dist/client/storefront/blocks/gallery.mjs.map +1 -1
- package/dist/client/storefront/blocks/hero.d.ts +12 -1
- package/dist/client/storefront/blocks/hero.d.ts.map +1 -1
- package/dist/client/storefront/blocks/hero.mjs +143 -145
- package/dist/client/storefront/blocks/hero.mjs.map +1 -1
- package/dist/client/storefront/blocks/link-block-small.d.ts.map +1 -1
- package/dist/client/storefront/blocks/link-block-small.mjs +1 -1
- package/dist/client/storefront/blocks/link-block-small.mjs.map +1 -1
- package/dist/client/storefront/blocks/link-block.d.ts.map +1 -1
- package/dist/client/storefront/blocks/link-block.mjs +4 -4
- package/dist/client/storefront/blocks/link-block.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-card-parts.d.ts +1 -1
- package/dist/client/storefront/blocks/product-card-parts.d.ts.map +1 -1
- package/dist/client/storefront/blocks/product-card-parts.mjs +2 -2
- package/dist/client/storefront/blocks/product-card-parts.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-card.d.ts +10 -1
- package/dist/client/storefront/blocks/product-card.d.ts.map +1 -1
- package/dist/client/storefront/blocks/product-card.mjs +122 -116
- package/dist/client/storefront/blocks/product-card.mjs.map +1 -1
- package/dist/client/storefront/blocks/product-image.mjs +2 -2
- package/dist/client/storefront/blocks/product-image.mjs.map +1 -1
- package/dist/client/storefront/blocks/text-content-with-image.d.ts +14 -1
- package/dist/client/storefront/blocks/text-content-with-image.d.ts.map +1 -1
- package/dist/client/storefront/blocks/text-content-with-image.mjs +141 -164
- package/dist/client/storefront/blocks/text-content-with-image.mjs.map +1 -1
- package/dist/client/storefront/carousel/swipeable-carousel.d.ts +5 -1
- package/dist/client/storefront/carousel/swipeable-carousel.d.ts.map +1 -1
- package/dist/client/storefront/carousel/swipeable-carousel.mjs +2 -1
- package/dist/client/storefront/carousel/swipeable-carousel.mjs.map +1 -1
- package/dist/client/storefront/checkout/cart-summary.mjs +1 -1
- package/dist/client/storefront/checkout/cart-summary.mjs.map +1 -1
- package/dist/client/storefront/components/language-selector.d.ts.map +1 -1
- package/dist/client/storefront/components/language-selector.mjs +1 -1
- package/dist/client/storefront/components/language-selector.mjs.map +1 -1
- package/dist/client/storefront/components/product-recommendations.d.ts.map +1 -1
- package/dist/client/storefront/components/product-recommendations.mjs +29 -37
- package/dist/client/storefront/components/product-recommendations.mjs.map +1 -1
- package/dist/client/storefront/filters/filter-chip.d.ts +5 -2
- package/dist/client/storefront/filters/filter-chip.d.ts.map +1 -1
- package/dist/client/storefront/filters/filter-chip.mjs +6 -4
- package/dist/client/storefront/filters/filter-chip.mjs.map +1 -1
- package/dist/client/storefront/filters/filter-panel.mjs +2 -2
- package/dist/client/storefront/filters/filter-panel.mjs.map +1 -1
- package/dist/client/storefront/filters/toggle-list-view.mjs +1 -1
- package/dist/client/storefront/filters/toggle-list-view.mjs.map +1 -1
- package/dist/client/storefront/index.d.ts +12 -1
- package/dist/client/storefront/index.mjs +12 -1
- package/dist/client/storefront/layout/header.d.ts.map +1 -1
- package/dist/client/storefront/layout/header.mjs +1 -1
- package/dist/client/storefront/layout/header.mjs.map +1 -1
- package/dist/client/storefront/layout/mobile-menu-drawer.mjs +1 -1
- package/dist/client/storefront/layout/promotion-bar.d.ts.map +1 -1
- package/dist/client/storefront/layout/promotion-bar.mjs +3 -3
- package/dist/client/storefront/layout/promotion-bar.mjs.map +1 -1
- package/dist/client/storefront/primitives/block-heading.d.ts +40 -0
- package/dist/client/storefront/primitives/block-heading.d.ts.map +1 -0
- package/dist/client/storefront/primitives/block-heading.mjs +43 -0
- package/dist/client/storefront/primitives/block-heading.mjs.map +1 -0
- package/dist/client/storefront/primitives/button.d.ts +2 -2
- package/dist/client/storefront/primitives/button.d.ts.map +1 -1
- package/dist/client/storefront/primitives/button.mjs +4 -4
- package/dist/client/storefront/primitives/button.mjs.map +1 -1
- package/dist/client/storefront/primitives/cta-group.d.ts +25 -0
- package/dist/client/storefront/primitives/cta-group.d.ts.map +1 -0
- package/dist/client/storefront/primitives/cta-group.mjs +27 -0
- package/dist/client/storefront/primitives/cta-group.mjs.map +1 -0
- package/dist/client/storefront/primitives/image-with-hover.d.ts +18 -0
- package/dist/client/storefront/primitives/image-with-hover.d.ts.map +1 -0
- package/dist/client/storefront/primitives/image-with-hover.mjs +16 -0
- package/dist/client/storefront/primitives/image-with-hover.mjs.map +1 -0
- package/dist/client/storefront/primitives/index.d.ts +4 -1
- package/dist/client/storefront/primitives/index.mjs +4 -1
- package/dist/client/storefront/primitives/input.d.ts +1 -1
- package/dist/client/storefront/primitives/input.mjs.map +1 -1
- package/dist/client/storefront/primitives/pagination.mjs +2 -2
- package/dist/client/storefront/primitives/pagination.mjs.map +1 -1
- package/dist/client/storefront/product/quantity-picker.mjs +2 -2
- package/dist/client/storefront/product/quantity-picker.mjs.map +1 -1
- package/dist/client/storefront/types.d.ts +1 -1
- package/dist/client/storefront/types.d.ts.map +1 -1
- package/dist/client/storefront/types.mjs.map +1 -1
- package/dist/client/theme/apply.d.ts +1 -1
- package/dist/client/theme/apply.d.ts.map +1 -1
- package/dist/client/theme/apply.mjs +0 -12
- package/dist/client/theme/apply.mjs.map +1 -1
- package/dist/client/theme/cli.mjs +0 -16
- package/dist/client/theme/cli.mjs.map +1 -1
- package/dist/client/theme/codec.d.ts.map +1 -1
- package/dist/client/theme/codec.mjs +0 -2
- package/dist/client/theme/codec.mjs.map +1 -1
- package/dist/client/theme/defaults.d.ts +0 -2
- package/dist/client/theme/defaults.mjs +0 -2
- package/dist/client/theme/defaults.mjs.map +1 -1
- package/dist/client/ui/accordion.d.ts +12 -1
- package/dist/client/ui/accordion.d.ts.map +1 -1
- package/dist/client/ui/accordion.mjs +23 -5
- package/dist/client/ui/accordion.mjs.map +1 -1
- package/dist/client/ui/alert.d.ts +16 -7
- package/dist/client/ui/alert.d.ts.map +1 -1
- package/dist/client/ui/alert.mjs +21 -8
- package/dist/client/ui/alert.mjs.map +1 -1
- package/dist/client/ui/avatar.d.ts +10 -1
- package/dist/client/ui/avatar.d.ts.map +1 -1
- package/dist/client/ui/avatar.mjs +18 -4
- package/dist/client/ui/avatar.mjs.map +1 -1
- package/dist/client/ui/breadcrumb.d.ts +13 -1
- package/dist/client/ui/breadcrumb.d.ts.map +1 -1
- package/dist/client/ui/breadcrumb.mjs +27 -7
- package/dist/client/ui/breadcrumb.mjs.map +1 -1
- package/dist/client/ui/button.d.ts +28 -10
- package/dist/client/ui/button.d.ts.map +1 -1
- package/dist/client/ui/button.mjs +45 -20
- package/dist/client/ui/button.mjs.map +1 -1
- package/dist/client/ui/card.d.ts +20 -1
- package/dist/client/ui/card.d.ts.map +1 -1
- package/dist/client/ui/card.mjs +36 -8
- package/dist/client/ui/card.mjs.map +1 -1
- package/dist/client/ui/carousel.d.ts +9 -1
- package/dist/client/ui/carousel.d.ts.map +1 -1
- package/dist/client/ui/carousel.mjs +20 -4
- package/dist/client/ui/carousel.mjs.map +1 -1
- package/dist/client/ui/checkbox.d.ts +9 -1
- package/dist/client/ui/checkbox.d.ts.map +1 -1
- package/dist/client/ui/checkbox.mjs +12 -3
- package/dist/client/ui/checkbox.mjs.map +1 -1
- package/dist/client/ui/dialog.d.ts +13 -1
- package/dist/client/ui/dialog.d.ts.map +1 -1
- package/dist/client/ui/dialog.mjs +27 -7
- package/dist/client/ui/dialog.mjs.map +1 -1
- package/dist/client/ui/hover-card.d.ts +6 -1
- package/dist/client/ui/hover-card.d.ts.map +1 -1
- package/dist/client/ui/hover-card.mjs +4 -2
- package/dist/client/ui/hover-card.mjs.map +1 -1
- package/dist/client/ui/input.d.ts +20 -7
- package/dist/client/ui/input.d.ts.map +1 -1
- package/dist/client/ui/input.mjs +33 -9
- package/dist/client/ui/input.mjs.map +1 -1
- package/dist/client/ui/label.d.ts +6 -1
- package/dist/client/ui/label.d.ts.map +1 -1
- package/dist/client/ui/label.mjs +4 -2
- package/dist/client/ui/label.mjs.map +1 -1
- package/dist/client/ui/navigation-menu.d.ts +20 -3
- package/dist/client/ui/navigation-menu.d.ts.map +1 -1
- package/dist/client/ui/navigation-menu.mjs +34 -12
- package/dist/client/ui/navigation-menu.mjs.map +1 -1
- package/dist/client/ui/pagination.d.ts.map +1 -1
- package/dist/client/ui/pagination.mjs +3 -3
- package/dist/client/ui/pagination.mjs.map +1 -1
- package/dist/client/ui/popover.d.ts +11 -1
- package/dist/client/ui/popover.d.ts.map +1 -1
- package/dist/client/ui/popover.mjs +21 -5
- package/dist/client/ui/popover.mjs.map +1 -1
- package/dist/client/ui/progress.d.ts +9 -1
- package/dist/client/ui/progress.d.ts.map +1 -1
- package/dist/client/ui/progress.mjs +12 -3
- package/dist/client/ui/progress.mjs.map +1 -1
- package/dist/client/ui/select.d.ts +14 -2
- package/dist/client/ui/select.d.ts.map +1 -1
- package/dist/client/ui/select.mjs +35 -9
- package/dist/client/ui/select.mjs.map +1 -1
- package/dist/client/ui/separator.d.ts +6 -1
- package/dist/client/ui/separator.d.ts.map +1 -1
- package/dist/client/ui/separator.mjs +4 -2
- package/dist/client/ui/separator.mjs.map +1 -1
- package/dist/client/ui/sheet.d.ts +13 -1
- package/dist/client/ui/sheet.d.ts.map +1 -1
- package/dist/client/ui/sheet.mjs +35 -7
- package/dist/client/ui/sheet.mjs.map +1 -1
- package/dist/client/ui/slot-wrapper.d.ts +28 -0
- package/dist/client/ui/slot-wrapper.d.ts.map +1 -0
- package/dist/client/ui/slot-wrapper.mjs +38 -0
- package/dist/client/ui/slot-wrapper.mjs.map +1 -0
- package/dist/client/ui/tabs.d.ts +11 -1
- package/dist/client/ui/tabs.d.ts.map +1 -1
- package/dist/client/ui/tabs.mjs +21 -5
- package/dist/client/ui/tabs.mjs.map +1 -1
- package/dist/client/ui/toggle-group.d.ts +7 -4
- package/dist/client/ui/toggle-group.d.ts.map +1 -1
- package/dist/client/ui/toggle-group.mjs +4 -4
- package/dist/client/ui/toggle-group.mjs.map +1 -1
- package/dist/client/ui/toggle.d.ts +17 -8
- package/dist/client/ui/toggle.d.ts.map +1 -1
- package/dist/client/ui/toggle.mjs +11 -9
- package/dist/client/ui/toggle.mjs.map +1 -1
- package/dist/client/ui/tooltip.d.ts +6 -1
- package/dist/client/ui/tooltip.d.ts.map +1 -1
- package/dist/client/ui/tooltip.mjs +4 -2
- package/dist/client/ui/tooltip.mjs.map +1 -1
- package/dist/client/ui-resolver/button.d.ts +3 -4
- package/dist/client/ui-resolver/button.d.ts.map +1 -1
- package/dist/client/ui-resolver/button.mjs +2 -2
- package/dist/client/ui-resolver/button.mjs.map +1 -1
- package/dist/client/ui-resolver/card.d.ts +14 -1
- package/dist/client/ui-resolver/card.d.ts.map +1 -1
- package/dist/client/ui-resolver/card.mjs +3 -2
- package/dist/client/ui-resolver/card.mjs.map +1 -1
- package/dist/client/ui-resolver/context.mjs +1 -1
- package/dist/client/ui-resolver/context.mjs.map +1 -1
- package/dist/client/ui-resolver/index.d.ts +7 -4
- package/dist/client/ui-resolver/index.mjs +8 -6
- package/dist/client/ui-resolver/input.d.ts +3 -4
- package/dist/client/ui-resolver/input.d.ts.map +1 -1
- package/dist/client/ui-resolver/input.mjs +2 -2
- package/dist/client/ui-resolver/input.mjs.map +1 -1
- package/dist/client/ui-resolver/navigation-menu.d.ts +1 -2
- package/dist/client/ui-resolver/navigation-menu.d.ts.map +1 -1
- package/dist/client/ui-resolver/recipe.d.ts +95 -0
- package/dist/client/ui-resolver/recipe.d.ts.map +1 -0
- package/dist/client/ui-resolver/recipe.mjs +134 -0
- package/dist/client/ui-resolver/recipe.mjs.map +1 -0
- package/dist/client/ui-resolver/toggle.d.ts +2 -2
- package/dist/client/ui-resolver/toggle.mjs +2 -2
- package/dist/client/ui-resolver/toggle.mjs.map +1 -1
- package/dist/client/ui-resolver/types.d.ts +14 -0
- package/dist/client/ui-resolver/types.d.ts.map +1 -0
- package/dist/client/ui-resolver/types.mjs +1 -0
- package/dist/client/wishlist/wishlist-drawer.mjs +4 -4
- package/dist/client/wishlist/wishlist-drawer.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { cn } from "../ui/utils.mjs";
|
|
2
|
+
//#region src/client/ui-resolver/recipe.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind-native slot recipe system for compound components.
|
|
5
|
+
*
|
|
6
|
+
* Slot recipes coordinate variant styles across multiple parts of a compound
|
|
7
|
+
* component. Each slot gets its own class string, and variants can target
|
|
8
|
+
* specific slots or all slots at once.
|
|
9
|
+
*
|
|
10
|
+
* CSS variable contract:
|
|
11
|
+
* instance style → [data-component-set] CSS → :root token → hardcoded fallback
|
|
12
|
+
*
|
|
13
|
+
* Component sets override CSS variables in their [data-component-set="..."]
|
|
14
|
+
* blocks. Recipes consume those variables via Tailwind arbitrary values
|
|
15
|
+
* (e.g. h-[var(--enad-button-height)]), so changing the set changes the
|
|
16
|
+
* component's dimensions without touching JS.
|
|
17
|
+
*/
|
|
18
|
+
function matchesCompoundCondition(condition, resolved) {
|
|
19
|
+
for (const key of Object.keys(condition)) {
|
|
20
|
+
if (key === "css") continue;
|
|
21
|
+
const expected = condition[key];
|
|
22
|
+
const actual = resolved[key];
|
|
23
|
+
if (Array.isArray(expected)) {
|
|
24
|
+
if (!expected.includes(actual)) return false;
|
|
25
|
+
} else if (actual !== expected) return false;
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a slot recipe for compound components.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const cardRecipe = defineSlotRecipe({
|
|
35
|
+
* slots: ["root", "header", "content", "footer"] as const,
|
|
36
|
+
* base: {
|
|
37
|
+
* root: "flex flex-col rounded-lg border",
|
|
38
|
+
* header: "grid items-start",
|
|
39
|
+
* content: "px-6",
|
|
40
|
+
* footer: "flex items-center px-6",
|
|
41
|
+
* },
|
|
42
|
+
* variants: {
|
|
43
|
+
* size: {
|
|
44
|
+
* sm: { root: "text-sm", content: "px-4" },
|
|
45
|
+
* md: { root: "text-base" },
|
|
46
|
+
* lg: { root: "text-lg", content: "px-8" },
|
|
47
|
+
* },
|
|
48
|
+
* },
|
|
49
|
+
* defaultVariants: { size: "md" },
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* const classes = cardRecipe({ size: "sm" });
|
|
53
|
+
* // classes.root → "flex flex-col rounded-lg border text-sm"
|
|
54
|
+
* // classes.content → "px-4" (merged via tailwind-merge)
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
function defineSlotRecipe(config) {
|
|
58
|
+
const { slots, base, variants, defaultVariants, compoundVariants } = config;
|
|
59
|
+
return function slotRecipe(props) {
|
|
60
|
+
const resolved = {};
|
|
61
|
+
if (variants) for (const variantKey of Object.keys(variants)) {
|
|
62
|
+
const fromProps = props?.[variantKey];
|
|
63
|
+
const fromDefaults = defaultVariants?.[variantKey];
|
|
64
|
+
resolved[variantKey] = fromProps ?? fromDefaults;
|
|
65
|
+
}
|
|
66
|
+
const result = {};
|
|
67
|
+
for (const slot of slots) {
|
|
68
|
+
const parts = [];
|
|
69
|
+
if (base[slot]) parts.push(base[slot]);
|
|
70
|
+
if (variants) for (const [variantKey, variantValues] of Object.entries(variants)) {
|
|
71
|
+
const value = resolved[variantKey];
|
|
72
|
+
if (value != null && variantValues[value]) {
|
|
73
|
+
const slotClasses = variantValues[value][slot];
|
|
74
|
+
if (slotClasses) parts.push(slotClasses);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (compoundVariants) {
|
|
78
|
+
for (const compound of compoundVariants) if (matchesCompoundCondition(compound, resolved)) {
|
|
79
|
+
const slotClasses = compound.css[slot];
|
|
80
|
+
if (slotClasses) parts.push(slotClasses);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (props?.className?.[slot]) parts.push(props.className[slot]);
|
|
84
|
+
result[slot] = cn(...parts);
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates a single-slot recipe for simple components.
|
|
91
|
+
* Thin wrapper around defineSlotRecipe with a single "root" slot.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const badgeRecipe = defineRecipe({
|
|
96
|
+
* base: "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold",
|
|
97
|
+
* variants: {
|
|
98
|
+
* variant: {
|
|
99
|
+
* solid: "bg-primary text-primary-foreground",
|
|
100
|
+
* soft: "bg-primary/10 text-primary",
|
|
101
|
+
* outlined: "border border-current",
|
|
102
|
+
* },
|
|
103
|
+
* },
|
|
104
|
+
* defaultVariants: { variant: "solid" },
|
|
105
|
+
* });
|
|
106
|
+
*
|
|
107
|
+
* const classes = badgeRecipe({ variant: "soft" });
|
|
108
|
+
* // → "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold bg-primary/10 text-primary"
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
function defineRecipe(config) {
|
|
112
|
+
const { base, variants, defaultVariants, compoundVariants } = config;
|
|
113
|
+
return function singleRecipe(props) {
|
|
114
|
+
const resolved = {};
|
|
115
|
+
const parts = [];
|
|
116
|
+
if (base) parts.push(base);
|
|
117
|
+
if (variants) for (const variantKey of Object.keys(variants)) {
|
|
118
|
+
const fromProps = props?.[variantKey];
|
|
119
|
+
const fromDefaults = defaultVariants?.[variantKey];
|
|
120
|
+
resolved[variantKey] = fromProps ?? fromDefaults;
|
|
121
|
+
const value = resolved[variantKey];
|
|
122
|
+
if (value != null && variants[variantKey]?.[value]) parts.push(variants[variantKey][value]);
|
|
123
|
+
}
|
|
124
|
+
if (compoundVariants) {
|
|
125
|
+
for (const compound of compoundVariants) if (matchesCompoundCondition(compound, resolved)) parts.push(compound.css);
|
|
126
|
+
}
|
|
127
|
+
if (props?.className) parts.push(props.className);
|
|
128
|
+
return cn(...parts);
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
export { defineRecipe, defineSlotRecipe };
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=recipe.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe.mjs","names":[],"sources":["../../../src/client/ui-resolver/recipe.ts"],"sourcesContent":["/**\n * Tailwind-native slot recipe system for compound components.\n *\n * Slot recipes coordinate variant styles across multiple parts of a compound\n * component. Each slot gets its own class string, and variants can target\n * specific slots or all slots at once.\n *\n * CSS variable contract:\n * instance style → [data-component-set] CSS → :root token → hardcoded fallback\n *\n * Component sets override CSS variables in their [data-component-set=\"...\"]\n * blocks. Recipes consume those variables via Tailwind arbitrary values\n * (e.g. h-[var(--enad-button-height)]), so changing the set changes the\n * component's dimensions without touching JS.\n */\n\nimport { cn } from \"../ui/utils\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype SlotClassMap<S extends string> = Partial<Record<S, string>>;\n\ninterface SlotRecipeConfig<\n S extends string,\n V extends Record<string, Record<string, SlotClassMap<S>>>,\n> {\n slots: readonly S[];\n base: SlotClassMap<S>;\n variants?: V;\n defaultVariants?: {\n [K in keyof V]?: keyof V[K];\n };\n compoundVariants?: Array<\n {\n [K in keyof V]?: keyof V[K] | Array<keyof V[K]>;\n } & {\n css: SlotClassMap<S>;\n }\n >;\n}\n\ntype VariantProps<V extends Record<string, Record<string, unknown>>> = {\n [K in keyof V]?: keyof V[K];\n};\n\ntype SlotRecipeResult<S extends string> = Record<S, string>;\n\ninterface RecipeConfig<V extends Record<string, Record<string, string>>> {\n base?: string;\n variants?: V;\n defaultVariants?: {\n [K in keyof V]?: keyof V[K];\n };\n compoundVariants?: Array<\n {\n [K in keyof V]?: keyof V[K] | Array<keyof V[K]>;\n } & {\n css: string;\n }\n >;\n}\n\n// ---------------------------------------------------------------------------\n// Compound variant matching\n// ---------------------------------------------------------------------------\n\nfunction matchesCompoundCondition(\n condition: Record<string, unknown>,\n resolved: Record<string, unknown>,\n): boolean {\n for (const key of Object.keys(condition)) {\n if (key === \"css\") continue;\n const expected = condition[key];\n const actual = resolved[key];\n if (Array.isArray(expected)) {\n if (!expected.includes(actual as never)) return false;\n } else if (actual !== expected) {\n return false;\n }\n }\n return true;\n}\n\n// ---------------------------------------------------------------------------\n// defineSlotRecipe\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a slot recipe for compound components.\n *\n * @example\n * ```ts\n * const cardRecipe = defineSlotRecipe({\n * slots: [\"root\", \"header\", \"content\", \"footer\"] as const,\n * base: {\n * root: \"flex flex-col rounded-lg border\",\n * header: \"grid items-start\",\n * content: \"px-6\",\n * footer: \"flex items-center px-6\",\n * },\n * variants: {\n * size: {\n * sm: { root: \"text-sm\", content: \"px-4\" },\n * md: { root: \"text-base\" },\n * lg: { root: \"text-lg\", content: \"px-8\" },\n * },\n * },\n * defaultVariants: { size: \"md\" },\n * });\n *\n * const classes = cardRecipe({ size: \"sm\" });\n * // classes.root → \"flex flex-col rounded-lg border text-sm\"\n * // classes.content → \"px-4\" (merged via tailwind-merge)\n * ```\n */\nexport function defineSlotRecipe<\n S extends string,\n V extends Record<string, Record<string, SlotClassMap<S>>>,\n>(config: SlotRecipeConfig<S, V>) {\n const { slots, base, variants, defaultVariants, compoundVariants } = config;\n\n return function slotRecipe(\n props?: VariantProps<V> & { className?: SlotClassMap<S> },\n ): SlotRecipeResult<S> {\n const resolved: Record<string, unknown> = {};\n\n // Resolve variant values: props override defaults\n if (variants) {\n for (const variantKey of Object.keys(variants)) {\n const fromProps = props?.[variantKey as keyof typeof props];\n const fromDefaults = defaultVariants?.[variantKey as keyof typeof defaultVariants];\n resolved[variantKey] = fromProps ?? fromDefaults;\n }\n }\n\n // Build class string for each slot\n const result = {} as Record<S, string>;\n\n for (const slot of slots) {\n const parts: string[] = [];\n\n // Base classes for this slot\n if (base[slot]) {\n parts.push(base[slot]);\n }\n\n // Variant classes for this slot\n if (variants) {\n for (const [variantKey, variantValues] of Object.entries(variants)) {\n const value = resolved[variantKey] as string | undefined;\n if (value != null && variantValues[value]) {\n const slotClasses = variantValues[value][slot];\n if (slotClasses) {\n parts.push(slotClasses);\n }\n }\n }\n }\n\n // Compound variant classes for this slot\n if (compoundVariants) {\n for (const compound of compoundVariants) {\n if (matchesCompoundCondition(compound, resolved)) {\n const slotClasses = compound.css[slot];\n if (slotClasses) {\n parts.push(slotClasses);\n }\n }\n }\n }\n\n // Per-slot className overrides from props\n if (props?.className?.[slot]) {\n parts.push(props.className[slot]);\n }\n\n result[slot] = cn(...parts);\n }\n\n return result;\n };\n}\n\n// ---------------------------------------------------------------------------\n// defineRecipe\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a single-slot recipe for simple components.\n * Thin wrapper around defineSlotRecipe with a single \"root\" slot.\n *\n * @example\n * ```ts\n * const badgeRecipe = defineRecipe({\n * base: \"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold\",\n * variants: {\n * variant: {\n * solid: \"bg-primary text-primary-foreground\",\n * soft: \"bg-primary/10 text-primary\",\n * outlined: \"border border-current\",\n * },\n * },\n * defaultVariants: { variant: \"solid\" },\n * });\n *\n * const classes = badgeRecipe({ variant: \"soft\" });\n * // → \"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold bg-primary/10 text-primary\"\n * ```\n */\nexport function defineRecipe<V extends Record<string, Record<string, string>>>(\n config: RecipeConfig<V>,\n) {\n const { base, variants, defaultVariants, compoundVariants } = config;\n\n return function singleRecipe(props?: VariantProps<V> & { className?: string }): string {\n const resolved: Record<string, unknown> = {};\n const parts: string[] = [];\n\n if (base) {\n parts.push(base);\n }\n\n // Resolve variant values: props override defaults\n if (variants) {\n for (const variantKey of Object.keys(variants)) {\n const fromProps = props?.[variantKey as keyof typeof props];\n const fromDefaults = defaultVariants?.[variantKey as keyof typeof defaultVariants];\n resolved[variantKey] = fromProps ?? fromDefaults;\n\n const value = resolved[variantKey] as string | undefined;\n if (value != null && variants[variantKey]?.[value]) {\n parts.push(variants[variantKey][value]);\n }\n }\n }\n\n // Compound variants\n if (compoundVariants) {\n for (const compound of compoundVariants) {\n if (matchesCompoundCondition(compound, resolved)) {\n parts.push(compound.css);\n }\n }\n }\n\n // className override from props\n if (props?.className) {\n parts.push(props.className);\n }\n\n return cn(...parts);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoEA,SAAS,yBACP,WACA,UACS;AACT,MAAK,MAAM,OAAO,OAAO,KAAK,UAAU,EAAE;AACxC,MAAI,QAAQ,MAAO;EACnB,MAAM,WAAW,UAAU;EAC3B,MAAM,SAAS,SAAS;AACxB,MAAI,MAAM,QAAQ,SAAS;OACrB,CAAC,SAAS,SAAS,OAAgB,CAAE,QAAO;aACvC,WAAW,SACpB,QAAO;;AAGX,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCT,SAAgB,iBAGd,QAAgC;CAChC,MAAM,EAAE,OAAO,MAAM,UAAU,iBAAiB,qBAAqB;AAErE,QAAO,SAAS,WACd,OACqB;EACrB,MAAM,WAAoC,EAAE;AAG5C,MAAI,SACF,MAAK,MAAM,cAAc,OAAO,KAAK,SAAS,EAAE;GAC9C,MAAM,YAAY,QAAQ;GAC1B,MAAM,eAAe,kBAAkB;AACvC,YAAS,cAAc,aAAa;;EAKxC,MAAM,SAAS,EAAE;AAEjB,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,QAAkB,EAAE;AAG1B,OAAI,KAAK,MACP,OAAM,KAAK,KAAK,MAAM;AAIxB,OAAI,SACF,MAAK,MAAM,CAAC,YAAY,kBAAkB,OAAO,QAAQ,SAAS,EAAE;IAClE,MAAM,QAAQ,SAAS;AACvB,QAAI,SAAS,QAAQ,cAAc,QAAQ;KACzC,MAAM,cAAc,cAAc,OAAO;AACzC,SAAI,YACF,OAAM,KAAK,YAAY;;;AAO/B,OAAI;SACG,MAAM,YAAY,iBACrB,KAAI,yBAAyB,UAAU,SAAS,EAAE;KAChD,MAAM,cAAc,SAAS,IAAI;AACjC,SAAI,YACF,OAAM,KAAK,YAAY;;;AAO/B,OAAI,OAAO,YAAY,MACrB,OAAM,KAAK,MAAM,UAAU,MAAM;AAGnC,UAAO,QAAQ,GAAG,GAAG,MAAM;;AAG7B,SAAO;;;;;;;;;;;;;;;;;;;;;;;;;AA8BX,SAAgB,aACd,QACA;CACA,MAAM,EAAE,MAAM,UAAU,iBAAiB,qBAAqB;AAE9D,QAAO,SAAS,aAAa,OAA0D;EACrF,MAAM,WAAoC,EAAE;EAC5C,MAAM,QAAkB,EAAE;AAE1B,MAAI,KACF,OAAM,KAAK,KAAK;AAIlB,MAAI,SACF,MAAK,MAAM,cAAc,OAAO,KAAK,SAAS,EAAE;GAC9C,MAAM,YAAY,QAAQ;GAC1B,MAAM,eAAe,kBAAkB;AACvC,YAAS,cAAc,aAAa;GAEpC,MAAM,QAAQ,SAAS;AACvB,OAAI,SAAS,QAAQ,SAAS,cAAc,OAC1C,OAAM,KAAK,SAAS,YAAY,OAAO;;AAM7C,MAAI;QACG,MAAM,YAAY,iBACrB,KAAI,yBAAyB,UAAU,SAAS,CAC9C,OAAM,KAAK,SAAS,IAAI;;AAM9B,MAAI,OAAO,UACT,OAAM,KAAK,MAAM,UAAU;AAG7B,SAAO,GAAG,GAAG,MAAM"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Toggle as Toggle$1, toggleVariants } from "../ui/toggle.js";
|
|
1
|
+
import { Toggle as Toggle$1, toggleRecipe, toggleVariants } from "../ui/toggle.js";
|
|
2
2
|
import * as React$1 from "react";
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
|
|
@@ -7,5 +7,5 @@ declare function Toggle({
|
|
|
7
7
|
...props
|
|
8
8
|
}: React$1.ComponentProps<typeof Toggle$1>): react_jsx_runtime0.JSX.Element;
|
|
9
9
|
//#endregion
|
|
10
|
-
export { Toggle, toggleVariants };
|
|
10
|
+
export { Toggle, toggleRecipe, toggleVariants };
|
|
11
11
|
//# sourceMappingURL=toggle.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useCustomComponent } from "./context.mjs";
|
|
3
|
-
import { Toggle as Toggle$1, toggleVariants } from "../ui/toggle.mjs";
|
|
3
|
+
import { Toggle as Toggle$1, toggleRecipe, toggleVariants } from "../ui/toggle.mjs";
|
|
4
4
|
import "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/client/ui-resolver/toggle.tsx
|
|
@@ -10,6 +10,6 @@ function Toggle({ ...props }) {
|
|
|
10
10
|
return /* @__PURE__ */ jsx(Toggle$1, { ...props });
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
|
-
export { Toggle, toggleVariants };
|
|
13
|
+
export { Toggle, toggleRecipe, toggleVariants };
|
|
14
14
|
|
|
15
15
|
//# sourceMappingURL=toggle.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle.mjs","names":["DefaultToggle"],"sources":["../../../src/client/ui-resolver/toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Toggle as DefaultToggle, toggleVariants } from \"../ui/toggle\";\nimport { useCustomComponent } from \"./context\";\n\nfunction Toggle({ ...props }: React.ComponentProps<typeof DefaultToggle>) {\n const Custom = useCustomComponent(\"toggle\");\n if (Custom) return <Custom {...props} />;\n return <DefaultToggle {...props} />;\n}\n\nexport { Toggle, toggleVariants };\n"],"mappings":";;;;;;AAMA,SAAS,OAAO,EAAE,GAAG,SAAqD;CACxE,MAAM,SAAS,mBAAmB,SAAS;AAC3C,KAAI,OAAQ,QAAO,oBAAC,QAAD,EAAQ,GAAI,OAAS,CAAA;AACxC,QAAO,oBAACA,UAAD,EAAe,GAAI,OAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"toggle.mjs","names":["DefaultToggle"],"sources":["../../../src/client/ui-resolver/toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Toggle as DefaultToggle, toggleRecipe, toggleVariants } from \"../ui/toggle\";\nimport { useCustomComponent } from \"./context\";\n\nfunction Toggle({ ...props }: React.ComponentProps<typeof DefaultToggle>) {\n const Custom = useCustomComponent(\"toggle\");\n if (Custom) return <Custom {...props} />;\n return <DefaultToggle {...props} />;\n}\n\nexport { Toggle, toggleRecipe, toggleVariants };\n"],"mappings":";;;;;;AAMA,SAAS,OAAO,EAAE,GAAG,SAAqD;CACxE,MAAM,SAAS,mBAAmB,SAAS;AAC3C,KAAI,OAAQ,QAAO,oBAAC,QAAD,EAAQ,GAAI,OAAS,CAAA;AACxC,QAAO,oBAACA,UAAD,EAAe,GAAI,OAAS,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/client/ui-resolver/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Global variant vocabulary for the SDK component system.
|
|
4
|
+
*
|
|
5
|
+
* Surface variants control visual treatment (fill, outline, etc.).
|
|
6
|
+
* Semantic colors communicate intent (primary action, error, etc.).
|
|
7
|
+
* Sizes follow a consistent t-shirt scale across all components.
|
|
8
|
+
*/
|
|
9
|
+
type Variant = "solid" | "soft" | "outlined" | "plain";
|
|
10
|
+
type SemanticColor = "primary" | "neutral" | "danger" | "success";
|
|
11
|
+
type Size = "xs" | "sm" | "md" | "lg" | "xl";
|
|
12
|
+
//#endregion
|
|
13
|
+
export { SemanticColor, Size, Variant };
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/client/ui-resolver/types.ts"],"mappings":";;AAQA;;;;;AAEA;KAFY,OAAA;AAAA,KAEA,aAAA;AAAA,KAEA,IAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -22,12 +22,12 @@ function WishlistItemActions({ productId, productName, onMoveToCart, onRemove, i
|
|
|
22
22
|
return /* @__PURE__ */ jsxs("div", {
|
|
23
23
|
className: "flex items-center gap-2 mt-2",
|
|
24
24
|
children: [onMoveToCart && productId && /* @__PURE__ */ jsx(Button, {
|
|
25
|
-
variant: "
|
|
25
|
+
variant: "outlined",
|
|
26
26
|
size: "sm",
|
|
27
27
|
onClick: () => onMoveToCart(productId),
|
|
28
28
|
children: moveToCartLabel
|
|
29
29
|
}), /* @__PURE__ */ jsx(Button, {
|
|
30
|
-
variant: "
|
|
30
|
+
variant: "plain",
|
|
31
31
|
size: "icon",
|
|
32
32
|
className: "flex-shrink-0",
|
|
33
33
|
onClick: () => productId && onRemove(productId),
|
|
@@ -98,7 +98,7 @@ function WishlistEmptyState({ emptyTitle, emptyDescription, continueShoppingLabe
|
|
|
98
98
|
}),
|
|
99
99
|
/* @__PURE__ */ jsx(Button, {
|
|
100
100
|
onClick: onClose,
|
|
101
|
-
variant: "
|
|
101
|
+
variant: "outlined",
|
|
102
102
|
children: continueShoppingLabel
|
|
103
103
|
})
|
|
104
104
|
]
|
|
@@ -155,7 +155,7 @@ function WishlistDrawer({ isOpen, onClose, wishlistId, onMoveToCart, className,
|
|
|
155
155
|
showClose: false,
|
|
156
156
|
children: title
|
|
157
157
|
}), /* @__PURE__ */ jsx(Button, {
|
|
158
|
-
variant: "
|
|
158
|
+
variant: "plain",
|
|
159
159
|
size: "icon",
|
|
160
160
|
onClick: onClose,
|
|
161
161
|
"aria-label": "Close wishlist",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wishlist-drawer.mjs","names":[],"sources":["../../../src/client/wishlist/wishlist-drawer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useIcon } from \"../icons/icon-context\";\nimport { Button } from \"../ui/button\";\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from \"../ui/sheet\";\nimport { useWishlist } from \"./hooks/useWishlist\";\nimport { useWishlistActions } from \"./hooks/useWishlistActions\";\n\ninterface WishlistItemImage {\n image_url?: string;\n alt_text?: string;\n}\n\ninterface WishlistItemProduct {\n id?: string;\n product_name?: string;\n images?: WishlistItemImage[];\n slug?: string;\n}\n\ninterface WishlistDrawerItem {\n id?: string;\n product_id?: string;\n product?: WishlistItemProduct;\n}\n\nexport interface WishlistDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n wishlistId?: string;\n onMoveToCart?: (productId: string) => void;\n className?: string;\n labels?: {\n title?: string;\n emptyTitle?: string;\n emptyDescription?: string;\n removeLabel?: string;\n moveToCartLabel?: string;\n continueShoppingLabel?: string;\n };\n}\n\nfunction WishlistItemImage({ imageUrl, imageAlt }: { imageUrl?: string; imageAlt: string }) {\n return (\n <div className=\"relative size-24 flex-shrink-0 overflow-hidden rounded-(--enad-border-radius) bg-(--enad-border-color)\">\n {imageUrl ? (\n <img src={imageUrl} alt={imageAlt} loading=\"lazy\" className=\"size-full object-cover\" />\n ) : (\n <div className=\"size-full bg-(--enad-border-color)\" />\n )}\n </div>\n );\n}\n\nfunction WishlistItemActions({\n productId,\n productName,\n onMoveToCart,\n onRemove,\n isDeleting,\n removeLabel,\n moveToCartLabel,\n}: {\n productId?: string;\n productName: string;\n onMoveToCart?: (productId: string) => void;\n onRemove: (productId: string) => void;\n isDeleting: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n}) {\n const TrashIcon = useIcon(\"trash\");\n\n return (\n <div className=\"flex items-center gap-2 mt-2\">\n {onMoveToCart && productId && (\n <Button variant=\"outline\" size=\"sm\" onClick={() => onMoveToCart(productId)}>\n {moveToCartLabel}\n </Button>\n )}\n\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"flex-shrink-0\"\n onClick={() => productId && onRemove(productId)}\n disabled={isDeleting || !productId}\n aria-label={`${removeLabel} ${productName}`}\n >\n <TrashIcon className=\"size-4\" />\n </Button>\n </div>\n );\n}\n\nfunction WishlistItemRow({\n item,\n onMoveToCart,\n onRemove,\n isDeleting,\n removeLabel,\n moveToCartLabel,\n}: {\n item: WishlistDrawerItem;\n onMoveToCart?: (productId: string) => void;\n onRemove: (productId: string) => void;\n isDeleting: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n}) {\n const product = item.product;\n const productName = product?.product_name ?? \"Unknown Product\";\n const imageUrl = product?.images?.[0]?.image_url;\n const imageAlt = product?.images?.[0]?.alt_text ?? productName;\n const productId = item.product_id ?? product?.id;\n\n return (\n <div className=\"flex gap-4\" role=\"listitem\">\n <WishlistItemImage imageUrl={imageUrl} imageAlt={imageAlt} />\n\n <div className=\"flex flex-1 min-w-0 flex-col justify-between\">\n <p className=\"text-sm font-medium text-(--enad-text-primary-color)\">{productName}</p>\n\n <WishlistItemActions\n productId={productId}\n productName={productName}\n onMoveToCart={onMoveToCart}\n onRemove={onRemove}\n isDeleting={isDeleting}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n />\n </div>\n </div>\n );\n}\n\nfunction WishlistLoadingSkeleton() {\n return (\n <div className=\"space-y-6\" aria-busy=\"true\" aria-label=\"Loading wishlist items\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-4 animate-pulse\">\n <div className=\"size-24 flex-shrink-0 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n <div className=\"flex flex-1 flex-col gap-2\">\n <div className=\"h-4 w-3/4 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n <div className=\"h-4 w-1/3 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction WishlistEmptyState({\n emptyTitle,\n emptyDescription,\n continueShoppingLabel,\n onClose,\n}: {\n emptyTitle: string;\n emptyDescription: string;\n continueShoppingLabel: string;\n onClose: () => void;\n}) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center text-center\">\n <p className=\"font-medium text-(--enad-text-primary-color) mb-2\">{emptyTitle}</p>\n <p className=\"text-(--enad-text-muted-color) mb-4\">{emptyDescription}</p>\n <Button onClick={onClose} variant=\"outline\">\n {continueShoppingLabel}\n </Button>\n </div>\n );\n}\n\nfunction WishlistContent({\n isLoading,\n items,\n onMoveToCart,\n handleMoveToCart,\n handleRemoveItem,\n isDeletingItemsFromWishlist,\n removeLabel,\n moveToCartLabel,\n emptyTitle,\n emptyDescription,\n continueShoppingLabel,\n onClose,\n}: {\n isLoading: boolean;\n items: WishlistDrawerItem[];\n onMoveToCart?: (productId: string) => void;\n handleMoveToCart: (productId: string) => void;\n handleRemoveItem: (productId: string) => void;\n isDeletingItemsFromWishlist: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n emptyTitle: string;\n emptyDescription: string;\n continueShoppingLabel: string;\n onClose: () => void;\n}) {\n if (isLoading) return <WishlistLoadingSkeleton />;\n if (items.length === 0) {\n return (\n <WishlistEmptyState\n emptyTitle={emptyTitle}\n emptyDescription={emptyDescription}\n continueShoppingLabel={continueShoppingLabel}\n onClose={onClose}\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-6\" role=\"list\" aria-label=\"Wishlist items\">\n {items.map((item) => (\n <WishlistItemRow\n key={item.id}\n item={item}\n onMoveToCart={onMoveToCart ? handleMoveToCart : undefined}\n onRemove={handleRemoveItem}\n isDeleting={isDeletingItemsFromWishlist}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n />\n ))}\n </div>\n );\n}\n\nexport function WishlistDrawer({\n isOpen,\n onClose,\n wishlistId,\n onMoveToCart,\n className,\n labels = {},\n}: WishlistDrawerProps) {\n const CloseIcon = useIcon(\"close\");\n const {\n title = \"Your Wishlist\",\n emptyTitle = \"Your wishlist is empty\",\n emptyDescription = \"Save items you love to your wishlist.\",\n removeLabel = \"Remove\",\n moveToCartLabel = \"Move to Cart\",\n continueShoppingLabel = \"Continue Shopping\",\n } = labels;\n\n const { wishlist, isLoading } = useWishlist(wishlistId ? { wishlistId } : undefined);\n const { deleteItems, isDeletingItemsFromWishlist } = useWishlistActions();\n\n const items = (wishlist?.items ?? []) as WishlistDrawerItem[];\n\n const handleRemoveItem = (productId: string) => {\n if (!wishlistId || !productId) return;\n deleteItems({ wishlistId, options: { product_ids: [productId] } });\n };\n\n const handleMoveToCart = (productId: string) => {\n if (onMoveToCart && productId) {\n onMoveToCart(productId);\n }\n };\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <SheetContent\n side=\"right\"\n className={`flex w-full flex-col p-0 sm:max-w-[480px] ${className ?? \"\"}`}\n >\n {/* Header */}\n <SheetHeader className=\"flex flex-row items-center justify-between p-6 pb-0\">\n <SheetTitle\n className=\"text-xl font-heading font-bold tracking-wider uppercase text-(--enad-text-primary-color)\"\n showClose={false}\n >\n {title}\n </SheetTitle>\n <Button variant=\"ghost\" size=\"icon\" onClick={onClose} aria-label=\"Close wishlist\">\n <CloseIcon className=\"size-5\" />\n </Button>\n </SheetHeader>\n\n {/* Wishlist Items */}\n <div className=\"flex-1 overflow-y-auto px-6 py-6\">\n <WishlistContent\n isLoading={isLoading}\n items={items}\n onMoveToCart={onMoveToCart}\n handleMoveToCart={handleMoveToCart}\n handleRemoveItem={handleRemoveItem}\n isDeletingItemsFromWishlist={isDeletingItemsFromWishlist}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n emptyTitle={emptyTitle}\n emptyDescription={emptyDescription}\n continueShoppingLabel={continueShoppingLabel}\n onClose={onClose}\n />\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wishlist-drawer.mjs","names":[],"sources":["../../../src/client/wishlist/wishlist-drawer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useIcon } from \"../icons/icon-context\";\nimport { Button } from \"../ui/button\";\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from \"../ui/sheet\";\nimport { useWishlist } from \"./hooks/useWishlist\";\nimport { useWishlistActions } from \"./hooks/useWishlistActions\";\n\ninterface WishlistItemImage {\n image_url?: string;\n alt_text?: string;\n}\n\ninterface WishlistItemProduct {\n id?: string;\n product_name?: string;\n images?: WishlistItemImage[];\n slug?: string;\n}\n\ninterface WishlistDrawerItem {\n id?: string;\n product_id?: string;\n product?: WishlistItemProduct;\n}\n\nexport interface WishlistDrawerProps {\n isOpen: boolean;\n onClose: () => void;\n wishlistId?: string;\n onMoveToCart?: (productId: string) => void;\n className?: string;\n labels?: {\n title?: string;\n emptyTitle?: string;\n emptyDescription?: string;\n removeLabel?: string;\n moveToCartLabel?: string;\n continueShoppingLabel?: string;\n };\n}\n\nfunction WishlistItemImage({ imageUrl, imageAlt }: { imageUrl?: string; imageAlt: string }) {\n return (\n <div className=\"relative size-24 flex-shrink-0 overflow-hidden rounded-(--enad-border-radius) bg-(--enad-border-color)\">\n {imageUrl ? (\n <img src={imageUrl} alt={imageAlt} loading=\"lazy\" className=\"size-full object-cover\" />\n ) : (\n <div className=\"size-full bg-(--enad-border-color)\" />\n )}\n </div>\n );\n}\n\nfunction WishlistItemActions({\n productId,\n productName,\n onMoveToCart,\n onRemove,\n isDeleting,\n removeLabel,\n moveToCartLabel,\n}: {\n productId?: string;\n productName: string;\n onMoveToCart?: (productId: string) => void;\n onRemove: (productId: string) => void;\n isDeleting: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n}) {\n const TrashIcon = useIcon(\"trash\");\n\n return (\n <div className=\"flex items-center gap-2 mt-2\">\n {onMoveToCart && productId && (\n <Button variant=\"outlined\" size=\"sm\" onClick={() => onMoveToCart(productId)}>\n {moveToCartLabel}\n </Button>\n )}\n\n <Button\n variant=\"plain\"\n size=\"icon\"\n className=\"flex-shrink-0\"\n onClick={() => productId && onRemove(productId)}\n disabled={isDeleting || !productId}\n aria-label={`${removeLabel} ${productName}`}\n >\n <TrashIcon className=\"size-4\" />\n </Button>\n </div>\n );\n}\n\nfunction WishlistItemRow({\n item,\n onMoveToCart,\n onRemove,\n isDeleting,\n removeLabel,\n moveToCartLabel,\n}: {\n item: WishlistDrawerItem;\n onMoveToCart?: (productId: string) => void;\n onRemove: (productId: string) => void;\n isDeleting: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n}) {\n const product = item.product;\n const productName = product?.product_name ?? \"Unknown Product\";\n const imageUrl = product?.images?.[0]?.image_url;\n const imageAlt = product?.images?.[0]?.alt_text ?? productName;\n const productId = item.product_id ?? product?.id;\n\n return (\n <div className=\"flex gap-4\" role=\"listitem\">\n <WishlistItemImage imageUrl={imageUrl} imageAlt={imageAlt} />\n\n <div className=\"flex flex-1 min-w-0 flex-col justify-between\">\n <p className=\"text-sm font-medium text-(--enad-text-primary-color)\">{productName}</p>\n\n <WishlistItemActions\n productId={productId}\n productName={productName}\n onMoveToCart={onMoveToCart}\n onRemove={onRemove}\n isDeleting={isDeleting}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n />\n </div>\n </div>\n );\n}\n\nfunction WishlistLoadingSkeleton() {\n return (\n <div className=\"space-y-6\" aria-busy=\"true\" aria-label=\"Loading wishlist items\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"flex gap-4 animate-pulse\">\n <div className=\"size-24 flex-shrink-0 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n <div className=\"flex flex-1 flex-col gap-2\">\n <div className=\"h-4 w-3/4 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n <div className=\"h-4 w-1/3 bg-(--enad-border-color) rounded-(--enad-border-radius)\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction WishlistEmptyState({\n emptyTitle,\n emptyDescription,\n continueShoppingLabel,\n onClose,\n}: {\n emptyTitle: string;\n emptyDescription: string;\n continueShoppingLabel: string;\n onClose: () => void;\n}) {\n return (\n <div className=\"flex h-full flex-col items-center justify-center text-center\">\n <p className=\"font-medium text-(--enad-text-primary-color) mb-2\">{emptyTitle}</p>\n <p className=\"text-(--enad-text-muted-color) mb-4\">{emptyDescription}</p>\n <Button onClick={onClose} variant=\"outlined\">\n {continueShoppingLabel}\n </Button>\n </div>\n );\n}\n\nfunction WishlistContent({\n isLoading,\n items,\n onMoveToCart,\n handleMoveToCart,\n handleRemoveItem,\n isDeletingItemsFromWishlist,\n removeLabel,\n moveToCartLabel,\n emptyTitle,\n emptyDescription,\n continueShoppingLabel,\n onClose,\n}: {\n isLoading: boolean;\n items: WishlistDrawerItem[];\n onMoveToCart?: (productId: string) => void;\n handleMoveToCart: (productId: string) => void;\n handleRemoveItem: (productId: string) => void;\n isDeletingItemsFromWishlist: boolean;\n removeLabel: string;\n moveToCartLabel: string;\n emptyTitle: string;\n emptyDescription: string;\n continueShoppingLabel: string;\n onClose: () => void;\n}) {\n if (isLoading) return <WishlistLoadingSkeleton />;\n if (items.length === 0) {\n return (\n <WishlistEmptyState\n emptyTitle={emptyTitle}\n emptyDescription={emptyDescription}\n continueShoppingLabel={continueShoppingLabel}\n onClose={onClose}\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-6\" role=\"list\" aria-label=\"Wishlist items\">\n {items.map((item) => (\n <WishlistItemRow\n key={item.id}\n item={item}\n onMoveToCart={onMoveToCart ? handleMoveToCart : undefined}\n onRemove={handleRemoveItem}\n isDeleting={isDeletingItemsFromWishlist}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n />\n ))}\n </div>\n );\n}\n\nexport function WishlistDrawer({\n isOpen,\n onClose,\n wishlistId,\n onMoveToCart,\n className,\n labels = {},\n}: WishlistDrawerProps) {\n const CloseIcon = useIcon(\"close\");\n const {\n title = \"Your Wishlist\",\n emptyTitle = \"Your wishlist is empty\",\n emptyDescription = \"Save items you love to your wishlist.\",\n removeLabel = \"Remove\",\n moveToCartLabel = \"Move to Cart\",\n continueShoppingLabel = \"Continue Shopping\",\n } = labels;\n\n const { wishlist, isLoading } = useWishlist(wishlistId ? { wishlistId } : undefined);\n const { deleteItems, isDeletingItemsFromWishlist } = useWishlistActions();\n\n const items = (wishlist?.items ?? []) as WishlistDrawerItem[];\n\n const handleRemoveItem = (productId: string) => {\n if (!wishlistId || !productId) return;\n deleteItems({ wishlistId, options: { product_ids: [productId] } });\n };\n\n const handleMoveToCart = (productId: string) => {\n if (onMoveToCart && productId) {\n onMoveToCart(productId);\n }\n };\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <SheetContent\n side=\"right\"\n className={`flex w-full flex-col p-0 sm:max-w-[480px] ${className ?? \"\"}`}\n >\n {/* Header */}\n <SheetHeader className=\"flex flex-row items-center justify-between p-6 pb-0\">\n <SheetTitle\n className=\"text-xl font-heading font-bold tracking-wider uppercase text-(--enad-text-primary-color)\"\n showClose={false}\n >\n {title}\n </SheetTitle>\n <Button variant=\"plain\" size=\"icon\" onClick={onClose} aria-label=\"Close wishlist\">\n <CloseIcon className=\"size-5\" />\n </Button>\n </SheetHeader>\n\n {/* Wishlist Items */}\n <div className=\"flex-1 overflow-y-auto px-6 py-6\">\n <WishlistContent\n isLoading={isLoading}\n items={items}\n onMoveToCart={onMoveToCart}\n handleMoveToCart={handleMoveToCart}\n handleRemoveItem={handleRemoveItem}\n isDeletingItemsFromWishlist={isDeletingItemsFromWishlist}\n removeLabel={removeLabel}\n moveToCartLabel={moveToCartLabel}\n emptyTitle={emptyTitle}\n emptyDescription={emptyDescription}\n continueShoppingLabel={continueShoppingLabel}\n onClose={onClose}\n />\n </div>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
|