@equinor/eds-core-react 0.39.0 → 0.39.1-dev13062024

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.
@@ -9420,6 +9420,7 @@ const Container$2 = styled__default.default.div.withConfig({
9420
9420
  componentId: "sc-yvif0e-0"
9421
9421
  })(["position:relative;"]);
9422
9422
  const AllSymbol = Symbol('Select all');
9423
+ // MARK: styled components
9423
9424
  const StyledList = styled__default.default(List$1).withConfig({
9424
9425
  displayName: "Autocomplete__StyledList",
9425
9426
  componentId: "sc-yvif0e-1"
@@ -9452,7 +9453,7 @@ const StyledButton$1 = styled__default.default(Button$1).withConfig({
9452
9453
  }
9453
9454
  }
9454
9455
  }) => styled.css(["height:", ";width:", ";"], button.height, button.height));
9455
-
9456
+ // MARK: outside functions
9456
9457
  // Typescript can struggle with parsing generic arrow functions in a .tsx file (see https://github.com/microsoft/TypeScript/issues/15713)
9457
9458
  // Workaround is to add a trailing , after T, which tricks the compiler, but also have to ignore prettier rule.
9458
9459
  // prettier-ignore
@@ -9542,9 +9543,9 @@ const handleListFocus = e => {
9542
9543
  });
9543
9544
  };
9544
9545
  const defaultOptionDisabled = () => false;
9546
+ // MARK: types
9545
9547
 
