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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/action-icons.d.ts +18 -0
- package/dist/action-icons.d.ts.map +1 -0
- package/dist/action-icons.js +36 -0
- package/dist/action-icons.js.map +1 -0
- package/dist/chrome-icons.d.ts +3 -0
- package/dist/chrome-icons.d.ts.map +1 -0
- package/dist/chrome-icons.js +32 -0
- package/dist/chrome-icons.js.map +1 -0
- package/dist/corners.d.ts +8 -0
- package/dist/corners.d.ts.map +1 -0
- package/dist/corners.js +205 -0
- package/dist/corners.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lifetime.d.ts +10 -0
- package/dist/lifetime.d.ts.map +1 -0
- package/dist/lifetime.js +44 -0
- package/dist/lifetime.js.map +1 -0
- package/dist/menu.d.ts +10 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +356 -0
- package/dist/menu.js.map +1 -0
- package/dist/panes.d.ts +13 -0
- package/dist/panes.d.ts.map +1 -0
- package/dist/panes.js +58 -0
- package/dist/panes.js.map +1 -0
- package/dist/picker.d.ts +6 -0
- package/dist/picker.d.ts.map +1 -0
- package/dist/picker.js +112 -0
- package/dist/picker.js.map +1 -0
- package/dist/registry.d.ts +25 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +39 -0
- package/dist/registry.js.map +1 -0
- package/dist/renderer.d.ts +3 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +570 -0
- package/dist/renderer.js.map +1 -0
- package/dist/resize.d.ts +7 -0
- package/dist/resize.d.ts.map +1 -0
- package/dist/resize.js +56 -0
- package/dist/resize.js.map +1 -0
- package/dist/shortcuts.d.ts +6 -0
- package/dist/shortcuts.d.ts.map +1 -0
- package/dist/shortcuts.js +64 -0
- package/dist/shortcuts.js.map +1 -0
- package/dist/styles.css +842 -0
- package/dist/tab-bar.d.ts +6 -0
- package/dist/tab-bar.d.ts.map +1 -0
- package/dist/tab-bar.js +336 -0
- package/dist/tab-bar.js.map +1 -0
- package/dist/tab-tooltip.d.ts +4 -0
- package/dist/tab-tooltip.d.ts.map +1 -0
- package/dist/tab-tooltip.js +95 -0
- package/dist/tab-tooltip.js.map +1 -0
- package/dist/tabs.d.ts +15 -0
- package/dist/tabs.d.ts.map +1 -0
- package/dist/tabs.js +126 -0
- package/dist/tabs.js.map +1 -0
- package/dist/theme.d.ts +206 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +166 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/windows.d.ts +23 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +247 -0
- package/dist/windows.js.map +1 -0
- package/package.json +50 -0
- package/src/action-icons.ts +40 -0
- package/src/chrome-icons.ts +30 -0
- package/src/corners.ts +259 -0
- package/src/index.ts +27 -0
- package/src/lifetime.ts +46 -0
- package/src/menu.ts +432 -0
- package/src/panes.ts +76 -0
- package/src/picker.ts +114 -0
- package/src/registry.ts +46 -0
- package/src/renderer.ts +654 -0
- package/src/resize.ts +65 -0
- package/src/shortcuts.ts +90 -0
- package/src/styles.css +842 -0
- package/src/tab-bar.ts +382 -0
- package/src/tab-tooltip.ts +96 -0
- package/src/tabs.ts +129 -0
- package/src/theme.ts +211 -0
- package/src/types.ts +67 -0
- 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"}
|
package/dist/tab-bar.js
ADDED
|
@@ -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":"AAEA,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,MAAmB,EACnB,IAAiB,EACjB,KAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,WAAY,CAAC;IAC7B,IAAI,MAA+B,CAAC;IACpC,IAAI,OAAmC,CAAC;IACxC,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,MAAM,EAAE,eAAe,CAAC,kBAAkB,CAAC,CAAC;QAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,GAAG,SAAS,CAAC;IACtB,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,aAAa,EAAE,CAAC;QAChB,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,GAAgB,EAAE,EAAE;QACxC,IAAI,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAc,oBAAoB,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,CACL,CAAC,KAAK,CAAC,WAAW;YAClB,CAAC,KAAK,CAAC,YAAY;YACnB,GAAG,CAAC,UAAU,KAAK,QAAQ;YAC3B,GAAG,CAAC,OAAO,KAAK,GAAG,CACpB,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,CAAC;YAC3D,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,aAAa,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACnC,OAAO,CAAC,SAAS,GAAG,qBAAqB,CAAC;YAC1C,OAAO,CAAC,EAAE,GAAG,mBAAmB,EAAE,WAAW,EAAE,CAAC;YAChD,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACxC,MAAM,CAAC,YAAY,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC/C,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;QAChG,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,qBAAqB,EAAE,CAAC;QAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,KAAK,MAAM,CAAC;QACpE,MAAM,CAAC,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QAC3F,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpF,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACzF,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,KAAY,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAwB,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,EAAE,OAAO,CAAc,8BAA8B,CAAC,CAAC;QACzE,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO;QAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO;QACpE,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,IAAI,EAAE,CAAC;YACP,MAAM,GAAG,GAAG,CAAC;YACb,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;YACtD,IAAI,KAAK;gBAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAC1C,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACtC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE;QAC3C,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAE,KAAsB,CAAC,aAA4B,CAAC;YAAE,IAAI,EAAE,CAAC;IACtF,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACvC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAC1C,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;QACrC,IAAK,KAAuB,CAAC,GAAG,KAAK,QAAQ;YAAE,IAAI,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,OAAO,OAAO,CAAC;AACjB,CAAC","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"}
|