@db-ux/wc-core-components 4.7.0-tabs-34782eb → 4.7.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 (168) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/agent/Tabs.md +30 -30
  3. package/dist/cjs/db-accordion-item.cjs.entry.js +2 -2
  4. package/dist/cjs/db-accordion.cjs.entry.js +1 -1
  5. package/dist/cjs/db-badge.cjs.entry.js +1 -1
  6. package/dist/cjs/db-brand.cjs.entry.js +1 -1
  7. package/dist/cjs/db-button.cjs.entry.js +1 -1
  8. package/dist/cjs/db-card.cjs.entry.js +2 -2
  9. package/dist/cjs/db-checkbox.cjs.entry.js +2 -2
  10. package/dist/cjs/db-custom-button.cjs.entry.js +2 -2
  11. package/dist/cjs/db-custom-select-dropdown_5.cjs.entry.js +9 -9
  12. package/dist/cjs/db-custom-select-form-field.cjs.entry.js +2 -2
  13. package/dist/cjs/db-custom-select.cjs.entry.js +5 -5
  14. package/dist/cjs/db-divider.cjs.entry.js +1 -1
  15. package/dist/cjs/db-drawer.cjs.entry.js +3 -3
  16. package/dist/cjs/db-header.cjs.entry.js +2 -2
  17. package/dist/cjs/db-icon.cjs.entry.js +1 -1
  18. package/dist/cjs/db-infotext.cjs.entry.js +1 -1
  19. package/dist/cjs/db-link.cjs.entry.js +1 -1
  20. package/dist/cjs/db-navigation-item.cjs.entry.js +1 -1
  21. package/dist/cjs/db-navigation.cjs.entry.js +2 -2
  22. package/dist/cjs/db-notification.cjs.entry.js +2 -2
  23. package/dist/cjs/db-page.cjs.entry.js +2 -2
  24. package/dist/cjs/db-popover.cjs.entry.js +2 -2
  25. package/dist/cjs/db-radio.cjs.entry.js +1 -1
  26. package/dist/cjs/db-section.cjs.entry.js +2 -2
  27. package/dist/cjs/db-select.cjs.entry.js +2 -2
  28. package/dist/cjs/db-stack.cjs.entry.js +2 -2
  29. package/dist/cjs/db-switch.cjs.entry.js +2 -2
  30. package/dist/cjs/db-tab-item_3.cjs.entry.js +67 -133
  31. package/dist/cjs/db-tabs.cjs.entry.js +123 -373
  32. package/dist/cjs/db-textarea.cjs.entry.js +2 -2
  33. package/dist/cjs/db-tooltip.cjs.entry.js +4 -3
  34. package/dist/cjs/db-ux.cjs.js +1 -1
  35. package/dist/cjs/index.cjs.js +2 -2
  36. package/dist/cjs/loader.cjs.js +1 -1
  37. package/dist/collection/components/accordion/accordion.js +1 -1
  38. package/dist/collection/components/accordion-item/accordion-item.js +2 -2
  39. package/dist/collection/components/badge/badge.js +1 -1
  40. package/dist/collection/components/brand/brand.js +1 -1
  41. package/dist/collection/components/button/button.js +1 -1
  42. package/dist/collection/components/card/card.js +2 -2
  43. package/dist/collection/components/checkbox/checkbox.js +2 -2
  44. package/dist/collection/components/custom-button/custom-button.js +2 -2
  45. package/dist/collection/components/custom-select/custom-select.js +5 -5
  46. package/dist/collection/components/custom-select-dropdown/custom-select-dropdown.js +2 -2
  47. package/dist/collection/components/custom-select-form-field/custom-select-form-field.js +2 -2
  48. package/dist/collection/components/custom-select-list/custom-select-list.js +2 -2
  49. package/dist/collection/components/custom-select-list-item/custom-select-list-item.js +1 -1
  50. package/dist/collection/components/divider/divider.js +1 -1
  51. package/dist/collection/components/drawer/drawer.js +3 -3
  52. package/dist/collection/components/header/header.js +2 -2
  53. package/dist/collection/components/icon/icon.js +1 -1
  54. package/dist/collection/components/infotext/infotext.js +1 -1
  55. package/dist/collection/components/input/input.js +2 -2
  56. package/dist/collection/components/link/link.js +1 -1
  57. package/dist/collection/components/navigation/navigation.js +2 -2
  58. package/dist/collection/components/navigation-item/navigation-item.js +1 -1
  59. package/dist/collection/components/notification/notification.js +2 -2
  60. package/dist/collection/components/page/page.js +2 -2
  61. package/dist/collection/components/popover/popover.js +2 -2
  62. package/dist/collection/components/radio/radio.js +1 -1
  63. package/dist/collection/components/section/section.js +2 -2
  64. package/dist/collection/components/select/select.js +2 -2
  65. package/dist/collection/components/stack/stack.js +2 -2
  66. package/dist/collection/components/switch/switch.js +2 -2
  67. package/dist/collection/components/tab-item/tab-item.js +129 -198
  68. package/dist/collection/components/tab-list/tab-list.js +12 -74
  69. package/dist/collection/components/tab-panel/tab-panel.js +2 -80
  70. package/dist/collection/components/tabs/tabs.js +167 -504
  71. package/dist/collection/components/tag/tag.js +2 -2
  72. package/dist/collection/components/textarea/textarea.js +2 -2
  73. package/dist/collection/components/tooltip/tooltip.js +4 -3
  74. package/dist/collection/shared/model.js +1 -1
  75. package/dist/custom-elements.json +2998 -3898
  76. package/dist/db-ux/db-ux.esm.js +1 -1
  77. package/dist/db-ux/index.esm.js +1 -1
  78. package/dist/db-ux/{p-9b518eb4.entry.js → p-0e0c3c72.entry.js} +1 -1
  79. package/dist/db-ux/{p-61784f7a.entry.js → p-12a2c502.entry.js} +1 -1
  80. package/dist/db-ux/{p-b7087f0b.entry.js → p-13157b54.entry.js} +1 -1
  81. package/dist/db-ux/p-202323c2.entry.js +1 -0
  82. package/dist/db-ux/p-21068628.entry.js +1 -0
  83. package/dist/db-ux/{p-b06fe221.entry.js → p-212bde1e.entry.js} +1 -1
  84. package/dist/db-ux/{p-01c278b9.entry.js → p-2355324e.entry.js} +1 -1
  85. package/dist/db-ux/p-377987d0.entry.js +1 -0
  86. package/dist/db-ux/p-3d5d49ff.entry.js +1 -0
  87. package/dist/db-ux/p-452a8b6b.entry.js +1 -0
  88. package/dist/db-ux/p-4de2c697.entry.js +1 -0
  89. package/dist/db-ux/{p-f08b14d9.entry.js → p-5cb74480.entry.js} +1 -1
  90. package/dist/db-ux/{p-071ae423.entry.js → p-5f5eb78d.entry.js} +1 -1
  91. package/dist/db-ux/p-605013f0.entry.js +1 -0
  92. package/dist/db-ux/p-6f9e146e.entry.js +1 -0
  93. package/dist/db-ux/{p-328faf6b.entry.js → p-70823b80.entry.js} +1 -1
  94. package/dist/db-ux/{p-70e6d32f.entry.js → p-761c9ddf.entry.js} +1 -1
  95. package/dist/db-ux/p-7fa91164.entry.js +1 -0
  96. package/dist/db-ux/p-8e84712d.entry.js +1 -0
  97. package/dist/db-ux/{p-ffe614c8.entry.js → p-980a6afe.entry.js} +1 -1
  98. package/dist/db-ux/{p-6c26b0ba.entry.js → p-a65d0d23.entry.js} +1 -1
  99. package/dist/db-ux/p-a9efbb0b.entry.js +1 -0
  100. package/dist/db-ux/{p-07c7ecc9.entry.js → p-abb0885d.entry.js} +1 -1
  101. package/dist/db-ux/{p-9a895c18.entry.js → p-ba8464d2.entry.js} +1 -1
  102. package/dist/db-ux/p-bd66d144.entry.js +1 -0
  103. package/dist/db-ux/{p-74a45768.entry.js → p-bed8d029.entry.js} +1 -1
  104. package/dist/db-ux/{p-ee43015b.entry.js → p-c76089f6.entry.js} +1 -1
  105. package/dist/db-ux/{p-44a0407b.entry.js → p-c7bf8d05.entry.js} +1 -1
  106. package/dist/db-ux/{p-43a9623f.entry.js → p-d85b1c15.entry.js} +1 -1
  107. package/dist/db-ux/{p-d93b9d58.entry.js → p-d8b38722.entry.js} +1 -1
  108. package/dist/db-ux/p-dd08f6e4.entry.js +1 -0
  109. package/dist/esm/db-accordion-item.entry.js +2 -2
  110. package/dist/esm/db-accordion.entry.js +1 -1
  111. package/dist/esm/db-badge.entry.js +1 -1
  112. package/dist/esm/db-brand.entry.js +1 -1
  113. package/dist/esm/db-button.entry.js +1 -1
  114. package/dist/esm/db-card.entry.js +2 -2
  115. package/dist/esm/db-checkbox.entry.js +2 -2
  116. package/dist/esm/db-custom-button.entry.js +2 -2
  117. package/dist/esm/db-custom-select-dropdown_5.entry.js +9 -9
  118. package/dist/esm/db-custom-select-form-field.entry.js +2 -2
  119. package/dist/esm/db-custom-select.entry.js +5 -5
  120. package/dist/esm/db-divider.entry.js +1 -1
  121. package/dist/esm/db-drawer.entry.js +3 -3
  122. package/dist/esm/db-header.entry.js +2 -2
  123. package/dist/esm/db-icon.entry.js +1 -1
  124. package/dist/esm/db-infotext.entry.js +1 -1
  125. package/dist/esm/db-link.entry.js +1 -1
  126. package/dist/esm/db-navigation-item.entry.js +1 -1
  127. package/dist/esm/db-navigation.entry.js +2 -2
  128. package/dist/esm/db-notification.entry.js +2 -2
  129. package/dist/esm/db-page.entry.js +2 -2
  130. package/dist/esm/db-popover.entry.js +2 -2
  131. package/dist/esm/db-radio.entry.js +1 -1
  132. package/dist/esm/db-section.entry.js +2 -2
  133. package/dist/esm/db-select.entry.js +2 -2
  134. package/dist/esm/db-stack.entry.js +2 -2
  135. package/dist/esm/db-switch.entry.js +2 -2
  136. package/dist/esm/db-tab-item_3.entry.js +68 -134
  137. package/dist/esm/db-tabs.entry.js +123 -373
  138. package/dist/esm/db-textarea.entry.js +2 -2
  139. package/dist/esm/db-tooltip.entry.js +5 -4
  140. package/dist/esm/db-ux.js +1 -1
  141. package/dist/esm/index.js +2 -2
  142. package/dist/esm/loader.js +1 -1
  143. package/dist/types/components/tab-item/model.d.ts +11 -28
  144. package/dist/types/components/tab-item/tab-item.d.ts +20 -22
  145. package/dist/types/components/tab-list/model.d.ts +5 -15
  146. package/dist/types/components/tab-list/tab-list.d.ts +1 -4
  147. package/dist/types/components/tab-panel/model.d.ts +3 -13
  148. package/dist/types/components/tab-panel/tab-panel.d.ts +0 -3
  149. package/dist/types/components/tabs/model.d.ts +17 -51
  150. package/dist/types/components/tabs/tabs.d.ts +16 -35
  151. package/dist/types/components.d.ts +30 -80
  152. package/dist/types/shared/model.d.ts +5 -5
  153. package/dist/vscode.html-custom-data.json +59 -147
  154. package/dist/web-types.json +135 -289
  155. package/package.json +3 -3
  156. package/dist/db-ux/p-10869bfa.entry.js +0 -1
  157. package/dist/db-ux/p-1427bb15.entry.js +0 -1
  158. package/dist/db-ux/p-397bc590.entry.js +0 -1
  159. package/dist/db-ux/p-68835a75.entry.js +0 -1
  160. package/dist/db-ux/p-68a995df.entry.js +0 -1
  161. package/dist/db-ux/p-6e898a58.entry.js +0 -1
  162. package/dist/db-ux/p-71868bb5.entry.js +0 -1
  163. package/dist/db-ux/p-9b4d0c18.entry.js +0 -1
  164. package/dist/db-ux/p-a927fe88.entry.js +0 -1
  165. package/dist/db-ux/p-a93ca690.entry.js +0 -1
  166. package/dist/db-ux/p-d97c0787.entry.js +0 -1
  167. package/dist/db-ux/p-efde1b6e.entry.js +0 -1
  168. package/dist/db-ux/p-f92cbbae.entry.js +0 -1
