tyrell-components 1.0.0-TC52 → 1.0.0-TC53

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 (105) hide show
  1. package/css/tyrell-theme.css +25 -2
  2. package/css/tyrell.css +4 -0
  3. package/dist/tyrell-colors-static.css +1 -316
  4. package/dist/tyrell-theme.css +1 -1443
  5. package/dist/tyrell.css +1 -1390
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.js +196 -196
  8. package/lib/components/button.d.ts +1 -1
  9. package/lib/components/button.js +260 -259
  10. package/lib/components/calendar-month.d.ts +2 -2
  11. package/lib/components/calendar-month.js +426 -416
  12. package/lib/components/calendar-navigation.js +238 -238
  13. package/lib/components/calendar.js +605 -602
  14. package/lib/components/checkbox.d.ts +1 -1
  15. package/lib/components/checkbox.js +273 -272
  16. package/lib/components/copy.d.ts +1 -1
  17. package/lib/components/copy.js +279 -278
  18. package/lib/components/date-picker.d.ts +1 -1
  19. package/lib/components/date-picker.js +1103 -1108
  20. package/lib/components/file-upload.js +404 -404
  21. package/lib/components/icon.js +141 -141
  22. package/lib/components/input.d.ts +1 -1
  23. package/lib/components/input.js +593 -596
  24. package/lib/components/modal.js +319 -319
  25. package/lib/components/option.js +167 -167
  26. package/lib/components/popup.js +233 -233
  27. package/lib/components/radio.d.ts +2 -2
  28. package/lib/components/radio.js +407 -406
  29. package/lib/components/resize-observer.js +67 -67
  30. package/lib/components/scroll-container.js +294 -294
  31. package/lib/components/select.d.ts +1 -1
  32. package/lib/components/select.js +1524 -1532
  33. package/lib/components/selected-tags.js +184 -184
  34. package/lib/components/step.js +62 -62
  35. package/lib/components/switch.d.ts +1 -1
  36. package/lib/components/switch.js +214 -213
  37. package/lib/components/tab.js +62 -62
  38. package/lib/components/tabs.js +507 -507
  39. package/lib/components/tag.d.ts +1 -1
  40. package/lib/components/tag.js +236 -235
  41. package/lib/components/textarea.d.ts +1 -1
  42. package/lib/components/textarea.js +457 -456
  43. package/lib/components/tooltip.js +283 -283
  44. package/lib/components/wizard.js +384 -384
  45. package/lib/icons/heroicons/micro.js +392 -392
  46. package/lib/icons/heroicons/mini.js +382 -382
  47. package/lib/icons/heroicons/outline.js +337 -337
  48. package/lib/icons/heroicons/solid.js +407 -407
  49. package/lib/icons/lucide.js +22843 -22843
  50. package/lib/icons/material/filled.js +9653 -9653
  51. package/lib/icons/material/outlined.js +10271 -10271
  52. package/lib/icons/material/round.js +10495 -10495
  53. package/lib/icons/material/sharp.js +9905 -9905
  54. package/lib/icons/material/two-tone.js +12792 -12792
  55. package/lib/index.js +21 -21
  56. package/lib/styles/button.js +176 -288
  57. package/lib/styles/calendar-month.js +123 -183
  58. package/lib/styles/calendar-navigation.js +60 -79
  59. package/lib/styles/calendar.js +8 -9
  60. package/lib/styles/checkbox.js +45 -72
  61. package/lib/styles/copy.js +67 -91
  62. package/lib/styles/custom-scrollbar.js +80 -100
  63. package/lib/styles/date-picker.js +261 -331
  64. package/lib/styles/field-size.d.ts +6 -0
  65. package/lib/styles/field-size.js +91 -0
  66. package/lib/styles/file-upload.js +139 -169
  67. package/lib/styles/icon.js +92 -156
  68. package/lib/styles/input.js +125 -241
  69. package/lib/styles/modal.js +67 -102
  70. package/lib/styles/option.d.ts +1 -1
  71. package/lib/styles/option.js +47 -67
  72. package/lib/styles/popup.js +34 -65
  73. package/lib/styles/radio.js +69 -96
  74. package/lib/styles/resize-observer.js +2 -5
  75. package/lib/styles/scroll-container.js +100 -130
  76. package/lib/styles/select-base.js +525 -778
  77. package/lib/styles/select.js +140 -228
  78. package/lib/styles/step.js +22 -29
  79. package/lib/styles/switch.js +34 -55
  80. package/lib/styles/tab.js +22 -29
  81. package/lib/styles/tabs.js +171 -252
  82. package/lib/styles/tag.js +135 -188
  83. package/lib/styles/textarea.d.ts +1 -1
  84. package/lib/styles/textarea.js +205 -271
  85. package/lib/styles/tooltip.js +3 -3
  86. package/lib/styles/wizard.js +170 -226
  87. package/lib/types/common.d.ts +2 -0
  88. package/lib/types/common.js +6 -5
  89. package/lib/utils/calendar-utils.js +100 -100
  90. package/lib/utils/custom-scrollbar.js +272 -272
  91. package/lib/utils/flavor-sheet.js +14 -14
  92. package/lib/utils/icon-registry.js +127 -127
  93. package/lib/utils/loader-registry.js +3 -3
  94. package/lib/utils/locale.js +34 -34
  95. package/lib/utils/mobile.js +1 -1
  96. package/lib/utils/number-format.js +54 -54
  97. package/lib/utils/positioning.js +212 -212
  98. package/lib/utils/property-capture.js +36 -36
  99. package/lib/utils/property-manager.js +125 -125
  100. package/lib/utils/resize-observer.js +23 -23
  101. package/lib/utils/scroll-lock.js +57 -57
  102. package/lib/utils/styles.js +17 -17
  103. package/lib/version.d.ts +1 -1
  104. package/lib/version.js +1 -1
  105. package/package.json +4 -4
@@ -3,579 +3,579 @@ import { tabsStyles } from '../styles/tabs.js';
3
3
  const eventHandlers = new WeakMap();
4
4
  const resizeObservers = new WeakMap();
5
5
  function getTabsAttributes(el) {
6
- return {
7
- width: el.getAttribute('width') || '100%',
8
- height: el.getAttribute('height') || '400px',
9
- active: el.getAttribute('active'),
10
- placement: (el.getAttribute('placement') || 'top'),
11
- fixed: el.hasAttribute('fixed'),
12
- };
6
+ return {
7
+ width: el.getAttribute('width') || '100%',
8
+ height: el.getAttribute('height') || '400px',
9
+ active: el.getAttribute('active'),
10
+ placement: (el.getAttribute('placement') || 'top'),
11
+ fixed: el.hasAttribute('fixed'),
12
+ };
13
13
  }
