@faststore/core 3.81.0 → 3.82.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 (50) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +24 -24
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/server-production/0.pack +0 -0
  8. package/.next/cache/webpack/server-production/index.pack +0 -0
  9. package/.next/prerender-manifest.js +1 -1
  10. package/.next/prerender-manifest.json +1 -1
  11. package/.next/react-loadable-manifest.json +2 -2
  12. package/.next/routes-manifest.json +1 -1
  13. package/.next/server/chunks/3945.js +1 -1
  14. package/.next/server/chunks/83.js +1 -1
  15. package/.next/server/chunks/9563.js +2 -2
  16. package/.next/server/chunks/9630.js +1 -1
  17. package/.next/server/middleware-build-manifest.js +1 -1
  18. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  19. package/.next/server/pages/[...slug].js +1 -1
  20. package/.next/server/pages/api/graphql.js +2 -2
  21. package/.next/server/pages/en-US/404.html +1 -1
  22. package/.next/server/pages/en-US/500.html +1 -1
  23. package/.next/server/pages/en-US/checkout.html +1 -1
  24. package/.next/server/pages/en-US/login.html +1 -1
  25. package/.next/server/pages/en-US/s.html +1 -1
  26. package/.next/server/pages/en-US.html +1 -1
  27. package/.next/server/pages/s.js +1 -1
  28. package/.next/server/pages-manifest.json +1 -1
  29. package/.next/static/chunks/3155.45360f19bde878fa.js +1 -0
  30. package/.next/static/chunks/{7191-2b424236f6799274.js → 7191-bfddc753cd9c143f.js} +1 -1
  31. package/.next/static/chunks/83.45e987438cef99ba.js +1 -0
  32. package/.next/static/chunks/pages/{_app-57478e0d1d2ddf62.js → _app-cdb132efa1562b88.js} +1 -1
  33. package/.next/static/chunks/{webpack-39f2e04144d694ad.js → webpack-70daccedc5bafd4f.js} +1 -1
  34. package/.next/static/{v2vl5Y9dOFfl93DdQC3uY → vwdTFcgKjIi-gK7aiBeq3}/_buildManifest.js +1 -1
  35. package/.next/trace +136 -136
  36. package/.turbo/turbo-build.log +16 -16
  37. package/.turbo/turbo-test.log +5 -5
  38. package/CHANGELOG.md +6 -0
  39. package/cms/faststore/content-types.json +21 -0
  40. package/package.json +3 -3
  41. package/src/components/search/Filter/FilterDeliveryMethodFacet.tsx +2 -8
  42. package/src/components/search/Filter/FilterDesktop.tsx +19 -7
  43. package/src/components/search/Filter/FilterSlider.tsx +20 -9
  44. package/src/components/templates/ProductListingPage/ProductListing.tsx +1 -1
  45. package/src/components/ui/ProductGallery/ProductGallery.tsx +1 -1
  46. package/src/sdk/deliveryPromise/useDeliveryPromise.ts +127 -63
  47. package/src/utils/globalSettings.ts +5 -0
  48. package/.next/static/chunks/3155.c3fa96f983101956.js +0 -1
  49. package/.next/static/chunks/83.affac11ef34a0c11.js +0 -1
  50. /package/.next/static/{v2vl5Y9dOFfl93DdQC3uY → vwdTFcgKjIi-gK7aiBeq3}/_ssgManifest.js +0 -0
@@ -1,23 +1,23 @@
1
1
 
2
- > @faststore/core@3.80.0 prebuild /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.81.0 prebuild /home/runner/work/faststore/faststore/packages/core
3
3
  > na run partytown && na run generate
4
4
 
5
5
 
6
- > @faststore/core@3.80.0 partytown /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@3.81.0 partytown /home/runner/work/faststore/faststore/packages/core
7
7
  > partytown copylib ./public/~partytown
8
8
 
9
9
  Partytown lib copied to: /home/runner/work/faststore/faststore/packages/core/public/~partytown
10
10
 
11
- > @faststore/core@3.80.0 generate /home/runner/work/faststore/faststore/packages/core
11
+ > @faststore/core@3.81.0 generate /home/runner/work/faststore/faststore/packages/core
12
12
  > na run generate:schema && na run generate:codegen && na run format:generated
