@q2devel/q2-storybook 1.0.84 → 1.0.86
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/components/Base/button/Button.d.ts +3 -3
- package/dist/components/Base/button/Button.js +4 -2
- package/dist/components/Base/tooltip/Tooltip.d.ts +35 -13
- package/dist/components/Base/tooltip/Tooltip.js +145 -18
- package/dist/components/Ecommerce/basket-dialog/BasketDialog.d.ts +27 -39
- package/dist/components/Ecommerce/basket-dialog/BasketDialog.js +62 -71
- package/dist/components/Ecommerce/basket-overview/BasketOverview.d.ts +34 -0
- package/dist/components/Ecommerce/basket-overview/BasketOverview.js +38 -0
- package/dist/components/Ecommerce/product-detail/ProductDetail.js +3 -2
- package/dist/components/Forms/checkbox/Checkbox.d.ts +29 -0
- package/dist/components/Forms/checkbox/Checkbox.js +99 -0
- package/dist/components/Forms/checkbox/CheckboxGroup.d.ts +9 -0
- package/dist/components/Forms/checkbox/CheckboxGroup.js +29 -0
- package/dist/components/Forms/checkbox/NumCheckbox.d.ts +19 -0
- package/dist/components/Forms/checkbox/NumCheckbox.js +14 -0
- package/dist/components/Forms/select-field/SelectField.js +2 -2
- package/dist/components/Web/nav-bar/NavBar.d.ts +2 -1
- package/dist/components/Web/nav-bar/NavBar.js +2 -2
- package/dist/components/Web/web-section/WebSection.d.ts +4 -1
- package/dist/components/Web/web-section/WebSection.js +4 -4
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface ButtonProps {
|
|
1
|
+
import React, { ButtonHTMLAttributes } from 'react';
|
|
2
|
+
export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
|
|
3
3
|
children?: React.ReactNode;
|
|
4
4
|
label?: string;
|
|
5
5
|
variant?: 'primary' | 'secondary';
|
|
@@ -18,5 +18,5 @@ export interface ButtonProps {
|
|
|
18
18
|
rel?: string;
|
|
19
19
|
unstyled?: boolean;
|
|
20
20
|
}
|
|
21
|
-
declare const Button:
|
|
21
|
+
declare const Button: ({ children, label, variant, disabled, asLink, openInNewTab, href, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, rounded, className, target, rel, unstyled, type, ...restProps }: ButtonProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
22
22
|
export default Button;
|
|
@@ -14,7 +14,9 @@ const variantClasses = {
|
|
|
14
14
|
primary: 'bg-blue-500 hover:bg-blue-600 text-white',
|
|
15
15
|
secondary: 'bg-gray-500 hover:bg-gray-600 text-white',
|
|
16
16
|
};
|
|
17
|
-
const Button = ({ children, label, variant, disabled = false, asLink = false, openInNewTab = false, href, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, rounded = 'md', className = '', target, rel, unstyled = false,
|
|
17
|
+
const Button = ({ children, label, variant, disabled = false, asLink = false, openInNewTab = false, href, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, rounded = 'md', className = '', target, rel, unstyled = false, type = 'button', // ← Teraz má default z natívneho button
|
|
18
|
+
...restProps // ← Všetky ostatné natívne props
|
|
19
|
+
}) => {
|
|
18
20
|
const baseClasses = unstyled
|
|
19
21
|
? className
|
|
20
22
|
: buildClassesByJoining('inline-block px-4 py-2 font-medium transition-colors duration-200', variantClasses[variant ?? 'primary'], roundedClasses[rounded], {
|
|
@@ -40,6 +42,6 @@ const Button = ({ children, label, variant, disabled = false, asLink = false, op
|
|
|
40
42
|
}
|
|
41
43
|
return (_jsx(Link, { href: href, ...commonProps, target: openInNewTab ? '_blank' : target, rel: openInNewTab ? 'noopener noreferrer' : rel, children: content }));
|
|
42
44
|
}
|
|
43
|
-
return (_jsx("button", { ...commonProps, disabled: disabled, children: content }));
|
|
45
|
+
return (_jsx("button", { ...commonProps, ...restProps, disabled: disabled, type: type, children: content }));
|
|
44
46
|
};
|
|
45
47
|
export default Button;
|
|
@@ -1,18 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { Placement, Strategy } from '@floating-ui/react';
|
|
2
|
+
import { HTMLAttributes, ReactNode, Ref } from 'react';
|
|
3
|
+
export type TooltipRef = {
|
|
4
|
+
open: () => void;
|
|
5
|
+
close: () => void;
|
|
6
|
+
};
|
|
7
|
+
export type TooltipChildren = ((ref: Ref<HTMLElement>, props: Record<string, unknown>, disabled: boolean) => ReactNode) | ReactNode;
|
|
8
|
+
export type TooltipProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'content'> & {
|
|
9
|
+
content: ((ref: Ref<HTMLElement>, props: Record<string, unknown>) => ReactNode) | ReactNode;
|
|
10
|
+
children: TooltipChildren;
|
|
11
|
+
placement?: Placement;
|
|
12
|
+
strategy?: Strategy;
|
|
13
|
+
contentClassName?: string;
|
|
14
|
+
zIndex?: number;
|
|
15
|
+
portalTarget?: HTMLElement;
|
|
10
16
|
backgroundColor?: string;
|
|
11
17
|
textColor?: string;
|
|
12
|
-
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
disableAutoHide?: boolean;
|
|
20
|
+
lazy?: boolean;
|
|
21
|
+
size?: 'sm' | 'md' | 'lg';
|
|
22
|
+
variant?: 'default' | 'dark' | 'light' | 'error' | 'warning' | 'success';
|
|
23
|
+
};
|
|
24
|
+
declare const _default: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "children" | "content"> & {
|
|
25
|
+
content: ((ref: Ref<HTMLElement>, props: Record<string, unknown>) => ReactNode) | ReactNode;
|
|
26
|
+
children: TooltipChildren;
|
|
27
|
+
placement?: Placement;
|
|
28
|
+
strategy?: Strategy;
|
|
13
29
|
contentClassName?: string;
|
|
30
|
+
zIndex?: number;
|
|
31
|
+
portalTarget?: HTMLElement;
|
|
32
|
+
backgroundColor?: string;
|
|
33
|
+
textColor?: string;
|
|
14
34
|
disabled?: boolean;
|
|
35
|
+
disableAutoHide?: boolean;
|
|
15
36
|
lazy?: boolean;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
37
|
+
size?: "sm" | "md" | "lg";
|
|
38
|
+
variant?: "default" | "dark" | "light" | "error" | "warning" | "success";
|
|
39
|
+
} & import("react").RefAttributes<TooltipRef>>;
|
|
40
|
+
export default _default;
|
|
@@ -1,18 +1,145 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import buildClassesByJoining from '@/utils/StyleHelper';
|
|
3
|
+
import { FloatingPortal, arrow, autoUpdate, hide, offset, safePolygon, shift, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole, useTransitionStyles, } from '@floating-ui/react';
|
|
4
|
+
import { forwardRef, useImperativeHandle, useRef, useState, } from 'react';
|
|
5
|
+
const Tooltip = ({ className, children, content, placement = 'top', strategy: strategyProp = 'absolute', contentClassName, zIndex = 30, portalTarget, backgroundColor, textColor, disabled = false, disableAutoHide, lazy = true, size = 'md', variant = 'default', ...props }, ref) => {
|
|
6
|
+
const [open, setOpen] = useState(false);
|
|
7
|
+
const arrowRef = useRef(null);
|
|
8
|
+
const { x, y, refs, strategy, context, middlewareData: { arrow: { x: arrowX, y: arrowY } = {}, hide: hideMiddleware }, placement: floatingPlacement, } = useFloating({
|
|
9
|
+
open: open,
|
|
10
|
+
onOpenChange: (value) => {
|
|
11
|
+
return disabled ? setOpen(false) : setOpen(disableAutoHide || value);
|
|
12
|
+
},
|
|
13
|
+
placement: placement,
|
|
14
|
+
strategy: strategyProp,
|
|
15
|
+
whileElementsMounted: autoUpdate,
|
|
16
|
+
middleware: [
|
|
17
|
+
offset(5),
|
|
18
|
+
shift(),
|
|
19
|
+
arrow({
|
|
20
|
+
element: arrowRef.current,
|
|
21
|
+
}),
|
|
22
|
+
hide(),
|
|
23
|
+
],
|
|
24
|
+
});
|
|
25
|
+
const { isMounted, styles } = useTransitionStyles(context);
|
|
26
|
+
const hover = useHover(context, {
|
|
27
|
+
move: false,
|
|
28
|
+
handleClose: safePolygon(),
|
|
29
|
+
});
|
|
30
|
+
const focus = useFocus(context);
|
|
31
|
+
const dismiss = useDismiss(context);
|
|
32
|
+
const role = useRole(context, { role: 'tooltip' });
|
|
33
|
+
const { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, dismiss, role]);
|
|
34
|
+
useImperativeHandle(ref, () => {
|
|
35
|
+
return {
|
|
36
|
+
open() {
|
|
37
|
+
setOpen(true);
|
|
38
|
+
},
|
|
39
|
+
close() {
|
|
40
|
+
setOpen(false);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
// Get variant-based colors
|
|
45
|
+
const getVariantColors = () => {
|
|
46
|
+
const variants = {
|
|
47
|
+
default: {
|
|
48
|
+
bg: backgroundColor || '#374151', // gray-700
|
|
49
|
+
text: textColor || '#ffffff',
|
|
50
|
+
},
|
|
51
|
+
dark: {
|
|
52
|
+
bg: backgroundColor || '#1f2937', // gray-800
|
|
53
|
+
text: textColor || '#ffffff',
|
|
54
|
+
},
|
|
55
|
+
light: {
|
|
56
|
+
bg: backgroundColor || '#f9fafb', // gray-50
|
|
57
|
+
text: textColor || '#374151', // gray-700
|
|
58
|
+
},
|
|
59
|
+
error: {
|
|
60
|
+
bg: backgroundColor || '#dc2626', // red-600
|
|
61
|
+
text: textColor || '#ffffff',
|
|
62
|
+
},
|
|
63
|
+
warning: {
|
|
64
|
+
bg: backgroundColor || '#d97706', // amber-600
|
|
65
|
+
text: textColor || '#ffffff',
|
|
66
|
+
},
|
|
67
|
+
success: {
|
|
68
|
+
bg: backgroundColor || '#059669', // emerald-600
|
|
69
|
+
text: textColor || '#ffffff',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
return variants[variant];
|
|
73
|
+
};
|
|
74
|
+
const colors = getVariantColors();
|
|
75
|
+
// Tooltip content classes based on size and variant
|
|
76
|
+
const tooltipClasses = buildClassesByJoining([
|
|
77
|
+
// Base classes
|
|
78
|
+
'rounded-md leading-tight shadow-2xl z-10 relative',
|
|
79
|
+
// Size variations
|
|
80
|
+
size === 'sm' && 'text-xs px-1.5 py-1',
|
|
81
|
+
size === 'md' && 'text-sm px-2 py-1.5',
|
|
82
|
+
size === 'lg' && 'text-base px-3 py-2',
|
|
83
|
+
// Image max width
|
|
84
|
+
'[&_img]:max-w-[420px]',
|
|
85
|
+
contentClassName,
|
|
86
|
+
]);
|
|
87
|
+
const tooltipStyles = {
|
|
88
|
+
zIndex,
|
|
89
|
+
display: (isMounted &&
|
|
90
|
+
hideMiddleware &&
|
|
91
|
+
!hideMiddleware.escaped &&
|
|
92
|
+
!hideMiddleware.referenceHidden) ||
|
|
93
|
+
lazy
|
|
94
|
+
? 'block'
|
|
95
|
+
: 'none',
|
|
96
|
+
position: strategy,
|
|
97
|
+
top: y ?? 0,
|
|
98
|
+
left: x ?? 0,
|
|
99
|
+
color: colors.text,
|
|
100
|
+
backgroundColor: colors.bg,
|
|
101
|
+
boxShadow: '0 12px 32px 10px rgba(9, 9, 9, 0.09)',
|
|
102
|
+
...styles,
|
|
103
|
+
};
|
|
104
|
+
const getAllReferenceProps = () => {
|
|
105
|
+
return {
|
|
106
|
+
...getReferenceProps(),
|
|
107
|
+
ref: refs.setReference,
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
const arrowSide = {
|
|
111
|
+
top: 'bottom',
|
|
112
|
+
right: 'left',
|
|
113
|
+
bottom: 'top',
|
|
114
|
+
left: 'right',
|
|
115
|
+
}[floatingPlacement.split('-')[0]] || 'bottom';
|
|
116
|
+
const renderChildren = () => {
|
|
117
|
+
if (typeof children === 'function') {
|
|
118
|
+
return children(refs.setReference, getReferenceProps(), disabled);
|
|
119
|
+
}
|
|
120
|
+
return (_jsx("div", { ...props, ...getAllReferenceProps(), className: buildClassesByJoining(['inline-block', className]), children: children }));
|
|
121
|
+
};
|
|
122
|
+
const renderTooltipContent = () => {
|
|
123
|
+
if (disabled || (lazy && !isMounted)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (typeof content === 'function') {
|
|
127
|
+
return content(refs.setFloating, {
|
|
128
|
+
style: tooltipStyles,
|
|
129
|
+
...getFloatingProps(),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return (_jsxs("div", { className: tooltipClasses, ref: refs.setFloating, style: tooltipStyles, ...getFloatingProps(), children: [_jsx("span", { className: "relative z-10", dangerouslySetInnerHTML: typeof content === 'string' ? { __html: content } : undefined, children: typeof content !== 'string' ? content : null }), _jsx("div", { ref: arrowRef, style: {
|
|
133
|
+
position: 'absolute',
|
|
134
|
+
width: '10px',
|
|
135
|
+
height: '10px',
|
|
136
|
+
backgroundColor: colors.bg,
|
|
137
|
+
left: arrowX != null ? `${arrowX}px` : '0px',
|
|
138
|
+
top: arrowY != null ? `${arrowY}px` : '0px',
|
|
139
|
+
[arrowSide]: '-5px',
|
|
140
|
+
transform: 'rotate(45deg)',
|
|
141
|
+
} })] }));
|
|
142
|
+
};
|
|
143
|
+
return (_jsxs(_Fragment, { children: [_jsx(FloatingPortal, { root: portalTarget, children: renderTooltipContent() }), renderChildren()] }));
|
|
144
|
+
};
|
|
145
|
+
export default forwardRef(Tooltip);
|
|
@@ -1,55 +1,43 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
name: string;
|
|
5
|
-
price: number;
|
|
1
|
+
import { PriceFormatOptions } from '@/utils/generalHelperFunction';
|
|
2
|
+
import { Product } from '@q2devel/q2-core';
|
|
3
|
+
export type BasketProduct = Omit<Product, 'price'> & {
|
|
6
4
|
quantity: number;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
[key: string]: any;
|
|
5
|
+
price: number;
|
|
6
|
+
formattedPrice?: string;
|
|
7
|
+
order_item_id: string;
|
|
8
|
+
};
|
|
9
|
+
export type BasketProductExtended = BasketProduct & {
|
|
10
|
+
drupalOrderItemId?: number;
|
|
14
11
|
};
|
|
15
|
-
export type BasketDialogVariant = "default" | "compact" | "full";
|
|
16
|
-
export type BasketDialogPosition = "right" | "left";
|
|
17
12
|
export type BasketDialogProps = {
|
|
18
13
|
isOpen: boolean;
|
|
19
14
|
onClose: () => void;
|
|
20
15
|
products: BasketProduct[];
|
|
21
|
-
subtotal:
|
|
22
|
-
onQuantityChange?: (
|
|
23
|
-
onRemoveProduct?: (
|
|
16
|
+
subtotal: number;
|
|
17
|
+
onQuantityChange?: (productUuid: string, quantity: number) => void;
|
|
18
|
+
onRemoveProduct?: (productUuid: string) => void;
|
|
24
19
|
onCheckout?: () => void;
|
|
25
20
|
onContinueShopping?: () => void;
|
|
26
|
-
|
|
21
|
+
productLink?: (productName: string, variationId: string) => string;
|
|
27
22
|
title?: string;
|
|
28
23
|
checkoutText?: string;
|
|
29
24
|
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
25
|
showShippingNote?: boolean;
|
|
45
26
|
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
27
|
pendingUpdates?: Record<string, number>;
|
|
53
28
|
processingItems?: Record<string, boolean>;
|
|
29
|
+
isAddingToCart?: boolean;
|
|
30
|
+
totalItems?: number;
|
|
31
|
+
locale: string;
|
|
32
|
+
productPriceOptions?: PriceFormatOptions;
|
|
33
|
+
totalPriceOptions?: PriceFormatOptions;
|
|
34
|
+
translations: {
|
|
35
|
+
emptyBasket: string;
|
|
36
|
+
amount: string;
|
|
37
|
+
remove: string;
|
|
38
|
+
addingToBasket: string;
|
|
39
|
+
total: string;
|
|
40
|
+
shippingAndTax: string;
|
|
41
|
+
};
|
|
54
42
|
};
|
|
55
|
-
export declare const BasketDialog: ({ isOpen, onClose, products, subtotal, onQuantityChange, onRemoveProduct, onCheckout, onContinueShopping,
|
|
43
|
+
export declare const BasketDialog: ({ isOpen, onClose, products, subtotal, onQuantityChange, onRemoveProduct, onCheckout, onContinueShopping, productLink, title, checkoutText, continueShoppingText, showShippingNote, showQuantityControls, pendingUpdates, processingItems, isAddingToCart, totalItems, locale, productPriceOptions, totalPriceOptions, translations, }: BasketDialogProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,29 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Stav
|
|
26
|
-
pendingUpdates = {}, processingItems = {}, }) => {
|
|
3
|
+
import Button from '@/components/Base/button/Button';
|
|
4
|
+
import Heading from '@/components/Base/heading/Heading';
|
|
5
|
+
import { Price } from '@/components/Base/price/Price';
|
|
6
|
+
import Spinner from '@/components/Base/spinner/Spinner';
|
|
7
|
+
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
|
|
8
|
+
import { MinusIcon, PlusIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
|
9
|
+
import { useEffect, useRef, useState } from 'react';
|
|
10
|
+
export const BasketDialog = ({ isOpen, onClose, products, subtotal, onQuantityChange, onRemoveProduct, onCheckout, onContinueShopping, productLink, title = 'Váš košík', checkoutText = 'Pokračovat k objednávce', continueShoppingText = 'Pokračovat v nákupu', showShippingNote = true, showQuantityControls = true, pendingUpdates = {}, processingItems = {}, isAddingToCart = false, totalItems, locale, productPriceOptions, totalPriceOptions, translations, }) => {
|
|
11
|
+
const [shouldShowAddingIndicator, setShouldShowAddingIndicator] = useState(false);
|
|
12
|
+
const initialTotalItems = useRef(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (isAddingToCart) {
|
|
15
|
+
initialTotalItems.current = totalItems || 0;
|
|
16
|
+
setShouldShowAddingIndicator(true);
|
|
17
|
+
}
|
|
18
|
+
else if (initialTotalItems.current !== null) {
|
|
19
|
+
if (totalItems !== initialTotalItems.current) {
|
|
20
|
+
setShouldShowAddingIndicator(false);
|
|
21
|
+
initialTotalItems.current = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}, [isAddingToCart, totalItems]);
|
|
27
25
|
const handleCheckout = () => {
|
|
28
26
|
if (onCheckout) {
|
|
29
27
|
onCheckout();
|
|
@@ -37,60 +35,53 @@ pendingUpdates = {}, processingItems = {}, }) => {
|
|
|
37
35
|
onClose();
|
|
38
36
|
}
|
|
39
37
|
};
|
|
40
|
-
const handleIncrement = (
|
|
38
|
+
const handleIncrement = (productUuid, quantity) => {
|
|
41
39
|
if (onQuantityChange) {
|
|
42
|
-
onQuantityChange(
|
|
40
|
+
onQuantityChange(productUuid, quantity + 1);
|
|
43
41
|
}
|
|
44
42
|
};
|
|
45
|
-
const handleDecrement = (
|
|
43
|
+
const handleDecrement = (productUuid, quantity) => {
|
|
46
44
|
if (onQuantityChange) {
|
|
47
45
|
if (quantity > 1) {
|
|
48
|
-
onQuantityChange(
|
|
46
|
+
onQuantityChange(productUuid, quantity - 1);
|
|
49
47
|
}
|
|
50
48
|
else {
|
|
51
|
-
onQuantityChange(
|
|
49
|
+
onQuantityChange(productUuid, 0);
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
: "bg-gray-200 hover:bg-gray-300"}`, children: _jsx(PlusIcon, { className: "h-4 w-4" }) })] })] })) : (_jsxs("p", { className: "text-gray-500", children: [quantityLabel, " ", displayQuantity] })), showRemoveButton && onRemoveProduct && (_jsx("div", { className: "flex", children: _jsx("button", { type: "button", className: `font-medium ${isProcessing
|
|
90
|
-
? "text-gray-400 cursor-not-allowed"
|
|
91
|
-
: "text-green-600 hover:text-green-500"}`, onClick: () => !isProcessing &&
|
|
92
|
-
onRemoveProduct(product.id), disabled: isProcessing, children: removeButtonText }) }))] })] })] }, product.id));
|
|
93
|
-
}) })) }) })] }), _jsxs("div", { className: "border-t border-gray-200 px-4 py-6 sm:px-6", children: [showSubtotal && (_jsxs("div", { className: "flex justify-between text-base font-medium text-gray-900", children: [_jsx("p", { children: totalLabel }), _jsx("p", { children: typeof subtotal === "number"
|
|
94
|
-
? formatPrice(subtotal)
|
|
95
|
-
: subtotal })] })), showShippingNote && (_jsx("p", { className: "mt-0.5 text-sm text-gray-500", children: shippingNoteText })), products.length > 0 && showCheckoutButton && onCheckout && (_jsx("div", { className: "mt-6", children: _jsx("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", children: checkoutText }) })), showContinueShoppingButton && (_jsx("div", { className: "mt-6 flex justify-center text-center text-sm text-gray-500", children: _jsx("p", { children: _jsxs("button", { type: "button", onClick: handleContinueShopping, className: "font-medium text-green-600 hover:text-green-500", children: [continueShoppingText, _jsx("span", { "aria-hidden": "true", children: " \u2192" })] }) }) })), renderCustomFooter && renderCustomFooter()] })] }) }) }) }) })] }));
|
|
53
|
+
return (_jsxs(Dialog, { open: isOpen, onClose: onClose, className: "relative z-110", children: [_jsx(DialogBackdrop, { transition: true, className: "fixed inset-0 bg-gray-500/75 transition-opacity duration-500 ease-in-out data-closed:opacity-0" }), _jsx("div", { className: "fixed inset-0 overflow-hidden", children: _jsx("div", { className: "absolute inset-0 overflow-hidden", children: _jsx("div", { className: "pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10", children: _jsx(DialogPanel, { transition: true, className: "pointer-events-auto w-screen max-w-md transform transition duration-500 ease-in-out data-closed:translate-x-full sm:duration-700", children: _jsxs("div", { className: "flex h-full flex-col overflow-y-scroll bg-white shadow-xl", children: [_jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-6 sm:px-6", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx(DialogTitle, { className: "text-lg font-medium text-gray-900", children: title }), _jsx("div", { className: "ml-3 flex h-7 items-center", children: _jsxs("button", { type: "button", onClick: onClose, className: "relative -m-2 p-2 text-gray-400 hover:text-gray-500", children: [_jsx("span", { className: "absolute -inset-0.5" }), _jsx(XMarkIcon, { "aria-hidden": "true", className: "size-6" })] }) })] }), _jsx("div", { className: "mt-8", children: _jsx("div", { className: "flow-root", children: products.length === 0 && !shouldShowAddingIndicator ? (_jsx("div", { className: "py-6 text-center text-gray-500", children: translations.emptyBasket })) : (_jsxs("ul", { role: "list", className: "-my-6 divide-y divide-gray-200", children: [products.map((product) => {
|
|
54
|
+
const productKey = product.variation_uuid;
|
|
55
|
+
const displayQuantity = productKey in pendingUpdates
|
|
56
|
+
? pendingUpdates[productKey]
|
|
57
|
+
: product.quantity;
|
|
58
|
+
const isProcessing = processingItems[productKey] === true;
|
|
59
|
+
const isTemporaryRow = shouldShowAddingIndicator &&
|
|
60
|
+
productKey === 'adding';
|
|
61
|
+
return (_jsxs("li", { className: `flex py-6 ${isTemporaryRow
|
|
62
|
+
? 'opacity-75 bg-gray-50'
|
|
63
|
+
: ''}`, children: [_jsxs("div", { className: "size-24 shrink-0 overflow-hidden border border-gray-200 relative", children: [_jsx("img", { alt: product
|
|
64
|
+
.variation_images[0]
|
|
65
|
+
?.alt ||
|
|
66
|
+
product.variation_name, src: product
|
|
67
|
+
.variation_images[0]
|
|
68
|
+
?.href ||
|
|
69
|
+
'/lk_logo.png', className: "size-full object-contain" }), isTemporaryRow && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-white bg-opacity-75", children: _jsx(Spinner, { className: "h-8 w-8 text-[var(--primary)]" }) }))] }), _jsxs("div", { className: "ml-4 flex flex-1 flex-col", children: [_jsx("div", { children: _jsxs("div", { className: "flex justify-between text-base font-medium text-gray-900", children: [_jsx(Heading, { level: 3, className: "font-extralight text-lg", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { asLink: true, unstyled: true, href: productLink?.(product.product_name, product.variation_uuid), children: product.product_name }), isProcessing &&
|
|
70
|
+
!isTemporaryRow && (_jsx(Spinner, { className: "h-4 w-4 text-gray-400" }))] }) }), _jsx(Price, { value: product.price, locale: locale, options: productPriceOptions, className: "ml-4 font-light" })] }) }), _jsxs("div", { className: "flex flex-1 items-end justify-between text-sm", children: [isTemporaryRow ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Spinner, { className: "h-4 w-4 text-[var(--primary)]" }), _jsx("p", { className: "text-gray-500 italic", children: "Prid\u00E1va sa do ko\u0161\u00EDka..." })] })) : showQuantityControls &&
|
|
71
|
+
onQuantityChange ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: "text-gray-500 mr-2", children: translations.amount }), _jsxs("div", { className: "flex items-center", children: [_jsx("button", { type: "button", onClick: () => !isProcessing &&
|
|
72
|
+
handleDecrement(product.variation_uuid, displayQuantity), disabled: isProcessing, className: `rounded-full p-1 text-gray-600 ${isProcessing
|
|
73
|
+
? 'bg-gray-100 cursor-not-allowed opacity-50'
|
|
74
|
+
: 'bg-gray-200 hover:bg-gray-300'}`, children: _jsx(MinusIcon, { className: "h-4 w-4" }) }), _jsx("span", { className: "mx-2 min-w-[20px] text-center text-black", children: displayQuantity }), _jsx("button", { type: "button", onClick: () => !isProcessing &&
|
|
75
|
+
handleIncrement(product.variation_uuid, displayQuantity), disabled: isProcessing, className: `rounded-full p-1 text-gray-600 ${isProcessing
|
|
76
|
+
? 'bg-gray-100 cursor-not-allowed opacity-50'
|
|
77
|
+
: 'bg-gray-200 hover:bg-gray-300'}`, children: _jsx(PlusIcon, { className: "h-4 w-4" }) })] })] })) : (_jsx("p", { className: "text-gray-500", children: translations.amount +
|
|
78
|
+
' ' +
|
|
79
|
+
displayQuantity })), !isTemporaryRow &&
|
|
80
|
+
onRemoveProduct && (_jsx("div", { className: "flex", children: _jsx("button", { type: "button", className: `font-medium ${isProcessing
|
|
81
|
+
? 'text-gray-400 cursor-not-allowed'
|
|
82
|
+
: 'text-[var(--accent)] hover:text-[var(--primary)]'}`, onClick: () => !isProcessing &&
|
|
83
|
+
onRemoveProduct(product.variation_uuid), disabled: isProcessing, children: translations.remove }) }))] })] })] }, `${product.variation_uuid}-${isTemporaryRow
|
|
84
|
+
? 'temp'
|
|
85
|
+
: 'normal'}`));
|
|
86
|
+
}), shouldShowAddingIndicator && (_jsxs("li", { className: "flex py-6 opacity-75 bg-gray-50", children: [_jsx("div", { className: "size-24 shrink-0 overflow-hidden rounded-md border border-gray-200 relative", children: _jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-white bg-opacity-75", children: _jsx(Spinner, { className: "h-8 w-8 text-[var(--primary)]" }) }) }), _jsx("div", { className: "ml-4 flex flex-1 flex-col justify-center", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Spinner, { className: "h-4 w-4 text-[var(--primary)]" }), _jsx("p", { className: "text-gray-500 italic", children: translations.addingToBasket })] }) })] }))] })) }) })] }), _jsxs("div", { className: "border-t border-gray-200 px-4 py-6 sm:px-6", children: [_jsxs("div", { className: "flex justify-between text-base font-medium text-gray-900", children: [_jsx("p", { children: translations.total }), _jsx(Price, { value: subtotal, locale: locale, options: totalPriceOptions })] }), showShippingNote && (_jsx("p", { className: "mt-0.5 text-sm text-gray-500", children: translations.shippingAndTax })), products.length > 0 && onCheckout && (_jsx("div", { className: "mt-6", children: _jsx("button", { onClick: handleCheckout, className: "button-brand w-full", children: checkoutText }) })), _jsx("div", { className: "mt-6 flex justify-center text-center text-sm text-gray-500", children: _jsx("p", { children: _jsxs("button", { type: "button", onClick: handleContinueShopping, className: "font-medium text-[var(--primary)] hover:text-[var(--primary)]", children: [continueShoppingText, _jsx("span", { "aria-hidden": "true", children: " \u2192" })] }) }) })] })] }) }) }) }) })] }));
|
|
96
87
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PriceFormatOptions } from '@/utils/generalHelperFunction';
|
|
2
|
+
import { Product } from '@q2devel/q2-core';
|
|
3
|
+
export type BasketProduct = Product & {
|
|
4
|
+
quantity: number;
|
|
5
|
+
inStock?: boolean;
|
|
6
|
+
leadTime?: string;
|
|
7
|
+
size?: string;
|
|
8
|
+
};
|
|
9
|
+
export type BasketOverviewProps = {
|
|
10
|
+
products: BasketProduct[];
|
|
11
|
+
subtotal: number;
|
|
12
|
+
onQuantityChange?: (productId: string, quantity: number) => void;
|
|
13
|
+
onRemoveProduct?: (productId: string) => void;
|
|
14
|
+
onClearBasket?: () => void;
|
|
15
|
+
onCheckout?: () => void;
|
|
16
|
+
onContinueShopping?: () => void;
|
|
17
|
+
productLink?: (productName: string, variationId: string) => string;
|
|
18
|
+
title?: string;
|
|
19
|
+
checkoutText?: string;
|
|
20
|
+
continueShoppingText?: string;
|
|
21
|
+
shippingNote?: string;
|
|
22
|
+
totalText?: string;
|
|
23
|
+
showShippingNote?: boolean;
|
|
24
|
+
clearBasketText?: string;
|
|
25
|
+
pendingUpdates?: Record<string, number>;
|
|
26
|
+
processingItems?: Record<string, boolean>;
|
|
27
|
+
locale: string;
|
|
28
|
+
productPriceOptions?: PriceFormatOptions;
|
|
29
|
+
TotalPriceOptions?: PriceFormatOptions;
|
|
30
|
+
translations?: {
|
|
31
|
+
emptyBasketPlaceholder?: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export declare const BasketOverview: ({ products, subtotal, onQuantityChange, onRemoveProduct, onClearBasket, onCheckout, onContinueShopping, productLink, title, checkoutText, continueShoppingText, showShippingNote, clearBasketText, totalText, shippingNote, pendingUpdates, processingItems, locale, productPriceOptions, TotalPriceOptions, translations, }: BasketOverviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import Button from '@/components/Base/button/Button';
|
|
4
|
+
import Heading from '@/components/Base/heading/Heading';
|
|
5
|
+
import { Price } from '@/components/Base/price/Price';
|
|
6
|
+
import { CheckIcon, ClockIcon, TrashIcon } from '@heroicons/react/20/solid';
|
|
7
|
+
import { MinusIcon, PlusIcon } from '@heroicons/react/24/solid';
|
|
8
|
+
export const BasketOverview = ({ products, subtotal, onQuantityChange, onRemoveProduct, onClearBasket, onCheckout, onContinueShopping, productLink, title = 'Shopping Cart', checkoutText = 'Checkout', continueShoppingText = 'Continue Shopping', showShippingNote = true, clearBasketText = 'Clear basket', totalText, shippingNote, pendingUpdates = {}, processingItems = {}, locale, productPriceOptions, TotalPriceOptions, translations, }) => {
|
|
9
|
+
const handleIncrement = (product, quantity) => {
|
|
10
|
+
if (onQuantityChange) {
|
|
11
|
+
onQuantityChange(product.variation_uuid, quantity + 1);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const handleDecrement = (product, quantity) => {
|
|
15
|
+
if (onQuantityChange) {
|
|
16
|
+
if (quantity > 1) {
|
|
17
|
+
onQuantityChange(product.variation_uuid, quantity - 1);
|
|
18
|
+
}
|
|
19
|
+
else if (onRemoveProduct) {
|
|
20
|
+
onRemoveProduct(product.variation_uuid);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return (_jsx("div", { children: _jsxs("div", { className: "mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-8 lg:px-0", children: [_jsx(Heading, { level: 1, className: "label", children: title }), _jsxs("form", { className: "mt-12", children: [_jsxs("section", { "aria-labelledby": "cart-heading", children: [_jsx(Heading, { level: 2, id: "cart-heading", className: "sr-only", children: "Items in your shopping cart" }), _jsx("ul", { role: "list", className: "divide-y divide-gray-200 border-t border-b border-gray-200", children: products.length === 0 ? (_jsx("li", { className: "py-6 text-center text-gray-500", children: translations?.emptyBasketPlaceholder })) : (products.map((product) => {
|
|
25
|
+
const productKey = product.variation_uuid;
|
|
26
|
+
const isProcessing = processingItems[productKey] || false;
|
|
27
|
+
const displayQuantity = productKey in pendingUpdates
|
|
28
|
+
? pendingUpdates[productKey]
|
|
29
|
+
: product.quantity;
|
|
30
|
+
return (_jsxs("li", { className: "flex py-6", children: [_jsx("div", { className: "shrink-0", children: _jsx("img", { width: 128, height: 128, alt: product.variation_images[0]?.alt, src: product.variation_images[0]?.href, className: "size-24 rounded-md object-contain sm:size-32" }) }), _jsxs("div", { className: "ml-4 flex flex-1 flex-col sm:ml-6", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex justify-between", children: [_jsx(Heading, { level: 4, children: _jsx(Button, { asLink: true, unstyled: true, href: productLink?.(product.product_name, product.variation_uuid), className: "font-medium text-gray-700 hover:text-gray-800", children: product.product_name }) }), _jsx("span", { className: "ml-4 text-sm font-medium text-gray-900", children: _jsx(Price, { value: product.price, locale: locale, options: productPriceOptions }) })] }), product.size && (_jsx("p", { className: "mt-1 text-sm text-gray-500", children: product.size }))] }), _jsxs("div", { className: "mt-4 flex flex-1 items-end justify-between", children: [_jsx("div", { className: "flex items-center space-x-2 text-sm text-gray-700", children: product.inStock !== undefined && (_jsxs(_Fragment, { children: [product.inStock ? (_jsx(CheckIcon, { "aria-hidden": "true", className: "size-5 shrink-0 text-[var(--primary)]" })) : (_jsx(ClockIcon, { "aria-hidden": "true", className: "size-5 shrink-0 text-gray-300" })), _jsx("span", { children: product.inStock
|
|
31
|
+
? 'In stock'
|
|
32
|
+
: `Will ship in ${product.leadTime}` })] })) }), _jsxs("div", { className: "flex items-center", children: [_jsx("button", { type: "button", onClick: () => handleDecrement(product, displayQuantity), disabled: isProcessing, className: `rounded-full p-1 text-gray-600 ${isProcessing
|
|
33
|
+
? 'bg-gray-100 cursor-not-allowed opacity-50'
|
|
34
|
+
: 'bg-gray-200 hover:bg-gray-300'}`, children: _jsx(MinusIcon, { className: "h-4 w-4" }) }), _jsx("span", { className: "mx-2 min-w-[20px] text-center text-black", children: displayQuantity }), _jsx("button", { type: "button", onClick: () => handleIncrement(product, displayQuantity), disabled: isProcessing, className: `rounded-full p-1 text-gray-600 ${isProcessing
|
|
35
|
+
? 'bg-gray-100 cursor-not-allowed opacity-50'
|
|
36
|
+
: 'bg-gray-200 hover:bg-gray-300'}`, children: _jsx(PlusIcon, { className: "h-4 w-4" }) })] })] })] })] }, product.variation_uuid));
|
|
37
|
+
})) })] }), _jsxs("section", { "aria-labelledby": "summary-heading", className: "mt-10", children: [_jsx(Heading, { level: 2, id: "summary-heading", className: "sr-only", children: "Order summary" }), products.length > 0 && onClearBasket && (_jsx("div", { className: "mb-4", children: _jsxs("button", { type: "button", onClick: onClearBasket, className: "inline-flex items-center text-sm font-medium text-red-600 hover:text-red-500", children: [_jsx(TrashIcon, { className: "mr-1 h-5 w-5 text-red-500" }), clearBasketText] }) })), _jsxs("div", { children: [_jsx("dl", { className: "space-y-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("dt", { className: "text-base font-medium text-gray-900", children: totalText }), _jsx("dd", { className: "ml-4 text-base font-medium text-gray-900", children: _jsx(Price, { value: subtotal, locale: locale, options: TotalPriceOptions }) })] }) }), showShippingNote && (_jsx("p", { className: "mt-1 text-sm text-gray-500", children: shippingNote }))] }), products.length > 0 && onCheckout && (_jsx("div", { className: "mt-10", children: _jsx("button", { type: "button", onClick: onCheckout, className: "button-brand w-full", children: checkoutText }) })), onContinueShopping && (_jsx("div", { className: "mt-6 text-center text-sm", children: _jsx("p", { children: _jsxs("button", { type: "button", onClick: onContinueShopping, className: "font-medium text-[var(--primary)] hover:text-[var(--primary)]", children: [continueShoppingText, _jsx("span", { "aria-hidden": "true", children: " \u2192" })] }) }) }))] })] })] }) }));
|
|
38
|
+
};
|