@graphcommerce/magento-product 9.0.0-canary.99 → 9.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 (106) hide show
  1. package/CHANGELOG.md +211 -1279
  2. package/components/AddProductsToCart/AddProductsToCartButton.tsx +4 -5
  3. package/components/AddProductsToCart/AddProductsToCartError.tsx +3 -2
  4. package/components/AddProductsToCart/AddProductsToCartFab.tsx +5 -6
  5. package/components/AddProductsToCart/AddProductsToCartForm.tsx +15 -19
  6. package/components/AddProductsToCart/AddProductsToCartQuantity.tsx +7 -5
  7. package/components/AddProductsToCart/AddProductsToCartSnackbar.tsx +2 -1
  8. package/components/AddProductsToCart/AddProductsToCartSnackbarMessage.tsx +5 -6
  9. package/components/AddProductsToCart/findAddedItems.ts +2 -2
  10. package/components/AddProductsToCart/toUserErrors.ts +2 -2
  11. package/components/AddProductsToCart/useAddProductsToCartAction.ts +4 -3
  12. package/components/AddProductsToCart/useFormAddProductsToCart.ts +3 -3
  13. package/components/JsonLdProduct/ProductPageJsonLd.tsx +1 -1
  14. package/components/JsonLdProduct/jsonLdProduct.tsx +2 -2
  15. package/components/ProductAddToCart/index.ts +0 -1
  16. package/components/ProductCustomizable/CustomizableAreaOption.tsx +5 -4
  17. package/components/ProductCustomizable/CustomizableCheckboxOption.tsx +4 -8
  18. package/components/ProductCustomizable/CustomizableDateOption.tsx +3 -3
  19. package/components/ProductCustomizable/CustomizableDropDownOption.tsx +6 -6
  20. package/components/ProductCustomizable/CustomizableFieldOption.tsx +3 -3
  21. package/components/ProductCustomizable/CustomizableMultipleOption.tsx +4 -8
  22. package/components/ProductCustomizable/CustomizableRadioOption.tsx +4 -8
  23. package/components/ProductCustomizable/ProductCustomizable.tsx +7 -6
  24. package/components/ProductFiltersPro/PriceSlider.tsx +4 -2
  25. package/components/ProductFiltersPro/ProductFilterEqualChip.tsx +1 -1
  26. package/components/ProductFiltersPro/ProductFilterEqualSection.tsx +1 -1
  27. package/components/ProductFiltersPro/ProductFilterRangeChip.tsx +1 -1
  28. package/components/ProductFiltersPro/ProductFiltersPro.tsx +10 -19
  29. package/components/ProductFiltersPro/ProductFiltersProAggregations.tsx +2 -2
  30. package/components/ProductFiltersPro/ProductFiltersProAllFiltersChip.tsx +7 -7
  31. package/components/ProductFiltersPro/ProductFiltersProAllFiltersSidebar.tsx +8 -15
  32. package/components/ProductFiltersPro/ProductFiltersProCategorySection.tsx +6 -8
  33. package/components/ProductFiltersPro/ProductFiltersProChips.tsx +4 -2
  34. package/components/ProductFiltersPro/ProductFiltersProClearAll.tsx +2 -2
  35. package/components/ProductFiltersPro/ProductFiltersProLayoutSidebar.tsx +8 -2
  36. package/components/ProductFiltersPro/ProductFiltersProLimitChip.tsx +4 -2
  37. package/components/ProductFiltersPro/ProductFiltersProLimitSection.tsx +3 -2
  38. package/components/ProductFiltersPro/ProductFiltersProNoResults.tsx +5 -4
  39. package/components/ProductFiltersPro/ProductFiltersProSortChip.tsx +4 -2
  40. package/components/ProductFiltersPro/ProductFiltersProSortDirectionArrow.tsx +5 -3
  41. package/components/ProductFiltersPro/ProductFiltersProSortSection.tsx +3 -2
  42. package/components/ProductFiltersPro/activeAggregations.ts +2 -2
  43. package/components/ProductFiltersPro/applyAggregationCount.ts +2 -2
  44. package/components/ProductFiltersPro/useProductFiltersProClearAllAction.ts +1 -1
  45. package/components/ProductFiltersPro/useProductFiltersProSort.tsx +3 -3
  46. package/components/ProductList/ProductList.graphql +4 -3
  47. package/components/ProductListCount/ProductListCount.tsx +3 -2
  48. package/components/ProductListFilters/FilterCheckboxType.tsx +5 -4
  49. package/components/ProductListFilters/FilterEqualType.tsx +7 -7
  50. package/components/ProductListFilters/FilterRangeType.tsx +4 -3
  51. package/components/ProductListFilters/ProductFilters.graphql +2 -2
  52. package/components/ProductListFilters/ProductListFilters.tsx +3 -3
  53. package/components/ProductListFiltersContainer/ProductListFiltersContainer.tsx +5 -4
  54. package/components/ProductListItem/ProductDiscountLabel.tsx +4 -3
  55. package/components/ProductListItem/ProductListItem.tsx +58 -31
  56. package/components/ProductListItem/ProductListItemImage.tsx +9 -7
  57. package/components/ProductListItem/ProductListItemImageContainer.tsx +9 -8
  58. package/components/ProductListItem/ProductListItemLinkOrDiv.tsx +13 -8
  59. package/components/ProductListItem/ProductListItemTitleAndPrice.tsx +4 -3
  60. package/components/ProductListItems/ProductListItemsBase.tsx +24 -18
  61. package/components/ProductListItems/ProductListParamsProvider.tsx +2 -2
  62. package/components/ProductListItems/filterTypes.tsx +4 -4
  63. package/components/ProductListItems/filteredProductList.tsx +2 -2
  64. package/components/ProductListItems/getFilterTypes.ts +2 -1
  65. package/components/ProductListItems/productListApplyCategoryDefaults.ts +5 -4
  66. package/components/ProductListItems/renderer.tsx +3 -2
  67. package/components/ProductListLink/ProductListLink.tsx +5 -3
  68. package/components/ProductListPagination/ProductListPagination.tsx +6 -5
  69. package/components/ProductListPrice/ProductListPrice.tsx +12 -7
  70. package/components/ProductListSort/ProductListSort.tsx +8 -6
  71. package/components/ProductListSuggestions/ProductListSearchSuggestion.graphql +3 -0
  72. package/components/ProductListSuggestions/ProductListSuggestions.graphql +1 -1
  73. package/components/ProductListSuggestions/ProductListSuggestions.tsx +2 -2
  74. package/components/ProductPage/ProductPageAddToCartRow.tsx +4 -3
  75. package/components/ProductPageBreadcrumb/ProductPageBreadcrumb.tsx +6 -4
  76. package/components/ProductPageBreadcrumb/ProductPageBreadcrumbs.tsx +3 -3
  77. package/components/ProductPageCategory/productPageCategory.ts +1 -1
  78. package/components/ProductPageDescription/ProductPageDescription.tsx +7 -6
  79. package/components/ProductPageGallery/ProductPageGallery.tsx +3 -7
  80. package/components/ProductPageMeta/ProductPageMeta.tsx +2 -2
  81. package/components/ProductPageName/ProductPageName.tsx +2 -2
  82. package/components/ProductPagePrice/ProductPagePrice.tsx +10 -11
  83. package/components/ProductPagePrice/ProductPagePriceTiers.tsx +5 -5
  84. package/components/ProductPagePrice/getProductTierPrice.ts +2 -2
  85. package/components/ProductPagePrice/useCustomizableOptionPrice.ts +7 -6
  86. package/components/ProductScroller/ProductScroller.tsx +11 -16
  87. package/components/ProductShortDescription/ProductShortDescription.tsx +3 -2
  88. package/components/ProductSidebarDelivery/ProductSidebarDelivery.tsx +4 -4
  89. package/components/ProductSpecs/ProductSpecs.tsx +5 -4
  90. package/components/ProductSpecs/ProductSpecsAggregations.tsx +2 -2
  91. package/components/ProductSpecs/ProductSpecsCustomAttributes.tsx +3 -3
  92. package/components/ProductStaticPaths/getProductStaticPaths.ts +4 -3
  93. package/components/ProductStaticPaths/getSitemapPaths.ts +3 -2
  94. package/components/ProductWeight/ProductWeight.tsx +5 -7
  95. package/components/index.ts +5 -0
  96. package/context/productListParamsContext.ts +1 -1
  97. package/hooks/useProductLink.ts +6 -2
  98. package/hooks/useProductList.ts +14 -17
  99. package/hooks/useProductListLink.ts +7 -5
  100. package/hooks/useProductListLinkReplace.ts +1 -1
  101. package/package.json +15 -15
  102. package/test/productURL.fixture.ts +1 -1
  103. package/tsconfig.json +1 -1
  104. package/components/ProductAddToCart/ProductAddToCart.tsx +0 -139
  105. package/components/ProductPageGallery/ProductImage.tsx +0 -10
  106. package/components/ProductPageGallery/ProductVideo.tsx +0 -10