13
13
 
14
14
 
15
- > @faststore/core@3.80.0 generate:schema /home/runner/work/faststore/faststore/packages/core
15
+ > @faststore/core@3.81.0 generate:schema /home/runner/work/faststore/faststore/packages/core
16
16
  > tsx src/server/generator/generateGraphQLSchemaFile.ts
17
17
 
18
18
  Schema GraphQL file generated successfully
19
19
 
20
- > @faststore/core@3.80.0 generate:codegen /home/runner/work/faststore/faststore/packages/core
20
+ > @faststore/core@3.81.0 generate:codegen /home/runner/work/faststore/faststore/packages/core
21
21
  > graphql-codegen
22
22
 
23
23
  [STARTED] Parse Configuration
@@ -37,11 +37,11 @@ Running lifecycle hook "afterStart" scripts...
37
37
  [CLI] Loading Documents
38
38
  [CLI] Generating output
39
39
 
40
- > @faststore/core@3.80.0 format:generated /home/runner/work/faststore/faststore/packages/core
40
+ > @faststore/core@3.81.0 format:generated /home/runner/work/faststore/faststore/packages/core
41
41
  > prettier --write "@generated/**/*.{ts,js,tsx,jsx,json}" --loglevel error
42
42
 
43
43
 
44
- > @faststore/core@3.80.0 build /home/runner/work/faststore/faststore/packages/core
44
+ > @faststore/core@3.81.0 build /home/runner/work/faststore/faststore/packages/core
45
45
  > next build
46
46
 
47
47
  ⚠ No build cache found. Please configure build caching for faster rebuilds. Read more: https://nextjs.org/docs/messages/no-cache
@@ -65,8 +65,8 @@ Browserslist: browsers data (caniuse-lite) is 8 months old. Please run:
65
65
  Collecting page data ...
66
66
  Generating static pages (0/6) ...
67
67
 
68
68
  Generating static pages (1/6)
69
-
70
69
  Generating static pages (2/6)
71
70
  Warning: Dynamic Content not found for the page: home. Refer to the Dynamic Content documentation at https://developers.vtex.com/docs/guides/faststore/dynamic-content-overview for mapping the page and the corresponding data-fetching function.
71
+
72
72
  Generating static pages (2/6)
73
73
 
74
74
  Generating static pages (4/6)
75
75
 
76
76
  ✓ Generating static pages (6/6)
77
77
  Finalizing page optimization ...
@@ -83,8 +83,8 @@ Route (pages) Size First Load JS
83
83
  ├ └ css/6d92375b6ee8276a.css 16.1 kB
84
84
  ├ ○ /404 1.55 kB 138 kB
85
85
  ├ ● /500 1.55 kB 138 kB
86
- ├ λ /account 240 B 106 kB
87
- ├ ● /account/[...unknown] 281 B 106 kB
86
+ ├ λ /account 240 B 107 kB
87
+ ├ ● /account/[...unknown] 281 B 107 kB
88
88
  ├ λ /account/403 2.44 kB 139 kB
89
89
  ├ └ css/b7bba8fce075688b.css 4.2 kB
90
90
  ├ λ /account/404 2.13 kB 139 kB
@@ -93,24 +93,24 @@ Route (pages) Size First Load JS
93
93
  ├ └ css/38e3a4a55b13b062.css 12.7 kB
94
94
  ├ λ /account/orders/[id] 12.1 kB 149 kB
95
95
  ├ └ css/297be4be3be36ff0.css 12.6 kB
96
- ├ λ /account/profile 1.79 kB 138 kB
96
+ ├ λ /account/profile 1.79 kB 139 kB
97
97
  ├ └ css/831a1f72fe4b2d80.css 3.97 kB
98
- ├ λ /account/security 3.76 kB 140 kB
98
+ ├ λ /account/security 3.76 kB 141 kB
99
99
  ├ └ css/ec7fdad03808422d.css 5.22 kB
100
- ├ λ /account/user-details 1.74 kB 138 kB
100
+ ├ λ /account/user-details 1.74 kB 139 kB
101
101
  ├ └ css/e46393a76c5d93a9.css 4.17 kB