14
14
  function getChildTabs(el) {
15
- return Array.from(el.querySelectorAll('ty-tab'));
15
+ return Array.from(el.querySelectorAll('ty-tab'));
16
16
  }
17
17
  function getTabId(tab) {
18
- return tab.getAttribute('id');
18
+ return tab.getAttribute('id');
19
19
  }
20
20
  function getSlotLabel(tabsEl, tabId) {
21
- return tabsEl.querySelector(`:scope > [slot='label-${tabId}']`);
21
+ return tabsEl.querySelector(`:scope > [slot='label-${tabId}']`);
22
22
  }
23
23
  function hasSlotLabel(tabsEl, tabId) {
24
- return getSlotLabel(tabsEl, tabId) !== null;
24
+ return getSlotLabel(tabsEl, tabId) !== null;
25
25
  }
26
26
  function getTabLabelType(tabsEl, tab) {
27
- const tabId = getTabId(tab);
28
- if (tabId && hasSlotLabel(tabsEl, tabId)) {
29
- return 'slot';
30
- }
31
- return 'text';
27
+ const tabId = getTabId(tab);
28
+ if (tabId && hasSlotLabel(tabsEl, tabId)) {
29
+ return 'slot';
30
+ }
31
+ return 'text';
32
32
  }
33
33
  function isTabDisabled(tab) {
34
- return tab.hasAttribute('disabled');
34
+ return tab.hasAttribute('disabled');
35
35
  }
36
36
  function hasCustomMarker(el) {
37
- return el.querySelector('[slot="marker"]') !== null;
37
+ return el.querySelector('[slot="marker"]') !== null;
38
38
  }
39
39
  function findTabIndex(tabs, tabId) {
40
- const index = tabs.findIndex(tab => getTabId(tab) === tabId);
41
- return index >= 0 ? index : undefined;
40
+ const index = tabs.findIndex(tab => getTabId(tab) === tabId);
41
+ return index >= 0 ? index : undefined;
42
42
  }
43
43
  function getActiveTabId(el, tabs) {
44
- const activeAttr = el.getAttribute('active');
45
- if (activeAttr && findTabIndex(tabs, activeAttr) !== undefined) {
46
- return activeAttr;
47
- }
48
- if (tabs.length > 0) {
49
- return getTabId(tabs[0]);
50
- }
51
- return null;
44
+ const activeAttr = el.getAttribute('active');
45
+ if (activeAttr && findTabIndex(tabs, activeAttr) !== undefined) {
46
+ return activeAttr;
47
+ }
48
+ if (tabs.length > 0) {
49
+ return getTabId(tabs[0]);
50
+ }
51
+ return null;
52
52
  }
53
53
  function setActiveTab(el, tabId) {
54
- el.setAttribute('active', tabId);
54
+ el.setAttribute('active', tabId);
55
55
  }
56
56
  function dispatchTabChangeEvent(el, activeId, activeIndex, previousId, previousIndex) {
57
- const event = new CustomEvent('ty-tab-change', {
58
- detail: {
59
- activeId,
60
- activeIndex,
61
- previousId,
62
- previousIndex,
63
- },
64
- bubbles: true,
65
- cancelable: false,
66
- });
67
- el.dispatchEvent(event);
57
+ const event = new CustomEvent('ty-tab-change', {
58
+ detail: {
59
+ activeId,
60
+ activeIndex,
61
+ previousId,
62
+ previousIndex,
63
+ },
64
+ bubbles: true,
65
+ cancelable: false,
66
+ });
67
+ el.dispatchEvent(event);
68
68
  }
69
69
  function handleTabClick(el, tabId, event) {
70
- event.preventDefault();
71
- event.stopPropagation();
72
- setActiveTab(el, tabId);
70
+ event.preventDefault();
71
+ event.stopPropagation();
72
+ setActiveTab(el, tabId);
73
73
  }
74
74
  function cleanupEventListeners(el) {
75
- const handlers = eventHandlers.get(el);
76
- if (!handlers)
77
- return;
78
- const shadowRoot = el.shadowRoot;
79
- if (!shadowRoot)
80
- return;
81
- handlers.tabClickHandlers.forEach((handler, tabId) => {
82
- const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
83
- if (button) {
84
- button.removeEventListener('pointerdown', handler);
85
- }
86
- });
87
- handlers.tabKeyClickHandlers.forEach((handler, tabId) => {
88
- const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
89
- if (button) {
90
- button.removeEventListener('click', handler);
91
- }
92
- });
93
- handlers.tabClickHandlers.clear();
94
- handlers.tabKeyClickHandlers.clear();
75
+ const handlers = eventHandlers.get(el);
76
+ if (!handlers)
77
+ return;
78
+ const shadowRoot = el.shadowRoot;
79
+ if (!shadowRoot)
80
+ return;
81
+ handlers.tabClickHandlers.forEach((handler, tabId) => {
82
+ const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
83
+ if (button) {
84
+ button.removeEventListener('pointerdown', handler);
85
+ }
86
+ });
87
+ handlers.tabKeyClickHandlers.forEach((handler, tabId) => {
88
+ const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
89
+ if (button) {
90
+ button.removeEventListener('click', handler);
91
+ }
92
+ });
93
+ handlers.tabClickHandlers.clear();
94
+ handlers.tabKeyClickHandlers.clear();
95
95
  }
96
96
  function setupEventListeners(el, shadowRoot, tabs) {
97
- cleanupEventListeners(el);
98
- const handlers = {
99
- tabClickHandlers: new Map(),
100
- tabKeyClickHandlers: new Map(),
101
- };
102
- tabs.forEach((tab) => {
103
- const tabId = getTabId(tab);
104
- if (!tabId)
105
- return;
106
- const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
107
- if (button) {
108
- const handler = (e) => handleTabClick(el, tabId, e);
109
- const keyClickHandler = (e) => {
110
- if (e.detail === 0)
111
- handleTabClick(el, tabId, e);
112
- };
113
- button.addEventListener('pointerdown', handler);
114
- button.addEventListener('click', keyClickHandler);
115
- handlers.tabClickHandlers.set(tabId, handler);
116
- handlers.tabKeyClickHandlers.set(tabId, keyClickHandler);
117
- }
118
- });
119
- eventHandlers.set(el, handlers);
97
+ cleanupEventListeners(el);
98
+ const handlers = {
99
+ tabClickHandlers: new Map(),
100
+ tabKeyClickHandlers: new Map(),
101
+ };
102
+ tabs.forEach((tab) => {
103
+ const tabId = getTabId(tab);
104
+ if (!tabId)
105
+ return;
106
+ const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
107
+ if (button) {
108
+ const handler = (e) => handleTabClick(el, tabId, e);
109
+ const keyClickHandler = (e) => {
110
+ if (e.detail === 0)
111
+ handleTabClick(el, tabId, e);
112
+ };
113
+ button.addEventListener('pointerdown', handler);
114
+ button.addEventListener('click', keyClickHandler);
115
+ handlers.tabClickHandlers.set(tabId, handler);
116
+ handlers.tabKeyClickHandlers.set(tabId, keyClickHandler);
117
+ }
118
+ });
119
+ eventHandlers.set(el, handlers);
120
120
  }
