@simplybusiness/mobius 6.9.4 → 6.9.6

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/index.js +31 -28
  3. package/dist/esm/index.js +34 -31
  4. package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
  5. package/dist/types/src/components/AddressLookup/__mocks__/LoqateAddressLookupService.d.ts +1 -1
  6. package/dist/types/src/components/AddressLookup/types.d.ts +6 -2
  7. package/dist/types/src/components/Button/Button.d.ts +1 -1
  8. package/dist/types/src/components/Grid/Item.d.ts +1 -1
  9. package/dist/types/src/components/LinkButton/LinkButton.d.ts +2 -3
  10. package/dist/types/src/components/List/List.d.ts +3 -3
  11. package/dist/types/src/components/Radio/Radio.d.ts +5 -0
  12. package/dist/types/src/types/index.d.ts +0 -1
  13. package/package.json +7 -5
  14. package/src/components/AddressLookup/AddressLookup.stories.tsx +0 -2
  15. package/src/components/AddressLookup/AddressLookup.tsx +14 -10
  16. package/src/components/AddressLookup/__mocks__/LoqateAddressLookupService.tsx +6 -4
  17. package/src/components/AddressLookup/types.tsx +7 -2
  18. package/src/components/Alert/Alert.css +5 -5
  19. package/src/components/Breadcrumbs/Breadcrumbs.css +2 -6
  20. package/src/components/Button/Button.css +4 -4
  21. package/src/components/Button/Button.tsx +3 -5
  22. package/src/components/Checkbox/Checkbox.css +7 -6
  23. package/src/components/Checkbox/CheckboxGroup.css +3 -3
  24. package/src/components/Checkbox/CheckboxGroup.test.tsx +5 -6
  25. package/src/components/Combobox/Combobox.css +1 -1
  26. package/src/components/Combobox/Combobox.tsx +5 -2
  27. package/src/components/Combobox/useComboboxOptions.ts +3 -2
  28. package/src/components/Drawer/Drawer.css +2 -2
  29. package/src/components/DropdownMenu/DropdownMenu.css +0 -3
  30. package/src/components/Fieldset/Fieldset.css +1 -1
  31. package/src/components/Grid/Item.tsx +9 -7
  32. package/src/components/LinkButton/LinkButton.test.tsx +4 -5
  33. package/src/components/LinkButton/LinkButton.tsx +2 -5
  34. package/src/components/List/List.css +1 -1
  35. package/src/components/List/List.tsx +5 -5
  36. package/src/components/Modal/Modal.css +2 -2
  37. package/src/components/NumberField/NumberField.css +3 -4
  38. package/src/components/PasswordField/PasswordField.css +2 -2
  39. package/src/components/Progress/Progress.tsx +4 -2
  40. package/src/components/Radio/Radio.css +6 -5
  41. package/src/components/Radio/Radio.tsx +9 -15
  42. package/src/components/Segment/Segment.css +25 -24
  43. package/src/components/Select/Select.css +6 -6
  44. package/src/components/Slider/Slider.css +68 -68
  45. package/src/components/Switch/Switch.css +26 -25
  46. package/src/components/Table/Table.css +0 -1
  47. package/src/components/TextArea/TextArea.css +5 -5
  48. package/src/components/TextField/TextField.css +70 -69
  49. package/src/hooks/useBreakpoint/useBreakpoint.stories.tsx +3 -9
  50. package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +6 -3
  51. package/src/hooks/useButton/useButton.test.tsx +6 -8
  52. package/src/types/index.tsx +0 -1
  53. package/dist/esm/tsconfig.tsbuildinfo +0 -1
  54. package/dist/types/src/types/components.d.ts +0 -4
  55. package/src/types/components.ts +0 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 6.9.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 3f0ca52: Add lint:css and lint:css:fix scripts to enable CSS linting with stylelint
