q2-tecton-elements 1.28.3 → 1.29.1

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 (109) hide show
  1. package/dist/cjs/click-elsewhere_2.cjs.entry.js +4 -3
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/q2-action-sheet.cjs.entry.js +10 -5
  4. package/dist/cjs/q2-badge.cjs.entry.js +43 -0
  5. package/dist/cjs/q2-btn_2.cjs.entry.js +1 -1
  6. package/dist/cjs/q2-calendar.cjs.entry.js +5 -0
  7. package/dist/cjs/q2-checkbox.cjs.entry.js +16 -7
  8. package/dist/cjs/q2-data-table.cjs.entry.js +287 -0
  9. package/dist/cjs/{q2-badge_2.cjs.entry.js → q2-input.cjs.entry.js} +1 -38
  10. package/dist/cjs/q2-section.cjs.entry.js +1 -1
  11. package/dist/cjs/q2-tecton-elements.cjs.js +1 -1
  12. package/dist/collection/collection-manifest.json +1 -0
  13. package/dist/collection/components/q2-action-sheet/index.js +26 -4
  14. package/dist/collection/components/q2-action-sheet/styles.css +2 -2
  15. package/dist/collection/components/q2-btn/styles.css +4 -0
  16. package/dist/collection/components/q2-calendar/index.js +5 -0
  17. package/dist/collection/components/q2-checkbox/index.js +15 -6
  18. package/dist/collection/components/q2-checkbox/styles.css +5 -0
  19. package/dist/collection/components/q2-data-table/index.js +539 -0
  20. package/dist/collection/components/q2-data-table/styles.css +192 -0
  21. package/dist/collection/components/q2-input/styles.css +1 -1
  22. package/dist/collection/components/q2-popover/index.js +4 -3
  23. package/dist/collection/components/q2-section/styles.css +17 -1
  24. package/dist/components/index.d.ts +1 -0
  25. package/dist/components/index.js +1 -0
  26. package/dist/components/index10.js +72 -55
  27. package/dist/components/index11.js +56 -44
  28. package/dist/components/index12.js +42 -42
  29. package/dist/components/index13.js +40 -538
  30. package/dist/components/index14.js +518 -136
  31. package/dist/components/index15.js +174 -574
  32. package/dist/components/index16.js +589 -0
  33. package/dist/components/index3.js +1 -1
  34. package/dist/components/index5.js +3 -3
  35. package/dist/components/index6.js +93 -94
  36. package/dist/components/index7.js +112 -2927
  37. package/dist/components/index8.js +2919 -3347
  38. package/dist/components/index9.js +3343 -56
  39. package/dist/components/q2-action-sheet.js +18 -12
  40. package/dist/components/q2-calendar.js +11 -6
  41. package/dist/components/q2-card.js +2 -2
  42. package/dist/components/q2-carousel-pane.js +1 -1
  43. package/dist/components/q2-carousel.js +3 -3
  44. package/dist/components/q2-chart-area.js +1 -1
  45. package/dist/components/q2-chart-bar.js +1 -1
  46. package/dist/components/q2-chart-donut.js +2 -2
  47. package/dist/components/q2-checkbox-group.js +2 -2
  48. package/dist/components/q2-checkbox.js +1 -133
  49. package/dist/components/q2-data-table.d.ts +11 -0
  50. package/dist/components/q2-data-table.js +349 -0
  51. package/dist/components/q2-dropdown-item.js +1 -1
  52. package/dist/components/q2-dropdown.js +5 -5
  53. package/dist/components/q2-editable-field.js +4 -4
  54. package/dist/components/q2-icon.js +1 -1
  55. package/dist/components/q2-input.js +1 -1
  56. package/dist/components/q2-loading.js +1 -1
  57. package/dist/components/q2-loc.js +1 -1
  58. package/dist/components/q2-message.js +1 -1
  59. package/dist/components/q2-month-picker.js +3 -3
  60. package/dist/components/q2-optgroup.js +1 -1
  61. package/dist/components/q2-option-list.js +1 -1
  62. package/dist/components/q2-option.js +1 -1
  63. package/dist/components/q2-pagination.js +4 -4
  64. package/dist/components/q2-pill.js +4 -4
  65. package/dist/components/q2-popover.js +1 -1
  66. package/dist/components/q2-radio-group.js +2 -2
  67. package/dist/components/q2-radio.js +1 -1
  68. package/dist/components/q2-section.js +4 -4
  69. package/dist/components/q2-select.js +6 -6
  70. package/dist/components/q2-stepper-pane.js +1 -1
  71. package/dist/components/q2-stepper-vertical.js +2 -2
  72. package/dist/components/q2-stepper.js +3 -3
  73. package/dist/components/q2-tab-container.js +3 -3
  74. package/dist/components/q2-tag.js +4 -4
  75. package/dist/components/q2-textarea.js +2 -2
  76. package/dist/components/q2-tooltip.js +1 -1
  77. package/dist/docs.json +280 -3
  78. package/dist/esm/click-elsewhere_2.entry.js +4 -3
  79. package/dist/esm/loader.js +1 -1
  80. package/dist/esm/q2-action-sheet.entry.js +10 -5
  81. package/dist/esm/q2-badge.entry.js +39 -0
  82. package/dist/esm/q2-btn_2.entry.js +1 -1
  83. package/dist/esm/q2-calendar.entry.js +5 -0
  84. package/dist/esm/q2-checkbox.entry.js +16 -7
  85. package/dist/esm/q2-data-table.entry.js +283 -0
  86. package/dist/esm/{q2-badge_2.entry.js → q2-input.entry.js} +3 -39
  87. package/dist/esm/q2-section.entry.js +1 -1
  88. package/dist/esm/q2-tecton-elements.js +1 -1
  89. package/dist/q2-tecton-elements/p-00b2c345.entry.js +1 -0
  90. package/dist/q2-tecton-elements/p-0112df78.entry.js +1 -0
  91. package/dist/q2-tecton-elements/p-08286237.entry.js +1 -0
  92. package/dist/q2-tecton-elements/p-18df4e0d.entry.js +1 -0
  93. package/dist/q2-tecton-elements/{p-6975e5e4.entry.js → p-38885cc4.entry.js} +1 -1
  94. package/dist/q2-tecton-elements/p-42d03011.entry.js +1 -0
  95. package/dist/q2-tecton-elements/p-47aefcc2.entry.js +1 -0
  96. package/dist/q2-tecton-elements/p-9a327827.entry.js +1 -0
  97. package/dist/q2-tecton-elements/{p-807e2e44.entry.js → p-ccc497d5.entry.js} +1 -1
  98. package/dist/q2-tecton-elements/q2-tecton-elements.esm.js +1 -1
  99. package/dist/types/components/q2-action-sheet/index.d.ts +1 -0
  100. package/dist/types/components/q2-checkbox/index.d.ts +4 -0
  101. package/dist/types/components/q2-data-table/index.d.ts +94 -0
  102. package/dist/types/components.d.ts +47 -0
  103. package/package.json +3 -3
  104. package/dist/q2-tecton-elements/p-0b7003c4.entry.js +0 -1
  105. package/dist/q2-tecton-elements/p-1b9e07b4.entry.js +0 -1
  106. package/dist/q2-tecton-elements/p-3bf06809.entry.js +0 -1
  107. package/dist/q2-tecton-elements/p-92e746c8.entry.js +0 -1
  108. package/dist/q2-tecton-elements/p-d6824ce5.entry.js +0 -1
  109. /package/dist/types/workspace/workspace/{tecton-production_release_1.28.x → tecton-production_release_1.29.x}/packages/q2-tecton-elements/.stencil/test/helpers.d.ts +0 -0
