@leafygreen-ui/combobox 6.0.4 → 6.0.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.
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ export declare const getComboboxOptions: (withGlyphs?: boolean) => JSX.Element[];
3
+ //# sourceMappingURL=getTestOptions.testutils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTestOptions.testutils.d.ts","sourceRoot":"","sources":["../../src/test-utils/getTestOptions.testutils.tsx"],"names":[],"mappings":";AAMA,eAAO,MAAM,kBAAkB,yCA4E9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafygreen-ui/combobox",
3
- "version": "6.0.4",
3
+ "version": "6.0.6",
4
4
  "description": "leafyGreen UI Kit Combobox",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -20,18 +20,18 @@
20
20
  "access": "public"
21
21
  },
22
22
  "dependencies": {
23
- "@leafygreen-ui/checkbox": "^12.0.11",
23
+ "@leafygreen-ui/checkbox": "^12.0.12",
24
24
  "@leafygreen-ui/emotion": "^4.0.4",
25
- "@leafygreen-ui/hooks": "^7.7.4",
26
- "@leafygreen-ui/icon": "^11.16.1",
27
- "@leafygreen-ui/icon-button": "^15.0.11",
28
- "@leafygreen-ui/inline-definition": "^6.0.6",
29
- "@leafygreen-ui/input-option": "^1.0.4",
30
- "@leafygreen-ui/lib": "^10.3.4",
25
+ "@leafygreen-ui/hooks": "^7.7.5",
26
+ "@leafygreen-ui/icon": "^11.17.0",
27
+ "@leafygreen-ui/icon-button": "^15.0.12",
28
+ "@leafygreen-ui/inline-definition": "^6.0.7",
29
+ "@leafygreen-ui/input-option": "^1.0.5",
30
+ "@leafygreen-ui/lib": "^10.4.0",
31
31
  "@leafygreen-ui/palette": "^4.0.4",
32
- "@leafygreen-ui/popover": "^11.0.10",
33
- "@leafygreen-ui/tokens": "^2.1.0",
34
- "@leafygreen-ui/typography": "^16.5.0",
32
+ "@leafygreen-ui/popover": "^11.0.12",
33
+ "@leafygreen-ui/tokens": "^2.1.1",
34
+ "@leafygreen-ui/typography": "^16.5.1",
35
35
  "chalk": "^4.1.2",
36
36
  "lodash": "^4.17.21",
37
37
  "polished": "^4.2.2"
@@ -40,7 +40,7 @@
40
40
  "@leafygreen-ui/leafygreen-provider": "^3.1.3"
41
41
  },
42
42
  "devDependencies": {
43
- "@leafygreen-ui/button": "^20.1.0"
43
+ "@leafygreen-ui/button": "^20.2.1"
44
44
  },
45
45
  "homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/combobox",