102
102
  ├ λ /api/graphql 0 B 106 kB
103
103
  ├ λ /api/health/live 0 B 106 kB
104
104
  ├ λ /api/health/ready 0 B 106 kB
105
105
  ├ λ /api/preview 0 B 106 kB
106
- ├ ● /checkout 737 B 137 kB
106
+ ├ ● /checkout 737 B 138 kB
107
107
  ├ ● /login 1.68 kB 138 kB
108
108
  └ ● /s 3.3 kB 155 kB
109
109
  + First Load JS shared by all 110 kB
110
110
  ├ chunks/framework-807b0f81cbc129f0.js 45.4 kB
111
111
  ├ chunks/main-f658704b53a96ab1.js 33.1 kB
112
- ├ chunks/pages/_app-57478e0d1d2ddf62.js 23.8 kB
113
- ├ chunks/webpack-39f2e04144d694ad.js 3.85 kB
112
+ ├ chunks/pages/_app-cdb132efa1562b88.js 24.1 kB
113
+ ├ chunks/webpack-70daccedc5bafd4f.js 3.85 kB
114
114
  └ css/4b8252ed2f23ac67.css 3.51 kB
115
115
 
116
116
  λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
@@ -1,14 +1,14 @@
1
1
 
2
- > @faststore/core@3.80.0 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@3.81.0 test /home/runner/work/faststore/faststore/packages/core
3
3
  > jest
4
4
 
5
- PASS test/utils/multipleTemplates.test.ts (26.996 s)
6
- PASS test/server/cms/global.test.ts (27.008 s)
5
+ PASS test/utils/multipleTemplates.test.ts (26.552 s)
6
+ PASS test/server/cms/global.test.ts (27.109 s)
7
7
  PASS test/server/cms/index.test.ts
8
- PASS test/server/index.test.ts (30.315 s)
8
+ PASS test/server/index.test.ts (30.406 s)
9
9
 
10
10
  Test Suites: 4 passed, 4 total
11
11
  Tests: 22 passed, 22 total
12
12
  Snapshots: 0 total
13
- Time: 31.607 s
13
+ Time: 31.589 s
14
14
  Ran all test suites.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.82.0](https://github.com/vtex/faststore/compare/v3.81.0...v3.82.0) (2025-09-05)
7
+
8
+ ### Features
9
+
10
+ - Delivery Promise 2.1 - filters by Delivery Option ([#2926](https://github.com/vtex/faststore/issues/2926)) ([d365a5e](https://github.com/vtex/faststore/commit/d365a5ea0da451a58c87fd6bcfd7f49df2c96158)), closes [#2928](https://github.com/vtex/faststore/issues/2928) [#2930](https://github.com/vtex/faststore/issues/2930) [#2937](https://github.com/vtex/faststore/issues/2937)
11
+
6
12
  # 3.81.0 (2025-09-05)
7
13
 
8
14
  ### Features
@@ -234,6 +234,27 @@
234
234
  }
235
235
  }
236
236
  }
237
+ },
238
+ "deliveryOptions": {
239
+ "title": "PLP/Search Filter: Delivery Options",
240
+ "type": "object",
241
+ "properties": {
242
+ "enabled": {
243
+ "title": "Should enable Delivery Options?",
244
+ "type": "boolean",
245
+ "default": true
246
+ },
247
+ "title": {
248
+ "title": "Delivery Options title",
249
+ "type": "string",
250
+ "default": "Delivery Option"
251
+ },
252
+ "allDeliveryOptions": {
253
+ "title": "All delivery options label",
254
+ "type": "string",
255
+ "default": "All delivery options"
256
+ }
257
+ }
237
258
  }
238
259
  }
239
260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "3.81.0",
3
+ "version": "3.82.0",
4
4
  "license": "MIT",
5
5
  "repository": "vtex/faststore",
6
6
  "browserslist": "supports es6-module and not dead",
@@ -44,7 +44,7 @@
44
44
  "@envelop/graphql-jit": "^8.0.3",
45
45
  "@envelop/parser-cache": "^6.0.2",
46
46
  "@envelop/validation-cache": "^6.0.2",
