@talixo-ds/options-input 1.0.3 → 1.0.5
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/LICENSE.md +1 -1
- package/dist/components/min-max-value-label.js.map +1 -1
- package/dist/components/options-input-content-item.d.ts +2 -1
- package/dist/components/options-input-content-item.js +7 -2
- package/dist/components/options-input-content-item.js.map +1 -1
- package/dist/components/options-input-dropdown-item.d.ts +2 -1
- package/dist/components/options-input-dropdown-item.js +11 -3
- package/dist/components/options-input-dropdown-item.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/options-input.d.ts +6 -1
- package/dist/options-input.js +47 -23
- package/dist/options-input.js.map +1 -1
- package/dist/styles.scss +52 -52
- package/dist/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/options-input.spec.tsx +21 -5
- package/src/components/__tests__/options-input-content-item.spec.tsx +3 -1
- package/src/components/__tests__/options-input-dropdown-item.spec.tsx +47 -1
- package/src/components/min-max-value-label.tsx +5 -1
- package/src/components/options-input-content-item.tsx +19 -4
- package/src/components/options-input-dropdown-item.tsx +30 -12
- package/src/index.ts +2 -2
- package/src/options-input.tsx +102 -25
- package/src/styles.scss +52 -52
- package/src/types.ts +9 -9
- package/src/utils.ts +2 -1
- package/tsconfig.build.json +7 -7
package/LICENSE.md
CHANGED
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"min-max-value-label.js","sourceRoot":"","sources":["../../src/components/min-max-value-label.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,EAAE,EAAwB,MAAM,0BAA0B,CAAC;AAQ5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"min-max-value-label.js","sourceRoot":"","sources":["../../src/components/min-max-value-label.tsx"],"names":[],"mappings":";AAAA,OAAO,UAAU,EAAE,EAAwB,MAAM,0BAA0B,CAAC;AAQ5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAChC,GAAG,EACH,GAAG,EACH,KAAK,EACkB,EAAE,EAAE,CAAC,CAC5B,MAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,aACvD,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,GAAG,EAAE,EAC3C,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,EAChE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,GAAG,EAAE,IAChC,CACb,CAAC"}
|
|
@@ -3,6 +3,7 @@ export type OptionsInputContentItemProps = {
|
|
|
3
3
|
item: OptionsInputOption;
|
|
4
4
|
disabled?: boolean;
|
|
5
5
|
displayMinMax?: boolean;
|
|
6
|
+
error?: boolean;
|
|
6
7
|
};
|
|
7
|
-
declare const OptionsInputContentItem: ({ item: { quantity, details, label, max, min, icon }, displayMinMax, disabled }: OptionsInputContentItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare const OptionsInputContentItem: ({ item: { quantity, details, label, max, min, icon }, displayMinMax, disabled, error }: OptionsInputContentItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
9
|
export default OptionsInputContentItem;
|
|
@@ -5,9 +5,14 @@ import Typography from "@mui/material/Typography";
|
|
|
5
5
|
import * as DesignSystemIcons from "@talixo-ds/icons";
|
|
6
6
|
import { MinMaxValueLabel } from "./min-max-value-label";
|
|
7
7
|
import { capitalize } from "../utils";
|
|
8
|
-
|
|
8
|
+
import { red } from "@mui/material/colors";
|
|
9
|
+
import { useMemo } from "react";
|
|
10
|
+
const OptionsInputContentItem = ({ item: { quantity, details, label, max, min, icon }, displayMinMax = false, disabled = false, error = false }) => {
|
|
9
11
|
const Icon = DesignSystemIcons[capitalize(icon)] || null;
|
|
10
|
-
const itemsColor =
|
|
12
|
+
const itemsColor = useMemo(() => {
|
|
13
|
+
const defaultItemColor = quantity === 0 || disabled ? "#a4a5b2" : "#000000";
|
|
14
|
+
return error ? red[700] : defaultItemColor;
|
|
15
|
+
}, [error, quantity, disabled]);
|
|
11
16
|
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: 0.5, color: itemsColor, "data-testid": "option-item", children: [label ? (_jsx(Tooltip, { title: _jsxs(Box, { display: "flex", flexDirection: "column", children: [_jsx(Typography, { variant: "caption", fontWeight: 600, sx: { my: 0 }, children: label }), details && (_jsx(Typography, { variant: "caption", sx: { my: 0 }, children: details })), displayMinMax && _jsx(MinMaxValueLabel, { min: min, max: max })] }), placement: "top", arrow: true, children: _jsx("span", { children: _jsx(Icon, { fontSize: "medium", sx: { color: itemsColor } }) }) })) : (_jsx(Icon, { fontSize: "medium", sx: { color: itemsColor } })), _jsx(Typography, { variant: "h6", color: itemsColor, children: quantity })] }));
|
|
12
17
|
};
|
|
13
18
|
export default OptionsInputContentItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options-input-content-item.js","sourceRoot":"","sources":["../../src/components/options-input-content-item.tsx"],"names":[],"mappings":";AAAA,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,KAAK,iBAAiB,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"options-input-content-item.js","sourceRoot":"","sources":["../../src/components/options-input-content-item.tsx"],"names":[],"mappings":";AAAA,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,KAAK,iBAAiB,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAShC,MAAM,uBAAuB,GAAG,CAAC,EAChC,IAAI,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAClD,aAAa,GAAG,KAAK,EACrB,QAAQ,GAAG,KAAK,EAChB,KAAK,GAAG,KAAK,EACiB,EAAE,EAAE;IAClC,MAAM,IAAI,GACT,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAmC,CAAC,IAAI,IAAI,CAAC;IAC/E,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,MAAM,gBAAgB,GAAG,QAAQ,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5E,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAC5C,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEhC,OAAO,CACN,MAAC,GAAG,IACH,OAAO,EAAC,MAAM,EACd,UAAU,EAAC,QAAQ,EACnB,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,UAAU,iBACL,aAAa,aAExB,KAAK,CAAC,CAAC,CAAC,CACR,KAAC,OAAO,IACP,KAAK,EACJ,MAAC,GAAG,IAAC,OAAO,EAAC,MAAM,EAAC,aAAa,EAAC,QAAQ,aACzC,KAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,UAAU,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,YAC1D,KAAK,GACM,EACZ,OAAO,IAAI,CACX,KAAC,UAAU,IAAC,OAAO,EAAC,SAAS,EAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,YACzC,OAAO,GACI,CACb,EACA,aAAa,IAAI,KAAC,gBAAgB,IAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAI,IACrD,EAEP,SAAS,EAAC,KAAK,EACf,KAAK,kBAEL,yBACC,KAAC,IAAI,IAAC,QAAQ,EAAC,QAAQ,EAAC,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,GAAI,GAC/C,GACE,CACV,CAAC,CAAC,CAAC,CACH,KAAC,IAAI,IAAC,QAAQ,EAAC,QAAQ,EAAC,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,GAAI,CACrD,EACD,KAAC,UAAU,IAAC,OAAO,EAAC,IAAI,EAAC,KAAK,EAAE,UAAU,YACxC,QAAQ,GACG,IACR,CACN,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -6,6 +6,7 @@ export type OptionsInputDropdownItemProps = {
|
|
|
6
6
|
onChange: (id: string, value: number | string) => void;
|
|
7
7
|
index: number;
|
|
8
8
|
displayMinMax?: boolean;
|
|
9
|
+
error?: boolean;
|
|
9
10
|
};
|
|
10
|
-
declare const OptionsInputDropdownItem: ({ item: { id, quantity, label, max, min, icon, details, inputQuantity }, onChange, onBlur, index, displayMinMax }: OptionsInputDropdownItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare const OptionsInputDropdownItem: ({ item: { id, quantity, label, max, min, icon, details, inputQuantity }, onChange, onBlur, index, displayMinMax, error }: OptionsInputDropdownItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
12
|
export default OptionsInputDropdownItem;
|
|
@@ -13,10 +13,18 @@ import RemoveIcon from "@mui/icons-material/Remove";
|
|
|
13
13
|
import * as DesignSystemIcons from "@talixo-ds/icons";
|
|
14
14
|
import { MinMaxValueLabel } from "./min-max-value-label";
|
|
15
15
|
import { capitalize } from "../utils";
|
|
16
|
-
const OptionsInputDropdownItem = ({ item: { id, quantity = 0, label, max, min, icon, details, inputQuantity }, onChange, onBlur, index, displayMinMax }) => {
|
|
16
|
+
const OptionsInputDropdownItem = ({ item: { id, quantity = 0, label, max, min, icon, details, inputQuantity }, onChange, onBlur, index, displayMinMax, error = false }) => {
|
|
17
17
|
const [shouldDisplayFullDetails, setShouldDisplayFullDetails] = useState(false);
|
|
18
18
|
const Icon = DesignSystemIcons[capitalize(icon)] || null;
|
|
19
|
-
|
|
19
|
+
const onIncrement = (inputId) => () => {
|
|
20
|
+
const isValueBelowMin = !!(min && quantity < min);
|
|
21
|
+
onChange(inputId, (isValueBelowMin ? min : quantity + 1));
|
|
22
|
+
};
|
|
23
|
+
const onDecrement = (inputId) => () => {
|
|
24
|
+
const isValueAboveMax = !!(max && quantity > max);
|
|
25
|
+
return onChange(inputId, (isValueAboveMax ? max : quantity - 1));
|
|
26
|
+
};
|
|
27
|
+
return (_jsxs(_Fragment, { children: [!!index && (_jsx(Divider, { sx: { color: (theme) => theme.palette.primary.main } })), _jsxs(ListItem, { sx: {
|
|
20
28
|
display: "flex",
|
|
21
29
|
justifyContent: "space-between"
|
|
22
30
|
}, className: classNames("options-input__dropdown-item", {
|
|
@@ -40,7 +48,7 @@ const OptionsInputDropdownItem = ({ item: { id, quantity = 0, label, max, min, i
|
|
|
40
48
|
})
|
|
41
49
|
}, "data-testid": "option-details", children: details?.length <= 15 || shouldDisplayFullDetails
|
|
42
50
|
? details
|
|
43
|
-
: `${details?.slice(0, 15)}...` }) })), displayMinMax && _jsx(MinMaxValueLabel, { min: min, max: max, color: "gray" })] })] }), _jsxs(ButtonGroup, { variant: "outlined", size: "small", className: "options-input__dropdown-item-buttons", children: [_jsx(Button, { onClick: ()
|
|
51
|
+
: `${details?.slice(0, 15)}...` }) })), displayMinMax && _jsx(MinMaxValueLabel, { min: min, max: max, color: "gray" })] })] }), _jsxs(ButtonGroup, { variant: "outlined", size: "small", className: "options-input__dropdown-item-buttons", children: [_jsx(Button, { onClick: onIncrement(id), disabled: !!(max && quantity && quantity >= max), className: "options-input__dropdown-item-button", role: "button", color: error ? "error" : "primary", children: _jsx(AddIcon, { sx: { color: error ? "black" : "primary" } }) }), _jsx(Button, { onClick: onDecrement(id), disabled: !!(quantity && min) && quantity <= min, className: "options-input__dropdown-item-button", role: "button", color: error ? "error" : "primary", children: _jsx(RemoveIcon, { sx: { color: error ? "black" : "primary" } }) })] })] })] }));
|
|
44
52
|
};
|
|
45
53
|
export default OptionsInputDropdownItem;
|
|
46
54
|
//# sourceMappingURL=options-input-dropdown-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options-input-dropdown-item.js","sourceRoot":"","sources":["../../src/components/options-input-dropdown-item.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,SAAS,MAAM,yBAAyB,CAAC;AAChD,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,UAAU,MAAM,4BAA4B,CAAC;AACpD,OAAO,KAAK,iBAAiB,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"options-input-dropdown-item.js","sourceRoot":"","sources":["../../src/components/options-input-dropdown-item.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,SAAS,MAAM,yBAAyB,CAAC;AAChD,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,OAAO,MAAM,yBAAyB,CAAC;AAC9C,OAAO,UAAU,MAAM,4BAA4B,CAAC;AACpD,OAAO,KAAK,iBAAiB,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAYtC,MAAM,wBAAwB,GAAG,CAAC,EACjC,IAAI,EAAE,EAAE,EAAE,EAAE,QAAQ,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,EACzE,QAAQ,EACR,MAAM,EACN,KAAK,EACL,aAAa,EACb,KAAK,GAAG,KAAK,EACkB,EAAE,EAAE;IACnC,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,GAC5D,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC1B,MAAM,IAAI,GACT,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAmC,CAAC,IAAI,IAAI,CAAC;IAE/E,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,EAAE;QAC7C,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,GAAG,GAAG,CAAC,CAAC;QAElD,QAAQ,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAE,CAAC,CAAC;IAC5D,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,EAAE;QAC7C,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,GAAG,GAAG,CAAC,CAAC;QAElD,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAE,CAAC,CAAC;IACnE,CAAC,CAAC;IAEF,OAAO,CACN,8BACE,CAAC,CAAC,KAAK,IAAI,CACX,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAI,CACjE,EACD,MAAC,QAAQ,IACR,EAAE,EAAE;oBACH,OAAO,EAAE,MAAM;oBACf,cAAc,EAAE,eAAe;iBAC/B,EACD,SAAS,EAAE,UAAU,CAAC,8BAA8B,EAAE;oBACrD,qCAAqC,EAAE,CAAC,QAAQ;iBAChD,CAAC,aAEF,MAAC,GAAG,IAAC,OAAO,EAAC,MAAM,EAAC,UAAU,EAAC,QAAQ,aACtC,KAAC,IAAI,IAAC,QAAQ,EAAC,OAAO,EAAC,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAI,EACjD,KAAC,SAAS,IACT,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,EACpD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,aAAa,EACpB,OAAO,EAAC,UAAU,EAClB,UAAU,EAAE;oCACX,SAAS,EAAE,SAAS;oCACpB,OAAO,EAAE,UAAU;oCACnB,KAAK,EAAE;wCACN,SAAS,EAAE,QAAQ;qCACnB;oCACD,aAAa,EAAE,qBAAqB;iCACpC;gCACD,wDAAwD;gCACxD,UAAU,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,EACtC,SAAS,EAAC,oCAAoC,GAC7C,EACF,MAAC,GAAG,IACH,OAAO,EAAC,MAAM,EACd,aAAa,EAAC,QAAQ,EACtB,cAAc,EAAC,QAAQ,EACvB,YAAY,EAAE,CAAC,EACf,WAAW,EAAE,CAAC,EACd,QAAQ,EAAC,MAAM,aAEf,KAAC,UAAU,IACV,OAAO,EAAC,SAAS,EACjB,UAAU,EAAE,GAAG,EACf,QAAQ,EAAE,EAAE,EACZ,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EACb,KAAK,EAAC,OAAO,YAEZ,KAAK,IAAI,EAAE,GACA,EACZ,OAAO,IAAI,CACX,KAAC,GAAG,IACH,QAAQ,EAAC,UAAU,EACnB,MAAM,EAAC,MAAM,iBACD,0BAA0B,EACtC,YAAY,EAAE,GAAG,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC,EACrD,YAAY,EAAE,GAAG,EAAE,CAAC,2BAA2B,CAAC,KAAK,CAAC,YAEtD,KAAC,UAAU,IACV,OAAO,EAAC,SAAS,EACjB,KAAK,EAAC,MAAM,EACZ,EAAE,EAAE;gDACH,EAAE,EAAE,CAAC;gDACL,MAAM,EAAE,KAAK;gDACb,QAAQ,EAAE,OAAO;gDACjB,GAAG,CAAC,wBAAwB,IAAI;oDAC/B,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;oDACjD,MAAM,EAAE,oBAAoB;iDAC5B,CAAC;6CACF,iBACW,gBAAgB,YAE3B,OAAO,EAAE,MAAM,IAAI,EAAE,IAAI,wBAAwB;gDACjD,CAAC,CAAC,OAAO;gDACT,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,GACpB,GACR,CACN,EACA,aAAa,IAAI,KAAC,gBAAgB,IAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAC,MAAM,GAAG,IAClE,IACD,EACN,MAAC,WAAW,IACX,OAAO,EAAC,UAAU,EAClB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,sCAAsC,aAEhD,KAAC,MAAM,IACN,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,EACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,IAAI,QAAQ,IAAI,GAAG,CAAC,EAChD,SAAS,EAAC,qCAAqC,EAC/C,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,YAElC,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,GAAI,GAC/C,EACT,KAAC,MAAM,IACN,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,EACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,QAAQ,IAAI,GAAG,EAChD,SAAS,EAAC,qCAAqC,EAC/C,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,YAElC,KAAC,UAAU,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,GAAI,GAClD,IACI,IACJ,IACT,CACH,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { OptionsInput } from
|
|
2
|
-
export type { OptionsInputProps } from
|
|
1
|
+
export { OptionsInput } from "./options-input";
|
|
2
|
+
export type { OptionsInputProps } from "./options-input";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { OptionsInput } from
|
|
1
|
+
export { OptionsInput } from "./options-input";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/options-input.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
1
2
|
import type { SxProps } from "@mui/material";
|
|
2
3
|
import type { OptionsInputOption, OptionsInputValue } from "./types";
|
|
3
4
|
import "./styles.scss";
|
|
@@ -32,5 +33,9 @@ export type OptionsInputProps = {
|
|
|
32
33
|
itemsGap?: string | number;
|
|
33
34
|
/** Custom styles for container */
|
|
34
35
|
containerSx?: SxProps;
|
|
36
|
+
/** Flag indicating if there is an validation error */
|
|
37
|
+
error?: boolean;
|
|
38
|
+
/** Additional content displayed with small font under the input */
|
|
39
|
+
helperText?: ReactNode;
|
|
35
40
|
};
|
|
36
|
-
export declare const OptionsInput: ({ options, onChange, onFocus, onBlur, persistentOptions, defaultValue, displayMinMax, disabled, readOnly, id, className, itemsGap, containerSx, ...rest }: OptionsInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
export declare const OptionsInput: ({ options, onChange, onFocus, onBlur, persistentOptions, defaultValue, displayMinMax, disabled, readOnly, id, className, itemsGap, containerSx, error, helperText, ...rest }: OptionsInputProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/options-input.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import React, { useState, useEffect, useCallback } from "react";
|
|
2
|
+
import React, { useState, useEffect, useCallback, useMemo, useRef } from "react";
|
|
3
3
|
import classNames from "classnames";
|
|
4
4
|
import Box from "@mui/material/Box";
|
|
5
5
|
import List from "@mui/material/List";
|
|
@@ -10,31 +10,44 @@ import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
|
|
10
10
|
import * as DesignSystemIcons from "@talixo-ds/icons";
|
|
11
11
|
import OptionsInputContentItem from "./components/options-input-content-item";
|
|
12
12
|
import OptionsInputDropdownItem from "./components/options-input-dropdown-item";
|
|
13
|
+
import { red } from "@mui/material/colors";
|
|
13
14
|
import "./styles.scss";
|
|
14
15
|
import "@emotion/react";
|
|
15
16
|
import "@emotion/styled";
|
|
16
17
|
import { capitalize } from "./utils";
|
|
17
|
-
export const OptionsInput = ({ options, onChange, onFocus, onBlur, persistentOptions = [], defaultValue, displayMinMax = false, disabled = false, readOnly = false, id, className, itemsGap = 1, containerSx = [], ...rest }) => {
|
|
18
|
+
export const OptionsInput = ({ options, onChange, onFocus, onBlur, persistentOptions = [], defaultValue, displayMinMax = false, disabled = false, readOnly = false, id, className, itemsGap = 1, containerSx = [], error = false, helperText, ...rest }) => {
|
|
18
19
|
const [currentOptions, setCurrentOptions] = useState([]);
|
|
20
|
+
const [inputContainerWidth, setInputContainerWidth] = useState(0);
|
|
21
|
+
const inputContainerRef = useRef();
|
|
19
22
|
const [anchorEl, setAnchorEl] = useState();
|
|
20
23
|
const open = !!anchorEl;
|
|
21
24
|
useEffect(() => setCurrentOptions(options.map((option) => {
|
|
22
|
-
const
|
|
23
|
-
const minQuantity = typeof option?.min === "number" && defaultQuantity < option.min
|
|
24
|
-
? option.min
|
|
25
|
-
: defaultQuantity;
|
|
26
|
-
const quantity = typeof option?.max === "number" && minQuantity > option.max ? option.max : minQuantity;
|
|
25
|
+
const quantity = defaultValue?.[option.id] ?? 0;
|
|
27
26
|
return {
|
|
28
27
|
...option,
|
|
29
28
|
quantity,
|
|
30
29
|
inputQuantity: quantity
|
|
31
30
|
};
|
|
32
31
|
})), [options, defaultValue]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
setInputContainerWidth(inputContainerRef?.current?.clientWidth ?? 0);
|
|
34
|
+
}, [inputContainerRef?.current?.clientWidth]);
|
|
35
|
+
const optionsExceedingBoundaries = useMemo(() => currentOptions.reduce((exceedingOptions, { quantity, id, label }) => {
|
|
36
|
+
const option = options.find((option) => option.id === id);
|
|
37
|
+
if (label &&
|
|
38
|
+
quantity !== undefined &&
|
|
39
|
+
((option?.max !== undefined && option?.max < quantity) ||
|
|
40
|
+
(option?.min !== undefined && option?.min > quantity))) {
|
|
41
|
+
return [...exceedingOptions, label];
|
|
42
|
+
}
|
|
43
|
+
return exceedingOptions;
|
|
44
|
+
}, []), [currentOptions, options]);
|
|
45
|
+
const isError = useMemo(() => error || !!optionsExceedingBoundaries.length, [error, optionsExceedingBoundaries]);
|
|
33
46
|
const toggleInput = useCallback((event) => {
|
|
34
47
|
const { currentTarget } = event;
|
|
35
48
|
if (!disabled && !readOnly) {
|
|
36
49
|
setTimeout(() => {
|
|
37
|
-
setAnchorEl((currentAnchor) =>
|
|
50
|
+
setAnchorEl((currentAnchor) => currentAnchor ? undefined : currentTarget);
|
|
38
51
|
}, 0);
|
|
39
52
|
}
|
|
40
53
|
}, [disabled, readOnly, setAnchorEl]);
|
|
@@ -57,11 +70,11 @@ export const OptionsInput = ({ options, onChange, onFocus, onBlur, persistentOpt
|
|
|
57
70
|
const onValueChange = (optionId, newValue) => {
|
|
58
71
|
const newQuantity = Number.isNaN(Number(newValue)) ? 0 : Number(newValue);
|
|
59
72
|
const newCurrentOptions = currentOptions.map((option) => {
|
|
60
|
-
const maxQuantity = newQuantity > (option
|
|
73
|
+
const maxQuantity = newQuantity > (option?.max ?? Infinity) ? option?.max : newQuantity;
|
|
61
74
|
return {
|
|
62
75
|
...option,
|
|
63
76
|
...(optionId === option.id && {
|
|
64
|
-
quantity: newQuantity < (option
|
|
77
|
+
quantity: newQuantity < (option?.min ?? -Infinity) ? option?.min : maxQuantity,
|
|
65
78
|
inputQuantity: newValue
|
|
66
79
|
})
|
|
67
80
|
};
|
|
@@ -77,38 +90,49 @@ export const OptionsInput = ({ options, onChange, onFocus, onBlur, persistentOpt
|
|
|
77
90
|
const onDropdownItemBlur = (optionId) => () => setCurrentOptions(currentOptions.map((option) => {
|
|
78
91
|
if (optionId !== option.id)
|
|
79
92
|
return option;
|
|
80
|
-
const finalQuantity = Number.isNaN(Number(option
|
|
93
|
+
const finalQuantity = Number.isNaN(Number(option?.inputQuantity))
|
|
81
94
|
? 0
|
|
82
|
-
: Number(option
|
|
83
|
-
const maxQuantity = finalQuantity > (option
|
|
95
|
+
: Number(option?.inputQuantity);
|
|
96
|
+
const maxQuantity = finalQuantity > (option?.max ?? Infinity) ? option?.max : finalQuantity;
|
|
84
97
|
return {
|
|
85
98
|
...option,
|
|
86
|
-
inputQuantity: finalQuantity < (option
|
|
99
|
+
inputQuantity: finalQuantity < (option?.min ?? -Infinity) ? option?.min : maxQuantity
|
|
87
100
|
};
|
|
88
101
|
}));
|
|
89
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Box, { id: id, onClick: toggleInput, onBlur: onInputBlur, onFocus: onInputFocus, className: classNames("options-input__container", {
|
|
102
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Box, { id: id, onClick: toggleInput, onBlur: onInputBlur, onFocus: onInputFocus, ref: inputContainerRef, className: classNames("options-input__container", className, {
|
|
90
103
|
"options-input__container--open": open,
|
|
91
104
|
"options-input__container--disabled": disabled,
|
|
92
105
|
"options-input__container--read-only": readOnly,
|
|
93
|
-
|
|
106
|
+
"options-input__container--error": isError
|
|
94
107
|
}), sx: [
|
|
95
108
|
{ "&:hover": { borderColor: "#d3d3d3" } },
|
|
96
109
|
...(Array.isArray(containerSx) ? containerSx : [containerSx]),
|
|
97
110
|
open && {
|
|
98
111
|
borderColor: (theme) => theme.palette.primary.main,
|
|
99
112
|
"&:hover": { borderColor: (theme) => theme.palette.primary.main }
|
|
113
|
+
},
|
|
114
|
+
isError && {
|
|
115
|
+
borderColor: red[700],
|
|
116
|
+
"&:hover": { borderColor: red[700] }
|
|
100
117
|
}
|
|
101
118
|
], "data-testid": rest["data-testid"] || "options-input-container", tabIndex: 0, children: [_jsx(Box, { display: "flex", gap: itemsGap, children: currentOptions
|
|
102
119
|
.filter(({ quantity, id: optionId, icon }) => !!(DesignSystemIcons[capitalize(icon)] &&
|
|
103
|
-
(quantity !== 0 || persistentOptions
|
|
104
|
-
.map((option) => (_jsx(OptionsInputContentItem, { item: option, disabled: disabled, displayMinMax: displayMinMax }, option.id))) }), !readOnly &&
|
|
105
|
-
(open ? (_jsx(KeyboardArrowUpIcon, { color: "primary" })) : (_jsx(KeyboardArrowDownIcon, { sx: {
|
|
106
|
-
color: (theme) =>
|
|
107
|
-
} })))] }),
|
|
120
|
+
(quantity !== 0 || persistentOptions?.includes(optionId))))
|
|
121
|
+
.map((option) => (_jsx(OptionsInputContentItem, { item: option, disabled: disabled, displayMinMax: displayMinMax, error: !!(option?.label && optionsExceedingBoundaries.includes(option.label)) }, option.id))) }), !readOnly &&
|
|
122
|
+
(open ? (_jsx(KeyboardArrowUpIcon, { sx: { color: isError ? red[700] : "primary" } })) : (_jsx(KeyboardArrowDownIcon, { sx: {
|
|
123
|
+
color: (theme) => disabled ? theme.palette.grey[400] : theme.palette.action.focus
|
|
124
|
+
} })))] }), (helperText || isError) && (_jsx(Box, { sx: {
|
|
125
|
+
...(isError ? { color: red[700] } : {})
|
|
126
|
+
}, marginTop: 1, marginLeft: 2, width: inputContainerWidth, fontSize: "small", children: optionsExceedingBoundaries.length
|
|
127
|
+
? (() => {
|
|
128
|
+
const messagePluralForm = optionsExceedingBoundaries.length > 1 ? "s" : "";
|
|
129
|
+
return `Value${messagePluralForm} for ${optionsExceedingBoundaries.join(", ")} option${messagePluralForm} ${messagePluralForm ? "are" : "is"} out of range.`;
|
|
130
|
+
})()
|
|
131
|
+
: helperText })), _jsx(ClickAwayListener, { onClickAway: () => open && setAnchorEl(undefined), children: _jsx(Popper, { open: open, placement: "bottom-start", anchorEl: anchorEl, sx: (theme) => ({ zIndex: theme.zIndex.modal }), children: _jsx(List, { disablePadding: true, "data-testid": "options-dropdown-list", className: "options-input__dropdown-items-list", sx: {
|
|
108
132
|
bgcolor: "Background",
|
|
109
|
-
border: (theme) => `thin solid ${theme.palette.primary.main}`
|
|
133
|
+
border: (theme) => `thin solid ${isError ? red[700] : theme.palette.primary.main}`
|
|
110
134
|
}, children: currentOptions
|
|
111
135
|
.filter(({ icon }) => !!DesignSystemIcons[capitalize(icon)])
|
|
112
|
-
.map((option, index) => (_jsx(OptionsInputDropdownItem, { item: option, onBlur: onDropdownItemBlur(option.id), onChange: onValueChange, index: index, displayMinMax: displayMinMax }, option.id))) }) }) })] }));
|
|
136
|
+
.map((option, index) => (_jsx(OptionsInputDropdownItem, { item: option, onBlur: onDropdownItemBlur(option.id), onChange: onValueChange, index: index, displayMinMax: displayMinMax, error: isError }, option.id))) }) }) })] }));
|
|
113
137
|
};
|
|
114
138
|
//# sourceMappingURL=options-input.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options-input.js","sourceRoot":"","sources":["../src/options-input.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"options-input.js","sourceRoot":"","sources":["../src/options-input.tsx"],"names":[],"mappings":"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"}
|
package/dist/styles.scss
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
1
|
.options-input {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
2
|
+
&__container {
|
|
3
|
+
border: thin solid transparent;
|
|
4
|
+
border-radius: 0.25rem;
|
|
5
|
+
display: flex;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
align-items: center;
|
|
8
|
+
padding: 0.25rem;
|
|
9
|
+
gap: 1rem;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
width: fit-content;
|
|
12
|
+
|
|
13
|
+
&--open {
|
|
14
|
+
border-bottom-width: 0;
|
|
15
|
+
border-bottom-left-radius: 0;
|
|
16
|
+
border-bottom-right-radius: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&--disabled {
|
|
20
|
+
cursor: unset;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&--read-only {
|
|
24
|
+
cursor: unset;
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
border-color: transparent;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&__dropdown-item {
|
|
33
|
+
gap: 1rem;
|
|
34
|
+
|
|
35
|
+
&--empty {
|
|
36
|
+
background-color: #eeeeee;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&__dropdown-item-input {
|
|
41
|
+
width: 2rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&__dropdown-item-buttons {
|
|
45
|
+
& > button[role="button"] {
|
|
46
|
+
min-width: 2rem;
|
|
47
|
+
padding: 0;
|
|
48
|
+
|
|
49
|
+
&[disabled] > svg {
|
|
50
|
+
color: #0000001f;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
54
|
}
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CACzC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talixo-ds/options-input",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"publishConfig": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"test": "vitest"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@talixo-ds/icons": "^1.0.
|
|
14
|
+
"@talixo-ds/icons": "^1.0.3"
|
|
15
15
|
},
|
|
16
|
-
"gitHead": "
|
|
16
|
+
"gitHead": "857e6fabaeeaec85a3180c66fe89545f74cabc96"
|
|
17
17
|
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
render,
|
|
3
|
+
screen,
|
|
4
|
+
fireEvent,
|
|
5
|
+
waitFor,
|
|
6
|
+
act
|
|
7
|
+
} from "@testing-library/react";
|
|
2
8
|
import { OptionsInput } from "../options-input";
|
|
3
9
|
|
|
4
10
|
const props = {
|
|
@@ -36,6 +42,14 @@ const props = {
|
|
|
36
42
|
};
|
|
37
43
|
|
|
38
44
|
describe("OptionsInput", () => {
|
|
45
|
+
it("should display invalid value error message for items with invalid value", () => {
|
|
46
|
+
const { queryByText } = render(<OptionsInput {...props} />);
|
|
47
|
+
|
|
48
|
+
expect(
|
|
49
|
+
queryByText("Value for sport equipment option is out of range.")
|
|
50
|
+
).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
|
|
39
53
|
describe("events", () => {
|
|
40
54
|
it("should open input dropdown properly", async () => {
|
|
41
55
|
const { getAllByTestId } = render(<OptionsInput {...props} />);
|
|
@@ -60,7 +74,9 @@ describe("OptionsInput", () => {
|
|
|
60
74
|
});
|
|
61
75
|
|
|
62
76
|
await waitFor(() => {
|
|
63
|
-
expect(
|
|
77
|
+
expect(
|
|
78
|
+
screen.queryByTestId("options-dropdown-list")
|
|
79
|
+
).not.toBeInTheDocument();
|
|
64
80
|
});
|
|
65
81
|
});
|
|
66
82
|
|
|
@@ -76,7 +92,7 @@ describe("OptionsInput", () => {
|
|
|
76
92
|
expect(props.onFocus).toHaveBeenCalledWith({
|
|
77
93
|
dog: 0,
|
|
78
94
|
luggage: 2,
|
|
79
|
-
"sport-equipment":
|
|
95
|
+
"sport-equipment": 5
|
|
80
96
|
});
|
|
81
97
|
});
|
|
82
98
|
|
|
@@ -92,7 +108,7 @@ describe("OptionsInput", () => {
|
|
|
92
108
|
expect(props.onBlur).toHaveBeenCalledWith({
|
|
93
109
|
dog: 0,
|
|
94
110
|
luggage: 2,
|
|
95
|
-
"sport-equipment":
|
|
111
|
+
"sport-equipment": 5
|
|
96
112
|
});
|
|
97
113
|
});
|
|
98
114
|
|
|
@@ -114,7 +130,7 @@ describe("OptionsInput", () => {
|
|
|
114
130
|
expect(props.onChange).toHaveBeenCalledWith({
|
|
115
131
|
dog: 0,
|
|
116
132
|
luggage: 9,
|
|
117
|
-
"sport-equipment":
|
|
133
|
+
"sport-equipment": 5
|
|
118
134
|
});
|
|
119
135
|
|
|
120
136
|
expect(screen.getAllByTestId("option-item")[0]).toHaveTextContent("9");
|
|
@@ -38,7 +38,9 @@ describe("OptionsInputDropdownItem", () => {
|
|
|
38
38
|
|
|
39
39
|
it("should not render tooltip when there is no label", async () => {
|
|
40
40
|
const { queryByTestId, queryByText, getByTestId } = render(
|
|
41
|
-
<OptionsInputContentItem
|
|
41
|
+
<OptionsInputContentItem
|
|
42
|
+
item={{ ...props.item, label: undefined, quantity: 1 }}
|
|
43
|
+
/>
|
|
42
44
|
);
|
|
43
45
|
|
|
44
46
|
expect(queryByTestId("LuggageIcon")).toBeInTheDocument();
|
|
@@ -55,6 +55,28 @@ describe("OptionsInputDropdownItem", () => {
|
|
|
55
55
|
expect(onChangeMock).toHaveBeenCalledWith("luggage-id", 1);
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
+
it("should call onChange on increment button click when value is below min", () => {
|
|
59
|
+
const { getAllByRole } = render(
|
|
60
|
+
<OptionsInputDropdownItem
|
|
61
|
+
{...{
|
|
62
|
+
...props,
|
|
63
|
+
item: {
|
|
64
|
+
...props.item,
|
|
65
|
+
quantity: -20,
|
|
66
|
+
inputQuantity: -20
|
|
67
|
+
}
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const buttons = getAllByRole("button");
|
|
73
|
+
|
|
74
|
+
fireEvent.click(buttons[0]!);
|
|
75
|
+
|
|
76
|
+
expect(onChangeMock).toHaveBeenCalledTimes(1);
|
|
77
|
+
expect(onChangeMock).toHaveBeenCalledWith("luggage-id", -10);
|
|
78
|
+
});
|
|
79
|
+
|
|
58
80
|
it("should call onChange on decrement button click", () => {
|
|
59
81
|
const { getAllByRole } = render(<OptionsInputDropdownItem {...props} />);
|
|
60
82
|
|
|
@@ -66,10 +88,34 @@ describe("OptionsInputDropdownItem", () => {
|
|
|
66
88
|
expect(onChangeMock).toHaveBeenCalledWith("luggage-id", -1);
|
|
67
89
|
});
|
|
68
90
|
|
|
91
|
+
it("should call onChange on decrement button click when value is above max", () => {
|
|
92
|
+
const { getAllByRole } = render(
|
|
93
|
+
<OptionsInputDropdownItem
|
|
94
|
+
{...{
|
|
95
|
+
...props,
|
|
96
|
+
item: {
|
|
97
|
+
...props.item,
|
|
98
|
+
quantity: 20,
|
|
99
|
+
inputQuantity: 20
|
|
100
|
+
}
|
|
101
|
+
}}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const buttons = getAllByRole("button");
|
|
106
|
+
|
|
107
|
+
fireEvent.click(buttons[1]!);
|
|
108
|
+
|
|
109
|
+
expect(onChangeMock).toHaveBeenCalledTimes(1);
|
|
110
|
+
expect(onChangeMock).toHaveBeenCalledWith("luggage-id", 10);
|
|
111
|
+
});
|
|
112
|
+
|
|
69
113
|
it("should expand details content", () => {
|
|
70
114
|
const { getByTestId } = render(<OptionsInputDropdownItem {...props} />);
|
|
71
115
|
|
|
72
|
-
expect(getByTestId("option-details")).toHaveTextContent(
|
|
116
|
+
expect(getByTestId("option-details")).toHaveTextContent(
|
|
117
|
+
props.item.details.slice(0, 15)
|
|
118
|
+
);
|
|
73
119
|
|
|
74
120
|
const optionDetailsContainer = getByTestId("option-details-container");
|
|
75
121
|
|
|
@@ -6,7 +6,11 @@ export type MinMaxValueLabelProps = {
|
|
|
6
6
|
color?: TypographyProps["color"];
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
export const MinMaxValueLabel = ({
|
|
9
|
+
export const MinMaxValueLabel = ({
|
|
10
|
+
min,
|
|
11
|
+
max,
|
|
12
|
+
color
|
|
13
|
+
}: MinMaxValueLabelProps) => (
|
|
10
14
|
<Typography variant="caption" color={color} sx={{ my: 0 }}>
|
|
11
15
|
{!Number.isNaN(Number(min)) && `min: ${min}`}
|
|
12
16
|
{!Number.isNaN(Number(max)) && !Number.isNaN(Number(min)) && ", "}
|
|
@@ -5,23 +5,38 @@ import * as DesignSystemIcons from "@talixo-ds/icons";
|
|
|
5
5
|
import { MinMaxValueLabel } from "./min-max-value-label";
|
|
6
6
|
import { capitalize } from "../utils";
|
|
7
7
|
import type { OptionsInputOption } from "../types";
|
|
8
|
+
import { red } from "@mui/material/colors";
|
|
9
|
+
import { useMemo } from "react";
|
|
8
10
|
|
|
9
11
|
export type OptionsInputContentItemProps = {
|
|
10
12
|
item: OptionsInputOption;
|
|
11
13
|
disabled?: boolean;
|
|
12
14
|
displayMinMax?: boolean;
|
|
15
|
+
error?: boolean;
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
const OptionsInputContentItem = ({
|
|
16
19
|
item: { quantity, details, label, max, min, icon },
|
|
17
20
|
displayMinMax = false,
|
|
18
|
-
disabled = false
|
|
21
|
+
disabled = false,
|
|
22
|
+
error = false
|
|
19
23
|
}: OptionsInputContentItemProps) => {
|
|
20
|
-
const Icon =
|
|
21
|
-
|
|
24
|
+
const Icon =
|
|
25
|
+
DesignSystemIcons[capitalize(icon) as keyof typeof DesignSystemIcons] || null;
|
|
26
|
+
const itemsColor = useMemo(() => {
|
|
27
|
+
const defaultItemColor = quantity === 0 || disabled ? "#a4a5b2" : "#000000";
|
|
28
|
+
|
|
29
|
+
return error ? red[700] : defaultItemColor;
|
|
30
|
+
}, [error, quantity, disabled]);
|
|
22
31
|
|
|
23
32
|
return (
|
|
24
|
-
<Box
|
|
33
|
+
<Box
|
|
34
|
+
display="flex"
|
|
35
|
+
alignItems="center"
|
|
36
|
+
gap={0.5}
|
|
37
|
+
color={itemsColor}
|
|
38
|
+
data-testid="option-item"
|
|
39
|
+
>
|
|
25
40
|
{label ? (
|
|
26
41
|
<Tooltip
|
|
27
42
|
title={
|
|
@@ -20,6 +20,7 @@ export type OptionsInputDropdownItemProps = {
|
|
|
20
20
|
onChange: (id: string, value: number | string) => void;
|
|
21
21
|
index: number;
|
|
22
22
|
displayMinMax?: boolean;
|
|
23
|
+
error?: boolean;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
const OptionsInputDropdownItem = ({
|
|
@@ -27,14 +28,31 @@ const OptionsInputDropdownItem = ({
|
|
|
27
28
|
onChange,
|
|
28
29
|
onBlur,
|
|
29
30
|
index,
|
|
30
|
-
displayMinMax
|
|
31
|
+
displayMinMax,
|
|
32
|
+
error = false
|
|
31
33
|
}: OptionsInputDropdownItemProps) => {
|
|
32
|
-
const [shouldDisplayFullDetails, setShouldDisplayFullDetails] =
|
|
33
|
-
|
|
34
|
+
const [shouldDisplayFullDetails, setShouldDisplayFullDetails] =
|
|
35
|
+
useState<boolean>(false);
|
|
36
|
+
const Icon =
|
|
37
|
+
DesignSystemIcons[capitalize(icon) as keyof typeof DesignSystemIcons] || null;
|
|
38
|
+
|
|
39
|
+
const onIncrement = (inputId: string) => () => {
|
|
40
|
+
const isValueBelowMin = !!(min && quantity < min);
|
|
41
|
+
|
|
42
|
+
onChange(inputId, (isValueBelowMin ? min : quantity + 1)!);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const onDecrement = (inputId: string) => () => {
|
|
46
|
+
const isValueAboveMax = !!(max && quantity > max);
|
|
47
|
+
|
|
48
|
+
return onChange(inputId, (isValueAboveMax ? max : quantity - 1)!);
|
|
49
|
+
};
|
|
34
50
|
|
|
35
51
|
return (
|
|
36
52
|
<>
|
|
37
|
-
{!!index &&
|
|
53
|
+
{!!index && (
|
|
54
|
+
<Divider sx={{ color: (theme) => theme.palette.primary.main }} />
|
|
55
|
+
)}
|
|
38
56
|
<ListItem
|
|
39
57
|
sx={{
|
|
40
58
|
display: "flex",
|
|
@@ -117,22 +135,22 @@ const OptionsInputDropdownItem = ({
|
|
|
117
135
|
className="options-input__dropdown-item-buttons"
|
|
118
136
|
>
|
|
119
137
|
<Button
|
|
120
|
-
onClick={(
|
|
121
|
-
disabled={quantity
|
|
138
|
+
onClick={onIncrement(id)}
|
|
139
|
+
disabled={!!(max && quantity && quantity >= max)}
|
|
122
140
|
className="options-input__dropdown-item-button"
|
|
123
141
|
role="button"
|
|
124
|
-
color="primary"
|
|
142
|
+
color={error ? "error" : "primary"}
|
|
125
143
|
>
|
|
126
|
-
<AddIcon sx={{ color: "primary" }} />
|
|
144
|
+
<AddIcon sx={{ color: error ? "black" : "primary" }} />
|
|
127
145
|
</Button>
|
|
128
146
|
<Button
|
|
129
|
-
onClick={(
|
|
130
|
-
disabled={quantity
|
|
147
|
+
onClick={onDecrement(id)}
|
|
148
|
+
disabled={!!(quantity && min) && quantity <= min}
|
|
131
149
|
className="options-input__dropdown-item-button"
|
|
132
150
|
role="button"
|
|
133
|
-
color="primary"
|
|
151
|
+
color={error ? "error" : "primary"}
|
|
134
152
|
>
|
|
135
|
-
<RemoveIcon sx={{ color: "primary" }} />
|
|
153
|
+
<RemoveIcon sx={{ color: error ? "black" : "primary" }} />
|
|
136
154
|
</Button>
|
|
137
155
|
</ButtonGroup>
|
|
138
156
|
</ListItem>
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { OptionsInput } from
|
|
2
|
-
export type { OptionsInputProps } from
|
|
1
|
+
export { OptionsInput } from "./options-input";
|
|
2
|
+
export type { OptionsInputProps } from "./options-input";
|
package/src/options-input.tsx
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useState,
|
|
3
|
+
useEffect,
|
|
4
|
+
useCallback,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef
|
|
8
|
+
} from "react";
|
|
2
9
|
import classNames from "classnames";
|
|
3
10
|
import Box from "@mui/material/Box";
|
|
4
11
|
import List from "@mui/material/List";
|
|
@@ -11,6 +18,7 @@ import type { SxProps } from "@mui/material";
|
|
|
11
18
|
import type { OptionsInputOption, OptionsInputValue } from "./types";
|
|
12
19
|
import OptionsInputContentItem from "./components/options-input-content-item";
|
|
13
20
|
import OptionsInputDropdownItem from "./components/options-input-dropdown-item";
|
|
21
|
+
import { red } from "@mui/material/colors";
|
|
14
22
|
import "./styles.scss";
|
|
15
23
|
|
|
16
24
|
import "@emotion/react";
|
|
@@ -46,6 +54,10 @@ export type OptionsInputProps = {
|
|
|
46
54
|
itemsGap?: string | number;
|
|
47
55
|
/** Custom styles for container */
|
|
48
56
|
containerSx?: SxProps;
|
|
57
|
+
/** Flag indicating if there is an validation error */
|
|
58
|
+
error?: boolean;
|
|
59
|
+
/** Additional content displayed with small font under the input */
|
|
60
|
+
helperText?: ReactNode;
|
|
49
61
|
};
|
|
50
62
|
|
|
51
63
|
export const OptionsInput = ({
|
|
@@ -62,9 +74,13 @@ export const OptionsInput = ({
|
|
|
62
74
|
className,
|
|
63
75
|
itemsGap = 1,
|
|
64
76
|
containerSx = [],
|
|
77
|
+
error = false,
|
|
78
|
+
helperText,
|
|
65
79
|
...rest
|
|
66
80
|
}: OptionsInputProps) => {
|
|
67
81
|
const [currentOptions, setCurrentOptions] = useState<OptionsInputOption[]>([]);
|
|
82
|
+
const [inputContainerWidth, setInputContainerWidth] = useState(0);
|
|
83
|
+
const inputContainerRef = useRef<HTMLElement>();
|
|
68
84
|
const [anchorEl, setAnchorEl] = useState<undefined | HTMLElement>();
|
|
69
85
|
const open = !!anchorEl;
|
|
70
86
|
|
|
@@ -72,13 +88,7 @@ export const OptionsInput = ({
|
|
|
72
88
|
() =>
|
|
73
89
|
setCurrentOptions(
|
|
74
90
|
options.map((option) => {
|
|
75
|
-
const
|
|
76
|
-
const minQuantity =
|
|
77
|
-
typeof option?.min === "number" && defaultQuantity < option.min
|
|
78
|
-
? option.min
|
|
79
|
-
: defaultQuantity;
|
|
80
|
-
const quantity =
|
|
81
|
-
typeof option?.max === "number" && minQuantity > option.max ? option.max : minQuantity;
|
|
91
|
+
const quantity = defaultValue?.[option.id] ?? 0;
|
|
82
92
|
|
|
83
93
|
return {
|
|
84
94
|
...option,
|
|
@@ -90,13 +100,43 @@ export const OptionsInput = ({
|
|
|
90
100
|
[options, defaultValue]
|
|
91
101
|
);
|
|
92
102
|
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
setInputContainerWidth(inputContainerRef?.current?.clientWidth ?? 0);
|
|
105
|
+
}, [inputContainerRef?.current?.clientWidth]);
|
|
106
|
+
|
|
107
|
+
const optionsExceedingBoundaries = useMemo(
|
|
108
|
+
() =>
|
|
109
|
+
currentOptions.reduce((exceedingOptions, { quantity, id, label }) => {
|
|
110
|
+
const option = options.find((option) => option.id === id);
|
|
111
|
+
|
|
112
|
+
if (
|
|
113
|
+
label &&
|
|
114
|
+
quantity !== undefined &&
|
|
115
|
+
((option?.max !== undefined && option?.max < quantity) ||
|
|
116
|
+
(option?.min !== undefined && option?.min > quantity))
|
|
117
|
+
) {
|
|
118
|
+
return [...exceedingOptions, label];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return exceedingOptions;
|
|
122
|
+
}, [] as string[]),
|
|
123
|
+
[currentOptions, options]
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const isError = useMemo(
|
|
127
|
+
() => error || !!optionsExceedingBoundaries.length,
|
|
128
|
+
[error, optionsExceedingBoundaries]
|
|
129
|
+
);
|
|
130
|
+
|
|
93
131
|
const toggleInput = useCallback(
|
|
94
132
|
(event: React.MouseEvent<HTMLElement>) => {
|
|
95
133
|
const { currentTarget } = event;
|
|
96
134
|
|
|
97
135
|
if (!disabled && !readOnly) {
|
|
98
136
|
setTimeout(() => {
|
|
99
|
-
setAnchorEl((currentAnchor) =>
|
|
137
|
+
setAnchorEl((currentAnchor) =>
|
|
138
|
+
currentAnchor ? undefined : currentTarget
|
|
139
|
+
);
|
|
100
140
|
}, 0);
|
|
101
141
|
}
|
|
102
142
|
},
|
|
@@ -112,7 +152,7 @@ export const OptionsInput = ({
|
|
|
112
152
|
[currentOption.id]: currentOption.quantity
|
|
113
153
|
}),
|
|
114
154
|
{}
|
|
115
|
-
)
|
|
155
|
+
) as OptionsInputValue
|
|
116
156
|
);
|
|
117
157
|
}
|
|
118
158
|
};
|
|
@@ -126,7 +166,7 @@ export const OptionsInput = ({
|
|
|
126
166
|
[currentOption.id]: currentOption.quantity
|
|
127
167
|
}),
|
|
128
168
|
{}
|
|
129
|
-
)
|
|
169
|
+
) as OptionsInputValue
|
|
130
170
|
);
|
|
131
171
|
}
|
|
132
172
|
};
|
|
@@ -135,12 +175,14 @@ export const OptionsInput = ({
|
|
|
135
175
|
const newQuantity = Number.isNaN(Number(newValue)) ? 0 : Number(newValue);
|
|
136
176
|
|
|
137
177
|
const newCurrentOptions = currentOptions.map((option) => {
|
|
138
|
-
const maxQuantity =
|
|
178
|
+
const maxQuantity =
|
|
179
|
+
newQuantity > (option?.max ?? Infinity) ? option?.max : newQuantity;
|
|
139
180
|
|
|
140
181
|
return {
|
|
141
182
|
...option,
|
|
142
183
|
...(optionId === option.id && {
|
|
143
|
-
quantity:
|
|
184
|
+
quantity:
|
|
185
|
+
newQuantity < (option?.min ?? -Infinity) ? option?.min : maxQuantity,
|
|
144
186
|
inputQuantity: newValue
|
|
145
187
|
})
|
|
146
188
|
};
|
|
@@ -154,7 +196,7 @@ export const OptionsInput = ({
|
|
|
154
196
|
[currentOption.id]: currentOption.quantity
|
|
155
197
|
}),
|
|
156
198
|
{}
|
|
157
|
-
)
|
|
199
|
+
) as OptionsInputValue
|
|
158
200
|
);
|
|
159
201
|
}
|
|
160
202
|
|
|
@@ -166,14 +208,16 @@ export const OptionsInput = ({
|
|
|
166
208
|
currentOptions.map((option) => {
|
|
167
209
|
if (optionId !== option.id) return option;
|
|
168
210
|
|
|
169
|
-
const finalQuantity = Number.isNaN(Number(option
|
|
211
|
+
const finalQuantity = Number.isNaN(Number(option?.inputQuantity))
|
|
170
212
|
? 0
|
|
171
|
-
: Number(option
|
|
172
|
-
const maxQuantity =
|
|
213
|
+
: Number(option?.inputQuantity);
|
|
214
|
+
const maxQuantity =
|
|
215
|
+
finalQuantity > (option?.max ?? Infinity) ? option?.max : finalQuantity;
|
|
173
216
|
|
|
174
217
|
return {
|
|
175
218
|
...option,
|
|
176
|
-
inputQuantity:
|
|
219
|
+
inputQuantity:
|
|
220
|
+
finalQuantity < (option?.min ?? -Infinity) ? option?.min : maxQuantity
|
|
177
221
|
};
|
|
178
222
|
})
|
|
179
223
|
);
|
|
@@ -185,11 +229,12 @@ export const OptionsInput = ({
|
|
|
185
229
|
onClick={toggleInput}
|
|
186
230
|
onBlur={onInputBlur}
|
|
187
231
|
onFocus={onInputFocus}
|
|
188
|
-
|
|
232
|
+
ref={inputContainerRef}
|
|
233
|
+
className={classNames("options-input__container", className, {
|
|
189
234
|
"options-input__container--open": open,
|
|
190
235
|
"options-input__container--disabled": disabled,
|
|
191
236
|
"options-input__container--read-only": readOnly,
|
|
192
|
-
|
|
237
|
+
"options-input__container--error": isError
|
|
193
238
|
})}
|
|
194
239
|
sx={[
|
|
195
240
|
{ "&:hover": { borderColor: "#d3d3d3" } },
|
|
@@ -197,6 +242,10 @@ export const OptionsInput = ({
|
|
|
197
242
|
open && {
|
|
198
243
|
borderColor: (theme) => theme.palette.primary.main,
|
|
199
244
|
"&:hover": { borderColor: (theme) => theme.palette.primary.main }
|
|
245
|
+
},
|
|
246
|
+
isError && {
|
|
247
|
+
borderColor: red[700],
|
|
248
|
+
"&:hover": { borderColor: red[700] }
|
|
200
249
|
}
|
|
201
250
|
]}
|
|
202
251
|
data-testid={rest["data-testid"] || "options-input-container"}
|
|
@@ -207,8 +256,10 @@ export const OptionsInput = ({
|
|
|
207
256
|
.filter(
|
|
208
257
|
({ quantity, id: optionId, icon }) =>
|
|
209
258
|
!!(
|
|
210
|
-
DesignSystemIcons[
|
|
211
|
-
|
|
259
|
+
DesignSystemIcons[
|
|
260
|
+
capitalize(icon) as keyof typeof DesignSystemIcons
|
|
261
|
+
] &&
|
|
262
|
+
(quantity !== 0 || persistentOptions?.includes(optionId))
|
|
212
263
|
)
|
|
213
264
|
)
|
|
214
265
|
.map((option) => (
|
|
@@ -217,20 +268,44 @@ export const OptionsInput = ({
|
|
|
217
268
|
item={option}
|
|
218
269
|
disabled={disabled}
|
|
219
270
|
displayMinMax={displayMinMax}
|
|
271
|
+
error={
|
|
272
|
+
!!(option?.label && optionsExceedingBoundaries.includes(option.label))
|
|
273
|
+
}
|
|
220
274
|
/>
|
|
221
275
|
))}
|
|
222
276
|
</Box>
|
|
223
277
|
{!readOnly &&
|
|
224
278
|
(open ? (
|
|
225
|
-
<KeyboardArrowUpIcon color
|
|
279
|
+
<KeyboardArrowUpIcon sx={{ color: isError ? red[700] : "primary" }} />
|
|
226
280
|
) : (
|
|
227
281
|
<KeyboardArrowDownIcon
|
|
228
282
|
sx={{
|
|
229
|
-
color: (theme) =>
|
|
283
|
+
color: (theme) =>
|
|
284
|
+
disabled ? theme.palette.grey[400] : theme.palette.action.focus
|
|
230
285
|
}}
|
|
231
286
|
/>
|
|
232
287
|
))}
|
|
233
288
|
</Box>
|
|
289
|
+
{(helperText || isError) && (
|
|
290
|
+
<Box
|
|
291
|
+
sx={{
|
|
292
|
+
...(isError ? { color: red[700] } : {})
|
|
293
|
+
}}
|
|
294
|
+
marginTop={1}
|
|
295
|
+
marginLeft={2}
|
|
296
|
+
width={inputContainerWidth}
|
|
297
|
+
fontSize="small"
|
|
298
|
+
>
|
|
299
|
+
{optionsExceedingBoundaries.length
|
|
300
|
+
? (() => {
|
|
301
|
+
const messagePluralForm =
|
|
302
|
+
optionsExceedingBoundaries.length > 1 ? "s" : "";
|
|
303
|
+
|
|
304
|
+
return `Value${messagePluralForm} for ${optionsExceedingBoundaries.join(", ")} option${messagePluralForm} ${messagePluralForm ? "are" : "is"} out of range.`;
|
|
305
|
+
})()
|
|
306
|
+
: helperText}
|
|
307
|
+
</Box>
|
|
308
|
+
)}
|
|
234
309
|
<ClickAwayListener onClickAway={() => open && setAnchorEl(undefined)}>
|
|
235
310
|
<Popper
|
|
236
311
|
open={open}
|
|
@@ -244,7 +319,8 @@ export const OptionsInput = ({
|
|
|
244
319
|
className="options-input__dropdown-items-list"
|
|
245
320
|
sx={{
|
|
246
321
|
bgcolor: "Background",
|
|
247
|
-
border: (theme) =>
|
|
322
|
+
border: (theme) =>
|
|
323
|
+
`thin solid ${isError ? red[700] : theme.palette.primary.main}`
|
|
248
324
|
}}
|
|
249
325
|
>
|
|
250
326
|
{currentOptions
|
|
@@ -260,6 +336,7 @@ export const OptionsInput = ({
|
|
|
260
336
|
onChange={onValueChange}
|
|
261
337
|
index={index}
|
|
262
338
|
displayMinMax={displayMinMax}
|
|
339
|
+
error={isError}
|
|
263
340
|
/>
|
|
264
341
|
))}
|
|
265
342
|
</List>
|
package/src/styles.scss
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
1
|
.options-input {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
2
|
+
&__container {
|
|
3
|
+
border: thin solid transparent;
|
|
4
|
+
border-radius: 0.25rem;
|
|
5
|
+
display: flex;
|
|
6
|
+
justify-content: space-between;
|
|
7
|
+
align-items: center;
|
|
8
|
+
padding: 0.25rem;
|
|
9
|
+
gap: 1rem;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
width: fit-content;
|
|
12
|
+
|
|
13
|
+
&--open {
|
|
14
|
+
border-bottom-width: 0;
|
|
15
|
+
border-bottom-left-radius: 0;
|
|
16
|
+
border-bottom-right-radius: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&--disabled {
|
|
20
|
+
cursor: unset;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&--read-only {
|
|
24
|
+
cursor: unset;
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
border-color: transparent;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&__dropdown-item {
|
|
33
|
+
gap: 1rem;
|
|
34
|
+
|
|
35
|
+
&--empty {
|
|
36
|
+
background-color: #eeeeee;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&__dropdown-item-input {
|
|
41
|
+
width: 2rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&__dropdown-item-buttons {
|
|
45
|
+
& > button[role="button"] {
|
|
46
|
+
min-width: 2rem;
|
|
47
|
+
padding: 0;
|
|
48
|
+
|
|
49
|
+
&[disabled] > svg {
|
|
50
|
+
color: #0000001f;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
54
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export interface OptionsInputOption {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
id: string;
|
|
3
|
+
icon: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
details?: string;
|
|
6
|
+
min?: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
quantity?: number;
|
|
9
|
+
inputQuantity?: string | number;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface OptionsInputValue {
|
|
13
|
-
|
|
13
|
+
[key: string]: number;
|
|
14
14
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export const capitalize = (str: string) =>
|
|
1
|
+
export const capitalize = (str: string) =>
|
|
2
|
+
str.charAt(0).toUpperCase() + str.slice(1);
|
package/tsconfig.build.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "dist",
|
|
5
|
+
"baseUrl": "../.."
|
|
6
|
+
},
|
|
7
|
+
"exclude": ["src/**/__tests__/**"]
|
|
8
|
+
}
|