@@ -1,188 +1,570 @@
1
- import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
2
- import { r as resizeIframe, w as waitForNextPaint } from './index15.js';
1
+ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
2
+ import { o as overrideFocus, w as waitForNextPaint, n as nextPaint, a as isEventFromElement } from './index16.js';
3
3
 
4
- const stylesCss = "*{box-sizing:border-box}*:active{outline:none}*:focus{outline:none;box-shadow:var(--const-double-focus-ring, 0 0 0 2px #ffffff, 0 0 0 4px #33b4ff #06C)}:host{box-shadow:none !important}::-moz-focus-inner{border:none}input,textarea,button{font-family:inherit;font-size:inherit;font-stretch:inherit}:host(.sr),:host(.sr) button{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.sr,.sr button{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none}:host([hidden]){display:none}.invisible{visibility:hidden}:host{display:block;width:100%}:host([align=right]){display:block;position:absolute;right:0;text-align:end;left:unset}.container{display:none;overflow:hidden;opacity:0;height:0;position:absolute;top:var(--tct-popover-top, var(--t-popover-top, initial));visibility:hidden;background-color:var(--tct-popover-background-color, var(--t-popover-background-color, var(--app-white, #ffffff)));color:var(--tct-popover-text-color, var(--t-popover-text-color, var(--t-text, #4d4d4d)));z-index:var(--tct-popover-z-index, var(--t-popover-z-index, 100));width:max-content;min-width:var(--tct-popover-min-width, var(--t-popover-min-width, 135px));box-shadow:var(--tct-popover-box-shadow, var(--t-popover-box-shadow, var(--app-shadow-1, 0 2px 4px rgba(0, 0, 0, 0.3))));text-align:start;left:0;border-radius:var(--tct-popover-border-radius, var(--t-popover-border-radius, 0));max-height:var(--comp-pop-max-height);--comp-scrollbar-size:var(--tct-scrollbar-size, var(--t-scrollbar-size, var(--app-scale-1x, 5px)));--comp-scrollbar-border-radius:var(--tct-scrollbar-border-radius, var(--t-scrollbar-border-radius, var(--app-border-radius-1, 3px)));--comp-scrollbar-color:var(--tct-scrollbar-color, var(--t-scrollbar-color, var(--t-a11y-gray-color, #747474)));scrollbar-width:thin;scrollbar-color:var(--comp-scrollbar-color) transparent}.container::-webkit-scrollbar{width:var(--comp-scrollbar-size);height:var(--comp-scrollbar-size);margin:5px}.container::-webkit-scrollbar-thumb{background:var(--comp-scrollbar-color);border-radius:var(--comp-scrollbar-border-radius)}.container::-webkit-scrollbar-track{background:transparent;border-radius:var(--comp-scrollbar-border-radius)}:host([block]) .container{left:unset;right:unset;width:100%;min-width:var(--tct-popover-min-width, var(--t-popover-min-width, unset))}:host([align=right]) .container{right:0;text-align:end;left:unset}.container :host([open]){display:block}:host([open]) .container.show{height:auto;overflow:auto;opacity:1;visibility:visible}.container.up{bottom:var(--comp-pop-offset)}click-elsewhere{position:relative;display:block}.content{height:auto}";
4
+ const stylesCss = "*{box-sizing:border-box}*:active{outline:none}*:focus{outline:none;box-shadow:var(--const-double-focus-ring, 0 0 0 2px #ffffff, 0 0 0 4px #33b4ff #06C)}:host{box-shadow:none !important}::-moz-focus-inner{border:none}input,textarea,button{font-family:inherit;font-size:inherit;font-stretch:inherit}:host(.sr),:host(.sr) button{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.sr,.sr button{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;white-space:nowrap}.hidden{display:none}:host([hidden]){display:none}.invisible{visibility:hidden}:host{position:relative;width:100%;display:block;line-height:var(--tct-option-list-line-height, var(--t-option-list-line-height, var(--app-line-height, 1.428571429em)))}.content{text-align:start}:host([is-sizeable]) .content{display:block;height:auto}";
5
5
 
