le-kit 0.2.4 → 0.2.6

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 (160) hide show
  1. package/dist/cjs/le-bar.cjs.entry.js +428 -0
  2. package/dist/cjs/le-box.cjs.entry.js +1 -1
  3. package/dist/cjs/le-button_13.cjs.entry.js +17 -17
  4. package/dist/cjs/le-card.cjs.entry.js +1 -1
  5. package/dist/cjs/le-combobox.cjs.entry.js +1 -1
  6. package/dist/cjs/le-header-placeholder.cjs.entry.js +1 -1
  7. package/dist/cjs/le-icon.cjs.entry.js +1 -1
  8. package/dist/cjs/le-kit.cjs.js +1 -1
  9. package/dist/cjs/le-multiselect.cjs.entry.js +3 -3
  10. package/dist/cjs/le-navigation.cjs.entry.js +61 -250
  11. package/dist/cjs/le-number-input.cjs.entry.js +1 -1
  12. package/dist/cjs/le-round-progress.cjs.entry.js +1 -1
  13. package/dist/cjs/le-segmented-control.cjs.entry.js +1 -1
  14. package/dist/cjs/le-stack.cjs.entry.js +1 -1
  15. package/dist/cjs/le-tab-bar.cjs.entry.js +1 -1
  16. package/dist/cjs/le-tab-panel.cjs.entry.js +2 -2
  17. package/dist/cjs/le-tab.cjs.entry.js +1 -1
  18. package/dist/cjs/le-tabs.cjs.entry.js +2 -2
  19. package/dist/cjs/le-tag.cjs.entry.js +1 -1
  20. package/dist/cjs/le-turntable.cjs.entry.js +1 -1
  21. package/dist/cjs/loader.cjs.js +1 -1
  22. package/dist/collection/collection-manifest.json +1 -0
  23. package/dist/collection/components/le-bar/le-bar.css +255 -0
  24. package/dist/collection/components/le-bar/le-bar.js +628 -0
  25. package/dist/collection/components/le-bar/le-bar.js.map +1 -0
  26. package/dist/collection/components/le-box/le-box.js +1 -1
  27. package/dist/collection/components/le-button/le-button.js +1 -1
  28. package/dist/collection/components/le-card/le-card.js +1 -1
  29. package/dist/collection/components/le-checkbox/le-checkbox.js +1 -1
  30. package/dist/collection/components/le-collapse/le-collapse.js +1 -1
  31. package/dist/collection/components/le-combobox/le-combobox.js +1 -1
  32. package/dist/collection/components/le-current-heading/le-current-heading.js +1 -1
  33. package/dist/collection/components/le-dropdown-base/le-dropdown-base.js +1 -1
  34. package/dist/collection/components/le-header/le-header.js +2 -2
  35. package/dist/collection/components/le-header-placeholder/le-header-placeholder.js +1 -1
  36. package/dist/collection/components/le-icon/le-icon.js +1 -1
  37. package/dist/collection/components/le-multiselect/le-multiselect.js +3 -3
  38. package/dist/collection/components/le-navigation/le-navigation.css +29 -47
  39. package/dist/collection/components/le-navigation/le-navigation.js +62 -251
  40. package/dist/collection/components/le-navigation/le-navigation.js.map +1 -1
  41. package/dist/collection/components/le-number-input/le-number-input.js +1 -1
  42. package/dist/collection/components/le-popover/le-popover.js +3 -3
  43. package/dist/collection/components/le-popup/le-popup.js +1 -1
  44. package/dist/collection/components/le-round-progress/le-round-progress.js +1 -1
  45. package/dist/collection/components/le-scroll-progress/le-scroll-progress.js +1 -1
  46. package/dist/collection/components/le-segmented-control/le-segmented-control.js +1 -1
  47. package/dist/collection/components/le-select/le-select.js +2 -2
  48. package/dist/collection/components/le-slot/le-slot.js +1 -1
  49. package/dist/collection/components/le-stack/le-stack.js +1 -1
  50. package/dist/collection/components/le-string-input/le-string-input.js +2 -2
  51. package/dist/collection/components/le-tab/le-tab.js +1 -1
  52. package/dist/collection/components/le-tab-bar/le-tab-bar.js +1 -1
  53. package/dist/collection/components/le-tab-panel/le-tab-panel.js +2 -2
  54. package/dist/collection/components/le-tabs/le-tabs.js +2 -2
  55. package/dist/collection/components/le-tag/le-tag.js +1 -1
  56. package/dist/collection/components/le-turntable/le-turntable.js +1 -1
  57. package/dist/collection/dist/components/assets/custom-elements.json +2147 -1764
  58. package/dist/components/assets/custom-elements.json +2147 -1764
  59. package/dist/components/le-bar.d.ts +11 -0
  60. package/dist/components/le-bar.js +9 -0
  61. package/dist/components/le-bar.js.map +1 -0
  62. package/dist/components/le-bar2.js +473 -0
  63. package/dist/components/le-bar2.js.map +1 -0
  64. package/dist/components/le-box.js +1 -1
  65. package/dist/components/le-button2.js +8 -8
  66. package/dist/components/le-card.js +1 -1
  67. package/dist/components/le-collapse2.js +1 -1
  68. package/dist/components/le-combobox.js +1 -1
  69. package/dist/components/le-current-heading.js +1 -1
  70. package/dist/components/le-dropdown-base2.js +1 -1
  71. package/dist/components/le-header-placeholder.js +1 -1
  72. package/dist/components/le-header.js +2 -2
  73. package/dist/components/le-icon2.js +1 -1
  74. package/dist/components/le-multiselect.js +3 -3
  75. package/dist/components/le-navigation.js +70 -253
  76. package/dist/components/le-navigation.js.map +1 -1
  77. package/dist/components/le-number-input.js +1 -1
  78. package/dist/components/le-popover2.js +3 -3
  79. package/dist/components/le-round-progress.js +1 -1
  80. package/dist/components/le-scroll-progress.js +1 -1
  81. package/dist/components/le-segmented-control.js +1 -1
  82. package/dist/components/le-stack.js +1 -1
  83. package/dist/components/le-tab-bar.js +1 -1
  84. package/dist/components/le-tab-panel.js +2 -2
  85. package/dist/components/le-tab2.js +1 -1
  86. package/dist/components/le-tabs.js +2 -2
  87. package/dist/components/le-tag2.js +1 -1
  88. package/dist/components/le-turntable.js +1 -1
  89. package/dist/docs.json +404 -13
  90. package/dist/esm/le-bar.entry.js +426 -0
  91. package/dist/esm/le-bar.entry.js.map +1 -0
  92. package/dist/esm/le-box.entry.js +1 -1
  93. package/dist/esm/le-button_13.entry.js +17 -17
  94. package/dist/esm/le-card.entry.js +1 -1
  95. package/dist/esm/le-combobox.entry.js +1 -1
  96. package/dist/esm/le-header-placeholder.entry.js +1 -1
  97. package/dist/esm/le-icon.entry.js +1 -1
  98. package/dist/esm/le-kit.js +1 -1
  99. package/dist/esm/le-multiselect.entry.js +3 -3
  100. package/dist/esm/le-navigation.entry.js +61 -250
  101. package/dist/esm/le-navigation.entry.js.map +1 -1
  102. package/dist/esm/le-number-input.entry.js +1 -1
  103. package/dist/esm/le-round-progress.entry.js +1 -1
  104. package/dist/esm/le-segmented-control.entry.js +1 -1
  105. package/dist/esm/le-stack.entry.js +1 -1
  106. package/dist/esm/le-tab-bar.entry.js +1 -1
  107. package/dist/esm/le-tab-panel.entry.js +2 -2
  108. package/dist/esm/le-tab.entry.js +1 -1
  109. package/dist/esm/le-tabs.entry.js +2 -2
  110. package/dist/esm/le-tag.entry.js +1 -1
  111. package/dist/esm/le-turntable.entry.js +1 -1
  112. package/dist/esm/loader.js +1 -1
  113. package/dist/le-kit/dist/components/assets/custom-elements.json +2147 -1764
  114. package/dist/le-kit/le-kit.esm.js +1 -1
  115. package/dist/le-kit/p-045e0d4a.entry.js +2 -0
  116. package/dist/le-kit/p-045e0d4a.entry.js.map +1 -0
  117. package/dist/le-kit/{p-00cd6dc4.entry.js → p-07705c61.entry.js} +2 -2
  118. package/dist/le-kit/{p-0b5ab6ec.entry.js → p-0a270831.entry.js} +2 -2
  119. package/dist/le-kit/p-2102a152.entry.js +2 -0
  120. package/dist/le-kit/{p-02699578.entry.js.map → p-2102a152.entry.js.map} +1 -1
  121. package/dist/le-kit/{p-76d03b1e.entry.js → p-244ff3d7.entry.js} +2 -2
  122. package/dist/le-kit/{p-a5e21c8e.entry.js → p-249db213.entry.js} +2 -2
  123. package/dist/le-kit/{p-348a4e39.entry.js → p-3a0a57e9.entry.js} +2 -2
  124. package/dist/le-kit/{p-2db32332.entry.js → p-4b88b0da.entry.js} +2 -2
  125. package/dist/le-kit/p-4f11ea11.entry.js +2 -0
  126. package/dist/le-kit/p-4f11ea11.entry.js.map +1 -0
  127. package/dist/le-kit/{p-9f409d74.entry.js → p-61edb398.entry.js} +2 -2
  128. package/dist/le-kit/{p-17ace252.entry.js → p-6d0090c1.entry.js} +2 -2
  129. package/dist/le-kit/{p-91421993.entry.js → p-73f7de28.entry.js} +2 -2
  130. package/dist/le-kit/{p-8907cf95.entry.js → p-764005e3.entry.js} +2 -2
  131. package/dist/le-kit/{p-509caf7f.entry.js → p-94f774af.entry.js} +2 -2
  132. package/dist/le-kit/p-ac822433.entry.js +2 -0
  133. package/dist/le-kit/{p-995f6de8.entry.js → p-b21277e8.entry.js} +2 -2
  134. package/dist/le-kit/{p-65fa68c3.entry.js → p-b6997587.entry.js} +2 -2
  135. package/dist/le-kit/{p-0aab5747.entry.js → p-c0ccc9aa.entry.js} +2 -2
  136. package/dist/le-kit/{p-b4dcb4df.entry.js → p-ebd86d4f.entry.js} +2 -2
  137. package/dist/types/components/le-bar/le-bar.d.ts +125 -0
  138. package/dist/types/components/le-navigation/le-navigation.d.ts +10 -18
  139. package/dist/types/components.d.ts +148 -0
  140. package/package.json +4 -4
  141. package/dist/le-kit/p-02699578.entry.js +0 -2
  142. package/dist/le-kit/p-a1c26c46.entry.js +0 -2
  143. package/dist/le-kit/p-a1c26c46.entry.js.map +0 -1
  144. package/dist/le-kit/p-ccf4c548.entry.js +0 -2
  145. /package/dist/le-kit/{p-00cd6dc4.entry.js.map → p-07705c61.entry.js.map} +0 -0
  146. /package/dist/le-kit/{p-0b5ab6ec.entry.js.map → p-0a270831.entry.js.map} +0 -0
  147. /package/dist/le-kit/{p-76d03b1e.entry.js.map → p-244ff3d7.entry.js.map} +0 -0
  148. /package/dist/le-kit/{p-a5e21c8e.entry.js.map → p-249db213.entry.js.map} +0 -0
  149. /package/dist/le-kit/{p-348a4e39.entry.js.map → p-3a0a57e9.entry.js.map} +0 -0
  150. /package/dist/le-kit/{p-2db32332.entry.js.map → p-4b88b0da.entry.js.map} +0 -0
  151. /package/dist/le-kit/{p-9f409d74.entry.js.map → p-61edb398.entry.js.map} +0 -0
  152. /package/dist/le-kit/{p-17ace252.entry.js.map → p-6d0090c1.entry.js.map} +0 -0
  153. /package/dist/le-kit/{p-91421993.entry.js.map → p-73f7de28.entry.js.map} +0 -0
  154. /package/dist/le-kit/{p-8907cf95.entry.js.map → p-764005e3.entry.js.map} +0 -0
  155. /package/dist/le-kit/{p-509caf7f.entry.js.map → p-94f774af.entry.js.map} +0 -0
  156. /package/dist/le-kit/{p-ccf4c548.entry.js.map → p-ac822433.entry.js.map} +0 -0
  157. /package/dist/le-kit/{p-995f6de8.entry.js.map → p-b21277e8.entry.js.map} +0 -0
  158. /package/dist/le-kit/{p-65fa68c3.entry.js.map → p-b6997587.entry.js.map} +0 -0
  159. /package/dist/le-kit/{p-0aab5747.entry.js.map → p-c0ccc9aa.entry.js.map} +0 -0
  160. /package/dist/le-kit/{p-b4dcb4df.entry.js.map → p-ebd86d4f.entry.js.map} +0 -0