46
46
  "repository": {
@@ -0,0 +1,35 @@
1
+ /* eslint-disable react/display-name */
2
+ import React from 'react';
3
+
4
+ import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider';
5
+ import { StoryMetaType } from '@leafygreen-ui/lib';
6
+
7
+ import { Chip } from './Chip';
8
+
9
+ const meta: StoryMetaType<typeof Chip> = {
10
+ title: 'Components/Combobox/Chip',
11
+ component: Chip,
12
+ parameters: {
13
+ default: null,
14
+ generate: {
15
+ combineArgs: {
16
+ darkMode: [false, true],
17
+ displayName: [
18
+ 'Chip',
19
+ '5f4dcc3b5aa765d61d8327deb882cf995f4dcc3b5aa765d61d8327deb882cf99',
20
+ ],
21
+ },
22
+ args: {},
23
+ decorator: (Instance, context) => {
24
+ return (
25
+ <LeafyGreenProvider darkMode={context?.args.darkMode}>
26
+ <Instance />
27
+ </LeafyGreenProvider>
28
+ );
29
+ },
30
+ },
31
+ },
32
+ };
33
+ export default meta;
34
+
35
+ export const Generated = () => <></>;
@@ -3,13 +3,14 @@ import { StoryFn } from '@storybook/react';
3
3
 
4
4
  import Button from '@leafygreen-ui/button';
5
5
  import { css } from '@leafygreen-ui/emotion';
6
- import Icon from '@leafygreen-ui/icon';
7
6
  import {
8
7
  storybookArgTypes,
9
8
  storybookExcludedControlParams,
10
9
  type StoryMetaType,
10
+ StoryType,
11
11
  } from '@leafygreen-ui/lib';
12
12
 
13
+ import { getComboboxOptions } from './test-utils/getTestOptions.testutils';
13
14
  import {
14
15
  ComboboxSize,
15
16
  Overflow,
@@ -17,7 +18,7 @@ import {
17
18
  State,
18
19
  TruncationLocation,
19
20
  } from './Combobox.types';
20
- import { Combobox, ComboboxGroup, ComboboxOption, ComboboxProps } from '.';
21
+ import { Combobox, ComboboxOption, ComboboxProps } from '.';
21
22
 
22
23
  const wrapperStyle = css`
23
24
  width: 256px;
@@ -25,6 +26,8 @@ const wrapperStyle = css`
25
26
  display: flex;
26
27
  `;
27
28
 
29
+ const multiValue = ['apple', 'banana'];
30
+
28
31
  const meta: StoryMetaType<typeof Combobox> = {
29
32
  title: 'Components/Combobox',
30
33
  component: Combobox,
@@ -36,7 +39,7 @@ const meta: StoryMetaType<typeof Combobox> = {
36
39
  ),
37
40
  ],
38
41
  parameters: {
39
- default: 'Demo',
42
+ default: 'LiveExample',
40
43
  controls: {
41
44
  exclude: [
42
45
  ...storybookExcludedControlParams,
@@ -48,27 +51,54 @@ const meta: StoryMetaType<typeof Combobox> = {
48
51
  'children',
49
52
  ],
50
53
  },
54
+ generate: {
55
+ storyNames: ['SingleSelect', 'MultiSelect'],
56
+ combineArgs: {
57
+ darkMode: [false, true],
58
+ clearable: [true, false],
59
+ description: [undefined, 'Please pick fruit(s)'],
60
+ label: [undefined, 'Choose a fruit'],
61
+ state: Object.values(State),
62
+ size: Object.values(ComboboxSize),
63
+ },
64
+ excludeCombinations: [
65
+ ['description', { label: undefined }],
66
+ {
67
+ clearable: false,
68
+ value: undefined,
69
+ },
70
+ {
71
+ multiselect: true,
72
+ value: 'apple',
73
+ },
74
+ {
75
+ multiselect: false,
76
+ value: multiValue,
77
+ },
78
+ ],
79
+ },
51
80
  },
81
+
82
+ args: {
83
+ label: 'Choose a fruit',
84
+ description: 'Please pick fruit(s)',
85
+ placeholder: 'Select fruit',
86
+ multiselect: false,
87
+ darkMode: false,
88
+ disabled: false,
89
+ clearable: true,
90
+ errorMessage: 'No Pomegranates!',
91
+ children: getComboboxOptions(),
92
+ },
93
+
52
94
  argTypes: {
53
95
  darkMode: storybookArgTypes.darkMode,
54
- multiselect: {
55
- control: 'boolean',
56
- },
57
- disabled: {
58
- control: 'boolean',
59
- },
60
- clearable: {
61
- control: 'boolean',
62
- },
63
- label: {
64
- control: 'text',
65
- },
66
- description: {
67
- control: 'text',
68
- },
69
- placeholder: {
70
- control: 'text',
71
- },
96
+ multiselect: { control: 'boolean' },
97
+ disabled: { control: 'boolean' },
98
+ clearable: { control: 'boolean' },
99
+ label: { control: 'text' },
100
+ description: { control: 'text' },
101
+ placeholder: { control: 'text' },
72
102
  size: {
73
103
  options: Object.values(ComboboxSize),
74
104
  control: 'select',
@@ -79,11 +109,8 @@ const meta: StoryMetaType<typeof Combobox> = {
79
109
  },
80
110
  errorMessage: {
81
111
  control: 'text',
82
- if: { arg: 'state', eq: State.error },
83
- },
84
- searchEmptyMessage: {
85
- control: 'text',
86
112
  },
113
+ searchEmptyMessage: { control: 'text' },
87
114
  searchState: {
88
115
  options: Object.values(SearchState),
89
116
  control: 'select',
@@ -111,164 +138,26 @@ const meta: StoryMetaType<typeof Combobox> = {
111
138
  if: { arg: 'multiselect' },
112
139
  },
113
140
  },
114
- args: {
115
- multiselect: false,
116
- darkMode: false,
117
- disabled: false,
118
- clearable: true,
119
- },
120
141
  };
121
142
 
122
143
  export default meta;
123
144
 
124
- const getComboboxOptions = (withGlyphs = true) => [
125
- <ComboboxOption
126
- key="apple"
127
- value="apple"
128
- displayName="Apple"
129
- data-testid="test-id"
130
- description="Do I keep the doctor away?"
131
- // eslint-disable-next-line no-console
132
- onClick={(event, value) => console.log(event, value)}
133
- className="className"
134
- />,
135
- <ComboboxOption key="banana" value="banana" displayName="Banana" />,
136
- <ComboboxOption key="carrot" value="carrot" displayName="Carrot" disabled />,
137
- <ComboboxOption
138
- key="pomegranate"
139
- value="pomegranate"
140
- displayName="Pomegranate"
141
- glyph={withGlyphs ? <Icon glyph="Warning" /> : undefined}
142
- description="Watch out, I stain everything I touch LOL"
143
- disabled
144
- />,
145
- <ComboboxOption
146
- key="plantain"
147
- value="plantain"
148
- displayName="Plantain"
149
- glyph={withGlyphs ? <Icon glyph="Connect" /> : undefined}
150
- description="Don't confuse me with a banana"
151
- // eslint-disable-next-line no-console
152
- onClick={() => console.log('I was clicked')}
153
- />,
154
- <ComboboxOption
155
- key="paragraph"
156
- value="paragraph"
157
- displayName="Nullam quis risus eget urna mollis ornare vel eu leo. Vestibulum id ligula porta felis euismod semper."
158
- />,
159
- <ComboboxOption
160
- key="hash"
161
- value="hash"
162
- displayName="5f4dcc3b5aa765d61d8327deb882cf995f4dcc3b5aa765d61d8327deb882cf99"
163
- />,
164
- <ComboboxOption
165
- key="dragonfruit"
166
- value="dragonfruit"
167
- displayName="Dragonfruit"
168
- description="Rawr"
169
- />,
170
- <ComboboxOption key="eggplant" value="eggplant" displayName="Eggplant" />,
171
- <ComboboxOption key="fig" value="fig" displayName="Fig" />,
172
- <ComboboxOption key="grape" value="grape" displayName="Grape" />,
173
- <ComboboxOption key="honeydew" value="honeydew" displayName="Honeydew" />,
174
- <ComboboxOption
175
- key="iceberg-lettuce"
176
- value="iceberg-lettuce"
177
- displayName="Iceberg lettuce"
178
- />,
179
- <ComboboxGroup key="peppers" label="Peppers">
180
- <ComboboxOption key="cayenne" value="cayenne" displayName="Cayenne" />
181
- <ComboboxOption
182
- key="ghost-pepper"
183
- value="ghost-pepper"
184
- displayName="Ghost pepper"
185
- />
186
- <ComboboxOption key="habanero" value="habanero" displayName="Habanero" />
187
- <ComboboxOption key="jalapeno" value="jalapeno" displayName="Jalapeño" />
188
- <ComboboxOption
189
- key="red-pepper"
190
- value="red-pepper"
191
- displayName="Red pepper"
192
- />
193
- <ComboboxOption
194
- key="scotch-bonnet"
195
- value="scotch-bonnet"
196
- displayName="Scotch bonnet"
197
- description="Don't touch your eyes"
198
- />
199
- </ComboboxGroup>,
200
- ];
201
-
202
- const SingleTemplate: StoryFn<ComboboxProps<false>> = (
203
- args: ComboboxProps<false>,
204
- ) => <Combobox {...args} />;
205
-
206
- export const SingleSelect: StoryFn<ComboboxProps<false>> = (
207
- args: ComboboxProps<false>,
208
- ) => <Combobox {...args} />;
209
- SingleSelect.args = {
210
- label: 'Choose a fruit',
211
- description: 'Please pick one',
212
- placeholder: 'Select fruit',
213
- multiselect: false,
214
- // children: getComboboxOptions(),
215
- };
216
- SingleSelect.argTypes = {
217
- multiselect: { control: 'none' },
218
- };
219
-
220
- export const SingleSelectWithoutGlyphs = SingleTemplate.bind({});
221
- SingleSelectWithoutGlyphs.args = {
222
- label: 'Choose a fruit',
223
- description: 'Please pick one',
224
- placeholder: 'Select fruit',
225
- multiselect: false,
226
- children: getComboboxOptions(false),
227
- };
228
- SingleSelectWithoutGlyphs.argTypes = {
229
- multiselect: { control: 'none' },
230
- };
231
-
232
- export const WithError = SingleTemplate.bind({});
233
- WithError.args = {
234
- label: 'Choose a fruit',
235
- description: 'Please pick one',
236
- placeholder: 'Select fruit',
237
- value: 'pomegranates',
238
- errorMessage: 'No Pomegranates!',
239
- state: 'error',
240
- };
241
-
242
- const MultiTemplate: StoryFn<ComboboxProps<true>> = (
243
- args: ComboboxProps<true>,
244
- ) => <Combobox {...args} />;
245
-
246
- export const Multiselect = MultiTemplate.bind({});
247
- Multiselect.args = {
248
- label: 'Choose a fruit',
249
- description: 'Please pick some',
250
- placeholder: 'Select fruit',
251
- multiselect: true,
252
- children: getComboboxOptions(),
253
- };
254
- Multiselect.argTypes = {
255
- multiselect: {
256
- control: 'none',
257
- },
258
- };
259
-
260
- export const MultiselectWithoutGlyphs = MultiTemplate.bind({});
261
- MultiselectWithoutGlyphs.args = {
262
- label: 'Choose a fruit',
263
- description: 'Please pick some',
264
- placeholder: 'Select fruit',
265
- multiselect: true,
266
- children: getComboboxOptions(false),
145
+ export const LiveExample: StoryFn<ComboboxProps<boolean>> = (
146
+ args: ComboboxProps<boolean>,
147
+ ) => {
148
+ return (
149
+ <>
150
+ {/* Since Combobox doesn't fully refresh when `multiselect` changes, we need to explicitly render a different instance */}
151
+ {args.multiselect ? (
152
+ <Combobox key="multi" {...args} multiselect={true} />
153
+ ) : (
154
+ <Combobox key="single" {...args} multiselect={false} />
155
+ )}
156
+ </>
157
+ );
267
158
  };
268
- MultiselectWithoutGlyphs.argTypes = {
269
- multiselect: {
270
- control: 'none',
271
- },
159
+ LiveExample.parameters = {
160
+ chromatic: { disableSnapshot: true },
272
161
  };
273
162
 
274
163
  export const ControlledSingleSelect = () => {
@@ -296,6 +185,9 @@ export const ControlledSingleSelect = () => {
296
185
  </div>
297
186
  );
298
187
  };
188
+ ControlledSingleSelect.parameters = {
189
+ chromatic: { disableSnapshot: true },
190
+ };
299
191
 
300
192
  export const ExternalFilter = () => {
301
193
  const allOptions = [
@@ -333,24 +225,30 @@ export const ExternalFilter = () => {
333
225
  </Combobox>
334
226
  );
335
227
  };
228
+ ExternalFilter.parameters = {
229
+ chromatic: { disableSnapshot: true },
230
+ };
336
231
 
337
- export const Demo: StoryFn<ComboboxProps<boolean>> = (
338
- args: ComboboxProps<boolean>,
339
- ) => {
340
- return (
341
- <>
342
- {/* Since Combobox doesn't fully refresh when `multiselect` changes, we need to explicitly render a different instance */}
343
- {args.multiselect ? (
344
- <Combobox key="multi" {...args} multiselect={true} />
345
- ) : (
346
- <Combobox key="single" {...args} multiselect={false} />
347
- )}
348
- </>
349
- );
232
+ export const SingleSelect: StoryType<typeof Combobox> = () => <></>;
233
+ SingleSelect.args = {
234
+ multiselect: false,
235
+ };
236
+ SingleSelect.parameters = {
237
+ generate: {
238
+ combineArgs: {
239
+ value: [undefined, 'apple'],
240
+ },
241
+ },
350
242
  };
351
- Demo.args = {
352
- label: 'Choose a fruit',
353
- description: 'Please pick fruit(s)',
354
- placeholder: 'Select fruit',
355
- children: getComboboxOptions(),
243
+
244
+ export const MultiSelect = () => <></>;
245
+ MultiSelect.args = {
246
+ multiselect: true,
247
+ };
248
+ MultiSelect.parameters = {
249
+ generate: {
250
+ combineArgs: {
251
+ value: [undefined, multiValue],
252
+ },
253
+ },
356
254
  };
@@ -56,8 +56,8 @@ export const Overflow = {
56
56
  export type Overflow = typeof Overflow[keyof typeof Overflow];
57
57
 
58
58
  export const State = {
59
- error: 'error',
60
59
  none: 'none',
60
+ error: 'error',
61
61
  } as const;
62
62
  export type State = typeof State[keyof typeof State];
63
63
 
@@ -8,7 +8,7 @@ import {
8
8
  TruncationLocation,
9
9
  } from '../Combobox.types';
10
10
 
11
- interface ComboboxData {
11
+ export interface ComboboxData {
12
12
  multiselect: boolean;
13
13
  size: ComboboxSize;
14
14
  withIcons: boolean;
@@ -23,7 +23,7 @@ interface ComboboxData {
23
23
  popoverZIndex?: number;
24
24
  }
25
25
 
26
- export const ComboboxContext = createContext<ComboboxData>({
26
+ export const defaultContext = {
27
27
  multiselect: false,
28
28
  size: ComboboxSize.Default,
29
29
  withIcons: false,
@@ -32,4 +32,6 @@ export const ComboboxContext = createContext<ComboboxData>({
32
32
  state: State.none,
33
33
  searchState: SearchState.unset,
34
34
  overflow: Overflow.expandY,
35
- });
35
+ };
36
+
37
+ export const ComboboxContext = createContext<ComboboxData>(defaultContext);
@@ -0,0 +1,47 @@
1
+ /* eslint-disable react/display-name */
2
+ import React from 'react';
3
+
4
+ import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider';
5
+ import { StoryMetaType } from '@leafygreen-ui/lib';
6
+
7
+ import { InternalComboboxOption } from '../ComboboxOption';
8
+
9
+ import { InternalComboboxGroup } from './ComboboxGroup';
10
+
11
+ const meta: StoryMetaType<typeof InternalComboboxGroup> = {
12
+ title: 'Components/Combobox/ComboboxGroup',
13
+ component: InternalComboboxGroup,
14
+ parameters: {
15
+ default: null,
16
+ generate: {
17
+ combineArgs: {
18
+ darkMode: [false, true],
19
+ },
20
+ args: {
21
+ label: 'Label',
22
+ children: (
23
+ <>
24
+ <InternalComboboxOption
25
+ value="option"
26
+ displayName="Option"
27
+ isSelected={false}
28
+ isFocused={false}
29
+ setSelected={() => {}}
30
+ index={0}
31
+ />
32
+ </>
33
+ ),
34
+ },
35
+ decorator: (Instance, context) => {
36
+ return (
37
+ <LeafyGreenProvider darkMode={context?.args.darkMode}>
38
+ <Instance />
39
+ </LeafyGreenProvider>
40
+ );
41
+ },
42
+ },
43
+ },
44
+ };
45
+ export default meta;
46
+
47
+ export const Generated = () => <></>;
@@ -0,0 +1,70 @@
1
+ /* eslint-disable react/display-name, react/jsx-key */
2
+ import React from 'react';
3
+
4
+ import Icon from '@leafygreen-ui/icon';
5
+ import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider';
6
+ import { StoryMetaType, StoryType } from '@leafygreen-ui/lib';
7
+
8
+ import { ComboboxContext } from '../ComboboxContext';
9
+ import { defaultContext } from '../ComboboxContext/ComboboxContext';
10
+
11
+ import { InternalComboboxOption } from './ComboboxOption';
12
+
13
+ const meta: StoryMetaType<typeof InternalComboboxOption> = {
14
+ title: 'Components/Combobox/ComboboxOption',
15
+ component: InternalComboboxOption,
16
+ parameters: {
17
+ default: null,
18
+ generate: {
19
+ storyNames: ['WithIcons', 'WithoutIcons'],
20
+ combineArgs: {
21
+ darkMode: [false, true],
22
+ description: [undefined, 'This is a description'],
23
+ isSelected: [false, true],
24
+ isFocused: [false, true],
25
+ disabled: [false, true],
26
+ },
27
+ decorator: (Instance, context) => {
28
+ return (
29
+ <LeafyGreenProvider darkMode={context?.args.darkMode}>
30
+ <ComboboxContext.Provider
31
+ value={{ ...defaultContext, withIcons: context?.args.withIcons }}
32
+ >
33
+ <Instance glyph={context?.args.glyph} />
34
+ </ComboboxContext.Provider>
35
+ </LeafyGreenProvider>
36
+ );
37
+ },
38
+ },
39
+ },
40
+ args: {
41
+ displayName: 'Option',
42
+ setSelected: () => {},
43
+ },
44
+ };
45
+
46
+ export default meta;
47
+
48
+ export const WithoutIcons: StoryType<typeof InternalComboboxOption> = () => (
49
+ <></>
50
+ );
51
+ WithoutIcons.parameters = {
52
+ generate: {
53
+ args: {
54
+ /// @ts-expect-error - withIcons is not a component prop
55
+ withIcons: false,
56
+ glyph: undefined,
57
+ },
58
+ },
59
+ };
60
+
61
+ export const WithIcons: StoryType<typeof InternalComboboxOption> = () => <></>;
62
+ WithIcons.parameters = {
63
+ generate: {
64
+ args: {
65
+ /// @ts-expect-error - withIcons is not a component prop
66
+ withIcons: true,
67
+ glyph: <Icon glyph="Cloud" />,
68
+ },
69
+ },
70
+ };