6
- const Q2Popover = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
6
+ const Q2OptionList = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
7
7
  constructor() {
8
8
  super();
9
9
  this.__registerHost();
10
10
  this.__attachShadow();
11
- this.popoverStateChanged = createEvent(this, "popoverStateChanged", 7);
11
+ this.change = createEvent(this, "change", 7);
12
+ this.popoverState = createEvent(this, "popoverState", 7);
13
+ this.ready = createEvent(this, "ready", 3);
12
14
  this.scheduledAfterRender = [];
13
- /// Helpers ///
14
- this.viewPortChanged = () => {
15
- if (!this.open)
16
- return;
17
- this.determinePopDirection();
15
+ this.keyStore = {
16
+ queue: [],
17
+ lastPressedAt: new Date(),
18
18
  };
19
- this.direction = undefined;
19
+ this.searchAndFocus = (keyValue, shouldSelect) => {
20
+ // pseudo search in non-searchable select
21
+ const reorder = () => {
22
+ this.pivotIndex = this.pivotIndex === undefined ? 0 : (this.activeIndex || 0) + 1;
23
+ const list = this.allOptions.map((element, index) => ({ element, index }));
24
+ return [...list.slice(this.pivotIndex), ...list.slice(0, this.pivotIndex)];
25
+ };
26
+ const buildQueue = () => {
27
+ const now = new Date();
28
+ if (now.getTime() - this.keyStore.lastPressedAt.getTime() > 1000) {
29
+ // empty stored keys if delay > 1s
30
+ this.keyStore.queue.length = 0;
31
+ }
32
+ if (this.keyStore.queue.length !== 1 || this.keyStore.queue[0] !== keyValue) {
33
+ this.keyStore.queue.push(keyValue);
34
+ }
35
+ this.keyStore.lastPressedAt = now;
36
+ };
37
+ const searchIndex = (list) => {
38
+ const keyStr = this.keyStore.queue.join('');
39
+ return list.find(v => {
40
+ return (!v.element.disabled &&
41
+ v.element.display &&
42
+ (v.element.display.match(new RegExp(`^${keyStr}`, 'i')) ||
43
+ v.element.display.replace(/\s/g, '').match(new RegExp(`^${keyStr}`, 'i'))));
44
+ });
45
+ };
46
+ const setFocus = ({ index }) => {
47
+ if (this.multiple) {
48
+ // multiple: should open to make sure that which options are selected
49
+ this.openDropdownWithActiveElement(index);
50
+ }
51
+ else {
52
+ this.activeIndex = index;
53
+ if (shouldSelect)
54
+ this.selectOption(this.allOptions[index]);
55
+ else
56
+ this.setActiveElement(index);
57
+ }
58
+ };
59
+ buildQueue();
60
+ const matched = searchIndex(reorder());
61
+ if (matched) {
62
+ setFocus(matched);
63
+ }
64
+ };
65
+ /// Event Handlers ///
66
+ /* tslint:disable:cyclomatic-complexity */
67
+ this.externalKeydownHandler = (event) => {
68
+ event.stopPropagation();
69
+ const { activeIndex, customSearch, allOptions } = this;
70
+ const { key } = event;
71
+ let nextIndex;
72
+ switch (key) {
73
+ case ' ':
74
+ if (this.searchString) {
75
+ if (customSearch)
76
+ break;
77
+ this.searchOptions(key, true);
78
+ break;
79
+ }
80
+ else if (this.role === 'menu') {
81
+ this.activeIndex = 0;
82
+ this.openDropdownWithActiveElement(0);
83
+ }
84
+ else {
85
+ this.setDefaultActiveElement();
86
+ }
87
+ break;
88
+ case 'Enter':
89
+ if (this.role === 'menu') {
90
+ this.activeIndex = 0;
91
+ this.openDropdownWithActiveElement(0);
92
+ }
93
+ else {
94
+ this.setDefaultActiveElement();
95
+ }
96
+ break;
97
+ case 'ArrowUp':
98
+ event.preventDefault();
99
+ this.activeIndex = 0;
100
+ nextIndex = !!this.selectedOptions.length ? this.getDefaultActiveIndex() : this.getNextVisibleIndex(-1);
101
+ if (nextIndex === -1)
102
+ break;
103
+ this.openDropdownWithActiveElement(nextIndex);
104
+ break;
105
+ case 'ArrowDown':
106
+ event.preventDefault();
107
+ this.activeIndex = 0;
108
+ nextIndex = !!this.selectedOptions.length ? this.getDefaultActiveIndex() : this.getNextVisibleIndex(0);
109
+ if (nextIndex === -1)
110
+ break;
111
+ this.openDropdownWithActiveElement(nextIndex);
112
+ break;
113
+ case 'Home':
114
+ event.preventDefault();
115
+ this.openDropdownWithActiveElement(0);
116
+ break;
117
+ case 'End':
118
+ event.preventDefault();
119
+ this.openDropdownWithActiveElement(allOptions.length - 1);
120
+ break;
121
+ case 'PageUp':
122
+ event.preventDefault();
123
+ this.openDropdownWithActiveElement(Math.max((activeIndex || 0) - 10, 0));
124
+ break;
125
+ case 'PageDown':
126
+ event.preventDefault();
127
+ this.openDropdownWithActiveElement(Math.min((activeIndex || 0) + 10, allOptions.length - 1));
128
+ break;
129
+ case 'Tab':
130
+ this.popoverState.emit({ open: false, action: 'close' });
131
+ break;
132
+ case 'Esc':
133
+ case 'Escape':
134
+ if (this.noSelect)
135
+ this.setActiveElement(null);
136
+ this.popoverState.emit({ open: false, action: 'close' });
137
+ break;
138
+ default:
139
+ if (customSearch)
140
+ break;
141
+ if (!key.match(/^[\w]$/))
142
+ break;
143
+ this.searchOptions(key, true);
144
+ break;
145
+ }
146
+ };
147
+ this.internalKeydownHandler = (event) => {
148
+ event.stopPropagation();
149
+ const { activeIndex, customSearch, allOptions } = this;
150
+ const { key, shiftKey } = event;
151
+ let newOption;
152
+ switch (key) {
153
+ case ' ':
154
+ if (this.searchString && !this.multiple) {
155
+ if (customSearch)
156
+ break;
157
+ this.searchOptions(key, false);
158
+ break;
159
+ }
160
+ event.preventDefault();
161
+ newOption = allOptions.find(element => element.active);
162
+ if (!newOption || newOption.disabled)
163
+ break;
164
+ this.selectOption(newOption);
165
+ break;
166
+ case 'Enter':
167
+ event.preventDefault();
168
+ newOption = allOptions.find(element => element.active);
169
+ if (!newOption || newOption.disabled)
170
+ break;
171
+ this.selectOption(newOption);
172
+ break;
173
+ case 'ArrowUp':
174
+ event.preventDefault();
175
+ const isFirstOptionActive = activeIndex === 0;
176
+ if (isFirstOptionActive)
177
+ break;
178
+ if (activeIndex === undefined) {
179
+ this.setDefaultActiveElement();
180
+ break;
181
+ }
182
+ else {
183
+ const nextIndex = this.getNextVisibleIndex(-1);
184
+ if (nextIndex === -1)
185
+ break;
186
+ this.adjustActiveOptionAndScroll(nextIndex - activeIndex);
187
+ break;
188
+ }
189
+ case 'ArrowDown':
190
+ event.preventDefault();
191
+ const isLastOptionActive = activeIndex === allOptions.length - 1;
192
+ if (isLastOptionActive)
193
+ break;
194
+ if (activeIndex === undefined) {
195
+ this.setDefaultActiveElement();
196
+ break;
197
+ }
198
+ else {
199
+ const nextIndex = this.getNextVisibleIndex(1);
200
+ if (nextIndex === -1)
201
+ break;
202
+ this.adjustActiveOptionAndScroll(nextIndex - activeIndex);
203
+ break;
204
+ }
205
+ case 'Home':
206
+ event.preventDefault();
207
+ this.openDropdownWithActiveElement(0);
208
+ break;
209
+ case 'End':
210
+ event.preventDefault();
211
+ this.openDropdownWithActiveElement(allOptions.length - 1);
212
+ break;
213
+ case 'PageUp':
214
+ event.preventDefault();
215
+ this.openDropdownWithActiveElement(Math.max(activeIndex - 10, 0));
216
+ break;
217
+ case 'PageDown':
218
+ event.preventDefault();
219
+ this.openDropdownWithActiveElement(Math.min(activeIndex + 10, allOptions.length - 1));
220
+ break;
221
+ case 'Tab':
222
+ if (shiftKey)
223
+ break;
224
+ if (this.multiple && this.role === 'listbox')
225
+ break;
226
+ newOption = allOptions.find(element => element.active);
227
+ if (!newOption || newOption.disabled)
228
+ return;
229
+ this.selectOption(newOption);
230
+ break;
231
+ case 'Esc':
232
+ case 'Escape':
233
+ if (this.noSelect)
234
+ this.setActiveElement(null);
235
+ this.popoverState.emit({ open: false, action: 'close' });
236
+ break;
237
+ default:
238
+ if (customSearch)
239
+ break;
240
+ if (!key.match(/^[\w]$/))
241
+ break;
242
+ this.searchOptions(key, false);
243
+ break;
244
+ }
245
+ };
246
+ /* tslint:enable:cyclomatic-complexity */
247
+ this.focusoutHandler = (event) => {
248
+ const { relatedTarget } = event;
249
+ const isInDropdown = this.allOptions.includes(relatedTarget);
250
+ const isInLightDom = !isInDropdown && this.hostElement.contains(relatedTarget);
251
+ if (isInDropdown || isInLightDom) {
252
+ event.stopPropagation();
253
+ }
254
+ };
255
+ this.clickHandler = (event) => {
256
+ const target = event.target;
257
+ const option = target.closest('q2-option');
258
+ this.selectOption(option);
259
+ };
260
+ this.role = 'listbox';
261
+ this.customSearch = undefined;
262
+ this.noSelect = undefined;
20
263
  this.align = undefined;
21
- this.open = undefined;
22
- this.block = undefined;
23
- this.minHeight = undefined;
24
- this.controlElement = undefined;
25
- this.currentDirection = undefined;
26
- this.show = false;
27
- }
28
- /// Lifecycle hooks ///
264
+ this.selectedOptions = [];
265
+ this.multiple = undefined;
266
+ this.disabled = undefined;
267
+ this.showSelected = undefined;
268
+ this.type = undefined;
269
+ this.hasOptions = undefined;
270
+ }
271
+ /// LifeCycle Hooks ///
272
+ componentWillLoad() {
273
+ this.hasOptions = !!this.hostElement.querySelectorAll('q2-option').length;
274
+ }
29
275
  componentDidLoad() {
30
- if (this.open)
31
- this.determinePopDirection();
276
+ overrideFocus(this.hostElement);
277
+ this.checkOptions();
278
+ this.selectedOptionsUpdated();
279
+ this.ready.emit();
32
280
  }