121
121
  function updateTransform(el, activeIndex) {
122
- const shadowRoot = el.shadowRoot;
123
- if (!shadowRoot)
124
- return;
125
- const panelsWrapper = shadowRoot.querySelector('.panels-wrapper');
126
- if (!panelsWrapper)
127
- return;
128
- const containerWidth = el.offsetWidth;
129
- const offsetPx = activeIndex * containerWidth;
130
- panelsWrapper.style.transform = `translateX(-${offsetPx}px)`;
122
+ const shadowRoot = el.shadowRoot;
123
+ if (!shadowRoot)
124
+ return;
125
+ const panelsWrapper = shadowRoot.querySelector('.panels-wrapper');
126
+ if (!panelsWrapper)
127
+ return;
128
+ const containerWidth = el.offsetWidth;
129
+ const offsetPx = activeIndex * containerWidth;
130
+ panelsWrapper.style.transform = `translateX(-${offsetPx}px)`;
131
131
  }
132
132
  function updateAriaAttributes(el, shadowRoot, activeId) {
133
- const tabs = getChildTabs(el);
134
- tabs.forEach((tab, idx) => {
135
- const tabId = getTabId(tab);
136
- if (!tabId)
137
- return;
138
- const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
139
- const isActive = tabId === activeId;
140
- if (button) {
141
- button.setAttribute('aria-selected', String(isActive));
142
- button.setAttribute('tabindex', isActive ? '0' : '-1');
143
- button.setAttribute('data-active', String(isActive));
144
- const slottedLabel = getSlotLabel(el, tabId);
145
- if (slottedLabel) {
146
- slottedLabel.setAttribute('data-active', String(isActive));
147
- }
148
- }
149
- });
133
+ const tabs = getChildTabs(el);
134
+ tabs.forEach((tab, idx) => {
135
+ const tabId = getTabId(tab);
136
+ if (!tabId)
137
+ return;
138
+ const button = shadowRoot.querySelector(`[data-tab-id='${tabId}']`);
139
+ const isActive = tabId === activeId;
140
+ if (button) {
141
+ button.setAttribute('aria-selected', String(isActive));
142
+ button.setAttribute('tabindex', isActive ? '0' : '-1');
143
+ button.setAttribute('data-active', String(isActive));
144
+ const slottedLabel = getSlotLabel(el, tabId);
145
+ if (slottedLabel) {
146
+ slottedLabel.setAttribute('data-active', String(isActive));
147
+ }
148
+ }
149
+ });
150
150
  }
151
151
  function updatePanelInteraction(el, activeId) {
152
- const tabs = getChildTabs(el);
153
- tabs.forEach((tab) => {
154
- const tabId = getTabId(tab);
155
- if (!tabId)
156
- return;
157
- const isActive = tabId === activeId;
158
- tab.setAttribute('data-active', String(isActive));
159
- if (isActive) {
160
- tab.style.pointerEvents = 'auto';
161
- tab.style.opacity = '1';
162
- }
163
- else {
164
- tab.style.pointerEvents = 'none';
165
- tab.style.opacity = '0';
166
- }
167
- });
152
+ const tabs = getChildTabs(el);
153
+ tabs.forEach((tab) => {
154
+ const tabId = getTabId(tab);
155
+ if (!tabId)
156
+ return;
157
+ const isActive = tabId === activeId;
158
+ tab.setAttribute('data-active', String(isActive));
159
+ if (isActive) {
160
+ tab.style.pointerEvents = 'auto';
161
+ tab.style.opacity = '1';
162
+ }
163
+ else {
164
+ tab.style.pointerEvents = 'none';
165
+ tab.style.opacity = '0';
166
+ }
167
+ });
168
168
  }
169
169
  function calculateMarkerPosition(el, shadowRoot, activeId) {
170
- const button = shadowRoot.querySelector(`[data-tab-id='${activeId}']`);
171
- const buttonsContainer = shadowRoot.querySelector('.tab-buttons');
172
- if (!button || !buttonsContainer)
173
- return null;
174
- const buttonRect = button.getBoundingClientRect();
175
- const left = button.offsetLeft;
176
- const top = button.offsetTop;
177
- return {
178
- left,
179
- top,
180
- width: buttonRect.width,
181
- height: buttonRect.height,
182
- };
170
+ const button = shadowRoot.querySelector(`[data-tab-id='${activeId}']`);
171
+ const buttonsContainer = shadowRoot.querySelector('.tab-buttons');
172
+ if (!button || !buttonsContainer)
173
+ return null;
174
+ const buttonRect = button.getBoundingClientRect();
175
+ const left = button.offsetLeft;
176
+ const top = button.offsetTop;
177
+ return {
178
+ left,
179
+ top,
180
+ width: buttonRect.width,
181
+ height: buttonRect.height,
182
+ };
183
183
  }
184
184
  function updateMarker(el, activeId) {
185
- const shadowRoot = el.shadowRoot;
186
- if (!shadowRoot)
187
- return;
188
- const marker = shadowRoot.querySelector('.marker-wrapper');
189
- if (!marker)
190
- return;
191
- const position = calculateMarkerPosition(el, shadowRoot, activeId);
192
- if (!position)
193
- return;
194
- const snap = !marker.style.left || marker.offsetWidth === 0;
195
- if (snap)
196
- marker.style.transition = 'none';
197
- marker.style.left = `${position.left}px`;
198
- marker.style.top = `${position.top}px`;
199
- marker.style.width = `${position.width}px`;
200
- marker.style.height = `${position.height}px`;
201
- if (snap) {
202
- marker.offsetWidth;
203
- marker.style.transition = '';
204
- }
185
+ const shadowRoot = el.shadowRoot;
186
+ if (!shadowRoot)
187
+ return;
188
+ const marker = shadowRoot.querySelector('.marker-wrapper');
189
+ if (!marker)
190
+ return;
191
+ const position = calculateMarkerPosition(el, shadowRoot, activeId);
192
+ if (!position)
193
+ return;
194
+ const snap = !marker.style.left || marker.offsetWidth === 0;
195
+ if (snap)
196
+ marker.style.transition = 'none';
197
+ marker.style.left = `${position.left}px`;
198
+ marker.style.top = `${position.top}px`;
199
+ marker.style.width = `${position.width}px`;
200
+ marker.style.height = `${position.height}px`;
201
+ if (snap) {
202
+ marker.offsetWidth;
203
+ marker.style.transition = '';
204
+ }
205
205
  }