8
+ - 67419b3: Remove `as any` type assertions and improve type safety
9
+ - Refactor type assertions to use safer alternatives (`as never`, `Reflect.set`, type guards)
10
+ - Use typed objects and proper mock patterns in tests
11
+ - Add `@ts-expect-error` comments where required due to TypeScript limitations (e.g., DatePicker onClick prop)
12
+ - Improve AddressLookup and Combobox type safety
13
+
14
+ ## 6.9.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 56c673f: Migrate CSS from SASS-style nesting to native CSS nesting syntax
19
+ - Update 62 CSS source files to use native CSS nesting with `&` prefix
20
+ - Switch PostCSS plugin from `postcss-nested` to `postcss-nesting`
21
+ - No functional changes to compiled CSS output (still Safari 14 compatible)
22
+
23
+ - c54e331: Remove deprecated ForwardedRefComponent type and migrate to ref-as-prop pattern
24
+ - @simplybusiness/icons@4.37.0
25
+
3
26
  ## 6.9.4
4
27
 
5
28
  ### Patch Changes
package/dist/cjs/index.js CHANGED
@@ -1477,8 +1477,10 @@ function useComboboxOptions({
1477
1477
  const result = await asyncOptions(debouncedInputValue, { signal });
1478
1478
  setFilteredOptions(result);
1479
1479
  onSearched?.(debouncedInputValue);
1480
- } else {
1480
+ } else if (options) {
1481
1481
  setFilteredOptions(filterOptions(options, debouncedInputValue));
1482
+ } else {
1483
+ setError(new Error("No options provided"));
1482
1484
  }
1483
1485
  } catch (e) {
1484
1486
  if (e instanceof DOMException && e.name === "AbortError") {
@@ -1626,7 +1628,11 @@ var ComboboxInner = ({
1626
1628
  const val = getOptionValue(option);
1627
1629
  if (!val) return;
1628
1630
  if (typeof option === "object" && "callback" in option && option.callback && typeof option.callback === "function") {
1629
- setTimeout(() => inputRef.current.focus(), 0);
1631
+ setTimeout(() => {
1632
+ if (inputRef && typeof inputRef !== "function" && inputRef.current) {
1633
+ inputRef.current.focus();
1634
+ }
1635
+ }, 0);
1630
1636
  updateFilteredOptions(option.callback());
1631
1637
  return;
1632
1638
  }
@@ -1862,6 +1868,10 @@ var AddressLookup = ({
1862
1868
  );
1863
1869
  const handleSelected = (selected) => {
1864
1870
  setError(null);
1871
+ if (typeof selected === "string" || !selected.id) {
1872
+ setError(new Error("Selected option missing id"));
1873
+ return Promise.resolve();
1874
+ }
1865
1875
  return addressLookupService.get(selected.id).then(onAddressSelected).catch(setError);
1866
1876
  };
1867
1877
  const realErrorMessage = error3 && "An error occurred" || errorMessage;
@@ -2148,10 +2158,7 @@ var Success = () => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_ru
2148
2158
  ] });
2149
2159
 
2150
2160
  // src/components/Button/Button.tsx
2151
- var import_jsx_runtime20 = (
2152
- // @ts-expect-error - ref type is not correct
2153
- require("react/jsx-runtime")
2154
- );
2161
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2155
2162
  var Button = ({ ref, ...props }) => {
2156
2163
  const {
2157
2164
  children,
@@ -2180,7 +2187,7 @@ var Button = ({ ref, ...props }) => {
2180
2187
  return variant;
2181
2188
  };
2182
2189
  const buttonVariant = getVariant(variant);
2183
- const classes = (0, import_dedupe15.default)(
2190
+ otherProps.className = (0, import_dedupe15.default)(
2184
2191
  "mobius",
2185
2192
  "mobius-button",
2186
2193
  `--variant-${buttonVariant}`,
@@ -2192,7 +2199,6 @@ var Button = ({ ref, ...props }) => {
2192
2199
  },
2193
2200
  otherProps.className
2194
2201
  );
2195
- otherProps.className = classes;
2196
2202
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Component, { ref, ...buttonProps, ...otherProps, children: [
2197
2203
  isLoading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Loading, { children }) : children,
2198
2204
  isSuccess && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Success, {})
@@ -2898,11 +2904,14 @@ Grid.displayName = "Grid";
2898
2904
  var import_react33 = require("react");
2899
2905
  var import_dedupe26 = __toESM(require("classnames/dedupe"));
2900
2906
  var import_jsx_runtime33 = require("react/jsx-runtime");
2901
- var getBreakpointMap = (config) => Object.entries(config).reduce((prev, [key, value]) => {
2902
- const previous = Object.values(prev);
2903
- const lastDefined = previous[previous.length - 1];
2904
- return { ...prev, [key]: value || lastDefined };
2905
- }, {});
2907
+ var getBreakpointMap = (config) => Object.entries(config).reduce(
2908
+ (prev, [key, value]) => {
2909
+ const previous = Object.values(prev);
2910
+ const lastDefined = previous[previous.length - 1];
2911
+ return { ...prev, [key]: value || lastDefined };
2912
+ },
2913
+ {}
2914
+ );
2906
2915
  var DEFAULT_SPAN = 12;
2907
2916
  var GridItem = ({ ref: _ref, ...props }) => {
2908
2917
  const {
@@ -3004,10 +3013,7 @@ Link.displayName = "Link";
3004
3013
 
3005
3014
  // src/components/LinkButton/LinkButton.tsx
3006
3015
  var import_dedupe29 = __toESM(require("classnames/dedupe"));
3007
- var import_jsx_runtime36 = (
3008
- // @ts-expect-error Button only allows elementType of string, not React component
3009
- require("react/jsx-runtime")
3010
- );
3016
+ var import_jsx_runtime36 = require("react/jsx-runtime");
3011
3017
  function LinkButton({
3012
3018
  href,
3013
3019
  children,
@@ -3568,8 +3574,10 @@ function warnAboutInvalidValues(value, minValue, maxValue) {
3568
3574
  }
3569
3575
  }
3570
3576
  var sanitizedValue = (value, defaultValue) => {
3571
- const numberValue = parseFloat(value);
3572
- return Number.isNaN(numberValue) ? defaultValue : numberValue;
3577
+ if (value === void 0 || Number.isNaN(value)) {
3578
+ return defaultValue;
3579
+ }
3580
+ return value;
3573
3581
  };
3574
3582
  var getLabelComponent = (label, progressLabelId, showLabel) => {
3575
3583
  if (showLabel) {
@@ -3672,6 +3680,7 @@ var Radio = ({ ref, ...props }) => {
3672
3680
  setSelected,
3673
3681
  isRequired,
3674
3682
  onOverflow,
3683
+ orientation,
3675
3684
  ...otherProps
3676
3685
  } = props;
3677
3686
  const realDisabled = groupDisabled || isDisabled;
@@ -3683,7 +3692,6 @@ var Radio = ({ ref, ...props }) => {
3683
3692
  vertical: false,
3684
3693
  horizontal: false
3685
3694
  });
3686
- const currentOrientation = otherProps.orientation;
3687
3695
  const hasIconFirst = (0, import_react43.useMemo)(() => {
3688
3696
  if (!children || import_react43.Children.count(children) === 0) return false;
3689
3697
  const firstChild = import_react43.Children.toArray(children)[0];
@@ -3693,7 +3701,7 @@ var Radio = ({ ref, ...props }) => {
3693
3701
  }, [children]);
3694
3702
  (0, import_react43.useLayoutEffect)(() => {
3695
3703
  if (!contentRef.current || !onOverflow) return;
3696
- if (currentOrientation === "vertical") {
3704
+ if (orientation === "vertical") {
3697
3705
  return;
3698
3706
  }
3699
3707
  const element = contentRef.current;
@@ -3713,7 +3721,7 @@ var Radio = ({ ref, ...props }) => {
3713
3721
  prevOverflowRef.current = newOverflowState;
3714
3722
  onOverflow(newOverflowState);
3715
3723
  }
3716
- }, [label, children, onOverflow, currentOrientation]);
3724
+ }, [label, children, onOverflow, orientation]);
3717
3725
  const radioClasses = {
3718
3726
  "--is-disabled": realDisabled,
3719
3727
  "--is-selected": selected === value,
@@ -3727,12 +3735,7 @@ var Radio = ({ ref, ...props }) => {
3727
3735
  { "--has-icon-first": hasIconFirst }
3728
3736
  );
3729
3737
  const inputClasses = (0, import_dedupe38.default)("mobius-radio__input", radioClasses);
3730
- const {
3731
- // @ts-expect-error - TS doesn't like the orientation prop
3732
- orientation,
3733
- "aria-describedby": _ariaDescribedBy,
3734
- ...rest
3735
- } = otherProps;
3738
+ const { "aria-describedby": _ariaDescribedBy, ...rest } = otherProps;
3736
3739
  const handleChange = (event) => {
3737
3740
  if (setSelected) {
3738
3741
  setSelected(event.target.value);
package/dist/esm/index.js CHANGED
@@ -1366,8 +1366,10 @@ function useComboboxOptions({
1366
1366
  const result = await asyncOptions(debouncedInputValue, { signal });
1367
1367
  setFilteredOptions(result);
1368
1368
  onSearched?.(debouncedInputValue);
1369
- } else {
1369
+ } else if (options) {
1370
1370
  setFilteredOptions(filterOptions(options, debouncedInputValue));
1371
+ } else {
1372
+ setError(new Error("No options provided"));
1371
1373
  }
1372
1374
  } catch (e) {
1373
1375
  if (e instanceof DOMException && e.name === "AbortError") {
@@ -1515,7 +1517,11 @@ var ComboboxInner = ({
1515
1517
  const val = getOptionValue(option);
1516
1518
  if (!val) return;
1517
1519
  if (typeof option === "object" && "callback" in option && option.callback && typeof option.callback === "function") {
1518
- setTimeout(() => inputRef.current.focus(), 0);
1520
+ setTimeout(() => {
1521
+ if (inputRef && typeof inputRef !== "function" && inputRef.current) {
1522
+ inputRef.current.focus();
1523
+ }
1524
+ }, 0);
1519
1525
  updateFilteredOptions(option.callback());
1520
1526
  return;
1521
1527
  }
@@ -1751,6 +1757,10 @@ var AddressLookup = ({
1751
1757
  );
1752
1758
  const handleSelected = (selected) => {
1753
1759
  setError(null);
1760
+ if (typeof selected === "string" || !selected.id) {
1761
+ setError(new Error("Selected option missing id"));
1762
+ return Promise.resolve();
1763
+ }
1754
1764
  return addressLookupService.get(selected.id).then(onAddressSelected).catch(setError);
1755
1765
  };
1756
1766
  const realErrorMessage = error3 && "An error occurred" || errorMessage;
@@ -2066,7 +2076,7 @@ var Button = ({ ref, ...props }) => {
2066
2076
  return variant;
2067
2077
  };
2068
2078
  const buttonVariant = getVariant(variant);
2069
- const classes = classNames17(
2079
+ otherProps.className = classNames17(
2070
2080
  "mobius",
2071
2081
  "mobius-button",
2072
2082
  `--variant-${buttonVariant}`,
@@ -2078,14 +2088,10 @@ var Button = ({ ref, ...props }) => {
2078
2088
  },
2079
2089
  otherProps.className
2080
2090
  );
2081
- otherProps.className = classes;
2082
- return (
2083
- // @ts-expect-error - ref type is not correct
2084
- /* @__PURE__ */ jsxs12(Component, { ref, ...buttonProps, ...otherProps, children: [
2085
- isLoading ? /* @__PURE__ */ jsx20(Loading, { children }) : children,
2086
- isSuccess && !isLoading && /* @__PURE__ */ jsx20(Success, {})
2087
- ] })
2088
- );
2091
+ return /* @__PURE__ */ jsxs12(Component, { ref, ...buttonProps, ...otherProps, children: [
2092
+ isLoading ? /* @__PURE__ */ jsx20(Loading, { children }) : children,
2093
+ isSuccess && !isLoading && /* @__PURE__ */ jsx20(Success, {})
2094
+ ] });
2089
2095
  };
2090
2096
  Button.displayName = "Button";
2091
2097
 
@@ -2795,11 +2801,14 @@ Grid.displayName = "Grid";
2795
2801
  import { useEffect as useEffect19, useState as useState16 } from "react";
2796
2802
  import classNames28 from "classnames/dedupe";
2797
2803
  import { jsx as jsx33 } from "react/jsx-runtime";
2798
- var getBreakpointMap = (config) => Object.entries(config).reduce((prev, [key, value]) => {
2799
- const previous = Object.values(prev);
2800
- const lastDefined = previous[previous.length - 1];
2801
- return { ...prev, [key]: value || lastDefined };
2802
- }, {});
2804
+ var getBreakpointMap = (config) => Object.entries(config).reduce(
2805
+ (prev, [key, value]) => {
2806
+ const previous = Object.values(prev);
2807
+ const lastDefined = previous[previous.length - 1];
2808
+ return { ...prev, [key]: value || lastDefined };
2809
+ },
2810
+ {}
2811
+ );
2803
2812
  var DEFAULT_SPAN = 12;
2804
2813
  var GridItem = ({ ref: _ref, ...props }) => {
2805
2814
  const {
@@ -2913,10 +2922,7 @@ function LinkButton({
2913
2922
  throw new Error("LinkButton requires a href prop");
2914
2923
  }
2915
2924
  const classes = classNames31("mobius", "mobius-link-button", className);
2916
- return (
2917
- // @ts-expect-error Button only allows elementType of string, not React component
2918
- /* @__PURE__ */ jsx36(Button, { elementType, href, className: classes, ...rest, children })
2919
- );
2925
+ return /* @__PURE__ */ jsx36(Button, { elementType, href, className: classes, ...rest, children });
2920
2926
  }
2921
2927
 
2922
2928
  // src/components/List/List.tsx
@@ -3475,8 +3481,10 @@ function warnAboutInvalidValues(value, minValue, maxValue) {
3475
3481
  }
3476
3482
  }
3477
3483
  var sanitizedValue = (value, defaultValue) => {
3478
- const numberValue = parseFloat(value);
3479
- return Number.isNaN(numberValue) ? defaultValue : numberValue;
3484
+ if (value === void 0 || Number.isNaN(value)) {
3485
+ return defaultValue;
3486
+ }
3487
+ return value;
3480
3488
  };
3481
3489
  var getLabelComponent = (label, progressLabelId, showLabel) => {
3482
3490
  if (showLabel) {
@@ -3585,6 +3593,7 @@ var Radio = ({ ref, ...props }) => {
3585
3593
  setSelected,
3586
3594
  isRequired,
3587
3595
  onOverflow,
3596
+ orientation,
3588
3597
  ...otherProps
3589
3598
  } = props;
3590
3599
  const realDisabled = groupDisabled || isDisabled;
@@ -3596,7 +3605,6 @@ var Radio = ({ ref, ...props }) => {
3596
3605
  vertical: false,
3597
3606
  horizontal: false
3598
3607
  });
3599
- const currentOrientation = otherProps.orientation;
3600
3608
  const hasIconFirst = useMemo3(() => {
3601
3609
  if (!children || Children7.count(children) === 0) return false;
3602
3610
  const firstChild = Children7.toArray(children)[0];
@@ -3606,7 +3614,7 @@ var Radio = ({ ref, ...props }) => {
3606
3614
  }, [children]);
3607
3615
  useLayoutEffect(() => {
3608
3616
  if (!contentRef.current || !onOverflow) return;
3609
- if (currentOrientation === "vertical") {
3617
+ if (orientation === "vertical") {
3610
3618
  return;
3611
3619
  }
3612
3620
  const element = contentRef.current;
@@ -3626,7 +3634,7 @@ var Radio = ({ ref, ...props }) => {
3626
3634
  prevOverflowRef.current = newOverflowState;
3627
3635
  onOverflow(newOverflowState);
3628
3636
  }
3629
- }, [label, children, onOverflow, currentOrientation]);
3637
+ }, [label, children, onOverflow, orientation]);
3630
3638
  const radioClasses = {
3631
3639
  "--is-disabled": realDisabled,
3632
3640
  "--is-selected": selected === value,
@@ -3640,12 +3648,7 @@ var Radio = ({ ref, ...props }) => {
3640
3648
  { "--has-icon-first": hasIconFirst }
3641
3649
  );
3642
3650
  const inputClasses = classNames41("mobius-radio__input", radioClasses);
3643
- const {
3644
- // @ts-expect-error - TS doesn't like the orientation prop
3645
- orientation,
3646
- "aria-describedby": _ariaDescribedBy,
3647
- ...rest
3648
- } = otherProps;
3651
+ const { "aria-describedby": _ariaDescribedBy, ...rest } = otherProps;
3649
3652
  const handleChange = (event) => {
3650
3653
  if (setSelected) {
3651
3654
  setSelected(event.target.value);