@khanacademy/wonder-blocks-dropdown 10.0.3 → 10.0.5

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/dist/es/index.js CHANGED
@@ -1,11 +1,10 @@
1
- import _extends from '@babel/runtime/helpers/extends';
1
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { useId } from 'react';
4
4
  import { StyleSheet } from 'aphrodite';
5
5
  import { CompactCell, DetailCell } from '@khanacademy/wonder-blocks-cell';
6
6
  import { spacing, semanticColor, border, sizing, color, font } from '@khanacademy/wonder-blocks-tokens';
7
7
  import { LabelMedium, LabelSmall, LabelLarge } from '@khanacademy/wonder-blocks-typography';
8
- import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
9
8
  import { View, addStyle, keys, Id, useOnMountEffect } from '@khanacademy/wonder-blocks-core';
10
9
  import { Strut } from '@khanacademy/wonder-blocks-layout';
11
10
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
@@ -26,3347 +25,58 @@ import { TextField } from '@khanacademy/wonder-blocks-form';
26
25
  import IconButton from '@khanacademy/wonder-blocks-icon-button';
27
26
  import Pill from '@khanacademy/wonder-blocks-pill';
28
27
 
29
- const selectDropdownStyle = {
30
- marginTop: spacing.xSmall_8,
31
- marginBottom: spacing.xSmall_8
32
- };
33
- const filterableDropdownStyle = {
34
- minHeight: 100
35
- };
36
- const DROPDOWN_ITEM_HEIGHT = 40;
37
- const MAX_VISIBLE_ITEMS = 9;
38
- const SEPARATOR_ITEM_HEIGHT = 9;
39
- const defaultLabels = {
40
- clearSearch: "Clear search",
41
- filter: "Filter",
42
- noResults: "No results",
43
- selectNoneLabel: "Select none",
44
- selectAllLabel: numOptions => `Select all (${numOptions})`,
45
- noneSelected: "0 items",
46
- someSelected: numSelectedValues => numSelectedValues === 1 ? "1 item" : `${numSelectedValues} items`,
47
- allSelected: "All items"
48
- };
49
- const defaultComboboxLabels = {
50
- clearSelection: "Clear selection",
51
- closedState: "Combobox is closed",
52
- comboboxButton: "Toggle listbox",
53
- listbox: "Options list",
54
- removeSelected: label => `Remove ${label}`,
55
- liveRegionCurrentItem: ({
56
- current,
57
- index,
58
- total,
59
- disabled,
60
- focused,
61
- selected
62
- }) => `${current}${focused ? " focused" : ""}${disabled ? " disabled" : ""}${selected ? " selected" : ""}, ${index + 1} of ${total}.`,
63
- liveRegionMultipleSelectionTotal: total => `${total} selected options.`,
64
- liveRegionListboxTotal: total => `${total} results available.`,
65
- noItems: "No results",
66
- selected: labels => `${labels} selected`,
67
- selectionCleared: "Selection cleared",
68
- unselected: labels => `${labels} not selected`
69
- };
28
+ const selectDropdownStyle={marginTop:spacing.xSmall_8,marginBottom:spacing.xSmall_8};const filterableDropdownStyle={minHeight:100};const DROPDOWN_ITEM_HEIGHT=40;const MAX_VISIBLE_ITEMS=9;const SEPARATOR_ITEM_HEIGHT=9;const defaultLabels={clearSearch:"Clear search",filter:"Filter",noResults:"No results",selectNoneLabel:"Select none",selectAllLabel:numOptions=>`Select all (${numOptions})`,noneSelected:"0 items",someSelected:numSelectedValues=>numSelectedValues===1?"1 item":`${numSelectedValues} items`,allSelected:"All items"};const defaultComboboxLabels={clearSelection:"Clear selection",closedState:"Combobox is closed",comboboxButton:"Toggle listbox",listbox:"Options list",removeSelected:label=>`Remove ${label}`,liveRegionCurrentItem:({current,index,total,disabled,focused,selected})=>`${current}${focused?" focused":""}${disabled?" disabled":""}${selected?" selected":""}, ${index+1} of ${total}.`,liveRegionMultipleSelectionTotal:total=>`${total} selected options.`,liveRegionListboxTotal:total=>`${total} results available.`,noItems:"No results",selected:labels=>`${labels} selected`,selectionCleared:"Selection cleared",unselected:labels=>`${labels} not selected`};
70
29
 
71
- class ActionItem extends React.Component {
72
- static isClassOf(instance) {
73
- return instance && instance.type && instance.type.__IS_ACTION_ITEM__;
74
- }
75
- render() {
76
- const {
77
- disabled,
78
- horizontalRule,
79
- href,
80
- target,
81
- indent,
82
- label,
83
- lang,
84
- leftAccessory,
85
- rightAccessory,
86
- onClick,
87
- role,
88
- style,
89
- testId
90
- } = this.props;
91
- const defaultStyle = [styles$b.wrapper, style];
92
- const labelComponent = typeof label === "string" ? React.createElement(LabelMedium, {
93
- lang: lang,
94
- style: styles$b.label
95
- }, label) : (React.cloneElement(label, _extends({
96
- lang,
97
- style: styles$b.label
98
- }, label.props)));
99
- return React.createElement(CompactCell, {
100
- disabled: disabled,
101
- horizontalRule: horizontalRule,
102
- rootStyle: defaultStyle,
103
- leftAccessory: leftAccessory,
104
- rightAccessory: rightAccessory,
105
- style: [styles$b.shared, indent && styles$b.indent],
106
- role: role,
107
- testId: testId,
108
- title: labelComponent,
109
- href: href,
110
- target: target,
111
- onClick: onClick
112
- });
113
- }
114
- }
115
- ActionItem.defaultProps = {
116
- disabled: false,
117
- horizontalRule: "none",
118
- indent: false,
119
- role: "menuitem"
120
- };
121
- ActionItem.__IS_ACTION_ITEM__ = true;
122
- const actionType$1 = semanticColor.action.primary.progressive;
123
- const theme$7 = {
124
- actionItem: {
125
- color: {
126
- hover: {
127
- background: actionType$1.hover.background,
128
- foreground: actionType$1.hover.foreground
129
- },
130
- press: {
131
- background: actionType$1.press.background,
132
- foreground: actionType$1.press.foreground
133
- }
134
- }
135
- }
136
- };
137
- const styles$b = StyleSheet.create({
138
- wrapper: {
139
- minHeight: DROPDOWN_ITEM_HEIGHT,
140
- touchAction: "manipulation",
141
- ":focus": {
142
- borderRadius: border.radius.radius_040,
143
- outline: `${spacing.xxxxSmall_2}px solid ${semanticColor.focus.outer}`,
144
- outlineOffset: -spacing.xxxxSmall_2
145
- },
146
- [":hover[aria-disabled=false]"]: {
147
- color: theme$7.actionItem.color.hover.foreground,
148
- background: theme$7.actionItem.color.hover.background
149
- },
150
- [":active[aria-disabled=false]"]: {
151
- color: theme$7.actionItem.color.press.foreground,
152
- background: theme$7.actionItem.color.press.background
153
- }
154
- },
155
- shared: {
156
- minHeight: DROPDOWN_ITEM_HEIGHT,
157
- paddingBlock: sizing.size_100
158
- },
159
- label: {
160
- whiteSpace: "nowrap",
161
- userSelect: "none"
162
- },
163
- indent: {
164
- paddingLeft: spacing.medium_16 * 2
165
- }
166
- });
30
+ class ActionItem extends React.Component{static isClassOf(instance){return instance&&instance.type&&instance.type.__IS_ACTION_ITEM__}render(){const{disabled,horizontalRule,href,target,indent,label,lang,leftAccessory,rightAccessory,onClick,role,style,testId}=this.props;const defaultStyle=[styles$b.wrapper,style];const labelComponent=typeof label==="string"?jsx(LabelMedium,{lang:lang,style:styles$b.label,children:label}):React.cloneElement(label,{lang,style:styles$b.label,...label.props});return jsx(CompactCell,{disabled:disabled,horizontalRule:horizontalRule,rootStyle:defaultStyle,leftAccessory:leftAccessory,rightAccessory:rightAccessory,style:[styles$b.shared,indent&&styles$b.indent],role:role,testId:testId,title:labelComponent,href:href,target:target,onClick:onClick})}}ActionItem.defaultProps={disabled:false,horizontalRule:"none",indent:false,role:"menuitem"};ActionItem.__IS_ACTION_ITEM__=true;const actionType$1=semanticColor.action.primary.progressive;const theme$7={actionItem:{color:{hover:{background:actionType$1.hover.background,foreground:actionType$1.hover.foreground},press:{background:actionType$1.press.background,foreground:actionType$1.press.foreground}}}};const styles$b=StyleSheet.create({wrapper:{minHeight:DROPDOWN_ITEM_HEIGHT,touchAction:"manipulation",":focus":{borderRadius:border.radius.radius_040,outline:`${spacing.xxxxSmall_2}px solid ${semanticColor.focus.outer}`,outlineOffset:-spacing.xxxxSmall_2},[":hover[aria-disabled=false]"]:{color:theme$7.actionItem.color.hover.foreground,background:theme$7.actionItem.color.hover.background},[":active[aria-disabled=false]"]:{color:theme$7.actionItem.color.press.foreground,background:theme$7.actionItem.color.press.background}},shared:{minHeight:DROPDOWN_ITEM_HEIGHT,paddingBlock:sizing.size_100},label:{whiteSpace:"nowrap",userSelect:"none"},indent:{paddingLeft:spacing.medium_16*2}});
167
31
 
168
- const Check = function Check(props) {
169
- const {
170
- selected
171
- } = props;
172
- return React.createElement(PhosphorIcon, {
173
- icon: checkIcon,
174
- size: "small",
175
- style: [styles$a.bounds, !selected && styles$a.hide]
176
- });
177
- };
178
- const styles$a = StyleSheet.create({
179
- bounds: {
180
- alignSelf: "center",
181
- height: spacing.medium_16,
182
- minHeight: spacing.medium_16,
183
- minWidth: spacing.medium_16
184
- },
185
- hide: {
186
- visibility: "hidden"
187
- }
188
- });
32
+ const Check=function(props){const{selected}=props;return jsx(PhosphorIcon,{icon:checkIcon,size:"small",style:[styles$a.bounds,!selected&&styles$a.hide]})};const styles$a=StyleSheet.create({bounds:{alignSelf:"center",height:spacing.medium_16,minHeight:spacing.medium_16,minWidth:spacing.medium_16},hide:{visibility:"hidden"}});
189
33
 
190
- const Checkbox = function Checkbox(props) {
191
- const {
192
- disabled,
193
- selected
194
- } = props;
195
- return React.createElement(View, {
196
- className: "checkbox",
197
- style: [styles$9.checkbox, selected && !disabled && styles$9.noBorder, disabled && styles$9.disabledCheckbox]
198
- }, selected && React.createElement(PhosphorIcon, {
199
- icon: checkIcon,
200
- size: "small",
201
- className: "check",
202
- style: [{
203
- width: spacing.small_12,
204
- height: spacing.small_12,
205
- margin: spacing.xxxxSmall_2
206
- }, disabled && selected && styles$9.disabledCheckFormatting]
207
- }));
208
- };
209
- const theme$6 = {
210
- checkbox: {
211
- color: {
212
- default: {
213
- border: semanticColor.border.strong
214
- },
215
- disabled: {
216
- border: semanticColor.action.secondary.disabled.border,
217
- background: semanticColor.action.secondary.disabled.background
218
- }
219
- }
220
- }
221
- };
222
- const styles$9 = StyleSheet.create({
223
- checkbox: {
224
- alignSelf: "center",
225
- minHeight: spacing.medium_16,
226
- minWidth: spacing.medium_16,
227
- height: spacing.medium_16,
228
- borderRadius: 3,
229
- borderWidth: border.width.thin,
230
- borderStyle: "solid",
231
- borderColor: theme$6.checkbox.color.default.border
232
- },
233
- noBorder: {
234
- borderWidth: 0
235
- },
236
- disabledCheckbox: {
237
- borderColor: theme$6.checkbox.color.disabled.border,
238
- backgroundColor: theme$6.checkbox.color.disabled.background
239
- },
240
- disabledCheckFormatting: {
241
- position: "absolute",
242
- top: -1,
243
- left: -1
244
- }
245
- });
34
+ const Checkbox=function(props){const{disabled,selected}=props;return jsx(View,{className:"checkbox",style:[styles$9.checkbox,selected&&!disabled&&styles$9.noBorder,disabled&&styles$9.disabledCheckbox],children:selected&&jsx(PhosphorIcon,{icon:checkIcon,size:"small",className:"check",style:[{width:spacing.small_12,height:spacing.small_12,margin:spacing.xxxxSmall_2},disabled&&selected&&styles$9.disabledCheckFormatting]})})};const theme$6={checkbox:{color:{default:{border:semanticColor.border.strong},disabled:{border:semanticColor.action.secondary.disabled.border,background:semanticColor.action.secondary.disabled.background}}}};const styles$9=StyleSheet.create({checkbox:{alignSelf:"center",minHeight:spacing.medium_16,minWidth:spacing.medium_16,height:spacing.medium_16,borderRadius:3,borderWidth:border.width.thin,borderStyle:"solid",borderColor:theme$6.checkbox.color.default.border},noBorder:{borderWidth:0},disabledCheckbox:{borderColor:theme$6.checkbox.color.disabled.border,backgroundColor:theme$6.checkbox.color.disabled.background},disabledCheckFormatting:{position:"absolute",top:-1,left:-1}});
246
35
 
247
- const _excluded$5 = ["disabled", "label", "selected", "testId", "leftAccessory", "horizontalRule", "parentComponent", "rightAccessory", "style", "subtitle1", "subtitle2", "value", "onClick", "onToggle", "variant", "role"];
248
- const StyledLi = addStyle("li");
249
- class OptionItem extends React.Component {
250
- constructor(...args) {
251
- super(...args);
252
- this.handleClick = () => {
253
- const {
254
- onClick,
255
- onToggle,
256
- value
257
- } = this.props;
258
- onToggle(value);
259
- if (onClick) {
260
- onClick();
261
- }
262
- };
263
- }
264
- static isClassOf(instance) {
265
- return instance && instance.type && instance.type.__IS_OPTION_ITEM__;
266
- }
267
- getCheckComponent() {
268
- if (this.props.variant === "check") {
269
- return Check;
270
- } else {
271
- return Checkbox;
272
- }
273
- }
274
- renderCell() {
275
- const _this$props = this.props,
276
- {
277
- disabled,
278
- label,
279
- selected,
280
- testId,
281
- leftAccessory,
282
- horizontalRule,
283
- parentComponent,
284
- rightAccessory,
285
- style,
286
- subtitle1,
287
- subtitle2,
288
- role
289
- } = _this$props,
290
- sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$5);
291
- const CheckComponent = this.getCheckComponent();
292
- const defaultStyle = [styles$8.item, style];
293
- return React.createElement(DetailCell, _extends({
294
- disabled: disabled,
295
- horizontalRule: horizontalRule,
296
- rootStyle: parentComponent === "listbox" ? styles$8.listboxItem : defaultStyle,
297
- style: styles$8.itemContainer,
298
- "aria-selected": parentComponent !== "listbox" && selected ? "true" : "false",
299
- role: parentComponent !== "listbox" ? role : undefined,
300
- testId: testId,
301
- leftAccessory: React.createElement(React.Fragment, null, leftAccessory ? React.createElement(View, {
302
- style: {
303
- flexDirection: "row"
304
- }
305
- }, React.createElement(CheckComponent, {
306
- disabled: disabled,
307
- selected: selected
308
- }), React.createElement(Strut, {
309
- size: spacing.xSmall_8
310
- }), leftAccessory) : React.createElement(CheckComponent, {
311
- disabled: disabled,
312
- selected: selected
313
- })),
314
- rightAccessory: rightAccessory,
315
- subtitle1: subtitle1 ? React.createElement(LabelSmall, {
316
- className: "subtitle"
317
- }, subtitle1) : undefined,
318
- title: React.createElement(LabelMedium, {
319
- style: styles$8.label
320
- }, label),
321
- subtitle2: subtitle2 ? React.createElement(LabelSmall, {
322
- className: "subtitle"
323
- }, subtitle2) : undefined,
324
- onClick: parentComponent !== "listbox" ? this.handleClick : undefined
325
- }, sharedProps));
326
- }
327
- render() {
328
- const {
329
- disabled,
330
- focused,
331
- parentComponent,
332
- role,
333
- selected
334
- } = this.props;
335
- if (parentComponent === "listbox") {
336
- return (React.createElement(StyledLi, {
337
- onMouseDown: e => {
338
- e.preventDefault();
339
- },
340
- onClick: this.handleClick,
341
- style: [styles$8.reset, styles$8.item, focused && styles$8.itemFocused, disabled && styles$8.itemDisabled],
342
- role: role,
343
- "aria-selected": selected ? "true" : "false",
344
- "aria-disabled": disabled ? "true" : "false",
345
- id: this.props.id,
346
- tabIndex: -1
347
- }, this.renderCell())
348
- );
349
- }
350
- return this.renderCell();
351
- }
352
- }
353
- OptionItem.defaultProps = {
354
- disabled: false,
355
- focused: false,
356
- horizontalRule: "none",
357
- onToggle: () => void 0,
358
- role: "option",
359
- selected: false
360
- };
361
- OptionItem.__IS_OPTION_ITEM__ = true;
362
- const focusedStyle = {
363
- borderRadius: border.radius.radius_040,
364
- outline: `${spacing.xxxxSmall_2}px solid ${semanticColor.focus.outer}`,
365
- outlineOffset: -spacing.xxxxSmall_2
366
- };
367
- const actionType = semanticColor.action.primary.progressive;
368
- const theme$5 = {
369
- optionItem: {
370
- color: {
371
- default: {
372
- background: semanticColor.surface.primary,
373
- foreground: semanticColor.text.primary
374
- },
375
- hover: {
376
- background: actionType.hover.background,
377
- foreground: actionType.hover.foreground
378
- },
379
- press: {
380
- background: actionType.press.background,
381
- foreground: actionType.press.foreground
382
- },
383
- disabled: {
384
- background: "transparent",
385
- foreground: semanticColor.action.secondary.disabled.foreground
386
- }
387
- }
388
- },
389
- checkbox: {
390
- color: {
391
- hover: {
392
- background: semanticColor.surface.primary,
393
- foreground: semanticColor.action.secondary.progressive.hover.foreground
394
- },
395
- press: {
396
- background: semanticColor.surface.primary,
397
- foreground: semanticColor.action.secondary.progressive.press.foreground
398
- },
399
- selected: {
400
- background: actionType.default.background,
401
- foreground: actionType.default.foreground
402
- }
403
- }
404
- },
405
- subtitle: {
406
- color: {
407
- default: {
408
- foreground: semanticColor.text.secondary
409
- },
410
- hover: {
411
- foreground: semanticColor.text.inverse
412
- },
413
- press: {
414
- foreground: semanticColor.text.inverse
415
- }
416
- }
417
- }
418
- };
419
- const styles$8 = StyleSheet.create({
420
- reset: {
421
- margin: 0,
422
- padding: 0,
423
- border: 0,
424
- background: "none",
425
- outline: "none",
426
- fontSize: "100%",
427
- verticalAlign: "baseline",
428
- textAlign: "left",
429
- textDecoration: "none",
430
- listStyle: "none",
431
- cursor: "pointer"
432
- },
433
- listboxItem: {
434
- backgroundColor: "transparent",
435
- color: "inherit"
436
- },
437
- item: {
438
- background: theme$5.optionItem.color.default.background,
439
- color: theme$5.optionItem.color.default.foreground,
440
- minHeight: "unset",
441
- ":focus": focusedStyle,
442
- ":focus-visible": {
443
- overflow: "visible"
444
- },
445
- [":hover[aria-disabled=false]"]: {
446
- color: theme$5.optionItem.color.hover.foreground,
447
- background: theme$5.optionItem.color.hover.background
448
- },
449
- [":active[aria-selected=false]"]: {},
450
- [":hover[aria-disabled=true]"]: {
451
- cursor: "not-allowed"
452
- },
453
- [":is([aria-disabled=true])"]: {
454
- color: theme$5.optionItem.color.disabled.foreground,
455
- ":focus-visible": {
456
- outline: "none"
457
- }
458
- },
459
- [":active[aria-disabled=false]"]: {
460
- color: theme$5.optionItem.color.press.foreground,
461
- background: theme$5.optionItem.color.press.background
462
- },
463
- [":hover[aria-disabled=false] .checkbox"]: {
464
- background: theme$5.checkbox.color.hover.background
465
- },
466
- [":active[aria-disabled=false] .checkbox"]: {
467
- background: theme$5.checkbox.color.press.background
468
- },
469
- [":hover[aria-disabled=false] .check"]: {
470
- color: theme$5.checkbox.color.hover.foreground
471
- },
472
- [":active[aria-disabled=false] .check"]: {
473
- color: theme$5.checkbox.color.press.foreground
474
- },
475
- [":is([aria-selected=true]) .checkbox"]: {
476
- background: theme$5.checkbox.color.selected.background
477
- },
478
- [":is([aria-selected=true]) .check"]: {
479
- color: theme$5.checkbox.color.selected.foreground
480
- },
481
- [":is([aria-disabled=false]) .subtitle"]: {
482
- color: theme$5.subtitle.color.default.foreground
483
- },
484
- [":hover[aria-disabled=false] .subtitle"]: {
485
- color: theme$5.subtitle.color.hover.foreground
486
- },
487
- [":active[aria-disabled=false] .subtitle"]: {
488
- color: theme$5.subtitle.color.press.foreground
489
- }
490
- },
491
- itemFocused: focusedStyle,
492
- itemDisabled: {
493
- outlineColor: semanticColor.focus.outer
494
- },
495
- itemContainer: {
496
- minHeight: "unset",
497
- paddingBlock: spacing.xSmall_8 + spacing.xxxxSmall_2,
498
- paddingInlineStart: spacing.xSmall_8,
499
- paddingInlineEnd: spacing.medium_16,
500
- whiteSpace: "nowrap"
501
- },
502
- label: {
503
- whiteSpace: "nowrap",
504
- userSelect: "none",
505
- overflow: "hidden",
506
- textOverflow: "ellipsis"
507
- },
508
- hide: {
509
- visibility: "hidden"
510
- }
511
- });
36
+ const StyledLi=addStyle("li");class OptionItem extends React.Component{static isClassOf(instance){return instance&&instance.type&&instance.type.__IS_OPTION_ITEM__}getCheckComponent(){if(this.props.variant==="check"){return Check}else {return Checkbox}}renderCell(){const{disabled,label,selected,testId,leftAccessory,horizontalRule,parentComponent,rightAccessory,style,subtitle1,subtitle2,value,onClick,onToggle,variant,role,...sharedProps}=this.props;const CheckComponent=this.getCheckComponent();const defaultStyle=[styles$8.item,style];return jsx(DetailCell,{disabled:disabled,horizontalRule:horizontalRule,rootStyle:parentComponent==="listbox"?styles$8.listboxItem:defaultStyle,style:styles$8.itemContainer,"aria-selected":parentComponent!=="listbox"&&selected?"true":"false",role:parentComponent!=="listbox"?role:undefined,testId:testId,leftAccessory:jsx(Fragment,{children:leftAccessory?jsxs(View,{style:{flexDirection:"row"},children:[jsx(CheckComponent,{disabled:disabled,selected:selected}),jsx(Strut,{size:spacing.xSmall_8}),leftAccessory]}):jsx(CheckComponent,{disabled:disabled,selected:selected})}),rightAccessory:rightAccessory,subtitle1:subtitle1?jsx(LabelSmall,{className:"subtitle",children:subtitle1}):undefined,title:jsx(LabelMedium,{style:styles$8.label,children:label}),subtitle2:subtitle2?jsx(LabelSmall,{className:"subtitle",children:subtitle2}):undefined,onClick:parentComponent!=="listbox"?this.handleClick:undefined,...sharedProps})}render(){const{disabled,focused,parentComponent,role,selected}=this.props;if(parentComponent==="listbox"){return jsx(StyledLi,{onMouseDown:e=>{e.preventDefault();},onClick:this.handleClick,style:[styles$8.reset,styles$8.item,focused&&styles$8.itemFocused,disabled&&styles$8.itemDisabled],role:role,"aria-selected":selected?"true":"false","aria-disabled":disabled?"true":"false",id:this.props.id,tabIndex:-1,children:this.renderCell()})}return this.renderCell()}constructor(...args){super(...args),this.handleClick=()=>{const{onClick,onToggle,value}=this.props;onToggle(value);if(onClick){onClick();}};}}OptionItem.defaultProps={disabled:false,focused:false,horizontalRule:"none",onToggle:()=>void 0,role:"option",selected:false};OptionItem.__IS_OPTION_ITEM__=true;const focusedStyle={borderRadius:border.radius.radius_040,outline:`${spacing.xxxxSmall_2}px solid ${semanticColor.focus.outer}`,outlineOffset:-spacing.xxxxSmall_2};const actionType=semanticColor.action.primary.progressive;const theme$5={optionItem:{color:{default:{background:semanticColor.surface.primary,foreground:semanticColor.text.primary},hover:{background:actionType.hover.background,foreground:actionType.hover.foreground},press:{background:actionType.press.background,foreground:actionType.press.foreground},disabled:{background:"transparent",foreground:semanticColor.action.secondary.disabled.foreground}}},checkbox:{color:{hover:{background:semanticColor.surface.primary,foreground:semanticColor.action.secondary.progressive.hover.foreground},press:{background:semanticColor.surface.primary,foreground:semanticColor.action.secondary.progressive.press.foreground},selected:{background:actionType.default.background,foreground:actionType.default.foreground}}},subtitle:{color:{default:{foreground:semanticColor.text.secondary},hover:{foreground:semanticColor.text.inverse},press:{foreground:semanticColor.text.inverse}}}};const styles$8=StyleSheet.create({reset:{margin:0,padding:0,border:0,background:"none",outline:"none",fontSize:"100%",verticalAlign:"baseline",textAlign:"left",textDecoration:"none",listStyle:"none",cursor:"pointer"},listboxItem:{backgroundColor:"transparent",color:"inherit"},item:{background:theme$5.optionItem.color.default.background,color:theme$5.optionItem.color.default.foreground,minHeight:"unset",":focus":focusedStyle,":focus-visible":{overflow:"visible"},[":hover[aria-disabled=false]"]:{color:theme$5.optionItem.color.hover.foreground,background:theme$5.optionItem.color.hover.background},[":active[aria-selected=false]"]:{},[":hover[aria-disabled=true]"]:{cursor:"not-allowed"},[":is([aria-disabled=true])"]:{color:theme$5.optionItem.color.disabled.foreground,":focus-visible":{outline:"none"}},[":active[aria-disabled=false]"]:{color:theme$5.optionItem.color.press.foreground,background:theme$5.optionItem.color.press.background},[":hover[aria-disabled=false] .checkbox"]:{background:theme$5.checkbox.color.hover.background},[":active[aria-disabled=false] .checkbox"]:{background:theme$5.checkbox.color.press.background},[":hover[aria-disabled=false] .check"]:{color:theme$5.checkbox.color.hover.foreground},[":active[aria-disabled=false] .check"]:{color:theme$5.checkbox.color.press.foreground},[":is([aria-selected=true]) .checkbox"]:{background:theme$5.checkbox.color.selected.background},[":is([aria-selected=true]) .check"]:{color:theme$5.checkbox.color.selected.foreground},[":is([aria-disabled=false]) .subtitle"]:{color:theme$5.subtitle.color.default.foreground},[":hover[aria-disabled=false] .subtitle"]:{color:theme$5.subtitle.color.hover.foreground},[":active[aria-disabled=false] .subtitle"]:{color:theme$5.subtitle.color.press.foreground}},itemFocused:focusedStyle,itemDisabled:{outlineColor:semanticColor.focus.outer},itemContainer:{minHeight:"unset",paddingBlock:spacing.xSmall_8+spacing.xxxxSmall_2,paddingInlineStart:spacing.xSmall_8,paddingInlineEnd:spacing.medium_16,whiteSpace:"nowrap"},label:{whiteSpace:"nowrap",userSelect:"none",overflow:"hidden",textOverflow:"ellipsis"},hide:{visibility:"hidden"}});
512
37
 
