@q2devel/q2-storybook 1.0.11 → 1.0.13

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,55 @@
1
+ import React from 'react';
2
+ export type BasketProduct = {
3
+ id: string;
4
+ name: string;
5
+ price: number;
6
+ quantity: number;
7
+ image?: {
8
+ src: string;
9
+ alt: string;
10
+ };
11
+ href?: string;
12
+ color?: string;
13
+ [key: string]: any;
14
+ };
15
+ export type BasketDialogVariant = 'default' | 'compact' | 'full';
16
+ export type BasketDialogPosition = 'right' | 'left';
17
+ export type BasketDialogProps = {
18
+ isOpen: boolean;
19
+ onClose: () => void;
20
+ products: BasketProduct[];
21
+ subtotal: string | number;
22
+ onQuantityChange?: (productId: string, quantity: number) => void;
23
+ onRemoveProduct?: (productId: string) => void;
24
+ onCheckout?: () => void;
25
+ onContinueShopping?: () => void;
26
+ onProductClick?: (product: BasketProduct) => void;
27
+ title?: string;
28
+ checkoutText?: string;
29
+ continueShoppingText?: string;
30
+ emptyCartText?: string;
31
+ quantityLabel?: string;
32
+ removeButtonText?: string;
33
+ totalLabel?: string;
34
+ shippingNoteText?: string;
35
+ variant?: BasketDialogVariant;
36
+ position?: BasketDialogPosition;
37
+ showProductImages?: boolean;
38
+ showProductColors?: boolean;
39
+ showProductLinks?: boolean;
40
+ showRemoveButton?: boolean;
41
+ showSubtotal?: boolean;
42
+ showCheckoutButton?: boolean;
43
+ showContinueShoppingButton?: boolean;
44
+ showShippingNote?: boolean;
45
+ showQuantityControls?: boolean;
46
+ customClassName?: string;
47
+ maxHeight?: string;
48
+ animationDuration?: number;
49
+ backdropOpacity?: number;
50
+ renderCustomProduct?: (product: BasketProduct) => React.ReactNode;
51
+ renderCustomFooter?: () => React.ReactNode;
52
+ pendingUpdates?: Record<string, number>;
53
+ processingItems?: Record<string, boolean>;
54
+ };
55
+ export declare const BasketDialog: ({ isOpen, onClose, products, subtotal, onQuantityChange, onRemoveProduct, onCheckout, onContinueShopping, onProductClick, title, checkoutText, continueShoppingText, emptyCartText, quantityLabel, removeButtonText, totalLabel, shippingNoteText, variant, position, showProductImages, showProductColors, showProductLinks, showRemoveButton, showSubtotal, showCheckoutButton, showContinueShoppingButton, showShippingNote, showQuantityControls, customClassName, maxHeight, animationDuration, backdropOpacity, renderCustomProduct, renderCustomFooter, pendingUpdates, processingItems, }: BasketDialogProps) => React.JSX.Element;
@@ -0,0 +1,167 @@
1
+ 'use client';
2
+ import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
3
+ import { MinusIcon, PlusIcon, XMarkIcon } from '@heroicons/react/24/outline';
4
+ import React from 'react';
5
+ // Helper funkcia pre formátovanie ceny
6
+ var formatPrice = function (price) {
7
+ return new Intl.NumberFormat('cs-CZ', {
8
+ style: 'currency',
9
+ currency: 'CZK',
10
+ }).format(price);
11
+ };
12
+ export var BasketDialog = function (_a) {
13
+ var
14
+ // Základné props
15
+ isOpen = _a.isOpen, onClose = _a.onClose, products = _a.products, subtotal = _a.subtotal,
16
+ // Callback funkcie
17
+ onQuantityChange = _a.onQuantityChange, onRemoveProduct = _a.onRemoveProduct, onCheckout = _a.onCheckout, onContinueShopping = _a.onContinueShopping, onProductClick = _a.onProductClick,
18
+ // Texty s predvolenými hodnotami
19
+ _b = _a.title,
20
+ // Texty s predvolenými hodnotami
21
+ title = _b === void 0 ? 'Váš košík' : _b, _c = _a.checkoutText, checkoutText = _c === void 0 ? 'Pokračovat k objednávce' : _c, _d = _a.continueShoppingText, continueShoppingText = _d === void 0 ? 'Pokračovat v nákupu' : _d, _e = _a.emptyCartText, emptyCartText = _e === void 0 ? 'Váš košík je prázdný' : _e, _f = _a.quantityLabel, quantityLabel = _f === void 0 ? 'Množství:' : _f, _g = _a.removeButtonText, removeButtonText = _g === void 0 ? 'Odstranit' : _g, _h = _a.totalLabel, totalLabel = _h === void 0 ? 'Celkem' : _h, _j = _a.shippingNoteText, shippingNoteText = _j === void 0 ? 'Doprava a daně budou vypočítány při dokončení objednávky.' : _j,
22
+ // Zobrazenie/konfigurácia s predvolenými hodnotami
23
+ _k = _a.variant,
24
+ // Zobrazenie/konfigurácia s predvolenými hodnotami
25
+ variant = _k === void 0 ? 'default' : _k, _l = _a.position, position = _l === void 0 ? 'right' : _l, _m = _a.showProductImages, showProductImages = _m === void 0 ? true : _m, _o = _a.showProductColors, showProductColors = _o === void 0 ? true : _o, _p = _a.showProductLinks, showProductLinks = _p === void 0 ? true : _p, _q = _a.showRemoveButton, showRemoveButton = _q === void 0 ? true : _q, _r = _a.showSubtotal, showSubtotal = _r === void 0 ? true : _r, _s = _a.showCheckoutButton, showCheckoutButton = _s === void 0 ? true : _s, _t = _a.showContinueShoppingButton, showContinueShoppingButton = _t === void 0 ? true : _t, _u = _a.showShippingNote, showShippingNote = _u === void 0 ? true : _u, _v = _a.showQuantityControls, showQuantityControls = _v === void 0 ? true : _v,
26
+ // Štýlovanie s predvolenými hodnotami
27
+ _w = _a.customClassName,
28
+ // Štýlovanie s predvolenými hodnotami
29
+ customClassName = _w === void 0 ? '' : _w, _x = _a.maxHeight, maxHeight = _x === void 0 ? '100vh' : _x, _y = _a.animationDuration, animationDuration = _y === void 0 ? 500 : _y, _z = _a.backdropOpacity, backdropOpacity = _z === void 0 ? 0.75 : _z,
30
+ // Vlastné renderovanie
31
+ renderCustomProduct = _a.renderCustomProduct, renderCustomFooter = _a.renderCustomFooter,
32
+ // Stav
33
+ _0 = _a.pendingUpdates,
34
+ // Stav
35
+ pendingUpdates = _0 === void 0 ? {} : _0, _1 = _a.processingItems, processingItems = _1 === void 0 ? {} : _1;
36
+ var handleCheckout = function () {
37
+ if (onCheckout) {
38
+ onCheckout();
39
+ }
40
+ };
41
+ var handleContinueShopping = function () {
42
+ if (onContinueShopping) {
43
+ onContinueShopping();
44
+ }
45
+ else {
46
+ onClose();
47
+ }
48
+ };
49
+ var handleIncrement = function (productId, quantity) {
50
+ if (onQuantityChange) {
51
+ onQuantityChange(productId, quantity + 1);
52
+ }
53
+ };
54
+ var handleDecrement = function (productId, quantity) {
55
+ if (onQuantityChange) {
56
+ if (quantity > 1) {
57
+ onQuantityChange(productId, quantity - 1);
58
+ }
59
+ else {
60
+ onQuantityChange(productId, 0);
61
+ }
62
+ }
63
+ };
64
+ var getVariantClasses = function () {
65
+ switch (variant) {
66
+ case 'compact':
67
+ return 'max-w-sm';
68
+ case 'full':
69
+ return 'max-w-2xl';
70
+ default:
71
+ return 'max-w-md';
72
+ }
73
+ };
74
+ var getPositionClasses = function () {
75
+ return position === 'left' ? 'left-0' : 'right-0';
76
+ };
77
+ return (React.createElement(Dialog, { open: isOpen, onClose: onClose, className: "relative z-60" },
78
+ React.createElement(DialogBackdrop, { transition: true, className: "fixed inset-0 bg-gray-500/75 transition-opacity duration-".concat(animationDuration, " ease-in-out data-closed:opacity-0"), style: { opacity: backdropOpacity } }),
79
+ React.createElement("div", { className: "fixed inset-0 overflow-hidden" },
80
+ React.createElement("div", { className: "absolute inset-0 overflow-hidden" },
81
+ React.createElement("div", { className: "pointer-events-none fixed inset-y-0 ".concat(getPositionClasses(), " flex max-w-full pl-10") },
82
+ React.createElement(DialogPanel, { transition: true, className: "pointer-events-auto w-screen ".concat(getVariantClasses(), " transform transition duration-").concat(animationDuration, " ease-in-out data-closed:translate-x-full sm:duration-700 ").concat(customClassName) },
83
+ React.createElement("div", { className: "flex h-full flex-col overflow-y-scroll bg-white shadow-xl", style: { maxHeight: maxHeight } },
84
+ React.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-6 sm:px-6" },
85
+ React.createElement("div", { className: "flex items-start justify-between" },
86
+ React.createElement(DialogTitle, { className: "text-lg font-medium text-gray-900" }, title),
87
+ React.createElement("div", { className: "ml-3 flex h-7 items-center" },
88
+ React.createElement("button", { type: "button", onClick: onClose, className: "relative -m-2 p-2 text-gray-400 hover:text-gray-500" },
89
+ React.createElement("span", { className: "absolute -inset-0.5" }),
90
+ React.createElement("span", { className: "sr-only" }, "Close panel"),
91
+ React.createElement(XMarkIcon, { "aria-hidden": "true", className: "size-6" })))),
92
+ React.createElement("div", { className: "mt-8" },
93
+ React.createElement("div", { className: "flow-root" }, products.length === 0 ? (React.createElement("div", { className: "py-6 text-center text-gray-500" }, emptyCartText)) : (React.createElement("ul", { role: "list", className: "-my-6 divide-y divide-gray-200" }, products.map(function (product) {
94
+ if (renderCustomProduct) {
95
+ return renderCustomProduct(product);
96
+ }
97
+ var displayQuantity = product.id in pendingUpdates
98
+ ? pendingUpdates[product.id]
99
+ : product.quantity;
100
+ var isProcessing = processingItems[product.id] === true;
101
+ return (React.createElement("li", { key: product.id, className: "flex py-6" },
102
+ showProductImages &&
103
+ product.image && (React.createElement("div", { className: "size-24 shrink-0 overflow-hidden rounded-md border border-gray-200" },
104
+ React.createElement("img", { alt: product.image
105
+ .alt, src: product.image
106
+ .src, className: "size-full object-cover" }))),
107
+ React.createElement("div", { className: "ml-4 flex flex-1 flex-col" },
108
+ React.createElement("div", null,
109
+ React.createElement("div", { className: "flex justify-between text-base font-medium text-gray-900" },
110
+ React.createElement("h3", null, showProductLinks &&
111
+ product.href ? (React.createElement("a", { href: product.href, onClick: function (e) {
112
+ if (onProductClick) {
113
+ e.preventDefault();
114
+ onProductClick(product);
115
+ }
116
+ } }, product.name)) : (product.name)),
117
+ React.createElement("p", { className: "ml-4" }, formatPrice(product.price))),
118
+ showProductColors &&
119
+ product.color && (React.createElement("p", { className: "mt-1 text-sm text-gray-500" }, product.color))),
120
+ React.createElement("div", { className: "flex flex-1 items-end justify-between text-sm" },
121
+ showQuantityControls &&
122
+ onQuantityChange ? (React.createElement("div", { className: "flex items-center gap-2" },
123
+ React.createElement("p", { className: "text-gray-500 mr-2" }, quantityLabel),
124
+ React.createElement("div", { className: "flex items-center" },
125
+ React.createElement("button", { type: "button", onClick: function () {
126
+ return !isProcessing &&
127
+ handleDecrement(product.id, displayQuantity);
128
+ }, disabled: isProcessing, className: "rounded-full p-1 text-gray-600 ".concat(isProcessing
129
+ ? 'bg-gray-100 cursor-not-allowed opacity-50'
130
+ : 'bg-gray-200 hover:bg-gray-300') },
131
+ React.createElement(MinusIcon, { className: "h-4 w-4" })),
132
+ React.createElement("span", { className: "mx-2 min-w-[20px] text-center text-black" }, displayQuantity),
133
+ React.createElement("button", { type: "button", onClick: function () {
134
+ return !isProcessing &&
135
+ handleIncrement(product.id, displayQuantity);
136
+ }, disabled: isProcessing, className: "rounded-full p-1 text-gray-600 ".concat(isProcessing
137
+ ? 'bg-gray-100 cursor-not-allowed opacity-50'
138
+ : 'bg-gray-200 hover:bg-gray-300') },
139
+ React.createElement(PlusIcon, { className: "h-4 w-4" }))))) : (React.createElement("p", { className: "text-gray-500" },
140
+ quantityLabel,
141
+ ' ',
142
+ displayQuantity)),
143
+ showRemoveButton &&
144
+ onRemoveProduct && (React.createElement("div", { className: "flex" },
145
+ React.createElement("button", { type: "button", className: "font-medium ".concat(isProcessing
146
+ ? 'text-gray-400 cursor-not-allowed'
147
+ : 'text-green-600 hover:text-green-500'), onClick: function () {
148
+ return !isProcessing &&
149
+ onRemoveProduct(product.id);
150
+ }, disabled: isProcessing }, removeButtonText)))))));
151
+ })))))),
152
+ React.createElement("div", { className: "border-t border-gray-200 px-4 py-6 sm:px-6" },
153
+ showSubtotal && (React.createElement("div", { className: "flex justify-between text-base font-medium text-gray-900" },
154
+ React.createElement("p", null, totalLabel),
155
+ React.createElement("p", null, typeof subtotal === 'number'
156
+ ? formatPrice(subtotal)
157
+ : subtotal))),
158
+ showShippingNote && (React.createElement("p", { className: "mt-0.5 text-sm text-gray-500" }, shippingNoteText)),
159
+ products.length > 0 && showCheckoutButton && onCheckout && (React.createElement("div", { className: "mt-6" },
160
+ React.createElement("button", { onClick: handleCheckout, className: "flex w-full items-center justify-center rounded-md border border-transparent bg-green-600 px-6 py-3 text-base font-medium text-white shadow-xs hover:bg-green-700" }, checkoutText))),
161
+ showContinueShoppingButton && (React.createElement("div", { className: "mt-6 flex justify-center text-center text-sm text-gray-500" },
162
+ React.createElement("p", null,
163
+ React.createElement("button", { type: "button", onClick: handleContinueShopping, className: "font-medium text-green-600 hover:text-green-500" },
164
+ continueShoppingText,
165
+ React.createElement("span", { "aria-hidden": "true" }, " \u2192"))))),
166
+ renderCustomFooter && renderCustomFooter()))))))));
167
+ };
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q2devel/q2-storybook",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,12 +14,12 @@
14
14
  "dist"
15
15
  ],
16
16
  "scripts": {
17
- "test": "echo \"Error: no test specified\" && exit 1",
18
- "storybook": "storybook dev -p 6006",
19
- "build-storybook": "storybook build",
20
- "build": "tsc",
21
- "prepublishOnly": "npm run build"
22
- },
17
+ "test": "echo \"Error: no test specified\" && exit 1",
18
+ "storybook": "storybook dev -p 6006",
19
+ "build-storybook": "storybook build",
20
+ "build": "tsc",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
23
  "keywords": [],
24
24
  "author": "Q2",
25
25
  "license": "ISC",
@@ -51,6 +51,7 @@
51
51
  "react-dom": "^19.0.0"
52
52
  },
53
53
  "dependencies": {
54
+ "@headlessui/react": "^2.2.2",
54
55
  "@heroicons/react": "^2.2.0",
55
56
  "@tailwindcss/postcss": "^4.1.4",
56
57
  "classnames": "^2.5.1",