@@ -6,321 +6,130 @@ import { h, Fragment, } from "@stencil/core";
6
6
  */
7
7
  export class DBTabs {
8
8
  constructor() {
9
- this.tabItemAlignment = "start";
10
- this.tabItemWidth = "auto";
11
- this.scrollStartLabel = "Scroll start";
12
- this.scrollEndLabel = "Scroll end";
13
- this._generatedId = "tabs-" + uuid();
14
- this._generatedName = uuid();
15
- this.activeTabIndex = 0;
9
+ this._name = "";
16
10
  this.initialized = false;
17
- this.showScrollStart = false;
18
- this.showScrollEnd = false;
19
- this._resizeObserver = null;
20
- this._observer = null;
21
- this._pendingRafId = null;
22
- this._scrollListener = null;
23
- this._cachedTabs = [];
11
+ this.showScrollLeft = false;
12
+ this.showScrollRight = false;
13
+ this.scrollContainer = null;
14
+ this._resizeObserver = undefined;
24
15
  }
25
- _id() {
26
- return this.id || this._generatedId;
27
- }
28
- _name() {
29
- return "tabs-" + (this.name || this._generatedName);
30
- }
31
- getTabId(index) {
32
- return `${this._name()}-tab-${index}`;
33
- }
34
- getPanelId(index) {
35
- return `${this._name()}-tab-panel-${index}`;
36
- }
37
- activateTab(index) {
38
- var _a, _b, _c;
39
- // Prevent activating a disabled tab
40
- if (this._ref) {
41
- const tabList = this._ref.querySelector('[role="tablist"]');
42
- if (tabList) {
43
- const tabs = Array.from(tabList.querySelectorAll('[role="tab"]'));
44
- const tab = tabs[index];
45
- if ((tab === null || tab === void 0 ? void 0 : tab.disabled) || (tab === null || tab === void 0 ? void 0 : tab.getAttribute("aria-disabled")) === "true") {
46
- return;
47
- }
48
- }
49
- }
50
- if (this.activeTabIndex !== index) {
51
- this.activeTabIndex = index;
52
- if (this.indexChange) {
53
- this.indexChange.emit(index);
54
- }
55
- // Emit value of the newly active tab item if value props are set
56
- if (this.valueChange) {
57
- const tabList = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]');
58
- const tabs = tabList
59
- ? Array.from(tabList.querySelectorAll('[role="tab"]'))
60
- : [];
61
- const value = (_c = (_b = tabs[index]) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c["value"];
62
- this.valueChange.emit(value);
63
- }
64
- this.initTabs(index);
65
- }
66
- }
67
- handleClick(event) {
68
- var _a;
69
- // In props-mode (props.tabs), tab activation is handled via onClick on each DBTabItem directly.
70
- // In slot-mode (!props.tabs), clicks bubble up and are handled here via DOM traversal.
71
- if (this.tabs) {
72
- return;
73
- }
74
- const target = event.target;
75
- const button = target.closest('[role="tab"]');
76
- if (!button || !this._ref)
77
- return;
78
- const tabList = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]');
79
- if (!tabList)
80
- return;
81
- const buttons = Array.from(tabList.querySelectorAll('[role="tab"]'));
82
- const index = buttons.indexOf(button);
83
- if (index !== -1) {
84
- event.preventDefault();
85
- this.activateTab(index);
86
- }
87
- }
88
- handleKeyDown(event) {
89
- var _a;
90
- if (!this._ref)
91
- return;
92
- const key = event.key;
93
- const navigationKeys = [
94
- "ArrowRight",
95
- "ArrowDown",
96
- "ArrowLeft",
97
- "ArrowUp",
98
- "Home",
99
- "End",
100
- "Enter",
101
- " ",
102
- ];
103
- if (!navigationKeys.includes(key)) {
104
- return;
105
- }
106
- const tabList = this._ref.querySelector('[role="tablist"]');
107
- if (!tabList)
108
- return;
109
- const buttons = Array.from(tabList.querySelectorAll('[role="tab"]'));
110
- // find currently focused element within the buttons list
111
- let currentIndex = -1;
112
- if (typeof document !== "undefined") {
113
- // Traverse Shadow DOM boundaries to find the truly focused element.
114
- // document.activeElement only returns the shadow host when focus is inside a Shadow DOM,
115
- // so we must walk through each shadowRoot to reach the actual focused element.
116
- let activeEl = document.activeElement;
117
- while ((_a = activeEl === null || activeEl === void 0 ? void 0 : activeEl.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement) {
118
- activeEl = activeEl.shadowRoot.activeElement;
119
- }
120
- if (activeEl) {
121
- const focusedButton = activeEl.closest('[role="tab"]');
122
- if (focusedButton) {
123
- currentIndex = buttons.indexOf(focusedButton);
124
- }
125
- }
126
- }
127
- if (currentIndex === -1) {
128
- currentIndex = this.activeTabIndex;
129
- }
130
- if (buttons.length > 0) {
131
- // handle activation (enter / space) -> change panel
132
- if (key === "Enter" || key === " ") {
133
- event.preventDefault();
134
- this.activateTab(currentIndex);
135
- return;
136
- }
137
- // handle navigation (arrows) -> moves focus
138
- let nextIndex;
139
- const length = buttons.length;
140
- if (key === "ArrowRight" || key === "ArrowDown") {
141
- nextIndex = (currentIndex + 1) % length;
142
- }
143
- else if (key === "ArrowLeft" || key === "ArrowUp") {
144
- nextIndex = (currentIndex - 1 + length) % length;
145
- }
146
- else if (key === "Home") {
147
- nextIndex = 0;
148
- }
149
- else if (key === "End") {
150
- nextIndex = length - 1;
151
- }
152
- if (nextIndex !== undefined) {
153
- event.preventDefault();
154
- // Skip disabled tabs when navigating with arrow keys
155
- const isForward = key === "ArrowRight" || key === "ArrowDown";
156
- const maxAttempts = length;
157
- for (let i = 0; i < maxAttempts; i++) {
158
- const candidate = buttons[nextIndex];
159
- if (!(candidate === null || candidate === void 0 ? void 0 : candidate.disabled) &&
160
- (candidate === null || candidate === void 0 ? void 0 : candidate.getAttribute("aria-disabled")) !== "true") {
161
- break;
162
- }
163
- if (isForward) {
164
- nextIndex = (nextIndex + 1) % length;
165
- }
166
- else {
167
- nextIndex = (nextIndex - 1 + length) % length;
168
- }
169
- }
170
- // do not activateTab here for manual activation, just move the focus
171
- const nextButton = buttons[nextIndex];
172
- if (nextButton &&
173
- !nextButton.disabled &&
174
- nextButton.getAttribute("aria-disabled") !== "true") {
175
- nextButton.focus();
176
- }
177
- }
178
- }
179
- }
180
- isIndexActive(index) {
181
- return this.activeTabIndex === Number(index);
182
- }
183
- getTabItemTabIndex(index) {
184
- const i = Number(index);
185
- // only the active tab should be reachable via Tab key
186
- return this.activeTabIndex === i || (this.activeTabIndex === -1 && i === 0)
187
- ? 0
188
- : -1;
189
- }
190
- _updateCachedTabs() {
16
+ convertTabs() {
191
17
  try {
192
18
  if (typeof this.tabs === "string") {
193
- this._cachedTabs = JSON.parse(this.tabs);
194
- }
195
- else if (this.tabs) {
196
- this._cachedTabs = this.tabs;
197
- }
198
- else {
199
- this._cachedTabs = [];
19
+ return JSON.parse(this.tabs);
200
20
  }
21
+ return this.tabs;
201
22
  }
202
23
  catch (error) {
203
24
  console.error(error);
204
- this._cachedTabs = [];
205
25
  }
206
- }
207
- _getScrollContainer() {
208
- var _a, _b;
209
- return (_b = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]')) !== null && _b !== void 0 ? _b : null;
210
- }
211
- _isRtl() {
212
- const container = this._getScrollContainer();
213
- return (!!container &&
214
- typeof getComputedStyle !== "undefined" &&
215
- getComputedStyle(container).direction === "rtl");
26
+ return [];
216
27
  }
217
28
  evaluateScrollButtons(tList) {
218
29
  const needsScroll = tList.scrollWidth > tList.clientWidth;
219
- if (!needsScroll) {
220
- this.showScrollStart = false;
221
- this.showScrollEnd = false;
222
- return;
223
- }
224
- const scrollPos = Math.abs(tList.scrollLeft);
225
- const maxScroll = tList.scrollWidth - tList.clientWidth;
226
- const tolerance = 2;
227
- // scrollPos=0 means "at inline-start" in both LTR and RTL
228
- this.showScrollStart = scrollPos > tolerance;
229
- this.showScrollEnd = scrollPos < maxScroll - tolerance;
30
+ this.showScrollLeft = needsScroll && tList.scrollLeft > 1;
31
+ this.showScrollRight =
32
+ needsScroll && tList.scrollLeft < tList.scrollWidth - tList.clientWidth;
230
33
  }
231
- scroll(toStart) {
232
- const container = this._getScrollContainer();
233
- if (!container) {
234
- return;
235
- }
236
- let step = Number(this.arrowScrollDistance) || 120;
237
- const isLeft = !!toStart;
238
- const isRtl = this._isRtl();
239
- // Map logical direction (start/end) to physical direction.
240
- // In LTR: toStart=true → scroll left (negative), toEnd → scroll right (positive).
241
- // In RTL: directions are inverted physically.
242
- if (isLeft !== isRtl) {
34
+ scroll(left) {
35
+ var _a;
36
+ let step = Number(this.arrowScrollDistance) || 100;
37
+ if (left) {
243
38
  step *= -1;
244
39
  }
245
- container.scrollBy({
40
+ (_a = this.scrollContainer) === null || _a === void 0 ? void 0 : _a.scrollBy({
41
+ top: 0,
246
42
  left: step,
247
43
  behavior: "smooth",
248
44
  });
249
45
  }
250
46
  initTabList() {
251
- var _a, _b;
252
47
  if (this._ref) {
253
- const container = this._ref.querySelector('[role="tablist"]');
254
- if (container) {
255
- if (!container.getAttribute("aria-orientation")) {
256
- container.setAttribute("aria-orientation", (_a = this.orientation) !== null && _a !== void 0 ? _a : "horizontal");
257
- }
258
- if (this.behavior === "arrows") {
259
- this.evaluateScrollButtons(container);
260
- const _listener = this._scrollListener;
261
- if (_listener && container) {
262
- container.removeEventListener("scroll", _listener.fn);
263
- this._scrollListener = null;
264
- }
265
- const onScroll = () => this.evaluateScrollButtons(container);
266
- this._scrollListener = {
267
- fn: onScroll,
268
- };
269
- container.addEventListener("scroll", onScroll);
270
- if (!this._resizeObserver) {
271
- const observer = new ResizeObserver(() => {
48
+ const tabList = this._ref.querySelector(".db-tab-list");
49
+ if (tabList) {
50
+ const container = tabList.querySelector('[role="tablist"]');
51
+ if (container) {
52
+ container.setAttribute("aria-orientation", this.orientation || "horizontal");
53
+ if (this.behavior === "arrows") {
54
+ this.scrollContainer = container;
55
+ this.evaluateScrollButtons(container);
56
+ container.addEventListener("scroll", () => {
272
57
  this.evaluateScrollButtons(container);
273
58
  });
274
- observer.observe(container);
275
- this._resizeObserver = observer;
59
+ // Use ResizeObserver to re-evaluate scroll buttons because it provides more accurate, container-specific resize detection than global window resize events.
60
+ if (!this._resizeObserver) {
61
+ const observer = new ResizeObserver(() => {
62
+ this.evaluateScrollButtons(container);
63
+ });
64
+ observer.observe(container);
65
+ this._resizeObserver = observer;
66
+ }
276
67
  }
277
68
  }
278
- if (this.name && !container.getAttribute("aria-label")) {
279
- container.setAttribute("aria-label", (_b = this.name) !== null && _b !== void 0 ? _b : "");
280
- }
281
69
  }
282
70
  }
283
71
  }
284
- initTabs(activeIndex) {
285
- var _a, _b;
286
- const currentIndex = activeIndex !== undefined ? activeIndex : this.activeTabIndex;
72
+ initTabs(init) {
287
73
  if (this._ref) {
288
- const tabListEl = this._ref.querySelector('[role="tablist"]');
289
- const panels = Array.from((_b = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelectorAll('[role="tabpanel"]')) !== null && _b !== void 0 ? _b : []).filter((panel) => panel.closest(".db-tabs") === this._ref);
290
- if (!tabListEl)
291
- return;
292
- const buttons = Array.from(tabListEl.querySelectorAll('[role="tab"]'));
293
- buttons.forEach((button, index) => {
294
- const isSelected = currentIndex === index;
295
- const panel = panels[index];
296
- const tabId = button.id || this.getTabId(index);
297
- const panelId = (panel === null || panel === void 0 ? void 0 : panel.id) || this.getPanelId(index);
298
- if (!button.id) {
299
- button.id = tabId;
300
- }
301
- if (!button.getAttribute("aria-controls")) {
302
- button.setAttribute("aria-controls", panelId);
303
- }
304
- button.dispatchEvent(new CustomEvent("aria-selected-changed", {
305
- detail: {
306
- selected: isSelected,
307
- tabIndex: currentIndex === index || (currentIndex === -1 && index === 0)
308
- ? 0
309
- : -1,
310
- },
311
- }));
312
- if (panel) {
313
- if (!panel.id) {
314
- panel.id = panelId;
74
+ const tabItems = Array.from(this._ref.getElementsByClassName("db-tab-item"));
75
+ const tabPanels = Array.from(this._ref.querySelectorAll(":is(:scope > .db-tab-panel, :scope > db-tab-panel > .db-tab-panel)"));
76
+ for (const tabItem of tabItems) {
77
+ const index = tabItems.indexOf(tabItem);
78
+ const label = tabItem.querySelector("label");
79
+ const input = tabItem.querySelector("input");
80
+ if (input && label) {
81
+ if (!input.id) {
82
+ const tabId = `${this._name}-tab-${index}`;
83
+ label.setAttribute("for", tabId);
84
+ input.id = tabId;
85
+ input.setAttribute("name", this._name);
86
+ if (tabPanels.length > index) {
87
+ input.setAttribute("aria-controls", `${this._name}-tab-panel-${index}`);
88
+ }
315
89
  }
316
- if (!panel.getAttribute("aria-label") &&
317
- !panel.getAttribute("aria-labelledby")) {
318
- panel.setAttribute("aria-labelledby", tabId);
90
+ if (init) {
91
+ // Auto select
92
+ const autoSelect = !this.initialSelectedMode || this.initialSelectedMode === "auto";
93
+ const shouldAutoSelect = (this.initialSelectedIndex == null && index === 0) ||
94
+ Number(this.initialSelectedIndex) === index;
95
+ if (autoSelect && shouldAutoSelect) {
96
+ input.click();
97
+ }
319
98
  }
320
- // toggle visibility
321
- panel.hidden = !isSelected;
322
99
  }
323
- });
100
+ }
101
+ for (const panel of tabPanels) {
102
+ if (panel.id)
103
+ continue;
104
+ const index = tabPanels.indexOf(panel);
105
+ panel.id = `${this._name}-tab-panel-${index}`;
106
+ panel.setAttribute("aria-labelledby", `${this._name}-tab-${index}`);
107
+ }
108
+ }
109
+ }
110
+ handleChange(event) {
111
+ var _a;
112
+ event.stopPropagation();
113
+ if (event.target) {
114
+ const target = event.target;
115
+ const parent = target.parentElement;
116
+ if (parent &&
117
+ parent.parentElement &&
118
+ ((_a = parent.parentElement) === null || _a === void 0 ? void 0 : _a.nodeName) === "LI") {
119
+ const tabItem = parent.parentElement.parentElement;
120
+ if (tabItem) {
121
+ const list = tabItem.parentElement;
122
+ if (list) {
123
+ const tabIndex = Array.from(list.children).indexOf(tabItem);
124
+ if (this.indexChange) {
125
+ this.indexChange.emit(tabIndex);
126
+ }
127
+ if (this.tabSelect) {
128
+ this.tabSelect.emit(event);
129
+ }
130
+ }
131
+ }
132
+ }
324
133
  }
325
134
  }
326
135
  /**
@@ -360,162 +169,51 @@ export class DBTabs {
360
169
  }
361
170
  }
362
171
  watch0Fn() {
363
- this._updateCachedTabs();
364
- }
365
- watch0() {
366
- this.watch0Fn();
367
- }
368
- watch1Fn() {
369
- if (this.activeIndex !== undefined) {
370
- const newIndex = Number(this.activeIndex);
371
- if (!isNaN(newIndex) && newIndex !== this.activeTabIndex) {
372
- this.activateTab(newIndex);
373
- }
374
- }
375
- }
376
- watch1() {
377
- this.watch1Fn();
378
- }
379
- componentDidLoad() {
380
- this.enableAttributePassing(this._ref, "db-tabs");
381
- // 1. Calculate final start index synchronously to avoid race conditions
382
- let startIndex = 0;
383
- if (this.initialSelectedIndex !== undefined) {
384
- const parsedIndex = Number(this.initialSelectedIndex);
385
- startIndex = isNaN(parsedIndex) ? 0 : parsedIndex;
386
- }
387
- else if (this.initialSelectedMode === "manually") {
388
- startIndex = -1;
389
- }
390
- // 2. Support deep linking: URL hash takes precedence over initial index
391
- if (typeof window !== "undefined" && window.location.hash) {
392
- const hashId = window.location.hash.substring(1);
393
- const name = this.name ? "tabs-" + this.name : this._name();
394
- const prefix = `${name}-tab-`;
395
- if (hashId.startsWith(prefix)) {
396
- const indexStr = hashId.replace(prefix, "");
397
- const index = parseInt(indexStr, 10);
398
- if (!isNaN(index)) {
399
- startIndex = index;
400
- }
401
- }
402
- }
403
- // 3. Set initial state synchronously
404
- this.activeTabIndex = startIndex;
405
- this.initialized = true;
406
- this._updateCachedTabs();
407
- // 4. Trigger single initial DOM update after paint
408
- if (typeof window !== "undefined") {
409
- requestAnimationFrame(() => {
410
- this.initTabList();
411
- this.initTabs(startIndex);
412
- });
413
- }
414
- if (this._ref) {
415
- const tabListEl = this._ref.querySelector('[role="tablist"]');
416
- if (tabListEl) {
417
- const observer = new MutationObserver(() => {
418
- const rafId = this._pendingRafId;
419
- if (rafId !== null)
420
- cancelAnimationFrame(rafId);
421
- this._pendingRafId = requestAnimationFrame(() => {
422
- this._pendingRafId = null;
423
- this.initTabList();
424
- this.initTabs(this.activeTabIndex);
172
+ if (this._ref && this.initialized) {
173
+ this.initTabList();
174
+ this.initTabs(true);
175
+ const tabList = this._ref.querySelector(".db-tab-list");
176
+ if (tabList) {
177
+ const observer = new MutationObserver((mutations) => {
178
+ mutations.forEach((mutation) => {
179
+ if (mutation.removedNodes.length || mutation.addedNodes.length) {
180
+ this.initTabList();
181
+ this.initTabs();
182
+ }
425
183
  });
426
184
  });
427
- // Observe only the tablist (not panel content) to avoid unnecessary
428
- // re-evaluations when user content inside panels changes.
429
- // childList only – attribute changes (set by initTabs) are not observed, preventing infinite loops.
430
- observer.observe(tabListEl, {
185
+ observer.observe(tabList, {
431
186
  childList: true,
432
187
  subtree: true,
433
188
  });
434
- this._observer = observer;
435
189
  }
190
+ this.initialized = false;
436
191
  }
192
+ }
193
+ watch0() {
194
+ this.watch0Fn();
195
+ }
196
+ componentDidLoad() {
197
+ this.enableAttributePassing(this._ref, "db-tabs");
198
+ this._name = `tabs-${this.name || uuid()}`;
199
+ this.initialized = true;
437
200
  this.watch0Fn();
438
- this.watch1Fn();
439
201
  }
440
202
  disconnectedCallback() {
441
- var _a, _b;
442
- const rafId = this._pendingRafId;
443
- if (rafId !== null) {
444
- cancelAnimationFrame(rafId);
445
- this._pendingRafId = null;
446
- }
447
- const _listener = this._scrollListener;
448
- const _container = this._getScrollContainer();
449
- if (_listener && _container) {
450
- _container.removeEventListener("scroll", _listener.fn);
451
- }
203
+ var _a;
452
204
  (_a = this._resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
453
- this._resizeObserver = null;
454
- (_b = this._observer) === null || _b === void 0 ? void 0 : _b.disconnect();
455
- this._observer = null;
205
+ this._resizeObserver = undefined;
456
206
  }
457
207
  render() {
458
- var _a, _b, _c, _d, _e;
459
- return (h("div", { key: '8d9608e7d9255b3bc138ee4c50f1fdfb0b09ba72', class: cls("db-tabs", this.className), ref: (el) => {
208
+ var _a, _b, _c, _d, _e, _f;
209
+ return (h("div", { key: '20d8d662866ff60717de87ad4deb98a3b647672a', class: cls("db-tabs", this.className), ref: (el) => {
460
210
  this._ref = el;
461
- }, id: (_c = (_a = this.id) !== null && _a !== void 0 ? _a : (_b = this.propOverrides) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : this._id(), "data-orientation": this.orientation, "data-scroll-behavior": this.behavior, "data-tab-item-alignment": this.tabItemAlignment, "data-tab-item-width": this.tabItemWidth, onClick: (event) => this.handleClick(event), onKeyDown: (event) => this.handleKeyDown(event) }, this.showScrollStart ? (h("db-button", { class: "tabs-scroll-start", variant: "ghost", icon: "chevron_left", type: "button", noText: true, onClick: () => this.scroll(true) }, this.scrollStartLabel)) : null, this.tabs ? (h(Fragment, null, h("db-tab-list", { orientation: this.orientation, ariaLabel: this.name }, (_d = this._cachedTabs) === null || _d === void 0 ? void 0 : _d.map((tab, index) => (h("db-tab-item", { key: this.name + "tab-item" + index, id: this.getTabId(index), ariaControls: this.getPanelId(index), active: this.isIndexActive(index), tabIndex: this.getTabItemTabIndex(index), label: tab.label, iconTrailing: tab.iconTrailing, icon: tab.icon, noText: tab.noText, onClick: () => this.activateTab(index) })))), (_e = this._cachedTabs) === null || _e === void 0 ? void 0 :
462
- _e.map((tab, index) => (h("db-tab-panel", { key: this.name + "tab-panel" + index, id: this.getPanelId(index), ariaLabelledby: this.getTabId(index), content: tab.content, hidden: !this.isIndexActive(index) }, tab.children))))) : null, !this.tabs ? h("slot", null) : null, this.showScrollEnd ? (h("db-button", { class: "tabs-scroll-end", variant: "ghost", icon: "chevron_right", type: "button", noText: true, onClick: () => this.scroll(false) }, this.scrollEndLabel)) : null));
211
+ }, id: (_a = this.id) !== null && _a !== void 0 ? _a : (_b = this.propOverrides) === null || _b === void 0 ? void 0 : _b.id, "data-orientation": this.orientation, "data-scroll-behavior": this.behavior, "data-alignment": (_c = this.alignment) !== null && _c !== void 0 ? _c : "start", "data-width": (_d = this.width) !== null && _d !== void 0 ? _d : "auto", onInput: (event) => this.handleChange(event), onChange: (event) => this.handleChange(event) }, this.showScrollLeft ? (h("db-button", { class: "tabs-scroll-left", variant: "ghost", icon: "chevron_left", type: "button", noText: true, onClick: () => this.scroll(true) }, "Scroll left")) : null, this.tabs ? (h(Fragment, null, h("db-tab-list", null, (_e = this.convertTabs()) === null || _e === void 0 ? void 0 : _e.map((tab, index) => (h("db-tab-item", { key: this.name + "tab-item" + index, active: tab.active, label: tab.label, iconTrailing: tab.iconTrailing, icon: tab.icon, noText: tab.noText })))), (_f = this.convertTabs()) === null || _f === void 0 ? void 0 :
212
+ _f.map((tab, index) => (h("db-tab-panel", { key: this.name + "tab-panel" + index, content: tab.content }, tab.children))))) : null, this.showScrollRight ? (h("db-button", { class: "tabs-scroll-right", variant: "ghost", icon: "chevron_right", type: "button", noText: true, onClick: () => this.scroll() }, "Scroll right")) : null, h("slot", { key: 'f9803a647f9a01adc0b20eb6bdb999f38c3602af' })));
463
213
  }
464
214
  static get is() { return "db-tabs"; }
465
215
  static get properties() {
466
216
  return {
467
- "initialSelectedIndex": {
468
- "type": "any",
469
- "mutable": false,
470
- "complexType": {
471
- "original": "DBTabsProps[\"initialSelectedIndex\"]",
472
- "resolved": "number | string",
473
- "references": {
474
- "DBTabsProps": {
475
- "location": "import",
476
- "path": "./model",
477
- "id": "src/components/tabs/model.ts::DBTabsProps",
478
- "referenceLocation": "DBTabsProps"
479
- }
480
- }
481
- },
482
- "required": false,
483
- "optional": false,
484
- "docs": {
485
- "tags": [],
486
- "text": ""
487
- },
488
- "getter": false,
489
- "setter": false,
490
- "reflect": false,
491
- "attribute": "initial-selected-index"
492
- },
493
- "initialSelectedMode": {
494
- "type": "string",
495
- "mutable": false,
496
- "complexType": {
497
- "original": "DBTabsProps[\"initialSelectedMode\"]",
498
- "resolved": "\"auto\" | \"manually\"",
499
- "references": {
500
- "DBTabsProps": {
501
- "location": "import",
502
- "path": "./model",
503
- "id": "src/components/tabs/model.ts::DBTabsProps",
504
- "referenceLocation": "DBTabsProps"
505
- }
506
- }
507
- },
508
- "required": false,
509
- "optional": false,
510
- "docs": {
511
- "tags": [],
512
- "text": ""
513
- },
514
- "getter": false,
515
- "setter": false,
516
- "reflect": false,
517
- "attribute": "initial-selected-mode"
518
- },
519
217
  "name": {
520
218
  "type": "string",
521
219
  "mutable": false,
@@ -568,11 +266,11 @@ export class DBTabs {
568
266
  "reflect": false,
569
267
  "attribute": "tabs"
570
268
  },
571
- "activeIndex": {
269
+ "arrowScrollDistance": {
572
270
  "type": "any",
573
271
  "mutable": false,
574
272
  "complexType": {
575
- "original": "DBTabsProps[\"activeIndex\"]",
273
+ "original": "DBTabsProps[\"arrowScrollDistance\"]",
576
274
  "resolved": "number | string",
577
275
  "references": {
578
276
  "DBTabsProps": {
@@ -592,14 +290,14 @@ export class DBTabs {
592
290
  "getter": false,
593
291
  "setter": false,
594
292
  "reflect": false,
595
- "attribute": "active-index"
293
+ "attribute": "arrow-scroll-distance"
596
294
  },
597
- "id": {
295
+ "orientation": {
598
296
  "type": "string",
599
297
  "mutable": false,
600
298
  "complexType": {
601
- "original": "DBTabsProps[\"id\"]",
602
- "resolved": "string",
299
+ "original": "DBTabsProps[\"orientation\"]",
300
+ "resolved": "\"horizontal\" | \"vertical\"",
603
301
  "references": {
604
302
  "DBTabsProps": {
605
303
  "location": "import",
@@ -618,14 +316,14 @@ export class DBTabs {
618
316
  "getter": false,
619
317
  "setter": false,
620
318
  "reflect": false,
621
- "attribute": "id"
319
+ "attribute": "orientation"
622
320
  },
623
- "arrowScrollDistance": {
624
- "type": "any",
321
+ "behavior": {
322
+ "type": "string",
625
323
  "mutable": false,
626
324
  "complexType": {
627
- "original": "DBTabsProps[\"arrowScrollDistance\"]",
628
- "resolved": "number | string",
325
+ "original": "DBTabsProps[\"behavior\"]",
326
+ "resolved": "\"arrows\" | \"scrollbar\"",
629
327
  "references": {
630
328
  "DBTabsProps": {
631
329
  "location": "import",
@@ -644,14 +342,14 @@ export class DBTabs {
644
342
  "getter": false,
645
343
  "setter": false,
646
344
  "reflect": false,
647
- "attribute": "arrow-scroll-distance"
345
+ "attribute": "behavior"
648
346
  },
649
- "orientation": {
347
+ "initialSelectedMode": {
650
348
  "type": "string",
651
349
  "mutable": false,
652
350
  "complexType": {
653
- "original": "DBTabsProps[\"orientation\"]",
654
- "resolved": "\"horizontal\" | \"vertical\"",
351
+ "original": "DBTabsProps[\"initialSelectedMode\"]",
352
+ "resolved": "\"auto\" | \"manually\"",
655
353
  "references": {
656
354
  "DBTabsProps": {
657
355
  "location": "import",
@@ -670,14 +368,14 @@ export class DBTabs {
670
368
  "getter": false,
671
369
  "setter": false,
672
370
  "reflect": false,
673
- "attribute": "orientation"
371
+ "attribute": "initial-selected-mode"
674
372
  },
675
- "behavior": {
676
- "type": "string",
373
+ "initialSelectedIndex": {
374
+ "type": "any",
677
375
  "mutable": false,
678
376
  "complexType": {
679
- "original": "DBTabsProps[\"behavior\"]",
680
- "resolved": "\"arrows\" | \"scrollbar\"",
377
+ "original": "DBTabsProps[\"initialSelectedIndex\"]",
378
+ "resolved": "number | string",
681
379
  "references": {
682
380
  "DBTabsProps": {
683
381
  "location": "import",
@@ -696,37 +394,13 @@ export class DBTabs {
696
394
  "getter": false,
697
395
  "setter": false,
698
396
  "reflect": false,
699
- "attribute": "behavior"
700
- },
701
- "propOverrides": {
702
- "type": "unknown",
703
- "mutable": false,
704
- "complexType": {
705
- "original": "DBTabsProps[\"propOverrides\"]",
706
- "resolved": "{ id?: string; }",
707
- "references": {
708
- "DBTabsProps": {
709
- "location": "import",
710
- "path": "./model",
711
- "id": "src/components/tabs/model.ts::DBTabsProps",
712
- "referenceLocation": "DBTabsProps"
713
- }
714
- }
715
- },
716
- "required": false,
717
- "optional": false,
718
- "docs": {
719
- "tags": [],
720
- "text": ""
721
- },
722
- "getter": false,
723
- "setter": false
397
+ "attribute": "initial-selected-index"
724
398
  },
725
- "className": {
399
+ "id": {
726
400
  "type": "string",
727
401
  "mutable": false,
728
402
  "complexType": {
729
- "original": "DBTabsProps[\"className\"]",
403
+ "original": "DBTabsProps[\"id\"]",
730
404
  "resolved": "string",
731
405
  "references": {
732
406
  "DBTabsProps": {
@@ -746,14 +420,14 @@ export class DBTabs {
746
420
  "getter": false,
747
421
  "setter": false,
748
422
  "reflect": false,
749
- "attribute": "classname"
423
+ "attribute": "id"
750
424
  },
751
- "tabItemAlignment": {
752
- "type": "string",
425
+ "propOverrides": {
426
+ "type": "unknown",
753
427
  "mutable": false,
754
428
  "complexType": {
755
- "original": "DBTabsProps[\"tabItemAlignment\"]",
756
- "resolved": "string",
429
+ "original": "DBTabsProps[\"propOverrides\"]",
430
+ "resolved": "{ id?: string; }",
757
431
  "references": {
758
432
  "DBTabsProps": {
759
433
  "location": "import",
@@ -770,16 +444,13 @@ export class DBTabs {
770
444
  "text": ""
771
445
  },
772
446
  "getter": false,
773
- "setter": false,
774
- "reflect": false,
775
- "attribute": "tab-item-alignment",
776
- "defaultValue": "\"start\""
447
+ "setter": false
777
448
  },
778
- "tabItemWidth": {
449
+ "className": {
779
450
  "type": "string",
780
451
  "mutable": false,
781
452
  "complexType": {
782
- "original": "DBTabsProps[\"tabItemWidth\"]",
453
+ "original": "DBTabsProps[\"className\"]",
783
454
  "resolved": "string",
784
455
  "references": {
785
456
  "DBTabsProps": {
@@ -799,14 +470,13 @@ export class DBTabs {
799
470
  "getter": false,
800
471
  "setter": false,
801
472
  "reflect": false,
802
- "attribute": "tab-item-width",
803
- "defaultValue": "\"auto\""
473
+ "attribute": "classname"
804
474
  },
805
- "scrollStartLabel": {
475
+ "alignment": {
806
476
  "type": "string",
807
477
  "mutable": false,
808
478
  "complexType": {
809
- "original": "DBTabsProps[\"scrollStartLabel\"]",
479
+ "original": "DBTabsProps[\"alignment\"]",
810
480
  "resolved": "string",
811
481
  "references": {
812
482
  "DBTabsProps": {
@@ -826,14 +496,13 @@ export class DBTabs {
826
496
  "getter": false,
827
497
  "setter": false,
828
498
  "reflect": false,
829
- "attribute": "scroll-start-label",
830
- "defaultValue": "\"Scroll start\""
499
+ "attribute": "alignment"
831
500
  },
832
- "scrollEndLabel": {
501
+ "width": {
833
502
  "type": "string",
834
503
  "mutable": false,
835
504
  "complexType": {
836
- "original": "DBTabsProps[\"scrollEndLabel\"]",
505
+ "original": "DBTabsProps[\"width\"]",
837
506
  "resolved": "string",
838
507
  "references": {
839
508
  "DBTabsProps": {
@@ -853,24 +522,18 @@ export class DBTabs {
853
522
  "getter": false,
854
523
  "setter": false,
855
524
  "reflect": false,
856
- "attribute": "scroll-end-label",
857
- "defaultValue": "\"Scroll end\""
525
+ "attribute": "width"
858
526
  }
859
527
  };
860
528
  }
861
529
  static get states() {
862
530
  return {
863
- "_generatedId": {},
864
- "_generatedName": {},
865
- "activeTabIndex": {},
531
+ "_name": {},
866
532
  "initialized": {},
867
- "showScrollStart": {},
868
- "showScrollEnd": {},
869
- "_resizeObserver": {},
870
- "_observer": {},
871
- "_pendingRafId": {},
872
- "_scrollListener": {},
873
- "_cachedTabs": {}
533
+ "showScrollLeft": {},
534
+ "showScrollRight": {},
535
+ "scrollContainer": {},
536
+ "_resizeObserver": {}
874
537
  };
875
538
  }
876
539
  static get events() {
@@ -890,8 +553,8 @@ export class DBTabs {
890
553
  "references": {}
891
554
  }
892
555
  }, {
893
- "method": "valueChange",
894
- "name": "valueChange",
556
+ "method": "tabSelect",
557
+ "name": "tabSelect",
895
558
  "bubbles": true,
896
559
  "cancelable": true,
897
560
  "composed": true,
@@ -908,11 +571,11 @@ export class DBTabs {
908
571
  }
909
572
  static get watchers() {
910
573
  return [{
911
- "propName": "tabs",
574
+ "propName": "_ref",
912
575
  "methodName": "watch0"
913
576
  }, {
914
- "propName": "activeIndex",
915
- "methodName": "watch1"
577
+ "propName": "initialized",
578
+ "methodName": "watch0"
916
579
  }];
917
580
  }
918
581
  }