513
- class SeparatorItem extends React.Component {
514
- static isClassOf(instance) {
515
- return instance && instance.type && instance.type.__IS_SEPARATOR_ITEM__;
516
- }
517
- render() {
518
- return (React.createElement(View, {
519
- style: [styles$7.separator, this.props.style],
520
- "aria-hidden": "true"
521
- })
522
- );
523
- }
524
- }
525
- SeparatorItem.__IS_SEPARATOR_ITEM__ = true;
526
- const theme$4 = {
527
- separator: {
528
- color: {
529
- border: semanticColor.border.primary
530
- }
531
- }
532
- };
533
- const styles$7 = StyleSheet.create({
534
- separator: {
535
- borderTop: `1px solid ${theme$4.separator.color.border}`,
536
- height: 1,
537
- minHeight: 1,
538
- marginTop: spacing.xxxSmall_4,
539
- marginBottom: spacing.xxxSmall_4
540
- }
541
- });
38
+ class SeparatorItem extends React.Component{static isClassOf(instance){return instance&&instance.type&&instance.type.__IS_SEPARATOR_ITEM__}render(){return jsx(View,{style:[styles$7.separator,this.props.style],"aria-hidden":"true"})}}SeparatorItem.__IS_SEPARATOR_ITEM__=true;const theme$4={separator:{color:{border:semanticColor.border.primary}}};const styles$7=StyleSheet.create({separator:{borderTop:`1px solid ${theme$4.separator.color.border}`,height:1,minHeight:1,marginTop:spacing.xxxSmall_4,marginBottom:spacing.xxxSmall_4}});
542
39
 
543
- class DropdownOpener extends React.Component {
544
- constructor(...args) {
545
- super(...args);
546
- this.getTestIdFromProps = childrenProps => {
547
- return childrenProps.testId || childrenProps["data-testid"];
548
- };
549
- }
550
- renderAnchorChildren(eventState, clickableChildrenProps) {
551
- var _childrenProps$ariaL;
552
- const {
553
- disabled,
554
- testId,
555
- text,
556
- opened,
557
- "aria-controls": ariaControls,
558
- "aria-haspopup": ariaHasPopUp,
559
- "aria-required": ariaRequired,
560
- id,
561
- role,
562
- onBlur
563
- } = this.props;
564
- const renderedChildren = this.props.children(_extends({}, eventState, {
565
- text,
566
- opened
567
- }));
568
- const childrenProps = renderedChildren.props;
569
- const childrenTestId = this.getTestIdFromProps(childrenProps);
570
- const renderedAriaLabel = (_childrenProps$ariaL = childrenProps["aria-label"]) != null ? _childrenProps$ariaL : this.props["aria-label"];
571
- return React.cloneElement(renderedChildren, _extends({}, clickableChildrenProps, {
572
- "aria-label": renderedAriaLabel != null ? renderedAriaLabel : undefined,
573
- "aria-invalid": this.props.error,
574
- disabled,
575
- "aria-controls": ariaControls,
576
- role,
577
- id,
578
- "aria-expanded": opened ? "true" : "false",
579
- "aria-haspopup": ariaHasPopUp,
580
- "aria-required": ariaRequired,
581
- onClick: childrenProps.onClick ? e => {
582
- childrenProps.onClick(e);
583
- clickableChildrenProps.onClick(e);
584
- } : clickableChildrenProps.onClick,
585
- "data-testid": childrenTestId || testId,
586
- onBlur
587
- }));
588
- }
589
- render() {
590
- return React.createElement(ClickableBehavior, {
591
- onClick: this.props.onClick,
592
- disabled: this.props.disabled,
593
- tabIndex: 0
594
- }, (eventState, handlers) => this.renderAnchorChildren(eventState, handlers));
595
- }
596
- }
597
- DropdownOpener.defaultProps = {
598
- disabled: false
599
- };
40
+ class DropdownOpener extends React.Component{renderAnchorChildren(eventState,clickableChildrenProps){const{disabled,testId,text,opened,"aria-controls":ariaControls,"aria-haspopup":ariaHasPopUp,"aria-required":ariaRequired,id,role,onBlur}=this.props;const renderedChildren=this.props.children({...eventState,text,opened});const childrenProps=renderedChildren.props;const childrenTestId=this.getTestIdFromProps(childrenProps);const renderedAriaLabel=childrenProps["aria-label"]??this.props["aria-label"];return React.cloneElement(renderedChildren,{...clickableChildrenProps,"aria-label":renderedAriaLabel??undefined,"aria-invalid":this.props.error,disabled,"aria-controls":ariaControls,role,id,"aria-expanded":opened?"true":"false","aria-haspopup":ariaHasPopUp,"aria-required":ariaRequired,onClick:childrenProps.onClick?e=>{childrenProps.onClick(e);clickableChildrenProps.onClick(e);}:clickableChildrenProps.onClick,"data-testid":childrenTestId||testId,onBlur})}render(){return jsx(ClickableBehavior,{onClick:this.props.onClick,disabled:this.props.disabled,tabIndex:0,children:(eventState,handlers)=>this.renderAnchorChildren(eventState,handlers)})}constructor(...args){super(...args),this.getTestIdFromProps=childrenProps=>{return childrenProps.testId||childrenProps["data-testid"]};}}DropdownOpener.defaultProps={disabled:false};
600
41
 
601
- class DropdownVirtualizedItem extends React.Component {
602
- render() {
603
- const {
604
- data,
605
- index,
606
- style
607
- } = this.props;
608
- const item = data[index];
609
- if (SeparatorItem.isClassOf(item.component)) {
610
- return React.cloneElement(item.component, {
611
- style
612
- });
613
- } else {
614
- const {
615
- component,
616
- populatedProps,
617
- onClick,
618
- role,
619
- ref
620
- } = item;
621
- return React.cloneElement(component, _extends({
622
- style
623
- }, populatedProps, {
624
- key: index,
625
- onClick,
626
- ref: item.focusable && ref,
627
- role
628
- }));
629
- }
630
- }
631
- }
42
+ class DropdownVirtualizedItem extends React.Component{render(){const{data,index,style}=this.props;const item=data[index];if(SeparatorItem.isClassOf(item.component)){return React.cloneElement(item.component,{style})}else {const{component,populatedProps,onClick,role,ref}=item;return React.cloneElement(component,{style,...populatedProps,key:index,onClick,ref:item.focusable&&ref,role})}}}
632
43
 
633
- function getDropdownMenuHeight(items, initialHeight = 0) {
634
- return items.slice(0, MAX_VISIBLE_ITEMS).reduce((sum, item) => {
635
- if (SeparatorItem.isClassOf(item.component)) {
636
- return sum + SEPARATOR_ITEM_HEIGHT;
637
- } else {
638
- return sum + DROPDOWN_ITEM_HEIGHT;
639
- }
640
- }, initialHeight);
641
- }
44
+ function getDropdownMenuHeight(items,initialHeight=0){return items.slice(0,MAX_VISIBLE_ITEMS).reduce((sum,item)=>{if(SeparatorItem.isClassOf(item.component)){return sum+SEPARATOR_ITEM_HEIGHT}else {return sum+DROPDOWN_ITEM_HEIGHT}},initialHeight)}
642
45
 
643
- class DropdownCoreVirtualized extends React.Component {
644
- constructor(props) {
645
- super(props);
646
- this.getItemSize = index => {
647
- const item = this.props.data[index];
648
- if (SeparatorItem.isClassOf(item.component)) {
649
- return SEPARATOR_ITEM_HEIGHT;
650
- } else {
651
- return DROPDOWN_ITEM_HEIGHT;
652
- }
653
- };
654
- this.state = {
655
- height: getDropdownMenuHeight(props.data),
656
- width: props.width
657
- };
658
- }
659
- componentDidMount() {
660
- const {
661
- schedule
662
- } = this.props;
663
- schedule.animationFrame(() => {
664
- this.setWidth();
665
- });
666
- }
667
- componentDidUpdate(prevProps) {
668
- const {
669
- data,
670
- listRef
671
- } = this.props;
672
- if (prevProps.data.length !== data.length) {
673
- this.setHeight();
674
- if (listRef && listRef.current) {
675
- listRef.current.resetAfterIndex(1);
676
- }
677
- }
678
- }
679
- setWidth() {
680
- const rootNode = ReactDOM.findDOMNode(this);
681
- const parentNode = rootNode == null ? void 0 : rootNode.parentElement;
682
- if (parentNode) {
683
- const width = parentNode.getBoundingClientRect().width;
684
- this.setState({
685
- width
686
- });
687
- }
688
- }
689
- setHeight() {
690
- const height = getDropdownMenuHeight(this.props.data);
691
- this.setState({
692
- height
693
- });
694
- }
695
- renderInitialItems() {
696
- const {
697
- data
698
- } = this.props;
699
- const allComponents = data.map(e => e.component);
700
- const longestItems = React.Children.toArray(allComponents).filter(Boolean).sort((a, b) => {
701
- if (b.props.label && a.props.label) {
702
- return b.props.label.length - a.props.label.length;
703
- }
704
- return -1;
705
- }).slice(0, MAX_VISIBLE_ITEMS);
706
- return longestItems.map(item => React.cloneElement(item, {
707
- style: {
708
- visibility: "hidden"
709
- }
710
- }));
711
- }
712
- renderVirtualizedList(width, height) {
713
- const {
714
- data,
715
- listRef
716
- } = this.props;
717
- return React.createElement(VariableSizeList, {
718
- height: height,
719
- itemCount: data.length,
720
- itemSize: this.getItemSize,
721
- itemData: data,
722
- style: {
723
- overflowX: "hidden"
724
- },
725
- width: width,
726
- overscanCount: 5,
727
- ref: listRef
728
- }, DropdownVirtualizedItem);
729
- }
730
- render() {
731
- const {
732
- width,
733
- height
734
- } = this.state;
735
- if (width == null) {
736
- return this.renderInitialItems();
737
- } else {
738
- return this.renderVirtualizedList(width, height);
739
- }
740
- }
741
- }
742
- var DropdownCoreVirtualized$1 = withActionScheduler(DropdownCoreVirtualized);
46
+ class DropdownCoreVirtualized extends React.Component{componentDidMount(){const{schedule}=this.props;schedule.animationFrame(()=>{this.setWidth();});}componentDidUpdate(prevProps){const{data,listRef}=this.props;if(prevProps.data.length!==data.length){this.setHeight();if(listRef&&listRef.current){listRef.current.resetAfterIndex(1);}}}setWidth(){const rootNode=ReactDOM.findDOMNode(this);const parentNode=rootNode?.parentElement;if(parentNode){const width=parentNode.getBoundingClientRect().width;this.setState({width});}}setHeight(){const height=getDropdownMenuHeight(this.props.data);this.setState({height});}renderInitialItems(){const{data}=this.props;const allComponents=data.map(e=>e.component);const longestItems=React.Children.toArray(allComponents).filter(Boolean).sort((a,b)=>{if(b.props.label&&a.props.label){return b.props.label.length-a.props.label.length}return -1}).slice(0,MAX_VISIBLE_ITEMS);return longestItems.map(item=>React.cloneElement(item,{style:{visibility:"hidden"}}))}renderVirtualizedList(width,height){const{data,listRef}=this.props;return jsx(VariableSizeList,{height:height,itemCount:data.length,itemSize:this.getItemSize,itemData:data,style:{overflowX:"hidden"},width:width,overscanCount:5,ref:listRef,children:DropdownVirtualizedItem})}render(){const{width,height}=this.state;if(width==null){return this.renderInitialItems()}else {return this.renderVirtualizedList(width,height)}}constructor(props){super(props),this.getItemSize=index=>{const item=this.props.data[index];if(SeparatorItem.isClassOf(item.component)){return SEPARATOR_ITEM_HEIGHT}else {return DROPDOWN_ITEM_HEIGHT}};this.state={height:getDropdownMenuHeight(props.data),width:props.width};}}var DropdownCoreVirtualized$1 = withActionScheduler(DropdownCoreVirtualized);
743
47
 
744
- function modifyMaxHeight({
745
- state,
746
- options
747
- }) {
748
- const overflow = detectOverflow(state, options);
749
- const {
750
- y
751
- } = state.modifiersData.preventOverflow || {
752
- x: 0,
753
- y: 0
754
- };
755
- const {
756
- height
757
- } = state.rects.popper;
758
- const [basePlacement] = state.placement.split("-");
759
- const heightProp = basePlacement === "top" ? "top" : "bottom";
760
- const maxHeight = height - overflow[heightProp] - y;
761
- state.styles.popper = _extends({}, state.styles.popper, {
762
- maxHeight: `${maxHeight}px`,
763
- ["--popper-max-height"]: `${maxHeight}px`
764
- });
765
- }
766
- const maxHeightModifier = {
767
- name: "maxHeight",
768
- enabled: true,
769
- phase: "main",
770
- options: {
771
- padding: DROPDOWN_ITEM_HEIGHT
772
- },
773
- requiresIfExists: ["offset", "preventOverflow", "flip"],
774
- fn: modifyMaxHeight
775
- };
48
+ function modifyMaxHeight({state,options}){const overflow=detectOverflow(state,options);const{y}=state.modifiersData.preventOverflow||{x:0,y:0};const{height}=state.rects.popper;const[basePlacement]=state.placement.split("-");const heightProp=basePlacement==="top"?"top":"bottom";const maxHeight=height-overflow[heightProp]-y;state.styles.popper={...state.styles.popper,maxHeight:`${maxHeight}px`,["--popper-max-height"]:`${maxHeight}px`};}const maxHeightModifier={name:"maxHeight",enabled:true,phase:"main",options:{padding:DROPDOWN_ITEM_HEIGHT},requiresIfExists:["offset","preventOverflow","flip"],fn:modifyMaxHeight};
776
49
 
777
- const modifiers = [{
778
- name: "preventOverflow",
779
- options: {
780
- rootBoundary: "viewport",
781
- altAxis: true,
782
- tether: false
783
- }
784
- }, maxHeightModifier];
785
- const DropdownPopper = function DropdownPopper({
786
- children,
787
- alignment = "left",
788
- onPopperElement,
789
- referenceElement
790
- }) {
791
- const modalHost = maybeGetPortalMountedModalHostElement(referenceElement) || document.querySelector("body");
792
- if (!modalHost) {
793
- return null;
794
- }
795
- return ReactDOM.createPortal(React.createElement(Popper, {
796
- innerRef: node => {
797
- if (node && onPopperElement) {
798
- onPopperElement(node);
799
- }
800
- },
801
- referenceElement: referenceElement,
802
- strategy: "fixed",
803
- placement: alignment === "left" ? "bottom-start" : "bottom-end",
804
- modifiers: modifiers
805
- }, ({
806
- placement,
807
- ref,
808
- style,
809
- hasPopperEscaped,
810
- isReferenceHidden
811
- }) => {
812
- const shouldHidePopper = !!(hasPopperEscaped || isReferenceHidden);
813
- return React.createElement("div", {
814
- ref: ref,
815
- style: style,
816
- "data-testid": "dropdown-popper",
817
- "data-placement": placement
818
- }, children(shouldHidePopper));
819
- }), modalHost);
820
- };
50
+ const modifiers=[{name:"preventOverflow",options:{rootBoundary:"viewport",altAxis:true,tether:false}},maxHeightModifier];const DropdownPopper=function({children,alignment="left",onPopperElement,referenceElement}){const modalHost=maybeGetPortalMountedModalHostElement(referenceElement)||document.querySelector("body");if(!modalHost){return null}return ReactDOM.createPortal(jsx(Popper,{innerRef:node=>{if(node&&onPopperElement){onPopperElement(node);}},referenceElement:referenceElement,strategy:"fixed",placement:alignment==="left"?"bottom-start":"bottom-end",modifiers:modifiers,children:({placement,ref,style,hasPopperEscaped,isReferenceHidden})=>{const shouldHidePopper=!!(hasPopperEscaped||isReferenceHidden);return jsx("div",{ref:ref,style:style,"data-testid":"dropdown-popper","data-placement":placement,children:children(shouldHidePopper)})}}),modalHost)};
821
51
 
822
- function getStringForKey(key) {
823
- if (key.length === 1 || !/^[A-Z]/i.test(key)) {
824
- return key;
825
- }
826
- return "";
827
- }
828
- function debounce(callback, wait) {
829
- let timeout;
830
- return function executedFunction(...args) {
831
- const later = () => {
832
- clearTimeout(timeout);
833
- callback(...args);
834
- };
835
- clearTimeout(timeout);
836
- timeout = setTimeout(later, wait);
837
- };
838
- }
839
- function isString(x) {
840
- return typeof x === "string";
841
- }
842
- function getLabel(props) {
843
- if (isString(props.label)) {
844
- return props.label;
845
- }
846
- if (isString(props.labelAsText)) {
847
- return props.labelAsText;
848
- }
849
- return "";
850
- }
851
- function getSelectOpenerLabel(showOpenerLabelAsText, props) {
852
- if (showOpenerLabelAsText) {
853
- return getLabel(props);
854
- }
855
- return props.label;
856
- }
52
+ function getStringForKey(key){if(key.length===1||!/^[A-Z]/i.test(key)){return key}return ""}function debounce(callback,wait){let timeout;return function executedFunction(...args){const later=()=>{clearTimeout(timeout);callback(...args);};clearTimeout(timeout);timeout=setTimeout(later,wait);}}function isString(x){return typeof x==="string"}function getLabel(props){if(isString(props.label)){return props.label}if(isString(props.labelAsText)){return props.labelAsText}return ""}function getSelectOpenerLabel(showOpenerLabelAsText,props){if(showOpenerLabelAsText){return getLabel(props)}return props.label}
857
53
 