206
206
  function updateActiveTabState(el, tabId, previousId) {
207
- const tabs = getChildTabs(el);
208
- const shadowRoot = el.shadowRoot;
209
- if (!shadowRoot)
210
- return;
211
- const currentIndex = previousId ? findTabIndex(tabs, previousId) : undefined;
212
- const newIndex = findTabIndex(tabs, tabId);
213
- if (previousId === tabId || newIndex === undefined)
214
- return;
215
- el.style.setProperty('--active-index', String(newIndex));
216
- updateTransform(el, newIndex);
217
- updateAriaAttributes(el, shadowRoot, tabId);
218
- updatePanelInteraction(el, tabId);
219
- updateMarker(el, tabId);
220
- shadowRoot.querySelectorAll('.tab-overflow-item').forEach((item) => {
221
- item.setAttribute('data-active', String(item.dataset.tabId === tabId));
222
- });
223
- const newPanel = tabs[newIndex];
224
- if (newPanel?.resetScroll) {
225
- newPanel.resetScroll();
226
- }
227
- dispatchTabChangeEvent(el, tabId, newIndex, previousId, currentIndex ?? null);
207
+ const tabs = getChildTabs(el);
208
+ const shadowRoot = el.shadowRoot;
209
+ if (!shadowRoot)
210
+ return;
211
+ const currentIndex = previousId ? findTabIndex(tabs, previousId) : undefined;
212
+ const newIndex = findTabIndex(tabs, tabId);
213
+ if (previousId === tabId || newIndex === undefined)
214
+ return;
215
+ el.style.setProperty('--active-index', String(newIndex));
216
+ updateTransform(el, newIndex);
217
+ updateAriaAttributes(el, shadowRoot, tabId);
218
+ updatePanelInteraction(el, tabId);
219
+ updateMarker(el, tabId);
220
+ shadowRoot.querySelectorAll('.tab-overflow-item').forEach((item) => {
221
+ item.setAttribute('data-active', String(item.dataset.tabId === tabId));
222
+ });
223
+ const newPanel = tabs[newIndex];
224
+ if (newPanel?.resetScroll) {
225
+ newPanel.resetScroll();
226
+ }
227
+ dispatchTabChangeEvent(el, tabId, newIndex, previousId, currentIndex ?? null);
228
228
  }
229
229
  function setupResizeObserver(el) {
230
- const oldObserver = resizeObservers.get(el);
231
- if (oldObserver) {
232
- oldObserver.disconnect();
233
- }
234
- const observer = new ResizeObserver((entries) => {
235
- const entry = entries[0];
236
- const { width } = getTabsAttributes(el);
237
- const tabs = getChildTabs(el);
238
- const activeId = getActiveTabId(el, tabs);
239
- const activeIndex = activeId ? findTabIndex(tabs, activeId) : 0;
240
- if (width.includes('%')) {
241
- el.style.setProperty('--tabs-page-width', `${entry.contentRect.width}px`);
242
- }
243
- if (activeIndex !== undefined) {
244
- updateTransform(el, activeIndex);
245
- }
246
- updateOverflow(el);
247
- if (activeId) {
248
- updateMarker(el, activeId);
249
- scrollActiveIntoView(el, activeId, false);
250
- }
251
- });
252
- observer.observe(el);
253
- resizeObservers.set(el, observer);
230
+ const oldObserver = resizeObservers.get(el);
231
+ if (oldObserver) {
232
+ oldObserver.disconnect();
233
+ }
234
+ const observer = new ResizeObserver((entries) => {
235
+ const entry = entries[0];
236
+ const { width } = getTabsAttributes(el);
237
+ const tabs = getChildTabs(el);
238
+ const activeId = getActiveTabId(el, tabs);
239
+ const activeIndex = activeId ? findTabIndex(tabs, activeId) : 0;
240
+ if (width.includes('%')) {
241
+ el.style.setProperty('--tabs-page-width', `${entry.contentRect.width}px`);
242
+ }
243
+ if (activeIndex !== undefined) {
244
+ updateTransform(el, activeIndex);
245
+ }
246
+ updateOverflow(el);
247
+ if (activeId) {
248
+ updateMarker(el, activeId);
249
+ scrollActiveIntoView(el, activeId, false);
250
+ }
251
+ });
252
+ observer.observe(el);
253
+ resizeObservers.set(el, observer);
254
254
  }
255
255
  function cleanupResizeObserver(el) {
256
- const observer = resizeObservers.get(el);
257
- if (observer) {
258
- observer.disconnect();
259
- resizeObservers.delete(el);
260
- }
256
+ const observer = resizeObservers.get(el);
257
+ if (observer) {
258
+ observer.disconnect();
259
+ resizeObservers.delete(el);
260
+ }
261
261
  }
262
262
  function renderTabButtons(tabsEl, tabs, activeId) {
263
- const buttons = tabs.map((tab) => {
264
- const tabId = getTabId(tab);
265
- if (!tabId)
266
- return '';
267
- const labelType = getTabLabelType(tabsEl, tab);
268
- const textLabel = labelType === 'text' ? (tab.getAttribute('label') || 'Tab') : '';
269
- const disabled = isTabDisabled(tab);
270
- const active = tabId === activeId;
271
- return `<button
272
- class="tab-button"
273
- role="tab"
274
- data-tab-id="${tabId}"
275
- id="tab-${tabId}"
276
- aria-selected="${active}"
277
- tabindex="${active ? '0' : '-1'}"
278
- data-active="${active}"
279
- ${disabled ? 'disabled aria-disabled="true"' : ''}
280
- >
281
- ${labelType === 'slot' ? `<slot name="label-${tabId}"></slot>` : `<span class="tab-label">${textLabel}</span>`}
282
- </button>`;
283
- }).join('');
284
- return `
285
- <div class="tab-buttons" role="tablist" part="buttons-container">
286
- <div class="tab-strip" part="strip">
287
- <div class="marker-wrapper" part="marker-wrapper">
288
- ${!hasCustomMarker(tabsEl) ? '<div class="default-marker"></div>' : ''}
289
- <slot name="marker"></slot>
290
- </div>
291
- ${buttons}
292
- </div>
293
- </div>
294
- `;
263
+ const buttons = tabs.map((tab) => {
264
+ const tabId = getTabId(tab);
265
+ if (!tabId)
266
+ return '';
267
+ const labelType = getTabLabelType(tabsEl, tab);
268
+ const textLabel = labelType === 'text' ? (tab.getAttribute('label') || 'Tab') : '';
269
+ const disabled = isTabDisabled(tab);
270
+ const active = tabId === activeId;
271
+ return `<button
272
+ class="tab-button"
273
+ role="tab"
274
+ data-tab-id="${tabId}"
275
+ id="tab-${tabId}"
276
+ aria-selected="${active}"
277
+ tabindex="${active ? '0' : '-1'}"
278
+ data-active="${active}"
279
+ ${disabled ? 'disabled aria-disabled="true"' : ''}
280
+ >
281
+ ${labelType === 'slot' ? `<slot name="label-${tabId}"></slot>` : `<span class="tab-label">${textLabel}</span>`}
282
+ </button>`;
283
+ }).join('');
284
+ return `
285
+ <div class="tab-buttons" role="tablist" part="buttons-container">
286
+ <div class="tab-strip" part="strip">
287
+ <div class="marker-wrapper" part="marker-wrapper">
288
+ ${!hasCustomMarker(tabsEl) ? '<div class="default-marker"></div>' : ''}
289
+ <slot name="marker"></slot>
290
+ </div>
291
+ ${buttons}
292
+ </div>
293
+ </div>
294
+ `;
295
295
  }
