@faststore/core 2.0.88-alpha.0 → 2.0.90-alpha.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.
- package/.turbo/turbo-build.log +11 -10
- package/CHANGELOG.md +12 -0
- package/cypress/integration/plp.test.js +2 -3
- package/package.json +4 -4
- package/src/components/product/OutOfStock/OutOfStock.tsx +26 -108
- package/src/components/product/OutOfStock/index.ts +0 -1
- package/src/components/search/Filter/Filter.tsx +7 -27
- package/src/components/search/Filter/FilterDesktop.tsx +109 -0
- package/src/components/search/Filter/FilterSlider.tsx +97 -73
- package/src/components/sections/ProductDetails/ProductDetails.tsx +62 -64
- package/src/components/sections/ProductDetails/product-details.module.scss +0 -4
- package/.next/BUILD_ID +0 -1
- package/.next/build-manifest.json +0 -101
- package/.next/cache/.tsbuildinfo +0 -1
- package/.next/cache/config.json +0 -7
- package/.next/cache/eslint/.cache_1gneedd +0 -1
- package/.next/cache/next-server.js.nft.json +0 -1
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/export-marker.json +0 -1
- package/.next/images-manifest.json +0 -1
- package/.next/next-server.js.nft.json +0 -1
- package/.next/package.json +0 -1
- package/.next/prerender-manifest.json +0 -1
- package/.next/react-loadable-manifest.json +0 -44
- package/.next/required-server-files.json +0 -1
- package/.next/routes-manifest.json +0 -1
- package/.next/server/chunks/104.js +0 -196
- package/.next/server/chunks/143.js +0 -106
- package/.next/server/chunks/154.js +0 -206
- package/.next/server/chunks/183.js +0 -72
- package/.next/server/chunks/247.js +0 -61
- package/.next/server/chunks/264.js +0 -67
- package/.next/server/chunks/280.js +0 -417
- package/.next/server/chunks/287.js +0 -79
- package/.next/server/chunks/312.js +0 -684
- package/.next/server/chunks/317.js +0 -125
- package/.next/server/chunks/350.js +0 -120
- package/.next/server/chunks/371.js +0 -1467
- package/.next/server/chunks/377.js +0 -82
- package/.next/server/chunks/394.js +0 -3801
- package/.next/server/chunks/439.js +0 -175
- package/.next/server/chunks/444.js +0 -464
- package/.next/server/chunks/465.js +0 -91
- package/.next/server/chunks/576.js +0 -72
- package/.next/server/chunks/608.js +0 -515
- package/.next/server/chunks/650.js +0 -216
- package/.next/server/chunks/664.js +0 -124
- package/.next/server/chunks/676.js +0 -32
- package/.next/server/chunks/746.js +0 -237
- package/.next/server/chunks/777.js +0 -708
- package/.next/server/chunks/854.js +0 -72
- package/.next/server/chunks/859.js +0 -959
- package/.next/server/chunks/872.js +0 -378
- package/.next/server/chunks/881.js +0 -320
- package/.next/server/chunks/898.js +0 -240
- package/.next/server/chunks/914.js +0 -96
- package/.next/server/chunks/953.js +0 -674
- package/.next/server/chunks/98.js +0 -266
- package/.next/server/chunks/992.js +0 -570
- package/.next/server/chunks/font-manifest.json +0 -1
- package/.next/server/font-manifest.json +0 -1
- package/.next/server/middleware-build-manifest.js +0 -1
- package/.next/server/middleware-manifest.json +0 -6
- package/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/.next/server/pages/404.js.nft.json +0 -1
- package/.next/server/pages/500.js.nft.json +0 -1
- package/.next/server/pages/[...slug].js +0 -633
- package/.next/server/pages/[...slug].js.nft.json +0 -1
- package/.next/server/pages/[slug]/p.js +0 -2491
- package/.next/server/pages/[slug]/p.js.nft.json +0 -1
- package/.next/server/pages/_app.js +0 -2479
- package/.next/server/pages/_app.js.nft.json +0 -1
- package/.next/server/pages/_document.js +0 -304
- package/.next/server/pages/_document.js.nft.json +0 -1
- package/.next/server/pages/_error.js +0 -164
- package/.next/server/pages/_error.js.nft.json +0 -1
- package/.next/server/pages/account.js.nft.json +0 -1
- package/.next/server/pages/api/graphql.js +0 -259
- package/.next/server/pages/api/graphql.js.nft.json +0 -1
- package/.next/server/pages/api/preview.js +0 -118
- package/.next/server/pages/api/preview.js.nft.json +0 -1
- package/.next/server/pages/checkout.js.nft.json +0 -1
- package/.next/server/pages/en-US/404.html +0 -81
- package/.next/server/pages/en-US/500.html +0 -81
- package/.next/server/pages/en-US/account.html +0 -81
- package/.next/server/pages/en-US/checkout.html +0 -81
- package/.next/server/pages/en-US/login.html +0 -81
- package/.next/server/pages/en-US/s.html +0 -81
- package/.next/server/pages/en-US.html +0 -81
- package/.next/server/pages/en-US.json +0 -1
- package/.next/server/pages/index.js +0 -428
- package/.next/server/pages/index.js.nft.json +0 -1
- package/.next/server/pages/login.js.nft.json +0 -1
- package/.next/server/pages/s.js.nft.json +0 -1
- package/.next/server/pages-manifest.json +0 -16
- package/.next/server/webpack-api-runtime.js +0 -229
- package/.next/server/webpack-runtime.js +0 -229
- package/.next/static/NEdGK5jp2ohL_vvU4f2Bi/_buildManifest.js +0 -1
- package/.next/static/NEdGK5jp2ohL_vvU4f2Bi/_ssgManifest.js +0 -1
- package/.next/static/chunks/143.dd8a556e6957baa1.js +0 -1
- package/.next/static/chunks/291.78e3aea4a7f45595.js +0 -1
- package/.next/static/chunks/351-a4e28d64f48c5269.js +0 -1
- package/.next/static/chunks/608.59e69b83f35d9c44.js +0 -1
- package/.next/static/chunks/650.807852d1c36bfe44.js +0 -1
- package/.next/static/chunks/651.7142f31ce1e052b3.js +0 -1
- package/.next/static/chunks/686.41582b9e75eaba89.js +0 -1
- package/.next/static/chunks/741.52f7fb873418346f.js +0 -1
- package/.next/static/chunks/781-7df372b5b56e3f96.js +0 -1
- package/.next/static/chunks/843.fab5a00e170b4f11.js +0 -1
- package/.next/static/chunks/855-05313b1877eceff8.js +0 -1
- package/.next/static/chunks/897-97b54479ad1b57d9.js +0 -1
- package/.next/static/chunks/98.97381d2021f86cd9.js +0 -1
- package/.next/static/chunks/framework-dfd14d7ce6600b03.js +0 -1
- package/.next/static/chunks/main-9746772201fe3ac1.js +0 -1
- package/.next/static/chunks/pages/404-ba608a2a9f0c420a.js +0 -1
- package/.next/static/chunks/pages/500-910883c20541d9ce.js +0 -1
- package/.next/static/chunks/pages/[...slug]-a947020e62f4ac94.js +0 -1
- package/.next/static/chunks/pages/[slug]/p-0a0c4a0e23758fd1.js +0 -1
- package/.next/static/chunks/pages/_app-256a3d53cde1dece.js +0 -1
- package/.next/static/chunks/pages/_error-a7a0c1d9bfbb4f38.js +0 -1
- package/.next/static/chunks/pages/account-f19102933e6fd84c.js +0 -1
- package/.next/static/chunks/pages/checkout-f8cb7cb22225ef9d.js +0 -1
- package/.next/static/chunks/pages/index-d7b3fd29a591657a.js +0 -1
- package/.next/static/chunks/pages/login-0b9ea80d9fa0f91b.js +0 -1
- package/.next/static/chunks/pages/s-56181f57d448f67c.js +0 -1
- package/.next/static/chunks/polyfills-c67a75d1b6f99dc8.js +0 -1
- package/.next/static/chunks/webpack-432485347f98ee3c.js +0 -1
- package/.next/static/css/430b8cafbf7c23c1.css +0 -1
- package/.next/static/css/43d61b402f41569b.css +0 -1
- package/.next/static/css/4ac2b0d468ca74dc.css +0 -1
- package/.next/static/css/6507cb48401e73a4.css +0 -1
- package/.next/static/css/9dd1d1084d254c66.css +0 -1
- package/.next/static/css/a3aac8b785a9dfe2.css +0 -1
- package/.next/static/css/b2f16bd4b93e0aca.css +0 -1
- package/.next/static/css/bd743407c8049677.css +0 -1
- package/.next/static/media/brandless-neutral.76ddf63a.png +0 -0
- package/.next/trace +0 -64
- package/public/~partytown/debug/partytown-atomics.js +0 -556
- package/public/~partytown/debug/partytown-media.js +0 -374
- package/public/~partytown/debug/partytown-sandbox-sw.js +0 -543
- package/public/~partytown/debug/partytown-sw.js +0 -59
- package/public/~partytown/debug/partytown-ww-atomics.js +0 -1789
- package/public/~partytown/debug/partytown-ww-sw.js +0 -1781
- package/public/~partytown/debug/partytown.js +0 -72
- package/public/~partytown/partytown-atomics.js +0 -2
- package/public/~partytown/partytown-media.js +0 -2
- package/public/~partytown/partytown-sw.js +0 -2
- package/public/~partytown/partytown.js +0 -2
- package/src/components/product/OutOfStock/OutOfStock.stories.mdx +0 -127
- package/src/components/product/OutOfStock/out-of-stock.module.scss +0 -55
- package/src/components/search/Filter/Facets.stories.mdx +0 -282
- package/src/components/search/Filter/Facets.tsx +0 -147
- package/src/components/search/Filter/Filter.stories.mdx +0 -208
- package/src/components/search/Filter/FilterSlider.stories.mdx +0 -216
- package/src/components/search/Filter/facets.module.scss +0 -117
- package/src/components/search/Filter/filter-slider.module.scss +0 -53
package/.turbo/turbo-build.log
CHANGED
|
@@ -17,6 +17,7 @@ info - Generating static pages (0/13)
|
|
|
17
17
|
info - Generating static pages (3/13)
|
|
18
18
|
info - Generating static pages (6/13)
|
|
19
19
|
info - Generating static pages (9/13)
|
|
20
|
+
warn - CallToAction not found. Add a new component for this section or remove it from the CMS
|
|
20
21
|
info - Generating static pages (13/13)
|
|
21
22
|
info - Finalizing page optimization...
|
|
22
23
|
|
|
@@ -24,10 +25,10 @@ Route (pages) Size First Load JS
|
|
|
24
25
|
┌ ● / 2.83 kB 127 kB
|
|
25
26
|
├ └ css/43d61b402f41569b.css 1.84 kB
|
|
26
27
|
├ /_app 0 B 105 kB
|
|
27
|
-
├ ● /[...slug] 9.
|
|
28
|
-
├ └ css/
|
|
29
|
-
├ ● /[slug]/p 11.
|
|
30
|
-
├ └ css/
|
|
28
|
+
├ ● /[...slug] 9.98 kB 131 kB
|
|
29
|
+
├ └ css/8ea129ea90e49e98.css 1.83 kB
|
|
30
|
+
├ ● /[slug]/p 11.7 kB 135 kB
|
|
31
|
+
├ └ css/59446068ab594e58.css 3 kB
|
|
31
32
|
├ ○ /404 431 B 110 kB
|
|
32
33
|
├ ○ /500 439 B 110 kB
|
|
33
34
|
├ ○ /account 369 B 110 kB
|
|
@@ -35,14 +36,14 @@ Route (pages) Size First Load JS
|
|
|
35
36
|
├ λ /api/preview 0 B 105 kB
|
|
36
37
|
├ ○ /checkout 371 B 110 kB
|
|
37
38
|
├ ○ /login 368 B 110 kB
|
|
38
|
-
└ ○ /s
|
|
39
|
-
└ css/
|
|
40
|
-
+ First Load JS shared by all
|
|
39
|
+
└ ○ /s 896 B 122 kB
|
|
40
|
+
└ css/db63ea05e98cb7e8.css 1.63 kB
|
|
41
|
+
+ First Load JS shared by all 126 kB
|
|
41
42
|
├ chunks/framework-dfd14d7ce6600b03.js 45.3 kB
|
|
42
43
|
├ chunks/main-9746772201fe3ac1.js 23.9 kB
|
|
43
|
-
├ chunks/pages/_app-
|
|
44
|
-
├ chunks/webpack-
|
|
45
|
-
└ css/
|
|
44
|
+
├ chunks/pages/_app-0bf8e95d55047056.js 33.2 kB
|
|
45
|
+
├ chunks/webpack-e8365cb80353190c.js 2.18 kB
|
|
46
|
+
└ css/e848206ea71282d6.css 21.8 kB
|
|
46
47
|
|
|
47
48
|
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
|
|
48
49
|
○ (Static) automatically rendered as static HTML (uses no initial props)
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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
|
+
## [2.0.90-alpha.0](https://github.com/vtex/faststore/compare/v2.0.89-alpha.0...v2.0.90-alpha.0) (2023-03-29)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- Adds `Filter` and `FilterSlider` Components. ([#1687](https://github.com/vtex/faststore/issues/1687)) ([a18e1af](https://github.com/vtex/faststore/commit/a18e1af9fe6037f19a558f2c49e52ba01e50e95a))
|
|
11
|
+
|
|
12
|
+
## [2.0.89-alpha.0](https://github.com/vtex/faststore/compare/v2.0.88-alpha.0...v2.0.89-alpha.0) (2023-03-29)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- Add `OutOfStock` components ([#1685](https://github.com/vtex/faststore/issues/1685)) ([25f4442](https://github.com/vtex/faststore/commit/25f444214e234f5f0f9287ef8bc403231b2eac2b))
|
|
17
|
+
|
|
6
18
|
## [2.0.88-alpha.0](https://github.com/vtex/faststore/compare/v2.0.87-alpha.0...v2.0.88-alpha.0) (2023-03-29)
|
|
7
19
|
|
|
8
20
|
### Features
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable cypress/no-unnecessary-waiting */
|
|
2
1
|
// eslint-disable-next-line spaced-comment
|
|
3
2
|
/// <reference types="cypress" />
|
|
4
3
|
/**
|
|
@@ -23,11 +22,11 @@ describe('Search page Filters and Sorting options', () => {
|
|
|
23
22
|
cy.getById('open-filter-button')
|
|
24
23
|
.click()
|
|
25
24
|
.get(
|
|
26
|
-
`[data-testid=mobile-
|
|
25
|
+
`[data-testid=mobile-fs-filter-accordion][data-type=StoreFacetBoolean]>[data-testid=mobile-fs-filter-accordion-button]`
|
|
27
26
|
)
|
|
28
27
|
.first()
|
|
29
28
|
.click()
|
|
30
|
-
.getById('mobile-
|
|
29
|
+
.getById('mobile-fs-filter-accordion-panel-checkbox')
|
|
31
30
|
.should('exist')
|
|
32
31
|
.first()
|
|
33
32
|
.click()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.90-alpha.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"browserslist": "supports es6-module and not dead",
|
|
6
6
|
"scripts": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"@envelop/parser-cache": "^2.2.0",
|
|
31
31
|
"@envelop/validation-cache": "^2.2.0",
|
|
32
32
|
"@faststore/api": "^2.0.3-alpha.0",
|
|
33
|
-
"@faststore/components": "^2.0.
|
|
33
|
+
"@faststore/components": "^2.0.90-alpha.0",
|
|
34
34
|
"@faststore/graphql-utils": "^2.0.3-alpha.0",
|
|
35
35
|
"@faststore/sdk": "^2.0.3-alpha.0",
|
|
36
|
-
"@faststore/ui": "^2.0.
|
|
36
|
+
"@faststore/ui": "^2.0.90-alpha.0",
|
|
37
37
|
"@types/react": "^18.0.14",
|
|
38
38
|
"@vtex/client-cms": "^0.2.12",
|
|
39
39
|
"autoprefixer": "^10.4.0",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"msw": {
|
|
109
109
|
"workerDirectory": "public"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "8382d02bffb1fcf8c517df11221b228ecb1a38bd"
|
|
112
112
|
}
|
|
@@ -1,133 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
OutOfStock as UIOutOfStock,
|
|
3
|
-
OutOfStockTitle as UIOutOfStockTitle,
|
|
4
|
-
OutOfStockMessage as UIOutOfStockMessage,
|
|
5
|
-
Button as UIButton,
|
|
6
|
-
InputField as UIInputField,
|
|
7
|
-
} from '@faststore/ui'
|
|
1
|
+
import { OutOfStock as UIOutOfStock, useUI } from '@faststore/ui'
|
|
8
2
|
import { useState } from 'react'
|
|
9
|
-
import type {
|
|
3
|
+
import type { FormEvent } from 'react'
|
|
10
4
|
|
|
11
|
-
import Icon from 'src/components/ui/Icon'
|
|
12
|
-
import styles from 'src/components/product/OutOfStock/out-of-stock.module.scss'
|
|
13
5
|
import { useSession } from 'src/sdk/session'
|
|
6
|
+
import Icon from 'src/components/ui/Icon'
|
|
14
7
|
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* The Out of Stock Section's title.
|
|
18
|
-
*/
|
|
19
|
-
title?: string
|
|
20
|
-
/**
|
|
21
|
-
* The button text.
|
|
22
|
-
*/
|
|
23
|
-
buttonText?: string
|
|
24
|
-
/**
|
|
25
|
-
* Message describing when the user will be notified.
|
|
26
|
-
*/
|
|
27
|
-
notificationMsg?: string
|
|
28
|
-
/**
|
|
29
|
-
* Icon displayed inside the button.
|
|
30
|
-
* @default <Icon name="BellRinging" />
|
|
31
|
-
*/
|
|
32
|
-
buttonIcon?: ReactElement
|
|
33
|
-
/**
|
|
34
|
-
* Icon displayed inside the notification message.
|
|
35
|
-
* @default <Icon name="BellRinging" />
|
|
36
|
-
*/
|
|
37
|
-
notificationMsgIcon?: ReactElement
|
|
38
|
-
/**
|
|
39
|
-
* ID to find this component in testing tools (e.g.: cypress,
|
|
40
|
-
* testing-library, and jest).
|
|
41
|
-
*/
|
|
42
|
-
testId?: string
|
|
43
|
-
/**
|
|
44
|
-
* Event emitted when form is submitted.
|
|
45
|
-
*/
|
|
46
|
-
onSubmit: (value: string) => void
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function OutOfStock(props: OutOfStockProps) {
|
|
8
|
+
function OutOfStock() {
|
|
50
9
|
const { postalCode } = useSession()
|
|
51
10
|
|
|
52
|
-
const
|
|
53
|
-
const defaultIconName = 'BellRinging'
|
|
54
|
-
|
|
55
|
-
const [btnText, setBtnText] = useState(defaultButtonText)
|
|
56
|
-
const [buttonIconName, setButtonIconName] = useState(defaultIconName)
|
|
57
|
-
const [disabled, setDisabled] = useState(false)
|
|
58
|
-
const [email, setEmail] = useState('')
|
|
11
|
+
const [isLoading, setIsLoading] = useState(false)
|
|
59
12
|
const [error, setError] = useState('')
|
|
60
|
-
|
|
61
|
-
const {
|
|
62
|
-
title = postalCode ? 'Unavailable in Your Location' : 'Out of Stock',
|
|
63
|
-
notificationMsg = 'Notify me when available',
|
|
64
|
-
buttonText = btnText,
|
|
65
|
-
buttonIcon = <Icon name={buttonIconName} width={16} height={16} />,
|
|
66
|
-
notificationMsgIcon = (
|
|
67
|
-
<Icon name={defaultIconName} width={16} height={16} />
|
|
68
|
-
),
|
|
69
|
-
onSubmit,
|
|
70
|
-
} = props
|
|
71
|
-
|
|
72
|
-
const reset = () => {
|
|
73
|
-
setButtonIconName(defaultIconName)
|
|
74
|
-
setBtnText(defaultButtonText)
|
|
75
|
-
setDisabled(false)
|
|
76
|
-
|
|
77
|
-
setEmail('')
|
|
78
|
-
setError('')
|
|
79
|
-
}
|
|
13
|
+
const { pushToast } = useUI()
|
|
80
14
|
|
|
81
15
|
const handleSubmit = (event: FormEvent) => {
|
|
82
16
|
event.preventDefault()
|
|
17
|
+
setIsLoading(true)
|
|
83
18
|
|
|
84
|
-
|
|
85
|
-
setButtonIconName('Ellipsis')
|
|
19
|
+
// TODO: Missing integration
|
|
86
20
|
|
|
87
21
|
try {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
22
|
+
// Return to original state after 2s mockup
|
|
23
|
+
setTimeout(() => setIsLoading(false), 2000)
|
|
24
|
+
|
|
25
|
+
const formElement = event.currentTarget as HTMLFormElement
|
|
26
|
+
formElement.reset()
|
|
27
|
+
|
|
28
|
+
pushToast({
|
|
29
|
+
title: 'Subscribed successfully!',
|
|
30
|
+
message: "You'll be notified when this product is back to stock.",
|
|
31
|
+
status: 'INFO',
|
|
32
|
+
icon: <Icon name="CircleWavyCheck" width={30} height={30} />,
|
|
33
|
+
})
|
|
91
34
|
} catch (err) {
|
|
92
35
|
setError(err.message)
|
|
93
36
|
} finally {
|
|
94
|
-
// Return to original state after 2s
|
|
95
|
-
setTimeout(reset, 2000)
|
|
96
37
|
}
|
|
97
38
|
}
|
|
98
39
|
|
|
99
40
|
return (
|
|
100
41
|
<UIOutOfStock
|
|
101
|
-
|
|
102
|
-
|
|
42
|
+
title={postalCode ? 'Unavailable in Your Location' : 'Out of Stock'}
|
|
43
|
+
inputLabel="Email"
|
|
44
|
+
subtitle="Notify me when available"
|
|
103
45
|
onSubmit={handleSubmit}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{notificationMsgIcon} {notificationMsg}
|
|
108
|
-
</UIOutOfStockMessage>
|
|
109
|
-
<UIInputField
|
|
110
|
-
id="out-of-stock-email"
|
|
111
|
-
value={email}
|
|
112
|
-
label="Email"
|
|
113
|
-
aria-label="Email"
|
|
114
|
-
error={error}
|
|
115
|
-
onChange={(e) => {
|
|
116
|
-
setError('')
|
|
117
|
-
setEmail(e.target.value)
|
|
118
|
-
}}
|
|
119
|
-
/>
|
|
120
|
-
<UIButton
|
|
121
|
-
data-fs-out-of-stock-button
|
|
122
|
-
type="submit"
|
|
123
|
-
disabled={disabled}
|
|
124
|
-
variant="primary"
|
|
125
|
-
icon={buttonIcon}
|
|
126
|
-
iconPosition="left"
|
|
127
|
-
>
|
|
128
|
-
{buttonText}
|
|
129
|
-
</UIButton>
|
|
130
|
-
</UIOutOfStock>
|
|
46
|
+
disabled={isLoading}
|
|
47
|
+
errorMessage={error}
|
|
48
|
+
/>
|
|
131
49
|
)
|
|
132
50
|
}
|
|
133
51
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { gql } from '@faststore/graphql-utils'
|
|
2
|
-
import { setFacet, toggleFacet, useSearch } from '@faststore/sdk'
|
|
3
2
|
|
|
4
|
-
import type { Filter_FacetsFragment } from '@generated/graphql'
|
|
5
3
|
import { useUI } from '@faststore/ui'
|
|
6
|
-
|
|
7
|
-
import
|
|
4
|
+
import type { Filter_FacetsFragment } from '@generated/graphql'
|
|
5
|
+
import FilterDesktop from './FilterDesktop'
|
|
8
6
|
import FilterSlider from './FilterSlider'
|
|
9
7
|
import { useFilter } from './useFilter'
|
|
10
8
|
|
|
@@ -20,37 +18,19 @@ interface Props {
|
|
|
20
18
|
testId?: string
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
function Filter({ facets: allFacets, testId = '
|
|
21
|
+
function Filter({ facets: allFacets, testId = 'fs-filter' }: Props) {
|
|
24
22
|
const filter = useFilter(allFacets)
|
|
25
|
-
const { resetInfiniteScroll, state, setState } = useSearch()
|
|
26
23
|
const { filter: displayFilter } = useUI()
|
|
27
|
-
const { facets, expanded, dispatch } = filter
|
|
28
24
|
|
|
29
25
|
return (
|
|
30
26
|
<>
|
|
31
27
|
<div className="hidden-mobile">
|
|
32
|
-
<
|
|
33
|
-
facets={facets}
|
|
34
|
-
testId={`desktop-${testId}`}
|
|
35
|
-
indicesExpanded={expanded}
|
|
36
|
-
onFacetChange={(facet, type) => {
|
|
37
|
-
setState({
|
|
38
|
-
...state,
|
|
39
|
-
selectedFacets:
|
|
40
|
-
type === 'BOOLEAN'
|
|
41
|
-
? toggleFacet(state.selectedFacets, facet)
|
|
42
|
-
: setFacet(state.selectedFacets, facet, true),
|
|
43
|
-
page: 0,
|
|
44
|
-
})
|
|
45
|
-
resetInfiniteScroll(0)
|
|
46
|
-
}}
|
|
47
|
-
onAccordionChange={(index) =>
|
|
48
|
-
dispatch({ type: 'toggleExpanded', payload: index })
|
|
49
|
-
}
|
|
50
|
-
/>
|
|
28
|
+
<FilterDesktop {...filter} testId={testId} title="Filters" />
|
|
51
29
|
</div>
|
|
52
30
|
|
|
53
|
-
{displayFilter &&
|
|
31
|
+
{displayFilter && (
|
|
32
|
+
<FilterSlider {...filter} testId={testId} title="Filters" />
|
|
33
|
+
)}
|
|
54
34
|
</>
|
|
55
35
|
)
|
|
56
36
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { setFacet, toggleFacet, useSearch } from '@faststore/sdk'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Filter as UIFilter,
|
|
5
|
+
FilterFacetBoolean as UIFilterFacetBoolean,
|
|
6
|
+
FilterFacetBooleanItem as UIFilterFacetBooleanItem,
|
|
7
|
+
FilterFacetRange as UIFilterFacetRange,
|
|
8
|
+
FilterFacets as UIFilterFacets,
|
|
9
|
+
} from '@faststore/ui'
|
|
10
|
+
import type { Filter_FacetsFragment } from '@generated/graphql'
|
|
11
|
+
import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
|
|
12
|
+
import { useFilter } from './useFilter'
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
/**
|
|
16
|
+
* The array that represents the details of every facet.
|
|
17
|
+
*/
|
|
18
|
+
facets: Filter_FacetsFragment[]
|
|
19
|
+
/**
|
|
20
|
+
* ID to find this component in testing tools (e.g.: cypress,
|
|
21
|
+
* testing-library, and jest).
|
|
22
|
+
*/
|
|
23
|
+
testId?: string
|
|
24
|
+
/**
|
|
25
|
+
* Title for the `FilterDesktop` component.
|
|
26
|
+
*/
|
|
27
|
+
title?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function FilterDesktop({
|
|
31
|
+
facets,
|
|
32
|
+
testId,
|
|
33
|
+
dispatch,
|
|
34
|
+
expanded,
|
|
35
|
+
title,
|
|
36
|
+
}: Props & ReturnType<typeof useFilter>) {
|
|
37
|
+
const { resetInfiniteScroll, state, setState } = useSearch()
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<UIFilter
|
|
41
|
+
testId={`desktop-${testId}`}
|
|
42
|
+
title={title}
|
|
43
|
+
indicesExpanded={expanded}
|
|
44
|
+
onAccordionChange={(idx) =>
|
|
45
|
+
dispatch({ type: 'toggleExpanded', payload: idx })
|
|
46
|
+
}
|
|
47
|
+
>
|
|
48
|
+
{facets.map((facet, index) => {
|
|
49
|
+
const { __typename: type, label } = facet
|
|
50
|
+
const isExpanded = expanded.has(index)
|
|
51
|
+
return (
|
|
52
|
+
<UIFilterFacets
|
|
53
|
+
key={`${testId}-${label}-${index}`}
|
|
54
|
+
testId={testId}
|
|
55
|
+
index={index}
|
|
56
|
+
type={type}
|
|
57
|
+
label={label}
|
|
58
|
+
>
|
|
59
|
+
{type === 'StoreFacetBoolean' && isExpanded && (
|
|
60
|
+
<UIFilterFacetBoolean>
|
|
61
|
+
{facet.values.map((item) => (
|
|
62
|
+
<UIFilterFacetBooleanItem
|
|
63
|
+
key={`${testId}-${facet.label}-${item.label}`}
|
|
64
|
+
id={`${testId}-${facet.label}-${item.label}`}
|
|
65
|
+
testId={testId}
|
|
66
|
+
onFacetChange={(facet) => {
|
|
67
|
+
setState({
|
|
68
|
+
...state,
|
|
69
|
+
selectedFacets: toggleFacet(
|
|
70
|
+
state.selectedFacets,
|
|
71
|
+
facet
|
|
72
|
+
),
|
|
73
|
+
page: 0,
|
|
74
|
+
})
|
|
75
|
+
resetInfiniteScroll(0)
|
|
76
|
+
}}
|
|
77
|
+
selected={item.selected}
|
|
78
|
+
value={item.value}
|
|
79
|
+
quantity={item.quantity}
|
|
80
|
+
facetKey={facet.key}
|
|
81
|
+
label={item.label}
|
|
82
|
+
/>
|
|
83
|
+
))}
|
|
84
|
+
</UIFilterFacetBoolean>
|
|
85
|
+
)}
|
|
86
|
+
{type === 'StoreFacetRange' && isExpanded && (
|
|
87
|
+
<UIFilterFacetRange
|
|
88
|
+
facetKey={facet.key}
|
|
89
|
+
min={facet.min}
|
|
90
|
+
max={facet.max}
|
|
91
|
+
formatter={useFormattedPrice}
|
|
92
|
+
onFacetChange={(facet) => {
|
|
93
|
+
setState({
|
|
94
|
+
...state,
|
|
95
|
+
selectedFacets: setFacet(state.selectedFacets, facet, true),
|
|
96
|
+
page: 0,
|
|
97
|
+
})
|
|
98
|
+
resetInfiniteScroll(0)
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</UIFilterFacets>
|
|
103
|
+
)
|
|
104
|
+
})}
|
|
105
|
+
</UIFilter>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default FilterDesktop
|
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
import { useSearch } from '@faststore/sdk'
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Filter as UIFilter,
|
|
4
|
+
FilterFacetBoolean as UIFilterFacetBoolean,
|
|
5
|
+
FilterFacetBooleanItem as UIFilterFacetBooleanItem,
|
|
6
|
+
FilterFacetRange as UIFilterFacetRange,
|
|
7
|
+
FilterFacets as UIFilterFacets,
|
|
8
|
+
FilterSlider as UIFilterSlider,
|
|
6
9
|
} from '@faststore/ui'
|
|
10
|
+
import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
|
|
7
11
|
|
|
8
12
|
import type { Filter_FacetsFragment } from '@generated/graphql'
|
|
9
|
-
import { useUI } from '@faststore/ui'
|
|
10
|
-
import { useFadeEffect } from '@faststore/ui'
|
|
11
13
|
|
|
12
|
-
import Facets from './Facets'
|
|
13
|
-
import styles from './filter-slider.module.scss'
|
|
14
14
|
import type { useFilter } from './useFilter'
|
|
15
15
|
|
|
16
16
|
interface Props {
|
|
17
|
+
/**
|
|
18
|
+
* ID to find this component in testing tools (e.g.: cypress,
|
|
19
|
+
* testing-library, and jest).
|
|
20
|
+
*/
|
|
21
|
+
testId?: string
|
|
17
22
|
/**
|
|
18
23
|
* The array that represents the details of every facet.
|
|
19
24
|
*/
|
|
20
25
|
facets: Filter_FacetsFragment[]
|
|
21
26
|
/**
|
|
22
|
-
*
|
|
23
|
-
* testing-library, and jest).
|
|
27
|
+
* Title for the `Filter` component.
|
|
24
28
|
*/
|
|
25
|
-
|
|
29
|
+
title?: string
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
function FilterSlider({
|
|
@@ -31,76 +35,96 @@ function FilterSlider({
|
|
|
31
35
|
dispatch,
|
|
32
36
|
expanded,
|
|
33
37
|
selected,
|
|
38
|
+
title,
|
|
34
39
|
}: Props & ReturnType<typeof useFilter>) {
|
|
35
|
-
const { closeFilter } = useUI()
|
|
36
|
-
const { fade, fadeOut } = useFadeEffect()
|
|
37
|
-
|
|
38
40
|
const { resetInfiniteScroll, setState, state } = useSearch()
|
|
39
41
|
|
|
40
42
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
fade={fade}
|
|
44
|
-
onDismiss={fadeOut}
|
|
43
|
+
<UIFilterSlider
|
|
44
|
+
title={title}
|
|
45
45
|
size="partial"
|
|
46
46
|
direction="rightSide"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
fadeOut()
|
|
59
|
-
}}
|
|
60
|
-
>
|
|
61
|
-
<h2 className="text__lead">Filters</h2>
|
|
62
|
-
</UISlideOverHeader>
|
|
63
|
-
<Facets
|
|
64
|
-
facets={facets}
|
|
65
|
-
testId={`mobile-${testId}`}
|
|
66
|
-
indicesExpanded={expanded}
|
|
67
|
-
onFacetChange={(facet, type) =>
|
|
68
|
-
type === 'BOOLEAN'
|
|
69
|
-
? dispatch({ type: 'toggleFacet', payload: facet })
|
|
70
|
-
: dispatch({ type: 'setFacet', payload: { facet, unique: true } })
|
|
71
|
-
}
|
|
72
|
-
onAccordionChange={(index) =>
|
|
73
|
-
dispatch({ type: 'toggleExpanded', payload: index })
|
|
74
|
-
}
|
|
75
|
-
/>
|
|
76
|
-
</div>
|
|
77
|
-
<footer data-fs-filter-slider-footer>
|
|
78
|
-
<UIButton
|
|
79
|
-
data-fs-filter-slider-footer-button-clear
|
|
80
|
-
variant="secondary"
|
|
81
|
-
onClick={() => dispatch({ type: 'selectFacets', payload: [] })}
|
|
82
|
-
>
|
|
83
|
-
Clear All
|
|
84
|
-
</UIButton>
|
|
85
|
-
<UIButton
|
|
86
|
-
data-fs-filter-slider-footer-button-apply
|
|
87
|
-
variant="primary"
|
|
88
|
-
data-testid="filter-slider-button-apply"
|
|
89
|
-
onClick={() => {
|
|
90
|
-
resetInfiniteScroll(0)
|
|
47
|
+
clearBtnProps={{
|
|
48
|
+
variant: 'secondary',
|
|
49
|
+
onClick: () => dispatch({ type: 'selectFacets', payload: [] }),
|
|
50
|
+
children: 'Clear All',
|
|
51
|
+
}}
|
|
52
|
+
applyBtnProps={{
|
|
53
|
+
variant: 'primary',
|
|
54
|
+
onClick: () => {
|
|
55
|
+
resetInfiniteScroll(0)
|
|
91
56
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
57
|
+
setState({
|
|
58
|
+
...state,
|
|
59
|
+
selectedFacets: selected,
|
|
60
|
+
page: 0,
|
|
61
|
+
})
|
|
62
|
+
},
|
|
63
|
+
children: 'Apply',
|
|
64
|
+
}}
|
|
65
|
+
onClose={() => {
|
|
66
|
+
dispatch({
|
|
67
|
+
type: 'selectFacets',
|
|
68
|
+
payload: state.selectedFacets,
|
|
69
|
+
})
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
<UIFilter
|
|
73
|
+
testId={`mobile-${testId}`}
|
|
74
|
+
indicesExpanded={expanded}
|
|
75
|
+
onAccordionChange={(index) =>
|
|
76
|
+
dispatch({ type: 'toggleExpanded', payload: index })
|
|
77
|
+
}
|
|
78
|
+
>
|
|
79
|
+
{facets.map((facet, index) => {
|
|
80
|
+
const { __typename: type, label } = facet
|
|
81
|
+
const isExpanded = expanded.has(index)
|
|
82
|
+
return (
|
|
83
|
+
<UIFilterFacets
|
|
84
|
+
key={`${testId}-${label}-${index}`}
|
|
85
|
+
testId={testId}
|
|
86
|
+
index={index}
|
|
87
|
+
type={type}
|
|
88
|
+
label={label}
|
|
89
|
+
>
|
|
90
|
+
{type === 'StoreFacetBoolean' && isExpanded && (
|
|
91
|
+
<UIFilterFacetBoolean>
|
|
92
|
+
{facet.values.map((item) => (
|
|
93
|
+
<UIFilterFacetBooleanItem
|
|
94
|
+
key={`${testId}-${facet.label}-${item.label}`}
|
|
95
|
+
id={`${testId}-${facet.label}-${item.label}`}
|
|
96
|
+
testId={testId}
|
|
97
|
+
onFacetChange={(facet) =>
|
|
98
|
+
dispatch({ type: 'toggleFacet', payload: facet })
|
|
99
|
+
}
|
|
100
|
+
selected={item.selected}
|
|
101
|
+
value={item.value}
|
|
102
|
+
quantity={item.quantity}
|
|
103
|
+
facetKey={facet.key}
|
|
104
|
+
label={item.label}
|
|
105
|
+
/>
|
|
106
|
+
))}
|
|
107
|
+
</UIFilterFacetBoolean>
|
|
108
|
+
)}
|
|
109
|
+
{type === 'StoreFacetRange' && isExpanded && (
|
|
110
|
+
<UIFilterFacetRange
|
|
111
|
+
facetKey={facet.key}
|
|
112
|
+
min={facet.min}
|
|
113
|
+
max={facet.max}
|
|
114
|
+
formatter={useFormattedPrice}
|
|
115
|
+
onFacetChange={(facet) =>
|
|
116
|
+
dispatch({
|
|
117
|
+
type: 'setFacet',
|
|
118
|
+
payload: { facet, unique: true },
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
/>
|
|
122
|
+
)}
|
|
123
|
+
</UIFilterFacets>
|
|
124
|
+
)
|
|
125
|
+
})}
|
|
126
|
+
</UIFilter>
|
|
127
|
+
</UIFilterSlider>
|
|
104
128
|
)
|
|
105
129
|
}
|
|
106
130
|
|