47
- "@faststore/api": "^3.81.0",
47
+ "@faststore/api": "^3.82.0",
48
48
  "@faststore/graphql-utils": "^3.81.0",
49
49
  "@faststore/lighthouse": "^3.81.0",
50
50
  "@faststore/sdk": "^3.81.0",
@@ -108,5 +108,5 @@
108
108
  "ts-jest": "29.1.1",
109
109
  "typescript": "5.3.2"
110
110
  },
111
- "gitHead": "37ac845dce3df8c22a348a2e6895f5b65dc9de45"
111
+ "gitHead": "8037b2c4dccc4add6e048c8082942a6744187f54"
112
112
  }
@@ -1,17 +1,11 @@
1
1
  import { regionSliderTypes, Button as UIButton, useUI } from '@faststore/ui'
2
+ import type { StoreFacetValueBoolean } from '@generated/graphql'
2
3
  import { sessionStore } from 'src/sdk/session'
3
4
  import type { GlobalCmsData } from 'src/utils/globalSettings'
4
5
  import { textToTitleCase } from 'src/utils/utilities'
5
6
 
6
- interface FacetValue {
7
- value: string
8
- label: string
9
- selected: boolean
10
- quantity: number
11
- }
12
-
13
7
  interface FilterDeliveryMethodFacetProps {
14
- item: FacetValue
8
+ item: StoreFacetValueBoolean
15
9
  deliveryMethods: GlobalCmsData['deliveryPromise']['deliveryMethods']
16
10
  }
17
11
 
@@ -18,8 +18,8 @@ import type { useFilter } from 'src/sdk/search/useFilter'
18
18
  import type { FilterSliderProps } from './FilterSlider'
19
19
 
20
20
  import {
21
- useDeliveryPromise,
22
21
  PICKUP_ALL_FACET_VALUE,
22
+ useDeliveryPromise,
23
23
  } from 'src/sdk/deliveryPromise'
24
24
  import { getGlobalSettings } from 'src/utils/globalSettings'
25
25
  import FilterDeliveryMethodFacet from './FilterDeliveryMethodFacet'