858
- const VIRTUALIZE_THRESHOLD = 125;
859
- class DropdownCore extends React.Component {
860
- static sameItemsFocusable(prevItems, currentItems) {
861
- if (prevItems.length !== currentItems.length) {
862
- return false;
863
- }
864
- for (let i = 0; i < prevItems.length; i++) {
865
- if (prevItems[i].focusable !== currentItems[i].focusable) {
866
- return false;
867
- }
868
- }
869
- return true;
870
- }
871
- static getDerivedStateFromProps(props, state) {
872
- if (state.itemRefs.length === 0 && props.open || !DropdownCore.sameItemsFocusable(state.prevItems, props.items)) {
873
- const itemRefs = [];
874
- for (let i = 0; i < props.items.length; i++) {
875
- if (props.items[i].focusable) {
876
- const ref = React.createRef();
877
- itemRefs.push({
878
- ref,
879
- originalIndex: i
880
- });
881
- }
882
- }
883
- return {
884
- itemRefs,
885
- prevItems: props.items,
886
- sameItemsFocusable: false
887
- };
888
- } else {
889
- return {
890
- prevItems: props.items,
891
- sameItemsFocusable: true
892
- };
893
- }
894
- }
895
- constructor(props) {
896
- super(props);
897
- this.popperElement = void 0;
898
- this.virtualizedListRef = void 0;
899
- this.handleKeyDownDebounced = void 0;
900
- this.textSuggestion = void 0;
901
- this.focusedIndex = -1;
902
- this.focusedOriginalIndex = -1;
903
- this.itemsClicked = false;
904
- this.searchFieldRef = React.createRef();
905
- this.handleInteract = event => {
906
- const {
907
- open,
908
- onOpenChanged
909
- } = this.props;
910
- const target = event.target;
911
- const thisElement = ReactDOM.findDOMNode(this);
912
- if (open && thisElement && !thisElement.contains(target) && this.popperElement && !this.popperElement.contains(target)) {
913
- onOpenChanged(false);
914
- }
915
- };
916
- this.handleKeyDown = event => {
917
- const {
918
- enableTypeAhead,
919
- onOpenChanged,
920
- open,
921
- searchText
922
- } = this.props;
923
- const key = event.key;
924
- if (enableTypeAhead && getStringForKey(key)) {
925
- event.stopPropagation();
926
- this.textSuggestion += key;
927
- this.handleKeyDownDebounced(this.textSuggestion);
928
- }
929
- if (!open) {
930
- if (key === keys.down) {
931
- event.preventDefault();
932
- onOpenChanged(true);
933
- return;
934
- }
935
- return;
936
- }
937
- switch (key) {
938
- case keys.tab:
939
- if (this.isSearchFieldFocused() && searchText) {
940
- return;
941
- }
942
- this.restoreTabOrder();
943
- onOpenChanged(false);
944
- return;
945
- case keys.space:
946
- if (this.isSearchFieldFocused()) {
947
- return;
948
- }
949
- event.preventDefault();
950
- return;
951
- case keys.up:
952
- event.preventDefault();
953
- this.focusPreviousItem();
954
- return;
955
- case keys.down:
956
- event.preventDefault();
957
- this.focusNextItem();
958
- return;
959
- }
960
- };
961
- this.handleKeyUp = event => {
962
- const {
963
- onOpenChanged,
964
- open
965
- } = this.props;
966
- const key = event.key;
967
- switch (key) {
968
- case keys.space:
969
- if (this.isSearchFieldFocused()) {
970
- return;
971
- }
972
- event.preventDefault();
973
- return;
974
- case keys.escape:
975
- if (open) {
976
- event.stopPropagation();
977
- this.restoreTabOrder();
978
- onOpenChanged(false);
979
- }
980
- return;
981
- }
982
- };
983
- this.handleKeyDownDebounceResult = key => {
984
- const foundIndex = this.props.items.filter(item => item.focusable).findIndex(({
985
- component
986
- }) => {
987
- if (SeparatorItem.isClassOf(component)) {
988
- return false;
989
- }
990
- if (OptionItem.isClassOf(component)) {
991
- const optionItemProps = component.props;
992
- return getLabel(optionItemProps).toLowerCase().startsWith(key.toLowerCase());
993
- }
994
- return false;
995
- });
996
- if (foundIndex >= 0) {
997
- const isClosed = !this.props.open;
998
- if (isClosed) {
999
- this.props.onOpenChanged(true);
1000
- }
1001
- this.focusedIndex = foundIndex;
1002
- this.scheduleToFocusCurrentItem(node => {
1003
- if (this.props.selectionType === "single" && isClosed && node) {
1004
- node.click();
1005
- this.props.onOpenChanged(false);
1006
- }
1007
- });
1008
- }
1009
- this.textSuggestion = "";
1010
- };
1011
- this.handleClickFocus = index => {
1012
- this.itemsClicked = true;
1013
- this.focusedIndex = index;
1014
- this.focusedOriginalIndex = this.state.itemRefs[this.focusedIndex].originalIndex;
1015
- };
1016
- this.handleDropdownMouseUp = event => {
1017
- if (event.nativeEvent.stopImmediatePropagation) {
1018
- event.nativeEvent.stopImmediatePropagation();
1019
- } else {
1020
- event.stopPropagation();
1021
- }
1022
- };
1023
- this.handleItemClick = (focusIndex, item) => {
1024
- this.handleClickFocus(focusIndex);
1025
- if (item.component.props.onClick) {
1026
- item.component.props.onClick();
1027
- }
1028
- if (item.populatedProps.onClick) {
1029
- item.populatedProps.onClick();
1030
- }
1031
- };
1032
- this.handleSearchTextChanged = searchText => {
1033
- const {
1034
- onSearchTextChanged
1035
- } = this.props;
1036
- if (onSearchTextChanged) {
1037
- onSearchTextChanged(searchText);
1038
- }
1039
- };
1040
- this.resetFocusedIndex();
1041
- this.state = {
1042
- prevItems: this.props.items,
1043
- itemRefs: [],
1044
- sameItemsFocusable: false,
1045
- labels: _extends({
1046
- noResults: defaultLabels.noResults,
1047
- someResults: defaultLabels.someSelected
1048
- }, props.labels)
1049
- };
1050
- this.virtualizedListRef = React.createRef();
1051
- this.handleKeyDownDebounced = debounce(this.handleKeyDownDebounceResult, 500);
1052
- this.textSuggestion = "";
1053
- }
1054
- componentDidMount() {
1055
- this.updateEventListeners();
1056
- this.maybeFocusInitialItem();
1057
- }
1058
- componentDidUpdate(prevProps) {
1059
- const {
1060
- open,
1061
- searchText
1062
- } = this.props;
1063
- if (prevProps.open !== open) {
1064
- this.updateEventListeners();
1065
- this.maybeFocusInitialItem();
1066
- } else if (open) {
1067
- const {
1068
- itemRefs,
1069
- sameItemsFocusable
1070
- } = this.state;
1071
- if (sameItemsFocusable || prevProps.searchText !== searchText) {
1072
- return;
1073
- } else {
1074
- const newFocusableIndex = itemRefs.findIndex(ref => ref.originalIndex === this.focusedOriginalIndex);
1075
- if (newFocusableIndex === -1) {
1076
- this.focusedIndex = 0;
1077
- this.itemsClicked = false;
1078
- this.scheduleToFocusCurrentItem();
1079
- } else {
1080
- this.focusedIndex = newFocusableIndex;
1081
- }
1082
- }
1083
- if (this.props.labels !== prevProps.labels) {
1084
- this.setState({
1085
- labels: _extends({}, this.state.labels, this.props.labels)
1086
- });
1087
- }
1088
- }
1089
- }
1090
- componentWillUnmount() {
1091
- this.removeEventListeners();
1092
- }
1093
- resetFocusedIndex() {
1094
- const {
1095
- initialFocusedIndex
1096
- } = this.props;
1097
- if (typeof initialFocusedIndex !== "undefined") {
1098
- this.focusedIndex = initialFocusedIndex;
1099
- } else {
1100
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1101
- return this.focusSearchField();
1102
- }
1103
- this.focusedIndex = 0;
1104
- }
1105
- }
1106
- maybeFocusInitialItem() {
1107
- const {
1108
- autoFocus,
1109
- open
1110
- } = this.props;
1111
- if (!autoFocus) {
1112
- return;
1113
- }
1114
- if (open) {
1115
- this.resetFocusedIndex();
1116
- this.scheduleToFocusCurrentItem();
1117
- } else if (!open) {
1118
- this.itemsClicked = false;
1119
- }
1120
- }
1121
- updateEventListeners() {
1122
- if (this.props.open) {
1123
- this.addEventListeners();
1124
- } else {
1125
- this.removeEventListeners();
1126
- }
1127
- }
1128
- addEventListeners() {
1129
- document.addEventListener("mouseup", this.handleInteract);
1130
- document.addEventListener("touchend", this.handleInteract);
1131
- }
1132
- removeEventListeners() {
1133
- document.removeEventListener("mouseup", this.handleInteract);
1134
- document.removeEventListener("touchend", this.handleInteract);
1135
- }
1136
- scheduleToFocusCurrentItem(onFocus) {
1137
- if (this.shouldVirtualizeList()) {
1138
- this.props.schedule.animationFrame(() => {
1139
- this.focusCurrentItem(onFocus);
1140
- });
1141
- } else {
1142
- this.focusCurrentItem(onFocus);
1143
- }
1144
- }
1145
- focusCurrentItem(onFocus) {
1146
- const focusedItemRef = this.state.itemRefs[this.focusedIndex];
1147
- if (!focusedItemRef) {
1148
- return;
1149
- }
1150
- const {
1151
- current: virtualizedList
1152
- } = this.virtualizedListRef;
1153
- if (virtualizedList) {
1154
- virtualizedList.scrollToItem(focusedItemRef.originalIndex);
1155
- }
1156
- const focusNode = () => {
1157
- if (!this.props.open) {
1158
- return;
1159
- }
1160
- const currentFocusedItemRef = this.state.itemRefs[this.focusedIndex];
1161
- const node = ReactDOM.findDOMNode(currentFocusedItemRef.ref.current);
1162
- if (!node && this.shouldVirtualizeList()) {
1163
- this.props.schedule.animationFrame(focusNode);
1164
- return;
1165
- }
1166
- if (node) {
1167
- node.focus();
1168
- this.focusedOriginalIndex = currentFocusedItemRef.originalIndex;
1169
- if (onFocus) {
1170
- onFocus(node);
1171
- }
1172
- }
1173
- };
1174
- if (this.shouldVirtualizeList()) {
1175
- this.props.schedule.animationFrame(focusNode);
1176
- } else {
1177
- focusNode();
1178
- }
1179
- }
1180
- focusSearchField() {
1181
- if (this.searchFieldRef.current) {
1182
- this.searchFieldRef.current.focus();
1183
- }
1184
- }
1185
- hasSearchField() {
1186
- return !!this.props.isFilterable;
1187
- }
1188
- isSearchFieldFocused() {
1189
- return this.hasSearchField() && document.activeElement === this.searchFieldRef.current;
1190
- }
1191
- focusPreviousItem() {
1192
- if (this.focusedIndex === 0 || this.isSearchFieldFocused() && !this.props.enableTypeAhead) {
1193
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1194
- return this.focusSearchField();
1195
- }
1196
- this.focusedIndex = this.state.itemRefs.length - 1;
1197
- } else if (!this.isSearchFieldFocused()) {
1198
- this.focusedIndex -= 1;
1199
- }
1200
- this.scheduleToFocusCurrentItem();
1201
- }
1202
- focusNextItem() {
1203
- if (this.focusedIndex === this.state.itemRefs.length - 1 || this.isSearchFieldFocused() && !this.props.enableTypeAhead) {
1204
- if (this.hasSearchField() && !this.isSearchFieldFocused()) {
1205
- return this.focusSearchField();
1206
- }
1207
- this.focusedIndex = 0;
1208
- } else if (!this.isSearchFieldFocused()) {
1209
- this.focusedIndex += 1;
1210
- }
1211
- this.scheduleToFocusCurrentItem();
1212
- }
1213
- restoreTabOrder() {
1214
- if (this.props.openerElement) {
1215
- this.props.openerElement.focus();
1216
- }
1217
- }
1218
- getItemRole() {
1219
- const {
1220
- role
1221
- } = this.props;
1222
- switch (role) {
1223
- case "listbox":
1224
- return "option";
1225
- case "menu":
1226
- return "menuitem";
1227
- default:
1228
- throw new Error(`Expected "listbox" or "menu" for role, but receieved "${role}" instead.`);
1229
- }
1230
- }
1231
- maybeRenderNoResults() {
1232
- const {
1233
- items,
1234
- labels: {
1235
- noResults
1236
- }
1237
- } = this.props;
1238
- const numResults = items.length;
1239
- if (numResults === 0) {
1240
- return React.createElement(LabelMedium, {
1241
- style: styles$6.noResult,
1242
- testId: "dropdown-core-no-results"
1243
- }, noResults);
1244
- }
1245
- return null;
1246
- }
1247
- shouldVirtualizeList() {
1248
- return this.props.items.length > VIRTUALIZE_THRESHOLD;
1249
- }
1250
- renderList() {
1251
- let focusCounter = 0;
1252
- const itemRole = this.getItemRole();
1253
- return this.props.items.map((item, index) => {
1254
- if (SeparatorItem.isClassOf(item.component)) {
1255
- return item.component;
1256
- }
1257
- const {
1258
- component,
1259
- focusable,
1260
- populatedProps
1261
- } = item;
1262
- if (focusable) {
1263
- focusCounter += 1;
1264
- }
1265
- const focusIndex = focusCounter - 1;
1266
- const currentRef = this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null;
1267
- return React.cloneElement(component, _extends({}, populatedProps, {
1268
- key: index,
1269
- onClick: () => {
1270
- this.handleItemClick(focusIndex, item);
1271
- },
1272
- ref: focusable ? currentRef : null,
1273
- role: populatedProps.role || itemRole
1274
- }));
1275
- });
1276
- }
1277
- parseVirtualizedItems() {
1278
- let focusCounter = 0;
1279
- const itemRole = this.getItemRole();
1280
- return this.props.items.map((item, index) => {
1281
- const {
1282
- populatedProps
1283
- } = item;
1284
- if (!SeparatorItem.isClassOf(item.component) && item.focusable) {
1285
- focusCounter += 1;
1286
- }
1287
- const focusIndex = focusCounter - 1;
1288
- return _extends({}, item, {
1289
- role: populatedProps.role || itemRole,
1290
- ref: item.focusable && this.state.itemRefs[focusIndex] ? this.state.itemRefs[focusIndex].ref : null,
1291
- onClick: () => {
1292
- this.handleItemClick(focusIndex, item);
1293
- }
1294
- });
1295
- });
1296
- }
1297
- renderVirtualizedList() {
1298
- const virtualizedItems = this.parseVirtualizedItems();
1299
- return React.createElement(DropdownCoreVirtualized$1, {
1300
- data: virtualizedItems,
1301
- listRef: this.virtualizedListRef
1302
- });
1303
- }
1304
- renderSearchField() {
1305
- const {
1306
- searchText
1307
- } = this.props;
1308
- const {
1309
- labels
1310
- } = this.state;
1311
- return React.createElement(SearchField, {
1312
- clearAriaLabel: labels.clearSearch,
1313
- onChange: this.handleSearchTextChanged,
1314
- placeholder: labels.filter,
1315
- ref: this.searchFieldRef,
1316
- style: styles$6.searchInputStyle,
1317
- value: searchText || ""
1318
- });
1319
- }
1320
- renderDropdownMenu(listRenderer, isReferenceHidden) {
1321
- const {
1322
- "aria-invalid": ariaInvalid,
1323
- "aria-required": ariaRequired,
1324
- dropdownStyle,
1325
- isFilterable,
1326
- openerElement,
1327
- role,
1328
- id
1329
- } = this.props;
1330
- const openerStyle = openerElement && window.getComputedStyle(openerElement);
1331
- const minDropdownWidth = openerStyle ? openerStyle.getPropertyValue("width") : 0;
1332
- return React.createElement(View, {
1333
- onMouseUp: this.handleDropdownMouseUp,
1334
- style: [styles$6.dropdown, isReferenceHidden && styles$6.hidden, dropdownStyle],
1335
- testId: "dropdown-core-container"
1336
- }, isFilterable && this.renderSearchField(), React.createElement(View, {
1337
- id: id,
1338
- role: role,
1339
- style: [styles$6.listboxOrMenu, {
1340
- minWidth: minDropdownWidth
1341
- }],
1342
- "aria-invalid": role === "listbox" ? ariaInvalid : undefined,
1343
- "aria-required": role === "listbox" ? ariaRequired : undefined
1344
- }, listRenderer), this.maybeRenderNoResults());
1345
- }
1346
- renderDropdown() {
1347
- const {
1348
- alignment,
1349
- openerElement
1350
- } = this.props;
1351
- const listRenderer = this.shouldVirtualizeList() ? this.renderVirtualizedList() : this.renderList();
1352
- return React.createElement(DropdownPopper, {
1353
- alignment: alignment,
1354
- onPopperElement: popperElement => {
1355
- this.popperElement = popperElement;
1356
- },
1357
- referenceElement: openerElement
1358
- }, isReferenceHidden => this.renderDropdownMenu(listRenderer, isReferenceHidden));
1359
- }
1360
- render() {
1361
- const {
1362
- open,
1363
- opener,
1364
- style,
1365
- className,
1366
- disabled
1367
- } = this.props;
1368
- return React.createElement(View, {
1369
- onKeyDown: !disabled ? this.handleKeyDown : undefined,
1370
- onKeyUp: !disabled ? this.handleKeyUp : undefined,
1371
- style: [styles$6.menuWrapper, style],
1372
- className: className
1373
- }, opener, open && this.renderDropdown());
1374
- }
1375
- }
1376
- DropdownCore.defaultProps = {
1377
- alignment: "left",
1378
- autoFocus: true,
1379
- enableTypeAhead: true,
1380
- labels: {
1381
- clearSearch: defaultLabels.clearSearch,
1382
- filter: defaultLabels.filter,
1383
- noResults: defaultLabels.noResults,
1384
- someResults: defaultLabels.someSelected
1385
- },
1386
- selectionType: "single"
1387
- };
1388
- const theme$3 = {
1389
- dropdown: {
1390
- color: {
1391
- default: {
1392
- background: semanticColor.surface.primary,
1393
- border: semanticColor.border.primary
1394
- }
1395
- }
1396
- },
1397
- noResults: {
1398
- color: {
1399
- foreground: semanticColor.text.secondary
1400
- }
1401
- }
1402
- };
1403
- const styles$6 = StyleSheet.create({
1404
- menuWrapper: {
1405
- width: "fit-content"
1406
- },
1407
- dropdown: {
1408
- backgroundColor: theme$3.dropdown.color.default.background,
1409
- borderRadius: border.radius.radius_040,
1410
- paddingTop: spacing.xxxSmall_4,
1411
- paddingBottom: spacing.xxxSmall_4,
1412
- border: `solid 1px ${theme$3.dropdown.color.default.border}`,
1413
- boxShadow: `0px 8px 8px 0px ${color.offBlack8}`,
1414
- maxHeight: "var(--popper-max-height)"
1415
- },
1416
- listboxOrMenu: {
1417
- overflowY: "auto"
1418
- },
1419
- hidden: {
1420
- pointerEvents: "none",
1421
- visibility: "hidden"
1422
- },
1423
- noResult: {
1424
- color: theme$3.noResults.color.foreground,
1425
- alignSelf: "center",
1426
- marginTop: spacing.xxSmall_6
1427
- },
1428
- searchInputStyle: {
1429
- margin: spacing.xSmall_8,
1430
- marginTop: spacing.xxxSmall_4,
1431
- minHeight: "auto",
1432
- position: "sticky"
1433
- },
1434
- srOnly: {
1435
- border: 0,
1436
- clip: "rect(0,0,0,0)",
1437
- height: 1,
1438
- margin: -1,
1439
- overflow: "hidden",
1440
- padding: 0,
1441
- position: "absolute",
1442
- width: 1
1443
- }
1444
- });
1445
- var DropdownCore$1 = withActionScheduler(DropdownCore);
54
+ const VIRTUALIZE_THRESHOLD=125;class DropdownCore extends React.Component{static sameItemsFocusable(prevItems,currentItems){if(prevItems.length!==currentItems.length){return false}for(let i=0;i<prevItems.length;i++){if(prevItems[i].focusable!==currentItems[i].focusable){return false}}return true}static getDerivedStateFromProps(props,state){if(state.itemRefs.length===0&&props.open||!DropdownCore.sameItemsFocusable(state.prevItems,props.items)){const itemRefs=[];for(let i=0;i<props.items.length;i++){if(props.items[i].focusable){const ref=React.createRef();itemRefs.push({ref,originalIndex:i});}}return {itemRefs,prevItems:props.items,sameItemsFocusable:false}}else {return {prevItems:props.items,sameItemsFocusable:true}}}componentDidMount(){this.updateEventListeners();this.maybeFocusInitialItem();}componentDidUpdate(prevProps){const{open,searchText}=this.props;if(prevProps.open!==open){this.updateEventListeners();this.maybeFocusInitialItem();}else if(open){const{itemRefs,sameItemsFocusable}=this.state;if(sameItemsFocusable||prevProps.searchText!==searchText){return}else {const newFocusableIndex=itemRefs.findIndex(ref=>ref.originalIndex===this.focusedOriginalIndex);if(newFocusableIndex===-1){this.focusedIndex=0;this.itemsClicked=false;this.scheduleToFocusCurrentItem();}else {this.focusedIndex=newFocusableIndex;}}if(this.props.labels!==prevProps.labels){this.setState({labels:{...this.state.labels,...this.props.labels}});}}}componentWillUnmount(){this.removeEventListeners();}resetFocusedIndex(){const{initialFocusedIndex}=this.props;if(typeof initialFocusedIndex!=="undefined"){this.focusedIndex=initialFocusedIndex;}else {if(this.hasSearchField()&&!this.isSearchFieldFocused()){return this.focusSearchField()}this.focusedIndex=0;}}maybeFocusInitialItem(){const{autoFocus,open}=this.props;if(!autoFocus){return}if(open){this.resetFocusedIndex();this.scheduleToFocusCurrentItem();}else if(!open){this.itemsClicked=false;}}updateEventListeners(){if(this.props.open){this.addEventListeners();}else {this.removeEventListeners();}}addEventListeners(){document.addEventListener("mouseup",this.handleInteract);document.addEventListener("touchend",this.handleInteract);}removeEventListeners(){document.removeEventListener("mouseup",this.handleInteract);document.removeEventListener("touchend",this.handleInteract);}scheduleToFocusCurrentItem(onFocus){if(this.shouldVirtualizeList()){this.props.schedule.animationFrame(()=>{this.focusCurrentItem(onFocus);});}else {this.focusCurrentItem(onFocus);}}focusCurrentItem(onFocus){const focusedItemRef=this.state.itemRefs[this.focusedIndex];if(!focusedItemRef){return}const{current:virtualizedList}=this.virtualizedListRef;if(virtualizedList){virtualizedList.scrollToItem(focusedItemRef.originalIndex);}const focusNode=()=>{if(!this.props.open){return}const currentFocusedItemRef=this.state.itemRefs[this.focusedIndex];const node=ReactDOM.findDOMNode(currentFocusedItemRef.ref.current);if(!node&&this.shouldVirtualizeList()){this.props.schedule.animationFrame(focusNode);return}if(node){node.focus();this.focusedOriginalIndex=currentFocusedItemRef.originalIndex;if(onFocus){onFocus(node);}}};if(this.shouldVirtualizeList()){this.props.schedule.animationFrame(focusNode);}else {focusNode();}}focusSearchField(){if(this.searchFieldRef.current){this.searchFieldRef.current.focus();}}hasSearchField(){return !!this.props.isFilterable}isSearchFieldFocused(){return this.hasSearchField()&&document.activeElement===this.searchFieldRef.current}focusPreviousItem(){if(this.focusedIndex===0||this.isSearchFieldFocused()&&!this.props.enableTypeAhead){if(this.hasSearchField()&&!this.isSearchFieldFocused()){return this.focusSearchField()}this.focusedIndex=this.state.itemRefs.length-1;}else if(!this.isSearchFieldFocused()){this.focusedIndex-=1;}this.scheduleToFocusCurrentItem();}focusNextItem(){if(this.focusedIndex===this.state.itemRefs.length-1||this.isSearchFieldFocused()&&!this.props.enableTypeAhead){if(this.hasSearchField()&&!this.isSearchFieldFocused()){return this.focusSearchField()}this.focusedIndex=0;}else if(!this.isSearchFieldFocused()){this.focusedIndex+=1;}this.scheduleToFocusCurrentItem();}restoreTabOrder(){if(this.props.openerElement){this.props.openerElement.focus();}}getItemRole(){const{role}=this.props;switch(role){case"listbox":return "option";case"menu":return "menuitem";default:throw new Error(`Expected "listbox" or "menu" for role, but receieved "${role}" instead.`)}}maybeRenderNoResults(){const{items,labels:{noResults}}=this.props;const numResults=items.length;if(numResults===0){return jsx(LabelMedium,{style:styles$6.noResult,testId:"dropdown-core-no-results",children:noResults})}return null}shouldVirtualizeList(){return this.props.items.length>VIRTUALIZE_THRESHOLD}renderList(){let focusCounter=0;const itemRole=this.getItemRole();return this.props.items.map((item,index)=>{if(SeparatorItem.isClassOf(item.component)){return item.component}const{component,focusable,populatedProps}=item;if(focusable){focusCounter+=1;}const focusIndex=focusCounter-1;const currentRef=this.state.itemRefs[focusIndex]?this.state.itemRefs[focusIndex].ref:null;return React.cloneElement(component,{...populatedProps,key:index,onClick:()=>{this.handleItemClick(focusIndex,item);},ref:focusable?currentRef:null,role:populatedProps.role||itemRole})})}parseVirtualizedItems(){let focusCounter=0;const itemRole=this.getItemRole();return this.props.items.map((item,index)=>{const{populatedProps}=item;if(!SeparatorItem.isClassOf(item.component)&&item.focusable){focusCounter+=1;}const focusIndex=focusCounter-1;return {...item,role:populatedProps.role||itemRole,ref:item.focusable&&this.state.itemRefs[focusIndex]?this.state.itemRefs[focusIndex].ref:null,onClick:()=>{this.handleItemClick(focusIndex,item);}}})}renderVirtualizedList(){const virtualizedItems=this.parseVirtualizedItems();return jsx(DropdownCoreVirtualized$1,{data:virtualizedItems,listRef:this.virtualizedListRef})}renderSearchField(){const{searchText}=this.props;const{labels}=this.state;return jsx(SearchField,{clearAriaLabel:labels.clearSearch,onChange:this.handleSearchTextChanged,placeholder:labels.filter,ref:this.searchFieldRef,style:styles$6.searchInputStyle,value:searchText||""})}renderDropdownMenu(listRenderer,isReferenceHidden){const{"aria-invalid":ariaInvalid,"aria-required":ariaRequired,dropdownStyle,isFilterable,openerElement,role,id}=this.props;const openerStyle=openerElement&&window.getComputedStyle(openerElement);const minDropdownWidth=openerStyle?openerStyle.getPropertyValue("width"):0;return jsxs(View,{onMouseUp:this.handleDropdownMouseUp,style:[styles$6.dropdown,isReferenceHidden&&styles$6.hidden,dropdownStyle],testId:"dropdown-core-container",children:[isFilterable&&this.renderSearchField(),jsx(View,{id:id,role:role,style:[styles$6.listboxOrMenu,{minWidth:minDropdownWidth}],"aria-invalid":role==="listbox"?ariaInvalid:undefined,"aria-required":role==="listbox"?ariaRequired:undefined,children:listRenderer}),this.maybeRenderNoResults()]})}renderDropdown(){const{alignment,openerElement}=this.props;const listRenderer=this.shouldVirtualizeList()?this.renderVirtualizedList():this.renderList();return jsx(DropdownPopper,{alignment:alignment,onPopperElement:popperElement=>{this.popperElement=popperElement;},referenceElement:openerElement,children:isReferenceHidden=>this.renderDropdownMenu(listRenderer,isReferenceHidden)})}render(){const{open,opener,style,className,disabled}=this.props;return jsxs(View,{onKeyDown:!disabled?this.handleKeyDown:undefined,onKeyUp:!disabled?this.handleKeyUp:undefined,style:[styles$6.menuWrapper,style],className:className,children:[opener,open&&this.renderDropdown()]})}constructor(props){super(props),this.focusedIndex=-1,this.focusedOriginalIndex=-1,this.itemsClicked=false,this.searchFieldRef=React.createRef(),this.handleInteract=event=>{const{open,onOpenChanged}=this.props;const target=event.target;const thisElement=ReactDOM.findDOMNode(this);if(open&&thisElement&&!thisElement.contains(target)&&this.popperElement&&!this.popperElement.contains(target)){onOpenChanged(false);}},this.handleKeyDown=event=>{const{enableTypeAhead,onOpenChanged,open,searchText}=this.props;const key=event.key;if(enableTypeAhead&&getStringForKey(key)){event.stopPropagation();this.textSuggestion+=key;this.handleKeyDownDebounced(this.textSuggestion);}if(!open){if(key===keys.down){event.preventDefault();onOpenChanged(true);return}return}switch(key){case keys.tab:if(this.isSearchFieldFocused()&&searchText){return}this.restoreTabOrder();onOpenChanged(false);return;case keys.space:if(this.isSearchFieldFocused()){return}event.preventDefault();return;case keys.up:event.preventDefault();this.focusPreviousItem();return;case keys.down:event.preventDefault();this.focusNextItem();return}},this.handleKeyUp=event=>{const{onOpenChanged,open}=this.props;const key=event.key;switch(key){case keys.space:if(this.isSearchFieldFocused()){return}event.preventDefault();return;case keys.escape:if(open){event.stopPropagation();this.restoreTabOrder();onOpenChanged(false);}return}},this.handleKeyDownDebounceResult=key=>{const foundIndex=this.props.items.filter(item=>item.focusable).findIndex(({component})=>{if(SeparatorItem.isClassOf(component)){return false}if(OptionItem.isClassOf(component)){const optionItemProps=component.props;return getLabel(optionItemProps).toLowerCase().startsWith(key.toLowerCase())}return false});if(foundIndex>=0){const isClosed=!this.props.open;if(isClosed){this.props.onOpenChanged(true);}this.focusedIndex=foundIndex;this.scheduleToFocusCurrentItem(node=>{if(this.props.selectionType==="single"&&isClosed&&node){node.click();this.props.onOpenChanged(false);}});}this.textSuggestion="";},this.handleClickFocus=index=>{this.itemsClicked=true;this.focusedIndex=index;this.focusedOriginalIndex=this.state.itemRefs[this.focusedIndex].originalIndex;},this.handleDropdownMouseUp=event=>{if(event.nativeEvent.stopImmediatePropagation){event.nativeEvent.stopImmediatePropagation();}else {event.stopPropagation();}},this.handleItemClick=(focusIndex,item)=>{this.handleClickFocus(focusIndex);if(item.component.props.onClick){item.component.props.onClick();}if(item.populatedProps.onClick){item.populatedProps.onClick();}},this.handleSearchTextChanged=searchText=>{const{onSearchTextChanged}=this.props;if(onSearchTextChanged){onSearchTextChanged(searchText);}};this.resetFocusedIndex();this.state={prevItems:this.props.items,itemRefs:[],sameItemsFocusable:false,labels:{noResults:defaultLabels.noResults,someResults:defaultLabels.someSelected,...props.labels}};this.virtualizedListRef=React.createRef();this.handleKeyDownDebounced=debounce(this.handleKeyDownDebounceResult,500);this.textSuggestion="";}}DropdownCore.defaultProps={alignment:"left",autoFocus:true,enableTypeAhead:true,labels:{clearSearch:defaultLabels.clearSearch,filter:defaultLabels.filter,noResults:defaultLabels.noResults,someResults:defaultLabels.someSelected},selectionType:"single"};const theme$3={dropdown:{color:{default:{background:semanticColor.surface.primary,border:semanticColor.border.primary}}},noResults:{color:{foreground:semanticColor.text.secondary}}};const styles$6=StyleSheet.create({menuWrapper:{width:"fit-content"},dropdown:{backgroundColor:theme$3.dropdown.color.default.background,borderRadius:border.radius.radius_040,paddingTop:spacing.xxxSmall_4,paddingBottom:spacing.xxxSmall_4,border:`solid 1px ${theme$3.dropdown.color.default.border}`,boxShadow:`0px 8px 8px 0px ${color.offBlack8}`,maxHeight:"var(--popper-max-height)"},listboxOrMenu:{overflowY:"auto"},hidden:{pointerEvents:"none",visibility:"hidden"},noResult:{color:theme$3.noResults.color.foreground,alignSelf:"center",marginTop:spacing.xxSmall_6},searchInputStyle:{margin:spacing.xSmall_8,marginTop:spacing.xxxSmall_4,minHeight:"auto",position:"sticky"},srOnly:{border:0,clip:"rect(0,0,0,0)",height:1,margin:-1,overflow:"hidden",padding:0,position:"absolute",width:1}});var DropdownCore$1 = withActionScheduler(DropdownCore);
1446
55
 
