@leafygreen-ui/combobox 5.0.8 → 5.0.10

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 (79) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/{Chip.d.ts → Chip/Chip.d.ts} +1 -1
  3. package/dist/Chip/Chip.d.ts.map +1 -0
  4. package/dist/Chip/Chip.styles.d.ts +23 -0
  5. package/dist/Chip/Chip.styles.d.ts.map +1 -0
  6. package/dist/Chip/index.d.ts +2 -0
  7. package/dist/Chip/index.d.ts.map +1 -0
  8. package/dist/{Combobox.d.ts → Combobox/Combobox.d.ts} +1 -1
  9. package/dist/Combobox/Combobox.d.ts.map +1 -0
  10. package/dist/{Combobox.styles.d.ts → Combobox/Combobox.styles.d.ts} +1 -12
  11. package/dist/Combobox/Combobox.styles.d.ts.map +1 -0
  12. package/dist/Combobox/index.d.ts +2 -0
  13. package/dist/Combobox/index.d.ts.map +1 -0
  14. package/dist/{ComboboxContext.d.ts → ComboboxContext/ComboboxContext.d.ts} +1 -4
  15. package/dist/ComboboxContext/ComboboxContext.d.ts.map +1 -0
  16. package/dist/ComboboxContext/index.d.ts +2 -0
  17. package/dist/ComboboxContext/index.d.ts.map +1 -0
  18. package/dist/{ComboboxGroup.d.ts → ComboboxGroup/ComboboxGroup.d.ts} +3 -4
  19. package/dist/ComboboxGroup/ComboboxGroup.d.ts.map +1 -0
  20. package/dist/ComboboxGroup/ComboboxGroup.styles.d.ts +5 -0
  21. package/dist/ComboboxGroup/ComboboxGroup.styles.d.ts.map +1 -0
  22. package/dist/ComboboxGroup/index.d.ts +2 -0
  23. package/dist/ComboboxGroup/index.d.ts.map +1 -0
  24. package/dist/ComboboxMenu/ComboboxMenu.d.ts.map +1 -1
  25. package/dist/ComboboxMenu/index.d.ts +2 -0
  26. package/dist/ComboboxMenu/index.d.ts.map +1 -0
  27. package/dist/{ComboboxOption.d.ts → ComboboxOption/ComboboxOption.d.ts} +5 -4
  28. package/dist/ComboboxOption/ComboboxOption.d.ts.map +1 -0
  29. package/dist/ComboboxOption/ComboboxOption.styles.d.ts +11 -0
  30. package/dist/ComboboxOption/ComboboxOption.styles.d.ts.map +1 -0
  31. package/dist/ComboboxOption/OptionContent.d.ts +4 -0
  32. package/dist/ComboboxOption/OptionContent.d.ts.map +1 -0
  33. package/dist/ComboboxOption/index.d.ts +2 -0
  34. package/dist/ComboboxOption/index.d.ts.map +1 -0
  35. package/dist/esm/index.js +1 -1
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/index.d.ts +1 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +1 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/{ComboboxTestUtils.d.ts → utils/ComboboxTestUtils.d.ts} +1 -1
  42. package/dist/utils/ComboboxTestUtils.d.ts.map +1 -0
  43. package/package.json +11 -10
  44. package/src/Chip/Chip.styles.ts +150 -0
  45. package/src/{Chip.tsx → Chip/Chip.tsx} +18 -138
  46. package/src/Chip/index.ts +1 -0
  47. package/src/{Combobox.spec.tsx → Combobox/Combobox.spec.tsx} +2 -2
  48. package/src/{Combobox.story.tsx → Combobox/Combobox.story.tsx} +3 -3
  49. package/src/{Combobox.styles.ts → Combobox/Combobox.styles.ts} +5 -19
  50. package/src/{Combobox.tsx → Combobox/Combobox.tsx} +192 -257
  51. package/src/Combobox/index.ts +1 -0
  52. package/src/{ComboboxContext.tsx → ComboboxContext/ComboboxContext.tsx} +1 -7
  53. package/src/ComboboxContext/index.ts +1 -0
  54. package/src/ComboboxGroup/ComboboxGroup.styles.ts +34 -0
  55. package/src/ComboboxGroup/ComboboxGroup.tsx +53 -0
  56. package/src/ComboboxGroup/index.ts +1 -0
  57. package/src/ComboboxMenu/ComboboxMenu.tsx +3 -2
  58. package/src/ComboboxMenu/index.ts +1 -0
  59. package/src/ComboboxOption/ComboboxOption.styles.ts +68 -0
  60. package/src/ComboboxOption/ComboboxOption.tsx +107 -0
  61. package/src/ComboboxOption/OptionContent.tsx +87 -0
  62. package/src/ComboboxOption/index.ts +1 -0
  63. package/src/index.ts +1 -1
  64. package/src/{ComboboxTestUtils.tsx → utils/ComboboxTestUtils.tsx} +2 -2
  65. package/tsconfig.json +3 -0
  66. package/tsconfig.tsbuildinfo +1 -1
  67. package/tsdoc.json +540 -3
  68. package/dist/Chip.d.ts.map +0 -1
  69. package/dist/Combobox.d.ts.map +0 -1
  70. package/dist/Combobox.styles.d.ts.map +0 -1
  71. package/dist/ComboboxContext.d.ts.map +0 -1
  72. package/dist/ComboboxGroup.d.ts.map +0 -1
  73. package/dist/ComboboxOption.d.ts.map +0 -1
  74. package/dist/ComboboxTestUtils.d.ts.map +0 -1
  75. package/dist/Menu.styles.d.ts +0 -22
  76. package/dist/Menu.styles.d.ts.map +0 -1
  77. package/src/ComboboxGroup.tsx +0 -80
  78. package/src/ComboboxOption.tsx +0 -329
  79. package/src/Menu.styles.ts +0 -112
