@faststore/components 2.0.52-alpha.0 → 2.0.54-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/dist/atoms/Button/Button.d.ts +9 -1
- package/dist/atoms/Button/Button.js +7 -4
- package/dist/atoms/Button/Button.js.map +1 -1
- package/dist/atoms/Loader/Loader.d.ts +13 -0
- package/dist/atoms/Loader/Loader.js +9 -0
- package/dist/atoms/Loader/Loader.js.map +1 -0
- package/dist/atoms/Loader/index.d.ts +2 -0
- package/dist/atoms/Loader/index.js +2 -0
- package/dist/atoms/Loader/index.js.map +1 -0
- package/dist/atoms/Slider/Slider.d.ts +71 -0
- package/dist/atoms/Slider/Slider.js +57 -0
- package/dist/atoms/Slider/Slider.js.map +1 -0
- package/dist/atoms/Slider/index.d.ts +2 -0
- package/dist/atoms/Slider/index.js +2 -0
- package/dist/atoms/Slider/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/molecules/BuyButton/BuyButton.js +2 -4
- package/dist/molecules/BuyButton/BuyButton.js.map +1 -1
- package/dist/organisms/PriceRange/PriceRange.d.ts +38 -0
- package/dist/organisms/PriceRange/PriceRange.js +75 -0
- package/dist/organisms/PriceRange/PriceRange.js.map +1 -0
- package/dist/organisms/PriceRange/index.d.ts +2 -0
- package/dist/organisms/PriceRange/index.js +2 -0
- package/dist/organisms/PriceRange/index.js.map +1 -0
- package/package.json +2 -2
- package/src/atoms/Button/Button.tsx +21 -3
- package/src/atoms/Loader/Loader.tsx +33 -0
- package/src/atoms/Loader/index.ts +2 -0
- package/src/atoms/Slider/Slider.tsx +220 -0
- package/src/atoms/Slider/index.ts +2 -0
- package/src/index.ts +7 -0
- package/src/molecules/BuyButton/BuyButton.tsx +8 -3
- package/src/organisms/PriceRange/PriceRange.tsx +188 -0
- package/src/organisms/PriceRange/index.ts +2 -0
|
@@ -21,13 +21,21 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
21
21
|
*/
|
|
22
22
|
inverse?: boolean;
|
|
23
23
|
/**
|
|
24
|
-
* Specifies that this button should be disabled
|
|
24
|
+
* Specifies that this button should be disabled.
|
|
25
25
|
*/
|
|
26
26
|
disabled?: boolean;
|
|
27
27
|
/**
|
|
28
28
|
* A React component that will be rendered as an icon.
|
|
29
29
|
*/
|
|
30
30
|
icon?: ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Boolean that represents a loading state.
|
|
33
|
+
*/
|
|
34
|
+
loading?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Specifies a label for loading state.
|
|
37
|
+
*/
|
|
38
|
+
loadingLabel?: string;
|
|
31
39
|
/**
|
|
32
40
|
* Specifies where the icon should be positioned
|
|
33
41
|
*/
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
|
-
import { Icon } from '../../index';
|
|
3
|
-
const Button = forwardRef(function Button({ children, variant, inverse, size = 'regular', testId = 'fs-button', icon, iconPosition = 'left', disabled, ...otherProps }, ref) {
|
|
4
|
-
return (React.createElement("button", { ref: ref, "data-fs-button": true, "data-fs-button-inverse": inverse, "data-fs-button-size": size, "data-fs-button-variant": variant, disabled: disabled, "data-testid": testId, ...otherProps },
|
|
2
|
+
import { Icon, Loader } from '../../index';
|
|
3
|
+
const Button = forwardRef(function Button({ children, variant, inverse, size = 'regular', testId = 'fs-button', loading, loadingLabel, icon, iconPosition = 'left', disabled, ...otherProps }, ref) {
|
|
4
|
+
return (React.createElement("button", { ref: ref, "data-fs-button": true, "data-fs-button-inverse": inverse, "data-fs-button-size": size, "data-fs-button-loading": loading, "data-fs-button-variant": variant, disabled: disabled, "data-testid": testId, ...otherProps },
|
|
5
|
+
loading && (React.createElement("p", { "data-fs-button-loading-label": true },
|
|
6
|
+
loadingLabel,
|
|
7
|
+
React.createElement(Loader, { variant: variant === 'primary' && !inverse ? 'light' : 'dark' }))),
|
|
5
8
|
icon && iconPosition === 'left' && React.createElement(Icon, { component: icon }),
|
|
6
|
-
children,
|
|
9
|
+
React.createElement("span", null, children),
|
|
7
10
|
icon && iconPosition === 'right' && React.createElement(Icon, { component: icon })));
|
|
8
11
|
});
|
|
9
12
|
export default Button;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/atoms/Button/Button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../src/atoms/Button/Button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AA6C1C,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CACvE,EACE,QAAQ,EACR,OAAO,EACP,OAAO,EACP,IAAI,GAAG,SAAS,EAChB,MAAM,GAAG,WAAW,EACpB,OAAO,EACP,YAAY,EACZ,IAAI,EACJ,YAAY,GAAG,MAAM,EACrB,QAAQ,EACR,GAAG,UAAU,EACd,EACD,GAAG;IAGH,OAAO,CACL,gCACE,GAAG,EAAE,GAAG,oDAEgB,OAAO,yBACV,IAAI,4BACD,OAAO,4BACP,OAAO,EAC/B,QAAQ,EAAE,QAAQ,iBACL,MAAM,KACf,UAAU;QAEb,OAAO,IAAI,CACV;YACG,YAAY;YACb,oBAAC,MAAM,IAAC,OAAO,EAAE,OAAO,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,GAAI,CACvE,CACL;QACA,IAAI,IAAI,YAAY,KAAK,MAAM,IAAI,oBAAC,IAAI,IAAC,SAAS,EAAE,IAAI,GAAI;QAC7D,kCAAO,QAAQ,CAAQ;QACtB,IAAI,IAAI,YAAY,KAAK,OAAO,IAAI,oBAAC,IAAI,IAAC,SAAS,EAAE,IAAI,GAAI,CACvD,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type LoaderProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Specifies the component color variant.
|
|
5
|
+
*/
|
|
6
|
+
variant?: 'light' | 'dark';
|
|
7
|
+
/**
|
|
8
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
9
|
+
*/
|
|
10
|
+
testId?: string;
|
|
11
|
+
};
|
|
12
|
+
declare const Loader: React.ForwardRefExoticComponent<LoaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
export default Loader;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
const Loader = forwardRef(function Loader({ variant = 'dark', testId = 'fs-loader', ...otherProps }, ref) {
|
|
3
|
+
return (React.createElement("div", { ref: ref, "data-fs-loader": true, "data-fs-loader-variant": variant, "data-testid": testId, ...otherProps },
|
|
4
|
+
React.createElement("span", { "data-fs-loader-item": true }),
|
|
5
|
+
React.createElement("span", { "data-fs-loader-item": true }),
|
|
6
|
+
React.createElement("span", { "data-fs-loader-item": true })));
|
|
7
|
+
});
|
|
8
|
+
export default Loader;
|
|
9
|
+
//# sourceMappingURL=Loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loader.js","sourceRoot":"","sources":["../../../src/atoms/Loader/Loader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAazC,MAAM,MAAM,GAAG,UAAU,CAA8B,SAAS,MAAM,CACpE,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,UAAU,EAAe,EACtE,GAAG;IAEH,OAAO,CACL,6BACE,GAAG,EAAE,GAAG,oDAEgB,OAAO,iBAClB,MAAM,KACf,UAAU;QAEd,4DAAiC;QACjC,4DAAiC;QACjC,4DAAiC,CAC7B,CACP,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,MAAM,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/atoms/Loader/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code is inspired by the work of [sandra-lewis](https://codesandbox.io/u/sandra-lewis)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import type { ReactNode } from 'react';
|
|
6
|
+
interface Range {
|
|
7
|
+
absolute: number;
|
|
8
|
+
selected: number;
|
|
9
|
+
}
|
|
10
|
+
interface RangeLabel {
|
|
11
|
+
min: string | ReactNode;
|
|
12
|
+
max: string | ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export type SliderProps = {
|
|
15
|
+
/**
|
|
16
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
17
|
+
*
|
|
18
|
+
* @default 'fs-slider'
|
|
19
|
+
*/
|
|
20
|
+
testId?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The minimum value of the slider.
|
|
23
|
+
*/
|
|
24
|
+
min: Range;
|
|
25
|
+
/**
|
|
26
|
+
* The maximum value of the slider.
|
|
27
|
+
*/
|
|
28
|
+
max: Range;
|
|
29
|
+
/**
|
|
30
|
+
* Specifies the number interval to be used in the inputs.
|
|
31
|
+
*/
|
|
32
|
+
step?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Specifies the absolute values labels.
|
|
35
|
+
*/
|
|
36
|
+
absoluteValuesLabel: RangeLabel;
|
|
37
|
+
/**
|
|
38
|
+
* Callback that fires when the slider value changes.
|
|
39
|
+
*/
|
|
40
|
+
onChange?: (value: {
|
|
41
|
+
min: number;
|
|
42
|
+
max: number;
|
|
43
|
+
}) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Callback that fires when the slider value ends changing.
|
|
46
|
+
*/
|
|
47
|
+
onEnd?: (value: {
|
|
48
|
+
min: number;
|
|
49
|
+
max: number;
|
|
50
|
+
}) => void;
|
|
51
|
+
/**
|
|
52
|
+
* A function used to set a human-readable value text based on the slider's current value.
|
|
53
|
+
*/
|
|
54
|
+
getAriaValueText?(value: number, thumb?: 'min' | 'max'): string;
|
|
55
|
+
/**
|
|
56
|
+
* Component that renders min value label above the left thumb.
|
|
57
|
+
*/
|
|
58
|
+
minValueLabelComponent?: (minValue: number) => ReactNode;
|
|
59
|
+
/**
|
|
60
|
+
* Component that renders max value label above the right thumb.
|
|
61
|
+
*/
|
|
62
|
+
maxValueLabelComponent?: (maxValue: number) => ReactNode;
|
|
63
|
+
};
|
|
64
|
+
type SliderRefType = {
|
|
65
|
+
setSliderValues: (values: {
|
|
66
|
+
min: number;
|
|
67
|
+
max: number;
|
|
68
|
+
}) => void;
|
|
69
|
+
};
|
|
70
|
+
declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<SliderRefType | undefined>>;
|
|
71
|
+
export default Slider;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code is inspired by the work of [sandra-lewis](https://codesandbox.io/u/sandra-lewis)
|
|
3
|
+
*/
|
|
4
|
+
import React, { useState, useMemo, useImperativeHandle, forwardRef, } from 'react';
|
|
5
|
+
const percent = (value, min, max) => Math.round(((value - min) / (max - min)) * 100);
|
|
6
|
+
const Slider = forwardRef(function Slider({ min, max, absoluteValuesLabel, onChange, onEnd, testId = 'fs-slider', getAriaValueText, step, minValueLabelComponent, maxValueLabelComponent, ...otherProps }, ref) {
|
|
7
|
+
const widthPercent = useMemo(() => (max.absolute - min.absolute) / 100, [max.absolute, min.absolute]);
|
|
8
|
+
const [minPercent, setMinPercent] = useState(() => percent(min.selected, min.absolute, max.absolute));
|
|
9
|
+
const [maxPercent, setMaxPercent] = useState(() => percent(max.selected, min.absolute, max.absolute));
|
|
10
|
+
const [minVal, setMinVal] = useState(() => Math.floor(min.absolute + minPercent * widthPercent));
|
|
11
|
+
const [maxVal, setMaxVal] = useState(() => Math.round(min.absolute + maxPercent * widthPercent));
|
|
12
|
+
const percentage = (value) => (value / max.absolute) * 100;
|
|
13
|
+
useImperativeHandle(ref, () => ({
|
|
14
|
+
setSliderValues: (values) => {
|
|
15
|
+
const sliderMinValue = Math.min(Number(values.min), maxVal);
|
|
16
|
+
setMinVal(sliderMinValue);
|
|
17
|
+
setMinPercent(percent(sliderMinValue, min.absolute, max.absolute));
|
|
18
|
+
if (values.max > max.absolute) {
|
|
19
|
+
setMaxVal(max.absolute);
|
|
20
|
+
setMaxPercent(percent(max.absolute, min.absolute, max.absolute));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const sliderMaxValue = Math.max(Number(values.max), minVal);
|
|
24
|
+
setMaxVal(sliderMaxValue);
|
|
25
|
+
setMaxPercent(percent(sliderMaxValue, min.absolute, max.absolute));
|
|
26
|
+
},
|
|
27
|
+
}));
|
|
28
|
+
return (React.createElement("div", { "data-fs-slider": true, "data-testid": testId },
|
|
29
|
+
React.createElement("div", { "data-fs-slider-absolute-values": true },
|
|
30
|
+
React.createElement("span", null, absoluteValuesLabel.min),
|
|
31
|
+
React.createElement("span", null, absoluteValuesLabel.max)),
|
|
32
|
+
React.createElement("div", { "data-fs-slider-wrapper": true },
|
|
33
|
+
React.createElement("div", { "data-fs-slider-range": true, style: {
|
|
34
|
+
left: `${minPercent}%`,
|
|
35
|
+
width: `${maxPercent - minPercent}%`,
|
|
36
|
+
} }),
|
|
37
|
+
React.createElement("input", { type: "range", min: Math.floor(min.absolute), max: Math.round(max.absolute), value: minVal, step: step, onMouseUp: () => onEnd?.({ min: minVal, max: maxVal }), onTouchEnd: () => onEnd?.({ min: minVal, max: maxVal }), onChange: (event) => {
|
|
38
|
+
const minValue = Math.min(Number(event.target.value), maxVal);
|
|
39
|
+
setMinVal(minValue);
|
|
40
|
+
setMinPercent(percent(minValue, min.absolute, max.absolute));
|
|
41
|
+
onChange?.({ min: minValue, max: maxVal });
|
|
42
|
+
}, "data-fs-slider-thumb": "left", "aria-valuemin": min.absolute, "aria-valuemax": max.absolute, "aria-valuenow": minVal, "aria-label": String(minVal), "aria-labelledby": getAriaValueText?.(minVal, 'min'), ...otherProps }),
|
|
43
|
+
minValueLabelComponent && (React.createElement("span", { "data-fs-slider-value-label": "min", style: {
|
|
44
|
+
left: `calc(${percentage(minVal)}% + (${8 - percentage(minVal) * 0.2}px))`,
|
|
45
|
+
} }, minValueLabelComponent(minVal))),
|
|
46
|
+
React.createElement("input", { type: "range", min: Math.floor(min.absolute), max: Math.round(max.absolute), value: maxVal, step: step, onMouseUp: () => onEnd?.({ min: minVal, max: maxVal }), onTouchEnd: () => onEnd?.({ min: minVal, max: maxVal }), onChange: (event) => {
|
|
47
|
+
const maxValue = Math.max(Number(event.target.value), minVal);
|
|
48
|
+
setMaxVal(maxValue);
|
|
49
|
+
setMaxPercent(percent(maxValue, min.absolute, max.absolute));
|
|
50
|
+
onChange?.({ min: minVal, max: maxValue });
|
|
51
|
+
}, "data-fs-slider-thumb": "right", "aria-valuemin": min.absolute, "aria-valuemax": max.absolute, "aria-valuenow": maxVal, "aria-label": String(maxVal), "aria-labelledby": getAriaValueText?.(maxVal, 'max') }),
|
|
52
|
+
maxValueLabelComponent && (React.createElement("span", { "data-fs-slider-value-label": "max", style: {
|
|
53
|
+
left: `calc(${percentage(maxVal)}% + (${8 - percentage(maxVal) * 0.2}px))`,
|
|
54
|
+
} }, maxValueLabelComponent(maxVal))))));
|
|
55
|
+
});
|
|
56
|
+
export default Slider;
|
|
57
|
+
//# sourceMappingURL=Slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Slider.js","sourceRoot":"","sources":["../../../src/atoms/Slider/Slider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/atoms/Slider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export { default as Label } from './atoms/Label';
|
|
|
13
13
|
export type { LabelProps } from './atoms/Label';
|
|
14
14
|
export { default as Link } from './atoms/Link';
|
|
15
15
|
export type { LinkProps, LinkElementType } from './atoms/Link';
|
|
16
|
+
export { default as Loader } from './atoms/Loader';
|
|
17
|
+
export type { LoaderProps } from './atoms/Loader';
|
|
16
18
|
export { default as List } from './atoms/List';
|
|
17
19
|
export type { ListProps } from './atoms/List';
|
|
18
20
|
export { default as Overlay } from './atoms/Overlay';
|
|
@@ -23,6 +25,8 @@ export { default as Radio } from './atoms/Radio';
|
|
|
23
25
|
export type { RadioProps } from './atoms/Radio';
|
|
24
26
|
export { default as Select } from './atoms/Select';
|
|
25
27
|
export type { SelectProps } from './atoms/Select';
|
|
28
|
+
export { default as Slider } from './atoms/Slider';
|
|
29
|
+
export type { SliderProps } from './atoms/Slider';
|
|
26
30
|
export { default as SROnly } from './atoms/SROnly';
|
|
27
31
|
export { default as Accordion, AccordionItem, AccordionButton, AccordionPanel, } from './molecules/Accordion';
|
|
28
32
|
export type { AccordionProps, AccordionItemProps, AccordionButtonProps, AccordionPanelProps, } from './molecules/Accordion';
|
|
@@ -63,3 +67,5 @@ export { default as QuantitySelector } from './molecules/QuantitySelector';
|
|
|
63
67
|
export type { QuantitySelectorProps } from './molecules/QuantitySelector';
|
|
64
68
|
export { default as Hero, HeroImage, HeroHeading } from './organisms/Hero';
|
|
65
69
|
export type { HeroProps, HeroImageProps, HeroHeadingProps, } from './organisms/Hero';
|
|
70
|
+
export { default as PriceRange } from './organisms/PriceRange';
|
|
71
|
+
export type { PriceRangeProps } from './organisms/PriceRange';
|
package/dist/index.js
CHANGED
|
@@ -8,11 +8,13 @@ export { default as Icon } from './atoms/Icon';
|
|
|
8
8
|
export { default as Input } from './atoms/Input';
|
|
9
9
|
export { default as Label } from './atoms/Label';
|
|
10
10
|
export { default as Link } from './atoms/Link';
|
|
11
|
+
export { default as Loader } from './atoms/Loader';
|
|
11
12
|
export { default as List } from './atoms/List';
|
|
12
13
|
export { default as Overlay } from './atoms/Overlay';
|
|
13
14
|
export { default as Price } from './atoms/Price';
|
|
14
15
|
export { default as Radio } from './atoms/Radio';
|
|
15
16
|
export { default as Select } from './atoms/Select';
|
|
17
|
+
export { default as Slider } from './atoms/Slider';
|
|
16
18
|
export { default as SROnly } from './atoms/SROnly';
|
|
17
19
|
// Molecules
|
|
18
20
|
export { default as Accordion, AccordionItem, AccordionButton, AccordionPanel, } from './molecules/Accordion';
|
|
@@ -36,4 +38,5 @@ export { default as ToggleField } from './molecules/ToggleField';
|
|
|
36
38
|
export { default as QuantitySelector } from './molecules/QuantitySelector';
|
|
37
39
|
// Organisms
|
|
38
40
|
export { default as Hero, HeroImage, HeroHeading } from './organisms/Hero';
|
|
41
|
+
export { default as PriceRange } from './organisms/PriceRange';
|
|
39
42
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,cAAc,UAAU,CAAA;AAExB,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAElD,YAAY;AACZ,OAAO,EACL,OAAO,IAAI,SAAS,EACpB,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,uBAAuB,CAAA;AAO9B,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEpD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EACL,OAAO,IAAI,QAAQ,EACnB,cAAc,EACd,YAAY,EACZ,YAAY,GACb,MAAM,sBAAsB,CAAA;AAO7B,OAAO,EACL,OAAO,IAAI,IAAI,EACf,WAAW,EACX,SAAS,GACV,MAAM,kBAAkB,CAAA;AAMzB,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EACL,OAAO,IAAI,UAAU,EACrB,WAAW,GACZ,MAAM,wBAAwB,CAAA;AAK/B,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAEhE,OAAO,EACL,KAAK,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,GACT,MAAM,mBAAmB,CAAA;AAS1B,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAEhE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAG1E,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Button
|
|
2
|
+
import { Button } from '../../index';
|
|
3
3
|
import { ShoppingCart } from '../../assets';
|
|
4
4
|
function BuyButton({ testId = 'fs-buy-button', icon, children, ...otherProps }) {
|
|
5
|
-
return (React.createElement(Button, { "data-fs-buy-button": true, "data-testid": testId, ...otherProps },
|
|
6
|
-
React.createElement(Icon, { component: React.createElement(ShoppingCart, null) }),
|
|
7
|
-
children));
|
|
5
|
+
return (React.createElement(Button, { "data-fs-buy-button": true, icon: React.createElement(ShoppingCart, null), iconPosition: "left", "data-testid": testId, ...otherProps }, children));
|
|
8
6
|
}
|
|
9
7
|
export default BuyButton;
|
|
10
8
|
//# sourceMappingURL=BuyButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuyButton.js","sourceRoot":"","sources":["../../../src/molecules/BuyButton/BuyButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"BuyButton.js","sourceRoot":"","sources":["../../../src/molecules/BuyButton/BuyButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAI3C,SAAS,SAAS,CAAC,EACjB,MAAM,GAAG,eAAe,EACxB,IAAI,EACJ,QAAQ,EACR,GAAG,UAAU,EACE;IACf,OAAO,CACL,oBAAC,MAAM,gCAEL,IAAI,EAAE,oBAAC,YAAY,OAAG,EACtB,YAAY,EAAC,MAAM,iBACN,MAAM,KACf,UAAU,IAEb,QAAQ,CACF,CACV,CAAA;AACH,CAAC;AAED,eAAe,SAAS,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AriaAttributes } from 'react';
|
|
3
|
+
import type { PriceProps, SliderProps } from '../../index';
|
|
4
|
+
export type PriceRangeProps = Omit<SliderProps, 'absoluteValuesLabel'> & {
|
|
5
|
+
/**
|
|
6
|
+
* The current use case variant for prices.
|
|
7
|
+
*/
|
|
8
|
+
variant?: PriceProps['variant'];
|
|
9
|
+
/**
|
|
10
|
+
* Formatter function that transforms the raw price value and render the result.
|
|
11
|
+
*/
|
|
12
|
+
formatter: PriceProps['formatter'];
|
|
13
|
+
/**
|
|
14
|
+
* Defines a string value that labels the current element.
|
|
15
|
+
*/
|
|
16
|
+
'aria-label'?: AriaAttributes['aria-label'];
|
|
17
|
+
};
|
|
18
|
+
type PriceRangeRefType = {
|
|
19
|
+
setPriceRangeValues: (values: {
|
|
20
|
+
min: number;
|
|
21
|
+
max: number;
|
|
22
|
+
}) => void;
|
|
23
|
+
};
|
|
24
|
+
declare const PriceRange: React.ForwardRefExoticComponent<Omit<SliderProps, "absoluteValuesLabel"> & {
|
|
25
|
+
/**
|
|
26
|
+
* The current use case variant for prices.
|
|
27
|
+
*/
|
|
28
|
+
variant?: PriceProps['variant'];
|
|
29
|
+
/**
|
|
30
|
+
* Formatter function that transforms the raw price value and render the result.
|
|
31
|
+
*/
|
|
32
|
+
formatter: PriceProps['formatter'];
|
|
33
|
+
/**
|
|
34
|
+
* Defines a string value that labels the current element.
|
|
35
|
+
*/
|
|
36
|
+
'aria-label'?: AriaAttributes['aria-label'];
|
|
37
|
+
} & React.RefAttributes<PriceRangeRefType | undefined>>;
|
|
38
|
+
export default PriceRange;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React, { useRef, useState, useImperativeHandle, forwardRef } from 'react';
|
|
2
|
+
import { Price, Slider, InputField } from '../../index';
|
|
3
|
+
const PriceRange = forwardRef(function PriceRange({ formatter, max, min, step = 1, onChange, onEnd, testId = 'fs-price-range', variant, 'aria-label': ariaLabel, ...otherProps }, ref) {
|
|
4
|
+
const sliderRef = useRef();
|
|
5
|
+
useImperativeHandle(ref, () => ({
|
|
6
|
+
setPriceRangeValues: (values) => {
|
|
7
|
+
onChange?.(values);
|
|
8
|
+
sliderRef.current?.setSliderValues(values);
|
|
9
|
+
},
|
|
10
|
+
}));
|
|
11
|
+
const inputMinRef = useRef(null);
|
|
12
|
+
const inputMaxRef = useRef(null);
|
|
13
|
+
const [inputMinError, setInputMinError] = useState();
|
|
14
|
+
const [inputMaxError, setInputMaxError] = useState();
|
|
15
|
+
const [priceRange, setPriceRange] = useState({
|
|
16
|
+
min: Math.floor(min.selected),
|
|
17
|
+
max: Math.round(max.selected),
|
|
18
|
+
});
|
|
19
|
+
function onChangePriceRange(value) {
|
|
20
|
+
setInputMinError(undefined);
|
|
21
|
+
setInputMaxError(undefined);
|
|
22
|
+
setPriceRange({ min: value.min, max: value.max });
|
|
23
|
+
if (inputMinRef.current?.value) {
|
|
24
|
+
inputMinRef.current.value = String(value.min);
|
|
25
|
+
}
|
|
26
|
+
if (inputMaxRef.current?.value) {
|
|
27
|
+
inputMaxRef.current.value = String(value.max);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function onChangeInputMin(value) {
|
|
31
|
+
setInputMinError(undefined);
|
|
32
|
+
if (Number(value) < Math.floor(min.absolute)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (Number(value) > Math.floor(priceRange.max)) {
|
|
36
|
+
setInputMinError(`Min price can't be greater than max`);
|
|
37
|
+
}
|
|
38
|
+
setPriceRange({ ...priceRange, min: Number(value) });
|
|
39
|
+
sliderRef.current?.setSliderValues({
|
|
40
|
+
...priceRange,
|
|
41
|
+
min: Number(value),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function onChangeInputMax(value) {
|
|
45
|
+
setInputMaxError(undefined);
|
|
46
|
+
if (Number(value) > Math.round(max.absolute)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (Number(value) < Math.round(priceRange.min)) {
|
|
50
|
+
setInputMaxError(`Max price can't be smaller than min`);
|
|
51
|
+
}
|
|
52
|
+
setPriceRange({ ...priceRange, max: Number(value) });
|
|
53
|
+
sliderRef.current?.setSliderValues({
|
|
54
|
+
...priceRange,
|
|
55
|
+
max: Number(value),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return (React.createElement("div", { "data-fs-price-range": true, "data-testid": testId, ...otherProps },
|
|
59
|
+
React.createElement(Slider, { ref: sliderRef, min: min, max: max, step: step, onEnd: (value) => {
|
|
60
|
+
onEnd?.(value);
|
|
61
|
+
onChangePriceRange(value);
|
|
62
|
+
}, "aria-label": ariaLabel, onChange: (value) => onChange?.(value), absoluteValuesLabel: {
|
|
63
|
+
min: (React.createElement(Price, { value: Math.floor(min.absolute), variant: variant, formatter: formatter })),
|
|
64
|
+
max: (React.createElement(Price, { value: Math.round(max.absolute), variant: variant, formatter: formatter })),
|
|
65
|
+
}, minValueLabelComponent: (minValue) => {
|
|
66
|
+
return (React.createElement(Price, { value: minValue, variant: variant, formatter: formatter }));
|
|
67
|
+
}, maxValueLabelComponent: (maxValue) => {
|
|
68
|
+
return (React.createElement(Price, { value: maxValue, variant: variant, formatter: formatter }));
|
|
69
|
+
} }),
|
|
70
|
+
React.createElement("div", { "data-fs-price-range-inputs": true },
|
|
71
|
+
React.createElement(InputField, { id: "price-range-min", step: step, label: "Min", type: "number", inputMode: "numeric", error: inputMinError, inputRef: inputMinRef, min: Math.floor(min.absolute), max: priceRange.max, value: priceRange.min, onChange: (e) => onChangeInputMin(e.target.value), onBlur: () => !inputMinError && onEnd?.(priceRange) }),
|
|
72
|
+
React.createElement(InputField, { id: "price-range-max", label: "Max", step: step, type: "number", inputMode: "numeric", error: inputMaxError, inputRef: inputMaxRef, max: Math.round(max.absolute), min: priceRange.min, value: priceRange.max, onChange: (e) => onChangeInputMax(e.target.value), onBlur: () => !inputMaxError && onEnd?.(priceRange) }))));
|
|
73
|
+
});
|
|
74
|
+
export default PriceRange;
|
|
75
|
+
//# sourceMappingURL=PriceRange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PriceRange.js","sourceRoot":"","sources":["../../../src/organisms/PriceRange/PriceRange.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/organisms/PriceRange/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/components",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.54-alpha.0",
|
|
4
4
|
"module": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"author": "Emerson Laurentino @emersonlaurentino",
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"node": "16.18.0",
|
|
31
31
|
"yarn": "1.19.1"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "7173ea0bec153905a6b800d002401b5c27fd3213"
|
|
34
34
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode, ButtonHTMLAttributes } from 'react'
|
|
2
2
|
import React, { forwardRef } from 'react'
|
|
3
|
-
import { Icon } from '../../index'
|
|
3
|
+
import { Icon, Loader } from '../../index'
|
|
4
4
|
|
|
5
5
|
export type Variant = 'primary' | 'secondary' | 'tertiary'
|
|
6
6
|
export type Size = 'small' | 'regular'
|
|
@@ -24,13 +24,21 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
|
24
24
|
*/
|
|
25
25
|
inverse?: boolean
|
|
26
26
|
/**
|
|
27
|
-
* Specifies that this button should be disabled
|
|
27
|
+
* Specifies that this button should be disabled.
|
|
28
28
|
*/
|
|
29
29
|
disabled?: boolean
|
|
30
30
|
/**
|
|
31
31
|
* A React component that will be rendered as an icon.
|
|
32
32
|
*/
|
|
33
33
|
icon?: ReactNode
|
|
34
|
+
/**
|
|
35
|
+
* Boolean that represents a loading state.
|
|
36
|
+
*/
|
|
37
|
+
loading?: boolean
|
|
38
|
+
/**
|
|
39
|
+
* Specifies a label for loading state.
|
|
40
|
+
*/
|
|
41
|
+
loadingLabel?: string
|
|
34
42
|
/**
|
|
35
43
|
* Specifies where the icon should be positioned
|
|
36
44
|
*/
|
|
@@ -44,6 +52,8 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
44
52
|
inverse,
|
|
45
53
|
size = 'regular',
|
|
46
54
|
testId = 'fs-button',
|
|
55
|
+
loading,
|
|
56
|
+
loadingLabel,
|
|
47
57
|
icon,
|
|
48
58
|
iconPosition = 'left',
|
|
49
59
|
disabled,
|
|
@@ -51,19 +61,27 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
51
61
|
},
|
|
52
62
|
ref
|
|
53
63
|
) {
|
|
64
|
+
|
|
54
65
|
return (
|
|
55
66
|
<button
|
|
56
67
|
ref={ref}
|
|
57
68
|
data-fs-button
|
|
58
69
|
data-fs-button-inverse={inverse}
|
|
59
70
|
data-fs-button-size={size}
|
|
71
|
+
data-fs-button-loading={loading}
|
|
60
72
|
data-fs-button-variant={variant}
|
|
61
73
|
disabled={disabled}
|
|
62
74
|
data-testid={testId}
|
|
63
75
|
{...otherProps}
|
|
64
76
|
>
|
|
77
|
+
{loading && (
|
|
78
|
+
<p data-fs-button-loading-label>
|
|
79
|
+
{loadingLabel}
|
|
80
|
+
<Loader variant={variant === 'primary' && !inverse ? 'light' : 'dark'} />
|
|
81
|
+
</p>
|
|
82
|
+
)}
|
|
65
83
|
{icon && iconPosition === 'left' && <Icon component={icon} />}
|
|
66
|
-
{children}
|
|
84
|
+
<span>{children}</span>
|
|
67
85
|
{icon && iconPosition === 'right' && <Icon component={icon} />}
|
|
68
86
|
</button>
|
|
69
87
|
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
|
|
3
|
+
export type LoaderProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Specifies the component color variant.
|
|
6
|
+
*/
|
|
7
|
+
variant?: 'light' | 'dark'
|
|
8
|
+
/**
|
|
9
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
10
|
+
*/
|
|
11
|
+
testId?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Loader = forwardRef<HTMLDivElement, LoaderProps>(function Loader(
|
|
15
|
+
{ variant = 'dark', testId = 'fs-loader', ...otherProps }: LoaderProps,
|
|
16
|
+
ref
|
|
17
|
+
) {
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
ref={ref}
|
|
21
|
+
data-fs-loader
|
|
22
|
+
data-fs-loader-variant={variant}
|
|
23
|
+
data-testid={testId}
|
|
24
|
+
{...otherProps}
|
|
25
|
+
>
|
|
26
|
+
<span data-fs-loader-item></span>
|
|
27
|
+
<span data-fs-loader-item></span>
|
|
28
|
+
<span data-fs-loader-item></span>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export default Loader
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code is inspired by the work of [sandra-lewis](https://codesandbox.io/u/sandra-lewis)
|
|
3
|
+
*/
|
|
4
|
+
import React, {
|
|
5
|
+
useState,
|
|
6
|
+
useMemo,
|
|
7
|
+
useImperativeHandle,
|
|
8
|
+
forwardRef,
|
|
9
|
+
} from 'react'
|
|
10
|
+
import type { ReactNode } from 'react'
|
|
11
|
+
|
|
12
|
+
interface Range {
|
|
13
|
+
absolute: number
|
|
14
|
+
selected: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface RangeLabel {
|
|
18
|
+
min: string | ReactNode
|
|
19
|
+
max: string | ReactNode
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type SliderProps = {
|
|
23
|
+
/**
|
|
24
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
25
|
+
*
|
|
26
|
+
* @default 'fs-slider'
|
|
27
|
+
*/
|
|
28
|
+
testId?: string
|
|
29
|
+
/**
|
|
30
|
+
* The minimum value of the slider.
|
|
31
|
+
*/
|
|
32
|
+
min: Range
|
|
33
|
+
/**
|
|
34
|
+
* The maximum value of the slider.
|
|
35
|
+
*/
|
|
36
|
+
max: Range
|
|
37
|
+
/**
|
|
38
|
+
* Specifies the number interval to be used in the inputs.
|
|
39
|
+
*/
|
|
40
|
+
step?: number
|
|
41
|
+
/**
|
|
42
|
+
* Specifies the absolute values labels.
|
|
43
|
+
*/
|
|
44
|
+
absoluteValuesLabel: RangeLabel
|
|
45
|
+
/**
|
|
46
|
+
* Callback that fires when the slider value changes.
|
|
47
|
+
*/
|
|
48
|
+
onChange?: (value: { min: number; max: number }) => void
|
|
49
|
+
/**
|
|
50
|
+
* Callback that fires when the slider value ends changing.
|
|
51
|
+
*/
|
|
52
|
+
onEnd?: (value: { min: number; max: number }) => void
|
|
53
|
+
/**
|
|
54
|
+
* A function used to set a human-readable value text based on the slider's current value.
|
|
55
|
+
*/
|
|
56
|
+
getAriaValueText?(value: number, thumb?: 'min' | 'max'): string
|
|
57
|
+
/**
|
|
58
|
+
* Component that renders min value label above the left thumb.
|
|
59
|
+
*/
|
|
60
|
+
minValueLabelComponent?: (minValue: number) => ReactNode
|
|
61
|
+
/**
|
|
62
|
+
* Component that renders max value label above the right thumb.
|
|
63
|
+
*/
|
|
64
|
+
maxValueLabelComponent?: (maxValue: number) => ReactNode
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type SliderRefType = {
|
|
68
|
+
setSliderValues: (values: { min: number; max: number }) => void
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const percent = (value: number, min: number, max: number) =>
|
|
72
|
+
Math.round(((value - min) / (max - min)) * 100)
|
|
73
|
+
|
|
74
|
+
const Slider = forwardRef<SliderRefType | undefined, SliderProps>(
|
|
75
|
+
function Slider(
|
|
76
|
+
{
|
|
77
|
+
min,
|
|
78
|
+
max,
|
|
79
|
+
absoluteValuesLabel,
|
|
80
|
+
onChange,
|
|
81
|
+
onEnd,
|
|
82
|
+
testId = 'fs-slider',
|
|
83
|
+
getAriaValueText,
|
|
84
|
+
step,
|
|
85
|
+
minValueLabelComponent,
|
|
86
|
+
maxValueLabelComponent,
|
|
87
|
+
...otherProps
|
|
88
|
+
},
|
|
89
|
+
ref
|
|
90
|
+
) {
|
|
91
|
+
const widthPercent = useMemo(
|
|
92
|
+
() => (max.absolute - min.absolute) / 100,
|
|
93
|
+
[max.absolute, min.absolute]
|
|
94
|
+
)
|
|
95
|
+
const [minPercent, setMinPercent] = useState(() =>
|
|
96
|
+
percent(min.selected, min.absolute, max.absolute)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
const [maxPercent, setMaxPercent] = useState(() =>
|
|
100
|
+
percent(max.selected, min.absolute, max.absolute)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
const [minVal, setMinVal] = useState(() =>
|
|
104
|
+
Math.floor(min.absolute + minPercent * widthPercent)
|
|
105
|
+
)
|
|
106
|
+
const [maxVal, setMaxVal] = useState(() =>
|
|
107
|
+
Math.round(min.absolute + maxPercent * widthPercent)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
const percentage = (value: number) => (value / max.absolute) * 100
|
|
111
|
+
|
|
112
|
+
useImperativeHandle(ref, () => ({
|
|
113
|
+
setSliderValues: (values: { min: number; max: number }) => {
|
|
114
|
+
const sliderMinValue = Math.min(Number(values.min), maxVal)
|
|
115
|
+
setMinVal(sliderMinValue)
|
|
116
|
+
setMinPercent(percent(sliderMinValue, min.absolute, max.absolute))
|
|
117
|
+
|
|
118
|
+
if (values.max > max.absolute) {
|
|
119
|
+
setMaxVal(max.absolute)
|
|
120
|
+
setMaxPercent(percent(max.absolute, min.absolute, max.absolute))
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const sliderMaxValue = Math.max(Number(values.max), minVal)
|
|
125
|
+
setMaxVal(sliderMaxValue)
|
|
126
|
+
setMaxPercent(percent(sliderMaxValue, min.absolute, max.absolute))
|
|
127
|
+
},
|
|
128
|
+
}))
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<div data-fs-slider data-testid={testId}>
|
|
132
|
+
<div data-fs-slider-absolute-values>
|
|
133
|
+
<span>{absoluteValuesLabel.min}</span>
|
|
134
|
+
<span>{absoluteValuesLabel.max}</span>
|
|
135
|
+
</div>
|
|
136
|
+
<div data-fs-slider-wrapper>
|
|
137
|
+
<div
|
|
138
|
+
data-fs-slider-range
|
|
139
|
+
style={{
|
|
140
|
+
left: `${minPercent}%`,
|
|
141
|
+
width: `${maxPercent - minPercent}%`,
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
<input
|
|
145
|
+
type="range"
|
|
146
|
+
min={Math.floor(min.absolute)}
|
|
147
|
+
max={Math.round(max.absolute)}
|
|
148
|
+
value={minVal}
|
|
149
|
+
step={step}
|
|
150
|
+
onMouseUp={() => onEnd?.({ min: minVal, max: maxVal })}
|
|
151
|
+
onTouchEnd={() => onEnd?.({ min: minVal, max: maxVal })}
|
|
152
|
+
onChange={(event) => {
|
|
153
|
+
const minValue = Math.min(Number(event.target.value), maxVal)
|
|
154
|
+
|
|
155
|
+
setMinVal(minValue)
|
|
156
|
+
setMinPercent(percent(minValue, min.absolute, max.absolute))
|
|
157
|
+
onChange?.({ min: minValue, max: maxVal })
|
|
158
|
+
}}
|
|
159
|
+
data-fs-slider-thumb="left"
|
|
160
|
+
aria-valuemin={min.absolute}
|
|
161
|
+
aria-valuemax={max.absolute}
|
|
162
|
+
aria-valuenow={minVal}
|
|
163
|
+
aria-label={String(minVal)}
|
|
164
|
+
aria-labelledby={getAriaValueText?.(minVal, 'min')}
|
|
165
|
+
{...otherProps}
|
|
166
|
+
/>
|
|
167
|
+
{minValueLabelComponent && (
|
|
168
|
+
<span
|
|
169
|
+
data-fs-slider-value-label="min"
|
|
170
|
+
style={{
|
|
171
|
+
left: `calc(${percentage(minVal)}% + (${
|
|
172
|
+
8 - percentage(minVal) * 0.2
|
|
173
|
+
}px))`,
|
|
174
|
+
}}
|
|
175
|
+
>
|
|
176
|
+
{minValueLabelComponent(minVal)}
|
|
177
|
+
</span>
|
|
178
|
+
)}
|
|
179
|
+
|
|
180
|
+
<input
|
|
181
|
+
type="range"
|
|
182
|
+
min={Math.floor(min.absolute)}
|
|
183
|
+
max={Math.round(max.absolute)}
|
|
184
|
+
value={maxVal}
|
|
185
|
+
step={step}
|
|
186
|
+
onMouseUp={() => onEnd?.({ min: minVal, max: maxVal })}
|
|
187
|
+
onTouchEnd={() => onEnd?.({ min: minVal, max: maxVal })}
|
|
188
|
+
onChange={(event) => {
|
|
189
|
+
const maxValue = Math.max(Number(event.target.value), minVal)
|
|
190
|
+
|
|
191
|
+
setMaxVal(maxValue)
|
|
192
|
+
setMaxPercent(percent(maxValue, min.absolute, max.absolute))
|
|
193
|
+
onChange?.({ min: minVal, max: maxValue })
|
|
194
|
+
}}
|
|
195
|
+
data-fs-slider-thumb="right"
|
|
196
|
+
aria-valuemin={min.absolute}
|
|
197
|
+
aria-valuemax={max.absolute}
|
|
198
|
+
aria-valuenow={maxVal}
|
|
199
|
+
aria-label={String(maxVal)}
|
|
200
|
+
aria-labelledby={getAriaValueText?.(maxVal, 'max')}
|
|
201
|
+
/>
|
|
202
|
+
{maxValueLabelComponent && (
|
|
203
|
+
<span
|
|
204
|
+
data-fs-slider-value-label="max"
|
|
205
|
+
style={{
|
|
206
|
+
left: `calc(${percentage(maxVal)}% + (${
|
|
207
|
+
8 - percentage(maxVal) * 0.2
|
|
208
|
+
}px))`,
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
{maxValueLabelComponent(maxVal)}
|
|
212
|
+
</span>
|
|
213
|
+
)}
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
export default Slider
|
package/src/index.ts
CHANGED
|
@@ -16,6 +16,8 @@ export { default as Label } from './atoms/Label'
|
|
|
16
16
|
export type { LabelProps } from './atoms/Label'
|
|
17
17
|
export { default as Link } from './atoms/Link'
|
|
18
18
|
export type { LinkProps, LinkElementType } from './atoms/Link'
|
|
19
|
+
export { default as Loader } from './atoms/Loader'
|
|
20
|
+
export type { LoaderProps } from './atoms/Loader'
|
|
19
21
|
export { default as List } from './atoms/List'
|
|
20
22
|
export type { ListProps } from './atoms/List'
|
|
21
23
|
export { default as Overlay } from './atoms/Overlay'
|
|
@@ -26,6 +28,8 @@ export { default as Radio } from './atoms/Radio'
|
|
|
26
28
|
export type { RadioProps } from './atoms/Radio'
|
|
27
29
|
export { default as Select } from './atoms/Select'
|
|
28
30
|
export type { SelectProps } from './atoms/Select'
|
|
31
|
+
export { default as Slider } from './atoms/Slider'
|
|
32
|
+
export type { SliderProps } from './atoms/Slider'
|
|
29
33
|
export { default as SROnly } from './atoms/SROnly'
|
|
30
34
|
|
|
31
35
|
// Molecules
|
|
@@ -122,3 +126,6 @@ export type {
|
|
|
122
126
|
HeroImageProps,
|
|
123
127
|
HeroHeadingProps,
|
|
124
128
|
} from './organisms/Hero'
|
|
129
|
+
|
|
130
|
+
export { default as PriceRange } from './organisms/PriceRange'
|
|
131
|
+
export type { PriceRangeProps } from './organisms/PriceRange'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
|
-
import { Button
|
|
3
|
+
import { Button } from '../../index'
|
|
4
4
|
import type { ButtonProps } from '../../index'
|
|
5
5
|
import { ShoppingCart } from '../../assets'
|
|
6
6
|
|
|
@@ -13,8 +13,13 @@ function BuyButton({
|
|
|
13
13
|
...otherProps
|
|
14
14
|
}: BuyButtonProps) {
|
|
15
15
|
return (
|
|
16
|
-
<Button
|
|
17
|
-
|
|
16
|
+
<Button
|
|
17
|
+
data-fs-buy-button
|
|
18
|
+
icon={<ShoppingCart />}
|
|
19
|
+
iconPosition="left"
|
|
20
|
+
data-testid={testId}
|
|
21
|
+
{...otherProps}
|
|
22
|
+
>
|
|
18
23
|
{children}
|
|
19
24
|
</Button>
|
|
20
25
|
)
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import React, { useRef, useState, useImperativeHandle, forwardRef } from 'react'
|
|
2
|
+
import type { AriaAttributes } from 'react'
|
|
3
|
+
|
|
4
|
+
import { Price, Slider, InputField } from '../../index'
|
|
5
|
+
import type { PriceProps, SliderProps } from '../../index'
|
|
6
|
+
|
|
7
|
+
export type PriceRangeProps = Omit<SliderProps, 'absoluteValuesLabel'> & {
|
|
8
|
+
/**
|
|
9
|
+
* The current use case variant for prices.
|
|
10
|
+
*/
|
|
11
|
+
variant?: PriceProps['variant']
|
|
12
|
+
/**
|
|
13
|
+
* Formatter function that transforms the raw price value and render the result.
|
|
14
|
+
*/
|
|
15
|
+
formatter: PriceProps['formatter']
|
|
16
|
+
/**
|
|
17
|
+
* Defines a string value that labels the current element.
|
|
18
|
+
*/
|
|
19
|
+
'aria-label'?: AriaAttributes['aria-label']
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type PriceRangeRefType = {
|
|
23
|
+
setPriceRangeValues: (values: { min: number; max: number }) => void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const PriceRange = forwardRef<PriceRangeRefType | undefined, PriceRangeProps>(
|
|
27
|
+
function PriceRange(
|
|
28
|
+
{
|
|
29
|
+
formatter,
|
|
30
|
+
max,
|
|
31
|
+
min,
|
|
32
|
+
step = 1,
|
|
33
|
+
onChange,
|
|
34
|
+
onEnd,
|
|
35
|
+
testId = 'fs-price-range',
|
|
36
|
+
variant,
|
|
37
|
+
'aria-label': ariaLabel,
|
|
38
|
+
...otherProps
|
|
39
|
+
},
|
|
40
|
+
ref
|
|
41
|
+
) {
|
|
42
|
+
const sliderRef = useRef<{
|
|
43
|
+
setSliderValues: (values: { min: number; max: number }) => void
|
|
44
|
+
}>()
|
|
45
|
+
|
|
46
|
+
useImperativeHandle(ref, () => ({
|
|
47
|
+
setPriceRangeValues: (values: { min: number; max: number }) => {
|
|
48
|
+
onChange?.(values)
|
|
49
|
+
sliderRef.current?.setSliderValues(values)
|
|
50
|
+
},
|
|
51
|
+
}))
|
|
52
|
+
|
|
53
|
+
const inputMinRef = useRef<HTMLInputElement>(null)
|
|
54
|
+
const inputMaxRef = useRef<HTMLInputElement>(null)
|
|
55
|
+
|
|
56
|
+
const [inputMinError, setInputMinError] = useState<string>()
|
|
57
|
+
const [inputMaxError, setInputMaxError] = useState<string>()
|
|
58
|
+
const [priceRange, setPriceRange] = useState<{ min: number; max: number }>({
|
|
59
|
+
min: Math.floor(min.selected),
|
|
60
|
+
max: Math.round(max.selected),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
function onChangePriceRange(value: { min: number; max: number }) {
|
|
64
|
+
setInputMinError(undefined)
|
|
65
|
+
setInputMaxError(undefined)
|
|
66
|
+
setPriceRange({ min: value.min, max: value.max })
|
|
67
|
+
|
|
68
|
+
if (inputMinRef.current?.value) {
|
|
69
|
+
inputMinRef.current.value = String(value.min)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (inputMaxRef.current?.value) {
|
|
73
|
+
inputMaxRef.current.value = String(value.max)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function onChangeInputMin(value: string) {
|
|
78
|
+
setInputMinError(undefined)
|
|
79
|
+
|
|
80
|
+
if (Number(value) < Math.floor(min.absolute)) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (Number(value) > Math.floor(priceRange.max)) {
|
|
85
|
+
setInputMinError(`Min price can't be greater than max`)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setPriceRange({ ...priceRange, min: Number(value) })
|
|
89
|
+
sliderRef.current?.setSliderValues({
|
|
90
|
+
...priceRange,
|
|
91
|
+
min: Number(value),
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function onChangeInputMax(value: string) {
|
|
96
|
+
setInputMaxError(undefined)
|
|
97
|
+
|
|
98
|
+
if (Number(value) > Math.round(max.absolute)) {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (Number(value) < Math.round(priceRange.min)) {
|
|
103
|
+
setInputMaxError(`Max price can't be smaller than min`)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setPriceRange({ ...priceRange, max: Number(value) })
|
|
107
|
+
sliderRef.current?.setSliderValues({
|
|
108
|
+
...priceRange,
|
|
109
|
+
max: Number(value),
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div data-fs-price-range data-testid={testId} {...otherProps}>
|
|
115
|
+
<Slider
|
|
116
|
+
ref={sliderRef}
|
|
117
|
+
min={min}
|
|
118
|
+
max={max}
|
|
119
|
+
step={step}
|
|
120
|
+
onEnd={(value) => {
|
|
121
|
+
onEnd?.(value)
|
|
122
|
+
onChangePriceRange(value)
|
|
123
|
+
}}
|
|
124
|
+
aria-label={ariaLabel}
|
|
125
|
+
onChange={(value) => onChange?.(value)}
|
|
126
|
+
absoluteValuesLabel={{
|
|
127
|
+
min: (
|
|
128
|
+
<Price
|
|
129
|
+
value={Math.floor(min.absolute)}
|
|
130
|
+
variant={variant}
|
|
131
|
+
formatter={formatter}
|
|
132
|
+
/>
|
|
133
|
+
),
|
|
134
|
+
max: (
|
|
135
|
+
<Price
|
|
136
|
+
value={Math.round(max.absolute)}
|
|
137
|
+
variant={variant}
|
|
138
|
+
formatter={formatter}
|
|
139
|
+
/>
|
|
140
|
+
),
|
|
141
|
+
}}
|
|
142
|
+
minValueLabelComponent={(minValue) => {
|
|
143
|
+
return (
|
|
144
|
+
<Price value={minValue} variant={variant} formatter={formatter} />
|
|
145
|
+
)
|
|
146
|
+
}}
|
|
147
|
+
maxValueLabelComponent={(maxValue) => {
|
|
148
|
+
return (
|
|
149
|
+
<Price value={maxValue} variant={variant} formatter={formatter} />
|
|
150
|
+
)
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
<div data-fs-price-range-inputs>
|
|
154
|
+
<InputField
|
|
155
|
+
id="price-range-min"
|
|
156
|
+
step={step}
|
|
157
|
+
label="Min"
|
|
158
|
+
type="number"
|
|
159
|
+
inputMode="numeric"
|
|
160
|
+
error={inputMinError}
|
|
161
|
+
inputRef={inputMinRef}
|
|
162
|
+
min={Math.floor(min.absolute)}
|
|
163
|
+
max={priceRange.max}
|
|
164
|
+
value={priceRange.min}
|
|
165
|
+
onChange={(e) => onChangeInputMin(e.target.value)}
|
|
166
|
+
onBlur={() => !inputMinError && onEnd?.(priceRange)}
|
|
167
|
+
/>
|
|
168
|
+
<InputField
|
|
169
|
+
id="price-range-max"
|
|
170
|
+
label="Max"
|
|
171
|
+
step={step}
|
|
172
|
+
type="number"
|
|
173
|
+
inputMode="numeric"
|
|
174
|
+
error={inputMaxError}
|
|
175
|
+
inputRef={inputMaxRef}
|
|
176
|
+
max={Math.round(max.absolute)}
|
|
177
|
+
min={priceRange.min}
|
|
178
|
+
value={priceRange.max}
|
|
179
|
+
onChange={(e) => onChangeInputMax(e.target.value)}
|
|
180
|
+
onBlur={() => !inputMaxError && onEnd?.(priceRange)}
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
export default PriceRange
|