@faststore/components 2.0.43-alpha.0 → 2.0.47-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/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
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.47-alpha.0](https://github.com/vtex/faststore/compare/v2.0.46-alpha.0...v2.0.47-alpha.0) (2023-01-13)
7
+
8
+
9
+ ### Features
10
+
11
+ * Adds `QuantitySelector` component ([#1597](https://github.com/vtex/faststore/issues/1597)) ([a587155](https://github.com/vtex/faststore/commit/a5871559a4a28754dd9868b7f85c92a5bde52917))
12
+
13
+
14
+
15
+ ## [2.0.44-alpha.0](https://github.com/vtex/faststore/compare/v2.0.43-alpha.0...v2.0.44-alpha.0) (2023-01-11)
16
+
17
+ **Note:** Version bump only for package @faststore/components
18
+
19
+
20
+
21
+
22
+
6
23
  ## [2.0.43-alpha.0](https://github.com/vtex/faststore/compare/v2.0.42-alpha.0...v2.0.43-alpha.0) (2023-01-11)
7
24
 
8
25
 
@@ -0,0 +1,3 @@
1
+ import type { FC } from 'react';
2
+ declare const Minus: FC;
3
+ export default Minus;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ // Icon from Phosphor Icons
3
+ const Minus = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", viewBox: "0 0 256 256", strokeWidth: "24", width: 16, height: 16 },
4
+ React.createElement("rect", { width: "256", height: "256", fill: "none" }),
5
+ React.createElement("line", { x1: "40", y1: "128", x2: "216", y2: "128", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" })));
6
+ export default Minus;
7
+ //# sourceMappingURL=Minus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minus.js","sourceRoot":"","sources":["../../src/assets/Minus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,2BAA2B;AAC3B,MAAM,KAAK,GAAO,GAAG,EAAE,CAAC,CACtB,6BACE,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,cAAc,EACnB,OAAO,EAAC,aAAa,EACrB,WAAW,EAAC,IAAI,EAChB,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE;IAEV,8BAAM,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAQ;IAClD,8BACE,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,KAAK,EACR,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GAChB,CACJ,CACP,CAAA;AAED,eAAe,KAAK,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { FC } from 'react';
2
+ declare const Plus: FC;
3
+ export default Plus;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ // Icon from Phosphor Icons
3
+ const Plus = () => (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", viewBox: "0 0 256 256", strokeWidth: "24", width: 16, height: 16 },
4
+ React.createElement("rect", { width: "256", height: "256", fill: "none" }),
5
+ React.createElement("line", { x1: "40", y1: "128", x2: "216", y2: "128", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" }),
6
+ React.createElement("line", { x1: "128", y1: "40", x2: "128", y2: "216", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" })));
7
+ export default Plus;
8
+ //# sourceMappingURL=Plus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plus.js","sourceRoot":"","sources":["../../src/assets/Plus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,2BAA2B;AAC3B,MAAM,IAAI,GAAO,GAAG,EAAE,CAAC,CACrB,6BACE,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,cAAc,EACnB,OAAO,EAAC,aAAa,EACrB,WAAW,EAAC,IAAI,EAChB,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE;IAEV,8BAAM,KAAK,EAAC,KAAK,EAAC,MAAM,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,GAAQ;IAClD,8BACE,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,KAAK,EACR,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GAChB;IACR,8BACE,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,KAAK,EACR,EAAE,EAAC,KAAK,EACR,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GAChB,CACJ,CACP,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -3,6 +3,8 @@ export { default as ArrowElbowDownRight } from './ArrowElbowDownRight';
3
3
  export { default as CaretDown } from './CaretDown';
4
4
  export { default as Checked } from './Checked';
5
5
  export { default as House } from './House';
6
+ export { default as Minus } from './Minus';
7
+ export { default as Plus } from './Plus';
6
8
  export { default as MinusCircle } from './MinusCircle';
7
9
  export { default as PlusCircle } from './PlusCircle';
8
10
  export { default as Ruler } from './Ruler';
@@ -3,6 +3,8 @@ export { default as ArrowElbowDownRight } from './ArrowElbowDownRight';
3
3
  export { default as CaretDown } from './CaretDown';
4
4
  export { default as Checked } from './Checked';
5
5
  export { default as House } from './House';
6
+ export { default as Minus } from './Minus';
7
+ export { default as Plus } from './Plus';
6
8
  export { default as MinusCircle } from './MinusCircle';
7
9
  export { default as PlusCircle } from './PlusCircle';
8
10
  export { default as Ruler } from './Ruler';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,MAAM,KAAK,CAAA;AAClC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAA;AAC1C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,MAAM,KAAK,CAAA;AAClC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.d.ts CHANGED
@@ -51,5 +51,7 @@ export { default as Toggle } from './molecules/Toggle';
51
51
  export type { ToggleProps } from './molecules/Toggle';
52
52
  export { default as ToggleField } from './molecules/ToggleField';
53
53
  export type { ToggleFieldProps } from './molecules/ToggleField';
54
+ export { default as QuantitySelector } from './molecules/QuantitySelector';
55
+ export type { QuantitySelectorProps } from './molecules/QuantitySelector';
54
56
  export { default as Hero, HeroImage, HeroHeading } from './organisms/Hero';
55
57
  export type { HeroProps, HeroImageProps, HeroHeadingProps, } from './organisms/Hero';
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ export { Table, TableBody, TableCell, TableFooter, TableHead, TableRow, } from '
29
29
  export { default as Tag } from './molecules/Tag';
30
30
  export { default as Toggle } from './molecules/Toggle';
31
31
  export { default as ToggleField } from './molecules/ToggleField';
32
+ export { default as QuantitySelector } from './molecules/QuantitySelector';
32
33
  // Organisms
33
34
  export { default as Hero, HeroImage, HeroHeading } from './organisms/Hero';
34
35
  //# 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,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,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,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;AAGhE,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":"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,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,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,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"}
@@ -0,0 +1,31 @@
1
+ /// <reference types="react" />
2
+ export interface QuantitySelectorProps {
3
+ /**
4
+ * ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
5
+ *
6
+ * @default 'fs-quantity-selector'
7
+ */
8
+ testId?: string;
9
+ /**
10
+ * The maximum value the quantity selector can receive
11
+ */
12
+ max?: number;
13
+ /**
14
+ * The minimum value the quantity selector can receive
15
+ */
16
+ min?: number;
17
+ /**
18
+ * The initial value for quantity selector
19
+ */
20
+ initial?: number;
21
+ /**
22
+ * Specifies that the whole quantity selector component should be disabled.
23
+ */
24
+ disabled?: boolean;
25
+ /**
26
+ * Event emitted when value is changed
27
+ */
28
+ onChange?: (value: number) => void;
29
+ }
30
+ declare const QuantitySelector: ({ max, min, initial, disabled, onChange, testId, ...otherProps }: QuantitySelectorProps) => JSX.Element;
31
+ export default QuantitySelector;
@@ -0,0 +1,38 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { IconButton, Input } from '../../index';
3
+ import { Minus, Plus } from '../../assets';
4
+ const QuantitySelector = ({ max, min = 1, initial, disabled = false, onChange, testId = 'fs-quantity-selector', ...otherProps }) => {
5
+ const [quantity, setQuantity] = useState(initial ?? min);
6
+ const isLeftDisabled = quantity === min;
7
+ const isRightDisabled = quantity === max;
8
+ const changeQuantity = (increaseValue) => {
9
+ const quantityValue = validateQuantityBounds(quantity + increaseValue);
10
+ onChange?.(quantityValue);
11
+ setQuantity(quantityValue);
12
+ };
13
+ const increase = () => changeQuantity(1);
14
+ const decrease = () => changeQuantity(-1);
15
+ function validateQuantityBounds(n) {
16
+ const maxValue = min ? Math.max(n, min) : n;
17
+ return max ? Math.min(maxValue, max) : maxValue;
18
+ }
19
+ function validateInput(e) {
20
+ const val = e.currentTarget.value;
21
+ if (!Number.isNaN(Number(val))) {
22
+ setQuantity(() => {
23
+ const quantityValue = validateQuantityBounds(Number(val));
24
+ onChange?.(quantityValue);
25
+ return quantityValue;
26
+ });
27
+ }
28
+ }
29
+ useEffect(() => {
30
+ initial && setQuantity(initial);
31
+ }, [initial]);
32
+ return (React.createElement("div", { "data-fs-quantity-selector": disabled ? 'disabled' : 'true', "data-testid": testId, ...otherProps },
33
+ React.createElement(IconButton, { "data-quantity-selector-button": "left", icon: React.createElement(Minus, null), "aria-label": "Decrement Quantity", "aria-controls": "quantity-selector-input", disabled: isLeftDisabled || disabled, onClick: decrease, testId: `${testId}-left-button` }),
34
+ React.createElement(Input, { "data-quantity-selector-input": true, id: "quantity-selector-input", "aria-label": "Quantity", value: quantity, onChange: validateInput, disabled: disabled }),
35
+ React.createElement(IconButton, { "data-quantity-selector-button": "right", "aria-controls": "quantity-selector-input", "aria-label": "Increment Quantity", disabled: isRightDisabled || disabled, icon: React.createElement(Plus, null), onClick: increase, testId: `${testId}-right-button` })));
36
+ };
37
+ export default QuantitySelector;
38
+ //# sourceMappingURL=QuantitySelector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuantitySelector.js","sourceRoot":"","sources":["../../../src/molecules/QuantitySelector/QuantitySelector.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { default } from './QuantitySelector';
2
+ export type { QuantitySelectorProps } from './QuantitySelector';
@@ -0,0 +1,2 @@
1
+ export { default } from './QuantitySelector';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/molecules/QuantitySelector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/components",
3
- "version": "2.0.43-alpha.0",
3
+ "version": "2.0.47-alpha.0",
4
4
  "module": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "author": "Emerson Laurentino @emersonlaurentino",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "devDependencies": {
24
24
  "@faststore/eslint-config": "^2.0.37-alpha.0",
25
- "@faststore/shared": "^2.0.37-alpha.0",
25
+ "@faststore/shared": "^2.0.44-alpha.0",
26
26
  "eslint": "7.32.0",
27
27
  "typescript": "^4.8.4"
28
28
  },
@@ -30,5 +30,5 @@
30
30
  "node": "16.18.0",
31
31
  "yarn": "1.19.1"
32
32
  },
33
- "gitHead": "40e830f6cae1423c5a9296fe123b0c5df1e1f42c"
33
+ "gitHead": "3e7e16180416349dc8471b69ad9e305fd2f4d424"
34
34
  }
@@ -0,0 +1,28 @@
1
+ import React from 'react'
2
+ import type { FC } from 'react'
3
+
4
+ // Icon from Phosphor Icons
5
+ const Minus: FC = () => (
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 256 256"
10
+ strokeWidth="24"
11
+ width={16}
12
+ height={16}
13
+ >
14
+ <rect width="256" height="256" fill="none"></rect>
15
+ <line
16
+ x1="40"
17
+ y1="128"
18
+ x2="216"
19
+ y2="128"
20
+ fill="none"
21
+ stroke="currentColor"
22
+ strokeLinecap="round"
23
+ strokeLinejoin="round"
24
+ ></line>
25
+ </svg>
26
+ )
27
+
28
+ export default Minus
@@ -0,0 +1,38 @@
1
+ import React from 'react'
2
+ import type { FC } from 'react'
3
+
4
+ // Icon from Phosphor Icons
5
+ const Plus: FC = () => (
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ fill="currentColor"
9
+ viewBox="0 0 256 256"
10
+ strokeWidth="24"
11
+ width={16}
12
+ height={16}
13
+ >
14
+ <rect width="256" height="256" fill="none"></rect>
15
+ <line
16
+ x1="40"
17
+ y1="128"
18
+ x2="216"
19
+ y2="128"
20
+ fill="none"
21
+ stroke="currentColor"
22
+ strokeLinecap="round"
23
+ strokeLinejoin="round"
24
+ ></line>
25
+ <line
26
+ x1="128"
27
+ y1="40"
28
+ x2="128"
29
+ y2="216"
30
+ fill="none"
31
+ stroke="currentColor"
32
+ strokeLinecap="round"
33
+ strokeLinejoin="round"
34
+ ></line>
35
+ </svg>
36
+ )
37
+
38
+ export default Plus
@@ -3,6 +3,8 @@ export { default as ArrowElbowDownRight } from './ArrowElbowDownRight'
3
3
  export { default as CaretDown } from './CaretDown'
4
4
  export { default as Checked } from './Checked'
5
5
  export { default as House } from './House'
6
+ export { default as Minus } from './Minus'
7
+ export { default as Plus } from './Plus'
6
8
  export { default as MinusCircle } from './MinusCircle'
7
9
  export { default as PlusCircle } from './PlusCircle'
8
10
  export { default as Ruler } from './Ruler'
package/src/index.ts CHANGED
@@ -90,6 +90,8 @@ export { default as Toggle } from './molecules/Toggle'
90
90
  export type { ToggleProps } from './molecules/Toggle'
91
91
  export { default as ToggleField } from './molecules/ToggleField'
92
92
  export type { ToggleFieldProps } from './molecules/ToggleField'
93
+ export { default as QuantitySelector } from './molecules/QuantitySelector'
94
+ export type { QuantitySelectorProps } from './molecules/QuantitySelector'
93
95
 
94
96
  // Organisms
95
97
  export { default as Hero, HeroImage, HeroHeading } from './organisms/Hero'
@@ -0,0 +1,120 @@
1
+ import React, { useState, useEffect } from 'react'
2
+
3
+ import { IconButton, Input } from '../../index'
4
+ import { Minus, Plus } from '../../assets'
5
+
6
+ export interface QuantitySelectorProps {
7
+ /**
8
+ * ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
9
+ *
10
+ * @default 'fs-quantity-selector'
11
+ */
12
+ testId?: string
13
+ /**
14
+ * The maximum value the quantity selector can receive
15
+ */
16
+ max?: number
17
+ /**
18
+ * The minimum value the quantity selector can receive
19
+ */
20
+ min?: number
21
+ /**
22
+ * The initial value for quantity selector
23
+ */
24
+ initial?: number
25
+ /**
26
+ * Specifies that the whole quantity selector component should be disabled.
27
+ */
28
+ disabled?: boolean
29
+ /**
30
+ * Event emitted when value is changed
31
+ */
32
+ onChange?: (value: number) => void
33
+ }
34
+
35
+ const QuantitySelector = ({
36
+ max,
37
+ min = 1,
38
+ initial,
39
+ disabled = false,
40
+ onChange,
41
+ testId = 'fs-quantity-selector',
42
+ ...otherProps
43
+ }: QuantitySelectorProps) => {
44
+ const [quantity, setQuantity] = useState<number>(initial ?? min)
45
+
46
+ const isLeftDisabled = quantity === min
47
+ const isRightDisabled = quantity === max
48
+
49
+ const changeQuantity = (increaseValue: number) => {
50
+ const quantityValue = validateQuantityBounds(quantity + increaseValue)
51
+
52
+ onChange?.(quantityValue)
53
+ setQuantity(quantityValue)
54
+ }
55
+
56
+ const increase = () => changeQuantity(1)
57
+
58
+ const decrease = () => changeQuantity(-1)
59
+
60
+ function validateQuantityBounds(n: number): number {
61
+ const maxValue = min ? Math.max(n, min) : n
62
+
63
+ return max ? Math.min(maxValue, max) : maxValue
64
+ }
65
+
66
+ function validateInput(e: React.FormEvent<HTMLInputElement>) {
67
+ const val = e.currentTarget.value
68
+
69
+ if (!Number.isNaN(Number(val))) {
70
+ setQuantity(() => {
71
+ const quantityValue = validateQuantityBounds(Number(val))
72
+
73
+ onChange?.(quantityValue)
74
+
75
+ return quantityValue
76
+ })
77
+ }
78
+ }
79
+
80
+ useEffect(() => {
81
+ initial && setQuantity(initial)
82
+ }, [initial])
83
+
84
+ return (
85
+ <div
86
+ data-fs-quantity-selector={disabled ? 'disabled' : 'true'}
87
+ data-testid={testId}
88
+ {...otherProps}
89
+ >
90
+ <IconButton
91
+ data-quantity-selector-button="left"
92
+ icon={<Minus />}
93
+ aria-label="Decrement Quantity"
94
+ aria-controls="quantity-selector-input"
95
+ disabled={isLeftDisabled || disabled}
96
+ onClick={decrease}
97
+ testId={`${testId}-left-button`}
98
+ />
99
+ <Input
100
+ data-quantity-selector-input
101
+ id="quantity-selector-input"
102
+ aria-label="Quantity"
103
+ value={quantity}
104
+ onChange={validateInput}
105
+ disabled={disabled}
106
+ />
107
+ <IconButton
108
+ data-quantity-selector-button="right"
109
+ aria-controls="quantity-selector-input"
110
+ aria-label="Increment Quantity"
111
+ disabled={isRightDisabled || disabled}
112
+ icon={<Plus />}
113
+ onClick={increase}
114
+ testId={`${testId}-right-button`}
115
+ />
116
+ </div>
117
+ )
118
+ }
119
+
120
+ export default QuantitySelector
@@ -0,0 +1,2 @@
1
+ export { default } from './QuantitySelector'
2
+ export type { QuantitySelectorProps } from './QuantitySelector'