@jiwambe/components 0.3.2 → 0.3.4

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.
@@ -0,0 +1,81 @@
1
+ import { default as React } from 'react';
2
+ /**
3
+ * ProductCard variant from Figma: Apply (two CTAs) or Choose (single CTA with selected state).
4
+ * Use variant="apply" for apply + view-details flows; variant="choose" for pick-one flows.
5
+ */
6
+ export type ProductCardVariant = 'apply' | 'choose';
7
+ /** One spec line: plain string or { text, secondary? } for text with muted suffix e.g. "150km range (full day coverage)". */
8
+ export type ProductCardSpec = string | {
9
+ text: string;
10
+ secondary?: string;
11
+ };
12
+ export interface ProductCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
13
+ /** Which CTA layout to use: apply (two buttons) or choose (one button, optional selected). @default 'apply' */
14
+ variant?: ProductCardVariant;
15
+ /** Main product image URL. */
16
+ imageSrc: string;
17
+ /** Alt text for the image. @default '' */
18
+ imageAlt?: string;
19
+ /** Width for next/image. @default 288 */
20
+ imageWidth?: number;
21
+ /** Height for next/image (aspect 16:9). @default 162 */
22
+ imageHeight?: number;
23
+ /** Show prev/next image nav overlay on hover (e.g. for carousel). @default false */
24
+ showImageNav?: boolean;
25
+ /** Called when the previous image control is clicked. Only relevant when showImageNav is true. */
26
+ onPrevImage?: () => void;
27
+ /** Called when the next image control is clicked. Only relevant when showImageNav is true. */
28
+ onNextImage?: () => void;
29
+ /** Product name (e.g. "Magnus 3000"). */
30
+ name: string;
31
+ /** Brand or model line (e.g. "Mazi"). @default undefined */
32
+ brand?: string;
33
+ /** Short description or tagline below the name. @default undefined */
34
+ description?: string;
35
+ /** List of feature lines; each can be a string or { text, secondary? }. */
36
+ specs?: ProductCardSpec[];
37
+ /** Daily price label (e.g. "500 KES"). */
38
+ priceDaily: string;
39
+ /** Optional unit after daily price (e.g. "/day"). @default '/day' */
40
+ priceUnit?: string;
41
+ /** Total or purchase price (e.g. "280,732 KES"). @default undefined */
42
+ priceTotal?: string;
43
+ /** Label for the primary action button. @default 'Apply now' */
44
+ primaryActionLabel?: string;
45
+ /** Label for the secondary action button. @default 'View details' */
46
+ secondaryActionLabel?: string;
47
+ /** Called when the primary action is clicked. Used when variant="apply". */
48
+ onPrimaryAction?: () => void;
49
+ /** When set, the primary action renders as a link. Used when variant="apply". */
50
+ primaryActionHref?: string;
51
+ /** Called when the secondary action is clicked. Used when variant="apply". */
52
+ onSecondaryAction?: () => void;
53
+ /** When set, the secondary action renders as a link. Used when variant="apply". */
54
+ secondaryActionHref?: string;
55
+ /** Label for the choose button when not selected. @default 'Choose' */
56
+ chooseLabel?: string;
57
+ /** Label for the choose button when selected. @default 'Selected' */
58
+ selectedLabel?: string;
59
+ /** Called when the choose button is clicked. Used when variant="choose". */
60
+ onChoose?: () => void;
61
+ /** When true, card shows selected state (heavier border, muted content). Used when variant="choose". @default false */
62
+ selected?: boolean;
63
+ /** Disables all actions and applies disabled styling. @default false */
64
+ disabled?: boolean;
65
+ /** Component to render link-style actions as (e.g. next/link). @default 'a' */
66
+ linkAs?: React.ElementType;
67
+ /** Additional class name for the root. */
68
+ className?: string;
69
+ /** Forwarded ref for the root div. */
70
+ ref?: React.Ref<HTMLDivElement>;
71
+ }
72
+ type ProductCardApplyProps = Omit<ProductCardProps, 'variant'>;
73
+ type ProductCardChooseProps = Omit<ProductCardProps, 'variant'>;
74
+ declare const ProductCardApplyWithRef: React.ForwardRefExoticComponent<Omit<ProductCardApplyProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
75
+ declare const ProductCardChooseWithRef: React.ForwardRefExoticComponent<Omit<ProductCardChooseProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
76
+ declare const ProductCard: React.ForwardRefExoticComponent<Omit<ProductCardProps, "ref"> & React.RefAttributes<HTMLDivElement>> & {
77
+ Apply: typeof ProductCardApplyWithRef;
78
+ Choose: typeof ProductCardChooseWithRef;
79
+ };
80
+ export { ProductCard };
81
+ //# sourceMappingURL=ProductCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductCard.d.ts","sourceRoot":"","sources":["../../../src/components/ProductCard/ProductCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ "use client";
2
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
+ import React, { useState } from "react";
4
+ import Image from "next/image";
5
+ import { Button } from "../Button/Button.js";
6
+ import { Icon } from "../Icon/Icon.js";
7
+ import { Divider } from "../Divider/Divider.js";
8
+ import { Link } from "../Link/Link.js";
9
+ function SpecItem({ spec }) {
10
+ if (typeof spec === "string") {
11
+ return /* @__PURE__ */ jsx("span", { children: spec });
12
+ }
13
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
14
+ /* @__PURE__ */ jsx("span", { children: spec.text }),
15
+ spec.secondary != null && /* @__PURE__ */ jsxs("span", { className: "text-text-secondary", children: [
16
+ " (",
17
+ spec.secondary,
18
+ ")"
19
+ ] })
20
+ ] });
21
+ }
22
+ function ProductCardInner({
23
+ variant = "apply",
24
+ imageSrc,
25
+ imageAlt = "",
26
+ imageWidth = 288,
27
+ imageHeight = 162,
28
+ showImageNav = false,
29
+ onPrevImage,
30
+ onNextImage,
31
+ name,
32
+ brand,
33
+ description,
34
+ specs = [],
35
+ priceDaily,
36
+ priceUnit = "/day",
37
+ priceTotal,
38
+ primaryActionLabel,
39
+ secondaryActionLabel,
40
+ onPrimaryAction,
41
+ primaryActionHref,
42
+ onSecondaryAction,
43
+ secondaryActionHref,
44
+ chooseLabel,
45
+ selectedLabel,
46
+ onChoose,
47
+ selected = false,
48
+ disabled = false,
49
+ linkAs = "a",
50
+ className = "",
51
+ ...rest
52
+ }, forwardedRef) {
53
+ const [imageHover, setImageHover] = useState(false);
54
+ const [cardHover, setCardHover] = useState(false);
55
+ const showNav = showImageNav && imageHover;
56
+ const isChoose = variant === "choose";
57
+ const isSelected = isChoose && selected;
58
+ const contentMuted = disabled || isSelected;
59
+ const borderHeavy = cardHover || isSelected;
60
+ const borderClass = borderHeavy ? "border-border-heavy" : "border-border-light";
61
+ const primaryLabel = primaryActionLabel ?? "Apply now";
62
+ const secondaryLabel = secondaryActionLabel ?? "View details";
63
+ const chooseBtnLabel = chooseLabel ?? "Choose";
64
+ const selectedBtnLabel = selectedLabel ?? "Selected";
65
+ const rootClasses = [
66
+ "flex flex-col rounded-rad-md overflow-hidden bg-fill-bg-primary border border-solid pb-space-4 gap-space-4 w-full max-w-[288px]",
67
+ borderClass,
68
+ className
69
+ ].filter(Boolean).join(" ");
70
+ return /* @__PURE__ */ jsxs(
71
+ "div",
72
+ {
73
+ ref: forwardedRef,
74
+ className: rootClasses,
75
+ onMouseEnter: () => setCardHover(true),
76
+ onMouseLeave: () => setCardHover(false),
77
+ ...rest,
78
+ children: [
79
+ /* @__PURE__ */ jsxs(
80
+ "div",
81
+ {
82
+ className: "relative flex flex-col gap-3 bg-fill-bg-secondary p-space-8 rounded-tl-rad-md rounded-tr-rad-md",
83
+ onMouseEnter: () => setImageHover(true),
84
+ onMouseLeave: () => setImageHover(false),
85
+ children: [
86
+ /* @__PURE__ */ jsx("div", { className: "relative aspect-video w-full overflow-hidden shrink-0", children: /* @__PURE__ */ jsx(
87
+ Image,
88
+ {
89
+ src: imageSrc,
90
+ alt: imageAlt,
91
+ width: imageWidth,
92
+ height: imageHeight,
93
+ className: "h-full w-full object-cover"
94
+ }
95
+ ) }),
96
+ showNav && (onPrevImage ?? onNextImage) && /* @__PURE__ */ jsxs("div", { className: "absolute left-4 right-4 top-1/2 flex -translate-y-1/2 items-center justify-between pointer-events-none", children: [
97
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-auto", children: onPrevImage && /* @__PURE__ */ jsx(
98
+ Button,
99
+ {
100
+ variant: "inverse",
101
+ size: "small",
102
+ iconOnly: /* @__PURE__ */ jsx(Icon, { name: "chevron-left" }),
103
+ "aria-label": "Previous image",
104
+ onClick: onPrevImage
105
+ }
106
+ ) }),
107
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-auto", children: onNextImage && /* @__PURE__ */ jsx(
108
+ Button,
109
+ {
110
+ variant: "inverse",
111
+ size: "small",
112
+ iconOnly: /* @__PURE__ */ jsx(Icon, { name: "chevron-right" }),
113
+ "aria-label": "Next image",
114
+ onClick: onNextImage
115
+ }
116
+ ) })
117
+ ] })
118
+ ]
119
+ }
120
+ ),
121
+ /* @__PURE__ */ jsxs(
122
+ "div",
123
+ {
124
+ className: `flex flex-col gap-space-1 px-space-4 ${contentMuted ? "text-text-disabled [&_.text-text-primary]:text-text-disabled [&_.text-text-secondary]:text-text-disabled" : ""}`,
125
+ children: [
126
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
127
+ /* @__PURE__ */ jsx("p", { className: "text-title-md leading-[1.2] tracking-[0.19px] text-text-primary", children: name }),
128
+ brand != null && /* @__PURE__ */ jsx("p", { className: "text-text-sm leading-[1.4] tracking-[0.16px] text-text-secondary", children: brand })
129
+ ] }),
130
+ description != null && /* @__PURE__ */ jsx("p", { className: "text-text-sm leading-[1.4] tracking-[0.16px] text-text-primary", children: description })
131
+ ]
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsx(Divider, { variant: "light", className: "my-0" }),
135
+ specs.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
136
+ /* @__PURE__ */ jsx(
137
+ "div",
138
+ {
139
+ className: `flex flex-col gap-space-2 px-space-4 ${contentMuted ? "text-text-disabled [&_*]:text-text-disabled" : ""}`,
140
+ children: specs.map((spec, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-space-2", children: [
141
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: 10 }) }),
142
+ /* @__PURE__ */ jsx("p", { className: "text-text-xs tracking-[0.18px] leading-[1.4] min-w-0", children: /* @__PURE__ */ jsx(SpecItem, { spec }) })
143
+ ] }, i))
144
+ }
145
+ ),
146
+ /* @__PURE__ */ jsx(Divider, { variant: "light", className: "my-0" })
147
+ ] }),
148
+ /* @__PURE__ */ jsxs(
149
+ "div",
150
+ {
151
+ className: `flex flex-col gap-space-1 px-space-4 ${contentMuted ? "text-text-disabled [&_*]:text-text-disabled" : ""}`,
152
+ children: [
153
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-space-1", children: [
154
+ /* @__PURE__ */ jsx("p", { className: "text-title-md leading-[1.2] tracking-[0.19px] text-text-primary whitespace-nowrap", children: priceDaily }),
155
+ /* @__PURE__ */ jsx("p", { className: "text-text-xs tracking-[0.18px] text-text-secondary", children: priceUnit })
156
+ ] }),
157
+ priceTotal != null && /* @__PURE__ */ jsx("p", { className: "text-text-xs tracking-[0.18px] text-text-secondary whitespace-nowrap", children: priceTotal })
158
+ ]
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsx(Divider, { variant: "light", className: "my-0" }),
162
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-space-2 px-space-4", children: [
163
+ variant === "apply" && /* @__PURE__ */ jsxs(Fragment, { children: [
164
+ primaryActionHref != null ? /* @__PURE__ */ jsx(
165
+ Link,
166
+ {
167
+ href: primaryActionHref,
168
+ as: linkAs,
169
+ className: "h-10 w-full items-center justify-center rounded-rad-sm bg-fill-action-primary text-text-action-primary hover:bg-fill-action-primary-hover text-btn-small no-underline",
170
+ children: primaryLabel
171
+ }
172
+ ) : /* @__PURE__ */ jsx(
173
+ Button,
174
+ {
175
+ variant: "primary",
176
+ size: "small",
177
+ disabled,
178
+ className: "w-full justify-center",
179
+ onClick: onPrimaryAction,
180
+ children: primaryLabel
181
+ }
182
+ ),
183
+ secondaryActionHref != null ? /* @__PURE__ */ jsx(
184
+ Link,
185
+ {
186
+ href: secondaryActionHref,
187
+ as: linkAs,
188
+ className: "h-10 w-full items-center justify-center rounded-rad-sm bg-fill-action-secondary text-text-action-secondary hover:bg-fill-action-secondary-hover text-btn-small no-underline",
189
+ children: secondaryLabel
190
+ }
191
+ ) : /* @__PURE__ */ jsx(
192
+ Button,
193
+ {
194
+ variant: "secondary",
195
+ size: "small",
196
+ disabled,
197
+ className: "w-full justify-center",
198
+ onClick: onSecondaryAction,
199
+ children: secondaryLabel
200
+ }
201
+ )
202
+ ] }),
203
+ variant === "choose" && /* @__PURE__ */ jsx(
204
+ Button,
205
+ {
206
+ variant: "primary",
207
+ size: "small",
208
+ disabled,
209
+ className: "w-full justify-center",
210
+ onClick: onChoose,
211
+ children: selected ? selectedBtnLabel : chooseBtnLabel
212
+ }
213
+ )
214
+ ] })
215
+ ]
216
+ }
217
+ );
218
+ }
219
+ function ProductCardApply(props, ref) {
220
+ return /* @__PURE__ */ jsx(ProductCardBase, { ...props, variant: "apply", ref });
221
+ }
222
+ function ProductCardChoose(props, ref) {
223
+ return /* @__PURE__ */ jsx(ProductCardBase, { ...props, variant: "choose", ref });
224
+ }
225
+ const ProductCardApplyWithRef = React.forwardRef(ProductCardApply);
226
+ const ProductCardChooseWithRef = React.forwardRef(ProductCardChoose);
227
+ const ProductCardBase = React.forwardRef(ProductCardInner);
228
+ const ProductCard = Object.assign(ProductCardBase, {
229
+ Apply: ProductCardApplyWithRef,
230
+ Choose: ProductCardChooseWithRef
231
+ });
232
+ export {
233
+ ProductCard
234
+ };
235
+ //# sourceMappingURL=ProductCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductCard.js","sources":["../../../src/components/ProductCard/ProductCard.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState } from 'react';\nimport Image from 'next/image';\nimport { Button } from '../Button/Button';\nimport { Icon } from '../Icon/Icon';\nimport { Divider } from '../Divider/Divider';\nimport { Link } from '../Link/Link';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * ProductCard variant from Figma: Apply (two CTAs) or Choose (single CTA with selected state).\n * Use variant=\"apply\" for apply + view-details flows; variant=\"choose\" for pick-one flows.\n */\nexport type ProductCardVariant = 'apply' | 'choose';\n\n/** One spec line: plain string or { text, secondary? } for text with muted suffix e.g. \"150km range (full day coverage)\". */\nexport type ProductCardSpec = string | { text: string; secondary?: string };\n\nexport interface ProductCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** Which CTA layout to use: apply (two buttons) or choose (one button, optional selected). @default 'apply' */\n variant?: ProductCardVariant;\n\n // Image\n /** Main product image URL. */\n imageSrc: string;\n /** Alt text for the image. @default '' */\n imageAlt?: string;\n /** Width for next/image. @default 288 */\n imageWidth?: number;\n /** Height for next/image (aspect 16:9). @default 162 */\n imageHeight?: number;\n /** Show prev/next image nav overlay on hover (e.g. for carousel). @default false */\n showImageNav?: boolean;\n /** Called when the previous image control is clicked. Only relevant when showImageNav is true. */\n onPrevImage?: () => void;\n /** Called when the next image control is clicked. Only relevant when showImageNav is true. */\n onNextImage?: () => void;\n\n // Head\n /** Product name (e.g. \"Magnus 3000\"). */\n name: string;\n /** Brand or model line (e.g. \"Mazi\"). @default undefined */\n brand?: string;\n /** Short description or tagline below the name. @default undefined */\n description?: string;\n\n // Specs\n /** List of feature lines; each can be a string or { text, secondary? }. */\n specs?: ProductCardSpec[];\n\n // Price\n /** Daily price label (e.g. \"500 KES\"). */\n priceDaily: string;\n /** Optional unit after daily price (e.g. \"/day\"). @default '/day' */\n priceUnit?: string;\n /** Total or purchase price (e.g. \"280,732 KES\"). @default undefined */\n priceTotal?: string;\n\n // Apply variant — primary and secondary actions (labels configurable by client)\n /** Label for the primary action button. @default 'Apply now' */\n primaryActionLabel?: string;\n /** Label for the secondary action button. @default 'View details' */\n secondaryActionLabel?: string;\n /** Called when the primary action is clicked. Used when variant=\"apply\". */\n onPrimaryAction?: () => void;\n /** When set, the primary action renders as a link. Used when variant=\"apply\". */\n primaryActionHref?: string;\n /** Called when the secondary action is clicked. Used when variant=\"apply\". */\n onSecondaryAction?: () => void;\n /** When set, the secondary action renders as a link. Used when variant=\"apply\". */\n secondaryActionHref?: string;\n\n // Choose variant\n /** Label for the choose button when not selected. @default 'Choose' */\n chooseLabel?: string;\n /** Label for the choose button when selected. @default 'Selected' */\n selectedLabel?: string;\n /** Called when the choose button is clicked. Used when variant=\"choose\". */\n onChoose?: () => void;\n /** When true, card shows selected state (heavier border, muted content). Used when variant=\"choose\". @default false */\n selected?: boolean;\n\n // Common\n /** Disables all actions and applies disabled styling. @default false */\n disabled?: boolean;\n /** Component to render link-style actions as (e.g. next/link). @default 'a' */\n linkAs?: React.ElementType;\n /** Additional class name for the root. */\n className?: string;\n /** Forwarded ref for the root div. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction SpecItem({ spec }: { spec: ProductCardSpec }) {\n if (typeof spec === 'string') {\n return <span>{spec}</span>;\n }\n return (\n <>\n <span>{spec.text}</span>\n {spec.secondary != null && <span className=\"text-text-secondary\"> ({spec.secondary})</span>}\n </>\n );\n}\n\n// ---------------------------------------------------------------------------\n// ProductCard\n// ---------------------------------------------------------------------------\n\n/**\n * Product card with two variants: apply (primary + secondary actions) or choose (single action with selected state).\n * Action labels are configurable: primaryActionLabel / secondaryActionLabel default to \"Apply now\" and \"View details\".\n * Use ProductCard.Apply or ProductCard.Choose for the same with variant fixed (less typing).\n *\n * @example\n * <ProductCard variant=\"apply\" imageSrc=\"...\" name=\"Product\" priceDaily=\"500 KES\" onPrimaryAction={...} onSecondaryAction={...} />\n *\n * @example\n * <ProductCard variant=\"apply\" primaryActionLabel=\"Get quote\" secondaryActionLabel=\"Learn more\" ... />\n *\n * @example\n * <ProductCard variant=\"choose\" imageSrc=\"...\" name=\"...\" priceDaily=\"500 KES\" onChoose={...} selected={isSelected} />\n */\nfunction ProductCardInner(\n {\n variant = 'apply',\n imageSrc,\n imageAlt = '',\n imageWidth = 288,\n imageHeight = 162,\n showImageNav = false,\n onPrevImage,\n onNextImage,\n name,\n brand,\n description,\n specs = [],\n priceDaily,\n priceUnit = '/day',\n priceTotal,\n primaryActionLabel,\n secondaryActionLabel,\n onPrimaryAction,\n primaryActionHref,\n onSecondaryAction,\n secondaryActionHref,\n chooseLabel,\n selectedLabel,\n onChoose,\n selected = false,\n disabled = false,\n linkAs = 'a',\n className = '',\n ...rest\n }: ProductCardProps,\n forwardedRef: React.Ref<HTMLDivElement>\n) {\n const [imageHover, setImageHover] = useState(false);\n const [cardHover, setCardHover] = useState(false);\n const showNav = showImageNav && imageHover;\n const isChoose = variant === 'choose';\n const isSelected = isChoose && selected;\n const contentMuted = disabled || isSelected;\n const borderHeavy = cardHover || isSelected;\n\n const borderClass = borderHeavy ? 'border-border-heavy' : 'border-border-light';\n\n const primaryLabel = primaryActionLabel ?? 'Apply now';\n const secondaryLabel = secondaryActionLabel ?? 'View details';\n const chooseBtnLabel = chooseLabel ?? 'Choose';\n const selectedBtnLabel = selectedLabel ?? 'Selected';\n\n const rootClasses = [\n 'flex flex-col rounded-rad-md overflow-hidden bg-fill-bg-primary border border-solid pb-space-4 gap-space-4 w-full max-w-[288px]',\n borderClass,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n ref={forwardedRef}\n className={rootClasses}\n onMouseEnter={() => setCardHover(true)}\n onMouseLeave={() => setCardHover(false)}\n {...rest}\n >\n {/* Image block */}\n <div\n className=\"relative flex flex-col gap-3 bg-fill-bg-secondary p-space-8 rounded-tl-rad-md rounded-tr-rad-md\"\n onMouseEnter={() => setImageHover(true)}\n onMouseLeave={() => setImageHover(false)}\n >\n <div className=\"relative aspect-video w-full overflow-hidden shrink-0\">\n <Image\n src={imageSrc}\n alt={imageAlt}\n width={imageWidth}\n height={imageHeight}\n className=\"h-full w-full object-cover\"\n />\n </div>\n {showNav && (onPrevImage ?? onNextImage) && (\n <div className=\"absolute left-4 right-4 top-1/2 flex -translate-y-1/2 items-center justify-between pointer-events-none\">\n <span className=\"pointer-events-auto\">\n {onPrevImage && (\n <Button\n variant=\"inverse\"\n size=\"small\"\n iconOnly={<Icon name=\"chevron-left\" />}\n aria-label=\"Previous image\"\n onClick={onPrevImage}\n />\n )}\n </span>\n <span className=\"pointer-events-auto\">\n {onNextImage && (\n <Button\n variant=\"inverse\"\n size=\"small\"\n iconOnly={<Icon name=\"chevron-right\" />}\n aria-label=\"Next image\"\n onClick={onNextImage}\n />\n )}\n </span>\n </div>\n )}\n </div>\n\n {/* Head */}\n <div\n className={`flex flex-col gap-space-1 px-space-4 ${contentMuted ? 'text-text-disabled [&_.text-text-primary]:text-text-disabled [&_.text-text-secondary]:text-text-disabled' : ''}`}\n >\n <div className=\"flex flex-col\">\n <p className=\"text-title-md leading-[1.2] tracking-[0.19px] text-text-primary\">{name}</p>\n {brand != null && (\n <p className=\"text-text-sm leading-[1.4] tracking-[0.16px] text-text-secondary\">\n {brand}\n </p>\n )}\n </div>\n {description != null && (\n <p className=\"text-text-sm leading-[1.4] tracking-[0.16px] text-text-primary\">\n {description}\n </p>\n )}\n </div>\n\n <Divider variant=\"light\" className=\"my-0\" />\n\n {/* Specs */}\n {specs.length > 0 && (\n <>\n <div\n className={`flex flex-col gap-space-2 px-space-4 ${contentMuted ? 'text-text-disabled [&_*]:text-text-disabled' : ''}`}\n >\n {specs.map((spec, i) => (\n <div key={i} className=\"flex items-center gap-space-2\">\n <span className=\"shrink-0\">\n <Icon name=\"check\" size={10} />\n </span>\n <p className=\"text-text-xs tracking-[0.18px] leading-[1.4] min-w-0\">\n <SpecItem spec={spec} />\n </p>\n </div>\n ))}\n </div>\n <Divider variant=\"light\" className=\"my-0\" />\n </>\n )}\n\n {/* Price */}\n <div\n className={`flex flex-col gap-space-1 px-space-4 ${contentMuted ? 'text-text-disabled [&_*]:text-text-disabled' : ''}`}\n >\n <div className=\"flex items-center gap-space-1\">\n <p className=\"text-title-md leading-[1.2] tracking-[0.19px] text-text-primary whitespace-nowrap\">\n {priceDaily}\n </p>\n <p className=\"text-text-xs tracking-[0.18px] text-text-secondary\">{priceUnit}</p>\n </div>\n {priceTotal != null && (\n <p className=\"text-text-xs tracking-[0.18px] text-text-secondary whitespace-nowrap\">\n {priceTotal}\n </p>\n )}\n </div>\n\n <Divider variant=\"light\" className=\"my-0\" />\n\n {/* Action */}\n <div className=\"flex flex-col gap-space-2 px-space-4\">\n {variant === 'apply' && (\n <>\n {primaryActionHref != null ? (\n <Link\n href={primaryActionHref}\n as={linkAs}\n className=\"h-10 w-full items-center justify-center rounded-rad-sm bg-fill-action-primary text-text-action-primary hover:bg-fill-action-primary-hover text-btn-small no-underline\"\n >\n {primaryLabel}\n </Link>\n ) : (\n <Button\n variant=\"primary\"\n size=\"small\"\n disabled={disabled}\n className=\"w-full justify-center\"\n onClick={onPrimaryAction}\n >\n {primaryLabel}\n </Button>\n )}\n {secondaryActionHref != null ? (\n <Link\n href={secondaryActionHref}\n as={linkAs}\n className=\"h-10 w-full items-center justify-center rounded-rad-sm bg-fill-action-secondary text-text-action-secondary hover:bg-fill-action-secondary-hover text-btn-small no-underline\"\n >\n {secondaryLabel}\n </Link>\n ) : (\n <Button\n variant=\"secondary\"\n size=\"small\"\n disabled={disabled}\n className=\"w-full justify-center\"\n onClick={onSecondaryAction}\n >\n {secondaryLabel}\n </Button>\n )}\n </>\n )}\n {variant === 'choose' && (\n <Button\n variant=\"primary\"\n size=\"small\"\n disabled={disabled}\n className=\"w-full justify-center\"\n onClick={onChoose}\n >\n {selected ? selectedBtnLabel : chooseBtnLabel}\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Compound components for minimal typing\n// ---------------------------------------------------------------------------\n\ntype ProductCardApplyProps = Omit<ProductCardProps, 'variant'>;\ntype ProductCardChooseProps = Omit<ProductCardProps, 'variant'>;\n\nfunction ProductCardApply(props: ProductCardApplyProps, ref: React.Ref<HTMLDivElement>) {\n return <ProductCardBase {...(props as ProductCardProps)} variant=\"apply\" ref={ref} />;\n}\n\nfunction ProductCardChoose(props: ProductCardChooseProps, ref: React.Ref<HTMLDivElement>) {\n return <ProductCardBase {...(props as ProductCardProps)} variant=\"choose\" ref={ref} />;\n}\n\nconst ProductCardApplyWithRef = React.forwardRef(ProductCardApply);\nconst ProductCardChooseWithRef = React.forwardRef(ProductCardChoose);\n\nconst ProductCardBase = React.forwardRef(ProductCardInner);\n\nconst ProductCard = Object.assign(ProductCardBase, {\n Apply: ProductCardApplyWithRef,\n Choose: ProductCardChooseWithRef,\n}) as React.ForwardRefExoticComponent<\n Omit<ProductCardProps, 'ref'> & React.RefAttributes<HTMLDivElement>\n> & {\n Apply: typeof ProductCardApplyWithRef;\n Choose: typeof ProductCardChooseWithRef;\n};\n\nexport { ProductCard };\n"],"names":[],"mappings":";;;;;;;;AAqGA;AACE;AACE;AAAmB;AAErB;AAEI;AAAiB;AACgD;AAAA;AAAQ;AAAU;AAAC;AAG1F;AAoBA;AACE;AACY;AACV;AACW;AACE;AACC;AACC;AACf;AACA;AACA;AACA;AACA;AACQ;AACR;AACY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACW;AACA;AACF;AACG;AAEd;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AACA;AACA;AAEA;AAAoB;AAClB;AACA;AACA;AAKF;AACE;AAAC;AAAA;AACM;AACM;AAC0B;AACC;AAClC;AAGJ;AAAA;AAAC;AAAA;AACW;AAC4B;AACC;AAEvC;AACE;AAAC;AAAA;AACM;AACA;AACE;AACC;AACE;AAAA;AAEd;AAGI;AAEI;AAAC;AAAA;AACS;AACH;AAC+B;AACzB;AACF;AAAA;AAGf;AAGI;AAAC;AAAA;AACS;AACH;AACgC;AAC1B;AACF;AAAA;AAGf;AACF;AAAA;AAAA;AAAA;AAKJ;AAAC;AAAA;AACkL;AAEjL;AACE;AAAqF;AAInF;AAEJ;AAIE;AAAA;AAAA;AAAA;AAIsC;AAKtC;AAAA;AAAC;AAAA;AACqH;AAIhH;AAEA;AAGA;AAEH;AAAA;AAAA;AAEuC;AAC5C;AAIF;AAAC;AAAA;AACqH;AAEpH;AACE;AAEA;AAC6E;AAC/E;AAIE;AAAA;AAAA;AAAA;AAIsC;AAIvC;AAEI;AACC;AAAC;AAAA;AACO;AACF;AACM;AAET;AAAA;AAGH;AAAC;AAAA;AACS;AACH;AACL;AACU;AACD;AAER;AAAA;AAAA;AAIH;AAAC;AAAA;AACO;AACF;AACM;AAET;AAAA;AAGH;AAAC;AAAA;AACS;AACH;AACL;AACU;AACD;AAER;AAAA;AAAA;AAGP;AAGA;AAAC;AAAA;AACS;AACH;AACL;AACU;AACD;AAEsB;AAAA;AAAA;AAGrC;AAAA;AAAA;AAGN;AASA;AACE;AACF;AAEA;AACE;AACF;AAEA;AACA;AAEA;AAEA;AAAmD;AAC1C;AAET;;;;"}
@@ -0,0 +1,3 @@
1
+ export { ProductCard } from './ProductCard';
2
+ export type { ProductCardProps, ProductCardVariant, ProductCardSpec, } from './ProductCard';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ProductCard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,GAChB,MAAM,eAAe,CAAC"}
@@ -40,6 +40,8 @@ export { Toggle, ToggleButton } from './Toggle/Toggle';
40
40
  export type { ToggleProps, ToggleButtonProps, ToggleOption, ToggleSize } from './Toggle/Toggle';
