quilt-vanilla 0.1.0

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/action-icons.d.ts +18 -0
  4. package/dist/action-icons.d.ts.map +1 -0
  5. package/dist/action-icons.js +36 -0
  6. package/dist/action-icons.js.map +1 -0
  7. package/dist/chrome-icons.d.ts +3 -0
  8. package/dist/chrome-icons.d.ts.map +1 -0
  9. package/dist/chrome-icons.js +32 -0
  10. package/dist/chrome-icons.js.map +1 -0
  11. package/dist/corners.d.ts +8 -0
  12. package/dist/corners.d.ts.map +1 -0
  13. package/dist/corners.js +205 -0
  14. package/dist/corners.js.map +1 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +5 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/lifetime.d.ts +10 -0
  20. package/dist/lifetime.d.ts.map +1 -0
  21. package/dist/lifetime.js +44 -0
  22. package/dist/lifetime.js.map +1 -0
  23. package/dist/menu.d.ts +10 -0
  24. package/dist/menu.d.ts.map +1 -0
  25. package/dist/menu.js +356 -0
  26. package/dist/menu.js.map +1 -0
  27. package/dist/panes.d.ts +13 -0
  28. package/dist/panes.d.ts.map +1 -0
  29. package/dist/panes.js +58 -0
  30. package/dist/panes.js.map +1 -0
  31. package/dist/picker.d.ts +6 -0
  32. package/dist/picker.d.ts.map +1 -0
  33. package/dist/picker.js +112 -0
  34. package/dist/picker.js.map +1 -0
  35. package/dist/registry.d.ts +25 -0
  36. package/dist/registry.d.ts.map +1 -0
  37. package/dist/registry.js +39 -0
  38. package/dist/registry.js.map +1 -0
  39. package/dist/renderer.d.ts +3 -0
  40. package/dist/renderer.d.ts.map +1 -0
  41. package/dist/renderer.js +570 -0
  42. package/dist/renderer.js.map +1 -0
  43. package/dist/resize.d.ts +7 -0
  44. package/dist/resize.d.ts.map +1 -0
  45. package/dist/resize.js +56 -0
  46. package/dist/resize.js.map +1 -0
  47. package/dist/shortcuts.d.ts +6 -0
  48. package/dist/shortcuts.d.ts.map +1 -0
  49. package/dist/shortcuts.js +64 -0
  50. package/dist/shortcuts.js.map +1 -0
  51. package/dist/styles.css +842 -0
  52. package/dist/tab-bar.d.ts +6 -0
  53. package/dist/tab-bar.d.ts.map +1 -0
  54. package/dist/tab-bar.js +336 -0
  55. package/dist/tab-bar.js.map +1 -0
  56. package/dist/tab-tooltip.d.ts +4 -0
  57. package/dist/tab-tooltip.d.ts.map +1 -0
  58. package/dist/tab-tooltip.js +95 -0
  59. package/dist/tab-tooltip.js.map +1 -0
  60. package/dist/tabs.d.ts +15 -0
  61. package/dist/tabs.d.ts.map +1 -0
  62. package/dist/tabs.js +126 -0
  63. package/dist/tabs.js.map +1 -0
  64. package/dist/theme.d.ts +206 -0
  65. package/dist/theme.d.ts.map +1 -0
  66. package/dist/theme.js +166 -0
  67. package/dist/theme.js.map +1 -0
  68. package/dist/types.d.ts +66 -0
  69. package/dist/types.d.ts.map +1 -0
  70. package/dist/types.js +2 -0
  71. package/dist/types.js.map +1 -0
  72. package/dist/windows.d.ts +23 -0
  73. package/dist/windows.d.ts.map +1 -0
  74. package/dist/windows.js +247 -0
  75. package/dist/windows.js.map +1 -0
  76. package/package.json +50 -0
  77. package/src/action-icons.ts +40 -0
  78. package/src/chrome-icons.ts +30 -0
  79. package/src/corners.ts +259 -0
  80. package/src/index.ts +27 -0
  81. package/src/lifetime.ts +46 -0
  82. package/src/menu.ts +432 -0
  83. package/src/panes.ts +76 -0
  84. package/src/picker.ts +114 -0
  85. package/src/registry.ts +46 -0
  86. package/src/renderer.ts +654 -0
  87. package/src/resize.ts +65 -0
  88. package/src/shortcuts.ts +90 -0
  89. package/src/styles.css +842 -0
  90. package/src/tab-bar.ts +382 -0
  91. package/src/tab-tooltip.ts +96 -0
  92. package/src/tabs.ts +129 -0
  93. package/src/theme.ts +211 -0
  94. package/src/types.ts +67 -0
  95. package/src/windows.ts +244 -0