296
296
  function renderButtonsOnly(tabsEl, tabs, activeId) {
297
- return tabs.map((tab) => {
298
- const tabId = getTabId(tab);
299
- if (!tabId)
300
- return '';
301
- const labelType = getTabLabelType(tabsEl, tab);
302
- const textLabel = labelType === 'text' ? (tab.getAttribute('label') || 'Tab') : '';
303
- const disabled = isTabDisabled(tab);
304
- const active = tabId === activeId;
305
- return `<button
306
- class="tab-button"
307
- role="tab"
308
- data-tab-id="${tabId}"
309
- id="tab-${tabId}"
310
- aria-selected="${active}"
311
- tabindex="${active ? '0' : '-1'}"
312
- data-active="${active}"
313
- ${disabled ? 'disabled aria-disabled="true"' : ''}
314
- >
315
- ${labelType === 'slot' ? `<slot name="label-${tabId}"></slot>` : `<span class="tab-label">${textLabel}</span>`}
316
- </button>`;
317
- }).join('');
297
+ return tabs.map((tab) => {
298
+ const tabId = getTabId(tab);
299
+ if (!tabId)
300
+ return '';
301
+ const labelType = getTabLabelType(tabsEl, tab);
302
+ const textLabel = labelType === 'text' ? (tab.getAttribute('label') || 'Tab') : '';
303
+ const disabled = isTabDisabled(tab);
304
+ const active = tabId === activeId;
305
+ return `<button
306
+ class="tab-button"
307
+ role="tab"
308
+ data-tab-id="${tabId}"
309
+ id="tab-${tabId}"
310
+ aria-selected="${active}"
311
+ tabindex="${active ? '0' : '-1'}"
312
+ data-active="${active}"
313
+ ${disabled ? 'disabled aria-disabled="true"' : ''}
314
+ >
315
+ ${labelType === 'slot' ? `<slot name="label-${tabId}"></slot>` : `<span class="tab-label">${textLabel}</span>`}
316
+ </button>`;
317
+ }).join('');
318
318
  }
319
319
  function getTabMenuLabel(tabsEl, tab) {
320
- const tabId = getTabId(tab);
321
- if (tabId && getTabLabelType(tabsEl, tab) === 'slot') {
322
- const slotted = getSlotLabel(tabsEl, tabId);
323
- return slotted?.textContent?.trim() || tabId;
324
- }
325
- return tab.getAttribute('label') || 'Tab';
320
+ const tabId = getTabId(tab);
321
+ if (tabId && getTabLabelType(tabsEl, tab) === 'slot') {
322
+ const slotted = getSlotLabel(tabsEl, tabId);
323
+ return slotted?.textContent?.trim() || tabId;
324
+ }
325
+ return tab.getAttribute('label') || 'Tab';
326
326
  }
327
327
  function removeOverflowMenu(shadowRoot) {
328
- shadowRoot.querySelector('.tab-overflow-trigger')?.remove();
328
+ shadowRoot.querySelector('.tab-overflow-trigger')?.remove();
329
329
  }
330
330
  function renderOverflowMenu(el, container, allTabs) {
331
- const activeId = getActiveTabId(el, allTabs);
332
- const trigger = document.createElement('button');
333
- trigger.className = 'tab-overflow-trigger';
334
- trigger.type = 'button';
335
- trigger.setAttribute('aria-label', `${allTabs.length} tabs`);
336
- trigger.textContent = '⋯';
337
- const popup = document.createElement('ty-popup');
338
- popup.setAttribute('placement', 'bottom');
339
- const menu = document.createElement('div');
340
- menu.className = 'tab-overflow-menu';
341
- menu.setAttribute('role', 'menu');
342
- allTabs.forEach((tab) => {
343
- const tabId = getTabId(tab);
344
- if (!tabId)
345
- return;
346
- const item = document.createElement('button');
347
- item.type = 'button';
348
- item.className = 'tab-overflow-item';
349
- item.setAttribute('role', 'menuitem');
350
- item.setAttribute('data-tab-id', tabId);
351
- item.setAttribute('data-active', String(tabId === activeId));
352
- item.textContent = getTabMenuLabel(el, tab);
353
- if (isTabDisabled(tab)) {
354
- item.disabled = true;
355
- }
356
- else {
357
- item.addEventListener('click', () => {
358
- setActiveTab(el, tabId);
359
- popup.closePopup?.();
360
- });
361
- }
362
- menu.appendChild(item);
363
- });
364
- popup.appendChild(menu);
365
- trigger.appendChild(popup);
366
- container.appendChild(trigger);
331
+ const activeId = getActiveTabId(el, allTabs);
332
+ const trigger = document.createElement('button');
333
+ trigger.className = 'tab-overflow-trigger';
334
+ trigger.type = 'button';
335
+ trigger.setAttribute('aria-label', `${allTabs.length} tabs`);
336
+ trigger.textContent = '⋯';
337
+ const popup = document.createElement('ty-popup');
338
+ popup.setAttribute('placement', 'bottom');
339
+ const menu = document.createElement('div');
340
+ menu.className = 'tab-overflow-menu';
341
+ menu.setAttribute('role', 'menu');
342
+ allTabs.forEach((tab) => {
343
+ const tabId = getTabId(tab);
344
+ if (!tabId)
345
+ return;
346
+ const item = document.createElement('button');
347
+ item.type = 'button';
348
+ item.className = 'tab-overflow-item';
349
+ item.setAttribute('role', 'menuitem');
350
+ item.setAttribute('data-tab-id', tabId);
351
+ item.setAttribute('data-active', String(tabId === activeId));
352
+ item.textContent = getTabMenuLabel(el, tab);
353
+ if (isTabDisabled(tab)) {
354
+ item.disabled = true;
355
+ }
356
+ else {
357
+ item.addEventListener('click', () => {
358
+ setActiveTab(el, tabId);
359
+ popup.closePopup?.();
360
+ });
361
+ }
362
+ menu.appendChild(item);
363
+ });
364
+ popup.appendChild(menu);
365
+ trigger.appendChild(popup);
366
+ container.appendChild(trigger);
367
367
  }