@@ -4,6 +4,7 @@ import isUndefined from 'lodash/isUndefined';
4
4
  import { css, cx } from '@leafygreen-ui/emotion';
5
5
  import { useAvailableSpace, useForwardedRef } from '@leafygreen-ui/hooks';
6
6
  import Icon from '@leafygreen-ui/icon';
7
+ import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
7
8
  import { palette } from '@leafygreen-ui/palette';
8
9
  import Popover from '@leafygreen-ui/popover';
9
10
 
@@ -55,8 +56,8 @@ export const ComboboxMenu = React.forwardRef<HTMLDivElement, ComboboxMenuProps>(
55
56
  }: ComboboxMenuProps,
56
57
  forwardedRef,
57
58
  ) => {
58
- const { disabled, darkMode, theme, size, isOpen, searchState } =
59
- useContext(ComboboxContext);
59
+ const { darkMode, theme } = useDarkMode();
60
+ const { disabled, size, isOpen, searchState } = useContext(ComboboxContext);
60
61
  const ref = useForwardedRef(forwardedRef, null);
61
62
 
62
63
  /** The max height of the menu element */
@@ -0,0 +1 @@
1
+ export { ComboboxMenu } from './ComboboxMenu';
@@ -0,0 +1,68 @@
1
+ import { css } from '@leafygreen-ui/emotion';
2
+ import { spacing, typeScales } from '@leafygreen-ui/tokens';
3
+
4
+ import { ComboboxSize } from '../Combobox.types';
5
+ import { menuItemHeight, menuItemPadding } from '../ComboboxMenu/Menu.styles';
6
+
7
+ /**
8
+ * Styles
9
+ */
10
+
11
+ export const comboboxOptionBaseStyle = css`
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: space-between;
15
+ list-style: none;
16
+ `;
17
+
18
+ export const comboboxOptionSizeStyle: Record<ComboboxSize, string> = {
19
+ [ComboboxSize.Default]: css`
20
+ font-size: ${typeScales.body1.fontSize}px;
21
+ line-height: ${typeScales.body1.lineHeight}px;
22
+ min-height: ${menuItemHeight[ComboboxSize.Default]}px;
23
+ padding: ${menuItemPadding[ComboboxSize.Default].y}px
24
+ ${menuItemPadding[ComboboxSize.Default].x}px;
25
+ gap: ${spacing[1]}px;
26
+
27
+ &:before {
28
+ max-height: ${menuItemHeight[ComboboxSize.Default]}px;
29
+ }
30
+ `,
31
+ [ComboboxSize.Large]: css`
32
+ font-size: ${typeScales.body2.fontSize}px;
33
+ line-height: ${typeScales.body2.lineHeight}px;
34
+ min-height: ${menuItemHeight[ComboboxSize.Large]}px;
35
+ padding: ${menuItemPadding[ComboboxSize.Large].y}px
36
+ ${menuItemPadding[ComboboxSize.Large].x}px;
37
+ gap: ${spacing[2]}px;
38
+
39
+ &:before {
40
+ max-height: ${menuItemHeight[ComboboxSize.Large]}px;
41
+ }
42
+ `,
43
+ };
44
+
45
+ export const checkIconStyle: Record<ComboboxSize, string> = {
46
+ [ComboboxSize.Default]: css`
47
+ min-width: ${spacing[3]}px;
48
+ `,
49
+ [ComboboxSize.Large]: css`
50
+ min-width: ${spacing[4]}px;
51
+ `,
52
+ };
53
+
54
+ export const flexSpan = css`
55
+ display: inline-flex;
56
+ gap: 8px;
57
+ justify-content: start;
58
+ align-items: inherit;
59
+ overflow-wrap: anywhere;
60
+ `;
61
+
62
+ export const disallowPointer = css`
63
+ pointer-events: none;
64
+ `;
65
+
66
+ export const displayNameStyle = (isSelected: boolean) => css`
67
+ font-weight: ${isSelected ? 'bold' : 'normal'};
68
+ `;
@@ -0,0 +1,107 @@
1
+ import React, { useCallback, useContext } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import { cx } from '@leafygreen-ui/emotion';
5
+ import { useForwardedRef } from '@leafygreen-ui/hooks';
6
+ import { InputOption } from '@leafygreen-ui/input-option';
7
+ import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
8
+
9
+ import {
10
+ ComboboxOptionProps,
11
+ InternalComboboxOptionProps,
12
+ } from '../Combobox.types';
13
+ import { ComboboxContext } from '../ComboboxContext';
14
+
15
+ import {
16
+ comboboxOptionBaseStyle,
17
+ comboboxOptionSizeStyle,
18
+ } from './ComboboxOption.styles';
19
+ import { OptionContent } from './OptionContent';
20
+
21
+ /**
22
+ * Internal ComboboxOption Component for use within Combobox only.
23
+ *
24
+ * Prefer using {@link ComboboxOption}
25
+ */
26
+ export const InternalComboboxOption = React.forwardRef<
27
+ HTMLLIElement,
28
+ InternalComboboxOptionProps
29
+ >(
30
+ (
31
+ {
32
+ glyph,
33
+ isSelected,
34
+ displayName,
35
+ isFocused,
36
+ disabled,
37
+ setSelected,
38
+ className,
39
+ ...rest
40
+ }: InternalComboboxOptionProps,
41
+ forwardedRef,
42
+ ) => {
43
+ const { darkMode } = useDarkMode();
44
+ const { size } = useContext(ComboboxContext);
45
+ const optionRef = useForwardedRef(forwardedRef, null);
46
+
47
+ const handleOptionClick = useCallback(
48
+ (e: React.SyntheticEvent) => {
49
+ // stopPropagation will not stop the keyDown event (only click)
50
+ // since the option is never `focused`, only `aria-selected`
51
+ // the keyDown event does not actually fire on the option element
52
+ e.stopPropagation();
53
+
54
+ // If user clicked on the option, or the checkbox
55
+ // Ignore extra click events on the checkbox wrapper
56
+ if (
57
+ !disabled &&
58
+ (e.target === optionRef.current ||
59
+ (e.target as Element).tagName === 'INPUT')
60
+ ) {
61
+ setSelected();
62
+ }
63
+ },
64
+ [disabled, optionRef, setSelected],
65
+ );
66
+
67
+ return (
68
+ <InputOption
69
+ {...rest}
70
+ as="li"
71
+ ref={optionRef}
72
+ highlighted={isFocused}
73
+ disabled={disabled}
74
+ aria-label={displayName}
75
+ darkMode={darkMode}
76
+ className={cx(
77
+ comboboxOptionBaseStyle,
78
+ comboboxOptionSizeStyle[size],
79
+ className,
80
+ )}
81
+ onClick={handleOptionClick}
82
+ onKeyDown={handleOptionClick}
83
+ >
84
+ <OptionContent
85
+ disabled={disabled}
86
+ displayName={displayName}
87
+ glyph={glyph}
88
+ isSelected={isSelected}
89
+ />
90
+ </InputOption>
91
+ );
92
+ },
93
+ );
94
+ InternalComboboxOption.displayName = 'ComboboxOption';
95
+
96
+ export function ComboboxOption(_: ComboboxOptionProps): JSX.Element {
97
+ throw Error('`ComboboxOption` must be a child of a `Combobox` instance');
98
+ }
99
+ ComboboxOption.displayName = 'ComboboxOption';
100
+
101
+ ComboboxOption.propTypes = {
102
+ displayName: PropTypes.string,
103
+ value: PropTypes.string,
104
+ glyph: PropTypes.node,
105
+ disabled: PropTypes.bool,
106
+ className: PropTypes.string,
107
+ };
@@ -0,0 +1,87 @@
1
+ import React, { useContext, useMemo } from 'react';
2
+
3
+ import Checkbox from '@leafygreen-ui/checkbox';
4
+ import { cx } from '@leafygreen-ui/emotion';
5
+ import { useIdAllocator } from '@leafygreen-ui/hooks';
6
+ import Icon, { isComponentGlyph } from '@leafygreen-ui/icon';
7
+ import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
8
+ import { palette } from '@leafygreen-ui/palette';
9
+
10
+ import { InternalComboboxOptionProps } from '../Combobox.types';
11
+ import { ComboboxContext } from '../ComboboxContext';
12
+ import { wrapJSX } from '../utils';
13
+
14
+ import {
15
+ checkIconStyle,
16
+ disallowPointer,
17
+ displayNameStyle,
18
+ flexSpan,
19
+ } from './ComboboxOption.styles';
20
+
21
+ export const OptionContent = ({
22
+ disabled,
23
+ displayName,
24
+ glyph,
25
+ isSelected,
26
+ }: Pick<
27
+ InternalComboboxOptionProps,
28
+ 'disabled' | 'displayName' | 'glyph' | 'isSelected'
29
+ >) => {
30
+ const { darkMode } = useDarkMode();
31
+ const { multiselect, withIcons, inputValue, size } =
32
+ useContext(ComboboxContext);
33
+ const optionTextId = useIdAllocator({ prefix: 'combobox-option-text' });
34
+
35
+ const icon = useMemo((): JSX.Element => {
36
+ if (glyph) {
37
+ if (isComponentGlyph(glyph)) {
38
+ return glyph;
39
+ }
40
+ console.error(
41
+ '`ComboboxOption` instance did not render icon because it is not a known glyph element.',
42
+ glyph,
43
+ );
44
+ }
45
+
46
+ return <></>;
47
+ }, [glyph]);
48
+
49
+ const checkbox = (
50
+ <Checkbox
51
+ aria-labelledby={optionTextId}
52
+ checked={isSelected}
53
+ tabIndex={-1}
54
+ disabled={disabled}
55
+ darkMode={darkMode}
56
+ />
57
+ );
58
+
59
+ return multiselect ? (
60
+ <>
61
+ <span className={cx(flexSpan, disallowPointer)}>
62
+ {withIcons ? icon : checkbox}
63
+ <span id={optionTextId} className={displayNameStyle(isSelected)}>
64
+ {wrapJSX(displayName, inputValue, 'strong')}
65
+ </span>
66
+ </span>
67
+ {withIcons && checkbox}
68
+ </>
69
+ ) : (
70
+ // Single select
71
+ <>
72
+ <span className={cx(flexSpan, disallowPointer)}>
73
+ {icon}
74
+ <span className={displayNameStyle(isSelected)}>
75
+ {wrapJSX(displayName, inputValue, 'strong')}
76
+ </span>
77
+ </span>
78
+ {isSelected && (
79
+ <Icon
80
+ glyph="Checkmark"
81
+ className={checkIconStyle[size]}
82
+ color={darkMode ? palette.blue.light1 : palette.blue.base}
83
+ />
84
+ )}
85
+ </>
86
+ );
87
+ };
@@ -0,0 +1 @@
1
+ export { ComboboxOption, InternalComboboxOption } from './ComboboxOption';
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { Combobox } from './Combobox';
2
- export { default as ComboboxGroup } from './ComboboxGroup';
2
+ export { ComboboxGroup } from './ComboboxGroup';
3
3
  export { ComboboxOption } from './ComboboxOption';
@@ -18,8 +18,8 @@ import {
18
18
  BaseComboboxProps,
19
19
  ComboboxMultiselectProps,
20
20
  OptionObject,
21
- } from './Combobox.types';
22
- import { Combobox, ComboboxGroup, ComboboxOption } from '.';
21
+ } from '../Combobox.types';
22
+ import { Combobox, ComboboxGroup, ComboboxOption } from '..';
23
23
 
24
24
  export interface NestedObject {
25
25
  label: string;
package/tsconfig.json CHANGED
@@ -27,6 +27,9 @@
27
27
  {
28
28
  "path": "../inline-definition"
29
29
  },
30
+ {
31
+ "path": "../input-option"
32
+ },
30
33
  {
31
34
  "path": "../lib"
32
35
  },