33
281
  componentDidRender() {
34
- setTimeout(() => {
35
- this.scheduledAfterRender.forEach(fn => fn());
36
- this.scheduledAfterRender = [];
37
- }, 25);
282
+ this.scheduledAfterRender.forEach(fn => fn());
283
+ this.scheduledAfterRender = [];
38
284
  }
39
- disconnectedCallback() {
40
- this.removeViewportListeners();
285
+ /// Getters ///
286
+ get allContents() {
287
+ const rootSlot = this.getRootSlot(this.hostElement);
288
+ const acceptedTags = ['Q2-OPTGROUP', 'Q2-OPTION'];
289
+ return rootSlot.filter(element => acceptedTags.includes(element.tagName));
41
290
  }
42
- /// Methods ///
43
- async toggle() {
44
- this.open = !this.open;
291
+ get allOptions() {
292
+ const contents = this.allContents;
293
+ const extractOptions = (elements) => {
294
+ return elements.reduce((acc, element) => {
295
+ if (element.tagName === 'Q2-OPTGROUP') {
296
+ return [...acc, ...extractOptions(Array.from(element.children))];
297
+ }
298
+ else if (element.tagName === 'Q2-OPTION') {
299
+ return [...acc, element];
300
+ }
301
+ else {
302
+ return acc;
303
+ }
304
+ }, []);
305
+ };
306
+ return extractOptions(contents);
45
307
  }
46
- /// Watchers ///
47
- openChanged(open) {
48
- this.popoverStateChanged.emit({ open });
49
- this.scheduledAfterRender.push(resizeIframe);
50
- if (open) {
51
- this.addViewportListeners();
52
- this.determinePopDirection();
308
+ get allVisibleOptions() {
309
+ return this.allOptions.filter(option => !option.hidden && !option._multiSelectHidden && !option.disabled && !option.disabledGroup);
310
+ }
311
+ /// Helpers ///
312
+ async checkOptions() {
313
+ const { type } = this;
314
+ const options = await this.getOptions();
315
+ if (!type)
316
+ return;
317
+ const optionRole = type === 'menu' ? 'menuitem' : 'option';
318
+ options.forEach(option => {
319
+ option.role = optionRole;
320
+ });
321
+ }
322
+ getRootSlot(element) {
323
+ var _a;
324
+ const slot = element.querySelector('slot');
325
+ const assignedElements = (_a = slot === null || slot === void 0 ? void 0 : slot.assignedElements()) !== null && _a !== void 0 ? _a : Array.from(element.children);
326
+ const hasAnotherSlot = !!assignedElements.length && assignedElements[0].tagName === 'SLOT';
327
+ if (hasAnotherSlot) {
328
+ return this.getRootSlot(assignedElements[0]);
53
329
  }
54
330
  else {
55
- this.removeViewportListeners();
56
- this.currentDirection = undefined;
57
- this.containerElement.style.removeProperty('display');
58
- this.containerElement.style.removeProperty('--comp-pop-max-height');
59
- this.show = false;
331
+ return assignedElements;
60
332
  }
61
333
  }
62
- /// Listeners ///
63
- popoverStateHandler(event) {
64
- const { detail: { open }, } = event;
65
- if (open === this.open)
334
+ scrollToActiveOption() {
335
+ const activeOption = this.allOptions[this.activeIndex];
336
+ activeOption === null || activeOption === void 0 ? void 0 : activeOption.scrollIntoView({ block: 'nearest' });
337
+ }
338
+ async openDropdownWithActiveElement(activeIndex) {
339
+ if (this.disabled)
66
340
  return;
67
- this.open = open;
68
- event.stopPropagation();
341
+ this.activeIndex = activeIndex;
342
+ this.popoverState.emit({ open: true, action: 'open' });
343
+ await waitForNextPaint();
344
+ this.setActiveOption();
345
+ await waitForNextPaint();
346
+ this.setFocusedOption();
347
+ this.scrollToActiveOption();
69
348
  }
70
- addViewportListeners() {
71
- // window.visualViewport.addEventListener('scroll', this.viewPortChanged);
72
- window.visualViewport.addEventListener('resize', this.viewPortChanged);
349
+ getDefaultActiveIndex() {
350
+ const { allOptions } = this;
351
+ const firstSelected = allOptions.findIndex(element => element.selected);
352
+ if (firstSelected > -1)
353
+ return firstSelected;
354
+ const firstEnabled = allOptions.findIndex(element => !element.hidden);
355
+ if (firstEnabled > -1)
356
+ return firstEnabled;
357
+ return 0;
73
358
  }
74
- removeViewportListeners() {
75
- // window.visualViewport.removeEventListener('scroll', this.viewPortChanged);
76
- window.visualViewport.removeEventListener('resize', this.viewPortChanged);
359
+ updateSingleOptionAttrs() {
360
+ var _a;
361
+ const { allOptions, selectedOptions } = this;
362
+ const selectedValue = ((_a = selectedOptions[0]) === null || _a === void 0 ? void 0 : _a.value) || undefined;
363
+ allOptions.forEach(element => {
364
+ element.selected = element.value === selectedValue;
365
+ });
77
366
  }
78
- async setDirectionAndShow(direction) {
79
- if (direction === 'up') {
80
- this.determinePopOffset();
367
+ updateMultipleOptionAttrs() {
368
+ const { allOptions, selectedOptions } = this;
369
+ const selectedValues = selectedOptions.map(({ value }) => value);
370
+ allOptions.forEach(element => {
371
+ element.selected = selectedValues.includes(element.value);
372
+ });
373
+ }
374
+ setActiveOption() {
375
+ const activeIndex = this.activeIndex;
376
+ this.allOptions.forEach((element, elementIndex) => {
377
+ element.active = activeIndex === elementIndex;
378
+ });
379
+ }
380
+ setFocusedOption() {
381
+ const option = this.allOptions[this.activeIndex];
382
+ if (!option)
383
+ return;
384
+ const isHostElementVisible = !!this.hostElement.offsetParent;
385
+ if (isHostElementVisible)
386
+ option.focus();
387
+ else
388
+ nextPaint(() => option.focus());
389
+ }
390
+ getNextVisibleIndex(direction) {
391
+ const { allVisibleOptions, allOptions, activeIndex } = this;
392
+ const activeOption = allOptions[activeIndex];
393
+ const visibleActiveOptionIndex = allVisibleOptions.indexOf(activeOption);
394
+ let nextVisibleOptionIndex = visibleActiveOptionIndex + direction;
395
+ if (nextVisibleOptionIndex < 0) {
396
+ nextVisibleOptionIndex = allVisibleOptions.length - 1;
81
397
  }
82
- this.currentDirection = direction;
83
- this.show = true;
84
- }
85
- async determinePopDirection() {
86
- var _a, _b, _c, _d, _e, _f, _g;
87
- const { containerElement, contentElement, direction, controlElement, currentDirection } = this;
88
- if (containerElement)
89
- containerElement.style.maxHeight = null;
90
- // If the direction is already set then use it, otherwise use the current direction
91
- const currentOrStatedDirection = direction !== null && direction !== void 0 ? direction : currentDirection;
92
- // Set the container to block so we can get the height
93
- containerElement.style.setProperty('display', 'block');
94
- await waitForNextPaint();
95
- // Determine the dimensions of the control element
96
- const { top: topOffset, height } = (_a = controlElement === null || controlElement === void 0 ? void 0 : controlElement.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {
97
- top: 0,
98
- height: 0,
398
+ else if (nextVisibleOptionIndex > allVisibleOptions.length - 1) {
399
+ nextVisibleOptionIndex = 0;
400
+ }
401
+ const nextVisibleOption = allVisibleOptions[nextVisibleOptionIndex];
402
+ return allOptions.indexOf(nextVisibleOption);
403
+ }
404
+ focusSelectedSibling(option) {
405
+ const { allVisibleOptions, allOptions } = this;
406
+ const hasNoSiblings = allVisibleOptions.length < 2;
407
+ if (hasNoSiblings) {
408
+ this.showSelected = false;
409
+ return;
410
+ }
411
+ const selectedOptionVisibleIndex = allVisibleOptions.indexOf(option);
412
+ const nextVisibleSiblingIndex = selectedOptionVisibleIndex
413
+ ? selectedOptionVisibleIndex - 1
414
+ : selectedOptionVisibleIndex + 1;
415
+ const nextVisibleSibling = allVisibleOptions[nextVisibleSiblingIndex];
416
+ const nextSiblingIndex = allOptions.indexOf(nextVisibleSibling);
417
+ this.activeIndex = nextSiblingIndex;
418
+ this.setFocusedOption();
419
+ this.scheduledAfterRender.push(() => {
420
+ option._multiSelectHidden = !option.selected;
421
+ });
422
+ }
423
+ selectOption(selectedOption) {
424
+ const { multiple, noSelect, showSelected } = this;
425
+ if (!selectedOption || selectedOption.disabled || selectedOption.disabledGroup)
426
+ return;
427
+ const selectedValue = selectedOption.value;
428
+ const valueObject = {
429
+ value: selectedValue,
430
+ display: selectedOption.display || selectedOption.innerText.trim(),
99
431
  };
100
- const contentHeight = contentElement.clientHeight;
101
- const scrollY = ((_c = (_b = window.Tecton) === null || _b === void 0 ? void 0 : _b.platformDimensions) === null || _c === void 0 ? void 0 : _c.scrollY) ||
102
- ((_d = window.visualViewport) === null || _d === void 0 ? void 0 : _d.offsetTop) || // Only Android Chrome provides this which we need when scrolled
103
- 0;
104
- const innerHeight = ((_f = (_e = window.Tecton) === null || _e === void 0 ? void 0 : _e.platformDimensions) === null || _f === void 0 ? void 0 : _f.innerHeight) || ((_g = window.visualViewport) === null || _g === void 0 ? void 0 : _g.height) || window.innerHeight;
105
- const bottomOffset = scrollY + innerHeight - topOffset - height;
106
- const canShowFullSizeBelow = bottomOffset > contentHeight;
107
- const canShowFullSizeAbove = contentHeight <= topOffset;
108
- let determinedDirection;
109
- // Show the full-size popover below or above if it will fit
110
- if (currentOrStatedDirection === 'down' && canShowFullSizeBelow)
111
- return this.setDirectionAndShow('down');
112
- else if (currentOrStatedDirection === 'up' && canShowFullSizeAbove)
113
- return this.setDirectionAndShow('up');
114
- else if (currentOrStatedDirection === undefined && canShowFullSizeBelow)
115
- determinedDirection = 'down';
116
- else if (currentOrStatedDirection === undefined && canShowFullSizeAbove)
117
- determinedDirection = 'up';
118
- if (determinedDirection)
119
- return this.setDirectionAndShow(determinedDirection);
120
- // If full size will not fit then make it as tall as possible
121
- const { minHeight = 150 } = this;
122
- const displayBuffer = 5;
123
- const canShowMinHeightBelow = bottomOffset >= minHeight + displayBuffer;
124
- let maxHeight;
125
- if (currentOrStatedDirection === 'down') {
126
- maxHeight = Math.max(bottomOffset - displayBuffer, minHeight);
127
- determinedDirection = 'down';
432
+ let values = [];
433
+ if (multiple) {
434
+ const { selectedOptions } = this;
435
+ const isAlreadySelected = selectedOptions.find(option => option.value === selectedValue);
436
+ if (isAlreadySelected) {
437
+ values = selectedOptions.filter(({ value }) => value !== selectedValue);
438
+ }
439
+ else {
440
+ values = [...selectedOptions, valueObject];
441
+ }
442
+ if (showSelected)
443
+ this.focusSelectedSibling(selectedOption);
444
+ }
445
+ else {
446
+ values = [valueObject];
447
+ }
448
+ if (noSelect)
449
+ this.setActiveElement(null);
450
+ else
451
+ this.selectedOptions = values;
452
+ this.change.emit({ value: selectedValue, values });
453
+ if (multiple)
454
+ return;
455
+ this.popoverState.emit({ open: false, action: 'select' });
456
+ }
457
+ adjustActiveOptionAndScroll(numToAdd) {
458
+ this.activeIndex += numToAdd;
459
+ this.setActiveOption();
460
+ this.setFocusedOption();
461
+ this.scrollToActiveOption();
462
+ }
463
+ resetTimer() {
464
+ if (this.searchStringTimer) {
465
+ clearTimeout(this.searchStringTimer);
466
+ }
467
+ this.searchStringTimer = window.setTimeout(() => {
468
+ this.searchString = null;
469
+ }, 2000);
470
+ }
471
+ searchOptions(key, shouldSelect) {
472
+ this.searchString = key;
473
+ this.searchAndFocus(key, shouldSelect);
474
+ }
475
+ /// Watchers ///
476
+ showSelectedUpdated(showSelected) {
477
+ if (showSelected && this.selectedOptions.length === 0) {
478
+ this.showSelected = false;
479
+ return;
480
+ }
481
+ this.allOptions.forEach(option => (option._multiSelectHidden = showSelected ? !option.selected : false));
482
+ }
483
+ selectedOptionsUpdated() {
484
+ if (this.multiple) {
485
+ this.updateMultipleOptionAttrs();
128
486
  }
129
- else if (currentOrStatedDirection === 'up') {
130
- maxHeight = Math.max(topOffset - displayBuffer, minHeight);
131
- determinedDirection = 'up';
487
+ else {
488
+ this.updateSingleOptionAttrs();
132
489
  }
133
- else if (canShowMinHeightBelow) {
134
- maxHeight = Math.max(bottomOffset - displayBuffer, minHeight);
135
- determinedDirection = 'down';
490
+ }
491
+ /// Listeners ///
492
+ delegateFocus(event) {
493
+ if (!isEventFromElement(event, this.hostElement))
494
+ return;
495
+ this.popoverState.emit({ open: true, action: 'open' });
496
+ const { activeIndex } = this;
497
+ if (typeof activeIndex === 'number' && activeIndex > -1) {
498
+ this.setActiveOption();
499
+ this.setFocusedOption();
136
500
  }
137
501
  else {
138
- maxHeight = Math.max(topOffset - scrollY - displayBuffer, minHeight);
139
- determinedDirection = 'up';
502
+ this.setDefaultActiveElement();
140
503
  }
141
- containerElement.style.setProperty('--comp-pop-max-height', `${maxHeight}px`);
142
- return this.setDirectionAndShow(determinedDirection);
143
504
  }
144
- determinePopOffset() {
145
- var _a;
146
- const { controlElement, containerElement } = this;
147
- const dropdownHeight = (_a = controlElement === null || controlElement === void 0 ? void 0 : controlElement.getBoundingClientRect().height) !== null && _a !== void 0 ? _a : 0;
148
- containerElement.style.setProperty('--comp-pop-offset', `${dropdownHeight}px`);
505
+ handleClick(event) {
506
+ event.stopPropagation();
507
+ }
508
+ /// Public Methods ///
509
+ async setDefaultActiveElement() {
510
+ this.activeIndex = this.getDefaultActiveIndex();
511
+ this.setActiveOption();
512
+ this.setFocusedOption();
513
+ }
514
+ async setActiveElement(index) {
515
+ this.activeIndex = index;
516
+ this.setActiveOption();
517
+ this.setFocusedOption();
518
+ }
519
+ async handleExternalKeydown(event) {
520
+ this.externalKeydownHandler(event);
521
+ }
522
+ async getContents() {
523
+ return this.allContents;
524
+ }
525
+ async getOptions() {
526
+ return this.allOptions;
149
527
  }
150
528
  /// DOM ///
151
529
  render() {
152
- const containerClasses = ['container', this.currentDirection];
153
- if (this.show)
154
- containerClasses.push('show');
155
- return (h("div", { ref: el => (this.containerElement = el), class: containerClasses.join(' '), "test-id": "outerContainer" }, h("div", { ref: el => (this.contentElement = el), class: "content" }, h("slot", null))));
530
+ return (h(Host, null, h("div", { class: "content", ref: el => (this.contentElement = el), onFocusout: this.focusoutHandler }, h("div", { class: "options", role: this.type || 'listbox', onKeyDown: this.internalKeydownHandler, onClick: this.clickHandler }, h("slot", null)))));
156
531
  }
157
532
  get hostElement() { return this; }
158
533
  static get watchers() { return {
159
- "open": ["openChanged"]
534
+ "showSelected": ["showSelectedUpdated"],
535
+ "selectedOptions": ["selectedOptionsUpdated"]
160
536
  }; }
161
537
  static get style() { return stylesCss; }
162
- }, [1, "q2-popover", {
163
- "direction": [513],
538
+ }, [1, "q2-option-list", {
539
+ "role": [513],
540
+ "customSearch": [516, "custom-search"],
541
+ "noSelect": [516, "no-select"],
164
542
  "align": [513],
165
- "open": [1540],
166
- "block": [516],
167
- "minHeight": [2, "min-height"],
168
- "controlElement": [16],
169
- "currentDirection": [32],
170
- "show": [32],
171
- "toggle": [64]
172
- }, [[0, "popoverState", "popoverStateHandler"]]]);
543
+ "selectedOptions": [1040],
544
+ "multiple": [516],
545
+ "disabled": [516],
546
+ "showSelected": [1540, "show-selected"],
547
+ "type": [1],
548
+ "hasOptions": [32],
549
+ "setDefaultActiveElement": [64],
550
+ "setActiveElement": [64],
551
+ "handleExternalKeydown": [64],
552
+ "getContents": [64],
553
+ "getOptions": [64]
554
+ }, [[0, "focus", "delegateFocus"], [0, "click", "handleClick"]]]);
173
555
  function defineCustomElement() {
174
556
  if (typeof customElements === "undefined") {
175
557
  return;
176
558
  }
177
- const components = ["q2-popover"];
559
+ const components = ["q2-option-list"];
178
560
  components.forEach(tagName => { switch (tagName) {
179
- case "q2-popover":
561
+ case "q2-option-list":
180
562
  if (!customElements.get(tagName)) {
181
- customElements.define(tagName, Q2Popover);
563
+ customElements.define(tagName, Q2OptionList);
182
564
  }
183
565
  break;
184
566
  } });
185
567
  }
186
568
  defineCustomElement();
187
569
 
188
- export { Q2Popover as Q, defineCustomElement as d };
570
+ export { Q2OptionList as Q, defineCustomElement as d };