@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 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,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAyB,EAAE,EAAE,CAAC,CAC/E,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"}
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
- const OptionsInputContentItem = ({ item: { quantity, details, label, max, min, icon }, displayMinMax = false, disabled = false }) => {
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 = quantity === 0 || disabled ? "#a4a5b2" : "#000000";
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;AAStC,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,EACc,EAAE,EAAE;IAClC,MAAM,IAAI,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAmC,CAAC,IAAI,IAAI,CAAC;IAC3F,MAAM,UAAU,GAAG,QAAQ,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtE,OAAO,CACN,MAAC,GAAG,IAAC,OAAO,EAAC,MAAM,EAAC,UAAU,EAAC,QAAQ,EAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,iBAAc,aAAa,aAC5F,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"}
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
- return (_jsxs(_Fragment, { children: [!!index && _jsx(Divider, { sx: { color: (theme) => theme.palette.primary.main } }), _jsxs(ListItem, { sx: {
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: () => onChange(id, quantity + 1), disabled: quantity === max, className: "options-input__dropdown-item-button", role: "button", color: "primary", children: _jsx(AddIcon, { sx: { color: "primary" } }) }), _jsx(Button, { onClick: () => onChange(id, quantity - 1), disabled: quantity === min, className: "options-input__dropdown-item-button", role: "button", color: "primary", children: _jsx(RemoveIcon, { sx: { color: "primary" } }) })] })] })] }));
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;AAWtC,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,EACkB,EAAE,EAAE;IACnC,MAAM,CAAC,wBAAwB,EAAE,2BAA2B,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IACzF,MAAM,IAAI,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,CAAmC,CAAC,IAAI,IAAI,CAAC;IAE3F,OAAO,CACN,8BACE,CAAC,CAAC,KAAK,IAAI,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAI,EAC7E,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,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,GAAG,CAAC,CAAC,EACzC,QAAQ,EAAE,QAAQ,KAAK,GAAG,EAC1B,SAAS,EAAC,qCAAqC,EAC/C,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,SAAS,YAEf,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAI,GAC7B,EACT,KAAC,MAAM,IACN,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,GAAG,CAAC,CAAC,EACzC,QAAQ,EAAE,QAAQ,KAAK,GAAG,EAC1B,SAAS,EAAC,qCAAqC,EAC/C,IAAI,EAAC,QAAQ,EACb,KAAK,EAAC,SAAS,YAEf,KAAC,UAAU,IAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAI,GAChC,IACI,IACJ,IACT,CACH,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"options-input-dropdown-item.js","sourceRoot":"","sources":["../../src/components/options-input-dropdown-item.tsx"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { OptionsInput } from './options-input';
2
- export type { OptionsInputProps } from './options-input';
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 './options-input';
1
+ export { OptionsInput } from "./options-input";
2
2
  //# sourceMappingURL=index.js.map
@@ -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;
@@ -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 defaultQuantity = defaultValue?.[option.id] ?? 0;
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) => (currentAnchor ? undefined : currentTarget));
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.max || Infinity) ? option.max : newQuantity;
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.min || -Infinity) ? option.min : maxQuantity,
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.inputQuantity))
93
+ const finalQuantity = Number.isNaN(Number(option?.inputQuantity))
81
94
  ? 0
82
- : Number(option.inputQuantity);
83
- const maxQuantity = finalQuantity > (option.max || Infinity) ? option.max : finalQuantity;
95
+ : Number(option?.inputQuantity);
96
+ const maxQuantity = finalQuantity > (option?.max ?? Infinity) ? option?.max : finalQuantity;
84
97
  return {
85
98
  ...option,
86
- inputQuantity: finalQuantity < (option.min || -Infinity) ? option.min : maxQuantity
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
- className
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.includes(optionId))))
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) => (disabled ? theme.palette.grey[400] : theme.palette.action.focus)
107
- } })))] }), _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: {
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":"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"}
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
- &__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
- }
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,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
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",
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.2"
14
+ "@talixo-ds/icons": "^1.0.3"
15
15
  },
16
- "gitHead": "618a5d4b960ff0a06427031dc8f41997b465c1d2"
16
+ "gitHead": "857e6fabaeeaec85a3180c66fe89545f74cabc96"
17
17
  }
@@ -1,4 +1,10 @@
1
- import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
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(screen.queryByTestId("options-dropdown-list")).not.toBeInTheDocument();
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": 1
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": 1
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": 1
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 item={{ ...props.item, label: undefined, quantity: 1 }} />
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(props.item.details.slice(0, 15));
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 = ({ min, max, color }: MinMaxValueLabelProps) => (
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 = DesignSystemIcons[capitalize(icon) as keyof typeof DesignSystemIcons] || null;
21
- const itemsColor = quantity === 0 || disabled ? "#a4a5b2" : "#000000";
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 display="flex" alignItems="center" gap={0.5} color={itemsColor} data-testid="option-item">
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] = useState<boolean>(false);
33
- const Icon = DesignSystemIcons[capitalize(icon) as keyof typeof DesignSystemIcons] || null;
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 && <Divider sx={{ color: (theme) => theme.palette.primary.main }} />}
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={() => onChange(id, quantity + 1)}
121
- disabled={quantity === max}
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={() => onChange(id, quantity - 1)}
130
- disabled={quantity === min}
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 './options-input';
2
- export type { OptionsInputProps } from './options-input';
1
+ export { OptionsInput } from "./options-input";
2
+ export type { OptionsInputProps } from "./options-input";
@@ -1,4 +1,11 @@
1
- import React, { useState, useEffect, useCallback } from "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 defaultQuantity = defaultValue?.[option.id] ?? 0;
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) => (currentAnchor ? undefined : currentTarget));
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 = newQuantity > (option.max || Infinity) ? option.max : newQuantity;
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: newQuantity < (option.min || -Infinity) ? option.min : maxQuantity,
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.inputQuantity))
211
+ const finalQuantity = Number.isNaN(Number(option?.inputQuantity))
170
212
  ? 0
171
- : Number(option.inputQuantity);
172
- const maxQuantity = finalQuantity > (option.max || Infinity) ? option.max : finalQuantity;
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: finalQuantity < (option.min || -Infinity) ? option.min : maxQuantity
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
- className={classNames("options-input__container", {
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
- className
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[capitalize(icon) as keyof typeof DesignSystemIcons] &&
211
- (quantity !== 0 || persistentOptions.includes(optionId))
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="primary" />
279
+ <KeyboardArrowUpIcon sx={{ color: isError ? red[700] : "primary" }} />
226
280
  ) : (
227
281
  <KeyboardArrowDownIcon
228
282
  sx={{
229
- color: (theme) => (disabled ? theme.palette.grey[400] : theme.palette.action.focus)
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) => `thin solid ${theme.palette.primary.main}`
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
- &__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
- }
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
- id: string;
3
- icon: string;
4
- label?: string;
5
- details?: string;
6
- min?: number;
7
- max?: number;
8
- quantity?: number;
9
- inputQuantity?: string | number;
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
- [key: string]: number;
13
+ [key: string]: number;
14
14
  }
package/src/utils.ts CHANGED
@@ -1 +1,2 @@
1
- export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
1
+ export const capitalize = (str: string) =>
2
+ str.charAt(0).toUpperCase() + str.slice(1);
@@ -1,8 +1,8 @@
1
1
  {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "baseUrl": "../.."
6
- },
7
- "exclude": ["src/**/__tests__/**"],
8
- }
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "baseUrl": "../.."
6
+ },
7
+ "exclude": ["src/**/__tests__/**"]
8
+ }