@vonage/vivid 3.31.0 → 3.32.0

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 (132) hide show
  1. package/alert/index.js +2 -1
  2. package/checkbox/index.js +2 -1
  3. package/combobox/index.js +2 -1
  4. package/custom-elements.json +748 -11
  5. package/date-picker/index.js +35 -0
  6. package/dialog/index.js +1 -1
  7. package/divider/index.js +1 -1
  8. package/empty-state/index.js +1 -1
  9. package/fab/index.js +1 -1
  10. package/file-picker/index.js +3 -2
  11. package/header/index.js +1 -1
  12. package/index.d.ts +1 -0
  13. package/index.js +48 -46
  14. package/layout/index.js +1 -1
  15. package/lib/button/button.d.ts +2 -0
  16. package/lib/components.d.ts +20 -19
  17. package/lib/date-picker/calendar/calendarGrid.d.ts +17 -0
  18. package/lib/date-picker/calendar/dateStr.d.ts +6 -0
  19. package/lib/date-picker/calendar/month.d.ts +11 -0
  20. package/lib/date-picker/calendar/monthPickerGrid.d.ts +10 -0
  21. package/lib/date-picker/calendar/presentationDate.d.ts +4 -0
  22. package/lib/date-picker/date-picker.d.ts +16 -0
  23. package/lib/date-picker/date-picker.template.d.ts +4 -0
  24. package/lib/date-picker/definition.d.ts +3 -0
  25. package/lib/date-picker/index.d.ts +1 -0
  26. package/lib/date-picker/locale.d.ts +21 -0
  27. package/lib/select/select.d.ts +4 -2
  28. package/listbox/index.js +3 -2
  29. package/locales/en-GB.d.ts +3 -0
  30. package/locales/en-GB.js +25 -0
  31. package/locales/en-US.d.ts +3 -0
  32. package/locales/en-US.js +25 -0
  33. package/locales/ja-JP.d.ts +3 -0
  34. package/locales/ja-JP.js +25 -0
  35. package/locales/zh-CN.d.ts +3 -0
  36. package/locales/zh-CN.js +25 -0
  37. package/menu/index.js +2 -2
  38. package/menu-item/index.js +1 -1
  39. package/nav/index.js +1 -1
  40. package/nav-disclosure/index.js +1 -1
  41. package/nav-item/index.js +1 -1
  42. package/note/index.js +3 -2
  43. package/number-field/index.js +4 -3
  44. package/option/index.js +2 -1
  45. package/package.json +2 -1
  46. package/pagination/index.js +1 -1
  47. package/progress/index.js +1 -1
  48. package/radio/index.js +1 -1
  49. package/radio-group/index.js +1 -1
  50. package/select/index.js +3 -2
  51. package/shared/definition.js +1 -1
  52. package/shared/definition10.js +1 -1
  53. package/shared/definition11.js +1 -1
  54. package/shared/definition12.js +1 -1
  55. package/shared/definition14.js +1 -1
  56. package/shared/definition15.js +1 -1
  57. package/shared/definition16.js +1 -1
  58. package/shared/definition17.js +1 -1
  59. package/shared/definition18.js +2 -2
  60. package/shared/definition19.js +2 -2
  61. package/shared/definition2.js +1 -1
  62. package/shared/definition21.js +3 -3
  63. package/shared/definition22.js +2 -2
  64. package/shared/definition23.js +5750 -189
  65. package/shared/definition24.js +116 -68
  66. package/shared/definition25.js +68 -38
  67. package/shared/definition26.js +222 -74
  68. package/shared/definition27.js +33 -2282
  69. package/shared/definition28.js +76 -47
  70. package/shared/definition29.js +2287 -38
  71. package/shared/definition30.js +39 -417
  72. package/shared/definition31.js +38 -364
  73. package/shared/definition32.js +427 -12
  74. package/shared/definition33.js +350 -59
  75. package/shared/definition34.js +12 -26
  76. package/shared/definition35.js +67 -31
  77. package/shared/definition36.js +20 -431
  78. package/shared/definition37.js +34 -194
  79. package/shared/definition38.js +427 -45
  80. package/shared/definition39.js +195 -33
  81. package/shared/definition4.js +1 -1
  82. package/shared/definition40.js +53 -425
  83. package/shared/definition41.js +29 -645
  84. package/shared/definition42.js +420 -73
  85. package/shared/definition43.js +549 -444
  86. package/shared/definition44.js +68 -90
  87. package/shared/definition45.js +501 -79
  88. package/shared/definition46.js +84 -45
  89. package/shared/definition47.js +131 -17
  90. package/shared/definition48.js +44 -471
  91. package/shared/definition49.js +21 -108
  92. package/shared/definition5.js +1 -1
  93. package/shared/definition50.js +487 -15
  94. package/shared/definition51.js +92 -255
  95. package/shared/definition52.js +16 -115
  96. package/shared/definition53.js +264 -115
  97. package/shared/definition54.js +91 -82
  98. package/shared/definition55.js +111 -65
  99. package/shared/definition56.js +64 -291
  100. package/shared/definition57.js +303 -0
  101. package/shared/definition6.js +2 -2
  102. package/shared/definition7.js +10 -3
  103. package/shared/definition9.js +1 -1
  104. package/shared/{form-elements.js → index2.js} +14 -2
  105. package/shared/localization/Locale.d.ts +4 -0
  106. package/shared/localization/index.d.ts +7 -0
  107. package/shared/patterns/form-elements/form-elements.d.ts +4 -4
  108. package/shared/patterns/index.d.ts +1 -0
  109. package/shared/patterns/localized.d.ts +4 -0
  110. package/shared/text-field.js +1 -1
  111. package/side-drawer/index.js +1 -1
  112. package/slider/index.js +1 -1
  113. package/split-button/index.js +1 -1
  114. package/styles/core/all.css +25 -3
  115. package/styles/core/theme.css +1 -1
  116. package/styles/core/typography.css +25 -3
  117. package/styles/tokens/theme-dark.css +4 -4
  118. package/styles/tokens/theme-light.css +4 -4
  119. package/styles/tokens/vivid-2-compat.css +2 -2
  120. package/switch/index.js +3 -2
  121. package/tab/index.js +1 -1
  122. package/tab-panel/index.js +1 -1
  123. package/tabs/index.js +3 -3
  124. package/tag/index.js +1 -1
  125. package/tag-group/index.js +1 -1
  126. package/text-area/index.js +3 -2
  127. package/text-field/index.js +3 -2
  128. package/toggletip/index.js +1 -1
  129. package/tooltip/index.js +1 -1
  130. package/tree-item/index.js +1 -1
  131. package/tree-view/index.js +1 -1
  132. package/vivid.api.json +137 -0
@@ -1,566 +1,671 @@
1
- import { F as FoundationElement, _ as __decorate, a as attr, o as observable, n as nullableNumberConverter, b as __metadata, h as html, r as registerFactory } from './index.js';
1
+ import { D as DOM, O as Observable, _ as __decorate, a as attr, v as volatile, o as observable, b as __metadata, h as html, r as registerFactory } from './index.js';
2
2
  import { f as focusRegistries } from './definition4.js';
3
- import { D as Direction, g as getDirection } from './direction.js';
4
- import { l as limit$1 } from './numbers.js';
3
+ import { P as Popup, p as popupRegistries } from './definition20.js';
4
+ import { i as iconRegistries } from './definition3.js';
5
+ import { L as ListboxOption, l as listboxOptionRegistries } from './definition21.js';
6
+ import { A as AffixIconWithTrailing, a as affixIconTemplateFactory } from './affix.js';
7
+ import './focus.js';
8
+ import { e as errorText, f as formElements, F as FormElementSuccessText, a as FormElementHelperText, g as getFeedbackTemplate } from './index2.js';
9
+ import { b as ListboxElement, L as Listbox, D as DelegatesARIAListbox, a as Listbox$1 } from './listbox.js';
10
+ import { S as StartEnd } from './start-end.js';
11
+ import { a as applyMixins } from './apply-mixins.js';
5
12
  import { F as FormAssociated } from './form-associated.js';
