@digital-realty/ix-select 1.1.3 → 1.1.4

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/IxSelect.js CHANGED
@@ -1,236 +1,244 @@
1
- var _a;
2
- import { __decorate } from "tslib";
3
- import '@digital-realty/ix-icon/ix-icon.js';
4
- import { requestUpdateOnAriaChange } from '@material/web/internal/aria/delegate.js';
5
- import { DEFAULT_TYPEAHEAD_BUFFER_TIME } from '@material/web/menu/internal/menu.js';
6
- import '@material/web/select/filled-select.js';
7
- import '@material/web/select/outlined-select.js';
8
- import { LitElement, html, isServer, nothing } from 'lit';
9
- import { property, query, state } from 'lit/decorators.js';
10
- import { ifDefined } from 'lit/directives/if-defined.js';
11
- import { literal, html as staticHtml } from 'lit/static-html.js';
12
- import './selectoption/ix-select-option.js';
13
- const VALUE = Symbol('value');
14
- export class IxSelect extends LitElement {
15
- constructor() {
16
- super(...arguments);
17
- this.minWidth = 0;
18
- /**
19
- * Whether or not the drop-down menu should be at least the width of the select element.
20
- */
21
- this.wideMenu = false;
22
- /**
23
- * The switch between filled and outlined.
24
- */
25
- this.filled = false;
26
- /**
27
- * The floating label for the field.
28
- */
29
- this.label = '';
30
- /**
31
- * Opens the menu synchronously with no animation.
32
- */
33
- this.quick = false;
34
- /**
35
- * Whether or not the select is required.
36
- */
37
- this.required = false;
38
- /**
39
- * Disables the select.
40
- */
41
- this.disabled = false;
42
- /**
43
- * The error message that replaces supporting text when `error` is true. If
44
- * `errorText` is an empty string, then the supporting text will continue to
45
- * show.
46
- *
47
- * This error message overrides the error message displayed by
48
- * `reportValidity()`.
49
- */
50
- this.errorText = '';
51
- /**
52
- * Conveys additional information below the select, such as how it should
53
- * be used.
54
- */
55
- this.supportingText = '';
56
- /**
57
- * Gets or sets whether or not the select is in a visually invalid state.
58
- *
59
- * This error state overrides the error state controlled by
60
- * `reportValidity()`.
61
- */
62
- this.error = false;
63
- /**
64
- * Text to display in the field. Only set for SSR.
65
- */
66
- this.displayText = '';
67
- /**
68
- * Name of icon. It is always a string.
69
- */
70
- this.leadingIcon = '';
71
- /**
72
- * Name of icon. It is always a string.
73
- */
74
- this.trailingIcon = '';
75
- /**
76
- * Whether or not the underlying md-menu should be position: fixed to display
77
- * in a top-level manner, or position: absolute.
78
- *
79
- * position:fixed is useful for cases where select is inside of another
80
- * element with stacking context and hidden overflows such as `md-dialog`.
81
- */
82
- this.menuPositioning = 'absolute';
83
- /**
84
- * The max time between the keystrokes of the typeahead select / menu behavior
85
- * before it clears the typeahead buffer.
86
- */
87
- this.typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
88
- /**
89
- * The index of the currently selected option.
90
- *
91
- * Note: For SSR, set `[selected]` on the requested option and `displayText`
92
- * rather than setting `selectedIndex` setting `selectedIndex` will incur a
93
- * DOM query.
94
- */
95
- this.selectedIndex = -1;
96
- this.nativeError = false;
97
- this.nativeErrorText = '';
98
- this.internals = this /* needed for closure */
99
- .attachInternals();
100
- this.customValidationMessage = '';
101
- this[_a] = '';
102
- this.handleResize = () => {
103
- this.minWidth = 0;
104
- };
105
- }
106
- get hasError() {
107
- return this.error || this.nativeError;
108
- }
109
- get form() {
110
- return this.internals.form;
111
- }
112
- get labels() {
113
- return this.internals.labels;
114
- }
115
- get name() {
116
- var _b;
117
- return (_b = this.getAttribute('name')) !== null && _b !== void 0 ? _b : '';
118
- }
119
- set name(name) {
120
- this.setAttribute('name', name);
121
- }
122
- get validity() {
123
- this.syncValidity();
124
- return this.internals.validity;
125
- }
126
- get value() {
127
- this[VALUE] = this.component.value;
128
- return this[VALUE];
129
- }
130
- set value(value) {
131
- if (isServer)
132
- return;
133
- this.component.value = value;
134
- }
135
- get validationMessage() {
136
- this.syncValidity();
137
- return this.internals.validationMessage;
138
- }
139
- handleSelection() {
140
- this.internals.setFormValue(this.component.value);
141
- this.syncValidity();
142
- }
143
- setMenuWidth() {
144
- if (this.wideMenu) {
145
- this.minWidth = this.component.offsetWidth;
146
- }
147
- }
148
- async getUpdateComplete() {
149
- await super.getUpdateComplete();
150
- await this.component.updateComplete;
151
- this.setMenuWidth();
152
- this.internals.setFormValue(this.component.value);
153
- return true;
154
- }
155
- async updated(changed) {
156
- if (changed.has('required')) {
157
- this.syncValidity();
158
- }
159
- await this.getUpdateComplete();
160
- }
161
- getErrorText() {
162
- return this.error ? this.errorText : this.nativeErrorText;
163
- }
164
- async syncValidity() {
165
- const valueMissing = this.required && !this.component.value;
166
- const customError = !!this.customValidationMessage;
167
- const validationMessage = this.customValidationMessage ||
168
- (valueMissing && this.getRequiredValidationMessage()) ||
169
- '';
170
- this.internals.setValidity({ valueMissing, customError }, validationMessage, this.component);
171
- }
172
- // Returns the platform `<select>` validation message for i18n.
173
- // eslint-disable-next-line class-methods-use-this
174
- getRequiredValidationMessage() {
175
- const select = document.createElement('select');
176
- select.required = true;
177
- return select.validationMessage;
178
- }
179
- checkValidity() {
180
- this.syncValidity();
181
- return this.internals.checkValidity();
182
- }
183
- reportValidity() {
184
- return this.component.reportValidity();
185
- }
186
- setCustomValidity(error) {
187
- this.customValidationMessage = error;
188
- this.syncValidity();
189
- }
190
- focus() {
191
- var _b, _c;
192
- (_c = (_b = this.component.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.field')) === null || _c === void 0 ? void 0 : _c.focus();
193
- }
194
- // eslint-disable-next-line class-methods-use-this
195
- onBlur(e) {
196
- // Prevent blur event from bubbling on focus in (when focus switches to options menu)
197
- const el = e.relatedTarget;
198
- if ((el === null || el === void 0 ? void 0 : el.tagName) === 'IX-SELECT-OPTION') {
199
- e.stopPropagation();
200
- }
201
- }
202
- /**
203
- * Reset the select to its default value.
204
- */
205
- reset() {
206
- this.component.reset();
207
- this.internals.setFormValue(this.component.value);
208
- }
209
- /** @private */
210
- formResetCallback() {
211
- this.reset();
212
- }
213
- /** @private */
214
- formStateRestoreCallback(newState) {
215
- this.value = newState;
216
- }
217
- connectedCallback() {
218
- super.connectedCallback();
219
- if (!isServer && this.wideMenu) {
220
- window.addEventListener('resize', this.handleResize);
221
- }
222
- }
223
- disconnectedCallback() {
224
- super.disconnectedCallback();
225
- if (!isServer && this.wideMenu) {
226
- window.removeEventListener('resize', this.handleResize);
227
- }
228
- }
229
- render() {
230
- const tag = this.filled
231
- ? literal `md-filled-select`
232
- : literal `md-outlined-select`;
233
- const ariaLabel = this.label || this.ariaLabel;
1
+ var _a;
2
+ import { __decorate } from "tslib";
3
+ import '@digital-realty/ix-icon/ix-icon.js';
4
+ import { requestUpdateOnAriaChange } from '@material/web/internal/aria/delegate.js';
5
+ import { DEFAULT_TYPEAHEAD_BUFFER_TIME } from '@material/web/menu/internal/menu.js';
6
+ import '@material/web/select/filled-select.js';
7
+ import '@material/web/select/outlined-select.js';
8
+ import { LitElement, html, isServer, nothing } from 'lit';
9
+ import { property, query, state } from 'lit/decorators.js';
10
+ import { ifDefined } from 'lit/directives/if-defined.js';
11
+ import { literal, html as staticHtml } from 'lit/static-html.js';
12
+ import './selectoption/ix-select-option.js';
13
+ const VALUE = Symbol('value');
14
+ export class IxSelect extends LitElement {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.minWidth = 0;
18
+ /**
19
+ * Whether or not the drop-down menu should be at least the width of the select element.
20
+ */
21
+ this.wideMenu = false;
22
+ /**
23
+ * The switch between filled and outlined.
24
+ */
25
+ this.filled = false;
26
+ /**
27
+ * The floating label for the field.
28
+ */
29
+ this.label = '';
30
+ /**
31
+ * Opens the menu synchronously with no animation.
32
+ */
33
+ this.quick = false;
34
+ /**
35
+ * Whether or not the select is required.
36
+ */
37
+ this.required = false;
38
+ /**
39
+ * Disables the select.
40
+ */
41
+ this.disabled = false;
42
+ /**
43
+ * The error message that replaces supporting text when `error` is true. If
44
+ * `errorText` is an empty string, then the supporting text will continue to
45
+ * show.
46
+ *
47
+ * This error message overrides the error message displayed by
48
+ * `reportValidity()`.
49
+ */
50
+ this.errorText = '';
51
+ /**
52
+ * Conveys additional information below the select, such as how it should
53
+ * be used.
54
+ */
55
+ this.supportingText = '';
56
+ /**
57
+ * Gets or sets whether or not the select is in a visually invalid state.
58
+ *
59
+ * This error state overrides the error state controlled by
60
+ * `reportValidity()`.
61
+ */
62
+ this.error = false;
63
+ /**
64
+ * Text to display in the field. Only set for SSR.
65
+ */
66
+ this.displayText = '';
67
+ /**
68
+ * Name of icon. It is always a string.
69
+ */
70
+ this.leadingIcon = '';
71
+ /**
72
+ * Name of icon. It is always a string.
73
+ */
74
+ this.trailingIcon = '';
75
+ /**
76
+ * Whether or not the underlying md-menu should be position: fixed to display
77
+ * in a top-level manner, or position: absolute.
78
+ *
79
+ * position:fixed is useful for cases where select is inside of another
80
+ * element with stacking context and hidden overflows such as `md-dialog`.
81
+ */
82
+ this.menuPositioning = 'absolute';
83
+ /**
84
+ * The max time between the keystrokes of the typeahead select / menu behavior
85
+ * before it clears the typeahead buffer.
86
+ */
87
+ this.typeaheadDelay = DEFAULT_TYPEAHEAD_BUFFER_TIME;
88
+ /**
89
+ * The index of the currently selected option.
90
+ *
91
+ * Note: For SSR, set `[selected]` on the requested option and `displayText`
92
+ * rather than setting `selectedIndex` setting `selectedIndex` will incur a
93
+ * DOM query.
94
+ */
95
+ this.selectedIndex = -1;
96
+ this.nativeError = false;
97
+ this.nativeErrorText = '';
98
+ this.internals = this /* needed for closure */
99
+ .attachInternals();
100
+ this.customValidationMessage = '';
101
+ this[_a] = '';
102
+ this.handleResize = () => {
103
+ this.minWidth = 0;
104
+ };
105
+ }
106
+ get hasError() {
107
+ return this.error || this.nativeError;
108
+ }
109
+ get form() {
110
+ return this.internals.form;
111
+ }
112
+ get labels() {
113
+ return this.internals.labels;
114
+ }
115
+ get name() {
116
+ var _b;
117
+ return (_b = this.getAttribute('name')) !== null && _b !== void 0 ? _b : '';
118
+ }
119
+ set name(name) {
120
+ this.setAttribute('name', name);
121
+ }
122
+ get validity() {
123
+ this.syncValidity();
124
+ return this.internals.validity;
125
+ }
126
+ get value() {
127
+ this[VALUE] = this.component.value;
128
+ return this[VALUE];
129
+ }
130
+ set value(value) {
131
+ if (isServer)
132
+ return;
133
+ this.component.value = value;
134
+ }
135
+ get validationMessage() {
136
+ this.syncValidity();
137
+ return this.internals.validationMessage;
138
+ }
139
+ handleSelection() {
140
+ this.internals.setFormValue(this.component.value);
141
+ this.syncValidity();
142
+ }
143
+ setMenuSize() {
144
+ var _b, _c, _d, _e;
145
+ const select = (_b = this.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.select');
146
+ const menu = (_e = (_d = (_c = select === null || select === void 0 ? void 0 : select.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('#listbox')) === null || _d === void 0 ? void 0 : _d.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('.menu');
147
+ // Set max-height to 70vh to prevent menus with many options from overflowing the viewport which
148
+ // can cause some options to become inaccessible: https://telxapp.atlassian.net/browse/IXUAT-9459
149
+ if (menu.style) {
150
+ menu.style.maxHeight = `70vh`;
151
+ }
152
+ if (this.wideMenu) {
153
+ this.minWidth = this.component.offsetWidth;
154
+ }
155
+ }
156
+ async getUpdateComplete() {
157
+ await super.getUpdateComplete();
158
+ await this.component.updateComplete;
159
+ this.setMenuSize();
160
+ this.internals.setFormValue(this.component.value);
161
+ return true;
162
+ }
163
+ async updated(changed) {
164
+ if (changed.has('required')) {
165
+ this.syncValidity();
166
+ }
167
+ await this.getUpdateComplete();
168
+ }
169
+ getErrorText() {
170
+ return this.error ? this.errorText : this.nativeErrorText;
171
+ }
172
+ async syncValidity() {
173
+ const valueMissing = this.required && !this.component.value;
174
+ const customError = !!this.customValidationMessage;
175
+ const validationMessage = this.customValidationMessage ||
176
+ (valueMissing && this.getRequiredValidationMessage()) ||
177
+ '';
178
+ this.internals.setValidity({ valueMissing, customError }, validationMessage, this.component);
179
+ }
180
+ // Returns the platform `<select>` validation message for i18n.
181
+ // eslint-disable-next-line class-methods-use-this
182
+ getRequiredValidationMessage() {
183
+ const select = document.createElement('select');
184
+ select.required = true;
185
+ return select.validationMessage;
186
+ }
187
+ checkValidity() {
188
+ this.syncValidity();
189
+ return this.internals.checkValidity();
190
+ }
191
+ reportValidity() {
192
+ return this.component.reportValidity();
193
+ }
194
+ setCustomValidity(error) {
195
+ this.customValidationMessage = error;
196
+ this.syncValidity();
197
+ }
198
+ focus() {
199
+ var _b, _c;
200
+ (_c = (_b = this.component.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.field')) === null || _c === void 0 ? void 0 : _c.focus();
201
+ }
202
+ // eslint-disable-next-line class-methods-use-this
203
+ onBlur(e) {
204
+ // Prevent blur event from bubbling on focus in (when focus switches to options menu)
205
+ const el = e.relatedTarget;
206
+ if ((el === null || el === void 0 ? void 0 : el.tagName) === 'IX-SELECT-OPTION') {
207
+ e.stopPropagation();
208
+ }
209
+ }
210
+ /**
211
+ * Reset the select to its default value.
212
+ */
213
+ reset() {
214
+ this.component.reset();
215
+ this.internals.setFormValue(this.component.value);
216
+ }
217
+ /** @private */
218
+ formResetCallback() {
219
+ this.reset();
220
+ }
221
+ /** @private */
222
+ formStateRestoreCallback(newState) {
223
+ this.value = newState;
224
+ }
225
+ connectedCallback() {
226
+ super.connectedCallback();
227
+ if (!isServer && this.wideMenu) {
228
+ window.addEventListener('resize', this.handleResize);
229
+ }
230
+ }
231
+ disconnectedCallback() {
232
+ super.disconnectedCallback();
233
+ if (!isServer && this.wideMenu) {
234
+ window.removeEventListener('resize', this.handleResize);
235
+ }
236
+ }
237
+ render() {
238
+ const tag = this.filled
239
+ ? literal `md-filled-select`
240
+ : literal `md-outlined-select`;
241
+ const ariaLabel = this.label || this.ariaLabel;
234
242
  return staticHtml `<${tag}
235
243
  ?disabled=${this.disabled}
236
244
  ?quick=${this.quick}
@@ -248,91 +256,91 @@ export class IxSelect extends LitElement {
248
256
  label=${this.label}
249
257
  name=${this.name}
250
258
  @request-selection=${this.handleSelection}
251
- @opening=${this.setMenuWidth}
259
+ @opening=${this.setMenuSize}
252
260
  class="select"
253
261
  style="min-width:${this.minWidth}px"
254
262
  @focus=${this.focus}
255
263
  @blur=${this.onBlur}
256
264
  >
257
265
  <slot></slot>
258
- ${this.leadingIcon
259
- ? html `<ix-icon slot="leading-icon">${this.leadingIcon}</ix-icon>`
266
+ ${this.leadingIcon
267
+ ? html `<ix-icon slot="leading-icon">${this.leadingIcon}</ix-icon>`
260
268
  : nothing}
261
- ${this.trailingIcon
269
+ ${this.trailingIcon
262
270
  ? html `<ix-icon slot="trailing-icon"
263
271
  >${this.trailingIcon}</ix-icon
264
- >`
272
+ >`
265
273
  : nothing}
266
274
  <slot slot="aria-describedby" name="aria-describedby"></slot>
267
- </${tag}>`;
268
- }
269
- }
270
- _a = VALUE;
271
- (() => {
272
- requestUpdateOnAriaChange(IxSelect);
273
- })();
274
- /** @nocollapse */
275
- IxSelect.shadowRootOptions = {
276
- ...LitElement.shadowRootOptions,
277
- delegatesFocus: true,
278
- };
279
- /** @nocollapse */
280
- IxSelect.formAssociated = true;
281
- __decorate([
282
- query('.select')
283
- ], IxSelect.prototype, "component", void 0);
284
- __decorate([
285
- property({ type: Number })
286
- ], IxSelect.prototype, "minWidth", void 0);
287
- __decorate([
288
- property({ type: Boolean, reflect: true, attribute: 'wide-menu' })
289
- ], IxSelect.prototype, "wideMenu", void 0);
290
- __decorate([
291
- property({ type: Boolean, reflect: true })
292
- ], IxSelect.prototype, "filled", void 0);
293
- __decorate([
294
- property()
295
- ], IxSelect.prototype, "label", void 0);
296
- __decorate([
297
- property({ type: Boolean })
298
- ], IxSelect.prototype, "quick", void 0);
299
- __decorate([
300
- property({ type: Boolean })
301
- ], IxSelect.prototype, "required", void 0);
302
- __decorate([
303
- property({ type: Boolean, reflect: true })
304
- ], IxSelect.prototype, "disabled", void 0);
305
- __decorate([
306
- property({ type: String, attribute: 'error-text' })
307
- ], IxSelect.prototype, "errorText", void 0);
308
- __decorate([
309
- property({ type: String, attribute: 'supporting-text' })
310
- ], IxSelect.prototype, "supportingText", void 0);
311
- __decorate([
312
- property({ type: Boolean, reflect: true })
313
- ], IxSelect.prototype, "error", void 0);
314
- __decorate([
315
- property({ type: String, attribute: 'display-text' })
316
- ], IxSelect.prototype, "displayText", void 0);
317
- __decorate([
318
- property({ attribute: 'leading-icon', reflect: true })
319
- ], IxSelect.prototype, "leadingIcon", void 0);
320
- __decorate([
321
- property({ attribute: 'trailing-icon', reflect: true })
322
- ], IxSelect.prototype, "trailingIcon", void 0);
323
- __decorate([
324
- property({ attribute: 'menu-positioning' })
325
- ], IxSelect.prototype, "menuPositioning", void 0);
326
- __decorate([
327
- property({ type: Number, attribute: 'typeahead-delay' })
328
- ], IxSelect.prototype, "typeaheadDelay", void 0);
329
- __decorate([
330
- property({ type: Number, attribute: 'selected-index' })
331
- ], IxSelect.prototype, "selectedIndex", void 0);
332
- __decorate([
333
- state()
334
- ], IxSelect.prototype, "nativeError", void 0);
335
- __decorate([
336
- state()
337
- ], IxSelect.prototype, "nativeErrorText", void 0);
275
+ </${tag}>`;
276
+ }
277
+ }
278
+ _a = VALUE;
279
+ (() => {
280
+ requestUpdateOnAriaChange(IxSelect);
281
+ })();
282
+ /** @nocollapse */
283
+ IxSelect.shadowRootOptions = {
284
+ ...LitElement.shadowRootOptions,
285
+ delegatesFocus: true,
286
+ };
287
+ /** @nocollapse */
288
+ IxSelect.formAssociated = true;
289
+ __decorate([
290
+ query('.select')
291
+ ], IxSelect.prototype, "component", void 0);
292
+ __decorate([
293
+ property({ type: Number })
294
+ ], IxSelect.prototype, "minWidth", void 0);
295
+ __decorate([
296
+ property({ type: Boolean, reflect: true, attribute: 'wide-menu' })
297
+ ], IxSelect.prototype, "wideMenu", void 0);
298
+ __decorate([
299
+ property({ type: Boolean, reflect: true })
300
+ ], IxSelect.prototype, "filled", void 0);
301
+ __decorate([
302
+ property()
303
+ ], IxSelect.prototype, "label", void 0);
304
+ __decorate([
305
+ property({ type: Boolean })
306
+ ], IxSelect.prototype, "quick", void 0);
307
+ __decorate([
308
+ property({ type: Boolean })
309
+ ], IxSelect.prototype, "required", void 0);
310
+ __decorate([
311
+ property({ type: Boolean, reflect: true })
312
+ ], IxSelect.prototype, "disabled", void 0);
313
+ __decorate([
314
+ property({ type: String, attribute: 'error-text' })
315
+ ], IxSelect.prototype, "errorText", void 0);
316
+ __decorate([
317
+ property({ type: String, attribute: 'supporting-text' })
318
+ ], IxSelect.prototype, "supportingText", void 0);
319
+ __decorate([
320
+ property({ type: Boolean, reflect: true })
321
+ ], IxSelect.prototype, "error", void 0);
322
+ __decorate([
323
+ property({ type: String, attribute: 'display-text' })
324
+ ], IxSelect.prototype, "displayText", void 0);
325
+ __decorate([
326
+ property({ attribute: 'leading-icon', reflect: true })
327
+ ], IxSelect.prototype, "leadingIcon", void 0);
328
+ __decorate([
329
+ property({ attribute: 'trailing-icon', reflect: true })
330
+ ], IxSelect.prototype, "trailingIcon", void 0);
331
+ __decorate([
332
+ property({ attribute: 'menu-positioning' })
333
+ ], IxSelect.prototype, "menuPositioning", void 0);
334
+ __decorate([
335
+ property({ type: Number, attribute: 'typeahead-delay' })
336
+ ], IxSelect.prototype, "typeaheadDelay", void 0);
337
+ __decorate([
338
+ property({ type: Number, attribute: 'selected-index' })
339
+ ], IxSelect.prototype, "selectedIndex", void 0);
340
+ __decorate([
341
+ state()
342
+ ], IxSelect.prototype, "nativeError", void 0);
343
+ __decorate([
344
+ state()
345
+ ], IxSelect.prototype, "nativeErrorText", void 0);
338
346
  //# sourceMappingURL=IxSelect.js.map