@@ -0,0 +1,628 @@
1
+ import { h, Host, } from "@stencil/core";
2
+ import { classnames, generateId } from "../../utils/utils";
3
+ /**
4
+ * A flexible bar component that handles overflow gracefully.
5
+ *
6
+ * Items are slotted children. The bar measures which items fit on the first
7
+ * row and handles overflow according to the `overflow` prop.
8
+ *
9
+ * @slot - Bar items (children will be measured for overflow)
10
+ * @slot more - Custom "more" button content
11
+ * @slot hamburger - Custom hamburger button content
12
+ * @slot start-arrow - Custom left scroll arrow
13
+ * @slot end-arrow - Custom right scroll arrow
14
+ * @slot all-menu - Custom "show all" menu button
15
+ *
16
+ * @csspart container - The main bar container
17
+ * @csspart item - Individual items in the bar
18
+ * @csspart more-button - The "more" overflow button
19
+ * @csspart hamburger-button - The hamburger menu button
20
+ * @csspart arrow-start - The start (left) scroll arrow
21
+ * @csspart arrow-end - The end (right) scroll arrow
22
+ * @csspart all-menu-button - The "show all" menu button
23
+ * @csspart popover-content - The popover content wrapper
24
+ *
25
+ * @cmsEditable true
26
+ * @cmsCategory Layout
27
+ */
28
+ export class LeBar {
29
+ el;
30
+ /**
31
+ * Overflow behavior when items don't fit on one row.
32
+ * - `more`: Overflow items appear in a "more" dropdown
33
+ * - `scroll`: Items scroll horizontally with optional arrows
34
+ * - `hamburger`: All items go into a hamburger menu if any overflow
35
+ * - `wrap`: Items wrap to additional rows
36
+ */
37
+ overflow = 'more';
38
+ /**
39
+ * Alignment of items within the bar (maps to justify-content).
40
+ */
41
+ alignItems = 'start';
42
+ /**
43
+ * Show scroll arrows when overflow is "scroll".
44
+ */
45
+ arrows = false;
46
+ /**
47
+ * Disable the internal overflow popover.
48
+ * When true, the bar still detects overflow and hides items,
49
+ * but doesn't render its own popover. Use this when providing
50
+ * custom overflow handling via the leBarOverflowChange event.
51
+ */
52
+ disablePopover = false;
53
+ /**
54
+ * Show an "all items" menu button.
55
+ * - `false`: Don't show
56
+ * - `true` or `'end'`: Show at end
57
+ * - `'start'`: Show at start
58
+ */
59
+ showAllMenu = false;
60
+ /**
61
+ * Emitted when overflow state changes.
62
+ */
63
+ leBarOverflowChange;
64
+ /** Whether the hamburger/more popover is open */
65
+ popoverOpen = false;
66
+ /** Whether hamburger mode is active (for hamburger overflow) */
67
+ hamburgerActive = false;
68
+ /** IDs of items that are overflowing */
69
+ overflowingIds = new Set();
70
+ /** Whether we can scroll left */
71
+ canScrollStart = false;
72
+ /** Whether we can scroll right */
73
+ canScrollEnd = false;
74
+ /** Whether the all-menu popover is open */
75
+ allMenuOpen = false;
76
+ /** Current height of the items container (for overflow handling) */
77
+ containerHeight = null;
78
+ itemsContainerEl;
79
+ moreButtonEl;
80
+ resizeObserver;
81
+ mutationObserver;
82
+ instanceId = generateId('le-bar');
83
+ // Map to track item elements and their IDs
84
+ itemMap = new Map();
85
+ // Prevent multiple recalculations in the same frame
86
+ pendingRecalc = null;
87
+ handleOverflowChange() {
88
+ this.resetOverflowState();
89
+ this.scheduleOverflowRecalc();
90
+ }
91
+ handleSlotChange() {
92
+ this.scheduleOverflowRecalc();
93
+ }
94
+ connectedCallback() {
95
+ this.setupObservers();
96
+ }
97
+ componentDidLoad() {
98
+ this.scheduleOverflowRecalc();
99
+ }
100
+ componentDidRender() {
101
+ // Recalculate after render in case children changed
102
+ this.scheduleOverflowRecalc();
103
+ }
104
+ disconnectedCallback() {
105
+ this.resizeObserver?.disconnect();
106
+ this.mutationObserver?.disconnect();
107
+ }
108
+ /**
109
+ * Force recalculation of overflow state.
110
+ */
111
+ async recalculate() {
112
+ this.computeOverflow();
113
+ }
114
+ setupObservers() {
115
+ // ResizeObserver for container size changes
116
+ if (typeof ResizeObserver !== 'undefined') {
117
+ this.resizeObserver = new ResizeObserver(() => {
118
+ this.computeOverflow();
119
+ this.updateScrollState();
120
+ });
121
+ }
122
+ // MutationObserver for child changes
123
+ this.mutationObserver = new MutationObserver(() => {
124
+ this.scheduleOverflowRecalc();
125
+ });
126
+ this.mutationObserver.observe(this.el, {
127
+ childList: true,
128
+ subtree: false,
129
+ });
130
+ }
131
+ observeContainer(el) {
132
+ if (!this.resizeObserver)
133
+ return;
134
+ this.resizeObserver.disconnect();
135
+ if (el)
136
+ this.resizeObserver.observe(el);
137
+ }
138
+ scheduleOverflowRecalc() {
139
+ // Debounce recalculations to prevent infinite loops
140
+ if (this.pendingRecalc !== null) {
141
+ cancelAnimationFrame(this.pendingRecalc);
142
+ }
143
+ this.pendingRecalc = requestAnimationFrame(() => {
144
+ this.pendingRecalc = null;
145
+ this.computeOverflow();
146
+ });
147
+ }
148
+ resetOverflowState() {
149
+ this.hamburgerActive = false;
150
+ this.overflowingIds = new Set();
151
+ this.containerHeight = null;
152
+ this.popoverOpen = false;
153
+ }
154
+ getSlottedItems() {
155
+ // Get direct children from the light DOM (excluding named slot elements)
156
+ return Array.from(this.el.children).filter((el) => el instanceof HTMLElement && !el.hasAttribute('slot'));
157
+ }
158
+ getItemId(el, index) {
159
+ return el.id || el.dataset.barId || `${this.instanceId}-item-${index}`;
160
+ }
161
+ computeOverflow() {
162
+ if (this.overflow === 'wrap' || this.overflow === 'scroll') {
163
+ // No overflow handling needed for wrap/scroll modes
164
+ this.resetOverflowState();
165
+ this.updateScrollState();
166
+ return;
167
+ }
168
+ const container = this.itemsContainerEl;
169
+ if (!container)
170
+ return;
171
+ const items = this.getSlottedItems();
172
+ if (items.length === 0) {
173
+ this.resetOverflowState();
174
+ return;
175
+ }
176
+ // Force a layout recalc
177
+ container.offsetHeight;
178
+ // Build item map
179
+ this.itemMap.clear();
180
+ items.forEach((item, index) => {
181
+ const id = this.getItemId(item, index);
182
+ this.itemMap.set(id, item);
183
+ });
184
+ // Get the position of items to determine which are on the first row
185
+ const itemRects = items.map((item, index) => ({
186
+ item,
187
+ id: this.getItemId(item, index),
188
+ rect: item.getBoundingClientRect(),
189
+ }));
190
+ if (itemRects.length === 0) {
191
+ return;
192
+ }
193
+ // Find the first row's top position (accounting for vertical alignment)
194
+ const containerRect = container.getBoundingClientRect();
195
+ const topValues = itemRects.map(i => i.rect.top - containerRect.top);
196
+ const minTop = Math.min(...topValues);
197
+ // Items are on the first row if their top is close to minTop
198
+ // Allow some tolerance for alignment differences
199
+ const tolerance = 15;
200
+ const firstRowItems = itemRects.filter(i => i.rect.top - containerRect.top <= minTop + tolerance);
201
+ const overflowItems = itemRects.filter(i => i.rect.top - containerRect.top > minTop + tolerance);
202
+ // Calculate the height of the first row
203
+ const firstRowBottom = firstRowItems.length > 0
204
+ ? Math.max(...firstRowItems.map(i => i.rect.bottom - containerRect.top))
205
+ : 0;
206
+ if (this.overflow === 'hamburger') {
207
+ // In hamburger mode, if ANY item overflows, all go into the menu
208
+ const shouldHamburger = overflowItems.length > 0;
209
+ if (shouldHamburger !== this.hamburgerActive) {
210
+ this.hamburgerActive = shouldHamburger;
211
+ this.emitOverflowChange();
212
+ }
213
+ // Set height to show only first row (or hide all if hamburger is active)
214
+ if (shouldHamburger && firstRowBottom > 0) {
215
+ this.containerHeight = firstRowBottom;
216
+ }
217
+ else {
218
+ this.containerHeight = null;
219
+ }
220
+ }
221
+ else {
222
+ // 'more' mode
223
+ const newOverflowingIds = new Set(overflowItems.map(i => i.id));
224
+ // Check if we need to make room for the "more" button
225
+ if (newOverflowingIds.size > 0 && this.moreButtonEl) {
226
+ const moreRect = this.moreButtonEl.getBoundingClientRect();
227
+ const moreTop = moreRect.top - containerRect.top;
228
+ // If "more" button is not on the first row, we need to hide one more item
229
+ if (moreTop > minTop + tolerance) {
230
+ // Find the last visible item and move it to overflow
231
+ const lastVisible = firstRowItems[firstRowItems.length - 1];
232
+ if (lastVisible) {
233
+ newOverflowingIds.add(lastVisible.id);
234
+ }
235
+ }
236
+ }
237
+ // Check if overflow state changed
238
+ const hasChanged = newOverflowingIds.size !== this.overflowingIds.size ||
239
+ ![...newOverflowingIds].every(id => this.overflowingIds.has(id));
240
+ if (hasChanged) {
241
+ this.overflowingIds = newOverflowingIds;
242
+ this.emitOverflowChange();
243
+ }
244
+ // Set container height to show only first row
245
+ if (newOverflowingIds.size > 0 && firstRowBottom > 0) {
246
+ this.containerHeight = firstRowBottom;
247
+ }
248
+ else {
249
+ this.containerHeight = null;
250
+ }
251
+ }
252
+ }
253
+ emitOverflowChange() {
254
+ this.leBarOverflowChange.emit({
255
+ overflowingIds: [...this.overflowingIds],
256
+ hamburgerActive: this.hamburgerActive,
257
+ });
258
+ }
259
+ updateScrollState() {
260
+ if (this.overflow !== 'scroll' || !this.itemsContainerEl) {
261
+ this.canScrollStart = false;
262
+ this.canScrollEnd = false;
263
+ return;
264
+ }
265
+ const el = this.itemsContainerEl;
266
+ this.canScrollStart = el.scrollLeft > 0;
267
+ this.canScrollEnd = el.scrollLeft < el.scrollWidth - el.clientWidth - 1;
268
+ }
269
+ handleScroll = () => {
270
+ this.updateScrollState();
271
+ };
272
+ scrollToStart = () => {
273
+ if (!this.itemsContainerEl)
274
+ return;
275
+ const items = this.getSlottedItems();
276
+ const container = this.itemsContainerEl;
277
+ // Find the scroll position of the previous item
278
+ const currentScroll = container.scrollLeft;
279
+ let targetScroll = 0;
280
+ for (let i = items.length - 1; i >= 0; i--) {
281
+ const item = items[i];
282
+ // Calculate item's left edge relative to container's scroll position
283
+ const itemLeft = item.offsetLeft - container.offsetLeft;
284
+ // If this item starts before current scroll position, scroll to it
285
+ if (itemLeft < currentScroll - 1) {
286
+ targetScroll = itemLeft;
287
+ break;
288
+ }
289
+ }
290
+ container.scrollTo({ left: targetScroll, behavior: 'smooth' });
291
+ // Update scroll state after animation
292
+ setTimeout(() => this.updateScrollState(), 300);
293
+ };
294
+ scrollToEnd = () => {
295
+ if (!this.itemsContainerEl)
296
+ return;
297
+ const container = this.itemsContainerEl;
298
+ const items = this.getSlottedItems();
299
+ if (items.length === 0)
300
+ return;
301
+ const containerWidth = container.clientWidth;
302
+ const currentScroll = container.scrollLeft;
303
+ let targetScroll = container.scrollWidth - containerWidth;
304
+ for (const item of items) {
305
+ // Calculate item's right edge relative to container
306
+ const itemLeft = item.offsetLeft - container.offsetLeft;
307
+ // If this is the next item to scroll to from left to right then scroll to it
308
+ if (itemLeft > currentScroll + 1) {
309
+ targetScroll = itemLeft;
310
+ break;
311
+ }
312
+ }
313
+ container.scrollTo({ left: Math.max(0, targetScroll), behavior: 'smooth' });
314
+ // Update scroll state after animation
315
+ setTimeout(() => this.updateScrollState(), 300);
316
+ };
317
+ togglePopover = () => {
318
+ this.popoverOpen = !this.popoverOpen;
319
+ };
320
+ closePopover = () => {
321
+ this.popoverOpen = false;
322
+ };
323
+ toggleAllMenu = () => {
324
+ this.allMenuOpen = !this.allMenuOpen;
325
+ };
326
+ closeAllMenu = () => {
327
+ this.allMenuOpen = false;
328
+ };
329
+ handleItemClick = (_e, id) => {
330
+ // Close popover when an item inside is clicked
331
+ const originalItem = this.itemMap.get(id);
332
+ if (originalItem) {
333
+ // Clone the click to the original item
334
+ const cloneEvent = new MouseEvent('click', {
335
+ bubbles: true,
336
+ cancelable: true,
337
+ view: window,
338
+ });
339
+ originalItem.dispatchEvent(cloneEvent);
340
+ }
341
+ this.closePopover();
342
+ this.closeAllMenu();
343
+ };
344
+ renderMoreButton() {
345
+ const hasSlottedMore = this.el.querySelector('[slot="more"]');
346
+ return (h("button", { class: "bar-more-button", part: "more-button", ref: el => (this.moreButtonEl = el), onClick: this.togglePopover, "aria-expanded": String(this.popoverOpen), "aria-haspopup": "true" }, hasSlottedMore ? h("slot", { name: "more" }) : h("le-icon", { name: "ellipsis-horizontal" })));
347
+ }
348
+ renderHamburgerButton() {
349
+ const hasSlottedHamburger = this.el.querySelector('[slot="hamburger"]');
350
+ return (h("button", { class: "bar-hamburger-button", part: "hamburger-button", onClick: this.togglePopover, "aria-expanded": String(this.popoverOpen), "aria-haspopup": "true" }, hasSlottedHamburger ? h("slot", { name: "hamburger" }) : h("le-icon", { name: "hamburger" })));
351
+ }
352
+ renderScrollArrows() {
353
+ if (!this.arrows || this.overflow !== 'scroll')
354
+ return null;
355
+ const hasSlottedStartArrow = this.el.querySelector('[slot="start-arrow"]');
356
+ const hasSlottedEndArrow = this.el.querySelector('[slot="end-arrow"]');
357
+ return [
358
+ h("button", { class: classnames('bar-arrow', 'bar-arrow-start', {
359
+ disabled: !this.canScrollStart,
360
+ }), part: "arrow-start", onClick: this.scrollToStart, disabled: !this.canScrollStart, "aria-label": "Scroll to start" }, hasSlottedStartArrow ? (h("slot", { name: "start-arrow" })) : (h("le-icon", { name: "chevron-down", class: "arrow-icon-start" }))),
361
+ h("button", { class: classnames('bar-arrow', 'bar-arrow-end', {
362
+ disabled: !this.canScrollEnd,
363
+ }), part: "arrow-end", onClick: this.scrollToEnd, disabled: !this.canScrollEnd, "aria-label": "Scroll to end" }, hasSlottedEndArrow ? (h("slot", { name: "end-arrow" })) : (h("le-icon", { name: "chevron-down", class: "arrow-icon-end" }))),
364
+ ];
365
+ }
366
+ renderAllMenuButton() {
367
+ if (!this.showAllMenu)
368
+ return null;
369
+ const hasSlottedAllMenu = this.el.querySelector('[slot="all-menu"]');
370
+ return (h("button", { class: "bar-all-menu-button", part: "all-menu-button", onClick: this.toggleAllMenu, "aria-expanded": String(this.allMenuOpen), "aria-haspopup": "true" }, hasSlottedAllMenu ? h("slot", { name: "all-menu" }) : h("le-icon", { name: "hamburger" })));
371
+ }
372
+ renderPopoverContent(itemsToShow) {
373
+ return (h("div", { class: "bar-popover-content", part: "popover-content" }, itemsToShow.map(({ id, item }) => (h("div", { class: "bar-popover-item", key: id, onClick: (e) => this.handleItemClick(e, id), innerHTML: item.outerHTML })))));
374
+ }
375
+ renderOverflowPopover() {
376
+ if (this.overflow !== 'more' && this.overflow !== 'hamburger')
377
+ return null;
378
+ const items = this.getSlottedItems();
379
+ let itemsToShow = [];
380
+ if (this.overflow === 'hamburger' && this.hamburgerActive) {
381
+ // Show all items in hamburger mode
382
+ itemsToShow = items.map((item, index) => ({
383
+ id: this.getItemId(item, index),
384
+ item,
385
+ }));
386
+ }
387
+ else if (this.overflow === 'more' && this.overflowingIds.size > 0) {
388
+ // Show only overflowing items
389
+ itemsToShow = items
390
+ .map((item, index) => ({
391
+ id: this.getItemId(item, index),
392
+ item,
393
+ }))
394
+ .filter(({ id }) => this.overflowingIds.has(id));
395
+ }
396
+ if (itemsToShow.length === 0)
397
+ return null;
398
+ return (h("le-popover", { mode: "default", open: this.popoverOpen, position: "bottom", align: "end", showClose: false, closeOnClickOutside: true, closeOnEscape: true, onLePopoverClose: this.closePopover }, h("div", { slot: "trigger", class: "bar-overflow-trigger" }, this.overflow === 'hamburger' ? this.renderHamburgerButton() : this.renderMoreButton()), this.renderPopoverContent(itemsToShow)));
399
+ }
400
+ renderAllMenuPopover() {
401
+ if (!this.showAllMenu)
402
+ return null;
403
+ const items = this.getSlottedItems();
404
+ const itemsToShow = items.map((item, index) => ({
405
+ id: this.getItemId(item, index),
406
+ item,
407
+ }));
408
+ const position = this.showAllMenu === 'start' ? 'start' : 'end';
409
+ return (h("le-popover", { mode: "default", open: this.allMenuOpen, position: "bottom", align: position, showClose: false, closeOnClickOutside: true, closeOnEscape: true, onLePopoverClose: this.closeAllMenu }, h("div", { slot: "trigger", class: "bar-all-menu-trigger" }, this.renderAllMenuButton()), this.renderPopoverContent(itemsToShow)));
410
+ }
411
+ render() {
412
+ const showOverflowButton = !this.disablePopover &&
413
+ ((this.overflow === 'more' && this.overflowingIds.size > 0) ||
414
+ (this.overflow === 'hamburger' && this.hamburgerActive));
415
+ const containerStyle = {};
416
+ if (this.containerHeight !== null &&
417
+ (this.overflow === 'more' || this.overflow === 'hamburger')) {
418
+ containerStyle.height = `${this.containerHeight}px`;
419
+ }
420
+ const showAllMenuAtStart = this.showAllMenu === 'start';
421
+ const showAllMenuAtEnd = this.showAllMenu === true || this.showAllMenu === 'end';
422
+ return (h(Host, { key: 'ee31d28cdad15267c6a31503d1a102d050114af1', class: classnames({
423
+ 'overflow-more': this.overflow === 'more',
424
+ 'overflow-scroll': this.overflow === 'scroll',
425
+ 'overflow-hamburger': this.overflow === 'hamburger',
426
+ 'overflow-wrap': this.overflow === 'wrap',
427
+ 'hamburger-active': this.hamburgerActive,
428
+ 'has-overflow': this.overflowingIds.size > 0 || this.hamburgerActive,
429
+ }) }, h("div", { key: 'd9dbc7ccd3256697362f701dcef24b26e6c36765', class: classnames('bar-container', {
430
+ [`align-${this.alignItems}`]: true,
431
+ }), part: "container" }, this.overflow === 'scroll' && this.arrows && (h("div", { key: '08e73b775740388f2b6bdb5f85965870713d119c', class: "bar-controls bar-controls-start" }, this.renderScrollArrows()?.[0])), showAllMenuAtStart && (h("div", { key: '919e6491693afb2095c4100744f53aa266f142d1', class: "bar-controls bar-controls-start" }, this.renderAllMenuPopover())), h("div", { key: '9a8251f1a1fe359efc266fb4787010f140ab4f5a', class: classnames('bar-items', {
432
+ 'is-scrollable': this.overflow === 'scroll',
433
+ 'is-wrapping': this.overflow === 'wrap',
434
+ }), style: containerStyle, ref: el => {
435
+ this.itemsContainerEl = el;
436
+ this.observeContainer(el);
437
+ }, onScroll: this.overflow === 'scroll' ? this.handleScroll : undefined }, h("slot", { key: '89f54e7a897583fec944db086958f5211df4e347' })), showOverflowButton && (h("div", { key: 'b7a2eab419de82a26d8af0a352706737c07f3d5e', class: "bar-controls bar-controls-end" }, this.renderOverflowPopover())), showAllMenuAtEnd && (h("div", { key: '1dd1b9d97f389f4668a69643f8ff4424c847e85f', class: "bar-controls bar-controls-end" }, this.renderAllMenuPopover())), this.overflow === 'scroll' && this.arrows && (h("div", { key: '5f0abf7e091380b5e6769127271c192b56e8f573', class: "bar-controls bar-controls-end" }, this.renderScrollArrows()?.[1])))));
438
+ }
439
+ static get is() { return "le-bar"; }
440
+ static get encapsulation() { return "shadow"; }
441
+ static get originalStyleUrls() {
442
+ return {
443
+ "$": ["le-bar.css"]
444
+ };
445
+ }
446
+ static get styleUrls() {
447
+ return {
448
+ "$": ["le-bar.css"]
449
+ };
450
+ }
451
+ static get properties() {
452
+ return {
453
+ "overflow": {
454
+ "type": "string",
455
+ "mutable": false,
456
+ "complexType": {
457
+ "original": "'more' | 'scroll' | 'hamburger' | 'wrap'",
458
+ "resolved": "\"hamburger\" | \"more\" | \"scroll\" | \"wrap\"",
459
+ "references": {}
460
+ },
461
+ "required": false,
462
+ "optional": false,
463
+ "docs": {
464
+ "tags": [],
465
+ "text": "Overflow behavior when items don't fit on one row.\n- `more`: Overflow items appear in a \"more\" dropdown\n- `scroll`: Items scroll horizontally with optional arrows\n- `hamburger`: All items go into a hamburger menu if any overflow\n- `wrap`: Items wrap to additional rows"
466
+ },
467
+ "getter": false,
468
+ "setter": false,
469
+ "reflect": true,
470
+ "attribute": "overflow",
471
+ "defaultValue": "'more'"
472
+ },
473
+ "alignItems": {
474
+ "type": "string",
475
+ "mutable": false,
476
+ "complexType": {
477
+ "original": "'start' | 'end' | 'center' | 'stretch'",
478
+ "resolved": "\"center\" | \"end\" | \"start\" | \"stretch\"",
479
+ "references": {}
480
+ },
481
+ "required": false,
482
+ "optional": false,
483
+ "docs": {
484
+ "tags": [],
485
+ "text": "Alignment of items within the bar (maps to justify-content)."
486
+ },
487
+ "getter": false,
488
+ "setter": false,
489
+ "reflect": true,
490
+ "attribute": "align-items",
491
+ "defaultValue": "'start'"
492
+ },
493
+ "arrows": {
494
+ "type": "boolean",
495
+ "mutable": false,
496
+ "complexType": {
497
+ "original": "boolean",
498
+ "resolved": "boolean",
499
+ "references": {}
500
+ },
501
+ "required": false,
502
+ "optional": false,
503
+ "docs": {
504
+ "tags": [],
505
+ "text": "Show scroll arrows when overflow is \"scroll\"."
506
+ },
507
+ "getter": false,
508
+ "setter": false,
509
+ "reflect": false,
510
+ "attribute": "arrows",
511
+ "defaultValue": "false"
512
+ },
513
+ "disablePopover": {
514
+ "type": "boolean",
515
+ "mutable": false,
516
+ "complexType": {
517
+ "original": "boolean",
518
+ "resolved": "boolean",
519
+ "references": {}
520
+ },
521
+ "required": false,
522
+ "optional": false,
523
+ "docs": {
524
+ "tags": [],
525
+ "text": "Disable the internal overflow popover.\nWhen true, the bar still detects overflow and hides items,\nbut doesn't render its own popover. Use this when providing\ncustom overflow handling via the leBarOverflowChange event."
526
+ },
527
+ "getter": false,
528
+ "setter": false,
529
+ "reflect": false,
530
+ "attribute": "disable-popover",
531
+ "defaultValue": "false"
532
+ },
533
+ "showAllMenu": {
534
+ "type": "any",
535
+ "mutable": false,
536
+ "complexType": {
537
+ "original": "boolean | 'start' | 'end'",
538
+ "resolved": "\"end\" | \"start\" | boolean",
539
+ "references": {}
540
+ },
541
+ "required": false,
542
+ "optional": false,
543
+ "docs": {
544
+ "tags": [],
545
+ "text": "Show an \"all items\" menu button.\n- `false`: Don't show\n- `true` or `'end'`: Show at end\n- `'start'`: Show at start"
546
+ },
547
+ "getter": false,
548
+ "setter": false,
549
+ "reflect": false,
550
+ "attribute": "show-all-menu",
551
+ "defaultValue": "false"
552
+ }
553
+ };
554
+ }
555
+ static get states() {
556
+ return {
557
+ "popoverOpen": {},
558
+ "hamburgerActive": {},
559
+ "overflowingIds": {},
560
+ "canScrollStart": {},
561
+ "canScrollEnd": {},
562
+ "allMenuOpen": {},
563
+ "containerHeight": {}
564
+ };
565
+ }
566
+ static get events() {
567
+ return [{
568
+ "method": "leBarOverflowChange",
569
+ "name": "leBarOverflowChange",
570
+ "bubbles": true,
571
+ "cancelable": true,
572
+ "composed": true,
573
+ "docs": {
574
+ "tags": [],
575
+ "text": "Emitted when overflow state changes."
576
+ },
577
+ "complexType": {
578
+ "original": "LeBarOverflowChangeDetail",
579
+ "resolved": "LeBarOverflowChangeDetail",
580
+ "references": {
581
+ "LeBarOverflowChangeDetail": {
582
+ "location": "local",
583
+ "path": "/home/runner/work/le-kit/le-kit/src/components/le-bar/le-bar.tsx",
584
+ "id": "src/components/le-bar/le-bar.tsx::LeBarOverflowChangeDetail"
585
+ }
586
+ }
587
+ }
588
+ }];
589
+ }
590
+ static get methods() {
591
+ return {
592
+ "recalculate": {
593
+ "complexType": {
594
+ "signature": "() => Promise<void>",
595
+ "parameters": [],
596
+ "references": {
597
+ "Promise": {
598
+ "location": "global",
599
+ "id": "global::Promise"
600
+ }
601
+ },
602
+ "return": "Promise<void>"
603
+ },
604
+ "docs": {
605
+ "text": "Force recalculation of overflow state.",
606
+ "tags": []
607
+ }
608
+ }
609
+ };
610
+ }
611
+ static get elementRef() { return "el"; }
612
+ static get watchers() {
613
+ return [{
614
+ "propName": "overflow",
615
+ "methodName": "handleOverflowChange"
616
+ }];
617
+ }
618
+ static get listeners() {
619
+ return [{
620
+ "name": "slotchange",
621
+ "method": "handleSlotChange",
622
+ "target": undefined,
623
+ "capture": false,
624
+ "passive": false
625
+ }];
626
+ }
627
+ }
628
+ //# sourceMappingURL=le-bar.js.map