1447
- const _excluded$4 = ["children", "disabled", "focused", "hovered", "pressed", "waiting", "testId", "opened", "aria-label"];
1448
- const StyledButton$1 = addStyle("button");
1449
- class ActionMenuOpenerCore extends React.Component {
1450
- render() {
1451
- const _this$props = this.props,
1452
- {
1453
- children,
1454
- disabled: disabledProp,
1455
- focused,
1456
- hovered,
1457
- pressed,
1458
- testId,
1459
- opened,
1460
- "aria-label": ariaLabel
1461
- } = _this$props,
1462
- restProps = _objectWithoutPropertiesLoose(_this$props, _excluded$4);
1463
- const disabled = disabledProp;
1464
- const defaultStyle = [sharedStyles.shared, sharedStyles.default, disabled && sharedStyles.disabled, !disabled && pressed && sharedStyles.press];
1465
- const label = React.createElement(LabelLarge, {
1466
- style: sharedStyles.text
1467
- }, children);
1468
- return React.createElement(StyledButton$1, _extends({
1469
- "aria-expanded": opened ? "true" : "false",
1470
- "aria-haspopup": "menu",
1471
- "aria-label": ariaLabel,
1472
- disabled: disabled,
1473
- style: defaultStyle,
1474
- type: "button"
1475
- }, restProps, {
1476
- "data-testid": testId
1477
- }), React.createElement(View, {
1478
- style: !disabled && (hovered || focused) && sharedStyles.focus
1479
- }, label), React.createElement(Strut, {
1480
- size: spacing.xxxSmall_4
1481
- }), React.createElement(PhosphorIcon, {
1482
- size: "small",
1483
- color: "currentColor",
1484
- icon: caretDownIcon,
1485
- "aria-hidden": "true"
1486
- }));
1487
- }
1488
- }
1489
- const theme$2 = {
1490
- actionMenuOpener: {
1491
- color: {
1492
- default: {
1493
- background: "none",
1494
- foreground: semanticColor.action.secondary.progressive.default.foreground
1495
- },
1496
- disabled: {
1497
- foreground: semanticColor.action.secondary.disabled.foreground
1498
- },
1499
- press: {
1500
- foreground: semanticColor.action.secondary.progressive.press.foreground
1501
- }
1502
- }
1503
- }
1504
- };
1505
- const sharedStyles = StyleSheet.create({
1506
- shared: {
1507
- position: "relative",
1508
- display: "inline-flex",
1509
- alignItems: "center",
1510
- justifyContent: "center",
1511
- height: DROPDOWN_ITEM_HEIGHT,
1512
- border: "none",
1513
- borderRadius: border.radius.radius_040,
1514
- cursor: "pointer",
1515
- outline: "none",
1516
- textDecoration: "none",
1517
- boxSizing: "border-box",
1518
- touchAction: "manipulation",
1519
- ":focus": {
1520
- WebkitTapHighlightColor: "rgba(0,0,0,0)"
1521
- }
1522
- },
1523
- default: {
1524
- background: theme$2.actionMenuOpener.color.default.background,
1525
- color: theme$2.actionMenuOpener.color.default.foreground
1526
- },
1527
- disabled: {
1528
- color: theme$2.actionMenuOpener.color.disabled.foreground,
1529
- cursor: "not-allowed"
1530
- },
1531
- small: {
1532
- height: spacing.xLarge_32
1533
- },
1534
- text: {
1535
- textAlign: "left",
1536
- display: "inline-block",
1537
- alignItems: "center",
1538
- fontWeight: "bold",
1539
- userSelect: "none",
1540
- whiteSpace: "nowrap",
1541
- overflow: "hidden",
1542
- textOverflow: "ellipsis",
1543
- pointerEvents: "none"
1544
- },
1545
- focus: {
1546
- ":after": {
1547
- content: "''",
1548
- position: "absolute",
1549
- height: 2,
1550
- left: 0,
1551
- right: 0,
1552
- bottom: -1,
1553
- background: "currentColor"
1554
- }
1555
- },
1556
- press: {
1557
- color: theme$2.actionMenuOpener.color.press.foreground
1558
- }
1559
- });
56
+ const StyledButton$1=addStyle("button");class ActionMenuOpenerCore extends React.Component{render(){const{children,disabled:disabledProp,focused,hovered,pressed,waiting:_,testId,opened,"aria-label":ariaLabel,...restProps}=this.props;const disabled=disabledProp;const defaultStyle=[sharedStyles.shared,sharedStyles.default,disabled&&sharedStyles.disabled,!disabled&&pressed&&sharedStyles.press];const label=jsx(LabelLarge,{style:sharedStyles.text,children:children});return jsxs(StyledButton$1,{"aria-expanded":opened?"true":"false","aria-haspopup":"menu","aria-label":ariaLabel,disabled:disabled,style:defaultStyle,type:"button",...restProps,"data-testid":testId,children:[jsx(View,{style:!disabled&&(hovered||focused)&&sharedStyles.focus,children:label}),jsx(Strut,{size:spacing.xxxSmall_4}),jsx(PhosphorIcon,{size:"small",color:"currentColor",icon:caretDownIcon,"aria-hidden":"true"})]})}}const theme$2={actionMenuOpener:{color:{default:{background:"none",foreground:semanticColor.action.secondary.progressive.default.foreground},disabled:{foreground:semanticColor.action.secondary.disabled.foreground},press:{foreground:semanticColor.action.secondary.progressive.press.foreground}}}};const sharedStyles=StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",height:DROPDOWN_ITEM_HEIGHT,border:"none",borderRadius:border.radius.radius_040,cursor:"pointer",outline:"none",textDecoration:"none",boxSizing:"border-box",touchAction:"manipulation",":focus":{WebkitTapHighlightColor:"rgba(0,0,0,0)"}},default:{background:theme$2.actionMenuOpener.color.default.background,color:theme$2.actionMenuOpener.color.default.foreground},disabled:{color:theme$2.actionMenuOpener.color.disabled.foreground,cursor:"not-allowed"},small:{height:spacing.xLarge_32},text:{textAlign:"left",display:"inline-block",alignItems:"center",fontWeight:"bold",userSelect:"none",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",pointerEvents:"none"},focus:{":after":{content:"''",position:"absolute",height:2,left:0,right:0,bottom:-1,background:"currentColor"}},press:{color:theme$2.actionMenuOpener.color.press.foreground}});
1560
57
 
1561
- const _excluded$3 = ["text", "opened"];
1562
- class ActionMenu extends React.Component {
1563
- constructor(...args) {
1564
- super(...args);
1565
- this.openerElement = void 0;
1566
- this.state = {
1567
- opened: false
1568
- };
1569
- this.handleItemSelected = () => {
1570
- this.handleOpenChanged(false);
1571
- if (this.openerElement) {
1572
- this.openerElement.focus();
1573
- }
1574
- };
1575
- this.handleOpenChanged = opened => {
1576
- this.setState({
1577
- opened
1578
- });
1579
- if (this.props.onToggle) {
1580
- this.props.onToggle(opened);
1581
- }
1582
- };
1583
- this.handleOptionSelected = selectedValue => {
1584
- const {
1585
- onChange,
1586
- selectedValues
1587
- } = this.props;
1588
- if (!onChange || !selectedValues) {
1589
- return;
1590
- }
1591
- if (selectedValues.includes(selectedValue)) {
1592
- const index = selectedValues.indexOf(selectedValue);
1593
- const updatedSelection = [...selectedValues.slice(0, index), ...selectedValues.slice(index + 1)];
1594
- onChange(updatedSelection);
1595
- } else {
1596
- onChange([...selectedValues, selectedValue]);
1597
- }
1598
- this.handleItemSelected();
1599
- };
1600
- this.handleOpenerRef = node => {
1601
- this.openerElement = ReactDOM.findDOMNode(node);
1602
- };
1603
- this.handleClick = e => {
1604
- this.handleOpenChanged(!this.state.opened);
1605
- };
1606
- }
1607
- static getDerivedStateFromProps(props, state) {
1608
- return {
1609
- opened: typeof props.opened === "boolean" ? props.opened : state.opened
1610
- };
1611
- }
1612
- getMenuItems() {
1613
- const {
1614
- children,
1615
- selectedValues
1616
- } = this.props;
1617
- const allChildren = React.Children.toArray(children).filter(Boolean);
1618
- const isOptionItemIncluded = allChildren.some(item => OptionItem.isClassOf(item));
1619
- return allChildren.map(item => {
1620
- const {
1621
- value,
1622
- disabled
1623
- } = item.props;
1624
- const itemObject = {
1625
- component: item,
1626
- focusable: ActionItem.isClassOf(item) || OptionItem.isClassOf(item) ? !disabled : false,
1627
- populatedProps: {}
1628
- };
1629
- if (ActionItem.isClassOf(item)) {
1630
- return _extends({}, itemObject, {
1631
- populatedProps: {
1632
- indent: isOptionItemIncluded,
1633
- onClick: this.handleItemSelected
1634
- }
1635
- });
1636
- } else if (OptionItem.isClassOf(item)) {
1637
- const selected = selectedValues ? selectedValues.includes(value) : false;
1638
- return _extends({}, itemObject, {
1639
- populatedProps: {
1640
- onToggle: this.handleOptionSelected,
1641
- selected,
1642
- variant: "check",
1643
- role: "menuitemcheckbox",
1644
- "aria-checked": selected,
1645
- "aria-selected": undefined
1646
- }
1647
- });
1648
- } else {
1649
- return itemObject;
1650
- }
1651
- });
1652
- }
1653
- renderOpener(numItems, dropdownId) {
1654
- const {
1655
- disabled,
1656
- menuText,
1657
- opener,
1658
- testId,
1659
- id
1660
- } = this.props;
1661
- return React.createElement(Id, {
1662
- id: id
1663
- }, uniqueOpenerId => React.createElement(DropdownOpener, {
1664
- id: uniqueOpenerId,
1665
- "aria-controls": dropdownId,
1666
- "aria-haspopup": "menu",
1667
- onClick: this.handleClick,
1668
- disabled: numItems === 0 || disabled,
1669
- text: menuText,
1670
- ref: this.handleOpenerRef,
1671
- testId: opener ? undefined : testId,
1672
- opened: this.state.opened,
1673
- role: "button"
1674
- }, opener ? opener : openerProps => {
1675
- const {
1676
- opened
1677
- } = openerProps,
1678
- eventState = _objectWithoutPropertiesLoose(openerProps, _excluded$3);
1679
- return React.createElement(ActionMenuOpenerCore, _extends({}, eventState, {
1680
- disabled: disabled,
1681
- opened: !!opened,
1682
- testId: testId
1683
- }), menuText);
1684
- }));
1685
- }
1686
- render() {
1687
- const {
1688
- alignment,
1689
- dropdownStyle,
1690
- style,
1691
- className,
1692
- dropdownId
1693
- } = this.props;
1694
- const items = this.getMenuItems();
1695
- return React.createElement(Id, {
1696
- id: dropdownId
1697
- }, uniqueDropdownId => React.createElement(DropdownCore$1, {
1698
- id: uniqueDropdownId,
1699
- role: "menu",
1700
- style: style,
1701
- className: className,
1702
- opener: this.renderOpener(items.length, uniqueDropdownId),
1703
- alignment: alignment,
1704
- open: this.state.opened,
1705
- items: items,
1706
- openerElement: this.openerElement,
1707
- onOpenChanged: this.handleOpenChanged,
1708
- dropdownStyle: [styles$5.menuTopSpace, dropdownStyle]
1709
- }));
1710
- }
1711
- }
1712
- ActionMenu.defaultProps = {
1713
- alignment: "left",
1714
- disabled: false
1715
- };
1716
- const styles$5 = StyleSheet.create({
1717
- caret: {
1718
- marginLeft: 4
1719
- },
1720
- opener: {
1721
- whiteSpace: "nowrap",
1722
- userSelect: "none",
1723
- overflow: "hidden",
1724
- textOverflow: "ellipsis"
1725
- },
1726
- menuTopSpace: {
1727
- top: -4
1728
- }
1729
- });
58
+ class ActionMenu extends React.Component{static getDerivedStateFromProps(props,state){return {opened:typeof props.opened==="boolean"?props.opened:state.opened}}getMenuItems(){const{children,selectedValues}=this.props;const allChildren=React.Children.toArray(children).filter(Boolean);const isOptionItemIncluded=allChildren.some(item=>OptionItem.isClassOf(item));return allChildren.map(item=>{const{value,disabled}=item.props;const itemObject={component:item,focusable:ActionItem.isClassOf(item)||OptionItem.isClassOf(item)?!disabled:false,populatedProps:{}};if(ActionItem.isClassOf(item)){return {...itemObject,populatedProps:{indent:isOptionItemIncluded,onClick:this.handleItemSelected}}}else if(OptionItem.isClassOf(item)){const selected=selectedValues?selectedValues.includes(value):false;return {...itemObject,populatedProps:{onToggle:this.handleOptionSelected,selected,variant:"check",role:"menuitemcheckbox","aria-checked":selected,"aria-selected":undefined}}}else {return itemObject}})}renderOpener(numItems,dropdownId){const{disabled,menuText,opener,testId,id}=this.props;return jsx(Id,{id:id,children:uniqueOpenerId=>jsx(DropdownOpener,{id:uniqueOpenerId,"aria-controls":dropdownId,"aria-haspopup":"menu",onClick:this.handleClick,disabled:numItems===0||disabled,text:menuText,ref:this.handleOpenerRef,testId:opener?undefined:testId,opened:this.state.opened,role:"button",children:opener?opener:openerProps=>{const{text,opened,...eventState}=openerProps;return jsx(ActionMenuOpenerCore,{...eventState,disabled:disabled,opened:!!opened,testId:testId,children:menuText})}})})}render(){const{alignment,dropdownStyle,style,className,dropdownId}=this.props;const items=this.getMenuItems();return jsx(Id,{id:dropdownId,children:uniqueDropdownId=>jsx(DropdownCore$1,{id:uniqueDropdownId,role:"menu",style:style,className:className,opener:this.renderOpener(items.length,uniqueDropdownId),alignment:alignment,open:this.state.opened,items:items,openerElement:this.openerElement,onOpenChanged:this.handleOpenChanged,dropdownStyle:[styles$5.menuTopSpace,dropdownStyle]})})}constructor(...args){super(...args),this.state={opened:false},this.handleItemSelected=()=>{this.handleOpenChanged(false);if(this.openerElement){this.openerElement.focus();}},this.handleOpenChanged=opened=>{this.setState({opened});if(this.props.onToggle){this.props.onToggle(opened);}},this.handleOptionSelected=selectedValue=>{const{onChange,selectedValues}=this.props;if(!onChange||!selectedValues){return}if(selectedValues.includes(selectedValue)){const index=selectedValues.indexOf(selectedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,selectedValue]);}this.handleItemSelected();},this.handleOpenerRef=node=>{this.openerElement=ReactDOM.findDOMNode(node);},this.handleClick=e=>{this.handleOpenChanged(!this.state.opened);};}}ActionMenu.defaultProps={alignment:"left",disabled:false};const styles$5=StyleSheet.create({caret:{marginLeft:4},opener:{whiteSpace:"nowrap",userSelect:"none",overflow:"hidden",textOverflow:"ellipsis"},menuTopSpace:{top:-4}});
1730
59
 
