@leafygreen-ui/combobox 1.0.0 → 1.0.3

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/src/Combobox.tsx CHANGED
@@ -5,7 +5,7 @@ import React, {
5
5
  useRef,
6
6
  useState,
7
7
  } from 'react';
8
- import { clone, isArray, isNull, isString, isUndefined } from 'lodash';
8
+ import { clone, isArray, isEqual, isNull, isString, isUndefined } from 'lodash';
9
9
  import { Description, Label } from '@leafygreen-ui/typography';
10
10
  import Popover from '@leafygreen-ui/popover';
11
11
  import {
@@ -20,7 +20,7 @@ import Icon from '@leafygreen-ui/icon';
20
20
  import IconButton from '@leafygreen-ui/icon-button';
21
21
  import { cx } from '@leafygreen-ui/emotion';
22
22
  import { uiColors } from '@leafygreen-ui/palette';
23
- import { isComponentType } from '@leafygreen-ui/lib';
23
+ import { consoleOnce, isComponentType } from '@leafygreen-ui/lib';
24
24
  import {
25
25
  ComboboxProps,
26
26
  getNullSelection,
@@ -114,8 +114,19 @@ export default function Combobox<M extends boolean>({
114
114
 
115
115
  // Tells typescript that selection is multiselect
116
116
  const isMultiselect = useCallback(
117
- <T extends number | string>(test: Array<T> | T | null): test is Array<T> =>
118
- multiselect && isArray(test),
117
+ <T extends string>(val?: Array<T> | T | null): val is Array<T> => {
118
+ if (multiselect && (typeof val == 'string' || typeof val == 'number')) {
119
+ consoleOnce.error(
120
+ `Error in Combobox: multiselect is set to \`true\`, but recieved a ${typeof val} value: "${val}"`,
121
+ );
122
+ } else if (!multiselect && isArray(val)) {
123
+ consoleOnce.error(
124
+ 'Error in Combobox: multiselect is set to `false`, but recieved an Array value',
125
+ );
126
+ }
127
+
128
+ return multiselect && isArray(val);
129
+ },
119
130
  [multiselect],
120
131
  );
121
132
 
@@ -211,10 +222,10 @@ export default function Combobox<M extends boolean>({
211
222
  [filteredOptions, getDisplayNameForValue, inputValue],
212
223
  );
213
224
 
214
- const visibleOptions = useMemo(() => allOptions.filter(isOptionVisible), [
215
- allOptions,
216
- isOptionVisible,
217
- ]);
225
+ const visibleOptions = useMemo(
226
+ () => allOptions.filter(isOptionVisible),
227
+ [allOptions, isOptionVisible],
228
+ );
218
229
 
219
230
  const isValueValid = useCallback(
220
231
  (value: string | null): boolean => {
@@ -497,10 +508,8 @@ export default function Combobox<M extends boolean>({
497
508
 
498
509
  if (focusedElementRef && focusedElementRef.current && menuRef.current) {
499
510
  const { offsetTop: optionTop } = focusedElementRef.current;
500
- const {
501
- scrollTop: menuScroll,
502
- offsetHeight: menuHeight,
503
- } = menuRef.current;
511
+ const { scrollTop: menuScroll, offsetHeight: menuHeight } =
512
+ menuRef.current;
504
513
 
505
514
  if (optionTop > menuHeight || optionTop < menuScroll) {
506
515
  menuRef.current.scrollTop = optionTop;
@@ -583,10 +592,10 @@ export default function Combobox<M extends boolean>({
583
592
  ],
584
593
  );
585
594
 
586
- const renderedOptions = useMemo(() => renderInternalOptions(children), [
587
- children,
588
- renderInternalOptions,
589
- ]);
595
+ const renderedOptions = useMemo(
596
+ () => renderInternalOptions(children),
597
+ [children, renderInternalOptions],
598
+ );
590
599
 
591
600
  const renderedChips = useMemo(() => {
592
601
  if (isMultiselect(selection)) {
@@ -676,9 +685,10 @@ export default function Combobox<M extends boolean>({
676
685
  ]);
677
686
 
678
687
  // Do any of the options have an icon?
679
- const withIcons = useMemo(() => allOptions.some(opt => opt.hasGlyph), [
680
- allOptions,
681
- ]);
688
+ const withIcons = useMemo(
689
+ () => allOptions.some(opt => opt.hasGlyph),
690
+ [allOptions],
691
+ );
682
692
 
683
693
  /**
684
694
  *
@@ -770,7 +780,7 @@ export default function Combobox<M extends boolean>({
770
780
  // onSelect
771
781
  // Side effects to run when the selection changes
772
782
  useEffect(() => {
773
- if (selection !== prevSelection) {
783
+ if (!isEqual(selection, prevSelection)) {
774
784
  onSelect();
775
785
  }
776
786
  }, [onSelect, prevSelection, selection]);
@@ -848,10 +858,8 @@ export default function Combobox<M extends boolean>({
848
858
  const menuMargin = 8;
849
859
 
850
860
  if (viewportSize && comboboxRef.current && menuRef.current) {
851
- const {
852
- top: triggerTop,
853
- bottom: triggerBottom,
854
- } = comboboxRef.current.getBoundingClientRect();
861
+ const { top: triggerTop, bottom: triggerBottom } =
862
+ comboboxRef.current.getBoundingClientRect();
855
863
 
856
864
  // Find out how much space is available above or below the trigger
857
865
  const safeSpace = Math.max(
@@ -880,7 +888,7 @@ export default function Combobox<M extends boolean>({
880
888
 
881
889
  // Prevent combobox from gaining focus by default
882
890
  const handleInputWrapperMousedown = (e: React.MouseEvent) => {
883
- if (e.target !== inputRef.current) {
891
+ if (disabled) {
884
892
  e.preventDefault();
885
893
  }
886
894
  };
@@ -976,13 +984,7 @@ export default function Combobox<M extends boolean>({
976
984
  break;
977
985
  }
978
986
 
979
- case keyMap.Enter:
980
- case keyMap.Space: {
981
- if (isOpen) {
982
- // prevent typing the space character
983
- event.preventDefault();
984
- }
985
-
987
+ case keyMap.Enter: {
986
988
  if (
987
989
  // Focused on input element
988
990
  document.activeElement === inputRef.current &&
@@ -16,7 +16,8 @@ export const TrunctationLocation = {
16
16
  end: 'end',
17
17
  none: 'none',
18
18
  } as const;
19
- export type TrunctationLocation = typeof TrunctationLocation[keyof typeof TrunctationLocation];
19
+ export type TrunctationLocation =
20
+ typeof TrunctationLocation[keyof typeof TrunctationLocation];
20
21
 
21
22
  export const Overflow = {
22
23
  expandY: 'expand-y',
@@ -55,7 +56,7 @@ export function getNullSelection<M extends boolean>(
55
56
  multiselect: M,
56
57
  ): SelectValueType<M> {
57
58
  if (multiselect) {
58
- return ([] as Array<string>) as SelectValueType<M>;
59
+ return [] as Array<string> as SelectValueType<M>;
59
60
  } else {
60
61
  return null as SelectValueType<M>;
61
62
  }
@@ -91,9 +91,8 @@ const InternalComboboxOption = React.forwardRef<
91
91
  }: InternalComboboxOptionProps,
92
92
  forwardedRef,
93
93
  ) => {
94
- const { multiselect, darkMode, withIcons, inputValue } = useContext(
95
- ComboboxContext,
96
- );
94
+ const { multiselect, darkMode, withIcons, inputValue } =
95
+ useContext(ComboboxContext);
97
96
  const optionTextId = useIdAllocator({ prefix: 'combobox-option-text' });
98
97
  const optionRef = useForwardedRef(forwardedRef, null);
99
98