@instructure/ui-select 11.7.8 → 11.7.9-pr-snapshot-1792147648392

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/es/Select/v1/Group/index.js +16 -44
  3. package/es/Select/v1/Group/props.js +5 -26
  4. package/es/Select/v1/Option/index.js +20 -48
  5. package/es/Select/v1/Option/props.js +10 -26
  6. package/es/Select/v1/index.js +493 -659
  7. package/es/Select/v1/props.js +38 -35
  8. package/es/Select/v1/styles.js +32 -65
  9. package/es/Select/v1/theme.js +17 -49
  10. package/es/Select/v2/Group/index.js +16 -44
  11. package/es/Select/v2/Group/props.js +5 -26
  12. package/es/Select/v2/Option/index.js +20 -48
  13. package/es/Select/v2/Option/props.js +10 -26
  14. package/es/Select/v2/index.js +507 -674
  15. package/es/Select/v2/props.js +39 -35
  16. package/es/Select/v2/styles.js +9 -39
  17. package/es/exports/a.js +1 -25
  18. package/es/exports/b.js +1 -25
  19. package/package.json +21 -27
  20. package/tsconfig.build.json +0 -1
  21. package/tsconfig.build.tsbuildinfo +1 -1
  22. package/lib/Select/v1/Group/index.js +0 -54
  23. package/lib/Select/v1/Group/props.js +0 -31
  24. package/lib/Select/v1/Option/index.js +0 -58
  25. package/lib/Select/v1/Option/props.js +0 -31
  26. package/lib/Select/v1/index.js +0 -701
  27. package/lib/Select/v1/props.js +0 -40
  28. package/lib/Select/v1/styles.js +0 -72
  29. package/lib/Select/v1/theme.js +0 -56
  30. package/lib/Select/v2/Group/index.js +0 -54
  31. package/lib/Select/v2/Group/props.js +0 -31
  32. package/lib/Select/v2/Option/index.js +0 -58
  33. package/lib/Select/v2/Option/props.js +0 -31
  34. package/lib/Select/v2/index.js +0 -716
  35. package/lib/Select/v2/props.js +0 -40
  36. package/lib/Select/v2/styles.js +0 -46
  37. package/lib/exports/a.js +0 -26
  38. package/lib/exports/b.js +0 -26
  39. package/lib/package.json +0 -1
@@ -1,28 +1,5 @@
1
- var _dec, _dec2, _class;
2
- /*
3
- * The MIT License (MIT)
4
- *
5
- * Copyright (c) 2015 - present Instructure, Inc.
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in all
15
- * copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
- * SOFTWARE.
24
- */
25
-
1
+ import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
26
3
  import { Children, Component, memo } from 'react';
27
4
  import * as utils from '@instructure/ui-utils';
28
5
  import { combineDataCid } from '@instructure/ui-utils';
@@ -40,651 +17,508 @@ import generateComponentTheme from './theme.js';
40
17
  import { Group } from './Group/index.js';
41
18
  import { Option } from './Option/index.js';
42
19
  import { allowedProps } from './props.js';