1731
- const _excluded$2 = ["children", "disabled", "error", "id", "isPlaceholder", "open", "testId", "aria-label", "aria-required", "aria-controls", "onBlur", "onOpenChanged"];
1732
- const StyledButton = addStyle("button");
1733
- class SelectOpener extends React.Component {
1734
- constructor(props) {
1735
- super(props);
1736
- this.handleClick = e => {
1737
- const {
1738
- open
1739
- } = this.props;
1740
- this.props.onOpenChanged(!open);
1741
- };
1742
- this.handleKeyDown = e => {
1743
- const keyName = e.key;
1744
- if (keyName === keys.enter || keyName === keys.space) {
1745
- this.setState({
1746
- pressed: true
1747
- });
1748
- e.preventDefault();
1749
- }
1750
- };
1751
- this.handleKeyUp = e => {
1752
- const keyName = e.key;
1753
- if (keyName === keys.enter || keyName === keys.space) {
1754
- this.setState({
1755
- pressed: false
1756
- });
1757
- this.handleClick(e);
1758
- }
1759
- };
1760
- this.state = {
1761
- pressed: false
1762
- };
1763
- }
1764
- render() {
1765
- const _this$props = this.props,
1766
- {
1767
- children,
1768
- disabled,
1769
- error,
1770
- id,
1771
- isPlaceholder,
1772
- open,
1773
- testId,
1774
- "aria-label": ariaLabel,
1775
- "aria-required": ariaRequired,
1776
- "aria-controls": ariaControls,
1777
- onBlur
1778
- } = _this$props,
1779
- sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
1780
- const stateStyles = _generateStyles(isPlaceholder, error);
1781
- const iconColor = disabled ? semanticColor.icon.disabled : semanticColor.icon.primary;
1782
- const style = [styles$4.shared, stateStyles.default, disabled && stateStyles.disabled, !disabled && this.state.pressed && stateStyles.press];
1783
- return React.createElement(StyledButton, _extends({}, sharedProps, {
1784
- "aria-disabled": disabled,
1785
- "aria-expanded": open ? "true" : "false",
1786
- "aria-invalid": error,
1787
- "aria-label": ariaLabel != null ? ariaLabel : undefined,
1788
- "aria-required": ariaRequired,
1789
- "aria-haspopup": "listbox",
1790
- "aria-controls": ariaControls,
1791
- "data-testid": testId,
1792
- id: id,
1793
- role: "combobox",
1794
- type: "button",
1795
- style: style,
1796
- onClick: !disabled ? this.handleClick : undefined,
1797
- onKeyDown: !disabled ? this.handleKeyDown : undefined,
1798
- onKeyUp: !disabled ? this.handleKeyUp : undefined,
1799
- onBlur: onBlur
1800
- }), React.createElement(LabelMedium, {
1801
- style: styles$4.text
1802
- }, children || React.createElement("span", {
1803
- "aria-hidden": "true"
1804
- }, "\xA0")), React.createElement(PhosphorIcon, {
1805
- icon: caretDownIcon,
1806
- color: iconColor,
1807
- size: "small",
1808
- style: styles$4.caret,
1809
- "aria-hidden": "true"
1810
- }));
1811
- }
1812
- }
1813
- SelectOpener.defaultProps = {
1814
- disabled: false,
1815
- error: false,
1816
- isPlaceholder: false
1817
- };
1818
- const styles$4 = StyleSheet.create({
1819
- shared: {
1820
- position: "relative",
1821
- display: "inline-flex",
1822
- alignItems: "center",
1823
- justifyContent: "space-between",
1824
- color: semanticColor.text.primary,
1825
- height: DROPDOWN_ITEM_HEIGHT,
1826
- paddingLeft: spacing.medium_16,
1827
- paddingRight: spacing.small_12,
1828
- borderWidth: 0,
1829
- borderRadius: border.radius.radius_040,
1830
- borderStyle: "solid",
1831
- outline: "none",
1832
- textDecoration: "none",
1833
- boxSizing: "border-box",
1834
- whiteSpace: "nowrap",
1835
- touchAction: "manipulation"
1836
- },
1837
- text: {
1838
- marginRight: spacing.xSmall_8,
1839
- whiteSpace: "nowrap",
1840
- userSelect: "none",
1841
- overflow: "hidden",
1842
- textOverflow: "ellipsis"
1843
- },
1844
- caret: {
1845
- minWidth: 16
1846
- }
1847
- });
1848
- const stateStyles = {};
1849
- const _generateStyles = (placeholder, error) => {
1850
- const styleKey = `${placeholder}-${error}`;
1851
- if (stateStyles[styleKey]) {
1852
- return stateStyles[styleKey];
1853
- }
1854
- const states = {
1855
- default: {
1856
- border: semanticColor.border.strong,
1857
- background: semanticColor.surface.primary,
1858
- foreground: semanticColor.text.primary
1859
- },
1860
- disabled: {
1861
- border: semanticColor.action.secondary.disabled.border,
1862
- background: semanticColor.action.secondary.disabled.background,
1863
- foreground: semanticColor.text.secondary
1864
- },
1865
- error: {
1866
- border: semanticColor.status.critical.foreground,
1867
- background: semanticColor.status.critical.background,
1868
- foreground: semanticColor.text.primary
1869
- }
1870
- };
1871
- const actionType = error ? "destructive" : "progressive";
1872
- const action = semanticColor.action.secondary[actionType];
1873
- const sharedOutlineStyling = {
1874
- outlineOffset: `calc(${border.width.medium} * -1)`,
1875
- outlineStyle: "solid",
1876
- outlineWidth: border.width.medium
1877
- };
1878
- const focusStyling = _extends({}, sharedOutlineStyling, {
1879
- outlineColor: semanticColor.focus.outer
1880
- });
1881
- const hoverStyling = _extends({}, sharedOutlineStyling, {
1882
- outlineColor: action.hover.border
1883
- });
1884
- const pressStyling = _extends({
1885
- background: action.press.background,
1886
- color: placeholder ? error ? semanticColor.text.secondary : semanticColor.action.secondary.progressive.press.foreground : semanticColor.text.primary,
1887
- outlineColor: action.press.border
1888
- }, sharedOutlineStyling);
1889
- const currentState = error ? states.error : states.default;
1890
- const newStyles = {
1891
- default: {
1892
- background: currentState.background,
1893
- borderColor: currentState.border,
1894
- borderWidth: border.width.thin,
1895
- color: placeholder ? semanticColor.text.secondary : currentState.foreground,
1896
- ":hover:not([aria-disabled=true])": hoverStyling,
1897
- ["@media not (hover: hover)"]: {
1898
- ":hover:not([aria-disabled=true])": {
1899
- borderColor: currentState.border,
1900
- borderWidth: border.width.thin,
1901
- paddingLeft: spacing.medium_16,
1902
- paddingRight: spacing.small_12
1903
- }
1904
- },
1905
- ":focus-visible:not([aria-disabled=true])": focusStyling,
1906
- ":active:not([aria-disabled=true])": pressStyling
1907
- },
1908
- disabled: {
1909
- background: states.disabled.background,
1910
- borderColor: states.disabled.border,
1911
- color: states.disabled.foreground,
1912
- cursor: "not-allowed",
1913
- ":focus-visible": _extends({
1914
- outlineColor: semanticColor.focus.outer
1915
- }, sharedOutlineStyling)
1916
- },
1917
- press: pressStyling
1918
- };
1919
- stateStyles[styleKey] = StyleSheet.create(newStyles);
1920
- return stateStyles[styleKey];
1921
- };
60
+ const StyledButton=addStyle("button");class SelectOpener extends React.Component{render(){const{children,disabled,error,id,isPlaceholder,open,testId,"aria-label":ariaLabel,"aria-required":ariaRequired,"aria-controls":ariaControls,onBlur,onOpenChanged,...sharedProps}=this.props;const stateStyles=_generateStyles(isPlaceholder,error);const iconColor=disabled?semanticColor.icon.disabled:semanticColor.icon.primary;const style=[styles$4.shared,stateStyles.default,disabled&&stateStyles.disabled,!disabled&&this.state.pressed&&stateStyles.press];return jsxs(StyledButton,{...sharedProps,"aria-disabled":disabled,"aria-expanded":open?"true":"false","aria-invalid":error,"aria-label":ariaLabel??undefined,"aria-required":ariaRequired,"aria-haspopup":"listbox","aria-controls":ariaControls,"data-testid":testId,id:id,role:"combobox",type:"button",style:style,onClick:!disabled?this.handleClick:undefined,onKeyDown:!disabled?this.handleKeyDown:undefined,onKeyUp:!disabled?this.handleKeyUp:undefined,onBlur:onBlur,children:[jsx(LabelMedium,{style:styles$4.text,children:children||jsx("span",{"aria-hidden":"true",children:" "})}),jsx(PhosphorIcon,{icon:caretDownIcon,color:iconColor,size:"small",style:styles$4.caret,"aria-hidden":"true"})]})}constructor(props){super(props),this.handleClick=e=>{const{open}=this.props;this.props.onOpenChanged(!open);},this.handleKeyDown=e=>{const keyName=e.key;if(keyName===keys.enter||keyName===keys.space){this.setState({pressed:true});e.preventDefault();}},this.handleKeyUp=e=>{const keyName=e.key;if(keyName===keys.enter||keyName===keys.space){this.setState({pressed:false});this.handleClick(e);}};this.state={pressed:false};}}SelectOpener.defaultProps={disabled:false,error:false,isPlaceholder:false};const styles$4=StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"space-between",color:semanticColor.text.primary,height:DROPDOWN_ITEM_HEIGHT,paddingLeft:spacing.medium_16,paddingRight:spacing.small_12,borderWidth:0,borderRadius:border.radius.radius_040,borderStyle:"solid",outline:"none",textDecoration:"none",boxSizing:"border-box",whiteSpace:"nowrap",touchAction:"manipulation"},text:{marginRight:spacing.xSmall_8,whiteSpace:"nowrap",userSelect:"none",overflow:"hidden",textOverflow:"ellipsis"},caret:{minWidth:16}});const stateStyles={};const _generateStyles=(placeholder,error)=>{const styleKey=`${placeholder}-${error}`;if(stateStyles[styleKey]){return stateStyles[styleKey]}const states={default:{border:semanticColor.border.strong,background:semanticColor.surface.primary,foreground:semanticColor.text.primary},disabled:{border:semanticColor.action.secondary.disabled.border,background:semanticColor.action.secondary.disabled.background,foreground:semanticColor.text.secondary},error:{border:semanticColor.status.critical.foreground,background:semanticColor.status.critical.background,foreground:semanticColor.text.primary}};const actionType=error?"destructive":"progressive";const action=semanticColor.action.secondary[actionType];const sharedOutlineStyling={outlineOffset:`calc(${border.width.medium} * -1)`,outlineStyle:"solid",outlineWidth:border.width.medium};const focusStyling={...sharedOutlineStyling,outlineColor:semanticColor.focus.outer};const hoverStyling={...sharedOutlineStyling,outlineColor:action.hover.border};const pressStyling={background:action.press.background,color:placeholder?error?semanticColor.text.secondary:semanticColor.action.secondary.progressive.press.foreground:semanticColor.text.primary,outlineColor:action.press.border,...sharedOutlineStyling};const currentState=error?states.error:states.default;const newStyles={default:{background:currentState.background,borderColor:currentState.border,borderWidth:border.width.thin,color:placeholder?semanticColor.text.secondary:currentState.foreground,":hover:not([aria-disabled=true])":hoverStyling,["@media not (hover: hover)"]:{":hover:not([aria-disabled=true])":{borderColor:currentState.border,borderWidth:border.width.thin,paddingLeft:spacing.medium_16,paddingRight:spacing.small_12}},":focus-visible:not([aria-disabled=true])":focusStyling,":active:not([aria-disabled=true])":pressStyling},disabled:{background:states.disabled.background,borderColor:states.disabled.border,color:states.disabled.foreground,cursor:"not-allowed",":focus-visible":{outlineColor:semanticColor.focus.outer,...sharedOutlineStyling}},press:pressStyling};stateStyles[styleKey]=StyleSheet.create(newStyles);return stateStyles[styleKey]};
1922
61
 
1923
- const defaultErrorMessage = "This field is required.";
1924
- function hasValue(value) {
1925
- return value ? value.length > 0 : false;
1926
- }
1927
- function useSelectValidation({
1928
- value,
1929
- disabled = false,
1930
- validate,
1931
- onValidate,
1932
- required,
1933
- open
1934
- }) {
1935
- const [errorMessage, setErrorMessage] = React.useState(() => validate && hasValue(value) && !disabled && validate(value) || null);
1936
- const handleValidation = React.useCallback(newValue => {
1937
- if (disabled) {
1938
- return;
1939
- }
1940
- if (validate) {
1941
- const error = newValue !== undefined && validate(newValue) || null;
1942
- setErrorMessage(error);
1943
- if (onValidate) {
1944
- onValidate(error);
1945
- }
1946
- if (error) {
1947
- return;
1948
- }
1949
- }
1950
- if (required) {
1951
- const requiredString = typeof required === "string" ? required : defaultErrorMessage;
1952
- const error = hasValue(newValue) ? null : requiredString;
1953
- setErrorMessage(error);
1954
- if (onValidate) {
1955
- onValidate(error);
1956
- }
1957
- }
1958
- }, [disabled, validate, setErrorMessage, onValidate, required]);
1959
- useOnMountEffect(() => {
1960
- if (hasValue(value)) {
1961
- handleValidation(value);
1962
- }
1963
- });
1964
- function onOpenerBlurValidation() {
1965
- if (!open && required && !hasValue(value)) {
1966
- handleValidation(value);
1967
- }
1968
- }
1969
- const onDropdownClosedValidation = () => {
1970
- if (required && !hasValue(value)) {
1971
- handleValidation(value);
1972
- }
1973
- };
1974
- const onSelectionValidation = newValue => {
1975
- handleValidation(newValue);
1976
- };
1977
- const onSelectedValuesChangeValidation = () => {
1978
- setErrorMessage(null);
1979
- if (onValidate) {
1980
- onValidate(null);
1981
- }
1982
- };
1983
- return {
1984
- errorMessage,
1985
- onOpenerBlurValidation,
1986
- onDropdownClosedValidation,
1987
- onSelectionValidation,
1988
- onSelectedValuesChangeValidation
1989
- };
1990
- }
62
+ const defaultErrorMessage="This field is required.";function hasValue(value){return value?value.length>0:false}function useSelectValidation({value,disabled=false,validate,onValidate,required,open}){const[errorMessage,setErrorMessage]=React.useState(()=>validate&&hasValue(value)&&!disabled&&validate(value)||null);const handleValidation=React.useCallback(newValue=>{if(disabled){return}if(validate){const error=newValue!==undefined&&validate(newValue)||null;setErrorMessage(error);if(onValidate){onValidate(error);}if(error){return}}if(required){const requiredString=typeof required==="string"?required:defaultErrorMessage;const error=hasValue(newValue)?null:requiredString;setErrorMessage(error);if(onValidate){onValidate(error);}}},[disabled,validate,setErrorMessage,onValidate,required]);useOnMountEffect(()=>{if(hasValue(value)){handleValidation(value);}});function onOpenerBlurValidation(){if(!open&&required&&!hasValue(value)){handleValidation(value);}}const onDropdownClosedValidation=()=>{if(required&&!hasValue(value)){handleValidation(value);}};const onSelectionValidation=newValue=>{handleValidation(newValue);};const onSelectedValuesChangeValidation=()=>{setErrorMessage(null);if(onValidate){onValidate(null);}};return {errorMessage,onOpenerBlurValidation,onDropdownClosedValidation,onSelectionValidation,onSelectedValuesChangeValidation}}
1991
63
 
1992
- const _excluded$1 = ["children", "error", "id", "opener", "placeholder", "selectedValue", "testId", "alignment", "autoFocus", "dropdownStyle", "enableTypeAhead", "isFilterable", "labels", "onChange", "onToggle", "opened", "style", "className", "aria-label", "aria-invalid", "aria-required", "disabled", "dropdownId", "validate", "onValidate", "required", "showOpenerLabelAsText"];
1993
- const SingleSelect = props => {
1994
- const selectedIndex = React.useRef(0);
1995
- const {
1996
- children,
1997
- error = false,
1998
- id,
1999
- opener,
2000
- placeholder,
2001
- selectedValue,
2002
- testId,
2003
- alignment = "left",
2004
- autoFocus = true,
2005
- dropdownStyle,
2006
- enableTypeAhead = true,
2007
- isFilterable,
2008
- labels = {
2009
- clearSearch: defaultLabels.clearSearch,
2010
- filter: defaultLabels.filter,
2011
- noResults: defaultLabels.noResults,
2012
- someResults: defaultLabels.someSelected
2013
- },
2014
- onChange,
2015
- onToggle,
2016
- opened,
2017
- style,
2018
- className,
2019
- "aria-label": ariaLabel,
2020
- "aria-invalid": ariaInvalid,
2021
- "aria-required": ariaRequired,
2022
- disabled = false,
2023
- dropdownId,
2024
- validate,
2025
- onValidate,
2026
- required,
2027
- showOpenerLabelAsText = true
2028
- } = props,
2029
- sharedProps = _objectWithoutPropertiesLoose(props, _excluded$1);
2030
- const [open, setOpen] = React.useState(false);
2031
- const [searchText, setSearchText] = React.useState("");
2032
- const [openerElement, setOpenerElement] = React.useState();
2033
- const {
2034
- errorMessage,
2035
- onOpenerBlurValidation,
2036
- onDropdownClosedValidation,
2037
- onSelectionValidation
2038
- } = useSelectValidation({
2039
- value: selectedValue,
2040
- disabled,
2041
- validate,
2042
- onValidate,
2043
- required,
2044
- open
2045
- });
2046
- const hasError = error || !!errorMessage;
2047
- React.useEffect(() => {
2048
- if (disabled) {
2049
- setOpen(false);
2050
- } else if (typeof opened === "boolean") {
2051
- setOpen(opened);
2052
- }
2053
- }, [disabled, opened]);
2054
- const handleOpenChanged = opened => {
2055
- setOpen(opened);
2056
- setSearchText("");
2057
- if (onToggle) {
2058
- onToggle(opened);
2059
- }
2060
- if (!opened) {
2061
- onDropdownClosedValidation();
2062
- }
2063
- };
2064
- const handleToggle = newSelectedValue => {
2065
- if (newSelectedValue !== selectedValue) {
2066
- onChange(newSelectedValue);
2067
- }
2068
- if (open && openerElement) {
2069
- openerElement.focus();
2070
- }
2071
- setOpen(false);
2072
- if (onToggle) {
2073
- onToggle(false);
2074
- }
2075
- onSelectionValidation(newSelectedValue);
2076
- };
2077
- const mapOptionItemsToDropdownItems = children => {
2078
- let indexCounter = 0;
2079
- selectedIndex.current = 0;
2080
- return children.map(option => {
2081
- const {
2082
- disabled,
2083
- value
2084
- } = option.props;
2085
- const selected = selectedValue === value;
2086
- if (selected) {
2087
- selectedIndex.current = indexCounter;
2088
- }
2089
- if (!disabled) {
2090
- indexCounter += 1;
2091
- }
2092
- return {
2093
- component: option,
2094
- focusable: !disabled,
2095
- populatedProps: {
2096
- onToggle: handleToggle,
2097
- selected: selected,
2098
- variant: "check"
2099
- }
2100
- };
2101
- });
2102
- };
2103
- const filterChildren = children => {
2104
- const lowercasedSearchText = searchText.toLowerCase();
2105
- return children.filter(({
2106
- props
2107
- }) => !searchText || getLabel(props).toLowerCase().indexOf(lowercasedSearchText) > -1);
2108
- };
2109
- const getMenuItems = children => {
2110
- return mapOptionItemsToDropdownItems(isFilterable ? filterChildren(children) : children);
2111
- };
2112
- const handleSearchTextChanged = searchText => {
2113
- setSearchText(searchText);
2114
- };
2115
- const handleOpenerRef = node => {
2116
- const openerElement = ReactDOM.findDOMNode(node);
2117
- setOpenerElement(openerElement);
2118
- };
2119
- const handleClick = e => {
2120
- handleOpenChanged(!open);
2121
- };
2122
- const handleAnnouncement = message => {
2123
- announceMessage({
2124
- message
2125
- });
2126
- };
2127
- React.useEffect(() => {
2128
- const optionItems = React.Children.toArray(children);
2129
- const selectedItem = optionItems.find(option => option.props.value === selectedValue);
2130
- if (selectedItem) {
2131
- const label = getLabel(selectedItem.props);
2132
- if (label) {
2133
- handleAnnouncement(label);
2134
- }
2135
- }
2136
- }, [selectedValue, children]);
2137
- const renderOpener = (isDisabled, dropdownId) => {
2138
- const items = React.Children.toArray(children);
2139
- const selectedItem = items.find(option => option.props.value === selectedValue);
2140
- let menuContent;
2141
- if (selectedItem) {
2142
- menuContent = getSelectOpenerLabel(showOpenerLabelAsText, selectedItem.props);
2143
- } else {
2144
- menuContent = placeholder;
2145
- }
2146
- const dropdownOpener = React.createElement(Id, {
2147
- id: id
2148
- }, uniqueOpenerId => {
2149
- return opener ? React.createElement(DropdownOpener, {
2150
- id: uniqueOpenerId,
2151
- "aria-label": ariaLabel,
2152
- "aria-controls": dropdownId,
2153
- "aria-haspopup": "listbox",
2154
- onClick: handleClick,
2155
- disabled: isDisabled,
2156
- ref: handleOpenerRef,
2157
- role: "combobox",
2158
- text: menuContent,
2159
- opened: open,
2160
- error: hasError,
2161
- onBlur: onOpenerBlurValidation
2162
- }, opener) : React.createElement(SelectOpener, _extends({}, sharedProps, {
2163
- "aria-label": ariaLabel,
2164
- "aria-controls": dropdownId,
2165
- disabled: isDisabled,
2166
- id: uniqueOpenerId,
2167
- error: hasError,
2168
- isPlaceholder: !selectedItem,
2169
- onOpenChanged: handleOpenChanged,
2170
- open: open,
2171
- ref: handleOpenerRef,
2172
- testId: testId,
2173
- onBlur: onOpenerBlurValidation
2174
- }), menuContent);
2175
- });
2176
- return dropdownOpener;
2177
- };
2178
- const allChildren = React.Children.toArray(children).filter(Boolean);
2179
- const numEnabledOptions = allChildren.filter(option => !option.props.disabled).length;
2180
- const items = getMenuItems(allChildren);
2181
- const isDisabled = numEnabledOptions === 0 || disabled;
2182
- const {
2183
- someResults
2184
- } = labels;
2185
- React.useEffect(() => {
2186
- if (open) {
2187
- handleAnnouncement(someResults(items.length));
2188
- }
2189
- }, [items.length, someResults, open]);
2190
- return React.createElement(Id, {
2191
- id: dropdownId
2192
- }, uniqueDropdownId => React.createElement(DropdownCore$1, {
2193
- id: uniqueDropdownId,
2194
- role: "listbox",
2195
- selectionType: "single",
2196
- alignment: alignment,
2197
- autoFocus: autoFocus,
2198
- enableTypeAhead: enableTypeAhead,
2199
- dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
2200
- initialFocusedIndex: selectedIndex.current,
2201
- items: items,
2202
- onOpenChanged: handleOpenChanged,
2203
- open: open,
2204
- opener: renderOpener(isDisabled, uniqueDropdownId),
2205
- openerElement: openerElement,
2206
- style: style,
2207
- className: className,
2208
- isFilterable: isFilterable,
2209
- onSearchTextChanged: isFilterable ? handleSearchTextChanged : undefined,
2210
- searchText: isFilterable ? searchText : "",
2211
- labels: labels,
2212
- "aria-invalid": ariaInvalid,
2213
- "aria-required": ariaRequired,
2214
- disabled: isDisabled
2215
- }));
2216
- };
64
+ const SingleSelect=props=>{const selectedIndex=React.useRef(0);const{children,error=false,id,opener,placeholder,selectedValue,testId,alignment="left",autoFocus=true,dropdownStyle,enableTypeAhead=true,isFilterable,labels={clearSearch:defaultLabels.clearSearch,filter:defaultLabels.filter,noResults:defaultLabels.noResults,someResults:defaultLabels.someSelected},onChange,onToggle,opened,style,className,"aria-label":ariaLabel,"aria-invalid":ariaInvalid,"aria-required":ariaRequired,disabled=false,dropdownId,validate,onValidate,required,showOpenerLabelAsText=true,...sharedProps}=props;const[open,setOpen]=React.useState(false);const[searchText,setSearchText]=React.useState("");const[openerElement,setOpenerElement]=React.useState();const{errorMessage,onOpenerBlurValidation,onDropdownClosedValidation,onSelectionValidation}=useSelectValidation({value:selectedValue,disabled,validate,onValidate,required,open});const hasError=error||!!errorMessage;React.useEffect(()=>{if(disabled){setOpen(false);}else if(typeof opened==="boolean"){setOpen(opened);}},[disabled,opened]);const handleOpenChanged=opened=>{setOpen(opened);setSearchText("");if(onToggle){onToggle(opened);}if(!opened){onDropdownClosedValidation();}};const handleToggle=newSelectedValue=>{if(newSelectedValue!==selectedValue){onChange(newSelectedValue);}if(open&&openerElement){openerElement.focus();}setOpen(false);if(onToggle){onToggle(false);}onSelectionValidation(newSelectedValue);};const mapOptionItemsToDropdownItems=children=>{let indexCounter=0;selectedIndex.current=0;return children.map(option=>{const{disabled,value}=option.props;const selected=selectedValue===value;if(selected){selectedIndex.current=indexCounter;}if(!disabled){indexCounter+=1;}return {component:option,focusable:!disabled,populatedProps:{onToggle:handleToggle,selected:selected,variant:"check"}}})};const filterChildren=children=>{const lowercasedSearchText=searchText.toLowerCase();return children.filter(({props})=>!searchText||getLabel(props).toLowerCase().indexOf(lowercasedSearchText)>-1)};const getMenuItems=children=>{return mapOptionItemsToDropdownItems(isFilterable?filterChildren(children):children)};const handleSearchTextChanged=searchText=>{setSearchText(searchText);};const handleOpenerRef=node=>{const openerElement=ReactDOM.findDOMNode(node);setOpenerElement(openerElement);};const handleClick=e=>{handleOpenChanged(!open);};const handleAnnouncement=message=>{announceMessage({message});};React.useEffect(()=>{const optionItems=React.Children.toArray(children);const selectedItem=optionItems.find(option=>option.props.value===selectedValue);if(selectedItem){const label=getLabel(selectedItem.props);if(label){handleAnnouncement(label);}}},[selectedValue,children]);const renderOpener=(isDisabled,dropdownId)=>{const items=React.Children.toArray(children);const selectedItem=items.find(option=>option.props.value===selectedValue);let menuContent;if(selectedItem){menuContent=getSelectOpenerLabel(showOpenerLabelAsText,selectedItem.props);}else {menuContent=placeholder;}const dropdownOpener=jsx(Id,{id:id,children:uniqueOpenerId=>{return opener?jsx(DropdownOpener,{id:uniqueOpenerId,"aria-label":ariaLabel,"aria-controls":dropdownId,"aria-haspopup":"listbox",onClick:handleClick,disabled:isDisabled,ref:handleOpenerRef,role:"combobox",text:menuContent,opened:open,error:hasError,onBlur:onOpenerBlurValidation,children:opener}):jsx(SelectOpener,{...sharedProps,"aria-label":ariaLabel,"aria-controls":dropdownId,disabled:isDisabled,id:uniqueOpenerId,error:hasError,isPlaceholder:!selectedItem,onOpenChanged:handleOpenChanged,open:open,ref:handleOpenerRef,testId:testId,onBlur:onOpenerBlurValidation,children:menuContent})}});return dropdownOpener};const allChildren=React.Children.toArray(children).filter(Boolean);const numEnabledOptions=allChildren.filter(option=>!option.props.disabled).length;const items=getMenuItems(allChildren);const isDisabled=numEnabledOptions===0||disabled;const{someResults}=labels;React.useEffect(()=>{if(open){handleAnnouncement(someResults(items.length));}},[items.length,someResults,open]);return jsx(Id,{id:dropdownId,children:uniqueDropdownId=>jsx(DropdownCore$1,{id:uniqueDropdownId,role:"listbox",selectionType:"single",alignment:alignment,autoFocus:autoFocus,enableTypeAhead:enableTypeAhead,dropdownStyle:[isFilterable&&filterableDropdownStyle,selectDropdownStyle,dropdownStyle],initialFocusedIndex:selectedIndex.current,items:items,onOpenChanged:handleOpenChanged,open:open,opener:renderOpener(isDisabled,uniqueDropdownId),openerElement:openerElement,style:style,className:className,isFilterable:isFilterable,onSearchTextChanged:isFilterable?handleSearchTextChanged:undefined,searchText:isFilterable?searchText:"",labels:labels,"aria-invalid":ariaInvalid,"aria-required":ariaRequired,disabled:isDisabled})})};
2217
65
 
