@fast-simon/shopify-hydrogen 1.0.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 (140) hide show
  1. package/README.md +180 -0
  2. package/dist/esnext/@types/Tab.d.ts +9 -0
  3. package/dist/esnext/@types/Tab.js +5 -0
  4. package/dist/esnext/@types/appServerProps.d.ts +12 -0
  5. package/dist/esnext/@types/appServerProps.js +1 -0
  6. package/dist/esnext/@types/articles.d.ts +12 -0
  7. package/dist/esnext/@types/articles.js +1 -0
  8. package/dist/esnext/@types/categories.d.ts +10 -0
  9. package/dist/esnext/@types/categories.js +1 -0
  10. package/dist/esnext/@types/currency.d.ts +1 -0
  11. package/dist/esnext/@types/currency.js +1 -0
  12. package/dist/esnext/@types/device.d.ts +1 -0
  13. package/dist/esnext/@types/device.js +1 -0
  14. package/dist/esnext/@types/editor.d.ts +416 -0
  15. package/dist/esnext/@types/editor.js +6 -0
  16. package/dist/esnext/@types/facets.d.ts +37 -0
  17. package/dist/esnext/@types/facets.js +16 -0
  18. package/dist/esnext/@types/ispOptions.d.ts +6 -0
  19. package/dist/esnext/@types/ispOptions.js +1 -0
  20. package/dist/esnext/@types/narrow.d.ts +7 -0
  21. package/dist/esnext/@types/narrow.js +1 -0
  22. package/dist/esnext/@types/product.d.ts +134 -0
  23. package/dist/esnext/@types/product.js +7 -0
  24. package/dist/esnext/@types/promoTile.d.ts +11 -0
  25. package/dist/esnext/@types/promoTile.js +1 -0
  26. package/dist/esnext/@types/results.d.ts +36 -0
  27. package/dist/esnext/@types/results.js +1 -0
  28. package/dist/esnext/@types/routing.d.ts +11 -0
  29. package/dist/esnext/@types/routing.js +1 -0
  30. package/dist/esnext/@types/siteSetup.d.ts +52 -0
  31. package/dist/esnext/@types/siteSetup.js +1 -0
  32. package/dist/esnext/@types/siteStatus.d.ts +5 -0
  33. package/dist/esnext/@types/siteStatus.js +1 -0
  34. package/dist/esnext/@types/sortBy.d.ts +12 -0
  35. package/dist/esnext/@types/sortBy.js +1 -0
  36. package/dist/esnext/@types/translations.d.ts +12 -0
  37. package/dist/esnext/@types/translations.js +6 -0
  38. package/dist/esnext/components/FastSimonApp.server.d.ts +8 -0
  39. package/dist/esnext/components/FastSimonApp.server.js +45 -0
  40. package/dist/esnext/components/FastSimonProvider.server.d.ts +10 -0
  41. package/dist/esnext/components/FastSimonProvider.server.js +9 -0
  42. package/dist/esnext/components/Filters/DesktopFilters/DesktopFilters.server.d.ts +7 -0
  43. package/dist/esnext/components/Filters/DesktopFilters/DesktopFilters.server.js +5 -0
  44. package/dist/esnext/components/Filters/FacetOption.client.d.ts +8 -0
  45. package/dist/esnext/components/Filters/FacetOption.client.js +39 -0
  46. package/dist/esnext/components/Filters/Filters.server.d.ts +11 -0
  47. package/dist/esnext/components/Filters/Filters.server.js +11 -0
  48. package/dist/esnext/components/Filters/FiltersList.server.d.ts +7 -0
  49. package/dist/esnext/components/Filters/FiltersList.server.js +11 -0
  50. package/dist/esnext/components/Filters/FiltersSkeleton.d.ts +2 -0
  51. package/dist/esnext/components/Filters/FiltersSkeleton.js +32 -0
  52. package/dist/esnext/components/Filters/MobileFilters/MobileFilters.client.d.ts +6 -0
  53. package/dist/esnext/components/Filters/MobileFilters/MobileFilters.client.js +20 -0
  54. package/dist/esnext/components/Filters/RemovableTags/RemovableTag.client.d.ts +7 -0
  55. package/dist/esnext/components/Filters/RemovableTags/RemovableTag.client.js +11 -0
  56. package/dist/esnext/components/Filters/RemovableTags/RemovableTags.client.d.ts +7 -0
  57. package/dist/esnext/components/Filters/RemovableTags/RemovableTags.client.js +51 -0
  58. package/dist/esnext/components/PageTitle/PageTitle.server.d.ts +6 -0
  59. package/dist/esnext/components/PageTitle/PageTitle.server.js +4 -0
  60. package/dist/esnext/components/Pagination/Pagination.client.d.ts +8 -0
  61. package/dist/esnext/components/Pagination/Pagination.client.js +43 -0
  62. package/dist/esnext/components/Pagination/utils.d.ts +1 -0
  63. package/dist/esnext/components/Pagination/utils.js +4 -0
  64. package/dist/esnext/components/ProductCard/ProductCard.d.ts +9 -0
  65. package/dist/esnext/components/ProductCard/ProductCard.js +31 -0
  66. package/dist/esnext/components/ProductCard/components/AddToCart/AddToCart.client.d.ts +9 -0
  67. package/dist/esnext/components/ProductCard/components/AddToCart/AddToCart.client.js +23 -0
  68. package/dist/esnext/components/ProductCard/components/Compare/Compare.d.ts +5 -0
  69. package/dist/esnext/components/ProductCard/components/Compare/Compare.js +6 -0
  70. package/dist/esnext/components/ProductCard/components/Info/ProductInfo.d.ts +8 -0
  71. package/dist/esnext/components/ProductCard/components/Info/ProductInfo.js +11 -0
  72. package/dist/esnext/components/ProductCard/components/Price/Price.d.ts +6 -0
  73. package/dist/esnext/components/ProductCard/components/Price/Price.js +6 -0
  74. package/dist/esnext/components/ProductCard/components/ProductImage/ProductImage.d.ts +7 -0
  75. package/dist/esnext/components/ProductCard/components/ProductImage/ProductImage.js +7 -0
  76. package/dist/esnext/components/ProductCard/components/Title/Title.d.ts +6 -0
  77. package/dist/esnext/components/ProductCard/components/Title/Title.js +4 -0
  78. package/dist/esnext/components/ProductGrid/ProductGrid.server.d.ts +9 -0
  79. package/dist/esnext/components/ProductGrid/ProductGrid.server.js +10 -0
  80. package/dist/esnext/components/ProductGrid/stylesUtil.d.ts +138 -0
  81. package/dist/esnext/components/ProductGrid/stylesUtil.js +122 -0
  82. package/dist/esnext/components/ResultsSummary/ResultsSummary.server.d.ts +6 -0
  83. package/dist/esnext/components/ResultsSummary/ResultsSummary.server.js +8 -0
  84. package/dist/esnext/components/SortBy/SortBy.client.d.ts +9 -0
  85. package/dist/esnext/components/SortBy/SortBy.client.js +8 -0
  86. package/dist/esnext/components/SortBy/components/DesktopSortBy.client.d.ts +7 -0
  87. package/dist/esnext/components/SortBy/components/DesktopSortBy.client.js +30 -0
  88. package/dist/esnext/components/SortBy/utils.d.ts +8 -0
  89. package/dist/esnext/components/SortBy/utils.js +28 -0
  90. package/dist/esnext/components/index.d.ts +2 -0
  91. package/dist/esnext/components/index.js +2 -0
  92. package/dist/esnext/context/setRoutingContext.d.ts +2 -0
  93. package/dist/esnext/context/setRoutingContext.js +14 -0
  94. package/dist/esnext/context/setSiteContext.d.ts +6 -0
  95. package/dist/esnext/context/setSiteContext.js +18 -0
  96. package/dist/esnext/hooks/ResizeDetect.client.d.ts +1 -0
  97. package/dist/esnext/hooks/ResizeDetect.client.js +6 -0
  98. package/dist/esnext/hooks/useClickOutside.d.ts +1 -0
  99. package/dist/esnext/hooks/useClickOutside.js +12 -0
  100. package/dist/esnext/hooks/useScreenSize.d.ts +1 -0
  101. package/dist/esnext/hooks/useScreenSize.js +19 -0
  102. package/dist/esnext/icons/DownArrowIcon.d.ts +8 -0
  103. package/dist/esnext/icons/DownArrowIcon.js +5 -0
  104. package/dist/esnext/icons/LeftArrowIcon.d.ts +7 -0
  105. package/dist/esnext/icons/LeftArrowIcon.js +5 -0
  106. package/dist/esnext/icons/RejectIcon.d.ts +7 -0
  107. package/dist/esnext/icons/RejectIcon.js +5 -0
  108. package/dist/esnext/icons/RightArrowIcon.d.ts +7 -0
  109. package/dist/esnext/icons/RightArrowIcon.js +5 -0
  110. package/dist/esnext/icons/Spinner.d.ts +10 -0
  111. package/dist/esnext/icons/Spinner.js +6 -0
  112. package/dist/esnext/index.d.ts +1 -0
  113. package/dist/esnext/index.js +1 -0
  114. package/dist/esnext/services/categories_navigation.d.ts +48 -0
  115. package/dist/esnext/services/categories_navigation.js +51 -0
  116. package/dist/esnext/services/search.d.ts +47 -0
  117. package/dist/esnext/services/search.js +51 -0
  118. package/dist/esnext/services/site_setup.d.ts +7 -0
  119. package/dist/esnext/services/site_setup.js +69 -0
  120. package/dist/esnext/styles/fast-simon.css +622 -0
  121. package/dist/esnext/utils/DynamicStyle.d.ts +6 -0
  122. package/dist/esnext/utils/DynamicStyle.js +5 -0
  123. package/dist/esnext/utils/defaults.d.ts +8 -0
  124. package/dist/esnext/utils/defaults.js +9 -0
  125. package/dist/esnext/utils/getDynamicStylesVar.d.ts +1 -0
  126. package/dist/esnext/utils/getDynamicStylesVar.js +5 -0
  127. package/dist/esnext/utils/getRoutingState.d.ts +9 -0
  128. package/dist/esnext/utils/getRoutingState.js +13 -0
  129. package/dist/esnext/utils/makeServingRequests.d.ts +6 -0
  130. package/dist/esnext/utils/makeServingRequests.js +32 -0
  131. package/dist/node/plugin/extendOptimizeDeps.d.ts +2 -0
  132. package/dist/node/plugin/extendOptimizeDeps.js +14 -0
  133. package/dist/node/plugin/index.d.ts +3 -0
  134. package/dist/node/plugin/index.js +13 -0
  135. package/dist/node/plugin/injectCSS.d.ts +2 -0
  136. package/dist/node/plugin/injectCSS.js +25 -0
  137. package/dist/node/plugin/suppressWarnings.d.ts +2 -0
  138. package/dist/node/plugin/suppressWarnings.js +21 -0
  139. package/package.json +34 -0
  140. package/plugin.js +1 -0