@@ -48,6 +48,7 @@ function FilterDesktop({
48
48
  const {
49
49
  facets: filteredFacets,
50
50
  deliveryLabel,
51
+ deliveryOptionsLabel,
51
52
  isPickupAllEnabled,
52
53
  shouldDisplayDeliveryButton,
53
54
  onDeliveryFacetChange,
@@ -92,17 +93,24 @@ function FilterDesktop({
92
93
  const index = shouldDisplayDeliveryButton ? idx + 1 : idx
93
94
  const { __typename: type, label } = facet
94
95
  const isExpanded = expanded.has(index)
95
- const isDeliveryFacet = facet.key === 'shipping'
96
+ const isDeliveryMethodFacet = facet.key === 'shipping'
97
+ const isDeliveryOptionFacet = facet.key === 'delivery-options'
98
+
99
+ const sectionLabel = isDeliveryMethodFacet
100
+ ? deliveryLabel
101
+ : isDeliveryOptionFacet
102
+ ? deliveryOptionsLabel
103
+ : label
96
104
 
97
105
  return (
98
106
  <UIFilterFacets
99
- key={`${testId}-${label}-${index}`}
107
+ key={`${testId}-${sectionLabel}-${index}`}
100
108
  testId={testId}
101
109
  index={index}
102
110
  type={type}
103
- label={isDeliveryFacet ? deliveryLabel : label}
111
+ label={sectionLabel}
104
112
  description={
105
- isDeliveryFacet
113
+ isDeliveryMethodFacet
106
114
  ? deliveryPromiseSettings?.deliveryMethods?.description
107
115
  : undefined
108
116
  }
@@ -126,7 +134,7 @@ function FilterDesktop({
126
134
  quantity={item.quantity}
127
135
  facetKey={facet.key}
128
136
  label={
129
- isDeliveryFacet ? (
137
+ isDeliveryMethodFacet ? (
130
138
  <FilterDeliveryMethodFacet
131
139
  item={item}
132
140
  deliveryMethods={
@@ -137,7 +145,11 @@ function FilterDesktop({
137
145
  item.label
138
146
  )
139
147
  }
140
- type={isDeliveryFacet ? 'radio' : 'checkbox'}
148
+ type={
149
+ isDeliveryMethodFacet || isDeliveryOptionFacet
150
+ ? 'radio'
151
+ : 'checkbox'
152
+ }
141
153
  />
142
154
  )
143
155
  )}
@@ -12,17 +12,16 @@ import {
12
12
  type FilterSliderProps as UIFilterSliderProps,
13
13
  type IconProps as UIIconProps,
14
14
  } from '@faststore/ui'
15
-
16
15
  import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
17
16
 
18
17
  import type { Filter_FacetsFragment } from '@generated/graphql'
19
18
  import FilterDeliveryMethodFacet from './FilterDeliveryMethodFacet'
20
19
 
21
- import type { useFilter } from 'src/sdk/search/useFilter'
22
20
  import {
23
- useDeliveryPromise,
24
21
  PICKUP_ALL_FACET_VALUE,
22
+ useDeliveryPromise,
25
23
  } from 'src/sdk/deliveryPromise'
24
+ import type { useFilter } from 'src/sdk/search/useFilter'
26
25
  import { getGlobalSettings } from 'src/utils/globalSettings'
27
26
 
28
27
  import styles from './section.module.scss'
@@ -104,6 +103,7 @@ function FilterSlider({
104
103
  const {
105
104
  facets: filteredFacets,
106
105
  deliveryLabel,
106
+ deliveryOptionsLabel,
107
107
  isPickupAllEnabled,
108
108
  shouldDisplayDeliveryButton,
109
109
  onDeliveryFacetChange,
@@ -190,17 +190,24 @@ function FilterSlider({
190
190
  const index = shouldDisplayDeliveryButton ? idx + 1 : idx
191
191
  const { __typename: type, label } = facet
192
192
  const isExpanded = expanded.has(index)
193
- const isDeliveryFacet = facet.key === 'shipping'
193
+ const isDeliveryMethodFacet = facet.key === 'shipping'
194
+ const isDeliveryOptionFacet = facet.key === 'delivery-options'
195
+
196
+ const sectionLabel = isDeliveryMethodFacet
197
+ ? deliveryLabel
198
+ : isDeliveryOptionFacet
199
+ ? deliveryOptionsLabel
200
+ : label
194
201
 
195
202
  return (
196
203
  <UIFilterFacets
197
- key={`${testId}-${label}-${index}`}
204
+ key={`${testId}-${sectionLabel}-${index}`}
198
205
  testId={`mobile-${testId}`}
199
206
  index={index}
200
207
  type={type}
201
- label={isDeliveryFacet ? deliveryLabel : label}
208
+ label={sectionLabel}
202
209
  description={
203
- isDeliveryFacet
210
+ isDeliveryMethodFacet
204
211
  ? deliveryPromiseSettings?.deliveryMethods?.description
205
212
  : undefined
206
213
  }
@@ -226,7 +233,7 @@ function FilterSlider({
226
233
  quantity={item.quantity}
227
234
  facetKey={facet.key}
228
235
  label={
229
- isDeliveryFacet ? (
236
+ isDeliveryMethodFacet ? (
230
237
  <FilterDeliveryMethodFacet
231
238
  item={item}
232
239
  deliveryMethods={
@@ -237,7 +244,11 @@ function FilterSlider({
237
244
  item.label
238
245
  )
239
246
  }
240
- type={isDeliveryFacet ? 'radio' : 'checkbox'}
247
+ type={
248
+ isDeliveryMethodFacet || isDeliveryOptionFacet
249
+ ? 'radio'
250
+ : 'checkbox'
251
+ }
241
252
  />
242
253
  )
243
254
  )}
@@ -1,4 +1,4 @@
1
- import { formatSearchState, useSearch } from '@faststore/sdk'
1
+ import { useSearch } from '@faststore/sdk'
2
2
  import type {
3
3
  ServerCollectionPageQueryQuery,
4
4
  ServerManyProductsQueryQuery,
@@ -22,8 +22,8 @@ import { useDelayedPagination } from 'src/sdk/search/useDelayedPagination'
22
22
  import { useFilter } from 'src/sdk/search/useFilter'
23
23
  import useScreenResize from 'src/sdk/ui/useScreenResize'
24
24
 
25
- import styles from '../../sections/ProductGallery/section.module.scss'
26
25
  import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
26
+ import styles from '../../sections/ProductGallery/section.module.scss'
27
27
 
28
28
  const ProductGalleryPage = lazy(() => import('./ProductGalleryPage'))
29
29
  const FilterSkeleton = dynamic(
@@ -26,6 +26,9 @@ export const SHIPPING_FACET_KEY = 'shipping' as const
26
26
  export const PICKUP_IN_POINT_FACET_VALUE = 'pickup-in-point' as const
27
27
  export const ALL_DELIVERY_METHODS_FACET_VALUE = 'all-delivery-methods' as const
28
28
  export const PICKUP_ALL_FACET_VALUE = 'pickup-all' as const
29
+ export const ALL_DELIVERY_OPTIONS_FACET_VALUE = 'all-delivery-options' as const
30
+ export const DELIVERY_OPTIONS_FACET_KEY = 'delivery-options' as const
31
+ export const DYNAMIC_ESTIMATE_FACET_KEY = 'dynamic-estimate' as const
29
32
 
30
33
  type Facet = SearchState['selectedFacets'][number]
31
34
 
@@ -105,6 +108,8 @@ export function useDeliveryPromise({
105
108
  } = useDeliveryPromiseContext()
106
109
 
107
110
  const isDeliveryPromiseEnabled = deliveryPromiseConfig.enabled
111
+ const isDeliveryOptionsEnabled =
112
+ deliveryPromiseSettings?.deliveryOptions?.enabled ?? true
108
113
 
109
114
  const selectedFacets = useMemo(
110
115
  () => selectedFilterFacets ?? searchState.selectedFacets,
@@ -199,21 +204,39 @@ export function useDeliveryPromise({
199
204
  [defaultPickupPoint, selectedFacets]
200
205
  )
201
206
 
202
- const allDeliveryMethodsFacet = useMemo(
203
- () => ({
204
- value: ALL_DELIVERY_METHODS_FACET_VALUE,
205
- label:
206
- deliveryPromiseSettings?.deliveryMethods?.allDeliveryMethods ??
207
- 'All delivery methods',
208
- selected:
209
- !selectedFacets.some((facet) => facet.key === SHIPPING_FACET_KEY) ||
210
- selectedFacets?.some(
211
- (facet) =>
212
- facet.key === SHIPPING_FACET_KEY &&
213
- facet.value === ALL_DELIVERY_METHODS_FACET_VALUE
214
- ),
215
- quantity: 0,
216
- }),
207
+ const [allDeliveryMethodsFacet, allDeliveryOptionsFacet] = useMemo(
208
+ () => [
209
+ {
210
+ value: ALL_DELIVERY_METHODS_FACET_VALUE,
211
+ label:
212
+ deliveryPromiseSettings?.deliveryMethods?.allDeliveryMethods ??
213
+ 'All delivery methods',
214
+ selected:
215
+ !selectedFacets.some(({ key }) => key === SHIPPING_FACET_KEY) ||
216
+ selectedFacets?.some(
217
+ ({ key, value }) =>
218
+ key === SHIPPING_FACET_KEY &&
219
+ value === ALL_DELIVERY_METHODS_FACET_VALUE
220
+ ),
221
+ quantity: 0,
222
+ },
223
+ {
224
+ value: ALL_DELIVERY_OPTIONS_FACET_VALUE,
225
+ label:
226
+ deliveryPromiseSettings?.deliveryOptions?.allDeliveryOptions ??
227
+ 'All delivery options',
228
+ selected:
229
+ !selectedFacets.some(
230
+ ({ key }) => key === DELIVERY_OPTIONS_FACET_KEY
231
+ ) ||
232
+ selectedFacets?.some(
233
+ ({ key, value }) =>
234
+ key === DELIVERY_OPTIONS_FACET_KEY &&
235
+ value === ALL_DELIVERY_OPTIONS_FACET_VALUE
236
+ ),
237
+ quantity: 0,
238
+ },
239
+ ],
217
240
  [selectedFacets, deliveryPromiseSettings, pickupInPointFacet]
218
241
  )
219
242
 
@@ -272,61 +295,100 @@ export function useDeliveryPromise({
272
295
  if (!allFacets) return []
273
296
 
274
297
  return !isDeliveryPromiseEnabled || !postalCode
275
- ? allFacets.filter(({ key }) => key !== SHIPPING_FACET_KEY)
276
- : allFacets.map((facet) => {
277
- if (
278
- facet.key !== SHIPPING_FACET_KEY ||
279
- facet.__typename !== 'StoreFacetBoolean'
280
- )
281
- return facet
298
+ ? allFacets.filter(
299
+ ({ key }) =>
300
+ key !== SHIPPING_FACET_KEY &&
301
+ key !== DELIVERY_OPTIONS_FACET_KEY &&
302
+ key !== DYNAMIC_ESTIMATE_FACET_KEY
303
+ )
304
+ : allFacets
305
+ .filter(({ key }) => key !== DYNAMIC_ESTIMATE_FACET_KEY) // TODO: remove this filter when dynamic estimate is implemented
306
+ .filter(({ key }) => {
307
+ if (
308
+ !isDeliveryOptionsEnabled &&
309
+ key === DELIVERY_OPTIONS_FACET_KEY
310
+ ) {
311
+ return false
312
+ }
313
+
314
+ return true
315
+ })
316
+ .map((facet) => {
317
+ if (facet.__typename !== 'StoreFacetBoolean') return facet
318
+
319
+ if (facet.key === DELIVERY_OPTIONS_FACET_KEY) {
320
+ facet.values = withUniqueFacet(
321
+ facet.values,
322
+ allDeliveryOptionsFacet
323
+ )
324
+
325
+ return facet
326
+ }
282
327
 
283
- facet.values = withUniqueFacet(facet.values, allDeliveryMethodsFacet)
284
- const pickupInPointFacetIndex = facet.values.findIndex(
285
- (item) => item?.value === PICKUP_IN_POINT_FACET_VALUE
286
- )
328
+ if (facet.key !== SHIPPING_FACET_KEY) return facet
287
329
 
288
- // Remove old pickup `pickup in point` facet from list and search state
289
- if (pickupInPointFacetIndex !== -1 && !defaultPickupPoint) {
290
- const selectedShippingFacet = selectedFacets.find(
291
- ({ key }) => key === SHIPPING_FACET_KEY
330
+ facet.values = withUniqueFacet(
331
+ facet.values,
332
+ allDeliveryMethodsFacet
333
+ )
334
+ const pickupInPointFacetIndex = facet.values.findIndex(
335
+ (item) => item?.value === PICKUP_IN_POINT_FACET_VALUE
292
336
  )
293
337
 
294
- if (selectedShippingFacet) {
295
- const selectedPickupInPointFacets = selectedFacets.filter(
296
- ({ key, value }) =>
297
- value === PICKUP_IN_POINT_FACET_VALUE ||
298
- key === PICKUP_POINT_FACET_KEY
338
+ // Remove old pickup `pickup in point` facet from list and search state
339
+ if (pickupInPointFacetIndex !== -1 && !defaultPickupPoint) {
340
+ const selectedShippingFacet = selectedFacets.find(
341
+ ({ key }) => key === SHIPPING_FACET_KEY
299
342
  )
300
343
 
301
- selectedPickupInPointFacets.length
302
- ? onDeliveryFacetChange({ facets: selectedPickupInPointFacets })
303
- : onDeliveryFacetChange({ facet: selectedShippingFacet })
344
+ if (selectedShippingFacet) {
345
+ const selectedPickupInPointFacets = selectedFacets.filter(
346
+ ({ key, value }) =>
347
+ value === PICKUP_IN_POINT_FACET_VALUE ||
348
+ key === PICKUP_POINT_FACET_KEY
349
+ )
350
+
351
+ selectedPickupInPointFacets.length
352
+ ? onDeliveryFacetChange({
353
+ facets: selectedPickupInPointFacets,
354
+ })
355
+ : onDeliveryFacetChange({ facet: selectedShippingFacet })
356
+ }
357
+
358
+ // Removes pickupInPointIndex from array
359
+ facet.values = facet.values.filter(
360
+ (_, index) => index !== pickupInPointFacetIndex
361
+ )
362
+ }
363
+ // Prevent multiple `pickup in point` facet
364
+ else if (pickupInPointFacetIndex === -1 && defaultPickupPoint) {
365
+ facet.values.push(pickupInPointFacet)
366
+ }
367
+ // Replace current `pickup-in-point` facet with the updated one
368
+ else if (
369
+ facet.values[pickupInPointFacetIndex] &&
370
+ facet.values[pickupInPointFacetIndex]?.label !==
371
+ pickupInPointFacet.label
372
+ ) {
373
+ facet.values[pickupInPointFacetIndex] = pickupInPointFacet
304
374
  }
305
375
 
306
- // Removes pickupInPointIndex from array
307
- facet.values = facet.values.filter(
308
- (_, index) => index !== pickupInPointFacetIndex
376
+ facet.values = facet.values.sort((a, b) =>
377
+ (a.value ?? '').localeCompare(b.value ?? '')
309
378
  )
310
- }
311
- // Prevent multiple `pickup in point` facet
312
- else if (pickupInPointFacetIndex === -1 && defaultPickupPoint) {
313
- facet.values.push(pickupInPointFacet)
314
- }
315
- // Replace current `pickup-in-point` facet with the updated one
316
- else if (
317
- facet.values[pickupInPointFacetIndex] &&
318
- facet.values[pickupInPointFacetIndex]?.label !==
319
- pickupInPointFacet.label
320
- ) {
321
- facet.values[pickupInPointFacetIndex] = pickupInPointFacet
322
- }
323
-
324
- facet.values = facet.values.sort((a, b) =>
325
- (a.value ?? '').localeCompare(b.value ?? '')
326
- )
327
-
328
- return facet
329
- })
379
+
380
+ return facet
381
+ })
382
+ .sort((a, b) => {
383
+ // Define priority order: shipping (0), delivery-options (1), others (2)
384
+ const getPriority = (key: string) => {
385
+ if (key === SHIPPING_FACET_KEY) return 0
386
+ if (key === DELIVERY_OPTIONS_FACET_KEY) return 1
387
+ return 2
388
+ }
389
+
390
+ return getPriority(a.key) - getPriority(b.key)
391
+ })
330
392
  }, [
331
393
  allDeliveryMethodsFacet,
332
394
  pickupInPointFacet,
@@ -395,6 +457,8 @@ export function useDeliveryPromise({
395
457
  onDeliveryFacetChange,
396
458
  deliveryLabel:
397
459
  deliveryPromiseSettings?.deliveryMethods?.title ?? 'Delivery',
460
+ deliveryOptionsLabel:
461
+ deliveryPromiseSettings?.deliveryOptions?.title ?? 'Delivery Option',
398
462
  isPickupAllEnabled:
399
463
  pickupPoints?.length > 0 &&
400
464
  (deliveryPromiseSettings?.deliveryMethods?.pickupAll?.enabled ?? false),
@@ -408,10 +472,10 @@ type BoleanFacet = Extract<
408
472
  >['values'][number]
409
473
 
410
474
  function withUniqueFacet(facets: Array<BoleanFacet>, facet: BoleanFacet) {
411
- return facets.filter((item) => item.value !== facet.value).concat([facet])
475
+ return [facet, ...facets.filter((item) => item.value !== facet.value)]
412
476
  }
413
477
 
414
- const RADIO_FACETS = ['shipping', 'pickupPoint'] as const
478
+ const RADIO_FACETS = ['shipping', 'pickupPoint', 'delivery-options'] as const
415
479
  function isRadioFacet(facet: unknown): facet is (typeof RADIO_FACETS)[number] {
416
480
  if (typeof facet !== 'string') return false
417
481
 
@@ -58,6 +58,11 @@ type DeliveryPromiseCmsData = {
58
58
  alt?: string
59
59
  }
60
60
  }
61
+ deliveryOptions?: {
62
+ enabled?: boolean
63
+ title?: string
64
+ allDeliveryOptions?: string
65
+ }
61
66
  }
62
67
 
63
68
  export function getGlobalSettings(