@faststore/components 3.65.0 → 3.68.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/dist/cjs/hooks/UIProvider.d.ts +15 -0
- package/dist/cjs/hooks/UIProvider.d.ts.map +1 -1
- package/dist/cjs/hooks/UIProvider.js +34 -1
- package/dist/cjs/hooks/UIProvider.js.map +1 -1
- package/dist/cjs/hooks/index.d.ts +3 -3
- package/dist/cjs/hooks/index.d.ts.map +1 -1
- package/dist/cjs/hooks/index.js +4 -3
- package/dist/cjs/hooks/index.js.map +1 -1
- package/dist/cjs/molecules/Accordion/Accordion.d.ts.map +1 -1
- package/dist/cjs/molecules/Accordion/Accordion.js +5 -1
- package/dist/cjs/molecules/Accordion/Accordion.js.map +1 -1
- package/dist/cjs/molecules/Modal/Modal.d.ts.map +1 -1
- package/dist/cjs/molecules/Modal/Modal.js +10 -15
- package/dist/cjs/molecules/Modal/Modal.js.map +1 -1
- package/dist/cjs/molecules/RadioField/RadioField.d.ts +5 -4
- package/dist/cjs/molecules/RadioField/RadioField.d.ts.map +1 -1
- package/dist/cjs/molecules/RadioField/RadioField.js +1 -1
- package/dist/cjs/molecules/RadioField/RadioField.js.map +1 -1
- package/dist/cjs/molecules/RegionBar/RegionBar.d.ts +30 -3
- package/dist/cjs/molecules/RegionBar/RegionBar.d.ts.map +1 -1
- package/dist/cjs/molecules/RegionBar/RegionBar.js +9 -8
- package/dist/cjs/molecules/RegionBar/RegionBar.js.map +1 -1
- package/dist/cjs/organisms/Filter/FilterFacetBooleanItem.d.ts +8 -3
- package/dist/cjs/organisms/Filter/FilterFacetBooleanItem.d.ts.map +1 -1
- package/dist/cjs/organisms/Filter/FilterFacetBooleanItem.js +3 -3
- package/dist/cjs/organisms/Filter/FilterFacetBooleanItem.js.map +1 -1
- package/dist/cjs/organisms/Filter/FilterFacets.d.ts +5 -1
- package/dist/cjs/organisms/Filter/FilterFacets.d.ts.map +1 -1
- package/dist/cjs/organisms/Filter/FilterFacets.js +4 -2
- package/dist/cjs/organisms/Filter/FilterFacets.js.map +1 -1
- package/dist/cjs/organisms/Filter/FilterSlider.d.ts +15 -1
- package/dist/cjs/organisms/Filter/FilterSlider.d.ts.map +1 -1
- package/dist/cjs/organisms/Filter/FilterSlider.js +15 -7
- package/dist/cjs/organisms/Filter/FilterSlider.js.map +1 -1
- package/dist/esm/hooks/UIProvider.d.ts +15 -0
- package/dist/esm/hooks/UIProvider.d.ts.map +1 -1
- package/dist/esm/hooks/UIProvider.js +33 -0
- package/dist/esm/hooks/UIProvider.js.map +1 -1
- package/dist/esm/hooks/index.d.ts +3 -3
- package/dist/esm/hooks/index.d.ts.map +1 -1
- package/dist/esm/hooks/index.js +2 -2
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/molecules/Accordion/Accordion.d.ts.map +1 -1
- package/dist/esm/molecules/Accordion/Accordion.js +5 -1
- package/dist/esm/molecules/Accordion/Accordion.js.map +1 -1
- package/dist/esm/molecules/Modal/Modal.d.ts.map +1 -1
- package/dist/esm/molecules/Modal/Modal.js +10 -15
- package/dist/esm/molecules/Modal/Modal.js.map +1 -1
- package/dist/esm/molecules/RadioField/RadioField.d.ts +5 -4
- package/dist/esm/molecules/RadioField/RadioField.d.ts.map +1 -1
- package/dist/esm/molecules/RadioField/RadioField.js +1 -1
- package/dist/esm/molecules/RadioField/RadioField.js.map +1 -1
- package/dist/esm/molecules/RegionBar/RegionBar.d.ts +30 -3
- package/dist/esm/molecules/RegionBar/RegionBar.d.ts.map +1 -1
- package/dist/esm/molecules/RegionBar/RegionBar.js +9 -8
- package/dist/esm/molecules/RegionBar/RegionBar.js.map +1 -1
- package/dist/esm/organisms/Filter/FilterFacetBooleanItem.d.ts +8 -3
- package/dist/esm/organisms/Filter/FilterFacetBooleanItem.d.ts.map +1 -1
- package/dist/esm/organisms/Filter/FilterFacetBooleanItem.js +4 -4
- package/dist/esm/organisms/Filter/FilterFacetBooleanItem.js.map +1 -1
- package/dist/esm/organisms/Filter/FilterFacets.d.ts +5 -1
- package/dist/esm/organisms/Filter/FilterFacets.d.ts.map +1 -1
- package/dist/esm/organisms/Filter/FilterFacets.js +4 -2
- package/dist/esm/organisms/Filter/FilterFacets.js.map +1 -1
- package/dist/esm/organisms/Filter/FilterSlider.d.ts +15 -1
- package/dist/esm/organisms/Filter/FilterSlider.d.ts.map +1 -1
- package/dist/esm/organisms/Filter/FilterSlider.js +15 -7
- package/dist/esm/organisms/Filter/FilterSlider.js.map +1 -1
- package/package.json +2 -2
- package/src/hooks/UIProvider.tsx +57 -0
- package/src/hooks/index.ts +10 -5
- package/src/molecules/Accordion/Accordion.tsx +5 -1
- package/src/molecules/Modal/Modal.tsx +9 -7
- package/src/molecules/RadioField/RadioField.tsx +13 -5
- package/src/molecules/RegionBar/RegionBar.tsx +71 -16
- package/src/organisms/Filter/FilterFacetBooleanItem.tsx +41 -19
- package/src/organisms/Filter/FilterFacets.tsx +11 -1
- package/src/organisms/Filter/FilterSlider.tsx +50 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterSlider.d.ts","sourceRoot":"","sources":["../../../../src/organisms/Filter/FilterSlider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAC9D,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAKlB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE1E,MAAM,WAAW,iBAAkB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACvE;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,SAAS,EAAE,kBAAkB,CAAA;IAC7B;;OAEG;IACH,IAAI,EAAE,kBAAkB,CAAA;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IACpC;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IACpC;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"FilterSlider.d.ts","sourceRoot":"","sources":["../../../../src/organisms/Filter/FilterSlider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAC9D,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,YAAY,EAKlB,MAAM,QAAQ,CAAA;AAEf,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE1E,MAAM,WAAW,iBAAkB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACvE;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,SAAS,EAAE,kBAAkB,CAAA;IAC7B;;OAEG;IACH,IAAI,EAAE,kBAAkB,CAAA;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IACpC;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IACpC;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,iBAAS,YAAY,CAAC,EACpB,MAA2B,EAC3B,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,aAAa,EACb,aAAa,EACb,YAAY,EACZ,OAAO,EACP,SAAS,EACT,MAAa,EACb,GAAG,UAAU,EACd,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,qBA2DtC;AAED,eAAe,YAAY,CAAA"}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Button, SlideOver, SlideOverHeader, useFadeEffect, useUI, } from '../../';
|
|
3
|
-
function FilterSlider({ title, size, direction, children, applyBtnProps, clearBtnProps, overlayProps, onClose, ...otherProps }) {
|
|
3
|
+
function FilterSlider({ testId = 'fs-filter-slider', title, size, direction, children, applyBtnProps, clearBtnProps, overlayProps, onClose, onDismiss, footer = true, ...otherProps }) {
|
|
4
4
|
const { fade, fadeOut } = useFadeEffect();
|
|
5
|
-
const { closeFilter } = useUI();
|
|
6
|
-
return (React.createElement(SlideOver, { "data-fs-filter-slider": true, isOpen: true, fade: fade, onDismiss:
|
|
5
|
+
const { closeFilter, closeRegionSlider } = useUI();
|
|
6
|
+
return (React.createElement(SlideOver, { "data-fs-filter-slider": true, isOpen: true, fade: fade, onDismiss: () => {
|
|
7
|
+
fadeOut();
|
|
8
|
+
onDismiss?.();
|
|
9
|
+
}, size: size, direction: direction, onTransitionEnd: () => {
|
|
10
|
+
if (fade === 'out') {
|
|
11
|
+
closeFilter();
|
|
12
|
+
closeRegionSlider();
|
|
13
|
+
}
|
|
14
|
+
}, testId: testId, overlayProps: overlayProps, ...otherProps },
|
|
7
15
|
React.createElement("div", { "data-fs-filter-slider-content": true },
|
|
8
16
|
React.createElement(SlideOverHeader, { onClose: () => {
|
|
9
17
|
onClose();
|
|
@@ -11,12 +19,12 @@ function FilterSlider({ title, size, direction, children, applyBtnProps, clearBt
|
|
|
11
19
|
} },
|
|
12
20
|
React.createElement("h2", { "data-fs-filter-slider-title": true }, title)),
|
|
13
21
|
children),
|
|
14
|
-
React.createElement("footer", { "data-fs-filter-slider-footer": true },
|
|
15
|
-
React.createElement(Button, { "data-fs-filter-slider-footer-button-clear": true, ...clearBtnProps }),
|
|
16
|
-
React.createElement(Button, { "data-fs-filter-slider-footer-button-apply": true,
|
|
22
|
+
footer && (React.createElement("footer", { "data-fs-filter-slider-footer": true },
|
|
23
|
+
clearBtnProps && (React.createElement(Button, { "data-fs-filter-slider-footer-button-clear": true, ...clearBtnProps })),
|
|
24
|
+
applyBtnProps && (React.createElement(Button, { "data-fs-filter-slider-footer-button-apply": true, testId: `${testId}-button-apply`, ...applyBtnProps, onClick: (e) => {
|
|
17
25
|
applyBtnProps?.onClick?.(e);
|
|
18
26
|
fadeOut();
|
|
19
|
-
} }))));
|
|
27
|
+
} }))))));
|
|
20
28
|
}
|
|
21
29
|
export default FilterSlider;
|
|
22
30
|
//# sourceMappingURL=FilterSlider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterSlider.js","sourceRoot":"","sources":["../../../../src/organisms/Filter/FilterSlider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EACL,MAAM,EAGN,SAAS,EACT,eAAe,EACf,aAAa,EACb,KAAK,GACN,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"FilterSlider.js","sourceRoot":"","sources":["../../../../src/organisms/Filter/FilterSlider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EACL,MAAM,EAGN,SAAS,EACT,eAAe,EACf,aAAa,EACb,KAAK,GACN,MAAM,QAAQ,CAAA;AAiDf,SAAS,YAAY,CAAC,EACpB,MAAM,GAAG,kBAAkB,EAC3B,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,aAAa,EACb,aAAa,EACb,YAAY,EACZ,OAAO,EACP,SAAS,EACT,MAAM,GAAG,IAAI,EACb,GAAG,UAAU,EACwB;IACrC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAA;IACzC,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,KAAK,EAAE,CAAA;IAElD,OAAO,CACL,oBAAC,SAAS,mCAER,MAAM,QACN,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,GAAG,EAAE;YACd,OAAO,EAAE,CAAA;YACT,SAAS,EAAE,EAAE,CAAA;QACf,CAAC,EACD,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,eAAe,EAAE,GAAG,EAAE;YACpB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,WAAW,EAAE,CAAA;gBACb,iBAAiB,EAAE,CAAA;YACrB,CAAC;QACH,CAAC,EACD,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,KACtB,UAAU;QAEd;YACE,oBAAC,eAAe,IACd,OAAO,EAAE,GAAG,EAAE;oBACZ,OAAO,EAAE,CAAA;oBACT,OAAO,EAAE,CAAA;gBACX,CAAC;gBAED,mEAAiC,KAAK,CAAM,CAC5B;YACjB,QAAQ,CACL;QACL,MAAM,IAAI,CACT;YACG,aAAa,IAAI,CAChB,oBAAC,MAAM,0DAED,aAAa,GACjB,CACH;YACA,aAAa,IAAI,CAChB,oBAAC,MAAM,uDAEL,MAAM,EAAE,GAAG,MAAM,eAAe,KAC5B,aAAa,EACjB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;oBACb,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;oBAC3B,OAAO,EAAE,CAAA;gBACX,CAAC,GACD,CACH,CACM,CACV,CACS,CACb,CAAA;AACH,CAAC;AAED,eAAe,YAAY,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/components",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.68.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"typings": "dist/esm/index.d.ts",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"volta": {
|
|
57
57
|
"extends": "../../package.json"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "ecc700eec58eaa22c6ae8c5f655c204ecf18f598"
|
|
60
60
|
}
|
package/src/hooks/UIProvider.tsx
CHANGED
|
@@ -13,6 +13,21 @@ export interface Popover {
|
|
|
13
13
|
triggerRef?: RefObject<HTMLElement>
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export const regionSliderTypes = {
|
|
17
|
+
setLocation: 'setLocation',
|
|
18
|
+
changeLocation: 'changeLocation',
|
|
19
|
+
changePickupPoint: 'changePickupPoint',
|
|
20
|
+
globalChangePickupPoint: 'globalChangePickupPoint',
|
|
21
|
+
} as const
|
|
22
|
+
|
|
23
|
+
type RegionSliderType =
|
|
24
|
+
(typeof regionSliderTypes)[keyof typeof regionSliderTypes]
|
|
25
|
+
|
|
26
|
+
export type RegionSlider = {
|
|
27
|
+
type: RegionSliderType | 'none'
|
|
28
|
+
isOpen: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
interface State {
|
|
17
32
|
/** Cart sidebar */
|
|
18
33
|
cart: boolean
|
|
@@ -26,6 +41,8 @@ interface State {
|
|
|
26
41
|
toasts: Toast[]
|
|
27
42
|
/** Region Popover */
|
|
28
43
|
popover: Popover
|
|
44
|
+
/** Region slider */
|
|
45
|
+
regionSlider: RegionSlider
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
type UIElement = 'navbar' | 'cart' | 'modal' | 'filter'
|
|
@@ -56,6 +73,13 @@ type Action =
|
|
|
56
73
|
| {
|
|
57
74
|
type: 'closePopover'
|
|
58
75
|
}
|
|
76
|
+
| {
|
|
77
|
+
type: 'openRegionSlider'
|
|
78
|
+
payload: RegionSliderType
|
|
79
|
+
}
|
|
80
|
+
| {
|
|
81
|
+
type: 'closeRegionSlider'
|
|
82
|
+
}
|
|
59
83
|
|
|
60
84
|
const reducer = (state: State, action: Action): State => {
|
|
61
85
|
const { type } = action
|
|
@@ -127,6 +151,30 @@ const reducer = (state: State, action: Action): State => {
|
|
|
127
151
|
}
|
|
128
152
|
}
|
|
129
153
|
|
|
154
|
+
case 'openRegionSlider': {
|
|
155
|
+
document.body.classList.add('no-scroll')
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
...state,
|
|
159
|
+
regionSlider: {
|
|
160
|
+
type: action.payload,
|
|
161
|
+
isOpen: true,
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
case 'closeRegionSlider':
|
|
166
|
+
if (!state.filter) {
|
|
167
|
+
document.body.classList.remove('no-scroll')
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
...state,
|
|
172
|
+
regionSlider: {
|
|
173
|
+
type: 'none',
|
|
174
|
+
isOpen: false,
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
|
|
130
178
|
default:
|
|
131
179
|
throw new Error(`Action ${type} not implemented`)
|
|
132
180
|
}
|
|
@@ -142,6 +190,10 @@ const initializer = (): State => ({
|
|
|
142
190
|
isOpen: false,
|
|
143
191
|
triggerRef: undefined,
|
|
144
192
|
},
|
|
193
|
+
regionSlider: {
|
|
194
|
+
type: 'none',
|
|
195
|
+
isOpen: false,
|
|
196
|
+
},
|
|
145
197
|
})
|
|
146
198
|
|
|
147
199
|
interface Context extends State {
|
|
@@ -157,6 +209,8 @@ interface Context extends State {
|
|
|
157
209
|
popToast: () => void
|
|
158
210
|
openPopover: (popover: Popover) => void
|
|
159
211
|
closePopover: () => void
|
|
212
|
+
openRegionSlider: (type: RegionSliderType) => void
|
|
213
|
+
closeRegionSlider: () => void
|
|
160
214
|
}
|
|
161
215
|
|
|
162
216
|
const UIContext = createContext<Context | undefined>(undefined)
|
|
@@ -180,6 +234,9 @@ function UIProvider({ children }: PropsWithChildren<unknown>) {
|
|
|
180
234
|
openPopover: (popover: Popover) =>
|
|
181
235
|
dispatch({ type: 'openPopover', payload: popover }),
|
|
182
236
|
closePopover: () => dispatch({ type: 'closePopover' }),
|
|
237
|
+
openRegionSlider: (type: RegionSliderType) =>
|
|
238
|
+
dispatch({ type: 'openRegionSlider', payload: type }),
|
|
239
|
+
closeRegionSlider: () => dispatch({ type: 'closeRegionSlider' }),
|
|
183
240
|
}),
|
|
184
241
|
[]
|
|
185
242
|
)
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
regionSliderTypes,
|
|
3
|
+
Toast as ToastProps,
|
|
4
|
+
default as UIProvider,
|
|
5
|
+
useUI,
|
|
6
|
+
} from './UIProvider'
|
|
2
7
|
export { useFadeEffect } from './useFadeEffect'
|
|
3
8
|
export { useOnClickOutside } from './useOnClickOutside'
|
|
9
|
+
export { useScrollDirection } from './useScrollDirection'
|
|
4
10
|
export { useSearch } from './useSearch'
|
|
5
11
|
export { useSKUMatrix } from './useSKUMatrix'
|
|
6
|
-
export { useScrollDirection } from './useScrollDirection'
|
|
7
12
|
export { useSlider } from './useSlider'
|
|
8
13
|
export type {
|
|
9
|
-
UseSliderArgs,
|
|
10
|
-
SliderState,
|
|
11
|
-
SliderDispatch,
|
|
12
14
|
SlideDirection,
|
|
15
|
+
SliderDispatch,
|
|
16
|
+
SliderState,
|
|
17
|
+
UseSliderArgs,
|
|
13
18
|
} from './useSlider'
|
|
14
19
|
export { useSlideVisibility } from './useSlideVisibility'
|
|
15
20
|
export { useTrapFocus } from './useTrapFocus'
|
|
@@ -37,7 +37,11 @@ const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(
|
|
|
37
37
|
) {
|
|
38
38
|
const childrenWithIndex = React.Children.map(
|
|
39
39
|
children as ReactElement,
|
|
40
|
-
(child, index) =>
|
|
40
|
+
(child, index) => {
|
|
41
|
+
if (!child) return
|
|
42
|
+
|
|
43
|
+
return cloneElement(child, { index: child.props.index ?? index })
|
|
44
|
+
}
|
|
41
45
|
)
|
|
42
46
|
|
|
43
47
|
const context = {
|
|
@@ -108,13 +108,15 @@ const Modal = ({
|
|
|
108
108
|
{...overlayProps}
|
|
109
109
|
>
|
|
110
110
|
<ModalContent
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
onTransitionEnd={(e) => {
|
|
112
|
+
// Checks if the event wast triggered by this modal or is a bubble event
|
|
113
|
+
if ((e.target as HTMLElement)?.dataset?.testid !== testId) return
|
|
114
|
+
// TODO:
|
|
115
|
+
// Using onTransitionEnd can lead to unexpected behavior. Since ModalContentPure uses the useTrapFocus hook,
|
|
116
|
+
// focus is automatically moved to the first focusable element inside the modal—typically the Close Button.
|
|
117
|
+
// This causes the onTransitionEnd event listener to attach to the Close Button instead of the ModalContent.
|
|
118
|
+
// As a result, we may end up listening to the transition of the button (e.g., its focus animation) rather than
|
|
119
|
+
// the intended transform transition of the modal content, which can introduce bugs during modal animations.
|
|
118
120
|
if (fade === 'out') {
|
|
119
121
|
closeModal()
|
|
120
122
|
} else if (fade === 'in' && onEntered) {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { HTMLAttributes } from 'react'
|
|
1
|
+
import type { HTMLAttributes, ReactNode, InputHTMLAttributes } from 'react'
|
|
2
2
|
import React, { forwardRef } from 'react'
|
|
3
3
|
|
|
4
4
|
import Label from '../../atoms/Label'
|
|
5
5
|
import Radio from '../../atoms/Radio'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type EnhancedRadioFieldProps = HTMLAttributes<HTMLDivElement> &
|
|
8
|
+
Pick<InputHTMLAttributes<HTMLInputElement>, 'checked'>
|
|
9
|
+
|
|
10
|
+
export interface RadioFieldProps extends EnhancedRadioFieldProps {
|
|
8
11
|
/**
|
|
9
12
|
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
10
13
|
*/
|
|
@@ -14,9 +17,9 @@ export interface RadioFieldProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
14
17
|
*/
|
|
15
18
|
id: string
|
|
16
19
|
/**
|
|
17
|
-
* The text displayed to identify the input radio.
|
|
20
|
+
* The text or component displayed to identify the input radio.
|
|
18
21
|
*/
|
|
19
|
-
label: string
|
|
22
|
+
label: string | ReactNode
|
|
20
23
|
/**
|
|
21
24
|
* The value to identify the input radio.
|
|
22
25
|
*/
|
|
@@ -34,7 +37,12 @@ const RadioField = forwardRef<HTMLDivElement, RadioFieldProps>(
|
|
|
34
37
|
) {
|
|
35
38
|
return (
|
|
36
39
|
<div ref={ref} data-fs-radio-field data-testid={testId}>
|
|
37
|
-
<Radio
|
|
40
|
+
<Radio
|
|
41
|
+
id={id}
|
|
42
|
+
value={typeof label === 'string' ? label : value}
|
|
43
|
+
name={name}
|
|
44
|
+
{...otherProps}
|
|
45
|
+
/>
|
|
38
46
|
<Label htmlFor={id}>{label}</Label>
|
|
39
47
|
</div>
|
|
40
48
|
)
|
|
@@ -15,11 +15,11 @@ export interface RegionBarProps
|
|
|
15
15
|
*/
|
|
16
16
|
postalCode?: string
|
|
17
17
|
/**
|
|
18
|
-
* Function called when button is clicked.
|
|
18
|
+
* Function called when location button is clicked.
|
|
19
19
|
*/
|
|
20
20
|
onButtonClick?: () => void
|
|
21
21
|
/**
|
|
22
|
-
* A React component that will be rendered as
|
|
22
|
+
* A React component that will be rendered as the location icon.
|
|
23
23
|
*/
|
|
24
24
|
icon?: ReactNode
|
|
25
25
|
/**
|
|
@@ -27,7 +27,8 @@ export interface RegionBarProps
|
|
|
27
27
|
*/
|
|
28
28
|
label: string
|
|
29
29
|
/**
|
|
30
|
-
* Specifies a label for the edit text.
|
|
30
|
+
* Specifies a label for the edit location text.
|
|
31
|
+
* @deprecated
|
|
31
32
|
*/
|
|
32
33
|
editLabel?: string
|
|
33
34
|
/**
|
|
@@ -39,18 +40,51 @@ export interface RegionBarProps
|
|
|
39
40
|
* @default true
|
|
40
41
|
*/
|
|
41
42
|
shouldDisplayPostalCode?: boolean
|
|
43
|
+
/**
|
|
44
|
+
* Properties of the global filter button.
|
|
45
|
+
*/
|
|
46
|
+
filterButton?: {
|
|
47
|
+
/**
|
|
48
|
+
* A React component that will be rendered as the filter icon.
|
|
49
|
+
*/
|
|
50
|
+
icon?: ReactNode
|
|
51
|
+
/**
|
|
52
|
+
* Specifies a label for the filter text.
|
|
53
|
+
*/
|
|
54
|
+
label?: string
|
|
55
|
+
/**
|
|
56
|
+
* The current selected filter name.
|
|
57
|
+
*/
|
|
58
|
+
selectedFilter?: string
|
|
59
|
+
/**
|
|
60
|
+
* Boolean to control whether the filter button should be visible or not.
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
shouldDisplayFilterButton?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* Function called when filter button is clicked.
|
|
66
|
+
*/
|
|
67
|
+
onClick?: () => void
|
|
68
|
+
}
|
|
42
69
|
}
|
|
43
70
|
|
|
44
71
|
const RegionBar = forwardRef<HTMLDivElement, RegionBarProps>(function RegionBar(
|
|
45
72
|
{
|
|
46
73
|
city,
|
|
47
74
|
postalCode,
|
|
48
|
-
icon,
|
|
49
|
-
label,
|
|
50
|
-
editLabel,
|
|
75
|
+
icon: locationIcon,
|
|
76
|
+
label: locationLabel,
|
|
77
|
+
editLabel: _ = undefined,
|
|
51
78
|
buttonIcon,
|
|
52
|
-
onButtonClick,
|
|
79
|
+
onButtonClick: onLocationButtonClick,
|
|
53
80
|
shouldDisplayPostalCode = true,
|
|
81
|
+
filterButton: {
|
|
82
|
+
icon: filterIcon,
|
|
83
|
+
label: filterLabel,
|
|
84
|
+
selectedFilter,
|
|
85
|
+
shouldDisplayFilterButton = false,
|
|
86
|
+
onClick: onFilterButtonClick,
|
|
87
|
+
} = {},
|
|
54
88
|
...otherProps
|
|
55
89
|
},
|
|
56
90
|
ref
|
|
@@ -59,23 +93,44 @@ const RegionBar = forwardRef<HTMLDivElement, RegionBarProps>(function RegionBar(
|
|
|
59
93
|
<div ref={ref} data-fs-region-bar {...otherProps}>
|
|
60
94
|
<Button
|
|
61
95
|
variant="tertiary"
|
|
62
|
-
iconPosition=
|
|
63
|
-
onClick={
|
|
64
|
-
icon={buttonIcon}
|
|
96
|
+
iconPosition={buttonIcon ? 'right' : undefined}
|
|
97
|
+
onClick={onLocationButtonClick}
|
|
98
|
+
icon={buttonIcon ?? undefined}
|
|
65
99
|
>
|
|
66
|
-
{!!
|
|
100
|
+
{!!locationIcon && locationIcon}
|
|
67
101
|
{city && postalCode ? (
|
|
68
|
-
|
|
69
|
-
<span
|
|
102
|
+
<div data-fs-region-bar-location>
|
|
103
|
+
<span
|
|
104
|
+
data-fs-region-bar-postal-code
|
|
105
|
+
data-fs-region-bar-location-city
|
|
106
|
+
>
|
|
70
107
|
{city}
|
|
108
|
+
</span>
|
|
109
|
+
<span data-fs-region-bar-location-postal-code>
|
|
71
110
|
{shouldDisplayPostalCode && `, ${postalCode}`}
|
|
72
111
|
</span>
|
|
73
|
-
|
|
74
|
-
</>
|
|
112
|
+
</div>
|
|
75
113
|
) : (
|
|
76
|
-
<span data-fs-region-bar-message>
|
|
114
|
+
<span data-fs-region-bar-message data-fs-region-bar-location-message>
|
|
115
|
+
{locationLabel}
|
|
116
|
+
</span>
|
|
77
117
|
)}
|
|
78
118
|
</Button>
|
|
119
|
+
{shouldDisplayFilterButton && (
|
|
120
|
+
<Button
|
|
121
|
+
variant="tertiary"
|
|
122
|
+
iconPosition={buttonIcon ? 'right' : undefined}
|
|
123
|
+
onClick={onFilterButtonClick}
|
|
124
|
+
icon={buttonIcon ?? undefined}
|
|
125
|
+
>
|
|
126
|
+
{!!filterIcon && filterIcon}
|
|
127
|
+
{selectedFilter ? (
|
|
128
|
+
<span data-fs-region-bar-filter>{selectedFilter}</span>
|
|
129
|
+
) : (
|
|
130
|
+
<span data-fs-region-bar-filter-message>{filterLabel}</span>
|
|
131
|
+
)}
|
|
132
|
+
</Button>
|
|
133
|
+
)}
|
|
79
134
|
</div>
|
|
80
135
|
)
|
|
81
136
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
1
2
|
import React from 'react'
|
|
2
|
-
import { Badge, Checkbox, Label } from '../..'
|
|
3
|
+
import { Badge, Checkbox, Label, RadioField } from '../..'
|
|
3
4
|
import type { OnFacetChange } from './Filter'
|
|
4
5
|
|
|
5
6
|
export interface FilterFacetBooleanItemProps {
|
|
@@ -10,7 +11,7 @@ export interface FilterFacetBooleanItemProps {
|
|
|
10
11
|
/**
|
|
11
12
|
* The text displayed to identify the Boolean Facet Item.
|
|
12
13
|
*/
|
|
13
|
-
label: string
|
|
14
|
+
label: string | ReactNode
|
|
14
15
|
/**
|
|
15
16
|
* Value to be emitted when Checkbox is clicked.
|
|
16
17
|
*/
|
|
@@ -22,7 +23,7 @@ export interface FilterFacetBooleanItemProps {
|
|
|
22
23
|
/**
|
|
23
24
|
* Counter badge shown besides the Facet Item.
|
|
24
25
|
*/
|
|
25
|
-
quantity
|
|
26
|
+
quantity?: number
|
|
26
27
|
/**
|
|
27
28
|
* ID to identify the Checkbox and corresponding label.
|
|
28
29
|
*/
|
|
@@ -35,6 +36,10 @@ export interface FilterFacetBooleanItemProps {
|
|
|
35
36
|
* This function is called when `Checkbox` from the facet changes.
|
|
36
37
|
*/
|
|
37
38
|
onFacetChange: OnFacetChange
|
|
39
|
+
/**
|
|
40
|
+
* Type of the Facet Item.
|
|
41
|
+
*/
|
|
42
|
+
type?: 'checkbox' | 'radio'
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
function FilterFacetBooleanItem({
|
|
@@ -45,26 +50,43 @@ function FilterFacetBooleanItem({
|
|
|
45
50
|
quantity,
|
|
46
51
|
facetKey,
|
|
47
52
|
label,
|
|
53
|
+
type = 'checkbox',
|
|
48
54
|
onFacetChange,
|
|
49
55
|
}: FilterFacetBooleanItemProps) {
|
|
50
56
|
return (
|
|
51
57
|
<li key={id} data-fs-filter-list-item>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
{type === 'checkbox' ? (
|
|
59
|
+
<>
|
|
60
|
+
<Checkbox
|
|
61
|
+
id={id}
|
|
62
|
+
checked={selected}
|
|
63
|
+
onChange={() => onFacetChange({ key: facetKey, value }, 'BOOLEAN')}
|
|
64
|
+
data-fs-filter-list-item-checkbox
|
|
65
|
+
data-testid={`${testId}-accordion-panel-checkbox`}
|
|
66
|
+
data-value={value}
|
|
67
|
+
data-quantity={quantity}
|
|
68
|
+
/>
|
|
69
|
+
<Label
|
|
70
|
+
htmlFor={id}
|
|
71
|
+
className="text__title-mini-alt"
|
|
72
|
+
data-fs-filter-list-item-label
|
|
73
|
+
>
|
|
74
|
+
{label} <Badge data-fs-filter-list-item-badge>{quantity}</Badge>
|
|
75
|
+
</Label>
|
|
76
|
+
</>
|
|
77
|
+
) : (
|
|
78
|
+
<RadioField
|
|
79
|
+
id={id}
|
|
80
|
+
name={facetKey}
|
|
81
|
+
value={value}
|
|
82
|
+
checked={selected}
|
|
83
|
+
onChange={() => onFacetChange({ key: facetKey, value }, 'BOOLEAN')}
|
|
84
|
+
data-fs-filter-list-item-radio
|
|
85
|
+
data-testid={`${testId}-accordion-panel-radio`}
|
|
86
|
+
data-value={value}
|
|
87
|
+
label={label}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
68
90
|
</li>
|
|
69
91
|
)
|
|
70
92
|
}
|
|
@@ -18,6 +18,10 @@ export interface FilterFacetsProps {
|
|
|
18
18
|
* The text displayed to identify the Facet.
|
|
19
19
|
*/
|
|
20
20
|
label: string
|
|
21
|
+
/**
|
|
22
|
+
* The description displayed to identify the Facet.
|
|
23
|
+
*/
|
|
24
|
+
description?: string
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
function FilterFacets({
|
|
@@ -26,6 +30,7 @@ function FilterFacets({
|
|
|
26
30
|
index,
|
|
27
31
|
children,
|
|
28
32
|
type,
|
|
33
|
+
description,
|
|
29
34
|
}: PropsWithChildren<FilterFacetsProps>) {
|
|
30
35
|
return (
|
|
31
36
|
<AccordionItem
|
|
@@ -39,7 +44,12 @@ function FilterFacets({
|
|
|
39
44
|
<AccordionButton testId={`${testId}-accordion-button`}>
|
|
40
45
|
{label}
|
|
41
46
|
</AccordionButton>
|
|
42
|
-
<AccordionPanel>
|
|
47
|
+
<AccordionPanel>
|
|
48
|
+
{description && (
|
|
49
|
+
<span data-fs-filter-accordion-item-description>{description}</span>
|
|
50
|
+
)}
|
|
51
|
+
{children}
|
|
52
|
+
</AccordionPanel>
|
|
43
53
|
</AccordionItem>
|
|
44
54
|
)
|
|
45
55
|
}
|
|
@@ -14,6 +14,11 @@ import {
|
|
|
14
14
|
import type { SlideOverDirection, SlideOverWidthSize } from '../SlideOver'
|
|
15
15
|
|
|
16
16
|
export interface FilterSliderProps extends HTMLAttributes<HTMLDivElement> {
|
|
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
|
* Title for the FilterSlider component.
|
|
19
24
|
*/
|
|
@@ -42,9 +47,19 @@ export interface FilterSliderProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
42
47
|
* Function called when Close Button is clicked.
|
|
43
48
|
*/
|
|
44
49
|
onClose: () => void
|
|
50
|
+
/**
|
|
51
|
+
* This function is called whenever the user clicks outside the slider content.
|
|
52
|
+
*/
|
|
53
|
+
onDismiss?: () => void
|
|
54
|
+
/**
|
|
55
|
+
* Display FilterSlider footer with buttons.
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
footer?: boolean
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
function FilterSlider({
|
|
62
|
+
testId = 'fs-filter-slider',
|
|
48
63
|
title,
|
|
49
64
|
size,
|
|
50
65
|
direction,
|
|
@@ -53,20 +68,31 @@ function FilterSlider({
|
|
|
53
68
|
clearBtnProps,
|
|
54
69
|
overlayProps,
|
|
55
70
|
onClose,
|
|
71
|
+
onDismiss,
|
|
72
|
+
footer = true,
|
|
56
73
|
...otherProps
|
|
57
74
|
}: PropsWithChildren<FilterSliderProps>) {
|
|
58
75
|
const { fade, fadeOut } = useFadeEffect()
|
|
59
|
-
const { closeFilter } = useUI()
|
|
76
|
+
const { closeFilter, closeRegionSlider } = useUI()
|
|
60
77
|
|
|
61
78
|
return (
|
|
62
79
|
<SlideOver
|
|
63
80
|
data-fs-filter-slider
|
|
64
81
|
isOpen
|
|
65
82
|
fade={fade}
|
|
66
|
-
onDismiss={
|
|
83
|
+
onDismiss={() => {
|
|
84
|
+
fadeOut()
|
|
85
|
+
onDismiss?.()
|
|
86
|
+
}}
|
|
67
87
|
size={size}
|
|
68
88
|
direction={direction}
|
|
69
|
-
onTransitionEnd={() =>
|
|
89
|
+
onTransitionEnd={() => {
|
|
90
|
+
if (fade === 'out') {
|
|
91
|
+
closeFilter()
|
|
92
|
+
closeRegionSlider()
|
|
93
|
+
}
|
|
94
|
+
}}
|
|
95
|
+
testId={testId}
|
|
70
96
|
overlayProps={overlayProps}
|
|
71
97
|
{...otherProps}
|
|
72
98
|
>
|
|
@@ -81,18 +107,27 @@ function FilterSlider({
|
|
|
81
107
|
</SlideOverHeader>
|
|
82
108
|
{children}
|
|
83
109
|
</div>
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
110
|
+
{footer && (
|
|
111
|
+
<footer data-fs-filter-slider-footer>
|
|
112
|
+
{clearBtnProps && (
|
|
113
|
+
<Button
|
|
114
|
+
data-fs-filter-slider-footer-button-clear
|
|
115
|
+
{...clearBtnProps}
|
|
116
|
+
/>
|
|
117
|
+
)}
|
|
118
|
+
{applyBtnProps && (
|
|
119
|
+
<Button
|
|
120
|
+
data-fs-filter-slider-footer-button-apply
|
|
121
|
+
testId={`${testId}-button-apply`}
|
|
122
|
+
{...applyBtnProps}
|
|
123
|
+
onClick={(e) => {
|
|
124
|
+
applyBtnProps?.onClick?.(e)
|
|
125
|
+
fadeOut()
|
|
126
|
+
}}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
</footer>
|
|
130
|
+
)}
|
|
96
131
|
</SlideOver>
|
|
97
132
|
)
|
|
98
133
|
}
|