2218
- const _excluded = ["id", "opener", "testId", "alignment", "dropdownStyle", "implicitAllEnabled", "isFilterable", "labels", "onChange", "onToggle", "opened", "selectedValues", "shortcuts", "style", "className", "aria-label", "aria-invalid", "aria-required", "disabled", "error", "children", "dropdownId", "showOpenerLabelAsText", "validate", "onValidate", "required"];
2219
- const MultiSelect = props => {
2220
- const {
2221
- id,
2222
- opener,
2223
- testId,
2224
- alignment = "left",
2225
- dropdownStyle,
2226
- implicitAllEnabled,
2227
- isFilterable,
2228
- labels: propLabels,
2229
- onChange,
2230
- onToggle,
2231
- opened,
2232
- selectedValues = [],
2233
- shortcuts = false,
2234
- style,
2235
- className,
2236
- "aria-label": ariaLabel,
2237
- "aria-invalid": ariaInvalid,
2238
- "aria-required": ariaRequired,
2239
- disabled = false,
2240
- error = false,
2241
- children,
2242
- dropdownId,
2243
- showOpenerLabelAsText = true,
2244
- validate,
2245
- onValidate,
2246
- required
2247
- } = props,
2248
- sharedProps = _objectWithoutPropertiesLoose(props, _excluded);
2249
- const labels = React.useMemo(() => {
2250
- return _extends({}, defaultLabels, propLabels);
2251
- }, [propLabels]);
2252
- const [open, setOpen] = React.useState(false);
2253
- const [searchText, setSearchText] = React.useState("");
2254
- const [lastSelectedValues, setLastSelectedValues] = React.useState([]);
2255
- const [openerElement, setOpenerElement] = React.useState();
2256
- const {
2257
- errorMessage,
2258
- onOpenerBlurValidation,
2259
- onDropdownClosedValidation,
2260
- onSelectionValidation,
2261
- onSelectedValuesChangeValidation
2262
- } = useSelectValidation({
2263
- value: selectedValues,
2264
- disabled,
2265
- validate,
2266
- onValidate,
2267
- required,
2268
- open
2269
- });
2270
- const hasError = error || !!errorMessage;
2271
- React.useEffect(() => {
2272
- if (disabled) {
2273
- setOpen(false);
2274
- } else if (typeof opened === "boolean") {
2275
- setOpen(opened);
2276
- }
2277
- }, [disabled, opened]);
2278
- const handleOpenChanged = opened => {
2279
- setOpen(opened);
2280
- setSearchText("");
2281
- setLastSelectedValues(selectedValues);
2282
- if (onToggle) {
2283
- onToggle(opened);
2284
- }
2285
- if (!opened) {
2286
- if (lastSelectedValues !== selectedValues) {
2287
- onSelectionValidation(selectedValues);
2288
- } else {
2289
- onDropdownClosedValidation();
2290
- }
2291
- }
2292
- };
2293
- const handleToggle = selectedValue => {
2294
- if (selectedValues.includes(selectedValue)) {
2295
- const index = selectedValues.indexOf(selectedValue);
2296
- const updatedSelection = [...selectedValues.slice(0, index), ...selectedValues.slice(index + 1)];
2297
- onChange(updatedSelection);
2298
- } else {
2299
- onChange([...selectedValues, selectedValue]);
2300
- }
2301
- onSelectedValuesChangeValidation();
2302
- };
2303
- const handleSelectAll = () => {
2304
- const allChildren = React.Children.toArray(children);
2305
- const selected = allChildren.filter(option => !!option && !option.props.disabled).map(option => option.props.value);
2306
- onChange(selected);
2307
- onSelectedValuesChangeValidation();
2308
- };
2309
- const handleSelectNone = () => {
2310
- onChange([]);
2311
- onSelectedValuesChangeValidation();
2312
- };
2313
- const getMenuTextOrNode = React.useCallback(children => {
2314
- const {
2315
- noneSelected,
2316
- someSelected,
2317
- allSelected
2318
- } = labels;
2319
- const numSelectedAll = children.filter(option => !option.props.disabled).length;
2320
- const noSelectionText = implicitAllEnabled ? allSelected : noneSelected;
2321
- switch (selectedValues.length) {
2322
- case 0:
2323
- return noSelectionText;
2324
- case 1:
2325
- const selectedItem = children.find(option => option.props.value === selectedValues[0]);
2326
- if (selectedItem) {
2327
- const selectedLabel = getSelectOpenerLabel(showOpenerLabelAsText, selectedItem == null ? void 0 : selectedItem.props);
2328
- if (selectedLabel) {
2329
- return selectedLabel;
2330
- } else {
2331
- return someSelected(1);
2332
- }
2333
- }
2334
- return noSelectionText;
2335
- case numSelectedAll:
2336
- return allSelected;
2337
- default:
2338
- return someSelected(selectedValues.length);
2339
- }
2340
- }, [implicitAllEnabled, labels, selectedValues, showOpenerLabelAsText]);
2341
- const getShortcuts = numOptions => {
2342
- const {
2343
- selectAllLabel,
2344
- selectNoneLabel
2345
- } = labels;
2346
- if (shortcuts && !searchText) {
2347
- const selectAllDisabled = numOptions === selectedValues.length;
2348
- const selectAll = {
2349
- component: React.createElement(ActionItem, {
2350
- disabled: selectAllDisabled,
2351
- label: selectAllLabel(numOptions),
2352
- indent: true,
2353
- onClick: handleSelectAll
2354
- }),
2355
- focusable: !selectAllDisabled,
2356
- populatedProps: {}
2357
- };
2358
- const selectNoneDisabled = selectedValues.length === 0;
2359
- const selectNone = {
2360
- component: React.createElement(ActionItem, {
2361
- disabled: selectNoneDisabled,
2362
- label: selectNoneLabel,
2363
- indent: true,
2364
- onClick: handleSelectNone
2365
- }),
2366
- focusable: !selectNoneDisabled,
2367
- populatedProps: {}
2368
- };
2369
- const separator = {
2370
- component: React.createElement(SeparatorItem, {
2371
- key: "shortcuts-separator"
2372
- }),
2373
- focusable: false,
2374
- populatedProps: {}
2375
- };
2376
- return [selectAll, selectNone, separator];
2377
- } else {
2378
- return [];
2379
- }
2380
- };
2381
- const getMenuItems = children => {
2382
- if (!isFilterable) {
2383
- return children.map(mapOptionItemToDropdownItem);
2384
- }
2385
- const lowercasedSearchText = searchText.toLowerCase();
2386
- const filteredChildren = children.filter(({
2387
- props
2388
- }) => !searchText || getLabel(props).toLowerCase().indexOf(lowercasedSearchText) > -1);
2389
- const lastSelectedChildren = [];
2390
- const restOfTheChildren = [];
2391
- for (const child of filteredChildren) {
2392
- if (lastSelectedValues.includes(child.props.value)) {
2393
- lastSelectedChildren.push(child);
2394
- } else {
2395
- restOfTheChildren.push(child);
2396
- }
2397
- }
2398
- const lastSelectedItems = lastSelectedChildren.map(mapOptionItemToDropdownItem);
2399
- if (lastSelectedChildren.length && restOfTheChildren.length) {
2400
- lastSelectedItems.push({
2401
- component: React.createElement(SeparatorItem, {
2402
- key: "selected-separator"
2403
- }),
2404
- focusable: false,
2405
- populatedProps: {}
2406
- });
2407
- }
2408
- return [...lastSelectedItems, ...restOfTheChildren.map(mapOptionItemToDropdownItem)];
2409
- };
2410
- const mapOptionItemToDropdownItem = option => {
2411
- const {
2412
- disabled,
2413
- value
2414
- } = option.props;
2415
- return {
2416
- component: option,
2417
- focusable: !disabled,
2418
- populatedProps: {
2419
- onToggle: handleToggle,
2420
- selected: selectedValues.includes(value),
2421
- variant: "checkbox"
2422
- }
2423
- };
2424
- };
2425
- const handleOpenerRef = node => {
2426
- const openerElement = ReactDOM.findDOMNode(node);
2427
- setOpenerElement(openerElement);
2428
- };
2429
- const handleSearchTextChanged = searchText => {
2430
- setSearchText(searchText);
2431
- };
2432
- const handleClick = e => {
2433
- handleOpenChanged(!open);
2434
- };
2435
- const handleAnnouncement = message => {
2436
- announceMessage({
2437
- message
2438
- });
2439
- };
2440
- const maybeGetOpenerStringValue = React.useCallback((children, openerContent) => {
2441
- let openerStringValue;
2442
- if (selectedValues.length === 1) {
2443
- const selectedItem = children.find(option => option.props.value === selectedValues[0]);
2444
- openerStringValue = selectedItem ? getLabel(selectedItem == null ? void 0 : selectedItem.props) : undefined;
2445
- } else if (typeof openerContent === "string") {
2446
- openerStringValue = openerContent;
2447
- }
2448
- return openerStringValue;
2449
- }, [selectedValues]);
2450
- React.useEffect(() => {
2451
- const optionItems = React.Children.toArray(children);
2452
- const openerContent = getMenuTextOrNode(optionItems);
2453
- const openerStringValue = maybeGetOpenerStringValue(optionItems, openerContent);
2454
- if (openerStringValue) {
2455
- handleAnnouncement(openerStringValue);
2456
- }
2457
- }, [children, getMenuTextOrNode, maybeGetOpenerStringValue]);
2458
- const renderOpener = (allChildren, isDisabled, dropdownId) => {
2459
- const {
2460
- noneSelected
2461
- } = labels;
2462
- const openerContent = getMenuTextOrNode(allChildren);
2463
- const dropdownOpener = React.createElement(Id, {
2464
- id: id
2465
- }, uniqueOpenerId => {
2466
- return opener ? React.createElement(DropdownOpener, {
2467
- id: uniqueOpenerId,
2468
- error: hasError,
2469
- "aria-label": ariaLabel,
2470
- "aria-controls": dropdownId,
2471
- "aria-haspopup": "listbox",
2472
- onClick: handleClick,
2473
- onBlur: onOpenerBlurValidation,
2474
- disabled: isDisabled,
2475
- ref: handleOpenerRef,
2476
- role: "combobox",
2477
- text: openerContent,
2478
- opened: open
2479
- }, opener) : React.createElement(SelectOpener, _extends({}, sharedProps, {
2480
- error: hasError,
2481
- disabled: isDisabled,
2482
- id: uniqueOpenerId,
2483
- "aria-label": ariaLabel,
2484
- "aria-controls": dropdownId,
2485
- isPlaceholder: openerContent === noneSelected,
2486
- onOpenChanged: handleOpenChanged,
2487
- onBlur: onOpenerBlurValidation,
2488
- open: open,
2489
- ref: handleOpenerRef,
2490
- testId: testId
2491
- }), openerContent);
2492
- });
2493
- return dropdownOpener;
2494
- };
2495
- const {
2496
- clearSearch,
2497
- filter,
2498
- noResults,
2499
- someSelected
2500
- } = labels;
2501
- const allChildren = React.Children.toArray(children).filter(Boolean);
2502
- const numEnabledOptions = allChildren.filter(option => !option.props.disabled).length;
2503
- const filteredItems = getMenuItems(allChildren);
2504
- const isDisabled = numEnabledOptions === 0 || disabled;
2505
- React.useEffect(() => {
2506
- if (open) {
2507
- handleAnnouncement(someSelected(filteredItems.length));
2508
- }
2509
- }, [filteredItems.length, someSelected, open]);
2510
- return React.createElement(Id, {
2511
- id: dropdownId
2512
- }, uniqueDropdownId => React.createElement(DropdownCore$1, {
2513
- id: uniqueDropdownId,
2514
- role: "listbox",
2515
- alignment: alignment,
2516
- dropdownStyle: [isFilterable && filterableDropdownStyle, selectDropdownStyle, dropdownStyle],
2517
- isFilterable: isFilterable,
2518
- items: [...getShortcuts(numEnabledOptions), ...filteredItems],
2519
- onOpenChanged: handleOpenChanged,
2520
- open: open,
2521
- opener: renderOpener(allChildren, isDisabled, uniqueDropdownId),
2522
- openerElement: openerElement,
2523
- selectionType: "multi",
2524
- style: style,
2525
- className: className,
2526
- onSearchTextChanged: isFilterable ? handleSearchTextChanged : undefined,
2527
- searchText: isFilterable ? searchText : "",
2528
- labels: {
2529
- clearSearch,
2530
- filter,
2531
- noResults,
2532
- someResults: someSelected
2533
- },
2534
- "aria-invalid": ariaInvalid,
2535
- "aria-required": ariaRequired,
2536
- disabled: isDisabled
2537
- }));
2538
- };
66
+ const MultiSelect=props=>{const{id,opener,testId,alignment="left",dropdownStyle,implicitAllEnabled,isFilterable,labels:propLabels,onChange,onToggle,opened,selectedValues=[],shortcuts=false,style,className,"aria-label":ariaLabel,"aria-invalid":ariaInvalid,"aria-required":ariaRequired,disabled=false,error=false,children,dropdownId,showOpenerLabelAsText=true,validate,onValidate,required,...sharedProps}=props;const labels=React.useMemo(()=>{return {...defaultLabels,...propLabels}},[propLabels]);const[open,setOpen]=React.useState(false);const[searchText,setSearchText]=React.useState("");const[lastSelectedValues,setLastSelectedValues]=React.useState([]);const[openerElement,setOpenerElement]=React.useState();const{errorMessage,onOpenerBlurValidation,onDropdownClosedValidation,onSelectionValidation,onSelectedValuesChangeValidation}=useSelectValidation({value:selectedValues,disabled,validate,onValidate,required,open});const hasError=error||!!errorMessage;React.useEffect(()=>{if(disabled){setOpen(false);}else if(typeof opened==="boolean"){setOpen(opened);}},[disabled,opened]);const handleOpenChanged=opened=>{setOpen(opened);setSearchText("");setLastSelectedValues(selectedValues);if(onToggle){onToggle(opened);}if(!opened){if(lastSelectedValues!==selectedValues){onSelectionValidation(selectedValues);}else {onDropdownClosedValidation();}}};const handleToggle=selectedValue=>{if(selectedValues.includes(selectedValue)){const index=selectedValues.indexOf(selectedValue);const updatedSelection=[...selectedValues.slice(0,index),...selectedValues.slice(index+1)];onChange(updatedSelection);}else {onChange([...selectedValues,selectedValue]);}onSelectedValuesChangeValidation();};const handleSelectAll=()=>{const allChildren=React.Children.toArray(children);const selected=allChildren.filter(option=>!!option&&!option.props.disabled).map(option=>option.props.value);onChange(selected);onSelectedValuesChangeValidation();};const handleSelectNone=()=>{onChange([]);onSelectedValuesChangeValidation();};const getMenuTextOrNode=React.useCallback(children=>{const{noneSelected,someSelected,allSelected}=labels;const numSelectedAll=children.filter(option=>!option.props.disabled).length;const noSelectionText=implicitAllEnabled?allSelected:noneSelected;switch(selectedValues.length){case 0:return noSelectionText;case 1:const selectedItem=children.find(option=>option.props.value===selectedValues[0]);if(selectedItem){const selectedLabel=getSelectOpenerLabel(showOpenerLabelAsText,selectedItem?.props);if(selectedLabel){return selectedLabel}else {return someSelected(1)}}return noSelectionText;case numSelectedAll:return allSelected;default:return someSelected(selectedValues.length)}},[implicitAllEnabled,labels,selectedValues,showOpenerLabelAsText]);const getShortcuts=numOptions=>{const{selectAllLabel,selectNoneLabel}=labels;if(shortcuts&&!searchText){const selectAllDisabled=numOptions===selectedValues.length;const selectAll={component:jsx(ActionItem,{disabled:selectAllDisabled,label:selectAllLabel(numOptions),indent:true,onClick:handleSelectAll}),focusable:!selectAllDisabled,populatedProps:{}};const selectNoneDisabled=selectedValues.length===0;const selectNone={component:jsx(ActionItem,{disabled:selectNoneDisabled,label:selectNoneLabel,indent:true,onClick:handleSelectNone}),focusable:!selectNoneDisabled,populatedProps:{}};const separator={component:jsx(SeparatorItem,{},"shortcuts-separator"),focusable:false,populatedProps:{}};return [selectAll,selectNone,separator]}else {return []}};const getMenuItems=children=>{if(!isFilterable){return children.map(mapOptionItemToDropdownItem)}const lowercasedSearchText=searchText.toLowerCase();const filteredChildren=children.filter(({props})=>!searchText||getLabel(props).toLowerCase().indexOf(lowercasedSearchText)>-1);const lastSelectedChildren=[];const restOfTheChildren=[];for(const child of filteredChildren){if(lastSelectedValues.includes(child.props.value)){lastSelectedChildren.push(child);}else {restOfTheChildren.push(child);}}const lastSelectedItems=lastSelectedChildren.map(mapOptionItemToDropdownItem);if(lastSelectedChildren.length&&restOfTheChildren.length){lastSelectedItems.push({component:jsx(SeparatorItem,{},"selected-separator"),focusable:false,populatedProps:{}});}return [...lastSelectedItems,...restOfTheChildren.map(mapOptionItemToDropdownItem)]};const mapOptionItemToDropdownItem=option=>{const{disabled,value}=option.props;return {component:option,focusable:!disabled,populatedProps:{onToggle:handleToggle,selected:selectedValues.includes(value),variant:"checkbox"}}};const handleOpenerRef=node=>{const openerElement=ReactDOM.findDOMNode(node);setOpenerElement(openerElement);};const handleSearchTextChanged=searchText=>{setSearchText(searchText);};const handleClick=e=>{handleOpenChanged(!open);};const handleAnnouncement=message=>{announceMessage({message});};const maybeGetOpenerStringValue=React.useCallback((children,openerContent)=>{let openerStringValue;if(selectedValues.length===1){const selectedItem=children.find(option=>option.props.value===selectedValues[0]);openerStringValue=selectedItem?getLabel(selectedItem?.props):undefined;}else if(typeof openerContent==="string"){openerStringValue=openerContent;}return openerStringValue},[selectedValues]);React.useEffect(()=>{const optionItems=React.Children.toArray(children);const openerContent=getMenuTextOrNode(optionItems);const openerStringValue=maybeGetOpenerStringValue(optionItems,openerContent);if(openerStringValue){handleAnnouncement(openerStringValue);}},[children,getMenuTextOrNode,maybeGetOpenerStringValue]);const renderOpener=(allChildren,isDisabled,dropdownId)=>{const{noneSelected}=labels;const openerContent=getMenuTextOrNode(allChildren);const dropdownOpener=jsx(Id,{id:id,children:uniqueOpenerId=>{return opener?jsx(DropdownOpener,{id:uniqueOpenerId,error:hasError,"aria-label":ariaLabel,"aria-controls":dropdownId,"aria-haspopup":"listbox",onClick:handleClick,onBlur:onOpenerBlurValidation,disabled:isDisabled,ref:handleOpenerRef,role:"combobox",text:openerContent,opened:open,children:opener}):jsx(SelectOpener,{...sharedProps,error:hasError,disabled:isDisabled,id:uniqueOpenerId,"aria-label":ariaLabel,"aria-controls":dropdownId,isPlaceholder:openerContent===noneSelected,onOpenChanged:handleOpenChanged,onBlur:onOpenerBlurValidation,open:open,ref:handleOpenerRef,testId:testId,children:openerContent})}});return dropdownOpener};const{clearSearch,filter,noResults,someSelected}=labels;const allChildren=React.Children.toArray(children).filter(Boolean);const numEnabledOptions=allChildren.filter(option=>!option.props.disabled).length;const filteredItems=getMenuItems(allChildren);const isDisabled=numEnabledOptions===0||disabled;React.useEffect(()=>{if(open){handleAnnouncement(someSelected(filteredItems.length));}},[filteredItems.length,someSelected,open]);return jsx(Id,{id:dropdownId,children:uniqueDropdownId=>jsx(DropdownCore$1,{id:uniqueDropdownId,role:"listbox",alignment:alignment,dropdownStyle:[isFilterable&&filterableDropdownStyle,selectDropdownStyle,dropdownStyle],isFilterable:isFilterable,items:[...getShortcuts(numEnabledOptions),...filteredItems],onOpenChanged:handleOpenChanged,open:open,opener:renderOpener(allChildren,isDisabled,uniqueDropdownId),openerElement:openerElement,selectionType:"multi",style:style,className:className,onSearchTextChanged:isFilterable?handleSearchTextChanged:undefined,searchText:isFilterable?searchText:"",labels:{clearSearch,filter,noResults,someResults:someSelected},"aria-invalid":ariaInvalid,"aria-required":ariaRequired,disabled:isDisabled})})};
2539
67
 
2540
- function updateMultipleSelection(previousSelection, value = "") {
2541
- if (!previousSelection) {
2542
- return [value];
2543
- }
2544
- return previousSelection.includes(value) ? previousSelection.filter(item => item !== value) : [...previousSelection, value];
2545
- }
68
+ function updateMultipleSelection(previousSelection,value=""){if(!previousSelection){return [value]}return previousSelection.includes(value)?previousSelection.filter(item=>item!==value):[...previousSelection,value]}
2546
69
 
2547
- function useListbox({
2548
- children: options,
2549
- disabled,
2550
- disableSpaceSelection,
2551
- id,
2552
- onChange,
2553
- selectionType = "single",
2554
- value
2555
- }) {
2556
- const selectedValueIndex = React.useMemo(() => {
2557
- const firstValue = Array.isArray(value) ? value[0] : value;
2558
- if (!firstValue || firstValue === "") {
2559
- return 0;
2560
- }
2561
- return options.findIndex(item => item.props.value === firstValue);
2562
- }, [options, value]);
2563
- const [focusedIndex, setFocusedIndex] = React.useState(selectedValueIndex);
2564
- const [isListboxFocused, setIsListboxFocused] = React.useState(false);
2565
- const [selected, setSelected] = React.useState(value);
2566
- const focusItem = index => {
2567
- setFocusedIndex(index);
2568
- };
2569
- const focusPreviousItem = React.useCallback(() => {
2570
- if (focusedIndex <= 0) {
2571
- focusItem(options.length - 1);
2572
- } else {
2573
- focusItem(focusedIndex - 1);
2574
- }
2575
- }, [options, focusedIndex]);
2576
- const focusNextItem = React.useCallback(() => {
2577
- if (focusedIndex === options.length - 1) {
2578
- focusItem(0);
2579
- } else {
2580
- focusItem(focusedIndex + 1);
2581
- }
2582
- }, [options, focusedIndex]);
2583
- const selectOption = React.useCallback(index => {
2584
- const optionItem = options[index];
2585
- if (optionItem.props.disabled) {
2586
- return;
2587
- }
2588
- if (selectionType === "single") {
2589
- setSelected(optionItem.props.value);
2590
- if (onChange) {
2591
- onChange(optionItem.props.value);
2592
- }
2593
- } else {
2594
- setSelected(prevSelected => {
2595
- const newSelectedValue = updateMultipleSelection(prevSelected, optionItem.props.value);
2596
- if (onChange) {
2597
- onChange(newSelectedValue);
2598
- }
2599
- return newSelectedValue;
2600
- });
2601
- }
2602
- }, [onChange, options, selectionType]);
2603
- const handleKeyDown = React.useCallback(event => {
2604
- const {
2605
- key
2606
- } = event;
2607
- switch (key) {
2608
- case "ArrowUp":
2609
- event.preventDefault();
2610
- focusPreviousItem();
2611
- return;
2612
- case "ArrowDown":
2613
- event.preventDefault();
2614
- focusNextItem();
2615
- return;
2616
- case "Home":
2617
- event.preventDefault();
2618
- focusItem(0);
2619
- return;
2620
- case "End":
2621
- event.preventDefault();
2622
- focusItem(options.length - 1);
2623
- return;
2624
- case "Enter":
2625
- case " ":
2626
- if (focusedIndex < 0 || key === " " && disableSpaceSelection) {
2627
- return;
2628
- }
2629
- event.preventDefault();
2630
- selectOption(focusedIndex);
2631
- return;
2632
- }
2633
- }, [disableSpaceSelection, focusNextItem, focusPreviousItem, focusedIndex, options, selectOption]);
2634
- const handleKeyUp = React.useCallback(event => {
2635
- switch (event.key) {
2636
- case " ":
2637
- event.preventDefault();
2638
- return;
2639
- }
2640
- }, []);
2641
- const handleFocus = React.useCallback(() => {
2642
- if (!disabled) {
2643
- setIsListboxFocused(true);
2644
- }
2645
- }, [disabled]);
2646
- const handleBlur = React.useCallback(() => {
2647
- if (!disabled) {
2648
- setIsListboxFocused(false);
2649
- }
2650
- }, [disabled]);
2651
- const handleClick = React.useCallback(value => {
2652
- const index = options.findIndex(item => item.props.value === value);
2653
- const isOptionDisabled = options[index].props.disabled;
2654
- if (disabled || isOptionDisabled) {
2655
- return;
2656
- }
2657
- focusItem(index);
2658
- selectOption(index);
2659
- }, [disabled, options, selectOption]);
2660
- const renderList = React.useMemo(() => {
2661
- return options.map((component, index) => {
2662
- const isSingleSelection = selectionType === "single" && typeof selected === "string";
2663
- const isSelected = (isSingleSelection ? selected === component.props.value : selected == null ? void 0 : selected.includes(component.props.value)) || false;
2664
- const optionId = id ? `${id}-option-${index}` : `option-${index}`;
2665
- return React.cloneElement(component, {
2666
- key: index,
2667
- focused: isListboxFocused && index === focusedIndex,
2668
- disabled: component.props.disabled || disabled || false,
2669
- selected: isSelected,
2670
- variant: selectionType === "single" ? "check" : "checkbox",
2671
- parentComponent: "listbox",
2672
- id: optionId,
2673
- onToggle: () => {
2674
- handleClick(component.props.value);
2675
- },
2676
- role: "option"
2677
- });
2678
- });
2679
- }, [options, selected, id, isListboxFocused, focusedIndex, disabled, selectionType, handleClick]);
2680
- return {
2681
- isListboxFocused,
2682
- focusedIndex,
2683
- setFocusedIndex,
2684
- renderList,
2685
- setSelected,
2686
- selected,
2687
- handleKeyDown,
2688
- handleKeyUp,
2689
- handleFocus,
2690
- handleBlur
2691
- };
2692
- }
70
+ function useListbox({children:options,disabled,disableSpaceSelection,id,onChange,selectionType="single",value}){const selectedValueIndex=React.useMemo(()=>{const firstValue=Array.isArray(value)?value[0]:value;if(!firstValue||firstValue===""){return 0}return options.findIndex(item=>item.props.value===firstValue)},[options,value]);const[focusedIndex,setFocusedIndex]=React.useState(selectedValueIndex);const[isListboxFocused,setIsListboxFocused]=React.useState(false);const[selected,setSelected]=React.useState(value);const focusItem=index=>{setFocusedIndex(index);};const focusPreviousItem=React.useCallback(()=>{if(focusedIndex<=0){focusItem(options.length-1);}else {focusItem(focusedIndex-1);}},[options,focusedIndex]);const focusNextItem=React.useCallback(()=>{if(focusedIndex===options.length-1){focusItem(0);}else {focusItem(focusedIndex+1);}},[options,focusedIndex]);const selectOption=React.useCallback(index=>{const optionItem=options[index];if(optionItem.props.disabled){return}if(selectionType==="single"){setSelected(optionItem.props.value);if(onChange){onChange(optionItem.props.value);}}else {setSelected(prevSelected=>{const newSelectedValue=updateMultipleSelection(prevSelected,optionItem.props.value);if(onChange){onChange(newSelectedValue);}return newSelectedValue});}},[onChange,options,selectionType]);const handleKeyDown=React.useCallback(event=>{const{key}=event;switch(key){case"ArrowUp":event.preventDefault();focusPreviousItem();return;case"ArrowDown":event.preventDefault();focusNextItem();return;case"Home":event.preventDefault();focusItem(0);return;case"End":event.preventDefault();focusItem(options.length-1);return;case"Enter":case" ":if(focusedIndex<0||key===" "&&disableSpaceSelection){return}event.preventDefault();selectOption(focusedIndex);return}},[disableSpaceSelection,focusNextItem,focusPreviousItem,focusedIndex,options,selectOption]);const handleKeyUp=React.useCallback(event=>{switch(event.key){case" ":event.preventDefault();return}},[]);const handleFocus=React.useCallback(()=>{if(!disabled){setIsListboxFocused(true);}},[disabled]);const handleBlur=React.useCallback(()=>{if(!disabled){setIsListboxFocused(false);}},[disabled]);const handleClick=React.useCallback(value=>{const index=options.findIndex(item=>item.props.value===value);const isOptionDisabled=options[index].props.disabled;if(disabled||isOptionDisabled){return}focusItem(index);selectOption(index);},[disabled,options,selectOption]);const renderList=React.useMemo(()=>{return options.map((component,index)=>{const isSingleSelection=selectionType==="single"&&typeof selected==="string";const isSelected=(isSingleSelection?selected===component.props.value:selected?.includes(component.props.value))||false;const optionId=id?`${id}-option-${index}`:`option-${index}`;return React.cloneElement(component,{key:index,focused:isListboxFocused&&index===focusedIndex,disabled:component.props.disabled||disabled||false,selected:isSelected,variant:selectionType==="single"?"check":"checkbox",parentComponent:"listbox",id:optionId,onToggle:()=>{handleClick(component.props.value);},role:"option"})})},[options,selected,id,isListboxFocused,focusedIndex,disabled,selectionType,handleClick]);return {isListboxFocused,focusedIndex,setFocusedIndex,renderList,setSelected,selected,handleKeyDown,handleKeyUp,handleFocus,handleBlur}}
2693
71
 
