@faststore/components 3.5.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/cjs/hooks/index.d.ts +1 -0
  2. package/dist/cjs/hooks/index.js +3 -1
  3. package/dist/cjs/hooks/index.js.map +1 -1
  4. package/dist/cjs/hooks/useSKUMatrix.d.ts +1 -0
  5. package/dist/cjs/hooks/useSKUMatrix.js +14 -0
  6. package/dist/cjs/hooks/useSKUMatrix.js.map +1 -0
  7. package/dist/cjs/index.d.ts +2 -0
  8. package/dist/cjs/index.js +5 -1
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/organisms/SKUMatrix/SKUMatrix.d.ts +9 -0
  11. package/dist/cjs/organisms/SKUMatrix/SKUMatrix.js +11 -0
  12. package/dist/cjs/organisms/SKUMatrix/SKUMatrix.js.map +1 -0
  13. package/dist/cjs/organisms/SKUMatrix/SKUMatrixSidebar.d.ts +45 -0
  14. package/dist/cjs/organisms/SKUMatrix/SKUMatrixSidebar.js +93 -0
  15. package/dist/cjs/organisms/SKUMatrix/SKUMatrixSidebar.js.map +1 -0
  16. package/dist/cjs/organisms/SKUMatrix/SKUMatrixTrigger.d.ts +5 -0
  17. package/dist/cjs/organisms/SKUMatrix/SKUMatrixTrigger.js +15 -0
  18. package/dist/cjs/organisms/SKUMatrix/SKUMatrixTrigger.js.map +1 -0
  19. package/dist/cjs/organisms/SKUMatrix/index.d.ts +6 -0
  20. package/dist/cjs/organisms/SKUMatrix/index.js +13 -0
  21. package/dist/cjs/organisms/SKUMatrix/index.js.map +1 -0
  22. package/dist/cjs/organisms/SKUMatrix/provider/SKUMatrixProvider.d.ts +49 -0
  23. package/dist/cjs/organisms/SKUMatrix/provider/SKUMatrixProvider.js +28 -0
  24. package/dist/cjs/organisms/SKUMatrix/provider/SKUMatrixProvider.js.map +1 -0
  25. package/dist/esm/hooks/index.d.ts +1 -0
  26. package/dist/esm/hooks/index.js +1 -0
  27. package/dist/esm/hooks/index.js.map +1 -1
  28. package/dist/esm/hooks/useSKUMatrix.d.ts +1 -0
  29. package/dist/esm/hooks/useSKUMatrix.js +10 -0
  30. package/dist/esm/hooks/useSKUMatrix.js.map +1 -0
  31. package/dist/esm/index.d.ts +2 -0
  32. package/dist/esm/index.js +1 -0
  33. package/dist/esm/index.js.map +1 -1
  34. package/dist/esm/organisms/SKUMatrix/SKUMatrix.d.ts +9 -0
  35. package/dist/esm/organisms/SKUMatrix/SKUMatrix.js +8 -0
  36. package/dist/esm/organisms/SKUMatrix/SKUMatrix.js.map +1 -0
  37. package/dist/esm/organisms/SKUMatrix/SKUMatrixSidebar.d.ts +45 -0
  38. package/dist/esm/organisms/SKUMatrix/SKUMatrixSidebar.js +90 -0
  39. package/dist/esm/organisms/SKUMatrix/SKUMatrixSidebar.js.map +1 -0
  40. package/dist/esm/organisms/SKUMatrix/SKUMatrixTrigger.d.ts +5 -0
  41. package/dist/esm/organisms/SKUMatrix/SKUMatrixTrigger.js +12 -0
  42. package/dist/esm/organisms/SKUMatrix/SKUMatrixTrigger.js.map +1 -0
  43. package/dist/esm/organisms/SKUMatrix/index.d.ts +6 -0
  44. package/dist/esm/organisms/SKUMatrix/index.js +4 -0
  45. package/dist/esm/organisms/SKUMatrix/index.js.map +1 -0
  46. package/dist/esm/organisms/SKUMatrix/provider/SKUMatrixProvider.d.ts +49 -0
  47. package/dist/esm/organisms/SKUMatrix/provider/SKUMatrixProvider.js +24 -0
  48. package/dist/esm/organisms/SKUMatrix/provider/SKUMatrixProvider.js.map +1 -0
  49. package/package.json +4 -4
  50. package/src/hooks/index.ts +1 -2
  51. package/src/hooks/useSKUMatrix.ts +15 -0
  52. package/src/index.ts +11 -0
  53. package/src/organisms/SKUMatrix/SKUMatrix.tsx +22 -0
  54. package/src/organisms/SKUMatrix/SKUMatrixSidebar.tsx +297 -0
  55. package/src/organisms/SKUMatrix/SKUMatrixTrigger.tsx +31 -0
  56. package/src/organisms/SKUMatrix/index.ts +8 -0
  57. package/src/organisms/SKUMatrix/provider/SKUMatrixProvider.tsx +104 -0