368
368
  function updateOverflow(el) {
369
- const shadowRoot = el.shadowRoot;
370
- if (!shadowRoot)
371
- return;
372
- const container = shadowRoot.querySelector('.tab-buttons');
373
- const strip = shadowRoot.querySelector('.tab-strip');
374
- if (!container || !strip)
375
- return;
376
- if (getTabsAttributes(el).fixed) {
377
- removeOverflowMenu(shadowRoot);
378
- strip.classList.add('unclipped');
379
- strip.style.removeProperty('--fade-left');
380
- strip.style.removeProperty('--fade-right');
381
- return;
382
- }
383
- const savedScrollLeft = strip.scrollLeft;
384
- removeOverflowMenu(shadowRoot);
385
- if (strip.clientWidth <= 0)
386
- return;
387
- const buttons = strip.querySelectorAll('.tab-button');
388
- const last = buttons[buttons.length - 1];
389
- const contentWidth = last ? last.offsetLeft + last.offsetWidth : 0;
390
- const stripWidth = strip.clientWidth;
391
- const hidden = contentWidth - stripWidth;
392
- strip.classList.toggle('unclipped', hidden <= 1);
393
- if (hidden <= 1) {
394
- strip.scrollLeft = savedScrollLeft;
395
- updateEdgeFades(strip);
396
- return;
397
- }
398
- renderOverflowMenu(el, container, getChildTabs(el));
399
- const triggerCost = container.clientWidth - strip.clientWidth;
400
- if (hidden <= triggerCost) {
401
- removeOverflowMenu(shadowRoot);
402
- }
403
- strip.scrollLeft = savedScrollLeft;
404
- updateEdgeFades(strip);
369
+ const shadowRoot = el.shadowRoot;
370
+ if (!shadowRoot)
371
+ return;
372
+ const container = shadowRoot.querySelector('.tab-buttons');
373
+ const strip = shadowRoot.querySelector('.tab-strip');
374
+ if (!container || !strip)
375
+ return;
376
+ if (getTabsAttributes(el).fixed) {
377
+ removeOverflowMenu(shadowRoot);
378
+ strip.classList.add('unclipped');
379
+ strip.style.removeProperty('--fade-left');
380
+ strip.style.removeProperty('--fade-right');
381
+ return;
382
+ }
383
+ const savedScrollLeft = strip.scrollLeft;
384
+ removeOverflowMenu(shadowRoot);
385
+ if (strip.clientWidth <= 0)
386
+ return;
387
+ const buttons = strip.querySelectorAll('.tab-button');
388
+ const last = buttons[buttons.length - 1];
389
+ const contentWidth = last ? last.offsetLeft + last.offsetWidth : 0;
390
+ const stripWidth = strip.clientWidth;
391
+ const hidden = contentWidth - stripWidth;
392
+ strip.classList.toggle('unclipped', hidden <= 1);
393
+ if (hidden <= 1) {
394
+ strip.scrollLeft = savedScrollLeft;
395
+ updateEdgeFades(strip);
396
+ return;
397
+ }
398
+ renderOverflowMenu(el, container, getChildTabs(el));
399
+ const triggerCost = container.clientWidth - strip.clientWidth;
400
+ if (hidden <= triggerCost) {
401
+ removeOverflowMenu(shadowRoot);
402
+ }
403
+ strip.scrollLeft = savedScrollLeft;
404
+ updateEdgeFades(strip);
405
405
  }
406
406
  function updateEdgeFades(strip) {
407
- const maxScroll = strip.scrollWidth - strip.clientWidth;
408
- const fade = (distance) => `${distance > 1 ? Math.min(28, distance) : 0}px`;
409
- strip.style.setProperty('--fade-left', fade(strip.scrollLeft));
410
- strip.style.setProperty('--fade-right', fade(maxScroll - strip.scrollLeft));
407
+ const maxScroll = strip.scrollWidth - strip.clientWidth;
408
+ const fade = (distance) => `${distance > 1 ? Math.min(28, distance) : 0}px`;
409
+ strip.style.setProperty('--fade-left', fade(strip.scrollLeft));
410
+ strip.style.setProperty('--fade-right', fade(maxScroll - strip.scrollLeft));
411
411
  }
412
412
  function scrollActiveIntoView(el, activeId, smooth) {
413
- const shadowRoot = el.shadowRoot;
414
- if (!shadowRoot)
415
- return;
416
- const strip = shadowRoot.querySelector('.tab-strip');
417
- const button = shadowRoot.querySelector(`[data-tab-id='${activeId}']`);
418
- if (!strip || !button || strip.clientWidth <= 0)
419
- return;
420
- const centered = button.offsetLeft + button.offsetWidth / 2 - strip.clientWidth / 2;
421
- const target = Math.max(0, Math.min(centered, strip.scrollWidth - strip.clientWidth));
422
- if (Math.round(target) !== Math.round(strip.scrollLeft)) {
423
- const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
424
- strip.scrollTo({ left: target, behavior: smooth && !reduce ? 'smooth' : 'auto' });
425
- }
413
+ const shadowRoot = el.shadowRoot;
414
+ if (!shadowRoot)
415
+ return;
416
+ const strip = shadowRoot.querySelector('.tab-strip');
417
+ const button = shadowRoot.querySelector(`[data-tab-id='${activeId}']`);
418
+ if (!strip || !button || strip.clientWidth <= 0)
419
+ return;
420
+ const centered = button.offsetLeft + button.offsetWidth / 2 - strip.clientWidth / 2;
421
+ const target = Math.max(0, Math.min(centered, strip.scrollWidth - strip.clientWidth));
422
+ if (Math.round(target) !== Math.round(strip.scrollLeft)) {
423
+ const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
424
+ strip.scrollTo({ left: target, behavior: smooth && !reduce ? 'smooth' : 'auto' });
425
+ }
426
426
  }