41
41
  export { Card } from './Card/Card';
42
42
  export type { CardProps, CardType } from './Card/Card';
43
+ export { ProductCard } from './ProductCard';
44
+ export type { ProductCardProps, ProductCardVariant, ProductCardSpec } from './ProductCard';
43
45
  export { ProductImage, ProductImageGallery } from './ProductImage/ProductImage';
44
46
  export type { ProductImageProps, ProductImageGalleryProps, GalleryImage } from './ProductImage/ProductImage';
45
47
  export { Box } from './Box/Box';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjF,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE7E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEhG,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE3F,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAChF,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE7G,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE1F,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { Typography, Button, Link, Accordion, AccordionSpecs, FAQ, Tab, Grid, Container, Box, Stack, Divider, Overlay, Drawer, Popover, TextInput, TextArea, Select, SelectTab, DateInput, PhoneInput, EAST_AFRICA_COUNTRIES, UploadInput, RadioGroup, CheckboxGroup, Slider, Toggle, ToggleButton, Card, ProductImage, ProductImageGallery, Icon, Section, Skeleton, List, } from './components';
2
- export type { TypographyProps, ButtonProps, LinkProps, AccordionProps, AccordionSpecsProps, FAQProps, TabProps, GridProps, ContainerProps, ContainerMaxWidth, BoxProps, ResponsiveValue, StackProps, StackDirection, StackAlign, StackJustify, DividerProps, DividerOrientation, DividerVariant, OverlayProps, DrawerProps, DrawerAnchor, PopoverProps, PopoverAlign, TextInputProps, TextAreaProps, SelectProps, SelectOption, SelectTabProps, SelectTabOption, DateInputProps, DateValue, PhoneInputProps, PhoneCountry, UploadInputProps, RadioGroupProps, RadioOption, CheckboxGroupProps, CheckboxOption, SliderProps, ToggleProps, ToggleButtonProps, ToggleOption, ToggleSize, CardProps, CardType, ProductImageProps, ProductImageGalleryProps, GalleryImage, IconProps, IconName, SectionProps, SectionSize, SkeletonProps, SkeletonRadius, ListProps, ListItemProps, ListMarker, ListItemSize, } from './components';
1
+ export { Typography, Button, Link, Accordion, AccordionSpecs, FAQ, Tab, Grid, Container, Box, Stack, Divider, Overlay, Drawer, Popover, TextInput, TextArea, Select, SelectTab, DateInput, PhoneInput, EAST_AFRICA_COUNTRIES, UploadInput, RadioGroup, CheckboxGroup, Slider, Toggle, ToggleButton, Card, ProductCard, ProductImage, ProductImageGallery, Icon, Section, Skeleton, List, } from './components';
2
+ export type { TypographyProps, ButtonProps, LinkProps, AccordionProps, AccordionSpecsProps, FAQProps, TabProps, GridProps, ContainerProps, ContainerMaxWidth, BoxProps, ResponsiveValue, StackProps, StackDirection, StackAlign, StackJustify, DividerProps, DividerOrientation, DividerVariant, OverlayProps, DrawerProps, DrawerAnchor, PopoverProps, PopoverAlign, TextInputProps, TextAreaProps, SelectProps, SelectOption, SelectTabProps, SelectTabOption, DateInputProps, DateValue, PhoneInputProps, PhoneCountry, UploadInputProps, RadioGroupProps, RadioOption, CheckboxGroupProps, CheckboxOption, SliderProps, ToggleProps, ToggleButtonProps, ToggleOption, ToggleSize, CardProps, CardType, ProductCardProps, ProductCardVariant, ProductCardSpec, ProductImageProps, ProductImageGalleryProps, GalleryImage, IconProps, IconName, SectionProps, SectionSize, SkeletonProps, SkeletonRadius, ListProps, ListItemProps, ListMarker, ListItemSize, } from './components';
3
3
  export type { TypographyVariant, ButtonVariant, ButtonSize, LinkVariant, LinkSize, AccordionItem, AccordionVariant, AccordionSpecItem, FAQItem, TabItem, } from './types';