@@ -0,0 +1,6 @@
1
+ import type { TabBarOptions, TabBarStyle } from './types.js';
2
+ import type { Scope } from './lifetime.js';
3
+ export declare function validateTabBar(options: TabBarOptions): void;
4
+ /** Chrome measurement never mounts or replaces application pane views. */
5
+ export declare function bindTabBar(region: HTMLElement, header: HTMLElement, root: HTMLElement, scope: Scope, getStyle: () => TabBarStyle): () => void;
6
+ //# sourceMappingURL=tab-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-bar.d.ts","sourceRoot":"","sources":["../src/tab-bar.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,QA2BpD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,WAAW,cAsV5B"}
@@ -0,0 +1,336 @@
1
+ import { bindTabTooltip } from './tab-tooltip.js';
2
+ export function validateTabBar(options) {
3
+ for (const style of [options, ...Object.values(options.regions ?? {})]) {
4
+ for (const [key, values] of Object.entries({
5
+ display: ['automatic', 'compact'],
6
+ attachment: ['anchored', 'floating'],
7
+ fit: ['full', 'fit'],
8
+ corners: ['fitted', 'rounded', 'capsule'],
9
+ })) {
10
+ const value = style[key];
11
+ if (value !== undefined && !values.includes(String(value)))
12
+ throw new Error(`Unknown tab bar ${key}`);
13
+ }
14
+ if (style.placement !== undefined && !['top', 'left'].includes(style.placement))
15
+ throw new Error('Unknown tab bar placement');
16
+ if (style.mode !== undefined && !['full', 'tapered'].includes(style.mode))
17
+ throw new Error('Unknown tab bar mode');
18
+ if (style.shape !== undefined &&
19
+ !['angle', 'round', 'scoop', 'vertical', 'rounded'].includes(style.shape))
20
+ throw new Error('Unknown tab bar shape');
21
+ if (style.taperWidth !== undefined &&
22
+ (!Number.isFinite(style.taperWidth) || style.taperWidth <= 0))
23
+ throw new Error('Tab bar taperWidth must be positive and finite');
24
+ }
25
+ }
26
+ /** Chrome measurement never mounts or replaces application pane views. */
27
+ export function bindTabBar(region, header, root, scope, getStyle) {
28
+ const doc = region.ownerDocument, win = doc.defaultView;
29
+ const drawChrome = (natural, occupied, height, capWidth, fits, left, style) => {
30
+ if (style.attachment === 'floating')
31
+ return;
32
+ if (fits && capWidth > 0) {
33
+ const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
34
+ svg.classList.add('layouts-tab-cap');
35
+ svg.setAttribute('aria-hidden', 'true');
36
+ svg.setAttribute('viewBox', '0 0 1 1');
37
+ svg.setAttribute('preserveAspectRatio', 'none');
38
+ svg.style.width = `${left ? height : capWidth}px`;
39
+ if (left)
40
+ svg.style.height = `${capWidth}px`;
41
+ const path = doc.createElementNS(svg.namespaceURI, 'path');
42
+ const curve = style.shape === 'round'
43
+ ? 'A1 1 0 0 0 1 0'
44
+ : style.shape === 'scoop'
45
+ ? 'A1 1 0 0 1 1 0'
46
+ : 'L1 0';
47
+ path.setAttribute('d', `M0 1 ${curve} H0 Z`);
48
+ if (left)
49
+ path.setAttribute('transform', 'matrix(0 1 1 0 0 0)');
50
+ svg.append(path);
51
+ header.append(svg);
52
+ }
53
+ // A single closed, inset outline covers the controls and cap. Splitting
54
+ // this between CSS borders and SVG strokes leaves seams and clipped edges.
55
+ const outline = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
56
+ outline.classList.add('layouts-tab-outline');
57
+ outline.setAttribute('aria-hidden', 'true');
58
+ outline.setAttribute('viewBox', `0 0 ${left ? height : occupied} ${left ? occupied : height}`);
59
+ outline.style.width = `${left ? height : occupied}px`;
60
+ outline.style.height = `${left ? occupied : height}px`;
61
+ const edge = doc.createElementNS(outline.namespaceURI, 'path');
62
+ const right = Math.max(0.5, occupied - 0.5);
63
+ const bottom = Math.max(0.5, height - 0.5);
64
+ const end = fits && capWidth > 0 ? natural : right;
65
+ const curve = fits && capWidth > 0
66
+ ? style.shape === 'round' || style.shape === 'scoop'
67
+ ? `A${Math.max(0.01, right - end)} ${Math.max(0.01, bottom - 0.5)} 0 0 ${style.shape === 'round' ? 1 : 0} ${end} ${bottom}`
68
+ : `L${end} ${bottom}`
69
+ : `V${bottom}`;
70
+ if (style.shape === 'rounded') {
71
+ const radius = Math.max(0, Math.min(parseFloat(win.getComputedStyle(header).borderTopLeftRadius) || 0, (right - 0.5) / 2, (bottom - 0.5) / 2));
72
+ edge.setAttribute('d', `M${0.5 + radius} 0.5 H${right - radius} Q${right} 0.5 ${right} ${0.5 + radius} V${bottom - radius} Q${right} ${bottom} ${right - radius} ${bottom} H${0.5 + radius} Q0.5 ${bottom} 0.5 ${bottom - radius} V${0.5 + radius} Q0.5 0.5 ${0.5 + radius} 0.5 Z`);
73
+ }
74
+ else
75
+ edge.setAttribute('d', `M0.5 0.5 H${right} ${curve} H0.5 Z`);
76
+ if (left)
77
+ edge.setAttribute('transform', 'matrix(0 1 1 0 0 0)');
78
+ const shared = region.dataset.sharedEdges?.split(' ') ?? [];
79
+ const w = left ? height : occupied;
80
+ const h = left ? occupied : height;
81
+ // Clip only decorative strokes on edges owned by an ancestor split.
82
+ const insets = [
83
+ shared.includes('top') ? 1 : 0,
84
+ shared.includes('right') && w >= region.clientWidth - 0.5 ? 1 : 0,
85
+ shared.includes('bottom') && h >= region.clientHeight - 0.5 ? 1 : 0,
86
+ shared.includes('left') ? 1 : 0,
87
+ ];
88
+ outline.style.clipPath = `inset(${insets.map((value) => `${value}px`).join(' ')})`;
89
+ outline.append(edge);
90
+ header.append(outline);
91
+ };
92
+ const refreshTooltip = bindTabTooltip(region, header, root, scope);
93
+ let frame = 0, disposed = false;
94
+ const observedContent = new Set();
95
+ const contentResize = new ResizeObserver(() => schedule());
96
+ const scrollbarClearance = () => {
97
+ const next = new Set();
98
+ const bounds = region.getBoundingClientRect();
99
+ let right = 0, bottom = 0;
100
+ const body = region.querySelector(':scope > .layouts-body');
101
+ if (body) {
102
+ for (const element of [body, ...body.querySelectorAll('*')]) {
103
+ if (!element.clientWidth || !element.clientHeight)
104
+ continue;
105
+ const css = win.getComputedStyle(element);
106
+ if (!/(auto|scroll)/.test(css.overflowX + css.overflowY))
107
+ continue;
108
+ next.add(element);
109
+ for (const child of element.children)
110
+ next.add(child);
111
+ const rect = element.getBoundingClientRect();
112
+ const fallback = parseFloat(css.getPropertyValue('--layouts-scrollbar-size')) || 6;
113
+ // Overlay scrollbars report zero gutter: use the themed size then.
114
+ if (/(auto|scroll)/.test(css.overflowY) &&
115
+ element.scrollHeight > element.clientHeight &&
116
+ Math.abs(bounds.right - rect.right) < 1) {
117
+ const gutter = element.offsetWidth -
118
+ element.clientWidth -
119
+ (parseFloat(css.borderLeftWidth) || 0) -
120
+ (parseFloat(css.borderRightWidth) || 0);
121
+ right = Math.max(right, gutter, fallback);
122
+ }
123
+ if (/(auto|scroll)/.test(css.overflowX) &&
124
+ element.scrollWidth > element.clientWidth &&
125
+ Math.abs(bounds.bottom - rect.bottom) < 1) {
126
+ const gutter = element.offsetHeight -
127
+ element.clientHeight -
128
+ (parseFloat(css.borderTopWidth) || 0) -
129
+ (parseFloat(css.borderBottomWidth) || 0);
130
+ bottom = Math.max(bottom, gutter, fallback);
131
+ }
132
+ }
133
+ }
134
+ for (const element of observedContent)
135
+ if (!next.has(element))
136
+ contentResize.unobserve(element);
137
+ for (const element of next)
138
+ if (!observedContent.has(element))
139
+ contentResize.observe(element);
140
+ observedContent.clear();
141
+ for (const element of next)
142
+ observedContent.add(element);
143
+ return { right, bottom };
144
+ };
145
+ const measure = () => {
146
+ frame = 0;
147
+ if (disposed || !region.isConnected)
148
+ return;
149
+ const style = getStyle();
150
+ const left = style.placement === 'left';
151
+ const compact = style.display === 'compact';
152
+ region.dataset.tabDisplay = compact ? 'compact' : 'automatic';
153
+ header.dataset.tabDisplay = compact ? 'compact' : 'automatic';
154
+ const floating = style.attachment === 'floating';
155
+ const padding = parseFloat(win.getComputedStyle(region).getPropertyValue('--layouts-panel-padding'));
156
+ const inset = floating ? (Number.isFinite(padding) ? Math.max(0, padding) : 8) : 0;
157
+ const scrollbar = floating ? scrollbarClearance() : { right: 0, bottom: 0 };
158
+ const insetX = inset;
159
+ const insetY = inset;
160
+ header.style.setProperty('--layouts-floating-inset-x', `${insetX}px`);
161
+ header.style.setProperty('--layouts-floating-inset-y', `${insetY}px`);
162
+ if (!floating) {
163
+ contentResize.disconnect();
164
+ observedContent.clear();
165
+ }
166
+ const tapered = floating || style.mode === 'tapered';
167
+ region.dataset.tabAttachment = floating ? 'floating' : 'anchored';
168
+ header.dataset.tabCorners = floating
169
+ ? (style.corners ?? 'rounded')
170
+ : style.shape === 'rounded'
171
+ ? 'rounded'
172
+ : 'fitted';
173
+ if (!left)
174
+ header.style.removeProperty('height');
175
+ region.dataset.tabPlacement = left ? 'left' : 'top';
176
+ refreshTooltip();
177
+ header
178
+ .querySelector('[role=tablist]')
179
+ ?.setAttribute('aria-orientation', left ? 'vertical' : 'horizontal');
180
+ region.dataset.tabBar = tapered ? 'tapered' : 'full';
181
+ header.dataset.tabBarShape = style.shape ?? 'angle';
182
+ header.querySelector('.layouts-tab-cap')?.remove();
183
+ header.querySelector('.layouts-tab-outline')?.remove();
184
+ const items = Array.from(header.querySelectorAll('.layouts-tab-item'));
185
+ header.dataset.tabBarEmpty = String(tapered && !items.length);
186
+ const height = header.hidden ? 0 : header.getBoundingClientRect().height;
187
+ // clientWidth rounds fractional split widths up, allowing chrome to spill
188
+ // outside the region and change the stage's scrollbar/resize geometry.
189
+ const available = Math.max(0, parseFloat(win.getComputedStyle(region).width) - insetX * 2 - scrollbar.right);
190
+ let occupied = available;
191
+ if (left) {
192
+ header.style.removeProperty('width');
193
+ for (const item of items)
194
+ item.style.removeProperty('--layouts-tab-preferred-width');
195
+ const width = header.hidden ? 0 : header.getBoundingClientRect().width;
196
+ const regionHeight = Math.max(0, parseFloat(win.getComputedStyle(region).height) - insetY * 2 - scrollbar.bottom);
197
+ let occupiedHeight = regionHeight;
198
+ if (tapered && width) {
199
+ const computed = win.getComputedStyle(header);
200
+ const list = header.querySelector('.layouts-tabs');
201
+ const controls = Array.from(header.querySelectorAll(':scope > .layouts-button'));
202
+ const natural = items.reduce((sum, item) => sum + parseFloat(win.getComputedStyle(item).flexBasis), 0) +
203
+ Math.max(0, items.length - 1) * (parseFloat(win.getComputedStyle(list).rowGap) || 0) +
204
+ controls.reduce((sum, control) => sum + control.getBoundingClientRect().height, 0) +
205
+ Math.max(0, controls.length - (items.length ? 0 : 1)) *
206
+ (parseFloat(computed.rowGap) || 0) +
207
+ parseFloat(computed.paddingTop) +
208
+ parseFloat(computed.paddingBottom);
209
+ const cap = floating || ['vertical', 'rounded'].includes(style.shape ?? '')
210
+ ? 0
211
+ : (style.taperWidth ?? width);
212
+ const fits = !(floating && style.fit === 'full') &&
213
+ natural + cap + (floating ? 0 : 12) <= regionHeight;
214
+ occupiedHeight = fits ? natural + cap : regionHeight;
215
+ header.style.height = `${fits ? natural : regionHeight}px`;
216
+ region.dataset.tabBarFilled = String(!fits);
217
+ drawChrome(natural, occupiedHeight, width, cap, fits, true, style);
218
+ }
219
+ else {
220
+ header.style.removeProperty('height');
221
+ delete region.dataset.tabBarFilled;
222
+ }
223
+ region.style.setProperty('--layouts-tab-bar-width', `${occupiedHeight ? width + insetX : 0}px`);
224
+ region.style.setProperty('--layouts-tab-bar-height', `${width ? occupiedHeight + insetY : 0}px`);
225
+ return;
226
+ }
227
+ if (!tapered) {
228
+ header.style.removeProperty('width');
229
+ for (const item of items)
230
+ item.style.removeProperty('--layouts-tab-preferred-width');
231
+ delete region.dataset.tabBarFilled;
232
+ }
233
+ else if (!height) {
234
+ header.style.width = '0px';
235
+ occupied = 0;
236
+ region.dataset.tabBarFilled = 'false';
237
+ }
238
+ else {
239
+ // Inline-size container queries suppress intrinsic sizing. Measure a hidden,
240
+ // noninteractive copy with containment disabled, including real icons/fonts.
241
+ const probe = header.cloneNode(true);
242
+ probe.classList.add('layouts-tab-measure');
243
+ probe.setAttribute('aria-hidden', 'true');
244
+ probe.inert = true;
245
+ probe.removeAttribute('id');
246
+ for (const node of probe.querySelectorAll('[id]'))
247
+ node.removeAttribute('id');
248
+ root.append(probe);
249
+ try {
250
+ const widths = Array.from(probe.querySelectorAll('.layouts-tab-item')).map((item) => Math.ceil(item.getBoundingClientRect().width));
251
+ const computed = win.getComputedStyle(probe);
252
+ const controls = Array.from(probe.querySelectorAll(':scope > .layouts-button'));
253
+ const tabGap = parseFloat(win.getComputedStyle(probe.querySelector('.layouts-tabs')).columnGap) || 0;
254
+ const natural = Math.ceil(widths.reduce((sum, width) => sum + width, 0) +
255
+ Math.max(0, widths.length - 1) * tabGap +
256
+ controls.reduce((sum, control) => sum + control.getBoundingClientRect().width, 0) +
257
+ parseFloat(computed.paddingLeft) +
258
+ parseFloat(computed.paddingRight) +
259
+ Math.max(0, controls.length - (items.length ? 0 : 1)) *
260
+ (parseFloat(computed.columnGap) || 0));
261
+ const capWidth = floating || ['vertical', 'rounded'].includes(style.shape ?? '')
262
+ ? 0
263
+ : (style.taperWidth ?? height);
264
+ // Leave breathing room at the pane edge instead of showing a nearly
265
+ // touching cap. This clearance is not part of the occupied footprint.
266
+ const edgeClearance = floating ? 0 : 12;
267
+ const fits = !(floating && style.fit === 'full') && natural + capWidth + edgeClearance <= available;
268
+ items.forEach((item, index) => item.style.setProperty('--layouts-tab-preferred-width', `${widths[index]}px`));
269
+ region.dataset.tabBarFilled = String(!fits);
270
+ header.style.width = `${fits ? natural : available}px`;
271
+ occupied = fits ? natural + capWidth : available;
272
+ drawChrome(natural, occupied, height, capWidth, fits, false, style);
273
+ }
274
+ finally {
275
+ probe.remove();
276
+ }
277
+ }
278
+ region.style.setProperty('--layouts-tab-bar-width', `${height ? occupied + insetX : 0}px`);
279
+ region.style.setProperty('--layouts-tab-bar-height', `${height ? height + insetY : 0}px`);
280
+ };
281
+ const schedule = () => {
282
+ if (!disposed && !frame)
283
+ frame = win.requestAnimationFrame(measure);
284
+ };
285
+ let observedHeaderCrossSize = -1;
286
+ const resize = new ResizeObserver((entries) => {
287
+ let changed = false;
288
+ for (const entry of entries) {
289
+ if (entry.target === region)
290
+ changed = true;
291
+ else if ((getStyle().placement === 'left' ? entry.contentRect.width : entry.contentRect.height) !==
292
+ observedHeaderCrossSize) {
293
+ observedHeaderCrossSize =
294
+ getStyle().placement === 'left' ? entry.contentRect.width : entry.contentRect.height;
295
+ changed = true;
296
+ }
297
+ }
298
+ // Header width is our output, not a measurement input. Observing our own
299
+ // width writes feeds compression changes back into another measurement.
300
+ if (changed)
301
+ schedule();
302
+ });
303
+ resize.observe(region);
304
+ resize.observe(header);
305
+ const mutation = new MutationObserver(schedule);
306
+ for (let node = root; node; node = node.parentElement)
307
+ mutation.observe(node, { attributes: true, attributeFilter: ['style', 'class'] });
308
+ mutation.observe(doc.head, { subtree: true, childList: true, characterData: true });
309
+ const body = region.querySelector(':scope > .layouts-body');
310
+ const contentMutation = new MutationObserver(() => {
311
+ if (getStyle().attachment === 'floating')
312
+ schedule();
313
+ });
314
+ if (body)
315
+ contentMutation.observe(body, {
316
+ subtree: true,
317
+ childList: true,
318
+ characterData: true,
319
+ attributes: true,
320
+ attributeFilter: ['class', 'style', 'hidden'],
321
+ });
322
+ scope.listen(doc.fonts, 'loadingdone', schedule);
323
+ void doc.fonts.ready.then(schedule);
324
+ scope.add(() => {
325
+ disposed = true;
326
+ if (frame)
327
+ win.cancelAnimationFrame(frame);
328
+ resize.disconnect();
329
+ mutation.disconnect();
330
+ contentMutation.disconnect();
331
+ contentResize.disconnect();
332
+ observedContent.clear();
333
+ });
334
+ return schedule;
335
+ }
336
+ //# sourceMappingURL=tab-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-bar.js","sourceRoot":"","sources":["../src/tab-bar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD,MAAM,UAAU,cAAc,CAAC,OAAsB;IACnD,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACvE,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC;YACzC,OAAO,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;YACjC,UAAU,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;YACpC,GAAG,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;YACpB,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;SAC1C,CAAC,EAAE,CAAC;YACH,MAAM,KAAK,GAAG,KAAK,CAAC,GAAwB,CAAC,CAAC;YAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxD,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,IACE,KAAK,CAAC,KAAK,KAAK,SAAS;YACzB,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;YAEzE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,IACE,KAAK,CAAC,UAAU,KAAK,SAAS;YAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;YAE7D,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CACxB,MAAmB,EACnB,MAAmB,EACnB,IAAiB,EACjB,KAAY,EACZ,QAA2B;IAE3B,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,EAC9B,GAAG,GAAG,GAAG,CAAC,WAAY,CAAC;IACzB,MAAM,UAAU,GAAG,CACjB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,QAAgB,EAChB,IAAa,EACb,IAAa,EACb,KAAkB,EAClB,EAAE;QACF,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO;QAC5C,IAAI,IAAI,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YACrE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YACxC,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACvC,GAAG,CAAC,YAAY,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;YAChD,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;YAClD,IAAI,IAAI;gBAAE,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,QAAQ,IAAI,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC3D,MAAM,KAAK,GACT,KAAK,CAAC,KAAK,KAAK,OAAO;gBACrB,CAAC,CAAC,gBAAgB;gBAClB,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,OAAO;oBACvB,CAAC,CAAC,gBAAgB;oBAClB,CAAC,CAAC,MAAM,CAAC;YACf,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC;YAC7C,IAAI,IAAI;gBAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;YAChE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,wEAAwE;QACxE,2EAA2E;QAC3E,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACzE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAC7C,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAC5C,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC;QACvD,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,GAAG,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QACnD,MAAM,KAAK,GACT,IAAI,IAAI,QAAQ,GAAG,CAAC;YAClB,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO;gBAClD,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,MAAM,EAAE;gBAC3H,CAAC,CAAC,IAAI,GAAG,IAAI,MAAM,EAAE;YACvB,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;QACnB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,CAAC,EACD,IAAI,CAAC,GAAG,CACN,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,EACjE,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,EACjB,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CACnB,CACF,CAAC;YACF,IAAI,CAAC,YAAY,CACf,GAAG,EACH,IAAI,GAAG,GAAG,MAAM,SAAS,KAAK,GAAG,MAAM,KAAK,KAAK,QAAQ,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,MAAM,GAAG,MAAM,KAAK,KAAK,IAAI,MAAM,IAAI,KAAK,GAAG,MAAM,IAAI,MAAM,KAAK,GAAG,GAAG,MAAM,SAAS,MAAM,QAAQ,MAAM,GAAG,MAAM,KAAK,GAAG,GAAG,MAAM,aAAa,GAAG,GAAG,MAAM,QAAQ,CAC5P,CAAC;QACJ,CAAC;;YAAM,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,KAAK,SAAS,CAAC,CAAC;QACpE,IAAI,IAAI;YAAE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QACnC,oEAAoE;QACpE,MAAM,MAAM,GAAG;YACb,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChC,CAAC;QACF,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACnF,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IACnE,IAAI,KAAK,GAAG,CAAC,EACX,QAAQ,GAAG,KAAK,CAAC;IACnB,MAAM,eAAe,GAAG,IAAI,GAAG,EAAW,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3D,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;QAC9C,IAAI,KAAK,GAAG,CAAC,EACX,MAAM,GAAG,CAAC,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAc,wBAAwB,CAAC,CAAC;QACzE,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAc,GAAG,CAAC,CAAC,EAAE,CAAC;gBACzE,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,YAAY;oBAAE,SAAS;gBAC5D,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAC1C,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;oBAAE,SAAS;gBACnE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAClB,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,QAAQ;oBAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACtD,MAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;gBAC7C,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,CAAC;gBACnF,mEAAmE;gBACnE,IACE,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;oBACnC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY;oBAC3C,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EACvC,CAAC;oBACD,MAAM,MAAM,GACV,OAAO,CAAC,WAAW;wBACnB,OAAO,CAAC,WAAW;wBACnB,CAAC,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;wBACtC,CAAC,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC1C,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAC5C,CAAC;gBACD,IACE,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;oBACnC,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW;oBACzC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EACzC,CAAC;oBACD,MAAM,MAAM,GACV,OAAO,CAAC,YAAY;wBACpB,OAAO,CAAC,YAAY;wBACpB,CAAC,UAAU,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;wBACrC,CAAC,UAAU,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC3C,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,eAAe;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAChG,KAAK,MAAM,OAAO,IAAI,IAAI;YAAE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9F,eAAe,CAAC,KAAK,EAAE,CAAC;QACxB,KAAK,MAAM,OAAO,IAAI,IAAI;YAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,KAAK,GAAG,CAAC,CAAC;QACV,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,WAAW;YAAE,OAAO;QAC5C,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC;QACxC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QAC9D,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QAC9D,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC;QACjD,MAAM,OAAO,GAAG,UAAU,CACxB,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CACzE,CAAC;QACF,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QAC5E,MAAM,MAAM,GAAG,KAAK,CAAC;QACrB,MAAM,MAAM,GAAG,KAAK,CAAC;QACrB,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;QACtE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,aAAa,CAAC,UAAU,EAAE,CAAC;YAC3B,eAAe,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;QACrD,MAAM,CAAC,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAClE,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,QAAQ;YAClC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,SAAS,CAAC;YAC9B,CAAC,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS;gBACzB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,QAAQ,CAAC;QACf,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QACpD,cAAc,EAAE,CAAC;QACjB,MAAM;aACH,aAAa,CAAC,gBAAgB,CAAC;YAChC,EAAE,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QACvE,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACrD,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC;QACpD,MAAM,CAAC,aAAa,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;QACnD,MAAM,CAAC,aAAa,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAc,mBAAmB,CAAC,CAAC,CAAC;QACpF,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC;QACzE,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,CAAC,EACD,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAC9E,CAAC;QACF,IAAI,QAAQ,GAAG,SAAS,CAAC;QACzB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,+BAA+B,CAAC,CAAC;YACrF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC;YACvE,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAC3B,CAAC,EACD,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAChF,CAAC;YACF,IAAI,cAAc,GAAG,YAAY,CAAC;YAClC,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;gBAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAc,eAAe,CAAE,CAAC;gBACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,MAAM,CAAC,gBAAgB,CAAc,0BAA0B,CAAC,CACjE,CAAC;gBACF,MAAM,OAAO,GACX,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;oBACtF,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBACpF,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;oBAClF,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACnD,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBACpC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAC/B,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACrC,MAAM,GAAG,GACP,QAAQ,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC7D,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,CAAC;gBAClC,MAAM,IAAI,GACR,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC;oBACnC,OAAO,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,YAAY,CAAC;gBACtD,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC;gBACrD,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC;gBAC3D,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5C,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;YACrE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACtC,OAAO,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;YACrC,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,WAAW,CACtB,yBAAyB,EACzB,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3C,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,WAAW,CACtB,0BAA0B,EAC1B,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3C,CAAC;YACF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACrC,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,+BAA+B,CAAC,CAAC;YACrF,OAAO,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;QACrC,CAAC;aAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAC3B,QAAQ,GAAG,CAAC,CAAC;YACb,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,6EAA6E;YAC7E,6EAA6E;YAC7E,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAgB,CAAC;YACpD,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YAC3C,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAC1C,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;YACnB,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC;gBAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAC9E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAc,mBAAmB,CAAC,CAAC,CAAC,GAAG,CACrF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,CACxD,CAAC;gBACF,MAAM,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBAC7C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CACzB,KAAK,CAAC,gBAAgB,CAAc,0BAA0B,CAAC,CAChE,CAAC;gBACF,MAAM,MAAM,GACV,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACzF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CACvB,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC;oBAC3C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM;oBACvC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;oBACjF,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;oBAChC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC;oBACjC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACnD,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAC1C,CAAC;gBACF,MAAM,QAAQ,GACZ,QAAQ,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC7D,CAAC,CAAC,CAAC;oBACH,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC;gBACnC,oEAAoE;gBACpE,sEAAsE;gBACtE,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,GACR,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,IAAI,OAAO,GAAG,QAAQ,GAAG,aAAa,IAAI,SAAS,CAAC;gBACzF,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,+BAA+B,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAC9E,CAAC;gBACF,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC;gBACvD,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;gBACjD,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YACtE,CAAC;oBAAS,CAAC;gBACT,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3F,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,0BAA0B,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5F,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;YAAE,KAAK,GAAG,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACtE,CAAC,CAAC;IACF,IAAI,uBAAuB,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;gBAAE,OAAO,GAAG,IAAI,CAAC;iBACvC,IACH,CAAC,QAAQ,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;gBACtF,uBAAuB,EACvB,CAAC;gBACD,uBAAuB;oBACrB,QAAQ,EAAE,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC;gBACvF,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QACD,yEAAyE;QACzE,wEAAwE;QACxE,IAAI,OAAO;YAAE,QAAQ,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAChD,KAAK,IAAI,IAAI,GAAuB,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,aAAa;QACvE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACpF,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;IAC5D,MAAM,eAAe,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;QAChD,IAAI,QAAQ,EAAE,CAAC,UAAU,KAAK,UAAU;YAAE,QAAQ,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,IAAI,IAAI;QACN,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE;YAC5B,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI;YACf,aAAa,EAAE,IAAI;YACnB,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;SAC9C,CAAC,CAAC;IACL,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACjD,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;QACb,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,KAAK;YAAE,GAAG,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtB,eAAe,CAAC,UAAU,EAAE,CAAC;QAC7B,aAAa,CAAC,UAAU,EAAE,CAAC;QAC3B,eAAe,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import { bindTabTooltip } from './tab-tooltip.js';\nimport type { TabBarOptions, TabBarStyle } from './types.js';\nimport type { Scope } from './lifetime.js';\n\nexport function validateTabBar(options: TabBarOptions) {\n for (const style of [options, ...Object.values(options.regions ?? {})]) {\n for (const [key, values] of Object.entries({\n display: ['automatic', 'compact'],\n attachment: ['anchored', 'floating'],\n fit: ['full', 'fit'],\n corners: ['fitted', 'rounded', 'capsule'],\n })) {\n const value = style[key as keyof TabBarStyle];\n if (value !== undefined && !values.includes(String(value)))\n throw new Error(`Unknown tab bar ${key}`);\n }\n if (style.placement !== undefined && !['top', 'left'].includes(style.placement))\n throw new Error('Unknown tab bar placement');\n if (style.mode !== undefined && !['full', 'tapered'].includes(style.mode))\n throw new Error('Unknown tab bar mode');\n if (\n style.shape !== undefined &&\n !['angle', 'round', 'scoop', 'vertical', 'rounded'].includes(style.shape)\n )\n throw new Error('Unknown tab bar shape');\n if (\n style.taperWidth !== undefined &&\n (!Number.isFinite(style.taperWidth) || style.taperWidth <= 0)\n )\n throw new Error('Tab bar taperWidth must be positive and finite');\n }\n}\n\n/** Chrome measurement never mounts or replaces application pane views. */\nexport function bindTabBar(\n region: HTMLElement,\n header: HTMLElement,\n root: HTMLElement,\n scope: Scope,\n getStyle: () => TabBarStyle,\n) {\n const doc = region.ownerDocument,\n win = doc.defaultView!;\n const drawChrome = (\n natural: number,\n occupied: number,\n height: number,\n capWidth: number,\n fits: boolean,\n left: boolean,\n style: TabBarStyle,\n ) => {\n if (style.attachment === 'floating') return;\n if (fits && capWidth > 0) {\n const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.classList.add('layouts-tab-cap');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('viewBox', '0 0 1 1');\n svg.setAttribute('preserveAspectRatio', 'none');\n svg.style.width = `${left ? height : capWidth}px`;\n if (left) svg.style.height = `${capWidth}px`;\n const path = doc.createElementNS(svg.namespaceURI, 'path');\n const curve =\n style.shape === 'round'\n ? 'A1 1 0 0 0 1 0'\n : style.shape === 'scoop'\n ? 'A1 1 0 0 1 1 0'\n : 'L1 0';\n path.setAttribute('d', `M0 1 ${curve} H0 Z`);\n if (left) path.setAttribute('transform', 'matrix(0 1 1 0 0 0)');\n svg.append(path);\n header.append(svg);\n }\n // A single closed, inset outline covers the controls and cap. Splitting\n // this between CSS borders and SVG strokes leaves seams and clipped edges.\n const outline = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');\n outline.classList.add('layouts-tab-outline');\n outline.setAttribute('aria-hidden', 'true');\n outline.setAttribute('viewBox', `0 0 ${left ? height : occupied} ${left ? occupied : height}`);\n outline.style.width = `${left ? height : occupied}px`;\n outline.style.height = `${left ? occupied : height}px`;\n const edge = doc.createElementNS(outline.namespaceURI, 'path');\n const right = Math.max(0.5, occupied - 0.5);\n const bottom = Math.max(0.5, height - 0.5);\n const end = fits && capWidth > 0 ? natural : right;\n const curve =\n fits && capWidth > 0\n ? style.shape === 'round' || style.shape === 'scoop'\n ? `A${Math.max(0.01, right - end)} ${Math.max(0.01, bottom - 0.5)} 0 0 ${style.shape === 'round' ? 1 : 0} ${end} ${bottom}`\n : `L${end} ${bottom}`\n : `V${bottom}`;\n if (style.shape === 'rounded') {\n const radius = Math.max(\n 0,\n Math.min(\n parseFloat(win.getComputedStyle(header).borderTopLeftRadius) || 0,\n (right - 0.5) / 2,\n (bottom - 0.5) / 2,\n ),\n );\n edge.setAttribute(\n 'd',\n `M${0.5 + radius} 0.5 H${right - radius} Q${right} 0.5 ${right} ${0.5 + radius} V${bottom - radius} Q${right} ${bottom} ${right - radius} ${bottom} H${0.5 + radius} Q0.5 ${bottom} 0.5 ${bottom - radius} V${0.5 + radius} Q0.5 0.5 ${0.5 + radius} 0.5 Z`,\n );\n } else edge.setAttribute('d', `M0.5 0.5 H${right} ${curve} H0.5 Z`);\n if (left) edge.setAttribute('transform', 'matrix(0 1 1 0 0 0)');\n const shared = region.dataset.sharedEdges?.split(' ') ?? [];\n const w = left ? height : occupied;\n const h = left ? occupied : height;\n // Clip only decorative strokes on edges owned by an ancestor split.\n const insets = [\n shared.includes('top') ? 1 : 0,\n shared.includes('right') && w >= region.clientWidth - 0.5 ? 1 : 0,\n shared.includes('bottom') && h >= region.clientHeight - 0.5 ? 1 : 0,\n shared.includes('left') ? 1 : 0,\n ];\n outline.style.clipPath = `inset(${insets.map((value) => `${value}px`).join(' ')})`;\n outline.append(edge);\n header.append(outline);\n };\n const refreshTooltip = bindTabTooltip(region, header, root, scope);\n let frame = 0,\n disposed = false;\n const observedContent = new Set<Element>();\n const contentResize = new ResizeObserver(() => schedule());\n const scrollbarClearance = () => {\n const next = new Set<Element>();\n const bounds = region.getBoundingClientRect();\n let right = 0,\n bottom = 0;\n const body = region.querySelector<HTMLElement>(':scope > .layouts-body');\n if (body) {\n for (const element of [body, ...body.querySelectorAll<HTMLElement>('*')]) {\n if (!element.clientWidth || !element.clientHeight) continue;\n const css = win.getComputedStyle(element);\n if (!/(auto|scroll)/.test(css.overflowX + css.overflowY)) continue;\n next.add(element);\n for (const child of element.children) next.add(child);\n const rect = element.getBoundingClientRect();\n const fallback = parseFloat(css.getPropertyValue('--layouts-scrollbar-size')) || 6;\n // Overlay scrollbars report zero gutter: use the themed size then.\n if (\n /(auto|scroll)/.test(css.overflowY) &&\n element.scrollHeight > element.clientHeight &&\n Math.abs(bounds.right - rect.right) < 1\n ) {\n const gutter =\n element.offsetWidth -\n element.clientWidth -\n (parseFloat(css.borderLeftWidth) || 0) -\n (parseFloat(css.borderRightWidth) || 0);\n right = Math.max(right, gutter, fallback);\n }\n if (\n /(auto|scroll)/.test(css.overflowX) &&\n element.scrollWidth > element.clientWidth &&\n Math.abs(bounds.bottom - rect.bottom) < 1\n ) {\n const gutter =\n element.offsetHeight -\n element.clientHeight -\n (parseFloat(css.borderTopWidth) || 0) -\n (parseFloat(css.borderBottomWidth) || 0);\n bottom = Math.max(bottom, gutter, fallback);\n }\n }\n }\n for (const element of observedContent) if (!next.has(element)) contentResize.unobserve(element);\n for (const element of next) if (!observedContent.has(element)) contentResize.observe(element);\n observedContent.clear();\n for (const element of next) observedContent.add(element);\n return { right, bottom };\n };\n const measure = () => {\n frame = 0;\n if (disposed || !region.isConnected) return;\n const style = getStyle();\n const left = style.placement === 'left';\n const compact = style.display === 'compact';\n region.dataset.tabDisplay = compact ? 'compact' : 'automatic';\n header.dataset.tabDisplay = compact ? 'compact' : 'automatic';\n const floating = style.attachment === 'floating';\n const padding = parseFloat(\n win.getComputedStyle(region).getPropertyValue('--layouts-panel-padding'),\n );\n const inset = floating ? (Number.isFinite(padding) ? Math.max(0, padding) : 8) : 0;\n const scrollbar = floating ? scrollbarClearance() : { right: 0, bottom: 0 };\n const insetX = inset;\n const insetY = inset;\n header.style.setProperty('--layouts-floating-inset-x', `${insetX}px`);\n header.style.setProperty('--layouts-floating-inset-y', `${insetY}px`);\n if (!floating) {\n contentResize.disconnect();\n observedContent.clear();\n }\n const tapered = floating || style.mode === 'tapered';\n region.dataset.tabAttachment = floating ? 'floating' : 'anchored';\n header.dataset.tabCorners = floating\n ? (style.corners ?? 'rounded')\n : style.shape === 'rounded'\n ? 'rounded'\n : 'fitted';\n if (!left) header.style.removeProperty('height');\n region.dataset.tabPlacement = left ? 'left' : 'top';\n refreshTooltip();\n header\n .querySelector('[role=tablist]')\n ?.setAttribute('aria-orientation', left ? 'vertical' : 'horizontal');\n region.dataset.tabBar = tapered ? 'tapered' : 'full';\n header.dataset.tabBarShape = style.shape ?? 'angle';\n header.querySelector('.layouts-tab-cap')?.remove();\n header.querySelector('.layouts-tab-outline')?.remove();\n const items = Array.from(header.querySelectorAll<HTMLElement>('.layouts-tab-item'));\n header.dataset.tabBarEmpty = String(tapered && !items.length);\n const height = header.hidden ? 0 : header.getBoundingClientRect().height;\n // clientWidth rounds fractional split widths up, allowing chrome to spill\n // outside the region and change the stage's scrollbar/resize geometry.\n const available = Math.max(\n 0,\n parseFloat(win.getComputedStyle(region).width) - insetX * 2 - scrollbar.right,\n );\n let occupied = available;\n if (left) {\n header.style.removeProperty('width');\n for (const item of items) item.style.removeProperty('--layouts-tab-preferred-width');\n const width = header.hidden ? 0 : header.getBoundingClientRect().width;\n const regionHeight = Math.max(\n 0,\n parseFloat(win.getComputedStyle(region).height) - insetY * 2 - scrollbar.bottom,\n );\n let occupiedHeight = regionHeight;\n if (tapered && width) {\n const computed = win.getComputedStyle(header);\n const list = header.querySelector<HTMLElement>('.layouts-tabs')!;\n const controls = Array.from(\n header.querySelectorAll<HTMLElement>(':scope > .layouts-button'),\n );\n const natural =\n items.reduce((sum, item) => sum + parseFloat(win.getComputedStyle(item).flexBasis), 0) +\n Math.max(0, items.length - 1) * (parseFloat(win.getComputedStyle(list).rowGap) || 0) +\n controls.reduce((sum, control) => sum + control.getBoundingClientRect().height, 0) +\n Math.max(0, controls.length - (items.length ? 0 : 1)) *\n (parseFloat(computed.rowGap) || 0) +\n parseFloat(computed.paddingTop) +\n parseFloat(computed.paddingBottom);\n const cap =\n floating || ['vertical', 'rounded'].includes(style.shape ?? '')\n ? 0\n : (style.taperWidth ?? width);\n const fits =\n !(floating && style.fit === 'full') &&\n natural + cap + (floating ? 0 : 12) <= regionHeight;\n occupiedHeight = fits ? natural + cap : regionHeight;\n header.style.height = `${fits ? natural : regionHeight}px`;\n region.dataset.tabBarFilled = String(!fits);\n drawChrome(natural, occupiedHeight, width, cap, fits, true, style);\n } else {\n header.style.removeProperty('height');\n delete region.dataset.tabBarFilled;\n }\n region.style.setProperty(\n '--layouts-tab-bar-width',\n `${occupiedHeight ? width + insetX : 0}px`,\n );\n region.style.setProperty(\n '--layouts-tab-bar-height',\n `${width ? occupiedHeight + insetY : 0}px`,\n );\n return;\n }\n if (!tapered) {\n header.style.removeProperty('width');\n for (const item of items) item.style.removeProperty('--layouts-tab-preferred-width');\n delete region.dataset.tabBarFilled;\n } else if (!height) {\n header.style.width = '0px';\n occupied = 0;\n region.dataset.tabBarFilled = 'false';\n } else {\n // Inline-size container queries suppress intrinsic sizing. Measure a hidden,\n // noninteractive copy with containment disabled, including real icons/fonts.\n const probe = header.cloneNode(true) as HTMLElement;\n probe.classList.add('layouts-tab-measure');\n probe.setAttribute('aria-hidden', 'true');\n probe.inert = true;\n probe.removeAttribute('id');\n for (const node of probe.querySelectorAll('[id]')) node.removeAttribute('id');\n root.append(probe);\n try {\n const widths = Array.from(probe.querySelectorAll<HTMLElement>('.layouts-tab-item')).map(\n (item) => Math.ceil(item.getBoundingClientRect().width),\n );\n const computed = win.getComputedStyle(probe);\n const controls = Array.from(\n probe.querySelectorAll<HTMLElement>(':scope > .layouts-button'),\n );\n const tabGap =\n parseFloat(win.getComputedStyle(probe.querySelector('.layouts-tabs')!).columnGap) || 0;\n const natural = Math.ceil(\n widths.reduce((sum, width) => sum + width, 0) +\n Math.max(0, widths.length - 1) * tabGap +\n controls.reduce((sum, control) => sum + control.getBoundingClientRect().width, 0) +\n parseFloat(computed.paddingLeft) +\n parseFloat(computed.paddingRight) +\n Math.max(0, controls.length - (items.length ? 0 : 1)) *\n (parseFloat(computed.columnGap) || 0),\n );\n const capWidth =\n floating || ['vertical', 'rounded'].includes(style.shape ?? '')\n ? 0\n : (style.taperWidth ?? height);\n // Leave breathing room at the pane edge instead of showing a nearly\n // touching cap. This clearance is not part of the occupied footprint.\n const edgeClearance = floating ? 0 : 12;\n const fits =\n !(floating && style.fit === 'full') && natural + capWidth + edgeClearance <= available;\n items.forEach((item, index) =>\n item.style.setProperty('--layouts-tab-preferred-width', `${widths[index]}px`),\n );\n region.dataset.tabBarFilled = String(!fits);\n header.style.width = `${fits ? natural : available}px`;\n occupied = fits ? natural + capWidth : available;\n drawChrome(natural, occupied, height, capWidth, fits, false, style);\n } finally {\n probe.remove();\n }\n }\n region.style.setProperty('--layouts-tab-bar-width', `${height ? occupied + insetX : 0}px`);\n region.style.setProperty('--layouts-tab-bar-height', `${height ? height + insetY : 0}px`);\n };\n const schedule = () => {\n if (!disposed && !frame) frame = win.requestAnimationFrame(measure);\n };\n let observedHeaderCrossSize = -1;\n const resize = new ResizeObserver((entries) => {\n let changed = false;\n for (const entry of entries) {\n if (entry.target === region) changed = true;\n else if (\n (getStyle().placement === 'left' ? entry.contentRect.width : entry.contentRect.height) !==\n observedHeaderCrossSize\n ) {\n observedHeaderCrossSize =\n getStyle().placement === 'left' ? entry.contentRect.width : entry.contentRect.height;\n changed = true;\n }\n }\n // Header width is our output, not a measurement input. Observing our own\n // width writes feeds compression changes back into another measurement.\n if (changed) schedule();\n });\n resize.observe(region);\n resize.observe(header);\n const mutation = new MutationObserver(schedule);\n for (let node: HTMLElement | null = root; node; node = node.parentElement)\n mutation.observe(node, { attributes: true, attributeFilter: ['style', 'class'] });\n mutation.observe(doc.head, { subtree: true, childList: true, characterData: true });\n const body = region.querySelector(':scope > .layouts-body');\n const contentMutation = new MutationObserver(() => {\n if (getStyle().attachment === 'floating') schedule();\n });\n if (body)\n contentMutation.observe(body, {\n subtree: true,\n childList: true,\n characterData: true,\n attributes: true,\n attributeFilter: ['class', 'style', 'hidden'],\n });\n scope.listen(doc.fonts, 'loadingdone', schedule);\n void doc.fonts.ready.then(schedule);\n scope.add(() => {\n disposed = true;\n if (frame) win.cancelAnimationFrame(frame);\n resize.disconnect();\n mutation.disconnect();\n contentMutation.disconnect();\n contentResize.disconnect();\n observedContent.clear();\n });\n return schedule;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { Scope } from './lifetime.js';
2
+ /** Icon-only tab hints and empty-pane hints follow the region lifetime. */
3
+ export declare function bindTabTooltip(region: HTMLElement, header: HTMLElement, root: HTMLElement, scope: Scope): () => void;
4
+ //# sourceMappingURL=tab-tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-tooltip.d.ts","sourceRoot":"","sources":["../src/tab-tooltip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAG3C,2EAA2E;AAC3E,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,WAAW,EACjB,KAAK,EAAE,KAAK,cAuFb"}
@@ -0,0 +1,95 @@
1
+ let nextTooltip = 0;
2
+ /** Icon-only tab hints and empty-pane hints follow the region lifetime. */
3
+ export function bindTabTooltip(region, header, root, scope) {
4
+ const doc = root.ownerDocument;
5
+ const win = doc.defaultView;
6
+ let anchor;
7
+ let tooltip;
8
+ const removeTooltip = () => {
9
+ anchor?.removeAttribute('aria-describedby');
10
+ tooltip?.remove();
11
+ tooltip = undefined;
12
+ };
13
+ const resize = new ResizeObserver(() => refresh());
14
+ const hide = () => {
15
+ removeTooltip();
16
+ resize.disconnect();
17
+ anchor = undefined;
18
+ };
19
+ const needsTooltip = (tab) => {
20
+ if (tab.matches('.layouts-empty'))
21
+ return !tab.matches(':disabled') && !region.querySelector('.layouts-picker');
22
+ const label = tab.querySelector('.layouts-tab-label');
23
+ if (!label || !label.getClientRects().length)
24
+ return true;
25
+ const css = win.getComputedStyle(label);
26
+ return (!label.clientWidth ||
27
+ !label.clientHeight ||
28
+ css.visibility === 'hidden' ||
29
+ css.opacity === '0');
30
+ };
31
+ const refresh = () => {
32
+ if (!anchor)
33
+ return;
34
+ if (!anchor.isConnected || !anchor.getClientRects().length) {
35
+ hide();
36
+ return;
37
+ }
38
+ if (!needsTooltip(anchor)) {
39
+ removeTooltip();
40
+ return;
41
+ }
42
+ if (!tooltip) {
43
+ tooltip = doc.createElement('div');
44
+ tooltip.className = 'layouts-tab-tooltip';
45
+ tooltip.id = `layouts-tooltip-${++nextTooltip}`;
46
+ tooltip.setAttribute('role', 'tooltip');
47
+ anchor.setAttribute('aria-describedby', tooltip.id);
48
+ root.append(tooltip);
49
+ }
50
+ const empty = anchor.matches('.layouts-empty');
51
+ tooltip.textContent = empty ? 'Click to add a pane' : (anchor.getAttribute('aria-label') ?? '');
52
+ const rect = (empty ? region : anchor).getBoundingClientRect();
53
+ const size = tooltip.getBoundingClientRect();
54
+ const horizontal = !empty && region.dataset.tabPlacement !== 'left';
55
+ const x = empty || horizontal ? rect.left + (rect.width - size.width) / 2 : rect.right + 8;
56
+ const y = horizontal ? rect.bottom + 8 : rect.top + (rect.height - size.height) / 2;
57
+ tooltip.style.left = `${Math.max(8, Math.min(x, win.innerWidth - size.width - 8))}px`;
58
+ tooltip.style.top = `${Math.max(8, Math.min(y, win.innerHeight - size.height - 8))}px`;
59
+ };
60
+ const show = (event) => {
61
+ const target = event.target;
62
+ const tab = target?.closest('.layouts-tab, .layouts-empty');
63
+ if (!tab || !region.contains(tab))
64
+ return;
65
+ if (!tab.matches('.layouts-empty') && !header.contains(tab))
66
+ return;
67
+ if (anchor !== tab) {
68
+ hide();
69
+ anchor = tab;
70
+ resize.observe(tab);
71
+ const label = tab.querySelector('.layouts-tab-label');
72
+ if (label)
73
+ resize.observe(label);
74
+ }
75
+ refresh();
76
+ };
77
+ scope.listen(region, 'pointerover', show);
78
+ scope.listen(region, 'focusin', show);
79
+ scope.listen(region, 'pointerout', (event) => {
80
+ if (!anchor?.contains(event.relatedTarget))
81
+ hide();
82
+ });
83
+ scope.listen(region, 'focusout', hide);
84
+ scope.listen(region, 'pointerdown', hide);
85
+ scope.listen(region, 'dragstart', hide);
86
+ scope.listen(root, 'scroll', hide, { capture: true });
87
+ scope.listen(win, 'resize', refresh);
88
+ scope.listen(doc, 'keydown', (event) => {
89
+ if (event.key === 'Escape')
90
+ hide();
91
+ });
92
+ scope.add(hide);
93
+ return refresh;
94
+ }
95
+ //# sourceMappingURL=tab-tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-tooltip.js","sourceRoot":"","sources":["../src/tab-tooltip.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Scope } from './lifetime.js';\n\nlet nextTooltip = 0;\n/** Icon-only tab hints and empty-pane hints follow the region lifetime. */\nexport function bindTabTooltip(\n region: HTMLElement,\n header: HTMLElement,\n root: HTMLElement,\n scope: Scope,\n) {\n const doc = root.ownerDocument;\n const win = doc.defaultView!;\n let anchor: HTMLElement | undefined;\n let tooltip: HTMLDivElement | undefined;\n const removeTooltip = () => {\n anchor?.removeAttribute('aria-describedby');\n tooltip?.remove();\n tooltip = undefined;\n };\n const resize = new ResizeObserver(() => refresh());\n const hide = () => {\n removeTooltip();\n resize.disconnect();\n anchor = undefined;\n };\n const needsTooltip = (tab: HTMLElement) => {\n if (tab.matches('.layouts-empty'))\n return !tab.matches(':disabled') && !region.querySelector('.layouts-picker');\n const label = tab.querySelector<HTMLElement>('.layouts-tab-label');\n if (!label || !label.getClientRects().length) return true;\n const css = win.getComputedStyle(label);\n return (\n !label.clientWidth ||\n !label.clientHeight ||\n css.visibility === 'hidden' ||\n css.opacity === '0'\n );\n };\n const refresh = () => {\n if (!anchor) return;\n if (!anchor.isConnected || !anchor.getClientRects().length) {\n hide();\n return;\n }\n if (!needsTooltip(anchor)) {\n removeTooltip();\n return;\n }\n if (!tooltip) {\n tooltip = doc.createElement('div');\n tooltip.className = 'layouts-tab-tooltip';\n tooltip.id = `layouts-tooltip-${++nextTooltip}`;\n tooltip.setAttribute('role', 'tooltip');\n anchor.setAttribute('aria-describedby', tooltip.id);\n root.append(tooltip);\n }\n const empty = anchor.matches('.layouts-empty');\n tooltip.textContent = empty ? 'Click to add a pane' : (anchor.getAttribute('aria-label') ?? '');\n const rect = (empty ? region : anchor).getBoundingClientRect();\n const size = tooltip.getBoundingClientRect();\n const horizontal = !empty && region.dataset.tabPlacement !== 'left';\n const x = empty || horizontal ? rect.left + (rect.width - size.width) / 2 : rect.right + 8;\n const y = horizontal ? rect.bottom + 8 : rect.top + (rect.height - size.height) / 2;\n tooltip.style.left = `${Math.max(8, Math.min(x, win.innerWidth - size.width - 8))}px`;\n tooltip.style.top = `${Math.max(8, Math.min(y, win.innerHeight - size.height - 8))}px`;\n };\n const show = (event: Event) => {\n const target = event.target as Element | null;\n const tab = target?.closest<HTMLElement>('.layouts-tab, .layouts-empty');\n if (!tab || !region.contains(tab)) return;\n if (!tab.matches('.layouts-empty') && !header.contains(tab)) return;\n if (anchor !== tab) {\n hide();\n anchor = tab;\n resize.observe(tab);\n const label = tab.querySelector('.layouts-tab-label');\n if (label) resize.observe(label);\n }\n refresh();\n };\n scope.listen(region, 'pointerover', show);\n scope.listen(region, 'focusin', show);\n scope.listen(region, 'pointerout', (event) => {\n if (!anchor?.contains((event as PointerEvent).relatedTarget as Node | null)) hide();\n });\n scope.listen(region, 'focusout', hide);\n scope.listen(region, 'pointerdown', hide);\n scope.listen(region, 'dragstart', hide);\n scope.listen(root, 'scroll', hide, { capture: true });\n scope.listen(win, 'resize', refresh);\n scope.listen(doc, 'keydown', (event) => {\n if ((event as KeyboardEvent).key === 'Escape') hide();\n });\n scope.add(hide);\n return refresh;\n}\n"]}
package/dist/tabs.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { Group, Pane } from 'quilt-core';
2
+ import type { LayoutOptions } from './types.js';
3
+ interface TabDependencies {
4
+ options: LayoutOptions;
5
+ prefix: string;
6
+ act: (fn: () => void) => void;
7
+ getDrag: () => string | undefined;
8
+ setDrag: (id: string | undefined) => void;
9
+ clearDrop: () => void;
10
+ focusActive: () => void;
11
+ }
12
+ /** Header nodes are disposable; pane views are owned separately by the renderer. */
13
+ export declare function fillTabs(tabs: HTMLElement, group: Group, panes: Pane[], deps: TabDependencies): void;
14
+ export {};
15
+ //# sourceMappingURL=tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../src/tabs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,UAAU,eAAe;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AACD,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,eAAe,QAiH7F"}