427
427
  function render(el) {
428
- const shadowRoot = el.shadowRoot;
429
- if (!shadowRoot)
430
- return;
431
- const { width, height, placement, fixed } = getTabsAttributes(el);
432
- const tabs = getChildTabs(el);
433
- const activeId = getActiveTabId(el, tabs);
434
- const activeIndex = activeId ? (findTabIndex(tabs, activeId) ?? 0) : 0;
435
- tabs.forEach((tab) => {
436
- const tabId = getTabId(tab);
437
- if (!tabId)
438
- return;
439
- tab.setAttribute('role', 'tabpanel');
440
- tab.setAttribute('aria-labelledby', `tab-${tabId}`);
441
- tab.setAttribute('tabindex', '0');
442
- });
443
- const existingContainer = shadowRoot.querySelector('.tabs-container');
444
- const existingButtons = shadowRoot.querySelector('.tab-buttons');
445
- const existingStrip = shadowRoot.querySelector('.tab-strip');
446
- const existingViewport = shadowRoot.querySelector('.panels-viewport');
447
- ensureStyles(shadowRoot, { css: tabsStyles, id: 'ty-tabs' });
448
- el.style.setProperty('--tabs-width', width.includes('%') ? '100%' : width);
449
- el.style.setProperty('--tabs-height', height);
450
- el.style.setProperty('--active-index', String(activeIndex));
451
- if (existingContainer && existingButtons && existingStrip && existingViewport) {
452
- existingContainer.setAttribute('data-placement', placement);
453
- existingContainer.toggleAttribute('data-fixed', fixed);
454
- const savedScrollLeft = existingStrip.scrollLeft;
455
- existingButtons.querySelector('.tab-overflow-trigger')?.remove();
456
- const allButtons = existingStrip.querySelectorAll('.tab-button');
457
- allButtons.forEach(button => button.remove());
458
- const buttonsHtml = renderButtonsOnly(el, tabs, activeId);
459
- const tempDiv = document.createElement('div');
460
- tempDiv.innerHTML = buttonsHtml;
461
- Array.from(tempDiv.children).forEach(button => {
462
- existingStrip.appendChild(button);
463
- });
464
- existingStrip.scrollLeft = savedScrollLeft;
465
- setupEventListeners(el, shadowRoot, tabs);
466
- updateAriaAttributes(el, shadowRoot, activeId || '');
467
- requestAnimationFrame(() => {
468
- const buttons = shadowRoot.querySelector('.tab-buttons');
469
- if (buttons) {
470
- const buttonsHeight = buttons.offsetHeight;
471
- el.style.setProperty('--buttons-height', `${buttonsHeight}px`);
472
- }
473
- updateTransform(el, activeIndex);
474
- updateOverflow(el);
475
- if (activeId) {
476
- updateMarker(el, activeId);
477
- scrollActiveIntoView(el, activeId, true);
478
- }
479
- });
480
- if (activeId) {
481
- updatePanelInteraction(el, activeId);
482
- }
483
- }
484
- else {
485
- shadowRoot.innerHTML = `
486
- <div class="tabs-container" data-placement="${placement}"${fixed ? ' data-fixed' : ''}>
487
- ${renderTabButtons(el, tabs, activeId)}
488
- <div class="panels-viewport" part="panels-container">
489
- <div class="panels-wrapper">
490
- <slot></slot>
491
- </div>
492
- </div>
493
- </div>
494
- `;
495
- requestAnimationFrame(() => {
496
- const buttons = shadowRoot.querySelector('.tab-buttons');
497
- if (buttons) {
498
- const buttonsHeight = buttons.offsetHeight;
499
- el.style.setProperty('--buttons-height', `${buttonsHeight}px`);
500
- }
501
- updateTransform(el, activeIndex);
502
- updateOverflow(el);
503
- if (activeId) {
504
- updateMarker(el, activeId);
505
- scrollActiveIntoView(el, activeId, false);
506
- }
507
- });
508
- setupEventListeners(el, shadowRoot, tabs);
509
- updateAriaAttributes(el, shadowRoot, activeId || '');
510
- setupResizeObserver(el);
511
- const strip = shadowRoot.querySelector('.tab-strip');
512
- strip?.addEventListener('scroll', () => updateEdgeFades(strip), { passive: true });
513
- if (activeId) {
514
- updatePanelInteraction(el, activeId);
515
- }
516
- const markerSlot = shadowRoot.querySelector('slot[name="marker"]');
517
- if (markerSlot) {
518
- const updateDefaultMarkerVisibility = () => {
519
- const defaultMarker = shadowRoot.querySelector('.default-marker');
520
- if (defaultMarker) {
521
- const hasCustom = markerSlot.assignedElements().length > 0;
522
- defaultMarker.style.display = hasCustom ? 'none' : '';
523
- }
524
- };
525
- markerSlot.addEventListener('slotchange', updateDefaultMarkerVisibility);
526
- updateDefaultMarkerVisibility();
527
- }
528
- }
428
+ const shadowRoot = el.shadowRoot;
429
+ if (!shadowRoot)
430
+ return;
431
+ const { width, height, placement, fixed } = getTabsAttributes(el);
432
+ const tabs = getChildTabs(el);
433
+ const activeId = getActiveTabId(el, tabs);
434
+ const activeIndex = activeId ? (findTabIndex(tabs, activeId) ?? 0) : 0;
435
+ tabs.forEach((tab) => {
436
+ const tabId = getTabId(tab);
437
+ if (!tabId)
438
+ return;
439
+ tab.setAttribute('role', 'tabpanel');
440
+ tab.setAttribute('aria-labelledby', `tab-${tabId}`);
441
+ tab.setAttribute('tabindex', '0');
442
+ });
443
+ const existingContainer = shadowRoot.querySelector('.tabs-container');
444
+ const existingButtons = shadowRoot.querySelector('.tab-buttons');
445
+ const existingStrip = shadowRoot.querySelector('.tab-strip');
446
+ const existingViewport = shadowRoot.querySelector('.panels-viewport');
447
+ ensureStyles(shadowRoot, { css: tabsStyles, id: 'ty-tabs' });
448
+ el.style.setProperty('--tabs-width', width.includes('%') ? '100%' : width);
449
+ el.style.setProperty('--tabs-height', height);
450
+ el.style.setProperty('--active-index', String(activeIndex));
451
+ if (existingContainer && existingButtons && existingStrip && existingViewport) {
452
+ existingContainer.setAttribute('data-placement', placement);
453
+ existingContainer.toggleAttribute('data-fixed', fixed);
454
+ const savedScrollLeft = existingStrip.scrollLeft;
455
+ existingButtons.querySelector('.tab-overflow-trigger')?.remove();
456
+ const allButtons = existingStrip.querySelectorAll('.tab-button');
457
+ allButtons.forEach(button => button.remove());
458
+ const buttonsHtml = renderButtonsOnly(el, tabs, activeId);
459
+ const tempDiv = document.createElement('div');
460
+ tempDiv.innerHTML = buttonsHtml;
461
+ Array.from(tempDiv.children).forEach(button => {
462
+ existingStrip.appendChild(button);
463
+ });
464
+ existingStrip.scrollLeft = savedScrollLeft;
465
+ setupEventListeners(el, shadowRoot, tabs);
466
+ updateAriaAttributes(el, shadowRoot, activeId || '');
467
+ requestAnimationFrame(() => {
468
+ const buttons = shadowRoot.querySelector('.tab-buttons');
469
+ if (buttons) {
470
+ const buttonsHeight = buttons.offsetHeight;
471
+ el.style.setProperty('--buttons-height', `${buttonsHeight}px`);
472
+ }
473
+ updateTransform(el, activeIndex);
474
+ updateOverflow(el);
475
+ if (activeId) {
476
+ updateMarker(el, activeId);
477
+ scrollActiveIntoView(el, activeId, true);
478
+ }
479
+ });
480
+ if (activeId) {
481
+ updatePanelInteraction(el, activeId);
482
+ }
483
+ }
484
+ else {
485
+ shadowRoot.innerHTML = `
486
+ <div class="tabs-container" data-placement="${placement}"${fixed ? ' data-fixed' : ''}>
487
+ ${renderTabButtons(el, tabs, activeId)}
488
+ <div class="panels-viewport" part="panels-container">
489
+ <div class="panels-wrapper">
490
+ <slot></slot>
491
+ </div>
492
+ </div>
493
+ </div>
494
+ `;
495
+ requestAnimationFrame(() => {
496
+ const buttons = shadowRoot.querySelector('.tab-buttons');
497
+ if (buttons) {
498
+ const buttonsHeight = buttons.offsetHeight;
499
+ el.style.setProperty('--buttons-height', `${buttonsHeight}px`);
500
+ }
501
+ updateTransform(el, activeIndex);
502
+ updateOverflow(el);
503
+ if (activeId) {
504
+ updateMarker(el, activeId);
505
+ scrollActiveIntoView(el, activeId, false);
506
+ }
507
+ });
508
+ setupEventListeners(el, shadowRoot, tabs);
509
+ updateAriaAttributes(el, shadowRoot, activeId || '');
510
+ setupResizeObserver(el);
511
+ const strip = shadowRoot.querySelector('.tab-strip');
512
+ strip?.addEventListener('scroll', () => updateEdgeFades(strip), { passive: true });
513
+ if (activeId) {
514
+ updatePanelInteraction(el, activeId);
515
+ }
516
+ const markerSlot = shadowRoot.querySelector('slot[name="marker"]');
517
+ if (markerSlot) {
518
+ const updateDefaultMarkerVisibility = () => {
519
+ const defaultMarker = shadowRoot.querySelector('.default-marker');
520
+ if (defaultMarker) {
521
+ const hasCustom = markerSlot.assignedElements().length > 0;
522
+ defaultMarker.style.display = hasCustom ? 'none' : '';
523
+ }
524
+ };
525
+ markerSlot.addEventListener('slotchange', updateDefaultMarkerVisibility);
526
+ updateDefaultMarkerVisibility();
527
+ }
528
+ }
529
529
  }