@@ -0,0 +1,90 @@
1
+ import Image from 'next/image';
2
+ import React, { useMemo } from 'react';
3
+ import { Badge, Button, QuantitySelector, Skeleton } from '../..';
4
+ import Price from '../../atoms/Price';
5
+ import Icon from '../../atoms/Icon';
6
+ import { useFadeEffect, useSKUMatrix, useUI } from '../../hooks';
7
+ import { Table, TableBody, TableCell, TableHead, TableRow, } from '../../molecules/Table';
8
+ import SlideOver, { SlideOverHeader } from '../SlideOver';
9
+ function SKUMatrixSidebar({ direction = 'rightSide', title, overlayProps, size = 'partial', children, columns, buyProps: { onClick: buyButtonOnClick, ...buyProps }, loading, formatter, ...otherProps }) {
10
+ const { isOpen, setIsOpen, setAllVariantProducts, allVariantProducts, onChangeQuantityItem, } = useSKUMatrix();
11
+ const { pushToast } = useUI();
12
+ const { fade } = useFadeEffect();
13
+ const cartDetails = useMemo(() => {
14
+ return allVariantProducts.reduce((acc, product) => ({
15
+ amount: acc.amount + product.selectedCount,
16
+ subtotal: acc.subtotal + product.selectedCount * product.price,
17
+ }), { amount: 0, subtotal: 0 });
18
+ }, [allVariantProducts]);
19
+ function resetQuantityItems() {
20
+ setAllVariantProducts((prev) => prev.map((item) => ({ ...item, quantity: 0 })));
21
+ }
22
+ function onClose() {
23
+ resetQuantityItems();
24
+ setIsOpen(false);
25
+ }
26
+ function handleAddToCart(e) {
27
+ buyButtonOnClick(e);
28
+ onClose();
29
+ }
30
+ const totalColumnsSkeletonLength = Object.keys(columns).filter((v) => v !== 'additionalColumns').length +
31
+ (columns.additionalColumns?.length ?? 0);
32
+ return (React.createElement(SlideOver, { "data-fs-sku-matrix-sidebar": true, size: size, direction: direction, overlayProps: overlayProps, isOpen: isOpen, fade: fade, ...otherProps },
33
+ React.createElement(SlideOverHeader, { onClose: onClose },
34
+ React.createElement("h2", { "data-fs-sku-matrix-sidebar-title": true }, title)),
35
+ children,
36
+ React.createElement(Table, { variant: "bordered" },
37
+ React.createElement(TableHead, null,
38
+ React.createElement(TableRow, null,
39
+ React.createElement(TableCell, { align: "left", variant: "header", scope: "col" }, columns.name),
40
+ columns.additionalColumns?.map(({ label, value }) => (React.createElement(TableCell, { key: value, align: "left", variant: "header", scope: "col" }, label))),
41
+ React.createElement(TableCell, { align: "left", variant: "header", scope: "col" }, columns.availability.label),
42
+ React.createElement(TableCell, { align: "right", variant: "header", scope: "col" }, columns.price),
43
+ React.createElement(TableCell, { align: "left", variant: "header", scope: "col" }, columns.quantitySelector))),
44
+ React.createElement(TableBody, null, loading ? (React.createElement(React.Fragment, null, Array.from({ length: 5 }).map((_, index) => {
45
+ return (React.createElement(TableRow, { key: `table-row-${index}` }, Array.from({
46
+ length: totalColumnsSkeletonLength,
47
+ }).map((_, index) => {
48
+ return (React.createElement(TableCell, { key: `table-cell-${index}` },
49
+ React.createElement("span", null,
50
+ React.createElement(Skeleton, { key: index, size: { width: '100%', height: '30px' } }))));
51
+ })));
52
+ }))) : (React.createElement(React.Fragment, null, allVariantProducts.map((variantProduct) => (React.createElement(TableRow, { key: `${variantProduct.name}-${variantProduct.id}` },
53
+ React.createElement(TableCell, { "data-fs-sku-matrix-sidebar-cell-image": true, align: "left" },
54
+ React.createElement(Image, { src: variantProduct.image.url, alt: variantProduct.image.alternateName, width: 48, height: 48 }),
55
+ variantProduct.name),
56
+ columns.additionalColumns?.map(({ value }) => (React.createElement(TableCell, { key: `${variantProduct.name}-${variantProduct.id}-${value}`, align: "left" }, variantProduct.specifications[value.toLowerCase()]))),
57
+ React.createElement(TableCell, { align: "left" },
58
+ columns.availability.stockDisplaySettings ===
59
+ 'showAvailability' && (React.createElement(Badge, { variant: variantProduct.availability === 'outOfStock'
60
+ ? 'warning'
61
+ : 'success' }, variantProduct.availability === 'outOfStock'
62
+ ? 'Out of stock'
63
+ : 'Available')),
64
+ columns.availability.stockDisplaySettings ===
65
+ 'showStockQuantity' && variantProduct.inventory),
66
+ React.createElement(TableCell, { align: "right" },
67
+ React.createElement("div", { "data-fs-sku-matrix-sidebar-table-price": true },
68
+ React.createElement(Price, { value: variantProduct.price, variant: "spot", formatter: formatter }))),
69
+ React.createElement(TableCell, { align: "right", "data-fs-sku-matrix-sidebar-table-cell-quantity-selector": true },
70
+ React.createElement("div", { "data-fs-sku-matrix-sidebar-table-action": true },
71
+ React.createElement(QuantitySelector, { min: 0, max: variantProduct.inventory, disabled: !variantProduct.inventory ||
72
+ variantProduct.availability === 'outOfStock', initial: variantProduct.selectedCount, onChange: (value) => onChangeQuantityItem(variantProduct.id, value), onValidateBlur: (min, maxValue, quantity) => {
73
+ pushToast({
74
+ title: 'Invalid quantity!',
75
+ message: `The quantity you entered is outside the range of ${min} to ${maxValue}. The quantity was set to ${quantity}.`,
76
+ status: 'INFO',
77
+ icon: (React.createElement(Icon, { name: "CircleWavyWarning", width: 30, height: 30 })),
78
+ });
79
+ } })))))))))),
80
+ React.createElement("footer", { "data-fs-sku-matrix-sidebar-footer": true },
81
+ React.createElement("div", null,
82
+ React.createElement("p", null,
83
+ cartDetails.amount,
84
+ " ",
85
+ cartDetails.amount !== 1 ? 'Items' : 'Item'),
86
+ React.createElement(Price, { value: cartDetails.subtotal, variant: "spot", formatter: formatter })),
87
+ React.createElement(Button, { variant: "primary", disabled: !cartDetails.amount, onClick: handleAddToCart, ...buyProps }, "Add to Cart"))));
88
+ }
89
+ export default SKUMatrixSidebar;
90
+ //# sourceMappingURL=SKUMatrixSidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SKUMatrixSidebar.js","sourceRoot":"","sources":["../../../../src/organisms/SKUMatrix/SKUMatrixSidebar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { ButtonProps } from '../../atoms/Button';
3
+ export type SKUMatrixTriggerProps = ButtonProps;
4
+ declare const SKUMatrixTrigger: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
5
+ export default SKUMatrixTrigger;
@@ -0,0 +1,12 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Button from '../../atoms/Button';
3
+ import { useSKUMatrix } from '../../hooks';
4
+ const SKUMatrixTrigger = forwardRef(function SKUMatrixTrigger({ children, variant = 'secondary', onClick, ...otherProps }, ref) {
5
+ const { setIsOpen } = useSKUMatrix();
6
+ return (React.createElement(Button, { ref: ref, variant: variant, onClick: (event) => {
7
+ setIsOpen(true);
8
+ onClick?.(event);
9
+ }, ...otherProps }, children));
10
+ });
11
+ export default SKUMatrixTrigger;
12
+ //# sourceMappingURL=SKUMatrixTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SKUMatrixTrigger.js","sourceRoot":"","sources":["../../../../src/organisms/SKUMatrix/SKUMatrixTrigger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAA;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI1C,MAAM,gBAAgB,GAAG,UAAU,CACjC,SAAS,gBAAgB,CACvB,EAAE,QAAQ,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,EAC3D,GAAG;IAEH,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAA;IAEpC,OAAO,CACL,oBAAC,MAAM,IACL,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,SAAS,CAAC,IAAI,CAAC,CAAA;YACf,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC,KACG,UAAU,IAEb,QAAQ,CACF,CACV,CAAA;AACH,CAAC,CACF,CAAA;AAED,eAAe,gBAAgB,CAAA"}
@@ -0,0 +1,6 @@
1
+ export { default } from './SKUMatrix';
2
+ export type { SKUMatrixProps } from './SKUMatrix';
3
+ export { default as SKUMatrixTrigger } from './SKUMatrixTrigger';
4
+ export type { SKUMatrixTriggerProps } from './SKUMatrixTrigger';
5
+ export { default as SKUMatrixSidebar } from './SKUMatrixSidebar';
6
+ export type { SKUMatrixSidebarProps } from './SKUMatrixSidebar';
@@ -0,0 +1,4 @@
1
+ export { default } from './SKUMatrix';
2
+ export { default as SKUMatrixTrigger } from './SKUMatrixTrigger';
3
+ export { default as SKUMatrixSidebar } from './SKUMatrixSidebar';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/organisms/SKUMatrix/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAGrC,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAGhE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,49 @@
1
+ import React, { SetStateAction } from 'react';
2
+ import type { ReactNode } from 'react';
3
+ interface IAllVariantProducts {
4
+ id: string;
5
+ name: string;
6
+ image: {
7
+ url: string;
8
+ alternateName: string;
9
+ };
10
+ inventory: number;
11
+ availability: string;
12
+ price: number;
13
+ listPrice: number;
14
+ priceWithTaxes: number;
15
+ listPriceWithTaxes: number;
16
+ specifications: Record<string, string>;
17
+ selectedCount: number;
18
+ offers: {
19
+ highPrice: number;
20
+ lowPrice: number;
21
+ lowPriceWithTaxes: number;
22
+ offerCount: number;
23
+ priceCurrency: string;
24
+ offers: Array<{
25
+ listPrice: number;
26
+ listPriceWithTaxes: number;
27
+ sellingPrice: number;
28
+ priceCurrency: string;
29
+ price: number;
30
+ priceWithTaxes: number;
31
+ priceValidUntil: string;
32
+ itemCondition: string;
33
+ availability: string;
34
+ quantity: number;
35
+ }>;
36
+ };
37
+ }
38
+ export interface SKUMatrixProviderContextValue {
39
+ isOpen: boolean;
40
+ allVariantProducts: IAllVariantProducts[];
41
+ setAllVariantProducts(items: SetStateAction<IAllVariantProducts[]>): void;
42
+ onChangeQuantityItem(id: string, value: number): IAllVariantProducts[];
43
+ setIsOpen(value: boolean): void;
44
+ }
45
+ export declare const SKUMatrixContext: React.Context<SKUMatrixProviderContextValue | null>;
46
+ declare function SKUMatrixProvider({ children }: {
47
+ children: ReactNode;
48
+ }): React.JSX.Element;
49
+ export default SKUMatrixProvider;
@@ -0,0 +1,24 @@
1
+ import React, { createContext, useCallback, useState } from 'react';
2
+ export const SKUMatrixContext = createContext(null);
3
+ function SKUMatrixProvider({ children }) {
4
+ const [isOpen, setIsOpen] = useState(false);
5
+ const [allVariantProducts, setAllVariantProducts] = useState([]);
6
+ const onChangeQuantityItem = useCallback((id, value) => {
7
+ const data = [...allVariantProducts];
8
+ const matchedSKU = data.find((item) => item.id === id);
9
+ if (matchedSKU) {
10
+ matchedSKU.selectedCount = value;
11
+ }
12
+ setAllVariantProducts(data);
13
+ return data;
14
+ }, [allVariantProducts]);
15
+ return (React.createElement(SKUMatrixContext.Provider, { value: {
16
+ isOpen,
17
+ allVariantProducts,
18
+ setAllVariantProducts,
19
+ onChangeQuantityItem,
20
+ setIsOpen,
21
+ } }, children));
22
+ }
23
+ export default SKUMatrixProvider;
24
+ //# sourceMappingURL=SKUMatrixProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SKUMatrixProvider.js","sourceRoot":"","sources":["../../../../../src/organisms/SKUMatrix/provider/SKUMatrixProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAmB,MAAM,OAAO,CAAA;AA+DpF,MAAM,CAAC,MAAM,gBAAgB,GAC3B,aAAa,CAAuC,IAAI,CAAC,CAAA;AAE3D,SAAS,iBAAiB,CAAC,EAAE,QAAQ,EAA2B;IAC9D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAA;IACpD,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAE1D,EAAE,CAAC,CAAA;IAEL,MAAM,oBAAoB,GAAG,WAAW,CACtC,CAAC,EAAU,EAAE,KAAa,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAA;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QAEtD,IAAG,UAAU,EAAE;YACb,UAAU,CAAC,aAAa,GAAG,KAAK,CAAA;SACjC;QAED,qBAAqB,CAAC,IAAI,CAAC,CAAA;QAE3B,OAAO,IAAI,CAAA;IACb,CAAC,EACD,CAAC,kBAAkB,CAAC,CACrB,CAAA;IAED,OAAO,CACL,oBAAC,gBAAgB,CAAC,QAAQ,IACxB,KAAK,EAAE;YACL,MAAM;YACN,kBAAkB;YAClB,qBAAqB;YACrB,oBAAoB;YACpB,SAAS;SACV,IAEA,QAAQ,CACiB,CAC7B,CAAA;AACH,CAAC;AAED,eAAe,iBAAiB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/components",
3
- "version": "3.5.0",
3
+ "version": "3.9.0",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "typings": "dist/esm/index.d.ts",
@@ -35,8 +35,8 @@
35
35
  "react-dom": "^18.2.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@faststore/eslint-config": "^3.5.0",