9546
- // prettier-ignore
9547
-
9548
+ // MARK: component
9548
9549
  function AutocompleteInner(props, ref) {
9549
9550
  const {
9550
9551
  options = [],
@@ -9579,6 +9580,8 @@ function AutocompleteInner(props, ref) {
9579
9580
  variant,
9580
9581
  ...other
9581
9582
  } = props;
9583
+
9584
+ // MARK: initializing data/setup
9582
9585
  const selectedOptions = _selectedOptions ? itemCompare ? options.filter(item => _selectedOptions.some(compare => itemCompare(item, compare))) : _selectedOptions : undefined;
9583
9586
  const initialSelectedOptions = _initialSelectedOptions ? itemCompare ? options.filter(item => _initialSelectedOptions.some(compare => itemCompare(item, compare))) : _initialSelectedOptions : undefined;
9584
9587
  if (disablePortal) {
@@ -9650,6 +9653,8 @@ function AutocompleteInner(props, ref) {
9650
9653
  selectedItems,
9651
9654
  setSelectedItems
9652
9655
  } = downshift.useMultipleSelection(multipleSelectionProps);
9656
+
9657
+ // MARK: select all logic
9653
9658
  const enabledItems = react.useMemo(() => {
9654
9659
  const disabledItemsSet = new Set(inputOptions.filter(optionDisabled));
9655
9660
  return inputOptions.filter(x => !disabledItemsSet.has(x));
@@ -9669,6 +9674,8 @@ function AutocompleteInner(props, ref) {
9669
9674
  setSelectedItems([...enabledItems, ...selectedDisabledItemsSet]);
9670
9675
  }
9671
9676
  };
9677
+
9678
+ // MARK: getLabel
9672
9679
  const getLabel = react.useCallback(item => {
9673
9680
  //note: non strict check for null or undefined to allow 0
9674
9681
  if (item == null) {
@@ -9691,6 +9698,8 @@ function AutocompleteInner(props, ref) {
9691
9698
  throw new Error('Unable to find label, make sure your are using options as documented');
9692
9699
  }
9693
9700
  }, [optionLabel]);
9701
+
9702
+ // MARK: setup virtualizer
9694
9703
  const scrollContainer = react.useRef(null);
9695
9704
  const rowVirtualizer = reactVirtual.useVirtualizer({
9696
9705
  count: availableItems.length,
@@ -9705,8 +9714,11 @@ function AutocompleteInner(props, ref) {
9705
9714
  edsUtils.useIsomorphicLayoutEffect(() => {
9706
9715
  rowVirtualizer?.measure?.();
9707
9716
  }, [rowVirtualizer, density]);
9717
+
9718
+ // MARK: downshift state
9708
9719
  let comboBoxProps = {
9709
9720
  items: availableItems,
9721
+ //can not pass readonly type to downshift so we cast it to regular T[]
9710
9722
  initialSelectedItem: initialSelectedOptions[0],
9711
9723
  isItemDisabled(item) {
9712
9724
  return optionDisabled(item);
@@ -9771,6 +9783,7 @@ function AutocompleteInner(props, ref) {
9771
9783
  }
9772
9784
  }
9773
9785
  };
9786
+ // MARK: singleselect specific
9774
9787
  if (!multiple) {
9775
9788
  comboBoxProps = {
9776
9789
  ...comboBoxProps,
@@ -9847,6 +9860,7 @@ function AutocompleteInner(props, ref) {
9847
9860
  };
9848
9861
  }
9849
9862
  }
9863
+ // MARK: multiselect specific
9850
9864
  if (multiple) {
9851
9865
  placeholderText = typeof placeholderText !== 'undefined' ? placeholderText : `${selectedItems.length}/${inputOptions.length} selected`;
9852
9866
  comboBoxProps = {
@@ -9940,6 +9954,8 @@ function AutocompleteInner(props, ref) {
9940
9954
  inputValue,
9941
9955
  reset: resetCombobox
9942
9956
  } = downshift.useCombobox(comboBoxProps);
9957
+
9958
+ // MARK: floating-ui setup
9943
9959
  const {
9944
9960
  x,
9945
9961
  y,
@@ -9971,6 +9987,8 @@ function AutocompleteInner(props, ref) {
9971
9987
  return react$1.autoUpdate(refs.reference.current, refs.floating.current, update);
9972
9988
  }
9973
9989
  }, [refs.reference, refs.floating, update, isOpen]);
9990
+
9991
+ // MARK: popover toggle
9974
9992
  edsUtils.useIsomorphicLayoutEffect(() => {
9975
9993
  if (isOpen) {
9976
9994
  refs.floating.current.showPopover();
@@ -9987,6 +10005,8 @@ function AutocompleteInner(props, ref) {
9987
10005
  const showClearButton = (selectedItems.length > 0 || inputValue) && !readOnly && !hideClearButton;
9988
10006
  const showNoOptions = isOpen && !availableItems.length && noOptionsText.length > 0;
9989
10007
  const selectedItemsLabels = react.useMemo(() => selectedItems.map(getLabel), [selectedItems, getLabel]);
10008
+
10009
+ // MARK: optionsList
9990
10010
  const optionsList = /*#__PURE__*/jsxRuntime.jsx(StyledPopover, {
9991
10011
  popover: "manual",
9992
10012
  ...getFloatingProps({
@@ -10088,6 +10108,8 @@ function AutocompleteInner(props, ref) {
10088
10108
  disabled
10089
10109
  }));
10090
10110
  const consolidatedEvents = mergeEventsFromRight(other, inputProps);
10111
+
10112
+ // MARK: input
10091
10113
  return /*#__PURE__*/jsxRuntime.jsx(styled.ThemeProvider, {
10092
10114
  theme: token,
10093
10115
  children: /*#__PURE__*/jsxRuntime.jsxs(Container$2, {
@@ -10143,6 +10165,7 @@ function AutocompleteInner(props, ref) {
10143
10165
  })
10144
10166
  });
10145
10167
  }
10168
+ // MARK: exported component
10146
10169
  const Autocomplete = /*#__PURE__*/react.forwardRef(AutocompleteInner);
10147
10170
 
10148
10171
  const {
@@ -24,6 +24,7 @@ const Container = styled.div.withConfig({
24
24
  componentId: "sc-yvif0e-0"
25
25
  })(["position:relative;"]);
26
26
  const AllSymbol = Symbol('Select all');
27
+ // MARK: styled components
27
28
  const StyledList = styled(List).withConfig({
28
29
  displayName: "Autocomplete__StyledList",
29
30
  componentId: "sc-yvif0e-1"
@@ -56,7 +57,7 @@ const StyledButton = styled(Button).withConfig({
56
57
  }
57
58
  }
58
59
  }) => css(["height:", ";width:", ";"], button.height, button.height));
59
-
60
+ // MARK: outside functions
60
61
  // Typescript can struggle with parsing generic arrow functions in a .tsx file (see https://github.com/microsoft/TypeScript/issues/15713)
61
62
  // Workaround is to add a trailing , after T, which tricks the compiler, but also have to ignore prettier rule.
62
63
  // prettier-ignore
@@ -146,9 +147,9 @@ const handleListFocus = e => {
146
147
  });
147
148
  };
148
149
  const defaultOptionDisabled = () => false;
150
+ // MARK: types
149
151
 
150
- // prettier-ignore
151
-
152
+ // MARK: component
152
153
  function AutocompleteInner(props, ref) {
153
154
  const {
154
155
  options = [],
@@ -183,6 +184,8 @@ function AutocompleteInner(props, ref) {
183
184
  variant,
184
185
  ...other
185
186
  } = props;
187
+
188
+ // MARK: initializing data/setup
186
189
  const selectedOptions = _selectedOptions ? itemCompare ? options.filter(item => _selectedOptions.some(compare => itemCompare(item, compare))) : _selectedOptions : undefined;
187
190
  const initialSelectedOptions = _initialSelectedOptions ? itemCompare ? options.filter(item => _initialSelectedOptions.some(compare => itemCompare(item, compare))) : _initialSelectedOptions : undefined;
188
191
  if (disablePortal) {
@@ -254,6 +257,8 @@ function AutocompleteInner(props, ref) {
254
257
  selectedItems,
255
258
  setSelectedItems
256
259
  } = useMultipleSelection(multipleSelectionProps);
260
+
261
+ // MARK: select all logic
257
262
  const enabledItems = useMemo(() => {
258
263
  const disabledItemsSet = new Set(inputOptions.filter(optionDisabled));
259
264
  return inputOptions.filter(x => !disabledItemsSet.has(x));
@@ -273,6 +278,8 @@ function AutocompleteInner(props, ref) {
273
278
  setSelectedItems([...enabledItems, ...selectedDisabledItemsSet]);
274
279
  }
275
280
  };
281
+
282
+ // MARK: getLabel
276
283
  const getLabel = useCallback(item => {
277
284
  //note: non strict check for null or undefined to allow 0
278
285
  if (item == null) {
@@ -295,6 +302,8 @@ function AutocompleteInner(props, ref) {
295
302
  throw new Error('Unable to find label, make sure your are using options as documented');
296
303
  }
297
304
  }, [optionLabel]);
305
+
306
+ // MARK: setup virtualizer
298
307
  const scrollContainer = useRef(null);
299
308
  const rowVirtualizer = useVirtualizer({
300
309
  count: availableItems.length,
@@ -309,8 +318,11 @@ function AutocompleteInner(props, ref) {
309
318
  useIsomorphicLayoutEffect(() => {
310
319
  rowVirtualizer?.measure?.();
311
320
  }, [rowVirtualizer, density]);
321
+
322
+ // MARK: downshift state
312
323
  let comboBoxProps = {
313
324
  items: availableItems,
325
+ //can not pass readonly type to downshift so we cast it to regular T[]
314
326
  initialSelectedItem: initialSelectedOptions[0],
315
327
  isItemDisabled(item) {
316
328
  return optionDisabled(item);
@@ -375,6 +387,7 @@ function AutocompleteInner(props, ref) {
375
387
  }
376
388
  }
377
389
  };
390
+ // MARK: singleselect specific
378
391
  if (!multiple) {
379
392
  comboBoxProps = {
380
393
  ...comboBoxProps,
@@ -451,6 +464,7 @@ function AutocompleteInner(props, ref) {
451
464
  };
452
465
  }
453
466
  }
467
+ // MARK: multiselect specific
454
468
  if (multiple) {
455
469
  placeholderText = typeof placeholderText !== 'undefined' ? placeholderText : `${selectedItems.length}/${inputOptions.length} selected`;
456
470
  comboBoxProps = {
@@ -544,6 +558,8 @@ function AutocompleteInner(props, ref) {
544
558
  inputValue,
545
559
  reset: resetCombobox
546
560
  } = useCombobox(comboBoxProps);
561
+
562
+ // MARK: floating-ui setup
547
563
  const {
548
564
  x,
549
565
  y,
@@ -575,6 +591,8 @@ function AutocompleteInner(props, ref) {
575
591
  return autoUpdate(refs.reference.current, refs.floating.current, update);
576
592
  }
577
593
  }, [refs.reference, refs.floating, update, isOpen]);
594
+
595
+ // MARK: popover toggle
578
596
  useIsomorphicLayoutEffect(() => {
579
597
  if (isOpen) {
580
598
  refs.floating.current.showPopover();
@@ -591,6 +609,8 @@ function AutocompleteInner(props, ref) {
591
609
  const showClearButton = (selectedItems.length > 0 || inputValue) && !readOnly && !hideClearButton;
592
610
  const showNoOptions = isOpen && !availableItems.length && noOptionsText.length > 0;
593
611
  const selectedItemsLabels = useMemo(() => selectedItems.map(getLabel), [selectedItems, getLabel]);
612
+
613
+ // MARK: optionsList
594
614
  const optionsList = /*#__PURE__*/jsx(StyledPopover, {
595
615
  popover: "manual",
596
616
  ...getFloatingProps({
@@ -692,6 +712,8 @@ function AutocompleteInner(props, ref) {
692
712
  disabled
693
713
  }));
694
714
  const consolidatedEvents = mergeEventsFromRight(other, inputProps);
715
+
716
+ // MARK: input
695
717
  return /*#__PURE__*/jsx(ThemeProvider, {
696
718
  theme: token,
697
719
  children: /*#__PURE__*/jsxs(Container, {
@@ -747,6 +769,7 @@ function AutocompleteInner(props, ref) {
747
769
  })
748
770
  });
749
771
  }
772
+ // MARK: exported component
750
773
  const Autocomplete = /*#__PURE__*/forwardRef(AutocompleteInner);
751
774
 
752
775
  export { Autocomplete };
@@ -1,30 +1,11 @@
1
1
  import { HTMLAttributes, ReactNode } from 'react';
2
2
  import { Variants } from '../types';
3
- type OptionLabelProps<T> = T extends string | number ? {
4
- /** Custom option label */
5
- optionLabel?: (option: T) => string;
6
- /** Disable option
7
- * @default () => false
8
- */
9
- optionDisabled?: (option: T) => boolean;
10
- /** List of options in dropdown */
11
- options: (string | number)[];
12
- } : {
13
- /** Custom option label */
14
- optionLabel: (option: T) => string;
15
- /** Disable option
16
- * @default () => false
17
- */
18
- optionDisabled?: (option: T) => boolean;
19
- /** List of options in dropdown */
20
- options: T[];
21
- };
22
3
  export type AutocompleteChanges<T> = {
23
4
  selectedItems: T[];
24
5
  };
25
6
  export type AutocompleteProps<T> = {
26
7
  /** List of options in dropdown */
27
- options: T[];
8
+ options: readonly T[];
28
9
  /** Label for the select element */
29
10
  label: ReactNode;
30
11
  /** Array of initial selected items
@@ -76,12 +57,18 @@ export type AutocompleteProps<T> = {
76
57
  multiple?: boolean;
77
58
  /** Add select-all option. Throws an error if true while multiple = false */
78
59
  allowSelectAll?: boolean;
60
+ /** Custom option label. NOTE: This is required when option is an object */
61
+ optionLabel?: (option: T) => string;
79
62
  /** Custom option template */
80
63
  optionComponent?: (option: T, isSelected: boolean) => ReactNode;
81
64
  /** Disable use of react portal for dropdown
82
65
  * @deprecated Autocomplete now uses the native popover api to render the dropdown. This prop will be removed in a future version
83
66
  */
84
67
  disablePortal?: boolean;
68
+ /** Disable option
69
+ * @default () => false
70
+ */
71
+ optionDisabled?: (option: T) => boolean;
85
72
  /** Custom filter function for options */
86
73
  optionsFilter?: (option: T, inputValue: string) => boolean;
87
74
  /** If `true` the width of the dropdown will adjust to the width of the input */
@@ -104,11 +91,11 @@ export type AutocompleteProps<T> = {
104
91
  * Method that is used to compare objects by value. If omitted, objects are matched by reference.
105
92
  */
106
93
  itemCompare?: (value: T, compare: T) => boolean;
107
- } & HTMLAttributes<HTMLDivElement> & OptionLabelProps<T>;
94
+ } & HTMLAttributes<HTMLDivElement>;
108
95
  declare function AutocompleteInner<T>(props: AutocompleteProps<T>, ref: React.ForwardedRef<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
109
96
  export declare const Autocomplete: <T>(props: {
110
97
  /** List of options in dropdown */
111
- options: T[];
98
+ options: readonly T[];
112
99
  /** Label for the select element */
113
100
  label: ReactNode;
114
101
  /** Array of initial selected items
@@ -160,12 +147,18 @@ export declare const Autocomplete: <T>(props: {
160
147
  multiple?: boolean;
161
148
  /** Add select-all option. Throws an error if true while multiple = false */
162
149
  allowSelectAll?: boolean;
150
+ /** Custom option label. NOTE: This is required when option is an object */
151
+ optionLabel?: (option: T) => string;
163
152
  /** Custom option template */
164
153
  optionComponent?: (option: T, isSelected: boolean) => ReactNode;
165
154
  /** Disable use of react portal for dropdown
166
155
  * @deprecated Autocomplete now uses the native popover api to render the dropdown. This prop will be removed in a future version
167
156
  */
168
157
  disablePortal?: boolean;
158
+ /** Disable option
159
+ * @default () => false
160
+ */
161
+ optionDisabled?: (option: T) => boolean;
169
162
  /** Custom filter function for options */
170
163
  optionsFilter?: (option: T, inputValue: string) => boolean;
171
164
  /** If `true` the width of the dropdown will adjust to the width of the input */
@@ -188,7 +181,7 @@ export declare const Autocomplete: <T>(props: {
188
181
  * Method that is used to compare objects by value. If omitted, objects are matched by reference.
189
182
  */
190
183
  itemCompare?: (value: T, compare: T) => boolean;
191
- } & HTMLAttributes<HTMLDivElement> & OptionLabelProps<T> & {
184
+ } & HTMLAttributes<HTMLDivElement> & {
192
185
  ref?: React.ForwardedRef<HTMLDivElement>;
193
186
  /** @ignore */
194
187
  displayName?: string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/eds-core-react",
3
- "version": "0.39.0",
3
+ "version": "0.39.1-dev13062024",
4
4
  "description": "The React implementation of the Equinor Design System",
5
5
  "sideEffects": [
6
6
  "**/*.css"
@@ -86,16 +86,12 @@
86
86
  "@react-stately/datepicker": "^3.9.3",
87
87
  "@react-types/shared": "^3.23.0",
88
88
  "@tanstack/react-virtual": "3.5.0",
89
- "downshift": "9.0.4",
89
+ "downshift": "9.0.6",
90
90
  "react-aria": "^3.33.0",
91
91
  "@equinor/eds-icons": "^0.21.0",
92
92
  "@equinor/eds-tokens": "0.9.2",
93
93
  "@equinor/eds-utils": "0.8.5"
94
94
  },
95
- "engines": {
96
- "pnpm": ">=4",
97
- "node": ">=10.0.0"
98
- },
99
95
  "scripts": {
100
96
  "build": "rollup -c --bundleConfigAsCjs && tsc -p tsconfig.build.json",
101
97
  "test": "tsc -p tsconfig.test.json && jest",