530
530
  function cleanup(el) {
531
- cleanupEventListeners(el);
532
- cleanupResizeObserver(el);
531
+ cleanupEventListeners(el);
532
+ cleanupResizeObserver(el);
533
533
  }
534
534
  export class TyTabs extends HTMLElement {
535
- static get observedAttributes() {
536
- return ['width', 'height', 'active', 'placement', 'fixed'];
537
- }
538
- constructor() {
539
- super();
540
- this._childObserver = null;
541
- this._childRenderQueued = false;
542
- this.attachShadow({ mode: 'open' });
543
- }
544
- connectedCallback() {
545
- render(this);
546
- this._childObserver = new MutationObserver(() => {
547
- if (this._childRenderQueued)
548
- return;
549
- this._childRenderQueued = true;
550
- queueMicrotask(() => {
551
- this._childRenderQueued = false;
552
- if (this.isConnected)
553
- render(this);
554
- });
555
- });
556
- this._childObserver.observe(this, { childList: true });
557
- }
558
- disconnectedCallback() {
559
- this._childObserver?.disconnect();
560
- this._childObserver = null;
561
- cleanup(this);
562
- }
563
- attributeChangedCallback(name, oldValue, newValue) {
564
- if (name === 'active') {
565
- if (!newValue)
566
- return;
567
- if (!this.shadowRoot?.querySelector(`[data-tab-id='${newValue}']`)) {
568
- render(this);
569
- return;
570
- }
571
- updateActiveTabState(this, newValue, oldValue);
572
- scrollActiveIntoView(this, newValue, true);
573
- }
574
- else {
575
- render(this);
576
- }
577
- }
535
+ static get observedAttributes() {
536
+ return ['width', 'height', 'active', 'placement', 'fixed'];
537
+ }
538
+ constructor() {
539
+ super();
540
+ this._childObserver = null;
541
+ this._childRenderQueued = false;
542
+ this.attachShadow({ mode: 'open' });
543
+ }
544
+ connectedCallback() {
545
+ render(this);
546
+ this._childObserver = new MutationObserver(() => {
547
+ if (this._childRenderQueued)
548
+ return;
549
+ this._childRenderQueued = true;
550
+ queueMicrotask(() => {
551
+ this._childRenderQueued = false;
552
+ if (this.isConnected)
553
+ render(this);
554
+ });
555
+ });
556
+ this._childObserver.observe(this, { childList: true });
557
+ }
558
+ disconnectedCallback() {
559
+ this._childObserver?.disconnect();
560
+ this._childObserver = null;
561
+ cleanup(this);
562
+ }
563
+ attributeChangedCallback(name, oldValue, newValue) {
564
+ if (name === 'active') {
565
+ if (!newValue)
566
+ return;
567
+ if (!this.shadowRoot?.querySelector(`[data-tab-id='${newValue}']`)) {
568
+ render(this);
569
+ return;
570
+ }
571
+ updateActiveTabState(this, newValue, oldValue);
572
+ scrollActiveIntoView(this, newValue, true);
573
+ }
574
+ else {
575
+ render(this);
576
+ }
577
+ }
578
578
  }
579
579
  if (!customElements.get('ty-tabs')) {
580
- customElements.define('ty-tabs', TyTabs);
580
+ customElements.define('ty-tabs', TyTabs);
581
581
  }