@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
@@ -7,322 +7,131 @@ const DBTabs = class {
7
7
  constructor(hostRef) {
8
8
  index.registerInstance(this, hostRef);
9
9
  this.indexChange = index.createEvent(this, "indexChange");
10
- this.valueChange = index.createEvent(this, "valueChange");
11
- this.tabItemAlignment = "start";
12
- this.tabItemWidth = "auto";
13
- this.scrollStartLabel = "Scroll start";
14
- this.scrollEndLabel = "Scroll end";
15
- this._generatedId = "tabs-" + index$1.uuid();
16
- this._generatedName = index$1.uuid();
17
- this.activeTabIndex = 0;
10
+ this.tabSelect = index.createEvent(this, "tabSelect");
11
+ this._name = "";
18
12
  this.initialized = false;
19
- this.showScrollStart = false;
20
- this.showScrollEnd = false;
21
- this._resizeObserver = null;
22
- this._observer = null;
23
- this._pendingRafId = null;
24
- this._scrollListener = null;
25
- this._cachedTabs = [];
13
+ this.showScrollLeft = false;
14
+ this.showScrollRight = false;
15
+ this.scrollContainer = null;
16
+ this._resizeObserver = undefined;
26
17
  }
27
- _id() {
28
- return this.id || this._generatedId;
29
- }
30
- _name() {
31
- return "tabs-" + (this.name || this._generatedName);
32
- }
33
- getTabId(index) {
34
- return `${this._name()}-tab-${index}`;
35
- }
36
- getPanelId(index) {
37
- return `${this._name()}-tab-panel-${index}`;
38
- }
39
- activateTab(index) {
40
- var _a, _b, _c;
41
- // Prevent activating a disabled tab
42
- if (this._ref) {
43
- const tabList = this._ref.querySelector('[role="tablist"]');
44
- if (tabList) {
45
- const tabs = Array.from(tabList.querySelectorAll('[role="tab"]'));
46
- const tab = tabs[index];
47
- if ((tab === null || tab === void 0 ? void 0 : tab.disabled) || (tab === null || tab === void 0 ? void 0 : tab.getAttribute("aria-disabled")) === "true") {
48
- return;
49
- }
50
- }
51
- }
52
- if (this.activeTabIndex !== index) {
53
- this.activeTabIndex = index;
54
- if (this.indexChange) {
55
- this.indexChange.emit(index);
56
- }
57
- // Emit value of the newly active tab item if value props are set
58
- if (this.valueChange) {
59
- const tabList = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]');
60
- const tabs = tabList
61
- ? Array.from(tabList.querySelectorAll('[role="tab"]'))
62
- : [];
63
- const value = (_c = (_b = tabs[index]) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c["value"];
64
- this.valueChange.emit(value);
65
- }
66
- this.initTabs(index);
67
- }
68
- }
69
- handleClick(event) {
70
- var _a;
71
- // In props-mode (props.tabs), tab activation is handled via onClick on each DBTabItem directly.
72
- // In slot-mode (!props.tabs), clicks bubble up and are handled here via DOM traversal.
73
- if (this.tabs) {
74
- return;
75
- }
76
- const target = event.target;
77
- const button = target.closest('[role="tab"]');
78
- if (!button || !this._ref)
79
- return;
80
- const tabList = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]');
81
- if (!tabList)
82
- return;
83
- const buttons = Array.from(tabList.querySelectorAll('[role="tab"]'));
84
- const index = buttons.indexOf(button);
85
- if (index !== -1) {
86
- event.preventDefault();
87
- this.activateTab(index);
88
- }
89
- }
90
- handleKeyDown(event) {
91
- var _a;
92
- if (!this._ref)
93
- return;
94
- const key = event.key;
95
- const navigationKeys = [
96
- "ArrowRight",
97
- "ArrowDown",
98
- "ArrowLeft",
99
- "ArrowUp",
100
- "Home",
101
- "End",
102
- "Enter",
103
- " ",
104
- ];
105
- if (!navigationKeys.includes(key)) {
106
- return;
107
- }
108
- const tabList = this._ref.querySelector('[role="tablist"]');
109
- if (!tabList)
110
- return;
111
- const buttons = Array.from(tabList.querySelectorAll('[role="tab"]'));
112
- // find currently focused element within the buttons list
113
- let currentIndex = -1;
114
- if (typeof document !== "undefined") {
115
- // Traverse Shadow DOM boundaries to find the truly focused element.
116
- // document.activeElement only returns the shadow host when focus is inside a Shadow DOM,
117
- // so we must walk through each shadowRoot to reach the actual focused element.
118
- let activeEl = document.activeElement;
119
- while ((_a = activeEl === null || activeEl === void 0 ? void 0 : activeEl.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement) {
120
- activeEl = activeEl.shadowRoot.activeElement;
121
- }
122
- if (activeEl) {
123
- const focusedButton = activeEl.closest('[role="tab"]');
124
- if (focusedButton) {
125
- currentIndex = buttons.indexOf(focusedButton);
126
- }
127
- }
128
- }
129
- if (currentIndex === -1) {
130
- currentIndex = this.activeTabIndex;
131
- }
132
- if (buttons.length > 0) {
133
- // handle activation (enter / space) -> change panel
134
- if (key === "Enter" || key === " ") {
135
- event.preventDefault();
136
- this.activateTab(currentIndex);
137
- return;
138
- }
139
- // handle navigation (arrows) -> moves focus
140
- let nextIndex;
141
- const length = buttons.length;
142
- if (key === "ArrowRight" || key === "ArrowDown") {
143
- nextIndex = (currentIndex + 1) % length;
144
- }
145
- else if (key === "ArrowLeft" || key === "ArrowUp") {
146
- nextIndex = (currentIndex - 1 + length) % length;
147
- }
148
- else if (key === "Home") {
149
- nextIndex = 0;
150
- }
151
- else if (key === "End") {
152
- nextIndex = length - 1;
153
- }
154
- if (nextIndex !== undefined) {
155
- event.preventDefault();
156
- // Skip disabled tabs when navigating with arrow keys
157
- const isForward = key === "ArrowRight" || key === "ArrowDown";
158
- const maxAttempts = length;
159
- for (let i = 0; i < maxAttempts; i++) {
160
- const candidate = buttons[nextIndex];
161
- if (!(candidate === null || candidate === void 0 ? void 0 : candidate.disabled) &&
162
- (candidate === null || candidate === void 0 ? void 0 : candidate.getAttribute("aria-disabled")) !== "true") {
163
- break;
164
- }
165
- if (isForward) {
166
- nextIndex = (nextIndex + 1) % length;
167
- }
168
- else {
169
- nextIndex = (nextIndex - 1 + length) % length;
170
- }
171
- }
172
- // do not activateTab here for manual activation, just move the focus
173
- const nextButton = buttons[nextIndex];
174
- if (nextButton &&
175
- !nextButton.disabled &&
176
- nextButton.getAttribute("aria-disabled") !== "true") {
177
- nextButton.focus();
178
- }
179
- }
180
- }
181
- }
182
- isIndexActive(index) {
183
- return this.activeTabIndex === Number(index);
184
- }
185
- getTabItemTabIndex(index) {
186
- const i = Number(index);
187
- // only the active tab should be reachable via Tab key
188
- return this.activeTabIndex === i || (this.activeTabIndex === -1 && i === 0)
189
- ? 0
190
- : -1;
191
- }
192
- _updateCachedTabs() {
18
+ convertTabs() {
193
19
  try {
194
20
  if (typeof this.tabs === "string") {
195
- this._cachedTabs = JSON.parse(this.tabs);
196
- }
197
- else if (this.tabs) {
198
- this._cachedTabs = this.tabs;
199
- }
200
- else {
201
- this._cachedTabs = [];
21
+ return JSON.parse(this.tabs);
202
22
  }
23
+ return this.tabs;
203
24
  }
204
25
  catch (error) {
205
26
  console.error(error);
206
- this._cachedTabs = [];
207
27
  }
208
- }
209
- _getScrollContainer() {
210
- var _a, _b;
211
- return (_b = (_a = this._ref) === null || _a === void 0 ? void 0 : _a.querySelector('[role="tablist"]')) !== null && _b !== void 0 ? _b : null;
212
- }
213
- _isRtl() {
214
- const container = this._getScrollContainer();
215
- return (!!container &&
216
- typeof getComputedStyle !== "undefined" &&
217
- getComputedStyle(container).direction === "rtl");
28
+ return [];
218
29
  }
219
30
  evaluateScrollButtons(tList) {
220
31
  const needsScroll = tList.scrollWidth > tList.clientWidth;
221
- if (!needsScroll) {
222
- this.showScrollStart = false;
223
- this.showScrollEnd = false;
224
- return;
225
- }
226
- const scrollPos = Math.abs(tList.scrollLeft);
227
- const maxScroll = tList.scrollWidth - tList.clientWidth;
228
- const tolerance = 2;
229
- // scrollPos=0 means "at inline-start" in both LTR and RTL
230
- this.showScrollStart = scrollPos > tolerance;
231
- this.showScrollEnd = scrollPos < maxScroll - tolerance;
32
+ this.showScrollLeft = needsScroll && tList.scrollLeft > 1;
33
+ this.showScrollRight =
34
+ needsScroll && tList.scrollLeft < tList.scrollWidth - tList.clientWidth;
232
35
  }
233
- scroll(toStart) {
234
- const container = this._getScrollContainer();
235
- if (!container) {
236
- return;
237
- }
238
- let step = Number(this.arrowScrollDistance) || 120;
239
- const isLeft = !!toStart;
240
- const isRtl = this._isRtl();
241
- // Map logical direction (start/end) to physical direction.
242
- // In LTR: toStart=true → scroll left (negative), toEnd → scroll right (positive).
243
- // In RTL: directions are inverted physically.
244
- if (isLeft !== isRtl) {
36
+ scroll(left) {
37
+ var _a;
38
+ let step = Number(this.arrowScrollDistance) || 100;
39
+ if (left) {
245
40
  step *= -1;
246
41
  }
247
- container.scrollBy({
42
+ (_a = this.scrollContainer) === null || _a === void 0 ? void 0 : _a.scrollBy({
43
+ top: 0,
248
44
  left: step,
249
45
  behavior: "smooth",
250
46
  });
251
47
  }
252
48
  initTabList() {
253
- var _a, _b;
254
49
  if (this._ref) {
255
- const container = this._ref.querySelector('[role="tablist"]');
256
- if (container) {
257
- if (!container.getAttribute("aria-orientation")) {
258
- container.setAttribute("aria-orientation", (_a = this.orientation) !== null && _a !== void 0 ? _a : "horizontal");
259
- }
260
- if (this.behavior === "arrows") {
261
- this.evaluateScrollButtons(container);
262
- const _listener = this._scrollListener;
263
- if (_listener && container) {
264
- container.removeEventListener("scroll", _listener.fn);
265
- this._scrollListener = null;
266
- }
267
- const onScroll = () => this.evaluateScrollButtons(container);
268
- this._scrollListener = {
269
- fn: onScroll,
270
- };
271
- container.addEventListener("scroll", onScroll);
272
- if (!this._resizeObserver) {
273
- const observer = new ResizeObserver(() => {
50
+ const tabList = this._ref.querySelector(".db-tab-list");
51
+ if (tabList) {
52
+ const container = tabList.querySelector('[role="tablist"]');
53
+ if (container) {
54
+ container.setAttribute("aria-orientation", this.orientation || "horizontal");
55
+ if (this.behavior === "arrows") {
56
+ this.scrollContainer = container;
57
+ this.evaluateScrollButtons(container);
58
+ container.addEventListener("scroll", () => {
274
59
  this.evaluateScrollButtons(container);
275
60
  });
276
- observer.observe(container);
277
- this._resizeObserver = observer;
61
+ // Use ResizeObserver to re-evaluate scroll buttons because it provides more accurate, container-specific resize detection than global window resize events.
62
+ if (!this._resizeObserver) {
63
+ const observer = new ResizeObserver(() => {
64
+ this.evaluateScrollButtons(container);
65
+ });
66
+ observer.observe(container);
67
+ this._resizeObserver = observer;
68
+ }
278
69
  }
279
70
  }
280
- if (this.name && !container.getAttribute("aria-label")) {
281
- container.setAttribute("aria-label", (_b = this.name) !== null && _b !== void 0 ? _b : "");
282
- }
283
71
  }
284
72
  }
285
73
  }
286
- initTabs(activeIndex) {
287
- var _a, _b;
288
- const currentIndex = activeIndex !== undefined ? activeIndex : this.activeTabIndex;
74
+ initTabs(init) {
289
75
  if (this._ref) {
290
- const tabListEl = this._ref.querySelector('[role="tablist"]');
291
- 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);
292
- if (!tabListEl)
293
- return;
294
- const buttons = Array.from(tabListEl.querySelectorAll('[role="tab"]'));
295
- buttons.forEach((button, index) => {
296
- const isSelected = currentIndex === index;
297
- const panel = panels[index];
298
- const tabId = button.id || this.getTabId(index);
299
- const panelId = (panel === null || panel === void 0 ? void 0 : panel.id) || this.getPanelId(index);
300
- if (!button.id) {
301
- button.id = tabId;
302
- }
303
- if (!button.getAttribute("aria-controls")) {
304
- button.setAttribute("aria-controls", panelId);
305
- }
306
- button.dispatchEvent(new CustomEvent("aria-selected-changed", {
307
- detail: {
308
- selected: isSelected,
309
- tabIndex: currentIndex === index || (currentIndex === -1 && index === 0)
310
- ? 0
311
- : -1,
312
- },
313
- }));
314
- if (panel) {
315
- if (!panel.id) {
316
- panel.id = panelId;
76
+ const tabItems = Array.from(this._ref.getElementsByClassName("db-tab-item"));
77
+ const tabPanels = Array.from(this._ref.querySelectorAll(":is(:scope > .db-tab-panel, :scope > db-tab-panel > .db-tab-panel)"));
78
+ for (const tabItem of tabItems) {
79
+ const index = tabItems.indexOf(tabItem);
80
+ const label = tabItem.querySelector("label");
81
+ const input = tabItem.querySelector("input");
82
+ if (input && label) {
83
+ if (!input.id) {
84
+ const tabId = `${this._name}-tab-${index}`;
85
+ label.setAttribute("for", tabId);
86
+ input.id = tabId;
87
+ input.setAttribute("name", this._name);
88
+ if (tabPanels.length > index) {
89
+ input.setAttribute("aria-controls", `${this._name}-tab-panel-${index}`);
90
+ }
317
91
  }
318
- if (!panel.getAttribute("aria-label") &&
319
- !panel.getAttribute("aria-labelledby")) {
320
- panel.setAttribute("aria-labelledby", tabId);
92
+ if (init) {
93
+ // Auto select
94
+ const autoSelect = !this.initialSelectedMode || this.initialSelectedMode === "auto";
95
+ const shouldAutoSelect = (this.initialSelectedIndex == null && index === 0) ||
96
+ Number(this.initialSelectedIndex) === index;
97
+ if (autoSelect && shouldAutoSelect) {
98
+ input.click();
99
+ }
321
100
  }
322
- // toggle visibility
323
- panel.hidden = !isSelected;
324
101
  }
325
- });
102
+ }
103
+ for (const panel of tabPanels) {
104
+ if (panel.id)
105
+ continue;
106
+ const index = tabPanels.indexOf(panel);
107
+ panel.id = `${this._name}-tab-panel-${index}`;
108
+ panel.setAttribute("aria-labelledby", `${this._name}-tab-${index}`);
109
+ }
110
+ }
111
+ }
112
+ handleChange(event) {
113
+ var _a;
114
+ event.stopPropagation();
115
+ if (event.target) {
116
+ const target = event.target;
117
+ const parent = target.parentElement;
118
+ if (parent &&
119
+ parent.parentElement &&
120
+ ((_a = parent.parentElement) === null || _a === void 0 ? void 0 : _a.nodeName) === "LI") {
121
+ const tabItem = parent.parentElement.parentElement;
122
+ if (tabItem) {
123
+ const list = tabItem.parentElement;
124
+ if (list) {
125
+ const tabIndex = Array.from(list.children).indexOf(tabItem);
126
+ if (this.indexChange) {
127
+ this.indexChange.emit(tabIndex);
128
+ }
129
+ if (this.tabSelect) {
130
+ this.tabSelect.emit(event);
131
+ }
132
+ }
133
+ }
134
+ }
326
135
  }
327
136
  }
328
137
  /**
@@ -362,113 +171,54 @@ const DBTabs = class {
362
171
  }
363
172
  }
364
173
  watch0Fn() {
365
- this._updateCachedTabs();
366
- }
367
- watch0() {
368
- this.watch0Fn();
369
- }
370
- watch1Fn() {
371
- if (this.activeIndex !== undefined) {
372
- const newIndex = Number(this.activeIndex);
373
- if (!isNaN(newIndex) && newIndex !== this.activeTabIndex) {
374
- this.activateTab(newIndex);
375
- }
376
- }
377
- }
378
- watch1() {
379
- this.watch1Fn();
380
- }
381
- componentDidLoad() {
382
- this.enableAttributePassing(this._ref, "db-tabs");
383
- // 1. Calculate final start index synchronously to avoid race conditions
384
- let startIndex = 0;
385
- if (this.initialSelectedIndex !== undefined) {
386
- const parsedIndex = Number(this.initialSelectedIndex);
387
- startIndex = isNaN(parsedIndex) ? 0 : parsedIndex;
388
- }
389
- else if (this.initialSelectedMode === "manually") {
390
- startIndex = -1;
391
- }
392
- // 2. Support deep linking: URL hash takes precedence over initial index
393
- if (typeof window !== "undefined" && window.location.hash) {
394
- const hashId = window.location.hash.substring(1);
395
- const name = this.name ? "tabs-" + this.name : this._name();
396
- const prefix = `${name}-tab-`;
397
- if (hashId.startsWith(prefix)) {
398
- const indexStr = hashId.replace(prefix, "");
399
- const index = parseInt(indexStr, 10);
400
- if (!isNaN(index)) {
401
- startIndex = index;
402
- }
403
- }
404
- }
405
- // 3. Set initial state synchronously
406
- this.activeTabIndex = startIndex;
407
- this.initialized = true;
408
- this._updateCachedTabs();
409
- // 4. Trigger single initial DOM update after paint
410
- if (typeof window !== "undefined") {
411
- requestAnimationFrame(() => {
412
- this.initTabList();
413
- this.initTabs(startIndex);
414
- });
415
- }
416
- if (this._ref) {
417
- const tabListEl = this._ref.querySelector('[role="tablist"]');
418
- if (tabListEl) {
419
- const observer = new MutationObserver(() => {
420
- const rafId = this._pendingRafId;
421
- if (rafId !== null)
422
- cancelAnimationFrame(rafId);
423
- this._pendingRafId = requestAnimationFrame(() => {
424
- this._pendingRafId = null;
425
- this.initTabList();
426
- this.initTabs(this.activeTabIndex);
174
+ if (this._ref && this.initialized) {
175
+ this.initTabList();
176
+ this.initTabs(true);
177
+ const tabList = this._ref.querySelector(".db-tab-list");
178
+ if (tabList) {
179
+ const observer = new MutationObserver((mutations) => {
180
+ mutations.forEach((mutation) => {
181
+ if (mutation.removedNodes.length || mutation.addedNodes.length) {
182
+ this.initTabList();
183
+ this.initTabs();
184
+ }
427
185
  });
428
186
  });
429
- // Observe only the tablist (not panel content) to avoid unnecessary
430
- // re-evaluations when user content inside panels changes.
431
- // childList only – attribute changes (set by initTabs) are not observed, preventing infinite loops.
432
- observer.observe(tabListEl, {
187
+ observer.observe(tabList, {
433
188
  childList: true,
434
189
  subtree: true,
435
190
  });
436
- this._observer = observer;
437
191
  }
192
+ this.initialized = false;
438
193
  }
194
+ }
195
+ watch0() {
196
+ this.watch0Fn();
197
+ }
198
+ componentDidLoad() {
199
+ this.enableAttributePassing(this._ref, "db-tabs");
200
+ this._name = `tabs-${this.name || index$1.uuid()}`;
201
+ this.initialized = true;
439
202
  this.watch0Fn();
440
- this.watch1Fn();
441
203
  }
442
204
  disconnectedCallback() {
443
- var _a, _b;
444
- const rafId = this._pendingRafId;
445
- if (rafId !== null) {
446
- cancelAnimationFrame(rafId);
447
- this._pendingRafId = null;
448
- }
449
- const _listener = this._scrollListener;
450
- const _container = this._getScrollContainer();
451
- if (_listener && _container) {
452
- _container.removeEventListener("scroll", _listener.fn);
453
- }
205
+ var _a;
454
206
  (_a = this._resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
455
- this._resizeObserver = null;
456
- (_b = this._observer) === null || _b === void 0 ? void 0 : _b.disconnect();
457
- this._observer = null;
207
+ this._resizeObserver = undefined;
458
208
  }
459
209
  render() {
460
- var _a, _b, _c, _d, _e;
461
- return (index.h("div", { key: '8d9608e7d9255b3bc138ee4c50f1fdfb0b09ba72', class: index$1.cls("db-tabs", this.className), ref: (el) => {
210
+ var _a, _b, _c, _d, _e, _f;
211
+ return (index.h("div", { key: '20d8d662866ff60717de87ad4deb98a3b647672a', class: index$1.cls("db-tabs", this.className), ref: (el) => {
462
212
  this._ref = el;
463
- }, 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 ? (index.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 ? (index.h(index.Fragment, null, index.h("db-tab-list", { orientation: this.orientation, ariaLabel: this.name }, (_d = this._cachedTabs) === null || _d === void 0 ? void 0 : _d.map((tab, index$1) => (index.h("db-tab-item", { key: this.name + "tab-item" + index$1, id: this.getTabId(index$1), ariaControls: this.getPanelId(index$1), active: this.isIndexActive(index$1), tabIndex: this.getTabItemTabIndex(index$1), label: tab.label, iconTrailing: tab.iconTrailing, icon: tab.icon, noText: tab.noText, onClick: () => this.activateTab(index$1) })))), (_e = this._cachedTabs) === null || _e === void 0 ? void 0 :
464
- _e.map((tab, index$1) => (index.h("db-tab-panel", { key: this.name + "tab-panel" + index$1, id: this.getPanelId(index$1), ariaLabelledby: this.getTabId(index$1), content: tab.content, hidden: !this.isIndexActive(index$1) }, tab.children))))) : null, !this.tabs ? index.h("slot", null) : null, this.showScrollEnd ? (index.h("db-button", { class: "tabs-scroll-end", variant: "ghost", icon: "chevron_right", type: "button", noText: true, onClick: () => this.scroll(false) }, this.scrollEndLabel)) : null));
213
+ }, 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 ? (index.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 ? (index.h(index.Fragment, null, index.h("db-tab-list", null, (_e = this.convertTabs()) === null || _e === void 0 ? void 0 : _e.map((tab, index$1) => (index.h("db-tab-item", { key: this.name + "tab-item" + index$1, active: tab.active, label: tab.label, iconTrailing: tab.iconTrailing, icon: tab.icon, noText: tab.noText })))), (_f = this.convertTabs()) === null || _f === void 0 ? void 0 :
214
+ _f.map((tab, index$1) => (index.h("db-tab-panel", { key: this.name + "tab-panel" + index$1, content: tab.content }, tab.children))))) : null, this.showScrollRight ? (index.h("db-button", { class: "tabs-scroll-right", variant: "ghost", icon: "chevron_right", type: "button", noText: true, onClick: () => this.scroll() }, "Scroll right")) : null, index.h("slot", { key: 'f9803a647f9a01adc0b20eb6bdb999f38c3602af' })));
465
215
  }
466
216
  static get watchers() { return {
467
- "tabs": [{
217
+ "_ref": [{
468
218
  "watch0": 0
469
219
  }],
470
- "activeIndex": [{
471
- "watch1": 0
220
+ "initialized": [{
221
+ "watch0": 0
472
222
  }]
473
223
  }; }
474
224
  };
@@ -201,10 +201,10 @@ const DBTextarea = class {
201
201
  }
202
202
  render() {
203
203
  var _a, _b, _c, _d, _e, _f;
204
- return (index.h("div", { key: '09bd0536df39649a7eb87c87f3402d0e626a4ffc', class: index$1.cls("db-textarea", this.className), "data-variant": this.variant, "data-hide-asterisk": index$1.getHideProp(this.showRequiredAsterisk), "data-hide-label": index$1.getHideProp(this.showLabel) }, index.h("label", { key: 'f30242db7f91eb79b9c3f5db090ce0ad2cfc9899', htmlFor: this._id }, (_a = this.label) !== null && _a !== void 0 ? _a : constants.DEFAULT_LABEL), index.h("textarea", { key: 'eec1ca9649b4daf2d8b6ba0cd9f09da21ddcd0b7', "aria-invalid": this.validation === "invalid", "data-custom-validity": this.validation, "data-field-sizing": this.fieldSizing, ref: (el) => {
204
+ return (index.h("div", { key: 'e6c64857826bf80558d0b402594a66418e62ef57', class: index$1.cls("db-textarea", this.className), "data-variant": this.variant, "data-hide-asterisk": index$1.getHideProp(this.showRequiredAsterisk), "data-hide-label": index$1.getHideProp(this.showLabel) }, index.h("label", { key: '38f6ce12d40275dd6fa5cfa64c6d2ca4c17fab8f', htmlFor: this._id }, (_a = this.label) !== null && _a !== void 0 ? _a : constants.DEFAULT_LABEL), index.h("textarea", { key: '6d11324a4cfce9eeed9e1bcafe0a7edb1ee6c8ce', "aria-invalid": this.validation === "invalid", "data-custom-validity": this.validation, "data-field-sizing": this.fieldSizing, ref: (el) => {
205
205
  this._ref = el;
206
206
  }, id: this._id, "data-resize": this.resize, "data-hide-resizer": index$1.getHideProp((_b = this.showResizer) !== null && _b !== void 0 ? _b : true), disabled: index$1.getBoolean(this.disabled, "disabled"), required: index$1.getBoolean(this.required, "required"), readOnly: index$1.getBoolean(this.readOnly, "readOnly") ||
207
- index$1.getBoolean(this.readonly, "readonly"), form: this.form, maxLength: index$1.getNumber(this.maxLength, this.maxlength), minLength: index$1.getNumber(this.minLength, this.minlength), name: this.name, wrap: this.wrap, spellcheck: this.spellCheck, autocomplete: this.autocomplete, onInput: (event) => this.handleInput(event), onChange: (event) => this.handleChange(event), onBlur: (event) => this.handleBlur(event), onFocus: (event) => this.handleFocus(event), value: (_d = (_c = this.value) !== null && _c !== void 0 ? _c : this._value) !== null && _d !== void 0 ? _d : "", "aria-describedby": (_e = this.ariaDescribedBy) !== null && _e !== void 0 ? _e : this._descByIds, placeholder: (_f = this.placeholder) !== null && _f !== void 0 ? _f : constants.DEFAULT_PLACEHOLDER, rows: index$1.getNumber(this.rows, constants.DEFAULT_ROWS), cols: index$1.getNumber(this.cols) }), index$1.stringPropVisible(this.message, this.showMessage) ? (index.h("db-infotext", { size: "small", icon: this.messageIcon, id: this._messageId }, this.message)) : null, this.hasValidState() ? (index.h("db-infotext", { size: "small", semantic: "successful", id: this._validMessageId }, this.validMessage || constants.DEFAULT_VALID_MESSAGE)) : null, index.h("db-infotext", { key: 'a23431e70fa69dfb3cc53f5c114802c586b76628', size: "small", semantic: "critical", id: this._invalidMessageId }, this._invalidMessage), index.h("span", { key: '936fc47a2da2c0590c5991df6ff6d2ba84342fd3', "data-visually-hidden": "true", role: "status" }, this._voiceOverFallback)));
207
+ index$1.getBoolean(this.readonly, "readonly"), form: this.form, maxLength: index$1.getNumber(this.maxLength, this.maxlength), minLength: index$1.getNumber(this.minLength, this.minlength), name: this.name, wrap: this.wrap, spellcheck: this.spellCheck, autocomplete: this.autocomplete, onInput: (event) => this.handleInput(event), onChange: (event) => this.handleChange(event), onBlur: (event) => this.handleBlur(event), onFocus: (event) => this.handleFocus(event), value: (_d = (_c = this.value) !== null && _c !== void 0 ? _c : this._value) !== null && _d !== void 0 ? _d : "", "aria-describedby": (_e = this.ariaDescribedBy) !== null && _e !== void 0 ? _e : this._descByIds, placeholder: (_f = this.placeholder) !== null && _f !== void 0 ? _f : constants.DEFAULT_PLACEHOLDER, rows: index$1.getNumber(this.rows, constants.DEFAULT_ROWS), cols: index$1.getNumber(this.cols) }), index$1.stringPropVisible(this.message, this.showMessage) ? (index.h("db-infotext", { size: "small", icon: this.messageIcon, id: this._messageId }, this.message)) : null, this.hasValidState() ? (index.h("db-infotext", { size: "small", semantic: "successful", id: this._validMessageId }, this.validMessage || constants.DEFAULT_VALID_MESSAGE)) : null, index.h("db-infotext", { key: '16d43aeea87f6e3597c95847c037faa194875b94', size: "small", semantic: "critical", id: this._invalidMessageId }, this._invalidMessage), index.h("span", { key: '8b407f9a60c61ac4af26d6ec5a9571d5f37ae915', "data-visually-hidden": "true", role: "status" }, this._voiceOverFallback)));
208
208
  }
209
209
  static get watchers() { return {
210
210
  "id": [{
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-BoC-BWt4.js');
4
+ var constants = require('./constants-bMY2_d8A.js');
4
5
  var index$1 = require('./index-2_9ESkQu.js');
5
6
  var documentScrollListener = require('./document-scroll-listener-ChQ7XZRk.js');
6
7
  var floatingComponents = require('./floating-components-DlstoCKH.js');
@@ -8,7 +9,7 @@ var floatingComponents = require('./floating-components-DlstoCKH.js');
8
9
  const DBTooltip = class {
9
10
  constructor(hostRef) {
10
11
  index.registerInstance(this, hostRef);
11
- this._id = "tooltip-" + index$1.uuid();
12
+ this._id = constants.DEFAULT_ID;
12
13
  this.initialized = false;
13
14
  this._documentScrollListenerCallbackId = undefined;
14
15
  this._observer = undefined;
@@ -157,9 +158,9 @@ const DBTooltip = class {
157
158
  }
158
159
  render() {
159
160
  var _a, _b;
160
- return (index.h("i", { key: 'c96329202b5534b72d32091f25637fa0cd49e8bb', class: index$1.cls("db-tooltip", this.className), role: "tooltip", "aria-hidden": "true", "data-gap": "true", ref: (el) => {
161
+ return (index.h("i", { key: 'df7b27f485e4029f51329dd73e50603f6965efb8', class: index$1.cls("db-tooltip", this.className), role: "tooltip", "aria-hidden": "true", "data-gap": "true", ref: (el) => {
161
162
  this._ref = el;
162
- }, id: this._id, "data-emphasis": this.emphasis, "data-wrap": index$1.getBooleanAsString(this.wrap), "data-animation": index$1.getBooleanAsString((_a = this.animation) !== null && _a !== void 0 ? _a : true), "data-delay": this.delay, "data-width": this.width, "data-show-arrow": index$1.getBooleanAsString((_b = this.showArrow) !== null && _b !== void 0 ? _b : true), "data-placement": this.placement, onClick: (event) => this.handleClick(event) }, index.h("slot", { key: 'ffbe2e72d2a2071c09c2dd66d694453be33c809c' })));
163
+ }, id: this._id, "data-emphasis": this.emphasis, "data-wrap": index$1.getBooleanAsString(this.wrap), "data-animation": index$1.getBooleanAsString((_a = this.animation) !== null && _a !== void 0 ? _a : true), "data-delay": this.delay, "data-width": this.width, "data-show-arrow": index$1.getBooleanAsString((_b = this.showArrow) !== null && _b !== void 0 ? _b : true), "data-placement": this.placement, onClick: (event) => this.handleClick(event) }, index.h("slot", { key: '7c1aee92a530f8b0899231f55122f6109c72bc46' })));
163
164
  }
164
165
  static get watchers() { return {
165
166
  "id": [{