@@ -0,0 +1,20 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import { useClickOutside } from "../../../hooks/useClickOutside";
3
+ export function MobileFiltersClient({ children }) {
4
+ const [isOpen, setIsOpen] = useState(false);
5
+ const [isClosing, setIsClosing] = useState(false);
6
+ const filtersRef = useRef(null);
7
+ const onClickOutside = () => {
8
+ setIsClosing(true);
9
+ setTimeout(() => {
10
+ setIsOpen(false);
11
+ setIsClosing(false);
12
+ }, 450);
13
+ };
14
+ useClickOutside(filtersRef, onClickOutside);
15
+ return (React.createElement(React.Fragment, null,
16
+ React.createElement("div", { className: 'fs-mobile-filters-button', onClick: () => setIsOpen(true) }, "Filters"),
17
+ isOpen ?
18
+ React.createElement("div", { className: `fs-mobile-filters-wrapper` },
19
+ React.createElement("span", { ref: filtersRef, className: isClosing ? 'fs-filters-slider-close' : 'fs-filters-slider-open' }, children)) : null));
20
+ }
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ name: string;
3
+ value: string;
4
+ onRemove: (name: string, value: string) => void;
5
+ }
6
+ export declare function RemovableTagClient({ name, value, onRemove }: Props): JSX.Element;
7
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { RejectIcon } from "../../../icons/RejectIcon";
3
+ export function RemovableTagClient({ name, value, onRemove }) {
4
+ const onRemoveClicked = () => {
5
+ onRemove(name, value);
6
+ };
7
+ return (React.createElement("div", { className: 'fs-removable-tag', onClick: onRemoveClicked },
8
+ React.createElement("span", { className: "removable-tag-text fs-removable-tag-text" }, value),
9
+ React.createElement("span", { className: "fs-removable-tag-remove-button", onClick: onRemoveClicked },
10
+ React.createElement(RejectIcon, { color: "gray" }))));
11
+ }
@@ -0,0 +1,7 @@
1
+ import { RemovableTagsSettings } from "../../../@types/editor";
2
+ interface Props {
3
+ narrowString?: string;
4
+ removableTagsSettings: RemovableTagsSettings;
5
+ }
6
+ export declare function RemovableTagsClient({ narrowString, removableTagsSettings }: Props): JSX.Element;
7
+ export {};
@@ -0,0 +1,51 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import { Narrow } from "@fast-simon/utilities";
3
+ import { RemovableTagClient } from "./RemovableTag.client";
4
+ import { useNavigate, useServerProps, useUrl } from "@shopify/hydrogen";
5
+ import { Defaults } from "../../../utils/defaults";
6
+ import { DynamicStyle } from "../../../utils/DynamicStyle";
7
+ export function RemovableTagsClient({ narrowString, removableTagsSettings }) {
8
+ const [narrow, setNarrow] = useState(Narrow.parseNarrow(narrowString || ''));
9
+ const [items, setItems] = useState(Object.entries(narrow));
10
+ //const [size, setSize] = useState(items.reduce((p, [name, values]) => p + values.size, 0)); TODO: use size to show clear all button
11
+ const url = useUrl();
12
+ const { setServerProps, serverProps } = useServerProps();
13
+ const navigation = useNavigate();
14
+ useEffect(() => {
15
+ const newNarrow = Narrow.parseNarrow(narrowString || '');
16
+ setNarrow(narrow);
17
+ const newItems = Object.entries(newNarrow);
18
+ setItems(newItems);
19
+ //setSize(newItems.reduce((p, [name, values]) => p + values.size, 0)) TODO: use size to show clear all button
20
+ }, [narrowString]);
21
+ const onRemoveClick = (name, value) => {
22
+ const newNarrow = Narrow.updateNarrow(Narrow.parseNarrow(narrowString || ''), name, value);
23
+ setNarrow(newNarrow);
24
+ setItems(Object.entries(newNarrow));
25
+ let dumpedNarrow = Narrow.dumpNarrow(newNarrow);
26
+ url.searchParams.delete('page');
27
+ if (dumpedNarrow) {
28
+ url.searchParams.set('filters', dumpedNarrow);
29
+ }
30
+ else {
31
+ url.searchParams.delete('filters');
32
+ }
33
+ navigation(url.href);
34
+ setServerProps(Defaults.fastSimonProps, { ...serverProps?.[Defaults.fastSimonProps], page: 1, narrowString: dumpedNarrow });
35
+ };
36
+ const removeNarrow = useCallback(onRemoveClick, [items]);
37
+ const dynamicStyles = {
38
+ 'border': removableTagsSettings?.border,
39
+ 'box-shadow': removableTagsSettings?.shadow,
40
+ 'border-radius': removableTagsSettings?.borderRadius,
41
+ 'font-family': removableTagsSettings?.font.font,
42
+ 'color': removableTagsSettings?.color,
43
+ 'letter-spacing': removableTagsSettings?.font.letterSpacing,
44
+ 'font-size': removableTagsSettings?.font.fontSize,
45
+ 'font-weight': removableTagsSettings?.font.fontWeight,
46
+ 'background-color': removableTagsSettings?.backgroundColor,
47
+ };
48
+ return (React.createElement(React.Fragment, null,
49
+ React.createElement(DynamicStyle, { styles: dynamicStyles, className: 'fs-removable-tag' }),
50
+ React.createElement("div", { className: 'fs-removable-tags-container' }, items.map(([name, values]) => Array.from(values).map(value => (React.createElement(RemovableTagClient, { key: `removable_tag_${name}_${value}`, name: name, value: value, onRemove: removeNarrow })))))));
51
+ }
@@ -0,0 +1,6 @@
1
+ interface Props {
2
+ searchTerm?: string | null;
3
+ categoryName?: string;
4
+ }
5
+ export declare function PageTitleServer({ searchTerm, categoryName }: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export function PageTitleServer({ searchTerm, categoryName }) {
3
+ return (React.createElement("div", { className: 'fs-page-title' }, searchTerm ? `Search results for ${searchTerm}` : categoryName));
4
+ }
@@ -0,0 +1,8 @@
1
+ import { Pagination as PaginationType } from "../../@types/editor";
2
+ interface Props {
3
+ currentPage: number;
4
+ paginationSettings: PaginationType;
5
+ totalPages: number;
6
+ }
7
+ export declare function Pagination({ currentPage, paginationSettings, totalPages }: Props): JSX.Element;
8
+ export {};
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { useNavigate, useServerProps, useUrl } from "@shopify/hydrogen";
3
+ import { Defaults } from "../../utils/defaults";
4
+ import { getPageURL } from "./utils";
5
+ import { LeftArrowIcon } from "../../icons/LeftArrowIcon";
6
+ import { RightArrowIcon } from "../../icons/RightArrowIcon";
7
+ export function Pagination({ currentPage, paginationSettings, totalPages }) {
8
+ const { setServerProps, serverProps } = useServerProps();
9
+ const navigation = useNavigate();
10
+ const url = useUrl();
11
+ const goTo = (event, pageNum) => {
12
+ event.preventDefault();
13
+ url.searchParams.set('page', String(pageNum));
14
+ navigation(url.href);
15
+ setServerProps(Defaults.fastSimonProps, { ...serverProps?.[Defaults.fastSimonProps], page: pageNum });
16
+ window.scrollTo({ top: 0, behavior: 'smooth' });
17
+ };
18
+ const totalOfPagesArray = [...Array.from(Array(totalPages).keys())].map(i => i + 1);
19
+ return (React.createElement("div", { className: "pagination-wrapper" },
20
+ currentPage > 1 ?
21
+ React.createElement("span", { className: "arrow-button-wrapper", onClick: (event) => goTo(event, currentPage - 1) },
22
+ React.createElement("a", { className: "arrow-button", href: getPageURL(currentPage - 1, url) },
23
+ React.createElement(LeftArrowIcon, null))) : null,
24
+ React.createElement("span", { className: "center-pages-wrapper" }, totalOfPagesArray.map(pageNumber => {
25
+ if (pageNumber === 2 && currentPage > 4) {
26
+ return React.createElement("span", { key: `three-dots-left`, className: "page-number-item three-dots-item" }, "...");
27
+ }
28
+ if (pageNumber === currentPage) {
29
+ return React.createElement("a", { key: `page_num_${pageNumber}`, className: "page-number-item page-number-item-selected", href: getPageURL(pageNumber, url), onClick: (event) => goTo(event, pageNumber) }, pageNumber);
30
+ }
31
+ else if (pageNumber === currentPage + 1 || pageNumber === currentPage + 2 || pageNumber === currentPage - 1 || pageNumber === currentPage - 2 || pageNumber === totalPages || pageNumber === 1) {
32
+ return React.createElement("a", { key: `page_num_${pageNumber}`, className: "page-number-item", href: getPageURL(pageNumber, url), onClick: (event) => goTo(event, pageNumber) }, pageNumber);
33
+ }
34
+ if (currentPage < totalPages - 3 && pageNumber === totalPages - 1) {
35
+ return React.createElement("span", { key: `three-dots-right`, className: "page-number-item three-dots-item" }, "...");
36
+ }
37
+ return React.createElement(React.Fragment, null);
38
+ })),
39
+ currentPage < totalPages ?
40
+ React.createElement("span", { className: "arrow-button-wrapper", onClick: (event) => goTo(event, currentPage + 1) },
41
+ React.createElement("a", { className: "arrow-button", href: getPageURL(currentPage + 1, url) },
42
+ React.createElement(RightArrowIcon, null))) : null));
43
+ }
@@ -0,0 +1 @@
1
+ export declare function getPageURL(page: number, url: URL): string;
@@ -0,0 +1,4 @@
1
+ export function getPageURL(page, url) {
2
+ url.searchParams.set('page', String(page));
3
+ return url.href;
4
+ }
@@ -0,0 +1,9 @@
1
+ import { ProductSettings } from "../../@types/editor";
2
+ import { ServerProduct } from "../../@types/product";
3
+ interface Props {
4
+ productData: ServerProduct;
5
+ productSettings: ProductSettings;
6
+ index: number;
7
+ }
8
+ export declare function ProductCard({ productData, productSettings, index }: Props): JSX.Element;
9
+ export {};
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { ProductImage } from "./components/ProductImage/ProductImage";
3
+ import { AddToCartClient } from "./components/AddToCart/AddToCart.client";
4
+ import { ProductInfo } from "./components/Info/ProductInfo";
5
+ export function ProductCard({ productData, productSettings, index }) {
6
+ const shopifyVariantNodes = productData.vra.map(variant => {
7
+ return {
8
+ id: `gid://shopify/ProductVariant/${variant[0]}`,
9
+ priceV2: { amount: productData.p, currencyCode: 'USD' },
10
+ compareAtPriceV2: null,
11
+ image: {
12
+ url: productData.t
13
+ }
14
+ };
15
+ });
16
+ if (!shopifyVariantNodes.length) {
17
+ shopifyVariantNodes.push({
18
+ id: `gid://shopify/ProductVariant/${productData.id}`,
19
+ priceV2: { amount: productData.p, currencyCode: 'USD' },
20
+ compareAtPriceV2: null,
21
+ image: {
22
+ url: productData.t
23
+ }
24
+ });
25
+ }
26
+ return (React.createElement(React.Fragment, null,
27
+ React.createElement("div", { className: "fs-product-card" },
28
+ React.createElement(ProductImage, { imageURL: productData.t, redirectURL: productData.u, index: index }),
29
+ React.createElement(ProductInfo, { productSettings: productSettings, productData: productData }),
30
+ React.createElement(AddToCartClient, { variantId: String(productData.id), variantNodes: shopifyVariantNodes, addToCartSettings: productSettings.addToCart }))));
31
+ }
@@ -0,0 +1,9 @@
1
+ import { ProductAddToCartSettings } from "../../../../@types/editor";
2
+ interface Props {
3
+ variantId: string;
4
+ quantity?: number;
5
+ variantNodes?: any;
6
+ addToCartSettings: ProductAddToCartSettings;
7
+ }
8
+ export declare function AddToCartClient({ variantId, quantity, variantNodes, addToCartSettings }: Props): JSX.Element;
9
+ export {};
@@ -0,0 +1,23 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { AddToCartButton, ProductOptionsProvider } from '@shopify/hydrogen';
3
+ import { useCart } from "@shopify/hydrogen";
4
+ import { Spinner } from "../../../../icons/Spinner";
5
+ export function AddToCartClient({ variantId, quantity = 1, variantNodes, addToCartSettings }) {
6
+ const { status } = useCart();
7
+ const [addingProduct, setAddingProduct] = useState(false);
8
+ useEffect(() => {
9
+ if (status === 'idle') {
10
+ if (addingProduct) {
11
+ window.dispatchEvent(new CustomEvent('fs-custom-events-product-added'));
12
+ }
13
+ setAddingProduct(false);
14
+ }
15
+ }, [status]);
16
+ const onButtonClick = () => {
17
+ setAddingProduct(true);
18
+ };
19
+ return (React.createElement(ProductOptionsProvider, { data: variantNodes },
20
+ React.createElement(AddToCartButton, { variantId: variantNodes[0].id, quantity: quantity, accessibleAddingToCartLabel: "Adding item to your cart", onClick: onButtonClick, className: 'fs-product-add-to-cart' }, addingProduct ? React.createElement("div", { className: 'fs-adding-product' },
21
+ React.createElement(Spinner, { color: addToCartSettings.color }),
22
+ " Adding...") : React.createElement("div", null, addToCartSettings.text))));
23
+ }
@@ -0,0 +1,5 @@
1
+ interface Props {
2
+ compare: string;
3
+ }
4
+ export declare function Compare({ compare }: Props): JSX.Element;
5
+ export {};
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export function Compare({ compare }) {
3
+ return (React.createElement("div", { className: "fs-product-card-compare" },
4
+ "$",
5
+ compare));
6
+ }
@@ -0,0 +1,8 @@
1
+ import { ServerProduct } from "../../../../@types/product";
2
+ import { ProductSettings } from "../../../../@types/editor";
3
+ interface Props {
4
+ productData: ServerProduct;
5
+ productSettings: ProductSettings;
6
+ }
7
+ export declare function ProductInfo({ productData, productSettings }: Props): JSX.Element;
8
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Title } from "../Title/Title";
3
+ import { Price } from "../Price/Price";
4
+ import { Compare } from "../Compare/Compare";
5
+ export function ProductInfo({ productData, productSettings }) {
6
+ const isCompare = productSettings.compare.isActive && Number(productData?.p_c) !== 0;
7
+ return (React.createElement("div", { className: `fs-product-card-info ${isCompare ? 'fs-info-areas-compare' : 'fs-info-areas'}` },
8
+ React.createElement(Title, { title: productData.l, redirectURL: productData.u }),
9
+ React.createElement(Price, { price: productData.p, isCompare: isCompare }),
10
+ isCompare ? React.createElement(Compare, { compare: productData.p_c }) : null));
11
+ }
@@ -0,0 +1,6 @@
1
+ interface Props {
2
+ price: string;
3
+ isCompare: boolean;
4
+ }
5
+ export declare function Price({ price, isCompare }: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export function Price({ price, isCompare }) {
3
+ return (React.createElement("div", { className: `fs-product-card-price ${isCompare ? 'fs-price-with-compare' : 'fs-price-without-compare'}` },
4
+ "$",
5
+ price));
6
+ }
@@ -0,0 +1,7 @@
1
+ interface Props {
2
+ imageURL: string;
3
+ redirectURL: string;
4
+ index: number;
5
+ }
6
+ export declare function ProductImage({ imageURL, redirectURL, index }: Props): JSX.Element;
7
+ export {};
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { Image, Link } from "@shopify/hydrogen";
3
+ const MISSING_IMAGE_SRC = 'https://acp-magento.appspot.com/images/missing.gif';
4
+ export function ProductImage({ imageURL, redirectURL, index }) {
5
+ return (React.createElement(Link, { to: redirectURL },
6
+ React.createElement(Image, { alt: "product image", src: imageURL || MISSING_IMAGE_SRC, width: 500, height: 500, className: 'fs-product-card-img', loading: index < 4 ? 'eager' : 'lazy' })));
7
+ }
@@ -0,0 +1,6 @@
1
+ interface Props {
2
+ title: string;
3
+ redirectURL: string;
4
+ }
5
+ export declare function Title({ title, redirectURL }: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export function Title({ title, redirectURL }) {
3
+ return (React.createElement("a", { href: redirectURL, className: "fs-product-card-title" }, title));
4
+ }
@@ -0,0 +1,9 @@
1
+ import { FullTextServerResponseAll } from "../../services/search";
2
+ import { CategoryNavigationServerResponseAll } from "../../services/categories_navigation";
3
+ import { ProductsGridSettings } from "../../@types/editor";
4
+ interface Props {
5
+ data?: FullTextServerResponseAll | CategoryNavigationServerResponseAll;
6
+ gridSettings: ProductsGridSettings;
7
+ }
8
+ export declare function ProductGridServer({ data, gridSettings }: Props): JSX.Element;
9
+ export {};
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { ProductCard } from "../ProductCard/ProductCard";
3
+ import { DynamicStyle } from "../../utils/DynamicStyle";
4
+ import { StylesUtil } from "./stylesUtil";
5
+ export function ProductGridServer({ data, gridSettings }) {
6
+ const dynamicStyles = StylesUtil.getDynamicStylesObject(gridSettings);
7
+ return (React.createElement(React.Fragment, null,
8
+ dynamicStyles.map(item => React.createElement(DynamicStyle, { key: item.className, styles: item.styles, className: item.className })),
9
+ React.createElement("div", { className: "fs-grid" }, data?.items?.map((product, index) => React.createElement(ProductCard, { key: product.id, productData: product, productSettings: gridSettings.product, index: index })))));
10
+ }
@@ -0,0 +1,138 @@
1
+ import { ProductAddToCartSettings, ProductComparePriceSettings, ProductPriceSettings, ProductSettings, ProductsGridSettings, ProductTitleSettings } from "../../@types/editor";
2
+ export declare class StylesUtil {
3
+ static getDynamicStylesObject: (gridSettings: ProductsGridSettings) => ({
4
+ className: string;
5
+ styles: {
6
+ "grid-template-columns": string;
7
+ "grid-row-gap": string;
8
+ "grid-column-gap": string;
9
+ "margin-left": string;
10
+ };
11
+ } | {
12
+ className: string;
13
+ styles: {
14
+ 'aspect-ratio': number;
15
+ 'object-fit': string;
16
+ };
17
+ } | {
18
+ className: string;
19
+ styles: {
20
+ 'background-color': string;
21
+ color: string;
22
+ };
23
+ } | {
24
+ className: string;
25
+ styles: {
26
+ 'font-weight': string;
27
+ 'font-family': string;
28
+ 'font-size': string;
29
+ 'letter-spacing': string;
30
+ 'line-height': string;
31
+ };
32
+ } | {
33
+ className: string;
34
+ styles: {
35
+ 'text-align': string;
36
+ color: string;
37
+ };
38
+ } | {
39
+ className: string;
40
+ styles: {
41
+ border: string | undefined;
42
+ };
43
+ } | {
44
+ className: string;
45
+ styles: {
46
+ padding: string;
47
+ };
48
+ } | {
49
+ className: string;
50
+ styles: {
51
+ 'grid-template-areas': string | undefined;
52
+ };
53
+ })[];
54
+ static getGridCustomStyles: (gridSettings: ProductsGridSettings) => {
55
+ "grid-template-columns": string;
56
+ "grid-row-gap": string;
57
+ "grid-column-gap": string;
58
+ "margin-left": string;
59
+ };
60
+ static getProductImageCustomStyles: (productSettings: ProductSettings) => {
61
+ 'aspect-ratio': number;
62
+ 'object-fit': string;
63
+ };
64
+ static getAddToCartCustomStyles: (addToCart: ProductAddToCartSettings) => {
65
+ base: {
66
+ 'font-weight': string;
67
+ 'font-family': string;
68
+ 'font-size': string;
69
+ 'letter-spacing': string;
70
+ color: string;
71
+ 'background-color': string;
72
+ border: string;
73
+ 'border-radius': string;
74
+ opacity: number;
75
+ };
76
+ hover: {
77
+ 'background-color': string;
78
+ color: string;
79
+ };
80
+ };
81
+ static getPriceCustomStyles: (priceSettings: ProductPriceSettings, comparePrice?: boolean) => {
82
+ base: {
83
+ 'font-weight': string;
84
+ 'font-family': string;
85
+ 'font-size': string;
86
+ 'letter-spacing': string;
87
+ 'line-height': string;
88
+ };
89
+ withCompare: {
90
+ 'text-align': "center" | "left" | "right";
91
+ color: string;
92
+ };
93
+ withoutCompare: {
94
+ 'text-align': string;
95
+ color: string;
96
+ };
97
+ };
98
+ static getProductTitleCustomStyles: (titleSettings: ProductTitleSettings) => {
99
+ '-webkit-line-clamp': string;
100
+ 'font-weight': string;
101
+ 'text-align': string;
102
+ 'font-family': string;
103
+ 'font-size': string;
104
+ 'letter-spacing': string;
105
+ 'line-height': string;
106
+ color: string;
107
+ };
108
+ static getProductCardCustomStyles: (productSettings: ProductSettings) => {
109
+ base: {
110
+ padding: string;
111
+ border: string | undefined;
112
+ 'border-radius': string;
113
+ shadow: string;
114
+ 'justify-content': string;
115
+ };
116
+ hover: {
117
+ border: string | undefined;
118
+ };
119
+ gridAreasWithCompare: {
120
+ 'grid-template-areas': string | undefined;
121
+ };
122
+ gridAreasWithoutCompare: {
123
+ 'grid-template-areas': string | undefined;
124
+ };
125
+ productInfo: {
126
+ padding: string;
127
+ };
128
+ };
129
+ static getCompareStyles: (compareSettings: ProductComparePriceSettings) => {
130
+ 'font-weight': string;
131
+ 'text-align': string;
132
+ 'font-family': string;
133
+ 'font-size': string;
134
+ 'letter-spacing': string;
135
+ 'line-height': string;
136
+ color: string;
137
+ };
138
+ }
@@ -0,0 +1,122 @@
1
+ import { GridAreaUtils } from "@fast-simon/utilities";
2
+ export class StylesUtil {
3
+ }
4
+ StylesUtil.getDynamicStylesObject = (gridSettings) => {
5
+ const gridStyles = StylesUtil.getGridCustomStyles(gridSettings);
6
+ const imageCustomStyles = StylesUtil.getProductImageCustomStyles(gridSettings.product);
7
+ const addToCartCustomStyles = StylesUtil.getAddToCartCustomStyles(gridSettings.product.addToCart);
8
+ const priceCustomStyles = StylesUtil.getPriceCustomStyles(gridSettings.product.price);
9
+ const titleCustomStyles = StylesUtil.getProductTitleCustomStyles(gridSettings.product.title);
10
+ const productCardCustomStyles = StylesUtil.getProductCardCustomStyles(gridSettings.product);
11
+ const compareStyles = StylesUtil.getCompareStyles(gridSettings.product.compare);
12
+ return [
13
+ { className: 'fs-grid', styles: gridStyles },
14
+ { className: 'fs-product-card-img', styles: imageCustomStyles },
15
+ { className: 'fs-product-add-to-cart', styles: addToCartCustomStyles.base },
16
+ { className: 'fs-product-add-to-cart:hover', styles: addToCartCustomStyles.hover },
17
+ { className: 'fs-product-card-price', styles: priceCustomStyles.base },
18
+ { className: 'fs-price-with-compare', styles: priceCustomStyles.withCompare },
19
+ { className: 'fs-price-without-compare', styles: priceCustomStyles.withoutCompare },
20
+ { className: 'fs-product-card-title', styles: titleCustomStyles },
21
+ { className: 'fs-product-card', styles: productCardCustomStyles.base },
22
+ { className: 'fs-product-card:hover', styles: productCardCustomStyles.hover },
23
+ { className: 'fs-product-card-info', styles: productCardCustomStyles.productInfo },
24
+ { className: 'fs-info-areas-compare', styles: productCardCustomStyles.gridAreasWithCompare },
25
+ { className: 'fs-info-areas', styles: productCardCustomStyles.gridAreasWithoutCompare },
26
+ { className: 'fs-product-card-compare', styles: compareStyles }
27
+ ];
28
+ };
29
+ StylesUtil.getGridCustomStyles = (gridSettings) => {
30
+ return {
31
+ "grid-template-columns": `repeat(${gridSettings.numberOfColumns}, calc(${100 / Number(gridSettings.numberOfColumns)}% - ${gridSettings.gridColumnGap}))`,
32
+ "grid-row-gap": gridSettings.gridRowGap,
33
+ "grid-column-gap": gridSettings.gridColumnGap,
34
+ "margin-left": gridSettings.gridColumnGap
35
+ };
36
+ };
37
+ StylesUtil.getProductImageCustomStyles = (productSettings) => {
38
+ return {
39
+ 'aspect-ratio': productSettings.imageRatio,
40
+ 'object-fit': productSettings.imageFit
41
+ };
42
+ };
43
+ StylesUtil.getAddToCartCustomStyles = (addToCart) => {
44
+ return {
45
+ base: {
46
+ 'font-weight': addToCart.font.fontWeight,
47
+ 'font-family': addToCart.font.font,
48
+ 'font-size': addToCart.font.fontSize,
49
+ 'letter-spacing': addToCart.font.letterSpacing,
50
+ 'color': addToCart.color,
51
+ 'background-color': addToCart.backgroundColor,
52
+ 'border': addToCart.border,
53
+ 'border-radius': addToCart.borderRadius,
54
+ 'opacity': addToCart.showOnHover ? 0 : 1
55
+ },
56
+ hover: {
57
+ 'background-color': addToCart.changeColorsOnHover && addToCart.backgroundColorOnHover !== 'unset' ? addToCart.backgroundColorOnHover : addToCart.backgroundColor,
58
+ 'color': addToCart.changeColorsOnHover && addToCart.backgroundColorOnHover !== 'unset' ? addToCart.textColorsOnHover : addToCart.color,
59
+ }
60
+ };
61
+ };
62
+ StylesUtil.getPriceCustomStyles = (priceSettings, comparePrice) => {
63
+ return {
64
+ base: {
65
+ 'font-weight': priceSettings?.font.fontWeight,
66
+ 'font-family': priceSettings?.font.font,
67
+ 'font-size': priceSettings?.font.fontSize,
68
+ 'letter-spacing': priceSettings?.font.letterSpacing,
69
+ 'line-height': priceSettings?.font.lineHeight,
70
+ },
71
+ withCompare: {
72
+ 'text-align': priceSettings.alignIfCompare,
73
+ 'color': priceSettings.colorIfCompareEnable ? priceSettings?.colorIfCompareEnable : priceSettings.color
74
+ },
75
+ withoutCompare: {
76
+ 'text-align': priceSettings?.font.textAlign,
77
+ 'color': priceSettings.color
78
+ }
79
+ };
80
+ };
81
+ StylesUtil.getProductTitleCustomStyles = (titleSettings) => {
82
+ return {
83
+ '-webkit-line-clamp': titleSettings?.numberOfLines,
84
+ 'font-weight': titleSettings?.font.fontWeight,
85
+ 'text-align': titleSettings?.font.textAlign,
86
+ 'font-family': titleSettings?.font.font,
87
+ 'font-size': titleSettings?.font.fontSize,
88
+ 'letter-spacing': titleSettings?.font.letterSpacing,
89
+ 'line-height': titleSettings?.font.lineHeight,
90
+ 'color': titleSettings?.color
91
+ };
92
+ };
93
+ StylesUtil.getProductCardCustomStyles = (productSettings) => {
94
+ return {
95
+ base: {
96
+ 'padding': productSettings?.padding,
97
+ 'border': productSettings?.showBorderOnHover ? undefined : productSettings?.border,
98
+ 'border-radius': productSettings?.borderRadius + "%",
99
+ 'shadow': productSettings?.shadow,
100
+ 'justify-content': productSettings?.addToCart.isActive && productSettings?.addToCart.addToCartType === 'product level' ? 'space-between' : ''
101
+ },
102
+ hover: {
103
+ 'border': productSettings?.showBorderOnHover ? productSettings?.border : undefined,
104
+ },
105
+ gridAreasWithCompare: { 'grid-template-areas': GridAreaUtils.arrangeGridAreas(productSettings?.info.gridAreas, true) },
106
+ gridAreasWithoutCompare: { 'grid-template-areas': GridAreaUtils.arrangeGridAreas(productSettings?.info.gridAreas, false) },
107
+ productInfo: {
108
+ padding: productSettings?.info.padding
109
+ }
110
+ };
111
+ };
112
+ StylesUtil.getCompareStyles = (compareSettings) => {
113
+ return {
114
+ 'font-weight': compareSettings.font.fontWeight,
115
+ 'text-align': compareSettings.font.textAlign,
116
+ 'font-family': compareSettings.font.font,
117
+ 'font-size': compareSettings.font.fontSize,
118
+ 'letter-spacing': compareSettings.font.letterSpacing,
119
+ 'line-height': compareSettings.font.lineHeight,
120
+ 'color': compareSettings.color
121
+ };
122
+ };
@@ -0,0 +1,6 @@
1
+ interface Props {
2
+ totalResults: number;
3
+ term: string;
4
+ }
5
+ export declare function ResultsSummaryServer({ totalResults, term }: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export function ResultsSummaryServer({ totalResults, term }) {
3
+ return (React.createElement("div", { className: 'fs-summary' },
4
+ React.createElement("div", null, term),
5
+ React.createElement("div", null,
6
+ totalResults,
7
+ " results")));
8
+ }