2694
- function useMultipleSelection({
2695
- inputValue,
2696
- selected,
2697
- setSelected
2698
- }) {
2699
- const [focusedMultiSelectIndex, setFocusedMultiSelectIndex] = React.useState(-1);
2700
- const handleKeyDown = React.useCallback(event => {
2701
- const {
2702
- key
2703
- } = event;
2704
- if (!Array.isArray(selected) || selected.length === 0) {
2705
- return;
2706
- }
2707
- if (key === "ArrowLeft") {
2708
- setFocusedMultiSelectIndex(prev => {
2709
- const newIndex = prev - 1;
2710
- return newIndex < 0 ? (selected == null ? void 0 : selected.length) - 1 : newIndex;
2711
- });
2712
- }
2713
- if (key === "ArrowRight") {
2714
- setFocusedMultiSelectIndex(prev => {
2715
- const newIndex = prev + 1;
2716
- return newIndex >= (selected == null ? void 0 : selected.length) ? 0 : newIndex;
2717
- });
2718
- }
2719
- if (inputValue === "" && key === "Backspace") {
2720
- let newSelected = [];
2721
- if (focusedMultiSelectIndex < 0) {
2722
- newSelected = selected == null ? void 0 : selected.slice(0, -1);
2723
- } else {
2724
- newSelected = selected.filter((_, index) => index !== focusedMultiSelectIndex);
2725
- }
2726
- setSelected(newSelected);
2727
- setFocusedMultiSelectIndex(-1);
2728
- }
2729
- if (focusedMultiSelectIndex >= 0 && key === "Enter") {
2730
- const newSelected = selected == null ? void 0 : selected.filter((_, index) => index !== focusedMultiSelectIndex);
2731
- setSelected(newSelected);
2732
- setFocusedMultiSelectIndex(-1);
2733
- }
2734
- if (key === "ArrowDown" || key === "ArrowUp") {
2735
- setFocusedMultiSelectIndex(-1);
2736
- }
2737
- if (key === "Escape") {
2738
- setFocusedMultiSelectIndex(-1);
2739
- }
2740
- }, [focusedMultiSelectIndex, inputValue, selected, setSelected]);
2741
- return {
2742
- focusedMultiSelectIndex,
2743
- handleKeyDown
2744
- };
2745
- }
72
+ function useMultipleSelection({inputValue,selected,setSelected}){const[focusedMultiSelectIndex,setFocusedMultiSelectIndex]=React.useState(-1);const handleKeyDown=React.useCallback(event=>{const{key}=event;if(!Array.isArray(selected)||selected.length===0){return}if(key==="ArrowLeft"){setFocusedMultiSelectIndex(prev=>{const newIndex=prev-1;return newIndex<0?selected?.length-1:newIndex});}if(key==="ArrowRight"){setFocusedMultiSelectIndex(prev=>{const newIndex=prev+1;return newIndex>=selected?.length?0:newIndex});}if(inputValue===""&&key==="Backspace"){let newSelected=[];if(focusedMultiSelectIndex<0){newSelected=selected?.slice(0,-1);}else {newSelected=selected.filter((_,index)=>index!==focusedMultiSelectIndex);}setSelected(newSelected);setFocusedMultiSelectIndex(-1);}if(focusedMultiSelectIndex>=0&&key==="Enter"){const newSelected=selected?.filter((_,index)=>index!==focusedMultiSelectIndex);setSelected(newSelected);setFocusedMultiSelectIndex(-1);}if(key==="ArrowDown"||key==="ArrowUp"){setFocusedMultiSelectIndex(-1);}if(key==="Escape"){setFocusedMultiSelectIndex(-1);}},[focusedMultiSelectIndex,inputValue,selected,setSelected]);return {focusedMultiSelectIndex,handleKeyDown}}
2746
73
 
2747
- const StyledSpan = addStyle("span");
2748
- function ComboboxLiveRegion({
2749
- focusedIndex,
2750
- focusedMultiSelectIndex,
2751
- labels = {
2752
- closedState: defaultComboboxLabels.closedState,
2753
- liveRegionCurrentItem: defaultComboboxLabels.liveRegionCurrentItem,
2754
- liveRegionListboxTotal: defaultComboboxLabels.liveRegionListboxTotal,
2755
- liveRegionMultipleSelectionTotal: defaultComboboxLabels.liveRegionMultipleSelectionTotal,
2756
- noItems: defaultComboboxLabels.noItems,
2757
- selected: defaultComboboxLabels.selected,
2758
- selectionCleared: defaultComboboxLabels.selectionCleared,
2759
- unselected: defaultComboboxLabels.unselected
2760
- },
2761
- selectedLabels,
2762
- opened,
2763
- options,
2764
- selected,
2765
- selectionType = "single",
2766
- testId
2767
- }) {
2768
- const lastSelectedValue = React.useRef(null);
2769
- const [message, setMessage] = React.useState("");
2770
- React.useEffect(() => {
2771
- if (selected && selected !== (lastSelectedValue == null ? void 0 : lastSelectedValue.current)) {
2772
- var _lastSelectedValue$cu, _lastSelectedValue$cu2, _selected$length;
2773
- let newMessage = "";
2774
- const lastSelectedLength = (_lastSelectedValue$cu = lastSelectedValue == null || (_lastSelectedValue$cu2 = lastSelectedValue.current) == null ? void 0 : _lastSelectedValue$cu2.length) != null ? _lastSelectedValue$cu : 0;
2775
- const selectedLength = (_selected$length = selected == null ? void 0 : selected.length) != null ? _selected$length : 0;
2776
- if (Array.isArray(selected) && selected.length > 0) {
2777
- const currentLabels = selectedLabels.join(", ");
2778
- const selectedState = selectedLength > lastSelectedLength ? labels.selected(currentLabels) : labels.unselected(currentLabels);
2779
- newMessage = selectedState;
2780
- } else {
2781
- newMessage = labels.selected(selectedLabels[0]);
2782
- }
2783
- setMessage(newMessage);
2784
- }
2785
- if (selectionType === "single" && !selected && lastSelectedValue.current) {
2786
- setMessage(labels.selectionCleared);
2787
- }
2788
- lastSelectedValue.current = selected;
2789
- if (selectionType === "multiple" && !opened) {
2790
- setMessage(labels.closedState);
2791
- }
2792
- }, [labels, labels.closedState, selectedLabels, opened, selected, selectionType]);
2793
- const focusedElementDescription = React.useMemo(() => {
2794
- if (focusedMultiSelectIndex >= 0) {
2795
- const _label = selectedLabels[focusedMultiSelectIndex];
2796
- return labels.liveRegionCurrentItem({
2797
- current: _label,
2798
- focused: true,
2799
- index: focusedMultiSelectIndex,
2800
- total: selectedLabels.length
2801
- }) + " " + labels.liveRegionMultipleSelectionTotal(selectedLabels.length);
2802
- }
2803
- if (options.length === 0) {
2804
- return labels.noItems;
2805
- }
2806
- if (focusedIndex < 0 || !options[focusedIndex]) {
2807
- return "";
2808
- }
2809
- const currentItemProps = options[focusedIndex].props;
2810
- const label = getLabel(currentItemProps);
2811
- const totalResults = options.length;
2812
- return labels.liveRegionCurrentItem({
2813
- current: label,
2814
- disabled: currentItemProps.disabled,
2815
- focused: false,
2816
- index: focusedIndex,
2817
- selected: currentItemProps.selected,
2818
- total: totalResults
2819
- }) + " " + labels.liveRegionListboxTotal(totalResults);
2820
- }, [focusedIndex, focusedMultiSelectIndex, labels, options, selectedLabels]);
2821
- return React.createElement(StyledSpan, {
2822
- role: "log",
2823
- "aria-live": "polite",
2824
- "aria-atomic": "false",
2825
- "aria-relevant": "additions text",
2826
- style: styles$3.srOnly,
2827
- "data-testid": testId ? `${testId}-status` : undefined
2828
- }, opened ? focusedElementDescription : message);
2829
- }
2830
- const styles$3 = StyleSheet.create({
2831
- srOnly: {
2832
- border: 0,
2833
- clip: "rect(0,0,0,0)",
2834
- height: 1,
2835
- margin: -1,
2836
- overflow: "hidden",
2837
- padding: 0,
2838
- position: "absolute",
2839
- width: 1
2840
- }
2841
- });
74
+ const StyledSpan=addStyle("span");function ComboboxLiveRegion({focusedIndex,focusedMultiSelectIndex,labels={closedState:defaultComboboxLabels.closedState,liveRegionCurrentItem:defaultComboboxLabels.liveRegionCurrentItem,liveRegionListboxTotal:defaultComboboxLabels.liveRegionListboxTotal,liveRegionMultipleSelectionTotal:defaultComboboxLabels.liveRegionMultipleSelectionTotal,noItems:defaultComboboxLabels.noItems,selected:defaultComboboxLabels.selected,selectionCleared:defaultComboboxLabels.selectionCleared,unselected:defaultComboboxLabels.unselected},selectedLabels,opened,options,selected,selectionType="single",testId}){const lastSelectedValue=React.useRef(null);const[message,setMessage]=React.useState("");React.useEffect(()=>{if(selected&&selected!==lastSelectedValue?.current){let newMessage="";const lastSelectedLength=lastSelectedValue?.current?.length??0;const selectedLength=selected?.length??0;if(Array.isArray(selected)&&selected.length>0){const currentLabels=selectedLabels.join(", ");const selectedState=selectedLength>lastSelectedLength?labels.selected(currentLabels):labels.unselected(currentLabels);newMessage=selectedState;}else {newMessage=labels.selected(selectedLabels[0]);}setMessage(newMessage);}if(selectionType==="single"&&!selected&&lastSelectedValue.current){setMessage(labels.selectionCleared);}lastSelectedValue.current=selected;if(selectionType==="multiple"&&!opened){setMessage(labels.closedState);}},[labels,labels.closedState,selectedLabels,opened,selected,selectionType]);const focusedElementDescription=React.useMemo(()=>{if(focusedMultiSelectIndex>=0){const label=selectedLabels[focusedMultiSelectIndex];return labels.liveRegionCurrentItem({current:label,focused:true,index:focusedMultiSelectIndex,total:selectedLabels.length})+" "+labels.liveRegionMultipleSelectionTotal(selectedLabels.length)}if(options.length===0){return labels.noItems}if(focusedIndex<0||!options[focusedIndex]){return ""}const currentItemProps=options[focusedIndex].props;const label=getLabel(currentItemProps);const totalResults=options.length;return labels.liveRegionCurrentItem({current:label,disabled:currentItemProps.disabled,focused:false,index:focusedIndex,selected:currentItemProps.selected,total:totalResults})+" "+labels.liveRegionListboxTotal(totalResults)},[focusedIndex,focusedMultiSelectIndex,labels,options,selectedLabels]);return jsx(StyledSpan,{role:"log","aria-live":"polite","aria-atomic":"false","aria-relevant":"additions text",style:styles$3.srOnly,"data-testid":testId?`${testId}-status`:undefined,children:opened?focusedElementDescription:message})}const styles$3=StyleSheet.create({srOnly:{border:0,clip:"rect(0,0,0,0)",height:1,margin:-1,overflow:"hidden",padding:0,position:"absolute",width:1}});
2842
75
 
2843
- const MultipleSelection = React.memo(function SelectedPills({
2844
- disabled,
2845
- focusedMultiSelectIndex,
2846
- id,
2847
- labels,
2848
- onRemove,
2849
- removeSelectedLabel,
2850
- selected,
2851
- testId
2852
- }) {
2853
- return React.createElement(View, {
2854
- role: "group",
2855
- style: styles$2.pillsWrapper,
2856
- id: id
2857
- }, selected.map((value, index) => {
2858
- const label = labels[index];
2859
- const focused = index === focusedMultiSelectIndex;
2860
- const uniqueId = id + index;
2861
- return React.createElement(Pill, {
2862
- id: uniqueId,
2863
- key: uniqueId,
2864
- testId: testId ? `${testId}-pill-${index}` : undefined,
2865
- size: "small",
2866
- style: [styles$2.pill, focused && styles$2.pillFocused],
2867
- kind: focused ? "info" : "neutral",
2868
- "aria-label": removeSelectedLabel(label),
2869
- tabIndex: -1,
2870
- onClick: () => onRemove(value)
2871
- }, React.createElement(React.Fragment, null, label, !disabled && React.createElement(PhosphorIcon, {
2872
- icon: xIcon,
2873
- size: "small"
2874
- })));
2875
- }));
2876
- });
2877
- const styles$2 = StyleSheet.create({
2878
- pillsWrapper: {
2879
- flexDirection: "row",
2880
- flexWrap: "wrap"
2881
- },
2882
- pill: {
2883
- fontSize: font.size.small,
2884
- justifyContent: "space-between",
2885
- alignItems: "center",
2886
- marginBlockStart: spacing.xxxSmall_4,
2887
- marginInlineEnd: spacing.xxxSmall_4,
2888
- paddingInlineEnd: spacing.xxxSmall_4
2889
- },
2890
- pillFocused: {
2891
- outline: `1px solid ${semanticColor.focus.outer}`
2892
- }
2893
- });
76
+ const MultipleSelection=React.memo(function SelectedPills({disabled,focusedMultiSelectIndex,id,labels,onRemove,removeSelectedLabel,selected,testId}){return jsx(View,{role:"group",style:styles$2.pillsWrapper,id:id,children:selected.map((value,index)=>{const label=labels[index];const focused=index===focusedMultiSelectIndex;const uniqueId=id+index;return jsx(Pill,{id:uniqueId,testId:testId?`${testId}-pill-${index}`:undefined,size:"small",style:[styles$2.pill,focused&&styles$2.pillFocused],kind:focused?"info":"neutral","aria-label":removeSelectedLabel(label),tabIndex:-1,onClick:()=>onRemove(value),children:jsxs(Fragment,{children:[label,!disabled&&jsx(PhosphorIcon,{icon:xIcon,size:"small"})]})},uniqueId)})})});const styles$2=StyleSheet.create({pillsWrapper:{flexDirection:"row",flexWrap:"wrap"},pill:{fontSize:font.size.small,justifyContent:"space-between",alignItems:"center",marginBlockStart:spacing.xxxSmall_4,marginInlineEnd:spacing.xxxSmall_4,paddingInlineEnd:spacing.xxxSmall_4},pillFocused:{outline:`1px solid ${semanticColor.focus.outer}`}});
2894
77
 
2895
- function StandaloneListbox(props) {
2896
- const {
2897
- children,
2898
- disabled,
2899
- id,
2900
- onChange,
2901
- selectionType = "single",
2902
- style,
2903
- tabIndex = 0,
2904
- testId,
2905
- value,
2906
- "aria-label": ariaLabel,
2907
- "aria-labelledby": ariaLabelledby
2908
- } = props;
2909
- const generatedUniqueId = useId();
2910
- const uniqueId = id != null ? id : generatedUniqueId;
2911
- const {
2912
- focusedIndex,
2913
- isListboxFocused,
2914
- renderList,
2915
- selected,
2916
- handleKeyDown,
2917
- handleKeyUp,
2918
- handleFocus,
2919
- handleBlur
2920
- } = useListbox({
2921
- children,
2922
- disabled,
2923
- id: uniqueId,
2924
- selectionType,
2925
- value
2926
- });
2927
- React.useEffect(() => {
2928
- if (selected && selected !== value) {
2929
- onChange == null || onChange(selected);
2930
- }
2931
- }, [onChange, selected, value]);
2932
- return React.createElement(View, {
2933
- role: "listbox",
2934
- id: uniqueId,
2935
- style: [styles$1.listbox, style, disabled && styles$1.disabled],
2936
- tabIndex: tabIndex,
2937
- testId: testId,
2938
- "aria-disabled": disabled,
2939
- "aria-label": ariaLabel,
2940
- "aria-labelledby": ariaLabelledby,
2941
- "aria-multiselectable": selectionType === "multiple",
2942
- onKeyDown: handleKeyDown,
2943
- onKeyUp: handleKeyUp,
2944
- onFocus: handleFocus,
2945
- onBlur: handleBlur,
2946
- "aria-activedescendant": isListboxFocused ? renderList[focusedIndex].props.id : undefined
2947
- }, renderList);
2948
- }
2949
- function Listbox(props) {
2950
- const {
2951
- children,
2952
- disabled,
2953
- id,
2954
- selectionType = "single",
2955
- style,
2956
- tabIndex = 0,
2957
- testId,
2958
- "aria-label": ariaLabel,
2959
- "aria-labelledby": ariaLabelledby
2960
- } = props;
2961
- if (tabIndex === 0) {
2962
- return React.createElement(StandaloneListbox, props);
2963
- }
2964
- return React.createElement(View, {
2965
- role: "listbox",
2966
- id: id,
2967
- style: [styles$1.listbox, style, disabled && styles$1.disabled],
2968
- tabIndex: tabIndex,
2969
- testId: testId,
2970
- "aria-disabled": disabled,
2971
- "aria-label": ariaLabel,
2972
- "aria-labelledby": ariaLabelledby,
2973
- "aria-multiselectable": selectionType === "multiple"
2974
- }, children);
2975
- }
2976
- const theme$1 = {
2977
- listbox: {
2978
- color: {
2979
- disabled: {
2980
- foreground: semanticColor.action.secondary.disabled.foreground
2981
- }
2982
- }
2983
- }
2984
- };
2985
- const styles$1 = StyleSheet.create({
2986
- listbox: {
2987
- outline: "none"
2988
- },
2989
- disabled: {
2990
- color: theme$1.listbox.color.disabled.foreground
2991
- }
2992
- });
78
+ function StandaloneListbox(props){const{children,disabled,id,onChange,selectionType="single",style,tabIndex=0,testId,value,"aria-label":ariaLabel,"aria-labelledby":ariaLabelledby}=props;const generatedUniqueId=useId();const uniqueId=id??generatedUniqueId;const{focusedIndex,isListboxFocused,renderList,selected,handleKeyDown,handleKeyUp,handleFocus,handleBlur}=useListbox({children,disabled,id:uniqueId,selectionType,value});React.useEffect(()=>{if(selected&&selected!==value){onChange?.(selected);}},[onChange,selected,value]);return jsx(View,{role:"listbox",id:uniqueId,style:[styles$1.listbox,style,disabled&&styles$1.disabled],tabIndex:tabIndex,testId:testId,"aria-disabled":disabled,"aria-label":ariaLabel,"aria-labelledby":ariaLabelledby,"aria-multiselectable":selectionType==="multiple",onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,onFocus:handleFocus,onBlur:handleBlur,"aria-activedescendant":isListboxFocused?renderList[focusedIndex].props.id:undefined,children:renderList})}function Listbox(props){const{children,disabled,id,selectionType="single",style,tabIndex=0,testId,"aria-label":ariaLabel,"aria-labelledby":ariaLabelledby}=props;if(tabIndex===0){return jsx(StandaloneListbox,{...props})}return jsx(View,{role:"listbox",id:id,style:[styles$1.listbox,style,disabled&&styles$1.disabled],tabIndex:tabIndex,testId:testId,"aria-disabled":disabled,"aria-label":ariaLabel,"aria-labelledby":ariaLabelledby,"aria-multiselectable":selectionType==="multiple",children:children})}const theme$1={listbox:{color:{disabled:{foreground:semanticColor.action.secondary.disabled.foreground}}}};const styles$1=StyleSheet.create({listbox:{outline:"none"},disabled:{color:theme$1.listbox.color.disabled.foreground}});
2993
79
 