6
- import { O as Orientation } from './aria.js';
7
- import { a as keyHome, k as keyEnd, b as keyArrowDown, i as keyArrowLeft, c as keyArrowUp, h as keyArrowRight } from './key-codes.js';
13
+ import { S as SelectPosition } from './select.options.js';
14
+ import { u as uniqueId } from './strings.js';
15
+ import { g as keyTab, f as keyEscape, d as keyEnter, k as keyEnd, a as keyHome, e as keySpace, b as keyArrowDown, c as keyArrowUp } from './key-codes.js';
8
16
  import { f as focusTemplateFactory } from './focus2.js';
17
+ import { w as when } from './when.js';
9
18
  import { r as ref } from './ref.js';
10
- import { O as Orientation$1 } from './aria2.js';
19
+ import { s as slotted } from './slotted.js';
11
20
  import { c as classNames } from './class-names.js';
12
21
 
13
- /**
14
- * Converts a pixel coordinate on the track to a percent of the track's range
15
- */
16
- function convertPixelToPercent(pixelPos, minPosition, maxPosition, direction) {
17
- let pct = limit$1(0, 1, (pixelPos - minPosition) / (maxPosition - minPosition));
18
- if (direction === Direction.rtl) {
19
- pct = 1 - pct;
20
- }
21
- return pct;
22
- }
23
-
24
- class _Slider extends FoundationElement {
22
+ class _Select extends ListboxElement {
25
23
  }
26
24
  /**
27
- * A form-associated base class for the {@link @microsoft/fast-foundation#(Slider:class)} component.
25
+ * A form-associated base class for the {@link @microsoft/fast-foundation#(Select:class)} component.
28
26
  *
29
27
  * @internal
30
28
  */
31
- class FormAssociatedSlider extends FormAssociated(_Slider) {
29
+ class FormAssociatedSelect extends FormAssociated(_Select) {
32
30
  constructor() {
33
31
  super(...arguments);
34
- this.proxy = document.createElement("input");
32
+ this.proxy = document.createElement("select");
35
33
  }
36
34
  }
37
35
 
38
36
  /**
39
- * The selection modes of a {@link @microsoft/fast-foundation#(Slider:class)}.
40
- * @public
41
- */
42
- const SliderMode = {
43
- singleValue: "single-value",
44
- };
45
- /**
46
- * A Slider Custom HTML Element.
47
- * Implements the {@link https://www.w3.org/TR/wai-aria-1.1/#slider | ARIA slider }.
37
+ * A Select Custom HTML Element.
38
+ * Implements the {@link https://www.w3.org/TR/wai-aria-1.1/#select | ARIA select }.
48
39
  *
49
- * @slot track - The track of the slider
50
- * @slot track-start - The track-start visual indicator
51
- * @slot thumb - The slider thumb
52
- * @slot - The default slot for labels
53
- * @csspart positioning-region - The region used to position the elements of the slider
54
- * @csspart track-container - The region containing the track elements
55
- * @csspart track-start - The element wrapping the track start slot
56
- * @csspart thumb-container - The thumb container element which is programatically positioned
57
- * @fires change - Fires a custom 'change' event when the slider value changes
40
+ * @slot start - Content which can be provided before the button content
41
+ * @slot end - Content which can be provided after the button content
42
+ * @slot button-container - The element representing the select button
43
+ * @slot selected-value - The selected value
44
+ * @slot indicator - The visual indicator for the expand/collapse state of the button
45
+ * @slot - The default slot for slotted options
46
+ * @csspart control - The element representing the select invoking element
47
+ * @csspart selected-value - The element wrapping the selected value
48
+ * @csspart indicator - The element wrapping the visual indicator
49
+ * @csspart listbox - The listbox element
50
+ * @fires input - Fires a custom 'input' event when the value updates
51
+ * @fires change - Fires a custom 'change' event when the value updates
58
52
  *
59
53
  * @public
60
54
  */
61
- class Slider$1 extends FormAssociatedSlider {
55
+ class Select$1 extends FormAssociatedSelect {
62
56
  constructor() {
63
57
  super(...arguments);
64
58
  /**
65
- * @internal
66
- */
67
- this.direction = Direction.ltr;
68
- /**
69
- * @internal
70
- */
71
- this.isDragging = false;
72
- /**
73
- * @internal
74
- */
75
- this.trackWidth = 0;
76
- /**
77
- * @internal
78
- */
79
- this.trackMinWidth = 0;
80
- /**
81
- * @internal
82
- */
83
- this.trackHeight = 0;
84
- /**
85
- * @internal
86
- */
87
- this.trackLeft = 0;
88
- /**
89
- * @internal
90
- */
91
- this.trackMinHeight = 0;
92
- /**
93
- * Custom function that generates a string for the component's "aria-valuetext" attribute based on the current value.
59
+ * The open attribute.
94
60
  *
95
61
  * @public
96
- */
97
- this.valueTextFormatter = () => null;
98
- /**
99
- * The minimum allowed value.
100
- *
101
- * @defaultValue - 0
102
- * @public
103
62
  * @remarks
104
- * HTML Attribute: min
63
+ * HTML Attribute: open
105
64
  */
106
- this.min = 0; // Map to proxy element.
65
+ this.open = false;
107
66
  /**
108
- * The maximum allowed value.
67
+ * Indicates the initial state of the position attribute.
109
68
  *
110
- * @defaultValue - 10
111
- * @public
112
- * @remarks
113
- * HTML Attribute: max
114
- */
115
- this.max = 10; // Map to proxy element.
116
- /**
117
- * Value to increment or decrement via arrow keys, mouse click or drag.
118
- *
119
- * @public
120
- * @remarks
121
- * HTML Attribute: step
122
- */
123
- this.step = 1; // Map to proxy element.
124
- /**
125
- * The orientation of the slider.
126
- *
127
- * @public
128
- * @remarks
129
- * HTML Attribute: orientation
69
+ * @internal
130
70
  */
131
- this.orientation = Orientation.horizontal;
71
+ this.forcedPosition = false;
132
72
  /**
133
- * The selection mode.
73
+ * The unique id for the internal listbox element.
134
74
  *
135
- * @public
136
- * @remarks
137
- * HTML Attribute: mode
138
- */
139
- this.mode = SliderMode.singleValue;
140
- this.keypressHandler = (e) => {
141
- if (this.readOnly) {
142
- return;
143
- }
144
- if (e.key === keyHome) {
145
- e.preventDefault();
146
- this.value = `${this.min}`;
147
- }
148
- else if (e.key === keyEnd) {
149
- e.preventDefault();
150
- this.value = `${this.max}`;
151
- }
152
- else if (!e.shiftKey) {
153
- switch (e.key) {
154
- case keyArrowRight:
155
- case keyArrowUp:
156
- e.preventDefault();
157
- this.increment();
158
- break;
159
- case keyArrowLeft:
160
- case keyArrowDown:
161
- e.preventDefault();
162
- this.decrement();
163
- break;
164
- }
165
- }
166
- };
167
- this.setupTrackConstraints = () => {
168
- const clientRect = this.track.getBoundingClientRect();
169
- this.trackWidth = this.track.clientWidth;
170
- this.trackMinWidth = this.track.clientLeft;
171
- this.trackHeight = clientRect.bottom;
172
- this.trackMinHeight = clientRect.top;
173
- this.trackLeft = this.getBoundingClientRect().left;
174
- if (this.trackWidth === 0) {
175
- this.trackWidth = 1;
176
- }
177
- };
178
- this.setupListeners = (remove = false) => {
179
- const eventAction = `${remove ? "remove" : "add"}EventListener`;
180
- this[eventAction]("keydown", this.keypressHandler);
181
- this[eventAction]("mousedown", this.handleMouseDown);
182
- this.thumb[eventAction]("mousedown", this.handleThumbMouseDown, {
183
- passive: true,
184
- });
185
- this.thumb[eventAction]("touchstart", this.handleThumbMouseDown, {
186
- passive: true,
187
- });
188
- // removes handlers attached by mousedown handlers
189
- if (remove) {
190
- this.handleMouseDown(null);
191
- this.handleThumbMouseDown(null);
192
- }
193
- };
194
- /**
195
75
  * @internal
196
76
  */
197
- this.initialValue = "";
198
- /**
199
- * Handle mouse moves during a thumb drag operation
200
- * If the event handler is null it removes the events
201
- */
202
- this.handleThumbMouseDown = (event) => {
203
- if (event) {
204
- if (this.readOnly || this.disabled || event.defaultPrevented) {
205
- return;
206
- }
207
- event.target.focus();
208
- }
209
- const eventAction = `${event !== null ? "add" : "remove"}EventListener`;
210
- window[eventAction]("mouseup", this.handleWindowMouseUp);
211
- window[eventAction]("mousemove", this.handleMouseMove, { passive: true });
212
- window[eventAction]("touchmove", this.handleMouseMove, { passive: true });
213
- window[eventAction]("touchend", this.handleWindowMouseUp);
214
- this.isDragging = event !== null;
215
- };
216
- /**
217
- * Handle mouse moves during a thumb drag operation
218
- */
219
- this.handleMouseMove = (e) => {
220
- if (this.readOnly || this.disabled || e.defaultPrevented) {
221
- return;
222
- }
223
- // update the value based on current position
224
- const sourceEvent = window.TouchEvent && e instanceof TouchEvent
225
- ? e.touches[0]
226
- : e;
227
- const eventValue = this.orientation === Orientation.horizontal
228
- ? sourceEvent.pageX - document.documentElement.scrollLeft - this.trackLeft
229
- : sourceEvent.pageY - document.documentElement.scrollTop;
230
- this.value = `${this.calculateNewValue(eventValue)}`;
231
- };
232
- this.calculateNewValue = (rawValue) => {
233
- // update the value based on current position
234
- const newPosition = convertPixelToPercent(rawValue, this.orientation === Orientation.horizontal
235
- ? this.trackMinWidth
236
- : this.trackMinHeight, this.orientation === Orientation.horizontal
237
- ? this.trackWidth
238
- : this.trackHeight, this.direction);
239
- const newValue = (this.max - this.min) * newPosition + this.min;
240
- return this.convertToConstrainedValue(newValue);
241
- };
242
- /**
243
- * Handle a window mouse up during a drag operation
244
- */
245
- this.handleWindowMouseUp = (event) => {
246
- this.stopDragging();
247
- };
248
- this.stopDragging = () => {
249
- this.isDragging = false;
250
- this.handleMouseDown(null);
251
- this.handleThumbMouseDown(null);
252
- };
77
+ this.listboxId = uniqueId("listbox-");
253
78
  /**
79
+ * The max height for the listbox when opened.
254
80
  *
255
- * @param e - MouseEvent or null. If there is no event handler it will remove the events
81
+ * @internal
256
82
  */
257
- this.handleMouseDown = (e) => {
258
- const eventAction = `${e !== null ? "add" : "remove"}EventListener`;
259
- if (e === null || (!this.disabled && !this.readOnly)) {
260
- window[eventAction]("mouseup", this.handleWindowMouseUp);
261
- window.document[eventAction]("mouseleave", this.handleWindowMouseUp);
262
- window[eventAction]("mousemove", this.handleMouseMove);
263
- if (e) {
264
- e.preventDefault();
265
- this.setupTrackConstraints();
266
- e.target.focus();
267
- const controlValue = this.orientation === Orientation.horizontal
268
- ? e.pageX - document.documentElement.scrollLeft - this.trackLeft
269
- : e.pageY - document.documentElement.scrollTop;
270
- this.value = `${this.calculateNewValue(controlValue)}`;
271
- }
272
- }
273
- };
274
- this.convertToConstrainedValue = (value) => {
275
- if (isNaN(value)) {
276
- value = this.min;
277
- }
278
- /**
279
- * The following logic intends to overcome the issue with math in JavaScript with regards to floating point numbers.
280
- * This is needed as the `step` may be an integer but could also be a float. To accomplish this the step is assumed to be a float
281
- * and is converted to an integer by determining the number of decimal places it represent, multiplying it until it is an
282
- * integer and then dividing it to get back to the correct number.
283
- */
284
- let constrainedValue = value - this.min;
285
- const roundedConstrainedValue = Math.round(constrainedValue / this.step);
286
- const remainderValue = constrainedValue -
287
- (roundedConstrainedValue * (this.stepMultiplier * this.step)) /
288
- this.stepMultiplier;
289
- constrainedValue =
290
- remainderValue >= Number(this.step) / 2
291
- ? constrainedValue - remainderValue + Number(this.step)
292
- : constrainedValue - remainderValue;
293
- return constrainedValue + this.min;
294
- };
83
+ this.maxHeight = 0;
295
84
  }
296
- readOnlyChanged() {
297
- if (this.proxy instanceof HTMLInputElement) {
298
- this.proxy.readOnly = this.readOnly;
85
+ /**
86
+ * Sets focus and synchronizes ARIA attributes when the open property changes.
87
+ *
88
+ * @param prev - the previous open value
89
+ * @param next - the current open value
90
+ *
91
+ * @internal
92
+ */
93
+ openChanged(prev, next) {
94
+ if (!this.collapsible) {
95
+ return;
299
96
  }
97
+ if (this.open) {
98
+ this.ariaControls = this.listboxId;
99
+ this.ariaExpanded = "true";
100
+ this.setPositioning();
101
+ this.focusAndScrollOptionIntoView();
102
+ this.indexWhenOpened = this.selectedIndex;
103
+ // focus is directed to the element when `open` is changed programmatically
104
+ DOM.queueUpdate(() => this.focus());
105
+ return;
106
+ }
107
+ this.ariaControls = "";
108
+ this.ariaExpanded = "false";
300
109
  }
301
110
  /**
302
- * The value property, typed as a number.
111
+ * The component is collapsible when in single-selection mode with no size attribute.
112
+ *
113
+ * @internal
114
+ */
115
+ get collapsible() {
116
+ return !(this.multiple || typeof this.size === "number");
117
+ }
118
+ /**
119
+ * The value property.
303
120
  *
304
121
  * @public
305
122
  */
306
- get valueAsNumber() {
307
- return parseFloat(super.value);
123
+ get value() {
124
+ Observable.track(this, "value");
125
+ return this._value;
308
126
  }
309
- set valueAsNumber(next) {
310
- this.value = next.toString();
127
+ set value(next) {
128
+ var _a, _b, _c, _d, _e, _f, _g;
129
+ const prev = `${this._value}`;
130
+ if ((_a = this._options) === null || _a === void 0 ? void 0 : _a.length) {
131
+ const selectedIndex = this._options.findIndex(el => el.value === next);
132
+ const prevSelectedValue = (_c = (_b = this._options[this.selectedIndex]) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : null;
133
+ const nextSelectedValue = (_e = (_d = this._options[selectedIndex]) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : null;
134
+ if (selectedIndex === -1 || prevSelectedValue !== nextSelectedValue) {
135
+ next = "";
136
+ this.selectedIndex = selectedIndex;
137
+ }
138
+ next = (_g = (_f = this.firstSelectedOption) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : next;
139
+ }
140
+ if (prev !== next) {
141
+ this._value = next;
142
+ super.valueChanged(prev, next);
143
+ Observable.notify(this, "value");
144
+ this.updateDisplayValue();
145
+ }
311
146
  }
312
147
  /**
148
+ * Sets the value and display value to match the first selected option.
149
+ *
150
+ * @param shouldEmit - if true, the input and change events will be emitted
151
+ *
313
152
  * @internal
314
153
  */
315
- valueChanged(previous, next) {
316
- super.valueChanged(previous, next);
154
+ updateValue(shouldEmit) {
155
+ var _a, _b;
317
156
  if (this.$fastController.isConnected) {
318
- this.setThumbPositionForOrientation(this.direction);
157
+ this.value = (_b = (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "";
319
158
  }
320
- this.$emit("change");
321
- }
322
- minChanged() {
323
- if (this.proxy instanceof HTMLInputElement) {
324
- this.proxy.min = `${this.min}`;
159
+ if (shouldEmit) {
160
+ this.$emit("input");
161
+ this.$emit("change", this, {
162
+ bubbles: true,
163
+ composed: undefined,
164
+ });
325
165
  }
326
- this.validate();
327
166
  }
328
- maxChanged() {
329
- if (this.proxy instanceof HTMLInputElement) {
330
- this.proxy.max = `${this.max}`;
331
- }
332
- this.validate();
167
+ /**
168
+ * Updates the proxy value when the selected index changes.
169
+ *
170
+ * @param prev - the previous selected index
171
+ * @param next - the next selected index
172
+ *
173
+ * @internal
174
+ */
175
+ selectedIndexChanged(prev, next) {
176
+ super.selectedIndexChanged(prev, next);
177
+ this.updateValue();
333
178
  }
334
- stepChanged() {
335
- if (this.proxy instanceof HTMLInputElement) {
336
- this.proxy.step = `${this.step}`;
179
+ positionChanged(prev, next) {
180
+ this.positionAttribute = next;
181
+ this.setPositioning();
182
+ }
183
+ /**
184
+ * Calculate and apply listbox positioning based on available viewport space.
185
+ *
186
+ * @public
187
+ */
188
+ setPositioning() {
189
+ const currentBox = this.getBoundingClientRect();
190
+ const viewportHeight = window.innerHeight;
191
+ const availableBottom = viewportHeight - currentBox.bottom;
192
+ this.position = this.forcedPosition
193
+ ? this.positionAttribute
194
+ : currentBox.top > availableBottom
195
+ ? SelectPosition.above
196
+ : SelectPosition.below;
197
+ this.positionAttribute = this.forcedPosition
198
+ ? this.positionAttribute
199
+ : this.position;
200
+ this.maxHeight =
201
+ this.position === SelectPosition.above ? ~~currentBox.top : ~~availableBottom;
202
+ }
203
+ /**
204
+ * The value displayed on the button.
205
+ *
206
+ * @public
207
+ */
208
+ get displayValue() {
209
+ var _a, _b;
210
+ Observable.track(this, "displayValue");
211
+ return (_b = (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : "";
212
+ }
213
+ /**
214
+ * Synchronize the `aria-disabled` property when the `disabled` property changes.
215
+ *
216
+ * @param prev - The previous disabled value
217
+ * @param next - The next disabled value
218
+ *
219
+ * @internal
220
+ */
221
+ disabledChanged(prev, next) {
222
+ if (super.disabledChanged) {
223
+ super.disabledChanged(prev, next);
337
224
  }
338
- this.updateStepMultiplier();
339
- this.validate();
225
+ this.ariaDisabled = this.disabled ? "true" : "false";
340
226
  }
341
- orientationChanged() {
342
- if (this.$fastController.isConnected) {
343
- this.setThumbPositionForOrientation(this.direction);
227
+ /**
228
+ * Reset the element to its first selectable option when its parent form is reset.
229
+ *
230
+ * @internal
231
+ */
232
+ formResetCallback() {
233
+ this.setProxyOptions();
234
+ // Call the base class's implementation setDefaultSelectedOption instead of the select's
235
+ // override, in order to reset the selectedIndex without using the value property.
236
+ super.setDefaultSelectedOption();
237
+ if (this.selectedIndex === -1) {
238
+ this.selectedIndex = 0;
344
239
  }
345
240
  }
346
241
  /**
242
+ * Handle opening and closing the listbox when the select is clicked.
243
+ *
244
+ * @param e - the mouse event
347
245
  * @internal
348
246
  */
349
- connectedCallback() {
350
- super.connectedCallback();
351
- this.proxy.setAttribute("type", "range");
352
- this.direction = getDirection(this);
353
- this.updateStepMultiplier();
354
- this.setupTrackConstraints();
355
- this.setupListeners();
356
- this.setupDefaultValue();
357
- this.setThumbPositionForOrientation(this.direction);
247
+ clickHandler(e) {
248
+ // do nothing if the select is disabled
249
+ if (this.disabled) {
250
+ return;
251
+ }
252
+ if (this.open) {
253
+ const captured = e.target.closest(`option,[role=option]`);
254
+ if (captured && captured.disabled) {
255
+ return;
256
+ }
257
+ }
258
+ super.clickHandler(e);
259
+ this.open = this.collapsible && !this.open;
260
+ if (!this.open && this.indexWhenOpened !== this.selectedIndex) {
261
+ this.updateValue(true);
262
+ }
263
+ return true;
358
264
  }
359
265
  /**
266
+ * Handles focus state when the element or its children lose focus.
267
+ *
268
+ * @param e - The focus event
360
269
  * @internal
361
270
  */
362
- disconnectedCallback() {
363
- this.setupListeners(true);
271
+ focusoutHandler(e) {
272
+ var _a;
273
+ super.focusoutHandler(e);
274
+ if (!this.open) {
275
+ return true;
276
+ }
277
+ const focusTarget = e.relatedTarget;
278
+ if (this.isSameNode(focusTarget)) {
279
+ this.focus();
280
+ return;
281
+ }
282
+ if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.includes(focusTarget))) {
283
+ this.open = false;
284
+ if (this.indexWhenOpened !== this.selectedIndex) {
285
+ this.updateValue(true);
286
+ }
287
+ }
364
288
  }
365
289
  /**
366
- * Increment the value by the step
290
+ * Updates the value when an option's value changes.
367
291
  *
368
- * @public
292
+ * @param source - the source object
293
+ * @param propertyName - the property to evaluate
294
+ *
295
+ * @internal
296
+ * @override
369
297
  */
370
- increment() {
371
- const newVal = this.direction !== Direction.rtl && this.orientation !== Orientation.vertical
372
- ? Number(this.value) + Number(this.step)
373
- : Number(this.value) - Number(this.step);
374
- const incrementedVal = this.convertToConstrainedValue(newVal);
375
- const incrementedValString = incrementedVal < Number(this.max) ? `${incrementedVal}` : `${this.max}`;
376
- this.value = incrementedValString;
298
+ handleChange(source, propertyName) {
299
+ super.handleChange(source, propertyName);
300
+ if (propertyName === "value") {
301
+ this.updateValue();
302
+ }
377
303
  }
378
304
  /**
379
- * Decrement the value by the step
305
+ * Synchronize the form-associated proxy and updates the value property of the element.
380
306
  *
381
- * @public
307
+ * @param prev - the previous collection of slotted option elements
308
+ * @param next - the next collection of slotted option elements
309
+ *
310
+ * @internal
382
311
  */
383
- decrement() {
384
- const newVal = this.direction !== Direction.rtl && this.orientation !== Orientation.vertical
385
- ? Number(this.value) - Number(this.step)
386
- : Number(this.value) + Number(this.step);
387
- const decrementedVal = this.convertToConstrainedValue(newVal);
388
- const decrementedValString = decrementedVal > Number(this.min) ? `${decrementedVal}` : `${this.min}`;
389
- this.value = decrementedValString;
312
+ slottedOptionsChanged(prev, next) {
313
+ this.options.forEach(o => {
314
+ const notifier = Observable.getNotifier(o);
315
+ notifier.unsubscribe(this, "value");
316
+ });
317
+ super.slottedOptionsChanged(prev, next);
318
+ this.options.forEach(o => {
319
+ const notifier = Observable.getNotifier(o);
320
+ notifier.subscribe(this, "value");
321
+ });
322
+ this.setProxyOptions();
323
+ this.updateValue();
390
324
  }
391
325
  /**
392
- * Places the thumb based on the current value
326
+ * Prevents focus when size is set and a scrollbar is clicked.
393
327
  *
394
- * @public
395
- * @param direction - writing mode
328
+ * @param e - the mouse event object
329
+ *
330
+ * @override
331
+ * @internal
396
332
  */
397
- setThumbPositionForOrientation(direction) {
398
- const newPct = convertPixelToPercent(Number(this.value), Number(this.min), Number(this.max), direction);
399
- const percentage = (1 - newPct) * 100;
400
- if (this.orientation === Orientation.horizontal) {
401
- this.position = this.isDragging
402
- ? `right: ${percentage}%; transition: none;`
403
- : `right: ${percentage}%; transition: all 0.2s ease;`;
333
+ mousedownHandler(e) {
334
+ var _a;
335
+ if (e.offsetX >= 0 && e.offsetX <= ((_a = this.listbox) === null || _a === void 0 ? void 0 : _a.scrollWidth)) {
336
+ return super.mousedownHandler(e);
404
337
  }
405
- else {
406
- this.position = this.isDragging
407
- ? `bottom: ${percentage}%; transition: none;`
408
- : `bottom: ${percentage}%; transition: all 0.2s ease;`;
338
+ return this.collapsible;
339
+ }
340
+ /**
341
+ * Sets the multiple property on the proxy element.
342
+ *
343
+ * @param prev - the previous multiple value
344
+ * @param next - the current multiple value
345
+ */
346
+ multipleChanged(prev, next) {
347
+ super.multipleChanged(prev, next);
348
+ if (this.proxy) {
349
+ this.proxy.multiple = next;
409
350
  }
410
351
  }
411
352
  /**
412
- * Update the step multiplier used to ensure rounding errors from steps that
413
- * are not whole numbers
353
+ * Updates the selectedness of each option when the list of selected options changes.
354
+ *
355
+ * @param prev - the previous list of selected options
356
+ * @param next - the current list of selected options
357
+ *
358
+ * @override
359
+ * @internal
414
360
  */
415
- updateStepMultiplier() {
416
- const stepString = this.step + "";
417
- const decimalPlacesOfStep = !!(this.step % 1)
418
- ? stepString.length - stepString.indexOf(".") - 1
419
- : 0;
420
- this.stepMultiplier = Math.pow(10, decimalPlacesOfStep);
361
+ selectedOptionsChanged(prev, next) {
362
+ var _a;
363
+ super.selectedOptionsChanged(prev, next);
364
+ (_a = this.options) === null || _a === void 0 ? void 0 : _a.forEach((o, i) => {
365
+ var _a;
366
+ const proxyOption = (_a = this.proxy) === null || _a === void 0 ? void 0 : _a.options.item(i);
367
+ if (proxyOption) {
368
+ proxyOption.selected = o.selected;
369
+ }
370
+ });
421
371
  }
422
- get midpoint() {
423
- return `${this.convertToConstrainedValue((this.max + this.min) / 2)}`;
372
+ /**
373
+ * Sets the selected index to match the first option with the selected attribute, or
374
+ * the first selectable option.
375
+ *
376
+ * @override
377
+ * @internal
378
+ */
379
+ setDefaultSelectedOption() {
380
+ var _a;
381
+ const options = (_a = this.options) !== null && _a !== void 0 ? _a : Array.from(this.children).filter(Listbox.slottedOptionFilter);
382
+ const selectedIndex = options === null || options === void 0 ? void 0 : options.findIndex(el => el.hasAttribute("selected") || el.selected || el.value === this.value);
383
+ if (selectedIndex !== -1) {
384
+ this.selectedIndex = selectedIndex;
385
+ return;
386
+ }
387
+ this.selectedIndex = 0;
388
+ }
389
+ /**
390
+ * Resets and fills the proxy to match the component's options.
391
+ *
392
+ * @internal
393
+ */
394
+ setProxyOptions() {
395
+ if (this.proxy instanceof HTMLSelectElement && this.options) {
396
+ this.proxy.options.length = 0;
397
+ this.options.forEach(option => {
398
+ const proxyOption = option.proxy ||
399
+ (option instanceof HTMLOptionElement ? option.cloneNode() : null);
400
+ if (proxyOption) {
401
+ this.proxy.options.add(proxyOption);
402
+ }
403
+ });
404
+ }
424
405
  }
425
- setupDefaultValue() {
426
- if (typeof this.value === "string") {
427
- if (this.value.length === 0) {
428
- this.initialValue = this.midpoint;
406
+ /**
407
+ * Handle keyboard interaction for the select.
408
+ *
409
+ * @param e - the keyboard event
410
+ * @internal
411
+ */
412
+ keydownHandler(e) {
413
+ super.keydownHandler(e);
414
+ const key = e.key || e.key.charCodeAt(0);
415
+ switch (key) {
416
+ case keySpace: {
417
+ e.preventDefault();
418
+ if (this.collapsible && this.typeAheadExpired) {
419
+ this.open = !this.open;
420
+ }
421
+ break;
422
+ }
423
+ case keyHome:
424
+ case keyEnd: {
425
+ e.preventDefault();
426
+ break;
429
427
  }
430
- else {
431
- const value = parseFloat(this.value);
432
- if (!Number.isNaN(value) && (value < this.min || value > this.max)) {
433
- this.value = this.midpoint;
428
+ case keyEnter: {
429
+ e.preventDefault();
430
+ this.open = !this.open;
431
+ break;
432
+ }
433
+ case keyEscape: {
434
+ if (this.collapsible && this.open) {
435
+ e.preventDefault();
436
+ this.open = false;
434
437
  }
438
+ break;
435
439
  }
440
+ case keyTab: {
441
+ if (this.collapsible && this.open) {
442
+ e.preventDefault();
443
+ this.open = false;
444
+ }
445
+ return true;
446
+ }
447
+ }
448
+ if (!this.open && this.indexWhenOpened !== this.selectedIndex) {
449
+ this.updateValue(true);
450
+ this.indexWhenOpened = this.selectedIndex;
451
+ }
452
+ return !(key === keyArrowDown || key === keyArrowUp);
453
+ }
454
+ connectedCallback() {
455
+ super.connectedCallback();
456
+ this.forcedPosition = !!this.positionAttribute;
457
+ this.addEventListener("contentchange", this.updateDisplayValue);
458
+ }
459
+ disconnectedCallback() {
460
+ this.removeEventListener("contentchange", this.updateDisplayValue);
461
+ super.disconnectedCallback();
462
+ }
463
+ /**
464
+ * Updates the proxy's size property when the size attribute changes.
465
+ *
466
+ * @param prev - the previous size
467
+ * @param next - the current size
468
+ *
469
+ * @override
470
+ * @internal
471
+ */
472
+ sizeChanged(prev, next) {
473
+ super.sizeChanged(prev, next);
474
+ if (this.proxy) {
475
+ this.proxy.size = next;
476
+ }
477
+ }
478
+ /**
479
+ *
480
+ * @internal
481
+ */
482
+ updateDisplayValue() {
483
+ if (this.collapsible) {
484
+ Observable.notify(this, "displayValue");
436
485
  }
437
486
  }
438
487
  }
439
488
  __decorate([
440
- attr({ attribute: "readonly", mode: "boolean" })
441
- ], Slider$1.prototype, "readOnly", void 0);
489
+ attr({ attribute: "open", mode: "boolean" })
490
+ ], Select$1.prototype, "open", void 0);
442
491
  __decorate([
443
- observable
444
- ], Slider$1.prototype, "direction", void 0);
492
+ volatile
493
+ ], Select$1.prototype, "collapsible", null);
445
494
  __decorate([
446
495
  observable
447
- ], Slider$1.prototype, "isDragging", void 0);
496
+ ], Select$1.prototype, "control", void 0);
448
497
  __decorate([
449
- observable
450
- ], Slider$1.prototype, "position", void 0);
451
- __decorate([
452
- observable
453
- ], Slider$1.prototype, "trackWidth", void 0);
454
- __decorate([
455
- observable
456
- ], Slider$1.prototype, "trackMinWidth", void 0);
457
- __decorate([
458
- observable
459
- ], Slider$1.prototype, "trackHeight", void 0);
498
+ attr({ attribute: "position" })
499
+ ], Select$1.prototype, "positionAttribute", void 0);
460
500
  __decorate([
461
501
  observable
462
- ], Slider$1.prototype, "trackLeft", void 0);
502
+ ], Select$1.prototype, "position", void 0);
463
503
  __decorate([
464
504
  observable
465
- ], Slider$1.prototype, "trackMinHeight", void 0);
466
- __decorate([
467
- observable
468
- ], Slider$1.prototype, "valueTextFormatter", void 0);
469
- __decorate([
470
- attr({ converter: nullableNumberConverter })
471
- ], Slider$1.prototype, "min", void 0);
472
- __decorate([
473
- attr({ converter: nullableNumberConverter })
474
- ], Slider$1.prototype, "max", void 0);
475
- __decorate([
476
- attr({ converter: nullableNumberConverter })
477
- ], Slider$1.prototype, "step", void 0);
478
- __decorate([
479
- attr
480
- ], Slider$1.prototype, "orientation", void 0);
481
- __decorate([
482
- attr
483
- ], Slider$1.prototype, "mode", void 0);
484
-
505
+ ], Select$1.prototype, "maxHeight", void 0);
485
506
  /**
486
- * This method keeps a given value within the bounds of a min and max value. If the value
487
- * is larger than the max, the minimum value will be returned. If the value is smaller than the minimum,
488
- * the maximum will be returned. Otherwise, the value is returned un-changed.
489
- */
490
- /**
491
- * Ensures that a value is between a min and max value. If value is lower than min, min will be returned.
492
- * If value is greater than max, max will be returned.
507
+ * Includes ARIA states and properties relating to the ARIA select role.
508
+ *
509
+ * @public
493
510
  */
494
- function limit(min, max, value) {
495
- return Math.min(Math.max(value, min), max);
511
+ class DelegatesARIASelect {
496
512
  }
513
+ __decorate([
514
+ observable
515
+ ], DelegatesARIASelect.prototype, "ariaControls", void 0);
516
+ applyMixins(DelegatesARIASelect, DelegatesARIAListbox);
517
+ applyMixins(Select$1, StartEnd, DelegatesARIASelect);
497
518
 
498
- var css_248z = ":host {\n display: inline-block;\n width: 100%;\n}\n\n:host([orientation=vertical]) {\n height: 100%;\n min-height: calc(var(--_thumb-interaction-indicator-size) * 5);\n}\n\n.control {\n --_thumb-size: 12px;\n --_thumb-interaction-indicator-size: 36px;\n height: var(--_thumb-interaction-indicator-size);\n cursor: pointer;\n outline: none;\n user-select: none;\n}\n@supports selector(:focus-visible) {\n .control:focus-visible {\n outline: none;\n }\n}\n.control .positioning-region {\n position: relative;\n}\n.control .track {\n position: absolute;\n background: var(--_track-background-color);\n border-radius: 4px;\n}\n.control .track .track-start {\n position: absolute;\n left: 0;\n height: 100%;\n background: var(--_track-start-background-color);\n border-radius: 4px;\n}\n.control .thumb-container {\n position: absolute;\n width: var(--_thumb-interaction-indicator-size);\n height: var(--_thumb-interaction-indicator-size);\n cursor: inherit;\n touch-action: none;\n}\n.control .thumb-container::before {\n position: absolute;\n display: block;\n width: var(--_thumb-interaction-indicator-size);\n height: var(--_thumb-interaction-indicator-size);\n background-color: var(--_track-start-background-color);\n border-radius: 50%;\n content: \"\";\n opacity: var(--_thumb-interaction-indicator-alpha, 0);\n transition: opacity 0.2s ease-out 0s;\n}\n.control .thumb-container::after {\n position: absolute;\n display: block;\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n background-color: var(--_track-start-background-color);\n border-radius: 50%;\n content: \"\";\n inset: calc((var(--_thumb-interaction-indicator-size) - var(--_thumb-size)) / 2);\n}\n.control[aria-orientation=horizontal] {\n width: calc(100% - var(--_thumb-size));\n min-width: var(--_thumb-size);\n margin-left: calc(var(--_thumb-size) / 2);\n}\n.control[aria-orientation=horizontal] .track {\n top: calc((var(--_thumb-interaction-indicator-size) - 2px) / 2);\n right: 0;\n left: 0;\n height: 2px;\n}\n.control[aria-orientation=horizontal] .track .mark {\n width: 100%;\n height: 4px;\n}\n.control[aria-orientation=horizontal] .thumb-container {\n transform: translateX(calc(var(--_thumb-interaction-indicator-size) / 2));\n}\n.control[aria-orientation=vertical] {\n height: calc(100% - var(--_thumb-interaction-indicator-size));\n min-height: var(--_thumb-interaction-indicator-size);\n margin-top: calc(var(--_thumb-interaction-indicator-size) / 2);\n}\n.control[aria-orientation=vertical] .positioning-region {\n height: 100%;\n}\n.control[aria-orientation=vertical] .track {\n left: calc((var(--_thumb-interaction-indicator-size) - 2px) / 2);\n width: 2px;\n height: 100%;\n}\n.control[aria-orientation=vertical] .track .mark {\n width: 4px;\n height: 100%;\n}\n.control[aria-orientation=vertical] .track-start {\n top: 0;\n width: 100%;\n height: auto;\n}\n.control[aria-orientation=vertical] .thumb-container {\n transform: translateY(calc(var(--_thumb-interaction-indicator-size) / 2));\n}\n.control.disabled {\n --_track-background-color: var(--vvd-color-neutral-100);\n --_track-start-background-color: var(--vvd-color-neutral-500);\n cursor: not-allowed;\n pointer-events: none;\n}\n.control:not(.disabled) {\n --_track-background-color: var(--vvd-color-neutral-300);\n --_track-start-background-color: var(--vvd-color-canvas-text);\n}\n.control:not(.disabled) .thumb-container:hover {\n --_thumb-interaction-indicator-alpha: 0.12;\n}\n.control:not(.disabled) .thumb-container:active {\n --_thumb-interaction-indicator-alpha: 0.25;\n}\n\n.focus-indicator {\n --focus-inset: -3px;\n --focus-stroke-gap-color: transparent;\n border-radius: 50%;\n}\n.control:not(:focus-visible) .focus-indicator {\n display: none;\n}";
519
+ var css_248z = "/**\n * Do not edit directly\n * Generated on Tue, 22 Aug 2023 13:37:39 GMT\n */\n@supports selector(:focus-visible) {\n :host(:focus-visible) {\n outline: none;\n }\n}\n:host {\n display: inline-flex;\n flex-direction: column;\n gap: 4px;\n --_low-ink-color: var(--vvd-color-neutral-600);\n}\n\n:host([disabled]) {\n --_low-ink-color: var(--vvd-color-neutral-400);\n}\n\n.label {\n color: var(--vvd-color-canvas-text);\n contain: inline-size;\n font: var(--vvd-typography-base);\n}\n\n.control {\n display: flex;\n align-items: center;\n justify-content: space-between;\n background-color: var(--_appearance-color-fill);\n block-size: calc(1px * (40 + 4 * clamp(-1, var(--vvd-size-density, 0), 2)));\n border-radius: var(--_select-control-border-radius);\n box-shadow: inset 0 0 0 1px var(--_appearance-color-outline);\n color: var(--_appearance-color-text);\n font: var(--vvd-typography-base);\n gap: 8px;\n padding-inline: 16px;\n transition: box-shadow 0.2s, background-color 0.2s;\n}\n.control {\n --_appearance-color-text: var(--vvd-color-canvas-text);\n --_appearance-color-fill: var(--_connotation-color-backdrop);\n --_appearance-color-outline: var(--_connotation-color-intermediate);\n}\n.control.appearance-ghost {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.control:where(:hover, .hover):where(:not(:disabled, .disabled, .readonly)) {\n --_appearance-color-text: var(--vvd-color-canvas-text);\n --_appearance-color-fill: var(--_connotation-color-backdrop);\n --_appearance-color-outline: var(--_connotation-color-firm);\n}\n.control:where(:hover, .hover):where(:not(:disabled, .disabled, .readonly)).appearance-ghost {\n --_appearance-color-text: var(--_connotation-color-primary);\n --_appearance-color-fill: var(--_connotation-color-faint);\n --_appearance-color-outline: transparent;\n}\n.control:where(:disabled, .disabled) {\n --_appearance-color-text: var(--vvd-color-neutral-300);\n --_appearance-color-fill: var(--vvd-color-neutral-100);\n --_appearance-color-outline: var(--vvd-color-neutral-300);\n}\n.control:where(:disabled, .disabled).appearance-ghost {\n --_appearance-color-text: var(--vvd-color-neutral-300);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.control:where(.readonly):where(:not(:disabled, .disabled)) {\n --_appearance-color-text: var(--vvd-color-canvas-text);\n --_appearance-color-fill: var(--vvd-color-neutral-200);\n --_appearance-color-outline: var(--vvd-color-neutral-400);\n}\n.control:where(.readonly):where(:not(:disabled, .disabled)).appearance-ghost {\n --_appearance-color-text: var(--vvd-color-neutral-600);\n --_appearance-color-fill: transparent;\n --_appearance-color-outline: transparent;\n}\n.control.connotation-success {\n /* @cssprop [--vvd-select-success-primary=var(--vvd-color-success-500)] */\n --_connotation-color-primary: var(--vvd-select-success-primary, var(--vvd-color-success-500));\n /* @cssprop [--vvd-select-success-backdrop=var(--vvd-color-success-50)] */\n --_connotation-color-backdrop: var(--vvd-select-success-backdrop, var(--vvd-color-success-50));\n /* @cssprop [--vvd-select-success-intermediate=var(--vvd-color-success-500)] */\n --_connotation-color-intermediate: var(--vvd-select-success-intermediate, var(--vvd-color-success-500));\n /* @cssprop [--vvd-select-success-firm=var(--vvd-color-success-600)] */\n --_connotation-color-firm: var(--vvd-select-success-firm, var(--vvd-color-success-600));\n}\n.control.connotation-alert {\n /* @cssprop [--vvd-select-alert-primary=var(--vvd-color-alert-500)] */\n --_connotation-color-primary: var(--vvd-select-alert-primary, var(--vvd-color-alert-500));\n /* @cssprop [--vvd-select-alert-backdrop=var(--vvd-color-alert-50)] */\n --_connotation-color-backdrop: var(--vvd-select-alert-backdrop, var(--vvd-color-alert-50));\n /* @cssprop [--vvd-select-alert-intermediate=var(--vvd-color-alert-500)] */\n --_connotation-color-intermediate: var(--vvd-select-alert-intermediate, var(--vvd-color-alert-500));\n /* @cssprop [--vvd-select-alert-firm=var(--vvd-color-alert-600)] */\n --_connotation-color-firm: var(--vvd-select-alert-firm, var(--vvd-color-alert-600));\n}\n.control:not(.connotation-success, .connotation-alert) {\n /* @cssprop [--vvd-select-accent-primary=var(--vvd-color-canvas-text)] */\n --_connotation-color-primary: var(--vvd-select-accent-primary, var(--vvd-color-canvas-text));\n /* @cssprop [--vvd-select-accent-backdrop=var(--vvd-color-canvas)] */\n --_connotation-color-backdrop: var(--vvd-select-accent-backdrop, var(--vvd-color-canvas));\n /* @cssprop [--vvd-select-accent-intermediate=var(--vvd-color-neutral-500)] */\n --_connotation-color-intermediate: var(--vvd-select-accent-intermediate, var(--vvd-color-neutral-500));\n /* @cssprop [--vvd-select-accent-firm=var(--vvd-color-canvas-text)] */\n --_connotation-color-firm: var(--vvd-select-accent-firm, var(--vvd-color-canvas-text));\n}\n.control-wrapper {\n position: relative;\n}\n.control:not(.disabled) {\n cursor: pointer;\n}\n.control.disabled {\n cursor: not-allowed;\n pointer-events: none;\n}\n.control:not(.shape-pill) {\n --_select-control-border-radius: 6px;\n}\n.control.shape-pill {\n --_select-control-border-radius: 24px;\n}\n\n.listbox {\n display: flex;\n max-height: var(--select-height, 408px);\n flex-direction: column;\n padding: 4px;\n gap: 2px;\n overflow-y: auto;\n}\n\n.icon {\n display: flex;\n flex-shrink: 0;\n}\n\n.selected-value {\n display: flex;\n overflow: hidden;\n flex-grow: 1;\n align-items: center;\n column-gap: 12px;\n white-space: nowrap;\n}\n.selected-value .text {\n overflow: hidden;\n max-inline-size: 100%;\n text-overflow: ellipsis;\n}\n.selected-value slot[name=icon] {\n flex: 0 0 20px;\n font-size: 20px;\n line-height: 1;\n}\n.control.has-meta .selected-value {\n padding-inline-end: 8px;\n}\n\n::part(popup-base) {\n inline-size: max-content;\n min-inline-size: var(--_select-fixed-width, 100%);\n}\n:host([multiple]) ::part(popup-base) {\n position: static;\n}\n\n.focus-indicator {\n --focus-stroke-gap-color: transparent;\n border-radius: var(--_select-control-border-radius);\n pointer-events: none;\n}\n:host(:not(:focus-visible)) .focus-indicator {\n display: none;\n}\n:host([multiple]) .focus-indicator {\n --_select-control-border-radius: 6px;\n}";
499
520
 
500
- class Slider extends Slider$1 {
521
+ let Select = class Select extends Select$1 {
501
522
  constructor() {
502
523
  super(...arguments);
503
- this.markers = false;
524
+ this.fixedDropdown = false;
525
+ this.placeholderOption = null;
526
+ }
527
+ connectedCallback() {
528
+ super.connectedCallback();
529
+ this._popup.anchor = this._anchor;
504
530
  }
505
- valueChanged(previous, next) {
506
- if (this.$fastController.isConnected) {
507
- const nextAsNumber = parseFloat(next);
508
- const value = limit(this.min, this.max, this['convertToConstrainedValue'](nextAsNumber)).toString();
509
- if (value !== next) {
510
- this.value = value;
511
- return;
512
- }
513
- super.valueChanged(previous, value);
531
+ get displayValue() {
532
+ var _a, _b, _c, _d, _e;
533
+ Observable.track(this, 'displayValue');
534
+ return (_e = (_d = (_b = (_a = this.firstSelectedOption) === null || _a === void 0 ? void 0 : _a.getAttribute('label')) !== null && _b !== void 0 ? _b : (_c = this.firstSelectedOption) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : this.placeholder) !== null && _e !== void 0 ? _e : '';
535
+ }
536
+ setDefaultSelectedOption() {
537
+ const options = Array.from(this.children).filter(Listbox$1.slottedOptionFilter);
538
+ const selectedIndex = options.findIndex(el => el.hasAttribute('selected') || el.selected || el.value === this.value);
539
+ if (selectedIndex === -1 && !this.placeholderOption) {
540
+ this.selectedIndex = 0;
541
+ return;
542
+ }
543
+ if (selectedIndex !== -1 || this.placeholder !== '') {
544
+ this.selectedIndex = selectedIndex;
545
+ return;
514
546
  }
515
547
  }
516
- }
548
+ };
549
+ __decorate([attr, __metadata("design:type", String)], Select.prototype, "appearance", void 0);
550
+ __decorate([attr, __metadata("design:type", String)], Select.prototype, "shape", void 0);
517
551
  __decorate([attr({
518
- mode: 'boolean'
519
- }), __metadata("design:type", Object)], Slider.prototype, "markers", void 0);
552
+ mode: 'boolean',
553
+ attribute: 'fixed-dropdown'
554
+ }), __metadata("design:type", Object)], Select.prototype, "fixedDropdown", void 0);
555
+ __decorate([attr, __metadata("design:type", Object)], Select.prototype, "placeholder", void 0);
556
+ __decorate([observable, __metadata("design:type", Object)], Select.prototype, "placeholderOption", void 0);
557
+ __decorate([observable, __metadata("design:type", Array)], Select.prototype, "metaSlottedContent", void 0);
558
+ Select = __decorate([errorText, formElements], Select);
559
+ applyMixins(Select, AffixIconWithTrailing, FormElementHelperText, FormElementSuccessText);
520
560
 
521
- const getClasses = ({
522
- disabled
523
- }) => classNames('control', ['disabled', Boolean(disabled)]);
524
- const getMarkersTemplate = (isHorizontal, numMarkers) => {
525
- const placeholder = isHorizontal ? ['right', 'center', '', '100% repeat-x'] : ['bottom', 'top', '100%', 'repeat-y'];
561
+ const getStateClasses = ({
562
+ shape,
563
+ disabled,
564
+ appearance,
565
+ metaSlottedContent,
566
+ errorValidationMessage,
567
+ successText
568
+ }) => classNames(['disabled', disabled], [`appearance-${appearance}`, Boolean(appearance)], [`shape-${shape}`, Boolean(shape)], ['has-meta', Boolean(metaSlottedContent === null || metaSlottedContent === void 0 ? void 0 : metaSlottedContent.length)], ['error connotation-alert', Boolean(errorValidationMessage)], ['success connotation-success', !!successText], ['has-meta', Boolean(metaSlottedContent === null || metaSlottedContent === void 0 ? void 0 : metaSlottedContent.length)]);
569
+ function renderLabel() {
526
570
  return html`
527
- <div class="mark" style="
528
- background: linear-gradient(to ${placeholder[0]}, currentcolor 3px, transparent 0px)
529
- 0px ${placeholder[1]} / ${placeholder[2]} calc((100% - 3px) / ${numMarkers}) ${placeholder[3]}
530
- "></div>`;
531
- };
532
- const SliderTemplate = context => {
571
+ <label for="control" class="label">
572
+ ${x => x.label}
573
+ </label>`;
574
+ }
575
+ function renderPlaceholder(context) {
576
+ const optionTag = context.tagFor(ListboxOption);
577
+ return html`
578
+ <${optionTag} ${ref('placeholderOption')}
579
+ text="${x => x.placeholder}" hidden disabled>
580
+ </${optionTag}>`;
581
+ }
582
+ function selectValue(context) {
583
+ const affixIconTemplate = affixIconTemplateFactory(context, false);
533
584
  const focusTemplate = focusTemplateFactory(context);
534
585
  return html`
535
- <div
536
- role="slider"
537
- tabindex="${x => x.disabled ? null : 0}"
538
- aria-valuetext="${x => x.valueTextFormatter(x.value)}"
539
- aria-valuenow="${x => x.value}"
540
- aria-valuemin="${x => x.min}"
541
- aria-valuemax="${x => x.max}"
542
- aria-disabled="${x => x.disabled ? true : void 0}"
543
- aria-orientation="${x => x.orientation}"
544
- class="${getClasses} ${x => x.orientation}"
545
- >
546
- <div class="positioning-region">
547
- <div ${ref('track')} class="track">
548
- <div class="track-start" style="${x => x.position}"></div>
549
- ${x => x.markers ? getMarkersTemplate(x.orientation === Orientation$1.horizontal, Math.floor((x.max - x.min) / x.step)) : void 0}
586
+ <div class="control ${getStateClasses}" ${ref('_anchor')}
587
+ id="control" ?disabled="${x => x.disabled}">
588
+ <div class="selected-value">
589
+ <slot name="icon">
590
+ ${when(x => x.icon, html`${x => affixIconTemplate(x.icon)}`)}
591
+ </slot>
592
+ <span class="text">${x => x.displayValue}</span>
593
+ <slot name="meta" ${slotted('metaSlottedContent')}></slot>
550
594
  </div>
551
- <div ${ref('thumb')} class="thumb-container" style="${x => x.position}">
552
- ${() => focusTemplate}
595
+ ${() => affixIconTemplate('chevron-down-line')}
596
+ ${() => focusTemplate}
597
+ </div>`;
598
+ }
599
+ function setFixedDropdownVarWidth(x) {
600
+ return x.open && x.fixedDropdown ? `--_select-fixed-width: ${Math.round(x.getBoundingClientRect().width)}px` : null;
601
+ }
602
+ function renderControl(context) {
603
+ const focusTemplate = focusTemplateFactory(context);
604
+ const popupTag = context.tagFor(Popup);
605
+ return html`
606
+ ${when(x => x.label, renderLabel())}
607
+ <div class="control-wrapper">
608
+ ${when(x => !x.multiple, selectValue(context))}
609
+ <${popupTag} class="popup" ${ref('_popup')}
610
+ style="${setFixedDropdownVarWidth}"
611
+ ?open="${x => x.collapsible ? x.open : true}"
612
+ anchor="control"
613
+ placement="bottom-start"
614
+ strategy="${x => x.fixedDropdown ? null : 'absolute'}">
615
+ <div class="listbox"
616
+ id="${x => x.listboxId}"
617
+ role="listbox"
618
+ ?disabled="${x => x.disabled}"
619
+ ?hidden="${x => x.collapsible ? !x.open : false}"
620
+ ${ref('listbox')}>
621
+ ${when(x => x.placeholder, renderPlaceholder(context))}
622
+ ${when(x => x.multiple, focusTemplate)}
623
+ <slot
624
+ ${slotted({
625
+ filter: Listbox$1.slottedOptionFilter,
626
+ flatten: true,
627
+ property: 'slottedOptions'
628
+ })}>
629
+ </slot>
630
+ </div>
631
+ </${popupTag}>
553
632
  </div>
554
- </div>
555
- </div>`;
633
+ ${when(x => {
634
+ var _a;
635
+ return (_a = x.helperText) === null || _a === void 0 ? void 0 : _a.length;
636
+ }, getFeedbackTemplate('helper', context))}
637
+ ${when(x => !x.successText && x.errorValidationMessage, getFeedbackTemplate('error', context))}
638
+ ${when(x => x.successText, getFeedbackTemplate('success', context))}
639
+ `;
640
+ }
641
+ const SelectTemplate = context => {
642
+ return html`
643
+ <template class="base"
644
+ aria-label="${x => x.ariaLabel ? x.ariaLabel : x.label}"
645
+ aria-activedescendant="${x => x.ariaActiveDescendant}"
646
+ aria-controls="${x => x.ariaControls}"
647
+ aria-disabled="${x => x.ariaDisabled}"
648
+ aria-expanded="${x => x.ariaExpanded}"
649
+ aria-haspopup="${x => x.collapsible ? 'listbox' : null}"
650
+ aria-multiselectable="${x => x.ariaMultiSelectable}"
651
+ ?open="${x => x.open}"
652
+ role="combobox"
653
+ tabindex="${x => !x.disabled ? '0' : null}"
654
+ @click="${(x, c) => x.clickHandler(c.event)}"
655
+ @focusin="${(x, c) => x.focusinHandler(c.event)}"
656
+ @focusout="${(x, c) => x.focusoutHandler(c.event)}"
657
+ @keydown="${(x, c) => x.keydownHandler(c.event)}"
658
+ @mousedown="${(x, c) => x.mousedownHandler(c.event)}">
659
+ ${renderControl(context)}
660
+ </template>`;
556
661
  };
557
662
 
558
- const sliderDefinition = Slider.compose({
559
- baseName: 'slider',
560
- template: SliderTemplate,
663
+ const selectDefinition = Select.compose({
664
+ baseName: 'select',
665
+ template: SelectTemplate,
561
666
  styles: css_248z
562
667
  });
563
- const sliderRegistries = [sliderDefinition(), ...focusRegistries];
564
- const registerSlider = registerFactory(sliderRegistries);
668
+ const selectRegistries = [selectDefinition(), ...focusRegistries, ...popupRegistries, ...iconRegistries, ...listboxOptionRegistries];
669
+ const registerSelect = registerFactory(selectRegistries);
565
670
 
566
- export { sliderRegistries as a, registerSlider as r, sliderDefinition as s };
671
+ export { selectRegistries as a, registerSelect as r, selectDefinition as s };