@@ -1,13 +1,10 @@
1
1
  import { useWatch } from '@graphcommerce/ecommerce-ui'
2
- import {
3
- CategoryTreeItem,
4
- UseCategoryTreeProps,
5
- useCategoryTree,
6
- } from '@graphcommerce/magento-category'
2
+ import type { CategoryTreeItem, UseCategoryTreeProps } from '@graphcommerce/magento-category'
3
+ import { useCategoryTree } from '@graphcommerce/magento-category'
4
+ import type { ActionCardAccordionProps } from '@graphcommerce/next-ui'
7
5
  import {
8
6
  ActionCard,
9
7
  ActionCardAccordion,
10
- ActionCardAccordionProps,
11
8
  ActionCardList,
12
9
  Button,
13
10
  IconSvg,
@@ -15,7 +12,8 @@ import {
15
12
  responsiveVal,
16
13
  } from '@graphcommerce/next-ui'
17
14
  import { Trans } from '@lingui/react'
18
- import { Box, SxProps, Theme } from '@mui/material'
15
+ import type { SxProps, Theme } from '@mui/material'
16
+ import { Box } from '@mui/material'
19
17
  import { useProductFiltersPro } from './ProductFiltersPro'
20
18
 
21
19
  export type ProductFiltersProCategoryAccordionProps = {
@@ -29,7 +27,7 @@ export function ProductFiltersProCategoryAccordion(props: ProductFiltersProCateg
29
27
  const { hideTitle, sx, categoryTree, onChange, defaultExpanded } = props
30
28
  const { form } = useProductFiltersPro()
31
29
 
32
- const name = `filters.category_uid.in` as const
30
+ const name = 'filters.category_uid.in'
33
31
  const currentFilter = useWatch({ control: form.control, name })
34
32
 
35
33
  return (
@@ -1,11 +1,13 @@
1
+ import type { ProductFiltersProAggregationsProps } from './ProductFiltersProAggregations'
1
2
  import {
2
3
  ProductFiltersProAggregations,
3
- ProductFiltersProAggregationsProps,
4
4
  productFiltersProChipRenderer,
5
5
  } from './ProductFiltersProAggregations'
6
6
 
7
7
  /**
8
- * @deprecated Not used anymore, use `<ProductFiltersProAggregations renderer={productFiltersProChipRenderer}/>`
8
+ * @deprecated Not used anymore, use `<ProductFiltersProAggregations
9
+ * renderer={productFiltersProChipRenderer}/>`
10
+ * @public
9
11
  */
10
12
  export function ProductFiltersProFilterChips(props: ProductFiltersProAggregationsProps) {
11
13
  const { renderer } = props
@@ -1,7 +1,7 @@
1
1
  import { Button } from '@graphcommerce/next-ui'
2
2
  import { Trans } from '@lingui/react'
3
- import { SxProps, Theme } from '@mui/material'
4
- import { ProductFiltersProAggregationsProps } from './ProductFiltersProAggregations'
3
+ import type { SxProps, Theme } from '@mui/material'
4
+ import type { ProductFiltersProAggregationsProps } from './ProductFiltersProAggregations'
5
5
  import { useProductFiltersProClearAllAction } from './useProductFiltersProClearAllAction'
6
6
  import { useProductFilterProHasFiltersApplied } from './useProductFiltersProHasFiltersApplied'
7
7
 
@@ -1,6 +1,8 @@
1
1
  import { FormAutoSubmit } from '@graphcommerce/ecommerce-ui'
2
2
  import { extendableComponent, StickyBelowHeader } from '@graphcommerce/next-ui'
3
- import { Box, Container, Theme, useMediaQuery } from '@mui/material'
3
+ import type { Theme } from '@mui/material'
4
+ // eslint-disable-next-line @typescript-eslint/no-restricted-imports
5
+ import { Box, Container, useMediaQuery } from '@mui/material'
4
6
  import React from 'react'
5
7
  import { useProductFiltersPro } from './ProductFiltersPro'
6
8
 
@@ -19,10 +21,14 @@ type OwnerProps = {
19
21
  headerPosition: 'before'
20
22
  }
21
23
 
22
- const name = 'ProductFiltersProLayoutSidebar' as const
24
+ const name = 'ProductFiltersProLayoutSidebar'
23
25
  const parts = ['root', 'content'] as const
24
26
  const { withState } = extendableComponent<OwnerProps, typeof name, typeof parts>(name, parts)
25
27
 
28
+ /**
29
+ * @deprecated
30
+ * @public
31
+ */
26
32
  export function ProductFiltersProLayoutSidebar(props: ProductFiltersProLayoutSidebarProps) {
27
33
  const {
28
34
  items,
@@ -1,7 +1,9 @@
1
- import { ActionCardItemBase, ActionCardListForm, useWatch } from '@graphcommerce/ecommerce-ui'
1
+ import type { ActionCardItemBase } from '@graphcommerce/ecommerce-ui'
2
+ import { ActionCardListForm, useWatch } from '@graphcommerce/ecommerce-ui'
2
3
  import { useQuery } from '@graphcommerce/graphql'
3
4
  import { StoreConfigDocument } from '@graphcommerce/magento-store'
4
- import { ActionCard, ChipOverlayOrPopper, ChipOverlayOrPopperProps } from '@graphcommerce/next-ui'
5
+ import type { ChipOverlayOrPopperProps } from '@graphcommerce/next-ui'
6
+ import { ActionCard, ChipOverlayOrPopper } from '@graphcommerce/next-ui'
5
7
  import { Trans } from '@lingui/react'
6
8
  import { useMemo } from 'react'
7
9
  import { useProductFiltersPro } from './ProductFiltersPro'
@@ -1,9 +1,10 @@
1
- import { ActionCardItemBase, ActionCardListForm, useWatch } from '@graphcommerce/ecommerce-ui'
1
+ import type { ActionCardItemBase } from '@graphcommerce/ecommerce-ui'
2
+ import { ActionCardListForm, useWatch } from '@graphcommerce/ecommerce-ui'
2
3
  import { useQuery } from '@graphcommerce/graphql'
3
4
  import { StoreConfigDocument } from '@graphcommerce/magento-store'
4
5
  import { ActionCard, ActionCardAccordion, Button } from '@graphcommerce/next-ui'
5
6
  import { Trans } from '@lingui/react'
6
- import { SxProps, Theme } from '@mui/material'
7
+ import type { SxProps, Theme } from '@mui/material'
7
8
  import { useMemo } from 'react'
8
9
  import { useProductFiltersPro } from './ProductFiltersPro'
9
10
 
@@ -1,12 +1,13 @@
1
1
  import { extendableComponent } from '@graphcommerce/next-ui'
2
2
  import { Trans } from '@lingui/macro'
3
- import { Box, Link, SxProps, Theme, Typography } from '@mui/material'
3
+ import type { SxProps, Theme } from '@mui/material'
4
+ import { Box, Link, Typography } from '@mui/material'
4
5
  import { useProductFiltersProClearAllAction } from './useProductFiltersProClearAllAction'
5
6
  import { useProductFilterProHasFiltersApplied } from './useProductFiltersProHasFiltersApplied'
6
7
 
7
8
  export type ProductFitlersProNoResultProps = { search?: string | null; sx?: SxProps<Theme> }
8
9
 
9
- const name = 'ProductFiltersProNoResults' as const
10
+ const name = 'ProductFiltersProNoResults'
10
11
  const parts = ['root'] as const
11
12
  const { classes } = extendableComponent(name, parts)
12
13
 
@@ -32,8 +33,8 @@ export function ProductFiltersProNoResults(props: ProductFitlersProNoResultProps
32
33
  >
33
34
  {term ? (
34
35
  <>
35
- <Typography variant='h5' align='center'>
36
- <Trans>We couldn&apos;t find any results for {term}</Trans>
36
+ <Typography variant='h5'>
37
+ <Trans>We couldnt find any results for {term}’</Trans>
37
38
  </Typography>
38
39
  <p>
39
40
  {hasFilters ? (
@@ -1,8 +1,10 @@
1
1
  import { ActionCardListForm } from '@graphcommerce/ecommerce-ui'
2
- import { ActionCard, ChipOverlayOrPopper, ChipOverlayOrPopperProps } from '@graphcommerce/next-ui'
2
+ import type { ChipOverlayOrPopperProps } from '@graphcommerce/next-ui'
3
+ import { ActionCard, ChipOverlayOrPopper } from '@graphcommerce/next-ui'
3
4
  import { Trans } from '@lingui/react'
4
5
  import { useProductFiltersPro } from './ProductFiltersPro'
5
- import { UseProductFiltersProSortProps, useProductFiltersProSort } from './useProductFiltersProSort'
6
+ import type { UseProductFiltersProSortProps } from './useProductFiltersProSort'
7
+ import { useProductFiltersProSort } from './useProductFiltersProSort'
6
8
 
7
9
  export type ProductListActionSortProps = UseProductFiltersProSortProps &
8
10
  Omit<
@@ -1,11 +1,13 @@
1
- import { SortEnum } from '@graphcommerce/graphql-mesh'
1
+ import type { SortEnum } from '@graphcommerce/graphql-mesh'
2
2
  import { IconSvg, iconArrowDown, iconArrowUp } from '@graphcommerce/next-ui'
3
3
 
4
- type Props = {
4
+ export type ProductFiltersProSortDirectionArrowProps = {
5
5
  sortDirection: SortEnum | null
6
6
  }
7
7
 
8
- export function ProductFiltersProSortDirectionArrow({ sortDirection }: Props) {
8
+ export function ProductFiltersProSortDirectionArrow({
9
+ sortDirection,
10
+ }: ProductFiltersProSortDirectionArrowProps) {
9
11
  return (
10
12
  <IconSvg
11
13
  src={sortDirection === 'ASC' || sortDirection === null ? iconArrowUp : iconArrowDown}
@@ -1,9 +1,10 @@
1
1
  import { ActionCardListForm } from '@graphcommerce/ecommerce-ui'
2
2
  import { ActionCard, ActionCardAccordion, Button } from '@graphcommerce/next-ui'
3
3
  import { Trans } from '@lingui/react'
4
- import { SxProps, Theme } from '@mui/material'
4
+ import type { SxProps, Theme } from '@mui/material'
5
5
  import { useProductFiltersPro } from './ProductFiltersPro'
6
- import { UseProductFiltersProSortProps, useProductFiltersProSort } from './useProductFiltersProSort'
6
+ import type { UseProductFiltersProSortProps } from './useProductFiltersProSort'
7
+ import { useProductFiltersProSort } from './useProductFiltersProSort'
7
8
 
8
9
  export type ProductFiltersProSortSectionProps = UseProductFiltersProSortProps & {
9
10
  sx?: SxProps<Theme>
@@ -1,6 +1,6 @@
1
1
  import { filterNonNullableKeys } from '@graphcommerce/next-ui'
2
- import { ProductListFiltersFragment } from '../ProductListFilters/ProductListFilters.gql'
3
- import { ProductFilterParams } from '../ProductListItems/filterTypes'
2
+ import type { ProductListFiltersFragment } from '../ProductListFilters/ProductListFilters.gql'
3
+ import type { ProductFilterParams } from '../ProductListItems/filterTypes'
4
4
 
5
5
  export function excludeCategory(aggregations: ProductListFiltersFragment['aggregations']) {
6
6
  return filterNonNullableKeys(aggregations).filter(
@@ -1,6 +1,6 @@
1
1
  import { filterNonNullableKeys } from '@graphcommerce/next-ui'
2
- import { ProductListFiltersFragment } from '../ProductListFilters/ProductListFilters.gql'
3
- import { ProductFilterParams } from '../ProductListItems/filterTypes'
2
+ import type { ProductListFiltersFragment } from '../ProductListFilters/ProductListFilters.gql'
3
+ import type { ProductFilterParams } from '../ProductListItems/filterTypes'
4
4
 
5
5
  /**
6
6
  * Apply aggregation count to aggregation options:
@@ -1,5 +1,5 @@
1
1
  import { useCallback } from 'react'
2
- import { ProductFilterParams } from '../ProductListItems/filterTypes'
2
+ import type { ProductFilterParams } from '../ProductListItems/filterTypes'
3
3
  import { useProductFiltersPro } from './ProductFiltersPro'
4
4
 
5
5
  export function useProductFiltersProClearAllAction() {
@@ -4,9 +4,9 @@ import { StoreConfigDocument } from '@graphcommerce/magento-store'
4
4
  import { filterNonNullableKeys } from '@graphcommerce/next-ui'
5
5
  import { i18n } from '@lingui/core'
6
6
  import { useMemo } from 'react'
7
- import { CategoryDefaultFragment } from '../ProductListItems/CategoryDefault.gql'
8
- import { ProductFilterParams } from '../ProductListItems/filterTypes'
9
- import { ProductListSortFragment } from '../ProductListSort'
7
+ import type { CategoryDefaultFragment } from '../ProductListItems/CategoryDefault.gql'
8
+ import type { ProductFilterParams } from '../ProductListItems/filterTypes'
9
+ import type { ProductListSortFragment } from '../ProductListSort'
10
10
  import { useProductFiltersPro } from './ProductFiltersPro'
11
11
  import type { ProductListActionSortProps } from './ProductFiltersProSortChip'
12
12
  import { ProductFiltersProSortDirectionArrow } from './ProductFiltersProSortDirectionArrow'
@@ -4,8 +4,9 @@ query ProductList(
4
4
  $filters: ProductAttributeFilterInput = {}
5
5
  $sort: ProductAttributeSortInput = {}
6
6
  $search: String = ""
7
- $context: InContextInput = { loggedIn: false }
7
+ $context: PrivateContext
8
8
  $onlyItems: Boolean = false
9
+ $quickSearch: Boolean = false
9
10
  ) {
10
11
  products(
11
12
  pageSize: $pageSize
@@ -13,10 +14,10 @@ query ProductList(
13
14
  filter: $filters
14
15
  sort: $sort
15
16
  search: $search
16
- ) @inContext(context: $context) {
17
+ ) @privateContext(context: $context) {
17
18
  ...ProductListSuggestions @skip(if: $onlyItems)
18
19
  ...ProductListFilters @skip(if: $onlyItems)
19
- ...ProductListCount @skip(if: $onlyItems)
20
+ ...ProductListCount @skip(if: $onlyItems) @include(if: $quickSearch)
20
21
  ...ProductListPagination @skip(if: $onlyItems)
21
22
  ...ProductListSort @skip(if: $onlyItems)
22
23
  ...ProductListItems
@@ -1,7 +1,8 @@
1
1
  import { extendableComponent, responsiveVal } from '@graphcommerce/next-ui'
2
2
  import { Trans } from '@lingui/react'
3
- import { Box, Divider, SxProps, Theme, Typography } from '@mui/material'
4
- import { ProductListCountFragment } from './ProductListCount.gql'
3
+ import type { SxProps, Theme } from '@mui/material'
4
+ import { Box, Divider, Typography } from '@mui/material'
5
+ import type { ProductListCountFragment } from './ProductListCount.gql'
5
6
 
6
7
  const { classes, selectors } = extendableComponent('ProductListCount', [
7
8
  'root',
@@ -1,11 +1,12 @@
1
1
  import { cloneDeep } from '@graphcommerce/graphql'
2
- import { iconCancelAlt, IconSvg } from '@graphcommerce/next-ui'
3
- import { Chip, ChipProps, SxProps, Theme } from '@mui/material'
2
+ import { IconSvg, iconCancelAlt } from '@graphcommerce/next-ui'
3
+ import type { ChipProps, SxProps, Theme } from '@mui/material'
4
+ import { Chip } from '@mui/material'
4
5
  import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
5
6
  import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
6
7
  import { ProductListLink } from '../ProductListLink/ProductListLink'
7
- import { FilterIn } from './FilterEqualType'
8
- import { ProductListFiltersFragment } from './ProductListFilters.gql'
8
+ import type { FilterIn } from './FilterEqualType'
9
+ import type { ProductListFiltersFragment } from './ProductListFilters.gql'
9
10
 
10
11
  type Filter = NonNullable<NonNullable<ProductListFiltersFragment['aggregations']>[number]>
11
12
  export type FilterCheckboxTypeProps = Filter &
@@ -1,9 +1,9 @@
1
1
  import { cloneDeep } from '@graphcommerce/graphql'
2
2
  import type { FilterEqualTypeInput } from '@graphcommerce/graphql-mesh'
3
- import { responsiveVal, extendableComponent, ChipMenu, ChipMenuProps } from '@graphcommerce/next-ui'
3
+ import type { ChipMenuProps } from '@graphcommerce/next-ui'
4
+ import { ChipMenu, extendableComponent, responsiveVal } from '@graphcommerce/next-ui'
4
5
  import {
5
- Box,
6
- // eslint-disable-next-line @typescript-eslint/no-restricted-imports
6
+ Box, // eslint-disable-next-line @typescript-eslint/no-restricted-imports
7
7
  Checkbox,
8
8
  ListItem,
9
9
  ListItemSecondaryAction,
@@ -14,13 +14,13 @@ import type { SetRequired } from 'type-fest'
14
14
  import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
15
15
  import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
16
16
  import { ProductListLink } from '../ProductListLink/ProductListLink'
17
- import { ProductListFiltersFragment } from './ProductListFilters.gql'
17
+ import type { ProductListFiltersFragment } from './ProductListFilters.gql'
18
18
 
19
19
  type OwnerState = {
20
20
  isColor: boolean
21
21
  isActive: boolean
22
22
  }
23
- const componentName = 'FilterEqual' as const
23
+ const componentName = 'FilterEqual'
24
24
  const parts = [
25
25
  'listItem',
26
26
  'listItemInnerContainer',
@@ -44,7 +44,7 @@ export type FilterIn = SetRequired<Omit<FilterEqualTypeInput, 'eq'>, 'in'>
44
44
 
45
45
  type Filter = NonNullable<NonNullable<ProductListFiltersFragment['aggregations']>[number]>
46
46
 
47
- type FilterEqualTypeProps = Filter & Omit<ChipMenuProps, 'selected'>
47
+ export type FilterEqualTypeProps = Filter & Omit<ChipMenuProps, 'selected'>
48
48
 
49
49
  export function FilterEqualType(props: FilterEqualTypeProps) {
50
50
  const { attribute_code, count, label, options, __typename, ...chipProps } = props
@@ -155,7 +155,7 @@ export function FilterEqualType(props: FilterEqualTypeProps) {
155
155
  },
156
156
  [`& .${listItemTextClasses.secondary}`]: {
157
157
  color: theme.palette.grey[500],
158
- marginLeft: `4px`,
158
+ marginLeft: '4px',
159
159
  fontSize: theme.typography.pxToRem(11),
160
160
  display: 'inline',
161
161
  },
@@ -1,16 +1,17 @@
1
1
  import { cloneDeep } from '@graphcommerce/graphql'
2
2
  import type { FilterRangeTypeInput } from '@graphcommerce/graphql-mesh'
3
3
  import { Money } from '@graphcommerce/magento-store'
4
- import { ChipMenu, ChipMenuProps, extendableComponent } from '@graphcommerce/next-ui'
4
+ import type { ChipMenuProps } from '@graphcommerce/next-ui'
5
+ import { ChipMenu, extendableComponent } from '@graphcommerce/next-ui'
5
6
  import { Trans } from '@lingui/react'
6
7
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
7
8
  import { Box, Slider } from '@mui/material'
8
9
  import React, { useEffect } from 'react'
9
10
  import { useProductListLinkReplace } from '../../hooks/useProductListLinkReplace'
10
11
  import { useProductListParamsContext } from '../../hooks/useProductListParamsContext'
11
- import { ProductListFiltersFragment } from './ProductListFilters.gql'
12
+ import type { ProductListFiltersFragment } from './ProductListFilters.gql'
12
13
 
13
- type FilterRangeTypeProps = NonNullable<
14
+ export type FilterRangeTypeProps = NonNullable<
14
15
  NonNullable<ProductListFiltersFragment['aggregations']>[0]
15
16
  > &
16
17
  Omit<ChipMenuProps, 'selected'>
@@ -1,11 +1,11 @@
1
1
  query ProductFilters(
2
2
  $filters: ProductAttributeFilterInput = {}
3
3
  $search: String
4
- $context: InContextInput
4
+ $context: PrivateContext
5
5
  $pageSize: Int = 1
6
6
  ) {
7
7
  filters: products(filter: $filters, currentPage: 1, pageSize: $pageSize, search: $search)
8
- @inContext(context: $context) {
8
+ @privateContext(context: $context) {
9
9
  page_info {
10
10
  total_pages
11
11
  }
@@ -1,9 +1,9 @@
1
- import { ChipMenuProps } from '@graphcommerce/next-ui'
2
- import { FilterTypes } from '../ProductListItems/getFilterTypes'
1
+ import type { ChipMenuProps } from '@graphcommerce/next-ui'
2
+ import type { FilterTypes } from '../ProductListItems/getFilterTypes'
3
3
  import { FilterCheckboxType } from './FilterCheckboxType'
4
4
  import { FilterEqualType } from './FilterEqualType'
5
5
  import { FilterRangeType } from './FilterRangeType'
6
- import { ProductListFiltersFragment } from './ProductListFilters.gql'
6
+ import type { ProductListFiltersFragment } from './ProductListFilters.gql'
7
7
 
8
8
  export type ProductFiltersProps = ProductListFiltersFragment & {
9
9
  filterTypes: FilterTypes
@@ -1,12 +1,13 @@
1
1
  import { Scroller, ScrollerButton, ScrollerProvider } from '@graphcommerce/framer-scroller'
2
2
  import {
3
+ IconSvg,
4
+ extendableComponent,
3
5
  iconChevronLeft,
4
6
  iconChevronRight,
5
- IconSvg,
6
7
  useScrollY,
7
- extendableComponent,
8
8
  } from '@graphcommerce/next-ui'
9
- import { Box, styled, SxProps, Theme } from '@mui/material'
9
+ import type { SxProps, Theme } from '@mui/material'
10
+ import { Box, styled } from '@mui/material'
10
11
  import { m, useTransform } from 'framer-motion'
11
12
  import React, { useEffect, useRef, useState } from 'react'
12
13
 
@@ -17,7 +18,7 @@ export type ProductListFiltersContainerProps = { children: React.ReactNode; sx?:
17
18
  type OwnerState = {
18
19
  isSticky: boolean
19
20
  }
20
- const name = 'ProductListFiltersContainer' as const
21
+ const name = 'ProductListFiltersContainer'
21
22
  const parts = [
22
23
  'wrapper',
23
24
  'container',
@@ -1,6 +1,7 @@
1
1
  import { PercentFormat } from '@graphcommerce/next-ui'
2
- import { Box, BoxProps } from '@mui/material'
3
- import { ProductListItemFragment } from '../../Api/ProductListItem.gql'
2
+ import type { BoxProps } from '@mui/material'
3
+ import { Box } from '@mui/material'
4
+ import type { ProductListItemFragment } from '../../Api/ProductListItem.gql'
4
5
 
5
6
  export type ProductDiscountLabelProps = Pick<ProductListItemFragment, 'price_range'> &
6
7
  Omit<BoxProps, 'children'>
@@ -25,7 +26,7 @@ export function ProductDiscountLabel(props: ProductDiscountLabelProps) {
25
26
  }}
26
27
  {...boxProps}
27
28
  >
28
- <PercentFormat>{discount / 100}</PercentFormat>
29
+ <PercentFormat maximumFractionDigits={0} value={discount / 100} />
29
30
  </Box>
30
31
  )}
31
32
  </>
@@ -1,27 +1,22 @@
1
- import { ImageProps } from '@graphcommerce/image'
1
+ import type { ImageProps } from '@graphcommerce/image'
2
2
  import { extendableComponent } from '@graphcommerce/next-ui'
3
- import { SxProps, Theme, useEventCallback, Skeleton } from '@mui/material'
3
+ import type { SxProps, Theme } from '@mui/material'
4
+ import { Skeleton, useEventCallback } from '@mui/material'
4
5
  import React from 'react'
5
- import { ProductListItemFragment } from '../../Api/ProductListItem.gql'
6
+ import type { ProductListItemFragment } from '../../Api/ProductListItem.gql'
6
7
  import { productLink } from '../../hooks/useProductLink'
7
8
  import { ProductListPrice } from '../ProductListPrice/ProductListPrice'
8
9
  import { ProductDiscountLabel } from './ProductDiscountLabel'
9
- import {
10
- ProductListItemImageProps,
11
- ProductListItemImage,
12
- ProductListItemImageSkeleton,
13
- } from './ProductListItemImage'
14
- import {
10
+ import type { ProductListItemImageProps } from './ProductListItemImage'
11
+ import { ProductListItemImage, ProductListItemImageSkeleton } from './ProductListItemImage'
12
+ import type {
15
13
  ProductListItemImageAreaKeys,
16
14
  ProductListsItemImageAreaProps,
17
- ProductListItemImageAreas,
18
- ProductImageContainer,
19
15
  } from './ProductListItemImageContainer'
20
- import { ProductListItemLinkOrDiv } from './ProductListItemLinkOrDiv'
21
- import {
22
- ProductListItemTitleAndPrice,
23
- ProductListItemTitleAndPriceProps,
24
- } from './ProductListItemTitleAndPrice'
16
+ import { ProductImageContainer, ProductListItemImageAreas } from './ProductListItemImageContainer'
17
+ import { ProductListItemLinkOrDiv, ProductListItemLinkOrDivProps } from './ProductListItemLinkOrDiv'
18
+ import type { ProductListItemTitleAndPriceProps } from './ProductListItemTitleAndPrice'
19
+ import { ProductListItemTitleAndPrice } from './ProductListItemTitleAndPrice'
25
20
 
26
21
  const { classes, selectors } = extendableComponent('ProductListItem', [
27
22
  'root',
@@ -45,25 +40,33 @@ type StyleProps = {
45
40
  imageOnly?: boolean
46
41
  }
47
42
 
48
- type BaseProps = {
43
+ export type BaseProps = {
49
44
  imageOnly?: boolean
50
45
  children?: React.ReactNode
51
46
  sx?: SxProps<Theme>
52
- // eslint-disable-next-line react/no-unused-prop-types
53
- onClick?: (event: React.MouseEvent<HTMLAnchorElement>, item: ProductListItemFragment) => void
47
+ onClick?: (
48
+ event: React.MouseEvent<HTMLAnchorElement | HTMLDivElement>,
49
+ item: ProductListItemFragment,
50
+ ) => void
51
+ slotProps?: {
52
+ root?: Partial<ProductListItemLinkOrDivProps>
53
+ image?: Partial<ProductListItemImageProps>
54
+ imageAreas?: Partial<ProductListsItemImageAreaProps>
55
+ titleAndPrice?: Partial<ProductListItemTitleAndPriceProps>
56
+ }
54
57
  } & StyleProps &
55
58
  Omit<ProductListItemTitleAndPriceProps, 'title' | 'classes' | 'children'> &
56
59
  Omit<ProductListItemImageProps, 'classes'> &
57
60
  Omit<ProductListsItemImageAreaProps, 'classes'> &
58
61
  Pick<ImageProps, 'loading' | 'sizes' | 'dontReportWronglySizedImages'>
59
62
 
60
- // eslint-disable-next-line react/no-unused-prop-types
61
- type SkeletonProps = BaseProps & { __typename: 'Skeleton' }
63
+ export type SkeletonProps = BaseProps & { __typename: 'Skeleton' }
62
64
 
63
- type ProductProps = BaseProps & ProductListItemFragment
65
+ export type ProductProps = BaseProps & ProductListItemFragment
64
66
 
65
67
  export type ProductListItemProps = ProductProps | SkeletonProps
66
68
 
69
+ /** @public */
67
70
  export function ProductListItemReal(props: ProductProps) {
68
71
  const {
69
72
  subTitle,
@@ -83,18 +86,20 @@ export function ProductListItemReal(props: ProductProps) {
83
86
  titleComponent = 'h2',
84
87
  sx = [],
85
88
  onClick,
89
+ slotProps = {},
86
90
  } = props
87
91
 
88
- const handleClick = useEventCallback((e: React.MouseEvent<HTMLAnchorElement>) =>
89
- onClick?.(e, props),
90
- )
91
-
92
92
  return (
93
93
  <ProductListItemLinkOrDiv
94
94
  href={productLink(props)}
95
95
  className={classes.root}
96
- sx={sx}
97
- onClick={handleClick}
96
+ onClick={(e: React.MouseEvent<HTMLAnchorElement | HTMLDivElement>) => onClick?.(e, props)}
97
+ {...slotProps.root}
98
+ sx={[
99
+ ...(Array.isArray(sx) ? sx : [sx]),
100
+ ...(Array.isArray(slotProps.root?.sx) ? slotProps.root.sx : [slotProps.root?.sx]),
101
+ ]}
102
+ ref={slotProps.root?.ref as React.Ref<HTMLAnchorElement | HTMLDivElement>}
98
103
  >
99
104
  <ProductImageContainer className={classes.imageContainer}>
100
105
  <ProductListItemImage
@@ -105,6 +110,7 @@ export function ProductListItemReal(props: ProductProps) {
105
110
  loading={loading}
106
111
  sizes={sizes}
107
112
  dontReportWronglySizedImages={dontReportWronglySizedImages}
113
+ {...slotProps.image}
108
114
  />
109
115
 
110
116
  {!imageOnly && (
@@ -119,6 +125,7 @@ export function ProductListItemReal(props: ProductProps) {
119
125
  {topLeft}
120
126
  </>
121
127
  }
128
+ {...slotProps.imageAreas}
122
129
  />
123
130
  )}
124
131
  </ProductImageContainer>
@@ -130,6 +137,7 @@ export function ProductListItemReal(props: ProductProps) {
130
137
  titleComponent={titleComponent}
131
138
  title={name}
132
139
  subTitle={subTitle}
140
+ {...slotProps.titleAndPrice}
133
141
  >
134
142
  <ProductListPrice {...price_range.minimum_price} />
135
143
  </ProductListItemTitleAndPrice>
@@ -140,13 +148,30 @@ export function ProductListItemReal(props: ProductProps) {
140
148
  )
141
149
  }
142
150
 
151
+ /** @public */
143
152
  export function ProductListItemSkeleton(props: BaseProps) {
144
- const { children, imageOnly = false, aspectRatio, titleComponent = 'h2', sx = [] } = props
153
+ const {
154
+ children,
155
+ imageOnly = false,
156
+ aspectRatio,
157
+ titleComponent = 'h2',
158
+ sx = [],
159
+ slotProps = {},
160
+ } = props
145
161
 
146
162
  return (
147
- <ProductListItemLinkOrDiv sx={sx} className={classes.root}>
163
+ <ProductListItemLinkOrDiv
164
+ sx={sx}
165
+ className={classes.root}
166
+ {...slotProps.root}
167
+ ref={slotProps.root?.ref as React.Ref<HTMLAnchorElement | HTMLDivElement>}
168
+ >
148
169
  <ProductImageContainer className={classes.imageContainer}>
149
- <ProductListItemImageSkeleton classes={classes} aspectRatio={aspectRatio} />
170
+ <ProductListItemImageSkeleton
171
+ classes={classes}
172
+ aspectRatio={aspectRatio}
173
+ {...slotProps.image}
174
+ />
150
175
  </ProductImageContainer>
151
176
 
152
177
  {!imageOnly && (
@@ -156,6 +181,7 @@ export function ProductListItemSkeleton(props: BaseProps) {
156
181
  titleComponent={titleComponent}
157
182
  title={<Skeleton variant='text' sx={{ width: '100px' }} />}
158
183
  subTitle={<Skeleton variant='text' sx={{ width: '20px' }} />}
184
+ {...slotProps.titleAndPrice}
159
185
  >
160
186
  <Skeleton variant='text' sx={{ width: '20px' }} />
161
187
  </ProductListItemTitleAndPrice>
@@ -169,6 +195,7 @@ export function ProductListItemSkeleton(props: BaseProps) {
169
195
  function isSkeleton(props: ProductListItemProps): props is SkeletonProps {
170
196
  return props.__typename === 'Skeleton'
171
197
  }
198
+
172
199
  export function ProductListItem(props: ProductListItemProps) {
173
200
  return isSkeleton(props) ? (
174
201
  <ProductListItemSkeleton {...props} />