39
- "@faststore/shared": "^3.5.0",
38
+ "@faststore/eslint-config": "^3.9.0",
39
+ "@faststore/shared": "^3.9.0",
40
40
  "@testing-library/jest-dom": "^6.5.0",
41
41
  "@testing-library/react": "^14.3.0",
42
42
  "@types/jest-axe": "^3.5.9",
@@ -52,5 +52,5 @@
52
52
  "volta": {
53
53
  "extends": "../../package.json"
54
54
  },
55
- "gitHead": "180554c88fee738fb4fffe62f9dd6d0ceab6bdfb"
55
+ "gitHead": "50345eff012999c1e2100a5fcfeccd0732da131e"
56
56
  }
@@ -2,6 +2,7 @@ export { default as UIProvider, Toast as ToastProps, useUI } from './UIProvider'
2
2
  export { useFadeEffect } from './useFadeEffect'
3
3
  export { useTrapFocus } from './useTrapFocus'
4
4
  export { useSearch } from './useSearch'
5
+ export { useSKUMatrix } from './useSKUMatrix'
5
6
  export { useScrollDirection } from './useScrollDirection'
6
7
  export { useSlider } from './useSlider'
7
8
  export type {
@@ -11,5 +12,3 @@ export type {
11
12
  SlideDirection,
12
13
  } from './useSlider'
13
14
  export { useSlideVisibility } from './useSlideVisibility'
14
-
15
-
@@ -0,0 +1,15 @@
1
+ import { useContext } from 'react'
2
+
3
+ import { SKUMatrixContext } from '../organisms/SKUMatrix/provider/SKUMatrixProvider'
4
+
5
+ export function useSKUMatrix() {
6
+ const context = useContext(SKUMatrixContext)
7
+
8
+ if (!context) {
9
+ throw new Error(
10
+ 'Do not use SKUMatrix components outside the SKUMatrix context.'
11
+ )
12
+ }
13
+
14
+ return context
15
+ }
package/src/index.ts CHANGED
@@ -360,3 +360,14 @@ export type {
360
360
  SlideOverProps,
361
361
  SlideOverHeaderProps,
362
362
  } from './organisms/SlideOver'
363
+
364
+ export {
365
+ default as SKUMatrix,
366
+ SKUMatrixTrigger,
367
+ SKUMatrixSidebar,
368
+ } from './organisms/SKUMatrix'
369
+ export type {
370
+ SKUMatrixProps,
371
+ SKUMatrixTriggerProps,
372
+ SKUMatrixSidebarProps
373
+ } from './organisms/SKUMatrix'
@@ -0,0 +1,22 @@
1
+ import React, { forwardRef, HTMLAttributes } from 'react'
2
+ import SKUMatrixProvider from './provider/SKUMatrixProvider'
3
+
4
+ export interface SKUMatrixProps extends HTMLAttributes<HTMLDivElement> {
5
+ /**
6
+ * ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
7
+ */
8
+ testId?: string
9
+ }
10
+
11
+ const SKUMatrix = forwardRef<HTMLDivElement, SKUMatrixProps>(function SKUMatrix(
12
+ { testId = 'fs-sku-matrix', children, ...otherProps },
13
+ ref
14
+ ) {
15
+ return (
16
+ <div ref={ref} data-fs-sku-matrix data-testid={testId} {...otherProps}>
17
+ <SKUMatrixProvider>{children}</SKUMatrixProvider>
18
+ </div>
19
+ )
20
+ })
21
+
22
+ export default SKUMatrix
@@ -0,0 +1,297 @@
1
+ import Image from 'next/image'
2
+ import React, { useMemo } from 'react'
3
+ import { Badge, Button, QuantitySelector, Skeleton } from '../..'
4
+ import Price, { PriceFormatter } from '../../atoms/Price'
5
+ import Icon from '../../atoms/Icon'
6
+ import { useFadeEffect, useSKUMatrix, useUI } from '../../hooks'
7
+ import {
8
+ Table,
9
+ TableBody,
10
+ TableCell,
11
+ TableHead,
12
+ TableRow,
13
+ } from '../../molecules/Table'
14
+ import SlideOver, { SlideOverHeader, SlideOverProps } from '../SlideOver'
15
+
16
+ interface VariationProductColumn {
17
+ name: string
18
+ additionalColumns: Array<{ label: string; value: string }>
19
+ availability: {
20
+ label: string
21
+ stockDisplaySettings: 'showStockQuantity' | 'showAvailability'
22
+ }
23
+ price: number
24
+ quantitySelector: number
25
+ }
26
+
27
+ export interface SKUMatrixSidebarProps
28
+ extends Omit<SlideOverProps, 'isOpen' | 'setIsOpen' | "fade"> {
29
+ /**
30
+ * Title for the SKUMatrixSidebar component.
31
+ */
32
+ title?: string
33
+ /**
34
+ * Represents the variations products to building the table.
35
+ */
36
+ columns: VariationProductColumn
37
+ /**
38
+ * Properties related to the 'add to cart' button
39
+ */
40
+ buyProps: {
41
+ 'data-testid': string
42
+ 'data-sku': string
43
+ 'data-seller': string
44
+ onClick(e: React.MouseEvent<HTMLButtonElement>): void
45
+ }
46
+ /**
47
+ * Formatter function that transforms the raw price value and render the result.
48
+ */
49
+ formatter?: PriceFormatter
50
+ /**
51
+ * Check if some result is still loading before render the result.
52
+ */
53
+ loading?: boolean
54
+ }
55
+
56
+ function SKUMatrixSidebar({
57
+ direction = 'rightSide',
58
+ title,
59
+ overlayProps,
60
+ size = 'partial',
61
+ children,
62
+ columns,
63
+ buyProps: { onClick: buyButtonOnClick, ...buyProps },
64
+ loading,
65
+ formatter,
66
+ ...otherProps
67
+ }: SKUMatrixSidebarProps) {
68
+ const {
69
+ isOpen,
70
+ setIsOpen,
71
+ setAllVariantProducts,
72
+ allVariantProducts,
73
+ onChangeQuantityItem,
74
+ } = useSKUMatrix()
75
+ const { pushToast } = useUI()
76
+ const { fade } = useFadeEffect()
77
+
78
+ const cartDetails = useMemo(() => {
79
+ return allVariantProducts.reduce(
80
+ (acc, product) => ({
81
+ amount: acc.amount + product.selectedCount,
82
+ subtotal: acc.subtotal + product.selectedCount * product.price,
83
+ }),
84
+ { amount: 0, subtotal: 0 }
85
+ )
86
+ }, [allVariantProducts])
87
+
88
+ function resetQuantityItems() {
89
+ setAllVariantProducts((prev) =>
90
+ prev.map((item) => ({ ...item, quantity: 0 }))
91
+ )
92
+ }
93
+
94
+ function onClose() {
95
+ resetQuantityItems()
96
+ setIsOpen(false)
97
+ }
98
+
99
+ function handleAddToCart(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
100
+ buyButtonOnClick(e)
101
+ onClose()
102
+ }
103
+
104
+ const totalColumnsSkeletonLength =
105
+ Object.keys(columns).filter((v) => v !== 'additionalColumns').length +
106
+ (columns.additionalColumns?.length ?? 0)
107
+
108
+ return (
109
+ <SlideOver
110
+ data-fs-sku-matrix-sidebar
111
+ size={size}
112
+ direction={direction}
113
+ overlayProps={overlayProps}
114
+ isOpen={isOpen}
115
+ fade={fade}
116
+ {...otherProps}
117
+ >
118
+ <SlideOverHeader onClose={onClose}>
119
+ <h2 data-fs-sku-matrix-sidebar-title>{title}</h2>
120
+ </SlideOverHeader>
121
+
122
+ {children}
123
+
124
+ <Table variant="bordered">
125
+ <TableHead>
126
+ <TableRow>
127
+ <TableCell align="left" variant="header" scope="col">
128
+ {columns.name}
129
+ </TableCell>
130
+
131
+ {columns.additionalColumns?.map(({ label, value }) => (
132
+ <TableCell key={value} align="left" variant="header" scope="col">
133
+ {label}
134
+ </TableCell>
135
+ ))}
136
+
137
+ <TableCell align="left" variant="header" scope="col">
138
+ {columns.availability.label}
139
+ </TableCell>
140
+
141
+ <TableCell align="right" variant="header" scope="col">
142
+ {columns.price}
143
+ </TableCell>
144
+
145
+ <TableCell align="left" variant="header" scope="col">
146
+ {columns.quantitySelector}
147
+ </TableCell>
148
+ </TableRow>
149
+ </TableHead>
150
+
151
+ <TableBody>
152
+ {loading ? (
153
+ <>
154
+ {Array.from({ length: 5 }).map((_, index) => {
155
+ return (
156
+ <TableRow key={`table-row-${index}`}>
157
+ {Array.from({
158
+ length: totalColumnsSkeletonLength,
159
+ }).map((_, index) => {
160
+ return (
161
+ <TableCell key={`table-cell-${index}`}>
162
+ <span>
163
+ <Skeleton
164
+ key={index}
165
+ size={{ width: '100%', height: '30px' }}
166
+ />
167
+ </span>
168
+ </TableCell>
169
+ )
170
+ })}
171
+ </TableRow>
172
+ )
173
+ })}
174
+ </>
175
+ ) : (
176
+ <>
177
+ {allVariantProducts.map((variantProduct) => (
178
+ <TableRow key={`${variantProduct.name}-${variantProduct.id}`}>
179
+ <TableCell data-fs-sku-matrix-sidebar-cell-image align="left">
180
+ <Image
181
+ src={variantProduct.image.url}
182
+ alt={variantProduct.image.alternateName}
183
+ width={48}
184
+ height={48}
185
+ />
186
+ {variantProduct.name}
187
+ </TableCell>
188
+
189
+ {columns.additionalColumns?.map(({ value }) => (
190
+ <TableCell
191
+ key={`${variantProduct.name}-${variantProduct.id}-${value}`}
192
+ align="left"
193
+ >
194
+ {variantProduct.specifications[value.toLowerCase()]}
195
+ </TableCell>
196
+ ))}
197
+
198
+ <TableCell align="left">
199
+ {columns.availability.stockDisplaySettings ===
200
+ 'showAvailability' && (
201
+ <Badge
202
+ variant={
203
+ variantProduct.availability === 'outOfStock'
204
+ ? 'warning'
205
+ : 'success'
206
+ }
207
+ >
208
+ {variantProduct.availability === 'outOfStock'
209
+ ? 'Out of stock'
210
+ : 'Available'}
211
+ </Badge>
212
+ )}
213
+
214
+ {columns.availability.stockDisplaySettings ===
215
+ 'showStockQuantity' && variantProduct.inventory}
216
+ </TableCell>
217
+
218
+ <TableCell align="right">
219
+ <div data-fs-sku-matrix-sidebar-table-price>
220
+ <Price
221
+ value={variantProduct.price}
222
+ variant="spot"
223
+ formatter={formatter}
224
+ />
225
+ </div>
226
+ </TableCell>
227
+
228
+ <TableCell
229
+ align="right"
230
+ data-fs-sku-matrix-sidebar-table-cell-quantity-selector
231
+ >
232
+ <div data-fs-sku-matrix-sidebar-table-action>
233
+ <QuantitySelector
234
+ min={0}
235
+ max={variantProduct.inventory}
236
+ disabled={
237
+ !variantProduct.inventory ||
238
+ variantProduct.availability === 'outOfStock'
239
+ }
240
+ initial={variantProduct.selectedCount}
241
+ onChange={(value) =>
242
+ onChangeQuantityItem(variantProduct.id, value)
243
+ }
244
+ onValidateBlur={(
245
+ min: number,
246
+ maxValue: number,
247
+ quantity: number
248
+ ) => {
249
+ pushToast({
250
+ title: 'Invalid quantity!',
251
+ message: `The quantity you entered is outside the range of ${min} to ${maxValue}. The quantity was set to ${quantity}.`,
252
+ status: 'INFO',
253
+ icon: (
254
+ <Icon
255
+ name="CircleWavyWarning"
256
+ width={30}
257
+ height={30}
258
+ />
259
+ ),
260
+ })
261
+ }}
262
+ />
263
+ </div>
264
+ </TableCell>
265
+ </TableRow>
266
+ ))}
267
+ </>
268
+ )}
269
+ </TableBody>
270
+ </Table>
271
+
272
+ <footer data-fs-sku-matrix-sidebar-footer>
273
+ <div>
274
+ <p>
275
+ {cartDetails.amount} {cartDetails.amount !== 1 ? 'Items' : 'Item'}
276
+ </p>
277
+ <Price
278
+ value={cartDetails.subtotal}
279
+ variant="spot"
280
+ formatter={formatter}
281
+ />
282
+ </div>
283
+
284
+ <Button
285
+ variant="primary"
286
+ disabled={!cartDetails.amount}
287
+ onClick={handleAddToCart}
288
+ {...buyProps}
289
+ >
290
+ Add to Cart
291
+ </Button>
292
+ </footer>
293
+ </SlideOver>
294
+ )
295
+ }
296
+
297
+ export default SKUMatrixSidebar
@@ -0,0 +1,31 @@
1
+ import React, { forwardRef } from 'react'
2
+ import Button from '../../atoms/Button'
3
+ import type { ButtonProps } from '../../atoms/Button'
4
+ import { useSKUMatrix } from '../../hooks'
5
+
6
+ export type SKUMatrixTriggerProps = ButtonProps
7
+
8
+ const SKUMatrixTrigger = forwardRef<HTMLButtonElement, SKUMatrixTriggerProps>(
9
+ function SKUMatrixTrigger(
10
+ { children, variant = 'secondary', onClick, ...otherProps },
11
+ ref
12
+ ) {
13
+ const { setIsOpen } = useSKUMatrix()
14
+
15
+ return (
16
+ <Button
17
+ ref={ref}
18
+ variant={variant}
19
+ onClick={(event) => {
20
+ setIsOpen(true)
21
+ onClick?.(event)
22
+ }}
23
+ {...otherProps}
24
+ >
25
+ {children}
26
+ </Button>
27
+ )
28
+ }
29
+ )
30
+
31
+ export default SKUMatrixTrigger
@@ -0,0 +1,8 @@
1
+ export { default } from './SKUMatrix'
2
+ export type { SKUMatrixProps } from './SKUMatrix'
3
+
4
+ export { default as SKUMatrixTrigger } from './SKUMatrixTrigger'
5
+ export type { SKUMatrixTriggerProps } from './SKUMatrixTrigger'
6
+
7
+ export { default as SKUMatrixSidebar } from './SKUMatrixSidebar'
8
+ export type { SKUMatrixSidebarProps } from './SKUMatrixSidebar'