4
4
  export type { FixedSpacingToken, FluidSpacingToken, SpacingToken, MarginToken, SpacingProps, GapProps, } from './types/spacing';
5
5
  export type { DisplayValue, AlignItemsValue, JustifyContentValue, FlexDirectionValue, FlexWrapValue, AlignSelfValue, LayoutProps, StackLayoutProps, } from './types/layout';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,MAAM,EACN,IAAI,EACJ,SAAS,EACT,cAAc,EACd,GAAG,EACH,GAAG,EACH,IAAI,EACJ,SAAS,EACT,GAAG,EACH,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,WAAW,EACX,UAAU,EACV,aAAa,EACb,MAAM,EACN,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,mBAAmB,EACnB,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,IAAI,GACL,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,UAAU,EACV,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,WAAW,EACX,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,OAAO,GACR,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,WAAW,EACX,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACV,oBAAoB,EACpB,aAAa,GACd,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,MAAM,EACN,IAAI,EACJ,SAAS,EACT,cAAc,EACd,GAAG,EACH,GAAG,EACH,IAAI,EACJ,SAAS,EACT,GAAG,EACH,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,WAAW,EACX,UAAU,EACV,aAAa,EACb,MAAM,EACN,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,IAAI,GACL,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,QAAQ,EACR,eAAe,EACf,UAAU,EACV,cAAc,EACd,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,EACT,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,aAAa,EACb,UAAU,EACV,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,WAAW,EACX,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,EACP,OAAO,GACR,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,WAAW,EACX,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACV,oBAAoB,EACpB,aAAa,GACd,MAAM,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import { Link } from "./components/Link/Link.js";
15
15
  import { List } from "./components/List/List.js";
16
16
  import { Overlay } from "./components/Overlay/Overlay.js";
17
17
  import { Popover } from "./components/Popover/Popover.js";
18
+ import { ProductCard } from "./components/ProductCard/ProductCard.js";
18
19
  import { ProductImage, ProductImageGallery } from "./components/ProductImage/ProductImage.js";
19
20
  import { RadioGroup } from "./components/RadioGroup/RadioGroup.js";
20
21
  import { Section } from "./components/Section/Section.js";
@@ -49,6 +50,7 @@ export {
49
50
  Overlay,
50
51
  PhoneInput,
51
52
  Popover,
53
+ ProductCard,
52
54
  ProductImage,
53
55
  ProductImageGallery,
54
56
  RadioGroup,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jiwambe/components",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -92,6 +92,6 @@
92
92
  "test": "vitest run",
93
93
  "test:watch": "vitest",
94
94
  "version-packages": "changeset version",
95
- "release": "pnpm run build && changeset publish"
95
+ "release": "pnpm test && pnpm run build && changeset publish"
96
96
  }
97
97
  }