43
- import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
44
- // This memoed Option component is used to prevent unnecessary re-renders of
45
- // Options.Item when the Select component is re-rendered. This is necessary
46
- // because the Select component is re-rendered on every prop change of the <Select.Option>
47
- // and with a large amount of options, this can cause a lot of unnecessary re-renders.
48
- const MemoedOption = /*#__PURE__*/memo(function Opt(props) {
49
- const {
50
- optionsItemProps,
51
- children
52
- } = props;
53
- return (
54
- // The main <Options> that renders this is always an "ul"
55
- _jsx(Options.Item, {
56
- as: "li",
57
- ...optionsItemProps,
58
- children: children
59
- })
60
- );
61
- },
62
- // This is a custom equality function that checks if the props of the
63
- // <Select.Option> have changed. If they haven't, then the Options.Item
64
- // doesn't need to be re-rendered.
65
- (prevProps, nextProps) => {
66
- return prevProps.selectOption.props.isHighlighted === nextProps.selectOption.props.isHighlighted && prevProps.selectOption.props.isSelected === nextProps.selectOption.props.isSelected && prevProps.selectOption.props.isDisabled === nextProps.selectOption.props.isDisabled && prevProps.selectOption.props.children === nextProps.selectOption.props.children && prevProps.selectOption.props.id === nextProps.selectOption.props.id && prevProps.selectOption.props.renderBeforeLabel === nextProps.selectOption.props.renderBeforeLabel && prevProps.selectOption.props.renderAfterLabel === nextProps.selectOption.props.renderAfterLabel && prevProps.children === nextProps.children;
20
+ const MemoedOption = /*#__PURE__*/ memo(function Opt(props) {
21
+ const { optionsItemProps, children } = props;
22
+ return /*#__PURE__*/ _jsx(Options.Item, {
23
+ as: "li",
24
+ ...optionsItemProps,
25
+ children: children
26
+ });
27
+ }, (prevProps, nextProps)=>{
28
+ return prevProps.selectOption.props.isHighlighted === nextProps.selectOption.props.isHighlighted && prevProps.selectOption.props.isSelected === nextProps.selectOption.props.isSelected && prevProps.selectOption.props.isDisabled === nextProps.selectOption.props.isDisabled && prevProps.selectOption.props.children === nextProps.selectOption.props.children && prevProps.selectOption.props.id === nextProps.selectOption.props.id && prevProps.selectOption.props.renderBeforeLabel === nextProps.selectOption.props.renderBeforeLabel && prevProps.selectOption.props.renderAfterLabel === nextProps.selectOption.props.renderAfterLabel && prevProps.children === nextProps.children;
67
29
  });
68
- // This is needed so the propTypes in <Options> check are correct
69
30
  MemoedOption.displayName = 'Item';
70
-
71
- /**
72
- ---
73
- category: components
74
- tags: autocomplete, typeahead, combobox, dropdown, search, form
75
- ---
76
- **/
77
- let Select = (_dec = withDeterministicId(), _dec2 = withStyle(generateStyle, generateComponentTheme), _dec(_class = _dec2(_class = class Select extends Component {
78
- static displayName = 'Select';
79
- static componentId = 'Select';
80
- SCROLL_TOLERANCE = 0.5;
81
- static allowedProps = allowedProps;
82
- static defaultProps = {
83
- inputValue: '',
84
- isShowingOptions: false,
85
- size: 'medium',
86
- // Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
87
- interaction: undefined,
88
- isRequired: false,
89
- isInline: false,
90
- visibleOptionsCount: 8,
91
- placement: 'bottom stretch',
92
- constrain: 'window',
93
- shouldNotWrap: false,
94
- scrollToHighlightedOption: true,
95
- isOptionContentAppliedToInput: false
96
- };
97
- static Option = Option;
98
- static Group = Group;
99
- componentDidMount() {
100
- this.props.makeStyles?.();
101
- }
102
- componentDidUpdate() {
103
- this.props.makeStyles?.();
104
- if (this.props.scrollToHighlightedOption) {
105
- // scroll option into view if needed
106
- requestAnimationFrame(() => this.scrollToOption(this.highlightedOptionId));
107
- }
108
- }
109
- state = {
110
- hasInputRef: false
111
- };
112
- ref = null;
113
- _input = null;
114
- _defaultId = this.props.deterministicId();
115
- _inputContainer = null;
116
- _listView = null;
117
- // temporarily stores actionable options
118
- _optionIds = [];
119
- // best guess for first calculation of list height
120
- _optionHeight = 36;
121
- focus() {
122
- this._input && this._input.focus();
123
- }
124
- blur() {
125
- this._input && this._input.blur();
126
- }
127
- get childrenArray() {
128
- return Children.toArray(this.props.children);
129
- }
130
- getGroupChildrenArray(group) {
131
- return Children.toArray(group.props.children);
132
- }
133
- get focused() {
134
- return this._input ? isActiveElement(this._input) : false;
135
- }
136
- get id() {
137
- return this.props.id || this._defaultId;
138
- }
139
- get width() {
140
- return this._inputContainer ? this._inputContainer.offsetWidth : undefined;
141
- }
142
- get interaction() {
143
- return getInteraction({
144
- props: this.props
145
- });
146
- }
147
- get highlightedOptionId() {
148
- let highlightedOptionId;
149
- this.childrenArray.forEach(child => {
150
- if (matchComponentTypes(child, [Group])) {
151
- // group found
152
- this.getGroupChildrenArray(child).forEach(option => {
153
- // check options in group
154
- if (option.props.isHighlighted) {
155
- highlightedOptionId = option.props.id;
156
- }
157
- });
158
- } else {
159
- // ungrouped option found
160
- if (child.props.isHighlighted) {
161
- highlightedOptionId = child.props.id;
31
+ class Select extends Component {
32
+ static{
33
+ this.displayName = 'Select';
34
+ }
35
+ static{
36
+ this.componentId = 'Select';
37
+ }
38
+ static{
39
+ this.allowedProps = allowedProps;
40
+ }
41
+ static{
42
+ this.defaultProps = {
43
+ inputValue: '',
44
+ isShowingOptions: false,
45
+ size: 'medium',
46
+ interaction: undefined,
47
+ isRequired: false,
48
+ isInline: false,
49
+ visibleOptionsCount: 8,
50
+ placement: 'bottom stretch',
51
+ constrain: 'window',
52
+ shouldNotWrap: false,
53
+ scrollToHighlightedOption: true,
54
+ isOptionContentAppliedToInput: false
55
+ };
56
+ }
57
+ static{
58
+ this.Option = Option;
59
+ }
60
+ static{
61
+ this.Group = Group;
62
+ }
63
+ componentDidMount() {
64
+ this.props.makeStyles?.();
65
+ }
66
+ componentDidUpdate() {
67
+ this.props.makeStyles?.();
68
+ if (this.props.scrollToHighlightedOption) {
69
+ requestAnimationFrame(()=>this.scrollToOption(this.highlightedOptionId));
162
70
  }
163
- }
164
- });
165
- return highlightedOptionId;
166
- }
167
- get selectedOptionId() {
168
- const selectedOptionId = [];
169
- this.childrenArray.forEach(child => {
170
- if (matchComponentTypes(child, [Group])) {
171
- // group found
172
- this.getGroupChildrenArray(child).forEach(option => {
173
- // check options in group
174
- if (option.props.isSelected) {
175
- selectedOptionId.push(option.props.id);
176
- }
71
+ }
72
+ focus() {
73
+ this._input && this._input.focus();
74
+ }
75
+ blur() {
76
+ this._input && this._input.blur();
77
+ }
78
+ get childrenArray() {
79
+ return Children.toArray(this.props.children);
80
+ }
81
+ getGroupChildrenArray(group) {
82
+ return Children.toArray(group.props.children);
83
+ }
84
+ get focused() {
85
+ return this._input ? isActiveElement(this._input) : false;
86
+ }
87
+ get id() {
88
+ return this.props.id || this._defaultId;
89
+ }
90
+ get width() {
91
+ return this._inputContainer ? this._inputContainer.offsetWidth : undefined;
92
+ }
93
+ get interaction() {
94
+ return getInteraction({
95
+ props: this.props
177
96
  });
178
- } else {
179
- // ungrouped option found
180
- if (child.props.isSelected) {
181
- selectedOptionId.push(child.props.id);
97
+ }
98
+ get highlightedOptionId() {
99
+ let highlightedOptionId;
100
+ this.childrenArray.forEach((child)=>{
101
+ if (matchComponentTypes(child, [
102
+ Group
103
+ ])) {
104
+ this.getGroupChildrenArray(child).forEach((option)=>{
105
+ if (option.props.isHighlighted) {
106
+ highlightedOptionId = option.props.id;
107
+ }
108
+ });
109
+ } else {
110
+ if (child.props.isHighlighted) {
111
+ highlightedOptionId = child.props.id;
112
+ }
113
+ }
114
+ });
115
+ return highlightedOptionId;
116
+ }
117
+ get selectedOptionId() {
118
+ const selectedOptionId = [];
119
+ this.childrenArray.forEach((child)=>{
120
+ if (matchComponentTypes(child, [
121
+ Group
122
+ ])) {
123
+ this.getGroupChildrenArray(child).forEach((option)=>{
124
+ if (option.props.isSelected) {
125
+ selectedOptionId.push(option.props.id);
126
+ }
127
+ });
128
+ } else {
129
+ if (child.props.isSelected) {
130
+ selectedOptionId.push(child.props.id);
131
+ }
132
+ }
133
+ });
134
+ if (selectedOptionId.length === 1) {
135
+ return selectedOptionId[0];
182
136
  }
183
- }
184
- });
185
- if (selectedOptionId.length === 1) {
186
- return selectedOptionId[0];
187
- }
188
- if (selectedOptionId.length === 0) {
189
- return undefined;
190
- }
191
- return selectedOptionId;
192
- }
193
- handleInputRef = node => {
194
- // ensures list is positioned with respect to input if list is open on mount
195
- if (!this.state.hasInputRef) {
196
- this.setState({
197
- hasInputRef: true
198
- });
199
- }
200
- this._input = node;
201
- this.props.inputRef?.(node);
202
- };
203
- handleListRef = node => {
204
- this.props.listRef?.(node);
205
-
206
- // store option height to calculate list maxHeight
207
- if (node && node.querySelector('[role="option"]')) {
208
- this._optionHeight = node.querySelector('[role="option"]').offsetHeight;
209
- }
210
- };
211
- handleInputContainerRef = node => {
212
- this._inputContainer = node;
213
- };
214
- scrollToOption(id) {
215
- if (!this._listView || !id) return;
216
- const option = this._listView.querySelector(`[id="${CSS.escape(id)}"]`);
217
- if (!option) return;
218
- const listItem = option.parentNode;
219
- const parentTop = getBoundingClientRect(this._listView).top;
220
- const elemTop = getBoundingClientRect(listItem).top;
221
- const parentBottom = parentTop + this._listView.clientHeight;
222
- const elemBottom = elemTop + (listItem ? listItem.clientHeight : 0);
223
- if (elemBottom > parentBottom) {
224
- this._listView.scrollTop += elemBottom - parentBottom;
225
- } else if (elemTop < parentTop) {
226
- this._listView.scrollTop -= parentTop - elemTop;
227
- }
228
- }
229
- highlightOption(event, id) {
230
- const {
231
- onRequestHighlightOption
232
- } = this.props;
233
- if (id) {
234
- onRequestHighlightOption?.(event, {
235
- id
236
- });
237
- }
238
- }
239
- getEventHandlers() {
240
- const {
241
- isShowingOptions,
242
- onRequestShowOptions,
243
- onRequestHideOptions,
244
- onRequestSelectOption
245
- } = this.props;
246
- return this.interaction === 'enabled' ? {
247
- onRequestShowOptions: event => {
248
- onRequestShowOptions?.(event);
249
- const selectedOptionId = this.selectedOptionId;
250
- if (selectedOptionId && !Array.isArray(selectedOptionId)) {
251
- // highlight selected option on show
252
- this.highlightOption(event, selectedOptionId);
137
+ if (selectedOptionId.length === 0) {
138
+ return undefined;
253
139
  }
254
- },
255
- onRequestHideOptions: event => {
256
- onRequestHideOptions?.(event);
257
- },
258
- onRequestHighlightOption: (event, {
259
- id,
260
- direction
261
- }) => {
262
- if (!isShowingOptions) return;
263
- const highlightedOptionId = this.highlightedOptionId;
264
- // if id exists, use that
265
- let highlightId = this._optionIds.indexOf(id) > -1 ? id : undefined;
266
- if (!highlightId) {
267
- if (!highlightedOptionId) {
268
- // nothing highlighted yet, highlight first option
269
- highlightId = this._optionIds[0];
270
- } else {
271
- // find next id based on direction
272
- const index = this._optionIds.indexOf(highlightedOptionId);
273
- highlightId = index > -1 ? this._optionIds[index + direction] : undefined;
274
- }
140
+ return selectedOptionId;
141
+ }
142
+ scrollToOption(id) {
143
+ if (!this._listView || !id) return;
144
+ const option = this._listView.querySelector(`[id="${CSS.escape(id)}"]`);
145
+ if (!option) return;
146
+ const listItem = option.parentNode;
147
+ const parentTop = getBoundingClientRect(this._listView).top;
148
+ const elemTop = getBoundingClientRect(listItem).top;
149
+ const parentBottom = parentTop + this._listView.clientHeight;
150
+ const elemBottom = elemTop + (listItem ? listItem.clientHeight : 0);
151
+ if (elemBottom > parentBottom) {
152
+ this._listView.scrollTop += elemBottom - parentBottom;
153
+ } else if (elemTop < parentTop) {
154
+ this._listView.scrollTop -= parentTop - elemTop;
275
155
  }
276
- if (highlightId) {
277
- // only highlight if id exists as a valid option
278
- this.highlightOption(event, highlightId);
156
+ }
157
+ highlightOption(event, id) {
158
+ const { onRequestHighlightOption } = this.props;
159
+ if (id) {
160
+ onRequestHighlightOption?.(event, {
161
+ id
162
+ });
279
163
  }
280
- },
281
- onRequestHighlightFirstOption: event => {
282
- this.highlightOption(event, this._optionIds[0]);
283
- },
284
- onRequestHighlightLastOption: event => {
285
- this.highlightOption(event, this._optionIds[this._optionIds.length - 1]);
286
- },
287
- onRequestSelectOption: (event, {
288
- id
289
- }) => {
290
- if (id && this._optionIds.indexOf(id) !== -1) {
291
- // only select if id exists as a valid option
292
- onRequestSelectOption?.(event, {
293
- id
294
- });
164
+ }
165
+ getEventHandlers() {
166
+ const { isShowingOptions, onRequestShowOptions, onRequestHideOptions, onRequestSelectOption } = this.props;
167
+ return this.interaction === 'enabled' ? {
168
+ onRequestShowOptions: (event)=>{
169
+ onRequestShowOptions?.(event);
170
+ const selectedOptionId = this.selectedOptionId;
171
+ if (selectedOptionId && !Array.isArray(selectedOptionId)) {
172
+ this.highlightOption(event, selectedOptionId);
173
+ }
174
+ },
175
+ onRequestHideOptions: (event)=>{
176
+ onRequestHideOptions?.(event);
177
+ },
178
+ onRequestHighlightOption: (event, { id, direction })=>{
179
+ if (!isShowingOptions) return;
180
+ const highlightedOptionId = this.highlightedOptionId;
181
+ let highlightId = this._optionIds.indexOf(id) > -1 ? id : undefined;
182
+ if (!highlightId) {
183
+ if (!highlightedOptionId) {
184
+ highlightId = this._optionIds[0];
185
+ } else {
186
+ const index = this._optionIds.indexOf(highlightedOptionId);
187
+ highlightId = index > -1 ? this._optionIds[index + direction] : undefined;
188
+ }
189
+ }
190
+ if (highlightId) {
191
+ this.highlightOption(event, highlightId);
192
+ }
193
+ },
194
+ onRequestHighlightFirstOption: (event)=>{
195
+ this.highlightOption(event, this._optionIds[0]);
196
+ },
197
+ onRequestHighlightLastOption: (event)=>{
198
+ this.highlightOption(event, this._optionIds[this._optionIds.length - 1]);
199
+ },
200
+ onRequestSelectOption: (event, { id })=>{
201
+ if (id && this._optionIds.indexOf(id) !== -1) {
202
+ onRequestSelectOption?.(event, {
203
+ id
204
+ });
205
+ }
206
+ }
207
+ } : {};
208
+ }
209
+ renderOption(option, data) {
210
+ const { getOptionProps, getDisabledOptionProps } = data;
211
+ const { id, isDisabled, isHighlighted, isSelected, renderBeforeLabel, renderAfterLabel, children } = option.props;
212
+ const getRenderOptionLabel = (renderOptionLabel)=>{
213
+ return typeof renderOptionLabel === 'function' && !renderOptionLabel?.prototype?.isReactComponent ? renderOptionLabel.bind(null, {
214
+ id,
215
+ isDisabled,
216
+ isSelected,
217
+ isHighlighted,
218
+ children
219
+ }) : renderOptionLabel;
220
+ };
221
+ let optionProps = {
222
+ ...omitProps(option.props, [
223
+ ...Option.allowedProps,
224
+ ...Options.Item.allowedProps
225
+ ]),
226
+ ...getOptionProps({
227
+ id
228
+ }),
229
+ renderBeforeLabel: getRenderOptionLabel(renderBeforeLabel),
230
+ renderAfterLabel: getRenderOptionLabel(renderAfterLabel)
231
+ };
232
+ if (isSelected && isHighlighted) {
233
+ optionProps.variant = 'selected-highlighted';
234
+ optionProps.isSelected = true;
235
+ } else if (isSelected) {
236
+ optionProps.variant = 'selected';
237
+ optionProps.isSelected = true;
238
+ } else if (isHighlighted) {
239
+ optionProps.variant = 'highlighted';
295
240
  }
296
- }
297
- } : {};
298
- }
299
- renderOption(option, data) {
300
- const {
301
- getOptionProps,
302
- getDisabledOptionProps
303
- } = data;
304
- const {
305
- id,
306
- isDisabled,
307
- isHighlighted,
308
- isSelected,
309
- renderBeforeLabel,
310
- renderAfterLabel,
311
- children
312
- } = option.props;
313
- const getRenderOptionLabel = renderOptionLabel => {
314
- return typeof renderOptionLabel === 'function' && !renderOptionLabel?.prototype?.isReactComponent ? renderOptionLabel.bind(null, {
315
- id,
316
- isDisabled,
317
- isSelected,
318
- isHighlighted,
319
- children
320
- }) : renderOptionLabel;
321
- };
322
- let optionProps = {
323
- // passthrough props
324
- ...omitProps(option.props, [...Option.allowedProps, ...Options.Item.allowedProps]),
325
- // props from selectable
326
- ...getOptionProps({
327
- id
328
- }),
329
- // Options.Item props
330
- renderBeforeLabel: getRenderOptionLabel(renderBeforeLabel),
331
- renderAfterLabel: getRenderOptionLabel(renderAfterLabel)
332
- };
333
- // should option be treated as highlighted or selected
334
- if (isSelected && isHighlighted) {
335
- optionProps.variant = 'selected-highlighted';
336
- optionProps.isSelected = true;
337
- } else if (isSelected) {
338
- optionProps.variant = 'selected';
339
- optionProps.isSelected = true;
340
- } else if (isHighlighted) {
341
- optionProps.variant = 'highlighted';
342
- }
343
- // should option be treated as disabled
344
- if (isDisabled) {
345
- optionProps.variant = 'disabled';
346
- optionProps = {
347
- ...optionProps,
348
- ...getDisabledOptionProps()
349
- };
350
- } else {
351
- // track as valid option if not disabled
352
- this._optionIds.push(id);
353
- }
354
- return _jsx(MemoedOption, {
355
- optionsItemProps: optionProps,
356
- selectOption: option,
357
- children: children
358
- });
359
- }
360
- renderGroup(group, data) {
361
- const {
362
- getOptionProps,
363
- getDisabledOptionProps,
364
- isFirstChild,
365
- isLastChild,
366
- afterGroup
367
- } = data;
368
- const {
369
- id,
370
- renderLabel,
371
- children,
372
- ...rest
373
- } = group.props;
374
- const groupChildren = [];
375
- // add a separator above
376
- if (!isFirstChild && !afterGroup) {
377
- groupChildren.push(_jsx(Options.Separator, {}));
378
- }
379
- // create a sublist as a group
380
- // a wrapping listitem will be created by Options
381
- groupChildren.push(_jsx(Options, {
382
- id: id,
383
- as: "ul",
384
- role: "group",
385
- renderLabel: renderLabel,
386
- ...omitProps(rest, [...Options.allowedProps, ...Group.allowedProps]),
387
- children: Children.map(children, child => {
388
- return this.renderOption(child, {
389
- getOptionProps,
390
- getDisabledOptionProps
241
+ if (isDisabled) {
242
+ optionProps.variant = 'disabled';
243
+ optionProps = {
244
+ ...optionProps,
245
+ ...getDisabledOptionProps()
246
+ };
247
+ } else {
248
+ this._optionIds.push(id);
249
+ }
250
+ return /*#__PURE__*/ _jsx(MemoedOption, {
251
+ optionsItemProps: optionProps,
252
+ selectOption: option,
253
+ children: children
391
254
  });
392
- })
393
- }));
394
- // add a separator below
395
- if (!isLastChild) {
396
- groupChildren.push(_jsx(Options.Separator, {}));
397
- }
398
- return groupChildren;
399
- }
400
- renderList(data) {
401
- const {
402
- getListProps,
403
- getOptionProps,
404
- getDisabledOptionProps
405
- } = data;
406
- const {
407
- isShowingOptions,
408
- optionsMaxWidth,
409
- optionsMaxHeight,
410
- visibleOptionsCount,
411
- children
412
- } = this.props;
413
- let lastWasGroup = false;
414
- const viewProps = isShowingOptions ? {
415
- display: 'block',
416
- overflowY: 'auto',
417
- maxHeight: optionsMaxHeight || this._optionHeight * visibleOptionsCount - (
418
- // in Chrome, we need to prevent scrolling when the bottom area of last item is hovered
419
- utils.isChromium() ? this.SCROLL_TOLERANCE : 0),
420
- maxWidth: optionsMaxWidth || this.width,
421
- background: 'primary',
422
- elementRef: node => this._listView = node,
423
- borderRadius: 'medium'
424
- } : {
425
- maxHeight: 0
426
- };
427
- return _jsx(View, {
428
- ...viewProps,
429
- children: _jsx(Options, {
430
- ...getListProps({
431
- as: 'ul',
432
- elementRef: this.handleListRef
433
- }),
434
- children: isShowingOptions ? Children.map(children, (child, index) => {
435
- if (!child || !matchComponentTypes(child, [Group, Option])) {
436
- return; // ignore invalid children
437
- }
438
- if (matchComponentTypes(child, [Option])) {
439
- lastWasGroup = false;
440
- return this.renderOption(child, {
441
- getOptionProps,
442
- getDisabledOptionProps
443
- });
444
- }
445
- if (matchComponentTypes(child, [Group])) {
446
- const afterGroup = lastWasGroup;
447
- lastWasGroup = true;
448
- return this.renderGroup(child, {
449
- getOptionProps,
450
- getDisabledOptionProps,
451
- // for rendering separators appropriately
452
- isFirstChild: index === 0,
453
- isLastChild: index === Children.count(children) - 1,
454
- afterGroup
455
- });
456
- }
457
- return;
458
- }) : null
459
- })
460
- });
461
- }
462
- renderIcon() {
463
- const {
464
- styles,
465
- isShowingOptions
466
- } = this.props;
467
- return _jsx("span", {
468
- css: styles?.icon,
469
- children: isShowingOptions ? _jsx(IconArrowOpenUpLine, {
470
- inline: false
471
- }) : _jsx(IconArrowOpenDownLine, {
472
- inline: false
473
- })
474
- });
475
- }
476
- renderContentBeforeOrAfterInput(position) {
477
- for (const child of this.childrenArray) {
478
- if (matchComponentTypes(child, [Group])) {
479
- // Group found
480
- const options = this.getGroupChildrenArray(child);
481
- for (const option of options) {
482
- if (option.props.isSelected) {
483
- return position === 'before' ? option.props.renderBeforeLabel : option.props.renderAfterLabel ? option.props.renderAfterLabel : this.renderIcon();
484
- }
255
+ }
256
+ renderGroup(group, data) {
257
+ const { getOptionProps, getDisabledOptionProps, isFirstChild, isLastChild, afterGroup } = data;
258
+ const { id, renderLabel, children, ...rest } = group.props;
259
+ const groupChildren = [];
260
+ if (!isFirstChild && !afterGroup) {
261
+ groupChildren.push(/*#__PURE__*/ _jsx(Options.Separator, {}));
262
+ }
263
+ groupChildren.push(/*#__PURE__*/ _jsx(Options, {
264
+ id: id,
265
+ as: "ul",
266
+ role: "group",
267
+ renderLabel: renderLabel,
268
+ ...omitProps(rest, [
269
+ ...Options.allowedProps,
270
+ ...Group.allowedProps
271
+ ]),
272
+ children: Children.map(children, (child)=>{
273
+ return this.renderOption(child, {
274
+ getOptionProps,
275
+ getDisabledOptionProps
276
+ });
277
+ })
278
+ }));
279
+ if (!isLastChild) {
280
+ groupChildren.push(/*#__PURE__*/ _jsx(Options.Separator, {}));
281
+ }
282
+ return groupChildren;
283
+ }
284
+ renderList(data) {
285
+ const { getListProps, getOptionProps, getDisabledOptionProps } = data;
286
+ const { isShowingOptions, optionsMaxWidth, optionsMaxHeight, visibleOptionsCount, children } = this.props;
287
+ let lastWasGroup = false;
288
+ const viewProps = isShowingOptions ? {
289
+ display: 'block',
290
+ overflowY: 'auto',
291
+ maxHeight: optionsMaxHeight || this._optionHeight * visibleOptionsCount - (utils.isChromium() ? this.SCROLL_TOLERANCE : 0),
292
+ maxWidth: optionsMaxWidth || this.width,
293
+ background: 'primary',
294
+ elementRef: (node)=>this._listView = node,
295
+ borderRadius: 'medium'
296
+ } : {
297
+ maxHeight: 0
298
+ };
299
+ return /*#__PURE__*/ _jsx(View, {
300
+ ...viewProps,
301
+ children: /*#__PURE__*/ _jsx(Options, {
302
+ ...getListProps({
303
+ as: 'ul',
304
+ elementRef: this.handleListRef
305
+ }),
306
+ children: isShowingOptions ? Children.map(children, (child, index)=>{
307
+ if (!child || !matchComponentTypes(child, [
308
+ Group,
309
+ Option
310
+ ])) {
311
+ return;
312
+ }
313
+ if (matchComponentTypes(child, [
314
+ Option
315
+ ])) {
316
+ lastWasGroup = false;
317
+ return this.renderOption(child, {
318
+ getOptionProps,
319
+ getDisabledOptionProps
320
+ });
321
+ }
322
+ if (matchComponentTypes(child, [
323
+ Group
324
+ ])) {
325
+ const afterGroup = lastWasGroup;
326
+ lastWasGroup = true;
327
+ return this.renderGroup(child, {
328
+ getOptionProps,
329
+ getDisabledOptionProps,
330
+ isFirstChild: index === 0,
331
+ isLastChild: index === Children.count(children) - 1,
332
+ afterGroup
333
+ });
334
+ }
335
+ return;
336
+ }) : null
337
+ })
338
+ });
339
+ }
340
+ renderIcon() {
341
+ const { styles, isShowingOptions } = this.props;
342
+ return /*#__PURE__*/ _jsx("span", {
343
+ css: styles?.icon,
344
+ children: isShowingOptions ? /*#__PURE__*/ _jsx(IconArrowOpenUpLine, {
345
+ inline: false
346
+ }) : /*#__PURE__*/ _jsx(IconArrowOpenDownLine, {
347
+ inline: false
348
+ })
349
+ });
350
+ }
351
+ renderContentBeforeOrAfterInput(position) {
352
+ for (const child of this.childrenArray){
353
+ if (matchComponentTypes(child, [
354
+ Group
355
+ ])) {
356
+ const options = this.getGroupChildrenArray(child);
357
+ for (const option of options){
358
+ if (option.props.isSelected) {
359
+ return position === 'before' ? option.props.renderBeforeLabel : option.props.renderAfterLabel ? option.props.renderAfterLabel : this.renderIcon();
360
+ }
361
+ }
362
+ } else {
363
+ if (child.props.isSelected) {
364
+ return position === 'before' ? child.props.renderBeforeLabel : child.props.renderAfterLabel ? child.props.renderAfterLabel : this.renderIcon();
365
+ }
366
+ }
367
+ }
368
+ if (position === 'after') {
369
+ return this.renderIcon();
370
+ }
371
+ return void 0;
372
+ }
373
+ handleInputContentRender(renderLabelInput, inputValue, isOptionContentAppliedToInput, position, defaultReturn) {
374
+ const isInputValueEmpty = !inputValue || inputValue === '';
375
+ if (renderLabelInput && isOptionContentAppliedToInput) {
376
+ if (!isInputValueEmpty) {
377
+ return this.renderContentBeforeOrAfterInput(position);
378
+ }
379
+ return renderLabelInput;
380
+ }
381
+ if (isOptionContentAppliedToInput) {
382
+ if (isInputValueEmpty) {
383
+ return defaultReturn;
384
+ }
385
+ return this.renderContentBeforeOrAfterInput(position);
485
386
  }
486
- } else {
487
- // Ungrouped option found
488
- if (child.props.isSelected) {
489
- return position === 'before' ? child.props.renderBeforeLabel : child.props.renderAfterLabel ? child.props.renderAfterLabel : this.renderIcon();
387
+ if (renderLabelInput) {
388
+ return renderLabelInput;
490
389
  }
491
- }
492
- }
493
- // if no option with isSelected is found
494
- if (position === 'after') {
495
- return this.renderIcon();
496
- }
497
- return void 0;
498
- }
499
- handleInputContentRender(renderLabelInput, inputValue, isOptionContentAppliedToInput, position, defaultReturn) {
500
- const isInputValueEmpty = !inputValue || inputValue === '';
501
- if (renderLabelInput && isOptionContentAppliedToInput) {
502
- if (!isInputValueEmpty) {
503
- return this.renderContentBeforeOrAfterInput(position);
504
- }
505
- return renderLabelInput;
506
- }
507
- if (isOptionContentAppliedToInput) {
508
- if (isInputValueEmpty) {
509
390
  return defaultReturn;
510
- }
511
- return this.renderContentBeforeOrAfterInput(position);
512
- }
513
- if (renderLabelInput) {
514
- return renderLabelInput;
515
- }
516
- return defaultReturn;
517
- }
518
- handleRenderBeforeInput() {
519
- const {
520
- renderBeforeInput,
521
- inputValue,
522
- isOptionContentAppliedToInput
523
- } = this.props;
524
- return this.handleInputContentRender(renderBeforeInput, inputValue, isOptionContentAppliedToInput, 'before', null // default for before
525
- );
526
- }
527
- handleRenderAfterInput() {
528
- const {
529
- renderAfterInput,
530
- inputValue,
531
- isOptionContentAppliedToInput
532
- } = this.props;
533
- return this.handleInputContentRender(renderAfterInput, inputValue, isOptionContentAppliedToInput, 'after', this.renderIcon() // default for after
534
- );
535
- }
536
- renderInput(data) {
537
- const {
538
- getInputProps,
539
- getTriggerProps
540
- } = data;
541
- const {
542
- renderLabel,
543
- inputValue,
544
- placeholder,
545
- isRequired,
546
- shouldNotWrap,
547
- size,
548
- isInline,
549
- width,
550
- htmlSize,
551
- messages,
552
- renderBeforeInput,
553
- renderAfterInput,
554
- onFocus,
555
- onBlur,
556
- onInputChange,
557
- onRequestHideOptions,
558
- layout,
559
- ...rest
560
- } = this.props;
561
- const {
562
- interaction
563
- } = this;
564
- const passthroughProps = omitProps(rest, Select.allowedProps);
565
- const {
566
- ref,
567
- ...triggerProps
568
- } = getTriggerProps({
569
- ...passthroughProps
570
- });
571
- const isEditable = typeof onInputChange !== 'undefined';
572
- let overrideProps = {};
573
- if (!isEditable) {
574
- overrideProps = {
575
- role: 'combobox',
576
- title: inputValue,
577
- 'aria-autocomplete': undefined
578
- };
579
- }
580
-
581
- // backdoor to autocomplete attr to work around chrome autofill issues
582
- if (passthroughProps['autoComplete']) {
583
- overrideProps.autoComplete = passthroughProps['autoComplete'];
584
- }
585
- const inputProps = {
586
- id: this.id,
587
- renderLabel,
588
- placeholder,
589
- size,
590
- width,
591
- htmlSize,
592
- messages,
593
- value: inputValue,
594
- inputRef: utils.createChainedFunction(ref, this.handleInputRef),
595
- inputContainerRef: this.handleInputContainerRef,
596
- interaction: interaction === 'enabled' && !isEditable ? 'readonly' // prevent keyboard cursor
597
- : interaction,
598
- isRequired,
599
- shouldNotWrap,
600
- layout,
601
- display: isInline ? 'inline-block' : 'block',
602
- renderBeforeInput: this.handleRenderBeforeInput(),
603
- // On iOS VoiceOver, if there is a custom element instead of the changing up and down arrow button
604
- // the listbox closes on a swipe, so a DOM change is enforced by the key change
605
- // that seems to inform VoiceOver to behave the correct way
606
- renderAfterInput: utils.isAndroidOrIOS() && renderAfterInput !== undefined ? _jsx("span", {
607
- children: this.handleRenderAfterInput()
608
- }, this.props.isShowingOptions ? 'open' : 'closed') : this.handleRenderAfterInput(),
609
- // If `inputValue` is provided, we need to pass a default onChange handler,
610
- // because TextInput `value` is a controlled prop,
611
- // and onChange is not required for Select
612
- // (before it was handled by TextInput's defaultProp)
613
- onChange: typeof onInputChange === 'function' ? onInputChange : inputValue ? () => {} : undefined,
614
- onFocus,
615
- onBlur: utils.createChainedFunction(onBlur, onRequestHideOptions),
616
- ...overrideProps
617
- };
618
- // suppressHydrationWarning is needed because `role` depends on the browser type
619
- return _jsx(TextInput, {
620
- ...triggerProps,
621
- ...getInputProps(inputProps),
622
- suppressHydrationWarning: true
623
- });
624
- }
625
- render() {
626
- const {
627
- constrain,
628
- placement,
629
- mountNode,
630
- assistiveText,
631
- isShowingOptions,
632
- styles
633
- } = this.props;
634
- // clear temporary option store
635
- this._optionIds = [];
636
- const highlightedOptionId = this.highlightedOptionId;
637
- const selectedOptionId = this.selectedOptionId;
638
- return _jsx(Selectable, {
639
- highlightedOptionId: highlightedOptionId,
640
- isShowingOptions: isShowingOptions,
641
- selectedOptionId: selectedOptionId,
642
- ...this.getEventHandlers(),
643
- children: ({
644
- getRootProps,
645
- getInputProps,
646
- getTriggerProps,
647
- getListProps,
648
- getOptionProps,
649
- getDisabledOptionProps,
650
- getDescriptionProps
651
- }) => _jsxs("span", {
652
- ...getRootProps({
653
- css: styles?.select
654
- }),
655
- ref: el => {
656
- this.ref = el;
657
- },
658
- "data-cid": combineDataCid('Select', this.props),
659
- children: [this.renderInput({
660
- getInputProps,
661
- getTriggerProps
662
- }), _jsx("span", {
663
- ...getDescriptionProps(),
664
- css: styles?.assistiveText,
665
- children: assistiveText
666
- }), _jsx(Popover, {
667
- constrain: constrain,
668
- placement: placement
669
- // On iOS VoiceOver, the Popover is mounted right after the input
670
- // in order to be able to navigate through the list items with a swipe.
671
- // The swipe would result in closing the listbox if mounted elsewhere.
672
- ,
673
- mountNode: mountNode !== undefined ? mountNode : utils.isAndroidOrIOS() ? this.ref : undefined,
674
- positionTarget: this._inputContainer,
675
- isShowingContent: isShowingOptions,
676
- shouldReturnFocus: false,
677
- withArrow: false,
678
- borderWidth: styles?.popoverBorderWidth,
679
- children: this.renderList({
680
- getListProps,
681
- getOptionProps,
682
- getDisabledOptionProps
683
- })
684
- })]
685
- })
686
- });
687
- }
688
- }) || _class) || _class);
391
+ }
392
+ handleRenderBeforeInput() {
393
+ const { renderBeforeInput, inputValue, isOptionContentAppliedToInput } = this.props;
394
+ return this.handleInputContentRender(renderBeforeInput, inputValue, isOptionContentAppliedToInput, 'before', null);
395
+ }
396
+ handleRenderAfterInput() {
397
+ const { renderAfterInput, inputValue, isOptionContentAppliedToInput } = this.props;
398
+ return this.handleInputContentRender(renderAfterInput, inputValue, isOptionContentAppliedToInput, 'after', this.renderIcon());
399
+ }
400
+ renderInput(data) {
401
+ const { getInputProps, getTriggerProps } = data;
402
+ const { renderLabel, inputValue, placeholder, isRequired, shouldNotWrap, size, isInline, width, htmlSize, messages, renderBeforeInput, renderAfterInput, onFocus, onBlur, onInputChange, onRequestHideOptions, layout, ...rest } = this.props;
403
+ const { interaction } = this;
404
+ const passthroughProps = omitProps(rest, Select.allowedProps);
405
+ const { ref, ...triggerProps } = getTriggerProps({
406
+ ...passthroughProps
407
+ });
408
+ const isEditable = typeof onInputChange !== 'undefined';
409
+ let overrideProps = {};
410
+ if (!isEditable) {
411
+ overrideProps = {
412
+ role: 'combobox',
413
+ title: inputValue,
414
+ 'aria-autocomplete': undefined
415
+ };
416
+ }
417
+ if (passthroughProps['autoComplete']) {
418
+ overrideProps.autoComplete = passthroughProps['autoComplete'];
419
+ }
420
+ const inputProps = {
421
+ id: this.id,
422
+ renderLabel,
423
+ placeholder,
424
+ size,
425
+ width,
426
+ htmlSize,
427
+ messages,
428
+ value: inputValue,
429
+ inputRef: utils.createChainedFunction(ref, this.handleInputRef),
430
+ inputContainerRef: this.handleInputContainerRef,
431
+ interaction: interaction === 'enabled' && !isEditable ? 'readonly' : interaction,
432
+ isRequired,
433
+ shouldNotWrap,
434
+ layout,
435
+ display: isInline ? 'inline-block' : 'block',
436
+ renderBeforeInput: this.handleRenderBeforeInput(),
437
+ renderAfterInput: utils.isAndroidOrIOS() && renderAfterInput !== undefined ? /*#__PURE__*/ _jsx("span", {
438
+ children: this.handleRenderAfterInput()
439
+ }, this.props.isShowingOptions ? 'open' : 'closed') : this.handleRenderAfterInput(),
440
+ onChange: typeof onInputChange === 'function' ? onInputChange : inputValue ? ()=>{} : undefined,
441
+ onFocus,
442
+ onBlur: utils.createChainedFunction(onBlur, onRequestHideOptions),
443
+ ...overrideProps
444
+ };
445
+ return /*#__PURE__*/ _jsx(TextInput, {
446
+ ...triggerProps,
447
+ ...getInputProps(inputProps),
448
+ suppressHydrationWarning: true
449
+ });
450
+ }
451
+ render() {
452
+ const { constrain, placement, mountNode, assistiveText, isShowingOptions, styles } = this.props;
453
+ this._optionIds = [];
454
+ const highlightedOptionId = this.highlightedOptionId;
455
+ const selectedOptionId = this.selectedOptionId;
456
+ return /*#__PURE__*/ _jsx(Selectable, {
457
+ highlightedOptionId: highlightedOptionId,
458
+ isShowingOptions: isShowingOptions,
459
+ selectedOptionId: selectedOptionId,
460
+ ...this.getEventHandlers(),
461
+ children: ({ getRootProps, getInputProps, getTriggerProps, getListProps, getOptionProps, getDisabledOptionProps, getDescriptionProps })=>/*#__PURE__*/ _jsxs("span", {
462
+ ...getRootProps({
463
+ css: styles?.select
464
+ }),
465
+ ref: (el)=>{
466
+ this.ref = el;
467
+ },
468
+ "data-cid": combineDataCid('Select', this.props),
469
+ children: [
470
+ this.renderInput({
471
+ getInputProps,
472
+ getTriggerProps
473
+ }),
474
+ /*#__PURE__*/ _jsx("span", {
475
+ ...getDescriptionProps(),
476
+ css: styles?.assistiveText,
477
+ children: assistiveText
478
+ }),
479
+ /*#__PURE__*/ _jsx(Popover, {
480
+ constrain: constrain,
481
+ placement: placement,
482
+ mountNode: mountNode !== undefined ? mountNode : utils.isAndroidOrIOS() ? this.ref : undefined,
483
+ positionTarget: this._inputContainer,
484
+ isShowingContent: isShowingOptions,
485
+ shouldReturnFocus: false,
486
+ withArrow: false,
487
+ borderWidth: styles?.popoverBorderWidth,
488
+ children: this.renderList({
489
+ getListProps,
490
+ getOptionProps,
491
+ getDisabledOptionProps
492
+ })
493
+ })
494
+ ]
495
+ })
496
+ });
497
+ }
498
+ constructor(...args){
499
+ super(...args), this.SCROLL_TOLERANCE = 0.5, this.state = {
500
+ hasInputRef: false
501
+ }, this.ref = null, this._input = null, this._defaultId = this.props.deterministicId(), this._inputContainer = null, this._listView = null, this._optionIds = [], this._optionHeight = 36, this.handleInputRef = (node)=>{
502
+ if (!this.state.hasInputRef) {
503
+ this.setState({
504
+ hasInputRef: true
505
+ });
506
+ }
507
+ this._input = node;
508
+ this.props.inputRef?.(node);
509
+ }, this.handleListRef = (node)=>{
510
+ this.props.listRef?.(node);
511
+ if (node && node.querySelector('[role="option"]')) {
512
+ this._optionHeight = node.querySelector('[role="option"]').offsetHeight;
513
+ }
514
+ }, this.handleInputContainerRef = (node)=>{
515
+ this._inputContainer = node;
516
+ };
517
+ }
518
+ }
519
+ Select = _ts_decorate([
520
+ withDeterministicId(),
521
+ withStyle(generateStyle, generateComponentTheme)
522
+ ], Select);
689
523
  export default Select;
690
- export { Select };
524
+ export { Select };