2994
- function Combobox({
2995
- autoComplete,
2996
- children,
2997
- disabled,
2998
- error,
2999
- id,
3000
- labels = defaultComboboxLabels,
3001
- onChange,
3002
- onToggle,
3003
- opened,
3004
- placeholder,
3005
- selectionType = "single",
3006
- startIcon,
3007
- testId,
3008
- value = ""
3009
- }) {
3010
- var _renderList$find, _renderList$focusedIn;
3011
- const generatedUniqueId = useId();
3012
- const uniqueId = id != null ? id : generatedUniqueId;
3013
- const comboboxRef = React.useRef(null);
3014
- const rootNodeRef = React.useRef(null);
3015
- const [open, setOpen] = React.useState(opened != null ? opened : false);
3016
- const isControlled = opened !== undefined;
3017
- const openState = disabled ? false : isControlled ? opened : open;
3018
- const [selectedValue, setSelectedValue] = React.useState(value);
3019
- const isValueControlled = value !== "" && onChange !== undefined;
3020
- const valueState = isValueControlled ? value : selectedValue;
3021
- const [currentOptions, setCurrentOptions] = React.useState(children);
3022
- const {
3023
- focusedIndex,
3024
- isListboxFocused,
3025
- setFocusedIndex,
3026
- handleKeyDown,
3027
- handleFocus,
3028
- handleBlur,
3029
- selected,
3030
- setSelected,
3031
- renderList
3032
- } = useListbox({
3033
- children: currentOptions,
3034
- disabled,
3035
- id: uniqueId,
3036
- onChange: value => handleChange(value),
3037
- value: valueState,
3038
- disableSpaceSelection: true,
3039
- selectionType
3040
- });
3041
- const itemFromSelected = (_renderList$find = renderList.find(item => item.props.value === selected)) == null ? void 0 : _renderList$find.props;
3042
- const labelFromSelected = itemFromSelected ? getLabel(itemFromSelected) : "";
3043
- const initialValue = typeof value === "string" ? labelFromSelected : "";
3044
- const [inputValue, setInputValue] = React.useState(initialValue);
3045
- const {
3046
- focusedMultiSelectIndex,
3047
- handleKeyDown: handleMultipleSelectionKeyDown
3048
- } = useMultipleSelection({
3049
- inputValue,
3050
- selected,
3051
- setSelected
3052
- });
3053
- const updateOpenState = React.useCallback((newState, selectedLabel = labelFromSelected) => {
3054
- if (disabled || newState === openState) {
3055
- return;
3056
- }
3057
- if (!isControlled) {
3058
- setOpen(newState);
3059
- }
3060
- if (!newState) {
3061
- setFocusedIndex(-1);
3062
- if (selectionType === "multiple") {
3063
- setInputValue("");
3064
- } else {
3065
- setInputValue(selectedLabel != null ? selectedLabel : "");
3066
- }
3067
- setCurrentOptions(children);
3068
- }
3069
- onToggle == null || onToggle(newState);
3070
- }, [children, disabled, isControlled, labelFromSelected, onToggle, openState, selectionType, setFocusedIndex]);
3071
- const handleChange = React.useCallback(value => {
3072
- if (value !== valueState) {
3073
- setSelectedValue(value);
3074
- onChange == null || onChange(value);
3075
- }
3076
- if (selectionType === "single" && typeof value === "string") {
3077
- var _renderList$find2;
3078
- const itemFromSelected = (_renderList$find2 = renderList.find(item => item.props.value === value)) == null ? void 0 : _renderList$find2.props;
3079
- const labelFromSelected = itemFromSelected ? getLabel(itemFromSelected) : "";
3080
- updateOpenState(false, labelFromSelected);
3081
- } else if (Array.isArray(value)) {
3082
- setInputValue("");
3083
- setCurrentOptions(children);
3084
- }
3085
- }, [children, onChange, renderList, selectionType, updateOpenState, valueState]);
3086
- const focusOnFilteredItem = React.useCallback((filtered, value) => {
3087
- const lowercasedSearchText = value.normalize("NFC").toLowerCase();
3088
- const itemIndex = filtered.findIndex(item => getLabel(item.props).normalize("NFC").toLowerCase().trim().includes(lowercasedSearchText));
3089
- setFocusedIndex(itemIndex);
3090
- }, [setFocusedIndex]);
3091
- const filterItems = React.useCallback(value => {
3092
- const lowercasedSearchText = value.normalize("NFC").toLowerCase();
3093
- return children.filter(item => getLabel(item.props).normalize("NFC").trim().toLowerCase().indexOf(lowercasedSearchText) > -1);
3094
- }, [children]);
3095
- const onKeyDown = event => {
3096
- const {
3097
- key
3098
- } = event;
3099
- const conditionsToOpen = key === "ArrowDown" || key === "ArrowUp" || key === "Backspace" || key.length === 1;
3100
- if (!openState && conditionsToOpen) {
3101
- updateOpenState(true);
3102
- }
3103
- if (key === "ArrowLeft" || key === "ArrowRight") {
3104
- setFocusedIndex(-1);
3105
- }
3106
- handleMultipleSelectionKeyDown(event);
3107
- if (key === "Escape" && openState) {
3108
- event.stopPropagation();
3109
- updateOpenState(false);
3110
- }
3111
- handleKeyDown(event);
3112
- };
3113
- const handleOnRemove = React.useCallback(value => {
3114
- const selectedValues = selected;
3115
- const newValues = selectedValues.filter(selectedValue => selectedValue !== value);
3116
- setSelected(newValues);
3117
- }, [selected, setSelected]);
3118
- const handleTextFieldChange = React.useCallback(value => {
3119
- setInputValue(value);
3120
- let filteredItems = renderList;
3121
- if (autoComplete === "list") {
3122
- filteredItems = filterItems(value);
3123
- setCurrentOptions(filteredItems);
3124
- }
3125
- focusOnFilteredItem(filteredItems, value);
3126
- }, [autoComplete, filterItems, focusOnFilteredItem, renderList]);
3127
- const handleClearClick = React.useCallback(e => {
3128
- var _comboboxRef$current;
3129
- e.stopPropagation();
3130
- setInputValue("");
3131
- setSelected("");
3132
- onChange == null || onChange("");
3133
- (_comboboxRef$current = comboboxRef.current) == null || _comboboxRef$current.focus();
3134
- }, [onChange, setSelected]);
3135
- React.useEffect(() => {
3136
- if (openState) {
3137
- var _comboboxRef$current2;
3138
- (_comboboxRef$current2 = comboboxRef.current) == null || _comboboxRef$current2.focus();
3139
- }
3140
- }, [openState]);
3141
- const selectedLabels = React.useMemo(() => {
3142
- if (Array.isArray(selected)) {
3143
- return selected.map(value => {
3144
- const item = children.find(item => item.props.value === value);
3145
- return item ? getLabel(item == null ? void 0 : item.props) : "";
3146
- });
3147
- }
3148
- return [labelFromSelected];
3149
- }, [children, labelFromSelected, selected]);
3150
- const maybeRenderStartIcon = () => {
3151
- var _startIcon$props$colo;
3152
- if (!startIcon) {
3153
- return null;
3154
- }
3155
- const startIconElement = React.cloneElement(startIcon, _extends({
3156
- size: "small"
3157
- }, startIcon.props, {
3158
- color: disabled ? semanticColor.icon.disabled : (_startIcon$props$colo = startIcon.props.color) != null ? _startIcon$props$colo : semanticColor.icon.primary
3159
- }));
3160
- return React.createElement(View, {
3161
- style: styles.iconWrapper
3162
- }, startIconElement);
3163
- };
3164
- const pillIdPrefix = `${uniqueId}-pill-`;
3165
- const textFieldId = useId();
3166
- const currentActiveDescendant = !openState ? undefined : focusedIndex >= 0 ? (_renderList$focusedIn = renderList[focusedIndex]) == null || (_renderList$focusedIn = _renderList$focusedIn.props) == null ? void 0 : _renderList$focusedIn.id : pillIdPrefix + focusedMultiSelectIndex;
3167
- const controlledWidget = !openState ? undefined : focusedIndex >= 0 ? uniqueId : pillIdPrefix;
3168
- return React.createElement(React.Fragment, null, React.createElement(View, {
3169
- onClick: () => {
3170
- updateOpenState(true);
3171
- },
3172
- ref: rootNodeRef,
3173
- style: [styles.wrapper, isListboxFocused && styles.focused, disabled && styles.disabled, !disabled && error && styles.error]
3174
- }, React.createElement(ComboboxLiveRegion, {
3175
- focusedIndex: focusedIndex,
3176
- focusedMultiSelectIndex: focusedMultiSelectIndex,
3177
- labels: labels,
3178
- options: renderList,
3179
- selectedLabels: selectedLabels,
3180
- testId: testId,
3181
- opened: openState,
3182
- selected: selected,
3183
- selectionType: selectionType
3184
- }), selectionType === "multiple" && Array.isArray(selected) && React.createElement(MultipleSelection, {
3185
- labels: selectedLabels,
3186
- focusedMultiSelectIndex: focusedMultiSelectIndex,
3187
- id: pillIdPrefix,
3188
- selected: selected,
3189
- onRemove: handleOnRemove,
3190
- disabled: disabled,
3191
- testId: testId,
3192
- removeSelectedLabel: labels.removeSelected
3193
- }), maybeRenderStartIcon(), React.createElement(TextField, {
3194
- id: textFieldId,
3195
- testId: testId,
3196
- style: styles.combobox,
3197
- value: inputValue,
3198
- onChange: handleTextFieldChange,
3199
- disabled: disabled,
3200
- onFocus: () => {
3201
- updateOpenState(true);
3202
- handleFocus();
3203
- },
3204
- placeholder: placeholder,
3205
- onBlur: () => {
3206
- updateOpenState(false);
3207
- handleBlur();
3208
- },
3209
- onKeyDown: onKeyDown,
3210
- "aria-activedescendant": currentActiveDescendant,
3211
- "aria-autocomplete": autoComplete,
3212
- "aria-controls": controlledWidget,
3213
- "aria-expanded": openState,
3214
- "aria-invalid": !!error,
3215
- ref: comboboxRef,
3216
- autoComplete: "off",
3217
- role: "combobox"
3218
- }), inputValue && !disabled && React.createElement(IconButton, {
3219
- icon: xIcon,
3220
- onClick: handleClearClick,
3221
- actionType: "neutral",
3222
- kind: "tertiary",
3223
- size: "small",
3224
- style: [styles.button, styles.clearButton],
3225
- "aria-label": labels.clearSelection,
3226
- testId: testId ? `${testId}-clear` : undefined
3227
- }), React.createElement(IconButton, {
3228
- disabled: disabled,
3229
- icon: caretDownIcon$1,
3230
- onClick: e => {
3231
- e.stopPropagation();
3232
- updateOpenState(!openState);
3233
- },
3234
- onMouseDown: e => {
3235
- e.preventDefault();
3236
- },
3237
- actionType: "neutral",
3238
- kind: "tertiary",
3239
- size: "small",
3240
- style: [styles.button, openState && styles.buttonOpen],
3241
- tabIndex: -1,
3242
- "aria-controls": uniqueId,
3243
- "aria-expanded": openState,
3244
- "aria-label": labels.comboboxButton
3245
- })), openState && React.createElement(DropdownPopper, {
3246
- alignment: "left",
3247
- referenceElement: rootNodeRef == null ? void 0 : rootNodeRef.current
3248
- }, isReferenceHidden => {
3249
- var _rootNodeRef$current, _rootNodeRef$current2;
3250
- return React.createElement(React.Fragment, null, renderList.length === 0 ? React.createElement(DetailCell, {
3251
- title: labels.noItems,
3252
- style: [styles.listbox, {
3253
- minWidth: rootNodeRef == null || (_rootNodeRef$current = rootNodeRef.current) == null ? void 0 : _rootNodeRef$current.offsetWidth
3254
- }],
3255
- horizontalRule: "none"
3256
- }) : React.createElement(Listbox, {
3257
- id: uniqueId,
3258
- tabIndex: -1,
3259
- selectionType: selectionType,
3260
- style: [styles.listbox, isReferenceHidden && styles.hidden, {
3261
- minWidth: rootNodeRef == null || (_rootNodeRef$current2 = rootNodeRef.current) == null ? void 0 : _rootNodeRef$current2.offsetWidth
3262
- }],
3263
- testId: testId ? `${testId}-listbox` : undefined,
3264
- "aria-label": labels.listbox,
3265
- "aria-labelledby": textFieldId
3266
- }, renderList));
3267
- }));
3268
- }
3269
- const theme = {
3270
- combobox: {
3271
- color: {
3272
- default: {
3273
- border: semanticColor.border.strong,
3274
- background: semanticColor.surface.primary
3275
- },
3276
- focus: {
3277
- border: semanticColor.focus.outer,
3278
- background: semanticColor.surface.primary
3279
- },
3280
- disabled: {
3281
- border: semanticColor.action.secondary.disabled.border,
3282
- background: semanticColor.action.secondary.disabled.background,
3283
- foreground: semanticColor.action.secondary.disabled.foreground
3284
- },
3285
- error: {
3286
- border: semanticColor.status.critical.foreground,
3287
- background: semanticColor.status.critical.background,
3288
- foreground: semanticColor.text.primary
3289
- }
3290
- }
3291
- },
3292
- listbox: {
3293
- color: {
3294
- default: {
3295
- background: semanticColor.surface.primary,
3296
- border: semanticColor.border.primary
3297
- }
3298
- }
3299
- }
3300
- };
3301
- const styles = StyleSheet.create({
3302
- wrapper: {
3303
- flexDirection: "row",
3304
- alignItems: "center",
3305
- width: "100%",
3306
- maxWidth: "100%",
3307
- flexWrap: "wrap",
3308
- background: theme.combobox.color.default.background,
3309
- borderRadius: border.radius.radius_040,
3310
- border: `solid 1px ${theme.combobox.color.default.border}`,
3311
- paddingInline: spacing.xSmall_8
3312
- },
3313
- focused: {
3314
- background: theme.combobox.color.focus.background,
3315
- border: `1px solid ${theme.combobox.color.focus.border}`
3316
- },
3317
- disabled: {
3318
- background: theme.combobox.color.disabled.background,
3319
- border: `1px solid ${theme.combobox.color.disabled.border}`,
3320
- color: theme.combobox.color.disabled.foreground
3321
- },
3322
- error: {
3323
- background: theme.combobox.color.error.background,
3324
- border: `1px solid ${theme.combobox.color.error.border}`,
3325
- color: theme.combobox.color.error.foreground
3326
- },
3327
- combobox: {
3328
- appearance: "none",
3329
- background: "none",
3330
- border: "none",
3331
- outline: "none",
3332
- padding: 0,
3333
- minWidth: spacing.xxxSmall_4,
3334
- width: "auto",
3335
- display: "inline-grid",
3336
- gridArea: "1 / 2",
3337
- ":focus-visible": {
3338
- outline: "none",
3339
- border: "none"
3340
- }
3341
- },
3342
- listbox: {
3343
- backgroundColor: theme.listbox.color.default.background,
3344
- borderRadius: border.radius.radius_040,
3345
- border: `solid ${border.width.thin} ${theme.listbox.color.default.border}`,
3346
- boxShadow: `0px ${spacing.xSmall_8}px ${spacing.xSmall_8}px 0px ${color.offBlack8}`,
3347
- maxHeight: "var(--popper-max-height)",
3348
- overflowY: "auto"
3349
- },
3350
- hidden: {
3351
- pointerEvents: "none",
3352
- visibility: "hidden"
3353
- },
3354
- button: {
3355
- position: "absolute",
3356
- right: spacing.xxxSmall_4,
3357
- top: spacing.xxxSmall_4,
3358
- margin: 0
3359
- },
3360
- buttonOpen: {
3361
- transform: "rotate(180deg)"
3362
- },
3363
- clearButton: {
3364
- right: spacing.xLarge_32 + spacing.xSmall_8
3365
- },
3366
- iconWrapper: {
3367
- padding: spacing.xxxSmall_4,
3368
- minWidth: "auto"
3369
- }
3370
- });
80
+ function Combobox({autoComplete,children,disabled,error,id,labels=defaultComboboxLabels,onChange,onToggle,opened,placeholder,selectionType="single",startIcon,testId,value=""}){const generatedUniqueId=useId();const uniqueId=id??generatedUniqueId;const comboboxRef=React.useRef(null);const rootNodeRef=React.useRef(null);const[open,setOpen]=React.useState(opened??false);const isControlled=opened!==undefined;const openState=disabled?false:isControlled?opened:open;const[selectedValue,setSelectedValue]=React.useState(value);const isValueControlled=value!==""&&onChange!==undefined;const valueState=isValueControlled?value:selectedValue;const[currentOptions,setCurrentOptions]=React.useState(children);const{focusedIndex,isListboxFocused,setFocusedIndex,handleKeyDown,handleFocus,handleBlur,selected,setSelected,renderList}=useListbox({children:currentOptions,disabled,id:uniqueId,onChange:value=>handleChange(value),value:valueState,disableSpaceSelection:true,selectionType});const itemFromSelected=renderList.find(item=>item.props.value===selected)?.props;const labelFromSelected=itemFromSelected?getLabel(itemFromSelected):"";const initialValue=typeof value==="string"?labelFromSelected:"";const[inputValue,setInputValue]=React.useState(initialValue);const{focusedMultiSelectIndex,handleKeyDown:handleMultipleSelectionKeyDown}=useMultipleSelection({inputValue,selected,setSelected});const updateOpenState=React.useCallback((newState,selectedLabel=labelFromSelected)=>{if(disabled||newState===openState){return}if(!isControlled){setOpen(newState);}if(!newState){setFocusedIndex(-1);if(selectionType==="multiple"){setInputValue("");}else {setInputValue(selectedLabel??"");}setCurrentOptions(children);}onToggle?.(newState);},[children,disabled,isControlled,labelFromSelected,onToggle,openState,selectionType,setFocusedIndex]);const handleChange=React.useCallback(value=>{if(value!==valueState){setSelectedValue(value);onChange?.(value);}if(selectionType==="single"&&typeof value==="string"){const itemFromSelected=renderList.find(item=>item.props.value===value)?.props;const labelFromSelected=itemFromSelected?getLabel(itemFromSelected):"";updateOpenState(false,labelFromSelected);}else if(Array.isArray(value)){setInputValue("");setCurrentOptions(children);}},[children,onChange,renderList,selectionType,updateOpenState,valueState]);const focusOnFilteredItem=React.useCallback((filtered,value)=>{const lowercasedSearchText=value.normalize("NFC").toLowerCase();const itemIndex=filtered.findIndex(item=>getLabel(item.props).normalize("NFC").toLowerCase().trim().includes(lowercasedSearchText));setFocusedIndex(itemIndex);},[setFocusedIndex]);const filterItems=React.useCallback(value=>{const lowercasedSearchText=value.normalize("NFC").toLowerCase();return children.filter(item=>getLabel(item.props).normalize("NFC").trim().toLowerCase().indexOf(lowercasedSearchText)>-1)},[children]);const onKeyDown=event=>{const{key}=event;const conditionsToOpen=key==="ArrowDown"||key==="ArrowUp"||key==="Backspace"||key.length===1;if(!openState&&conditionsToOpen){updateOpenState(true);}if(key==="ArrowLeft"||key==="ArrowRight"){setFocusedIndex(-1);}handleMultipleSelectionKeyDown(event);if(key==="Escape"&&openState){event.stopPropagation();updateOpenState(false);}handleKeyDown(event);};const handleOnRemove=React.useCallback(value=>{const selectedValues=selected;const newValues=selectedValues.filter(selectedValue=>selectedValue!==value);setSelected(newValues);},[selected,setSelected]);const handleTextFieldChange=React.useCallback(value=>{setInputValue(value);let filteredItems=renderList;if(autoComplete==="list"){filteredItems=filterItems(value);setCurrentOptions(filteredItems);}focusOnFilteredItem(filteredItems,value);},[autoComplete,filterItems,focusOnFilteredItem,renderList]);const handleClearClick=React.useCallback(e=>{e.stopPropagation();setInputValue("");setSelected("");onChange?.("");comboboxRef.current?.focus();},[onChange,setSelected]);React.useEffect(()=>{if(openState){comboboxRef.current?.focus();}},[openState]);const selectedLabels=React.useMemo(()=>{if(Array.isArray(selected)){return selected.map(value=>{const item=children.find(item=>item.props.value===value);return item?getLabel(item?.props):""})}return [labelFromSelected]},[children,labelFromSelected,selected]);const maybeRenderStartIcon=()=>{if(!startIcon){return null}const startIconElement=React.cloneElement(startIcon,{size:"small",...startIcon.props,color:disabled?semanticColor.icon.disabled:startIcon.props.color??semanticColor.icon.primary});return jsx(View,{style:styles.iconWrapper,children:startIconElement})};const pillIdPrefix=`${uniqueId}-pill-`;const textFieldId=useId();const currentActiveDescendant=!openState?undefined:focusedIndex>=0?renderList[focusedIndex]?.props?.id:pillIdPrefix+focusedMultiSelectIndex;const controlledWidget=!openState?undefined:focusedIndex>=0?uniqueId:pillIdPrefix;return jsxs(Fragment,{children:[jsxs(View,{onClick:()=>{updateOpenState(true);},ref:rootNodeRef,style:[styles.wrapper,isListboxFocused&&styles.focused,disabled&&styles.disabled,!disabled&&error&&styles.error],children:[jsx(ComboboxLiveRegion,{focusedIndex:focusedIndex,focusedMultiSelectIndex:focusedMultiSelectIndex,labels:labels,options:renderList,selectedLabels:selectedLabels,testId:testId,opened:openState,selected:selected,selectionType:selectionType}),selectionType==="multiple"&&Array.isArray(selected)&&jsx(MultipleSelection,{labels:selectedLabels,focusedMultiSelectIndex:focusedMultiSelectIndex,id:pillIdPrefix,selected:selected,onRemove:handleOnRemove,disabled:disabled,testId:testId,removeSelectedLabel:labels.removeSelected}),maybeRenderStartIcon(),jsx(TextField,{id:textFieldId,testId:testId,style:styles.combobox,value:inputValue,onChange:handleTextFieldChange,disabled:disabled,onFocus:()=>{updateOpenState(true);handleFocus();},placeholder:placeholder,onBlur:()=>{updateOpenState(false);handleBlur();},onKeyDown:onKeyDown,"aria-activedescendant":currentActiveDescendant,"aria-autocomplete":autoComplete,"aria-controls":controlledWidget,"aria-expanded":openState,"aria-invalid":!!error,ref:comboboxRef,autoComplete:"off",role:"combobox"}),inputValue&&!disabled&&jsx(IconButton,{icon:xIcon,onClick:handleClearClick,actionType:"neutral",kind:"tertiary",size:"small",style:[styles.button,styles.clearButton],"aria-label":labels.clearSelection,testId:testId?`${testId}-clear`:undefined}),jsx(IconButton,{disabled:disabled,icon:caretDownIcon$1,onClick:e=>{e.stopPropagation();updateOpenState(!openState);},onMouseDown:e=>{e.preventDefault();},actionType:"neutral",kind:"tertiary",size:"small",style:[styles.button,openState&&styles.buttonOpen],tabIndex:-1,"aria-controls":uniqueId,"aria-expanded":openState,"aria-label":labels.comboboxButton})]}),openState&&jsx(DropdownPopper,{alignment:"left",referenceElement:rootNodeRef?.current,children:isReferenceHidden=>jsx(Fragment,{children:renderList.length===0?jsx(DetailCell,{title:labels.noItems,style:[styles.listbox,{minWidth:rootNodeRef?.current?.offsetWidth}],horizontalRule:"none"}):jsx(Listbox,{id:uniqueId,tabIndex:-1,selectionType:selectionType,style:[styles.listbox,isReferenceHidden&&styles.hidden,{minWidth:rootNodeRef?.current?.offsetWidth}],testId:testId?`${testId}-listbox`:undefined,"aria-label":labels.listbox,"aria-labelledby":textFieldId,children:renderList})})})]})}const theme={combobox:{color:{default:{border:semanticColor.border.strong,background:semanticColor.surface.primary},focus:{border:semanticColor.focus.outer,background:semanticColor.surface.primary},disabled:{border:semanticColor.action.secondary.disabled.border,background:semanticColor.action.secondary.disabled.background,foreground:semanticColor.action.secondary.disabled.foreground},error:{border:semanticColor.status.critical.foreground,background:semanticColor.status.critical.background,foreground:semanticColor.text.primary}}},listbox:{color:{default:{background:semanticColor.surface.primary,border:semanticColor.border.primary}}}};const styles=StyleSheet.create({wrapper:{flexDirection:"row",alignItems:"center",width:"100%",maxWidth:"100%",flexWrap:"wrap",background:theme.combobox.color.default.background,borderRadius:border.radius.radius_040,border:`solid 1px ${theme.combobox.color.default.border}`,paddingInline:spacing.xSmall_8},focused:{background:theme.combobox.color.focus.background,border:`1px solid ${theme.combobox.color.focus.border}`},disabled:{background:theme.combobox.color.disabled.background,border:`1px solid ${theme.combobox.color.disabled.border}`,color:theme.combobox.color.disabled.foreground},error:{background:theme.combobox.color.error.background,border:`1px solid ${theme.combobox.color.error.border}`,color:theme.combobox.color.error.foreground},combobox:{appearance:"none",background:"none",border:"none",outline:"none",padding:0,minWidth:spacing.xxxSmall_4,width:"auto",display:"inline-grid",gridArea:"1 / 2",":focus-visible":{outline:"none",border:"none"}},listbox:{backgroundColor:theme.listbox.color.default.background,borderRadius:border.radius.radius_040,border:`solid ${border.width.thin} ${theme.listbox.color.default.border}`,boxShadow:`0px ${spacing.xSmall_8}px ${spacing.xSmall_8}px 0px ${color.offBlack8}`,maxHeight:"var(--popper-max-height)",overflowY:"auto"},hidden:{pointerEvents:"none",visibility:"hidden"},button:{position:"absolute",right:spacing.xxxSmall_4,top:spacing.xxxSmall_4,margin:0},buttonOpen:{transform:"rotate(180deg)"},clearButton:{right:spacing.xLarge_32+spacing.xSmall_8},iconWrapper:{padding:spacing.xxxSmall_4,minWidth:"auto"}});
3371
81
 
3372
82
  export { ActionItem, ActionMenu, Combobox, Listbox, MultiSelect, OptionItem, SeparatorItem, SingleSelect };