@salt-ds/lab 1.0.0-alpha.93 → 1.0.0-alpha.94
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/CHANGELOG.md +104 -0
- package/css/salt-lab.css +163 -122
- package/dist-cjs/index.js +6 -8
- package/dist-cjs/index.js.map +1 -1
- package/dist-cjs/toolbar-next/ToolbarContentNext.css.js +6 -0
- package/dist-cjs/toolbar-next/ToolbarContentNext.css.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarContentNext.js +32 -0
- package/dist-cjs/toolbar-next/ToolbarContentNext.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarNext.css.js +6 -0
- package/dist-cjs/toolbar-next/ToolbarNext.css.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarNext.js +394 -0
- package/dist-cjs/toolbar-next/ToolbarNext.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflow.css.js +6 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflow.css.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflow.js +705 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflow.js.map +1 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflowFloatingBoundary.js +165 -0
- package/dist-cjs/toolbar-next/ToolbarNextOverflowFloatingBoundary.js.map +1 -0
- package/dist-cjs/toolbar-next/TooltrayNext.css.js +6 -0
- package/dist-cjs/toolbar-next/TooltrayNext.css.js.map +1 -0
- package/dist-cjs/toolbar-next/TooltrayNext.js +55 -0
- package/dist-cjs/toolbar-next/TooltrayNext.js.map +1 -0
- package/dist-cjs/toolbar-next/toolbarNextKeyboardUtils.js +391 -0
- package/dist-cjs/toolbar-next/toolbarNextKeyboardUtils.js.map +1 -0
- package/dist-cjs/toolbar-next/toolbarNextUtils.js +215 -0
- package/dist-cjs/toolbar-next/toolbarNextUtils.js.map +1 -0
- package/dist-cjs/toolbar-next/useToolbarNextKeyboardNavigation.js +334 -0
- package/dist-cjs/toolbar-next/useToolbarNextKeyboardNavigation.js.map +1 -0
- package/dist-cjs/toolbar-next/useToolbarNextOverflow.js +743 -0
- package/dist-cjs/toolbar-next/useToolbarNextOverflow.js.map +1 -0
- package/dist-es/index.js +3 -4
- package/dist-es/index.js.map +1 -1
- package/dist-es/toolbar-next/ToolbarContentNext.css.js +4 -0
- package/dist-es/toolbar-next/ToolbarContentNext.css.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarContentNext.js +30 -0
- package/dist-es/toolbar-next/ToolbarContentNext.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarNext.css.js +4 -0
- package/dist-es/toolbar-next/ToolbarNext.css.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarNext.js +392 -0
- package/dist-es/toolbar-next/ToolbarNext.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarNextOverflow.css.js +4 -0
- package/dist-es/toolbar-next/ToolbarNextOverflow.css.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarNextOverflow.js +700 -0
- package/dist-es/toolbar-next/ToolbarNextOverflow.js.map +1 -0
- package/dist-es/toolbar-next/ToolbarNextOverflowFloatingBoundary.js +159 -0
- package/dist-es/toolbar-next/ToolbarNextOverflowFloatingBoundary.js.map +1 -0
- package/dist-es/toolbar-next/TooltrayNext.css.js +4 -0
- package/dist-es/toolbar-next/TooltrayNext.css.js.map +1 -0
- package/dist-es/toolbar-next/TooltrayNext.js +53 -0
- package/dist-es/toolbar-next/TooltrayNext.js.map +1 -0
- package/dist-es/toolbar-next/toolbarNextKeyboardUtils.js +372 -0
- package/dist-es/toolbar-next/toolbarNextKeyboardUtils.js.map +1 -0
- package/dist-es/toolbar-next/toolbarNextUtils.js +211 -0
- package/dist-es/toolbar-next/toolbarNextUtils.js.map +1 -0
- package/dist-es/toolbar-next/useToolbarNextKeyboardNavigation.js +332 -0
- package/dist-es/toolbar-next/useToolbarNextKeyboardNavigation.js.map +1 -0
- package/dist-es/toolbar-next/useToolbarNextOverflow.js +741 -0
- package/dist-es/toolbar-next/useToolbarNextOverflow.js.map +1 -0
- package/dist-types/index.d.ts +1 -1
- package/dist-types/toolbar-next/ToolbarContentNext.d.ts +11 -0
- package/dist-types/toolbar-next/ToolbarNext.d.ts +12 -0
- package/dist-types/toolbar-next/ToolbarNextOverflow.d.ts +34 -0
- package/dist-types/toolbar-next/ToolbarNextOverflowFloatingBoundary.d.ts +16 -0
- package/dist-types/toolbar-next/TooltrayNext.d.ts +37 -0
- package/dist-types/toolbar-next/index.d.ts +3 -0
- package/dist-types/toolbar-next/toolbarNextKeyboardUtils.d.ts +39 -0
- package/dist-types/toolbar-next/toolbarNextUtils.d.ts +42 -0
- package/dist-types/toolbar-next/useToolbarNextKeyboardNavigation.d.ts +41 -0
- package/dist-types/toolbar-next/useToolbarNextOverflow.d.ts +37 -0
- package/package.json +2 -2
- package/dist-cjs/tree/Tree.css.js +0 -6
- package/dist-cjs/tree/Tree.css.js.map +0 -1
- package/dist-cjs/tree/Tree.js +0 -303
- package/dist-cjs/tree/Tree.js.map +0 -1
- package/dist-cjs/tree/TreeContext.js +0 -31
- package/dist-cjs/tree/TreeContext.js.map +0 -1
- package/dist-cjs/tree/TreeNode.css.js +0 -6
- package/dist-cjs/tree/TreeNode.css.js.map +0 -1
- package/dist-cjs/tree/TreeNode.js +0 -103
- package/dist-cjs/tree/TreeNode.js.map +0 -1
- package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +0 -6
- package/dist-cjs/tree/TreeNodeExpansionIcon.css.js.map +0 -1
- package/dist-cjs/tree/TreeNodeExpansionIcon.js +0 -62
- package/dist-cjs/tree/TreeNodeExpansionIcon.js.map +0 -1
- package/dist-cjs/tree/TreeNodeLabel.css.js +0 -6
- package/dist-cjs/tree/TreeNodeLabel.css.js.map +0 -1
- package/dist-cjs/tree/TreeNodeLabel.js +0 -26
- package/dist-cjs/tree/TreeNodeLabel.js.map +0 -1
- package/dist-cjs/tree/TreeNodeTrigger.css.js +0 -6
- package/dist-cjs/tree/TreeNodeTrigger.css.js.map +0 -1
- package/dist-cjs/tree/TreeNodeTrigger.js +0 -153
- package/dist-cjs/tree/TreeNodeTrigger.js.map +0 -1
- package/dist-cjs/tree/treeModel.js +0 -61
- package/dist-cjs/tree/treeModel.js.map +0 -1
- package/dist-cjs/tree/useTree.js +0 -337
- package/dist-cjs/tree/useTree.js.map +0 -1
- package/dist-es/tree/Tree.css.js +0 -4
- package/dist-es/tree/Tree.css.js.map +0 -1
- package/dist-es/tree/Tree.js +0 -301
- package/dist-es/tree/Tree.js.map +0 -1
- package/dist-es/tree/TreeContext.js +0 -26
- package/dist-es/tree/TreeContext.js.map +0 -1
- package/dist-es/tree/TreeNode.css.js +0 -4
- package/dist-es/tree/TreeNode.css.js.map +0 -1
- package/dist-es/tree/TreeNode.js +0 -101
- package/dist-es/tree/TreeNode.js.map +0 -1
- package/dist-es/tree/TreeNodeExpansionIcon.css.js +0 -4
- package/dist-es/tree/TreeNodeExpansionIcon.css.js.map +0 -1
- package/dist-es/tree/TreeNodeExpansionIcon.js +0 -60
- package/dist-es/tree/TreeNodeExpansionIcon.js.map +0 -1
- package/dist-es/tree/TreeNodeLabel.css.js +0 -4
- package/dist-es/tree/TreeNodeLabel.css.js.map +0 -1
- package/dist-es/tree/TreeNodeLabel.js +0 -24
- package/dist-es/tree/TreeNodeLabel.js.map +0 -1
- package/dist-es/tree/TreeNodeTrigger.css.js +0 -4
- package/dist-es/tree/TreeNodeTrigger.css.js.map +0 -1
- package/dist-es/tree/TreeNodeTrigger.js +0 -151
- package/dist-es/tree/TreeNodeTrigger.js.map +0 -1
- package/dist-es/tree/treeModel.js +0 -57
- package/dist-es/tree/treeModel.js.map +0 -1
- package/dist-es/tree/useTree.js +0 -335
- package/dist-es/tree/useTree.js.map +0 -1
- package/dist-types/tree/Tree.d.ts +0 -36
- package/dist-types/tree/TreeContext.d.ts +0 -77
- package/dist-types/tree/TreeNode.d.ts +0 -25
- package/dist-types/tree/TreeNodeExpansionIcon.d.ts +0 -4
- package/dist-types/tree/TreeNodeLabel.d.ts +0 -4
- package/dist-types/tree/TreeNodeTrigger.d.ts +0 -8
- package/dist-types/tree/index.d.ts +0 -4
- package/dist-types/tree/treeModel.d.ts +0 -24
- package/dist-types/tree/useTree.d.ts +0 -68
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@salt-ds/core');
|
|
4
|
+
var window = require('@salt-ds/window');
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var toolbarNextUtils = require('./toolbarNextUtils.js');
|
|
7
|
+
|
|
8
|
+
const emptyOverflowState = {
|
|
9
|
+
overflowGroups: [],
|
|
10
|
+
overflowedIds: /* @__PURE__ */ new Set()
|
|
11
|
+
};
|
|
12
|
+
const bandPositions = ["start", "center", "end"];
|
|
13
|
+
function measureWidth(element) {
|
|
14
|
+
if (!element) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
const { width } = element.getBoundingClientRect();
|
|
18
|
+
return Math.ceil(width);
|
|
19
|
+
}
|
|
20
|
+
function isVisibleMeasurementElement(element) {
|
|
21
|
+
if (!(element instanceof HTMLElement)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const { width, height } = element.getBoundingClientRect();
|
|
25
|
+
const styles = core.ownerWindow(element).getComputedStyle(element);
|
|
26
|
+
return width > 0 && height > 0 && styles.display !== "none" && styles.visibility !== "hidden";
|
|
27
|
+
}
|
|
28
|
+
function measureOverflowItemWidth(element) {
|
|
29
|
+
if (!element) {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
const rect = element.getBoundingClientRect();
|
|
33
|
+
let left = rect.left;
|
|
34
|
+
let right = rect.right;
|
|
35
|
+
for (const descendant of element.querySelectorAll("*")) {
|
|
36
|
+
if (!isVisibleMeasurementElement(descendant)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const descendantRect = descendant.getBoundingClientRect();
|
|
40
|
+
left = Math.min(left, descendantRect.left);
|
|
41
|
+
right = Math.max(right, descendantRect.right);
|
|
42
|
+
}
|
|
43
|
+
return Math.ceil(Math.max(rect.width, right - left));
|
|
44
|
+
}
|
|
45
|
+
function readGap(gapValue) {
|
|
46
|
+
return Number.parseFloat(gapValue || "0") || 0;
|
|
47
|
+
}
|
|
48
|
+
function sumFlexWidths(widths, gap) {
|
|
49
|
+
if (widths.length === 0) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
return widths.reduce((total, width) => total + width, 0) + gap * (widths.length - 1);
|
|
53
|
+
}
|
|
54
|
+
function buildGroupDefinitions(items) {
|
|
55
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const [sequence, item] of items.entries()) {
|
|
57
|
+
if (item.overflowMode === "none") {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const existing = groupMap.get(item.overflowGroupKey);
|
|
61
|
+
if (existing) {
|
|
62
|
+
if (!existing.named && item.overflowGroup === "shared") {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (existing.label === item.overflowGroup && item.overflowLabel) {
|
|
66
|
+
existing.label = item.overflowLabel;
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
groupMap.set(item.overflowGroupKey, {
|
|
71
|
+
id: `${item.overflowGroupKey}-${sequence}`,
|
|
72
|
+
key: item.overflowGroupKey,
|
|
73
|
+
label: item.overflowGroup === "shared" ? "More" : item.overflowLabel ?? item.overflowGroup,
|
|
74
|
+
named: item.overflowGroup !== "shared",
|
|
75
|
+
order: sequence,
|
|
76
|
+
overflowGroup: item.overflowGroup,
|
|
77
|
+
contentKey: item.overflowGroup === "shared" ? void 0 : item.contentKey
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return Array.from(groupMap.values()).sort(
|
|
81
|
+
(left, right) => left.order - right.order
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
function buildCollapseUnits(items) {
|
|
85
|
+
const groupedUnits = /* @__PURE__ */ new Map();
|
|
86
|
+
const units = [];
|
|
87
|
+
for (const [sequence, item] of items.entries()) {
|
|
88
|
+
if (item.overflowMode === "none") {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (item.overflowMode === "grouped" && item.overflowGroup !== "shared") {
|
|
92
|
+
const existing = groupedUnits.get(item.overflowGroupKey);
|
|
93
|
+
if (existing) {
|
|
94
|
+
existing.itemIds.push(item.id);
|
|
95
|
+
existing.order = Math.max(existing.order, sequence);
|
|
96
|
+
existing.priority = Math.max(existing.priority, item.overflowPriority);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const unit = {
|
|
100
|
+
groupKey: item.overflowGroupKey,
|
|
101
|
+
itemIds: [item.id],
|
|
102
|
+
order: sequence,
|
|
103
|
+
priority: item.overflowPriority
|
|
104
|
+
};
|
|
105
|
+
groupedUnits.set(item.overflowGroupKey, unit);
|
|
106
|
+
units.push(unit);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
units.push({
|
|
110
|
+
groupKey: item.overflowGroupKey,
|
|
111
|
+
itemIds: [item.id],
|
|
112
|
+
order: sequence,
|
|
113
|
+
priority: item.overflowPriority
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return units.sort((left, right) => {
|
|
117
|
+
if (left.priority !== right.priority) {
|
|
118
|
+
return right.priority - left.priority;
|
|
119
|
+
}
|
|
120
|
+
return right.order - left.order;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function areOverflowStatesEqual(previous, next) {
|
|
124
|
+
if (previous.overflowedIds.size !== next.overflowedIds.size) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
for (const itemId of previous.overflowedIds) {
|
|
128
|
+
if (!next.overflowedIds.has(itemId)) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (previous.overflowGroups.length !== next.overflowGroups.length) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return previous.overflowGroups.every((group, index) => {
|
|
136
|
+
const nextGroup = next.overflowGroups[index];
|
|
137
|
+
if (nextGroup == null || group.id !== nextGroup.id || group.label !== nextGroup.label || group.items.length !== nextGroup.items.length) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
return group.items.every((item, itemIndex) => {
|
|
141
|
+
var _a;
|
|
142
|
+
return item.id === ((_a = nextGroup.items[itemIndex]) == null ? void 0 : _a.id);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function computeToolbarNextOverflowState({
|
|
147
|
+
bandGaps,
|
|
148
|
+
collapseUnits,
|
|
149
|
+
containerWidth,
|
|
150
|
+
groupDefinitions,
|
|
151
|
+
itemWidths,
|
|
152
|
+
items,
|
|
153
|
+
namedTriggerWidths,
|
|
154
|
+
content,
|
|
155
|
+
contentGaps,
|
|
156
|
+
rootGap,
|
|
157
|
+
triggerWidths
|
|
158
|
+
}) {
|
|
159
|
+
const hasCenteredLayout = content.some(
|
|
160
|
+
(contentArea) => contentArea.position === "center"
|
|
161
|
+
);
|
|
162
|
+
const contentByPosition = bandPositions.reduce(
|
|
163
|
+
(bands, position) => {
|
|
164
|
+
bands[position] = content.filter(
|
|
165
|
+
(contentArea) => contentArea.position === position
|
|
166
|
+
);
|
|
167
|
+
return bands;
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
start: [],
|
|
171
|
+
center: [],
|
|
172
|
+
end: []
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
const overflowedIds = /* @__PURE__ */ new Set();
|
|
176
|
+
const activeGroups = /* @__PURE__ */ new Set();
|
|
177
|
+
const getContentWidth = (contentArea) => {
|
|
178
|
+
const renderSlots = toolbarNextUtils.buildContentOverflowRenderSlots(
|
|
179
|
+
contentArea.items,
|
|
180
|
+
overflowedIds,
|
|
181
|
+
new Set(
|
|
182
|
+
groupDefinitions.filter((group) => {
|
|
183
|
+
return group.named && group.contentKey === contentArea.key && activeGroups.has(group.key);
|
|
184
|
+
}).map((group) => group.key)
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
const slotWidths = [];
|
|
188
|
+
for (const slot of renderSlots) {
|
|
189
|
+
const width = slot.triggerGroupKey != null ? namedTriggerWidths.get(slot.item.id) : itemWidths.get(slot.item.id);
|
|
190
|
+
if (width == null || width <= 0) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
slotWidths.push(width);
|
|
194
|
+
}
|
|
195
|
+
return sumFlexWidths(slotWidths, contentGaps.get(contentArea.key) ?? 0);
|
|
196
|
+
};
|
|
197
|
+
const getBandWidth = (position) => {
|
|
198
|
+
const bandChildWidths = [];
|
|
199
|
+
for (const contentArea of contentByPosition[position]) {
|
|
200
|
+
const contentWidth = getContentWidth(contentArea);
|
|
201
|
+
if (contentWidth == null) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if (contentWidth > 0) {
|
|
205
|
+
bandChildWidths.push(contentWidth);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (position === "end") {
|
|
209
|
+
for (const group of groupDefinitions) {
|
|
210
|
+
if (!group.named && activeGroups.has(group.key)) {
|
|
211
|
+
const width = triggerWidths.get(group.key);
|
|
212
|
+
if (width == null || width <= 0) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
bandChildWidths.push(width);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return sumFlexWidths(bandChildWidths, bandGaps.get(position) ?? 0);
|
|
220
|
+
};
|
|
221
|
+
const getTotalWidth = () => {
|
|
222
|
+
if (hasCenteredLayout) {
|
|
223
|
+
const startBandWidth = getBandWidth("start");
|
|
224
|
+
const centerBandWidth = getBandWidth("center");
|
|
225
|
+
const endBandWidth = getBandWidth("end");
|
|
226
|
+
if (startBandWidth == null || centerBandWidth == null || endBandWidth == null) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
return centerBandWidth + Math.max(startBandWidth, endBandWidth) * 2;
|
|
230
|
+
}
|
|
231
|
+
const visibleBandWidths = [];
|
|
232
|
+
for (const position of bandPositions) {
|
|
233
|
+
const bandWidth = getBandWidth(position);
|
|
234
|
+
if (bandWidth == null) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
if (bandWidth > 0) {
|
|
238
|
+
visibleBandWidths.push(bandWidth);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return sumFlexWidths(visibleBandWidths, rootGap);
|
|
242
|
+
};
|
|
243
|
+
const initialWidth = getTotalWidth();
|
|
244
|
+
if (initialWidth == null) {
|
|
245
|
+
return emptyOverflowState;
|
|
246
|
+
}
|
|
247
|
+
if (initialWidth > containerWidth) {
|
|
248
|
+
for (const unit of collapseUnits) {
|
|
249
|
+
for (const itemId of unit.itemIds) {
|
|
250
|
+
overflowedIds.add(itemId);
|
|
251
|
+
}
|
|
252
|
+
activeGroups.add(unit.groupKey);
|
|
253
|
+
const nextWidth = getTotalWidth();
|
|
254
|
+
if (nextWidth == null) {
|
|
255
|
+
return emptyOverflowState;
|
|
256
|
+
}
|
|
257
|
+
if (nextWidth <= containerWidth) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const overflowGroups = groupDefinitions.reduce(
|
|
263
|
+
(groups, group) => {
|
|
264
|
+
const hiddenItems = items.filter(
|
|
265
|
+
(item) => item.overflowGroupKey === group.key && overflowedIds.has(item.id)
|
|
266
|
+
);
|
|
267
|
+
if (hiddenItems.length > 0) {
|
|
268
|
+
groups.push({
|
|
269
|
+
id: group.id,
|
|
270
|
+
items: hiddenItems,
|
|
271
|
+
key: group.key,
|
|
272
|
+
label: group.label,
|
|
273
|
+
named: group.named,
|
|
274
|
+
overflowGroup: group.overflowGroup,
|
|
275
|
+
contentKey: group.contentKey
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
return groups;
|
|
279
|
+
},
|
|
280
|
+
[]
|
|
281
|
+
);
|
|
282
|
+
return {
|
|
283
|
+
overflowGroups,
|
|
284
|
+
overflowedIds
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function useToolbarNextOverflow({
|
|
288
|
+
content
|
|
289
|
+
}) {
|
|
290
|
+
const targetWindow = window.useWindow();
|
|
291
|
+
const items = react.useMemo(
|
|
292
|
+
() => content.flatMap((contentArea) => contentArea.items),
|
|
293
|
+
[content]
|
|
294
|
+
);
|
|
295
|
+
const containerRef = react.useRef(null);
|
|
296
|
+
const bandRefs = react.useRef({
|
|
297
|
+
start: null,
|
|
298
|
+
center: null,
|
|
299
|
+
end: null
|
|
300
|
+
});
|
|
301
|
+
const bandRefCallbacks = react.useRef(
|
|
302
|
+
/* @__PURE__ */ new Map()
|
|
303
|
+
);
|
|
304
|
+
const contentRefs = react.useRef({});
|
|
305
|
+
const contentRefCallbacks = react.useRef(
|
|
306
|
+
/* @__PURE__ */ new Map()
|
|
307
|
+
);
|
|
308
|
+
const itemRefs = react.useRef({});
|
|
309
|
+
const itemRefCallbacks = react.useRef(
|
|
310
|
+
/* @__PURE__ */ new Map()
|
|
311
|
+
);
|
|
312
|
+
const namedTriggerRefs = react.useRef({});
|
|
313
|
+
const namedTriggerRefCallbacks = react.useRef(
|
|
314
|
+
/* @__PURE__ */ new Map()
|
|
315
|
+
);
|
|
316
|
+
const namedTriggerMeasureRefs = react.useRef(
|
|
317
|
+
{}
|
|
318
|
+
);
|
|
319
|
+
const namedTriggerMeasureCallbacks = react.useRef(
|
|
320
|
+
/* @__PURE__ */ new Map()
|
|
321
|
+
);
|
|
322
|
+
const triggerMeasureRefs = react.useRef(
|
|
323
|
+
{}
|
|
324
|
+
);
|
|
325
|
+
const triggerMeasureCallbacks = react.useRef(
|
|
326
|
+
/* @__PURE__ */ new Map()
|
|
327
|
+
);
|
|
328
|
+
const rafRef = react.useRef(null);
|
|
329
|
+
const clearComputingRafRef = react.useRef(null);
|
|
330
|
+
const isComputingRef = react.useRef(false);
|
|
331
|
+
const pendingMeasureRef = react.useRef(false);
|
|
332
|
+
const resizeObserverRef = react.useRef(null);
|
|
333
|
+
const observedWidthTargetsRef = react.useRef(
|
|
334
|
+
/* @__PURE__ */ new Map()
|
|
335
|
+
);
|
|
336
|
+
const cachedItemWidths = react.useRef({});
|
|
337
|
+
const cachedNamedTriggerWidths = react.useRef({});
|
|
338
|
+
const cachedSharedTriggerWidths = react.useRef({});
|
|
339
|
+
const [overflowState, setOverflowState] = react.useState(emptyOverflowState);
|
|
340
|
+
const namedTriggerItems = react.useMemo(
|
|
341
|
+
() => items.filter((item) => {
|
|
342
|
+
return item.overflowMode !== "none" && item.overflowGroup !== "shared";
|
|
343
|
+
}),
|
|
344
|
+
[items]
|
|
345
|
+
);
|
|
346
|
+
const groupDefinitions = react.useMemo(() => buildGroupDefinitions(items), [items]);
|
|
347
|
+
const collapseUnits = react.useMemo(() => buildCollapseUnits(items), [items]);
|
|
348
|
+
const computeOverflow = react.useCallback(() => {
|
|
349
|
+
const container = containerRef.current;
|
|
350
|
+
if (!container) {
|
|
351
|
+
return emptyOverflowState;
|
|
352
|
+
}
|
|
353
|
+
const containerStyles = core.ownerWindow(container).getComputedStyle(container);
|
|
354
|
+
const paddingLeft = Number.parseFloat(containerStyles.paddingLeft || "0") || 0;
|
|
355
|
+
const paddingRight = Number.parseFloat(containerStyles.paddingRight || "0") || 0;
|
|
356
|
+
const borderLeft = Number.parseFloat(containerStyles.borderLeftWidth || "0") || 0;
|
|
357
|
+
const borderRight = Number.parseFloat(containerStyles.borderRightWidth || "0") || 0;
|
|
358
|
+
const containerWidth = Math.floor(
|
|
359
|
+
container.getBoundingClientRect().width - paddingLeft - paddingRight - borderLeft - borderRight
|
|
360
|
+
);
|
|
361
|
+
if (containerWidth <= 0) {
|
|
362
|
+
return emptyOverflowState;
|
|
363
|
+
}
|
|
364
|
+
const rootGap = readGap(
|
|
365
|
+
containerStyles.columnGap || containerStyles.gap || "0"
|
|
366
|
+
);
|
|
367
|
+
const bandGaps = /* @__PURE__ */ new Map();
|
|
368
|
+
const contentGaps = /* @__PURE__ */ new Map();
|
|
369
|
+
const itemWidths = /* @__PURE__ */ new Map();
|
|
370
|
+
const namedTriggerWidths = /* @__PURE__ */ new Map();
|
|
371
|
+
const triggerWidths = /* @__PURE__ */ new Map();
|
|
372
|
+
for (const position of bandPositions) {
|
|
373
|
+
const bandElement = bandRefs.current[position];
|
|
374
|
+
if (!bandElement) {
|
|
375
|
+
bandGaps.set(position, 0);
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
const bandStyles = core.ownerWindow(bandElement).getComputedStyle(bandElement);
|
|
379
|
+
bandGaps.set(
|
|
380
|
+
position,
|
|
381
|
+
readGap(bandStyles.columnGap || bandStyles.gap || "0")
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
for (const contentArea of content) {
|
|
385
|
+
const contentElement = contentRefs.current[contentArea.key];
|
|
386
|
+
if (!contentElement) {
|
|
387
|
+
return emptyOverflowState;
|
|
388
|
+
}
|
|
389
|
+
const contentStyles = core.ownerWindow(contentElement).getComputedStyle(contentElement);
|
|
390
|
+
contentGaps.set(
|
|
391
|
+
contentArea.key,
|
|
392
|
+
readGap(contentStyles.columnGap || contentStyles.gap || "0")
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
for (const item of items) {
|
|
396
|
+
const element = itemRefs.current[item.id];
|
|
397
|
+
if (element) {
|
|
398
|
+
const width = measureOverflowItemWidth(element);
|
|
399
|
+
if (width > 0) {
|
|
400
|
+
itemWidths.set(item.id, width);
|
|
401
|
+
cachedItemWidths.current[item.id] = width;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
const cached = cachedItemWidths.current[item.id];
|
|
406
|
+
if (cached != null && cached > 0) {
|
|
407
|
+
itemWidths.set(item.id, cached);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
return emptyOverflowState;
|
|
411
|
+
}
|
|
412
|
+
for (const item of namedTriggerItems) {
|
|
413
|
+
const liveWidth = measureWidth(namedTriggerRefs.current[item.id]);
|
|
414
|
+
if (liveWidth > 0) {
|
|
415
|
+
namedTriggerWidths.set(item.id, liveWidth);
|
|
416
|
+
cachedNamedTriggerWidths.current[item.id] = liveWidth;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
const measureWidthForItem = measureWidth(
|
|
420
|
+
namedTriggerMeasureRefs.current[item.id]
|
|
421
|
+
);
|
|
422
|
+
if (measureWidthForItem > 0) {
|
|
423
|
+
namedTriggerWidths.set(item.id, measureWidthForItem);
|
|
424
|
+
cachedNamedTriggerWidths.current[item.id] = measureWidthForItem;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
const cached = cachedNamedTriggerWidths.current[item.id];
|
|
428
|
+
if (cached != null && cached > 0) {
|
|
429
|
+
namedTriggerWidths.set(item.id, cached);
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
return emptyOverflowState;
|
|
433
|
+
}
|
|
434
|
+
for (const group of groupDefinitions.filter((entry) => !entry.named)) {
|
|
435
|
+
const width = measureWidth(triggerMeasureRefs.current[group.key]);
|
|
436
|
+
if (width <= 0) {
|
|
437
|
+
const cached = cachedSharedTriggerWidths.current[group.key];
|
|
438
|
+
if (cached != null && cached > 0) {
|
|
439
|
+
triggerWidths.set(group.key, cached);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
return emptyOverflowState;
|
|
443
|
+
}
|
|
444
|
+
triggerWidths.set(group.key, width);
|
|
445
|
+
cachedSharedTriggerWidths.current[group.key] = width;
|
|
446
|
+
}
|
|
447
|
+
const nextOverflowState = computeToolbarNextOverflowState({
|
|
448
|
+
bandGaps,
|
|
449
|
+
collapseUnits,
|
|
450
|
+
containerWidth,
|
|
451
|
+
groupDefinitions,
|
|
452
|
+
itemWidths,
|
|
453
|
+
items,
|
|
454
|
+
namedTriggerWidths,
|
|
455
|
+
content,
|
|
456
|
+
contentGaps,
|
|
457
|
+
rootGap,
|
|
458
|
+
triggerWidths
|
|
459
|
+
});
|
|
460
|
+
return nextOverflowState;
|
|
461
|
+
}, [collapseUnits, groupDefinitions, items, namedTriggerItems, content]);
|
|
462
|
+
const scheduleMeasureRef = react.useRef(() => {
|
|
463
|
+
});
|
|
464
|
+
const scheduleMeasure = react.useCallback(() => {
|
|
465
|
+
if (!targetWindow) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (isComputingRef.current) {
|
|
469
|
+
pendingMeasureRef.current = true;
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (rafRef.current != null) {
|
|
473
|
+
targetWindow.cancelAnimationFrame(rafRef.current);
|
|
474
|
+
}
|
|
475
|
+
rafRef.current = targetWindow.requestAnimationFrame(() => {
|
|
476
|
+
rafRef.current = null;
|
|
477
|
+
isComputingRef.current = true;
|
|
478
|
+
try {
|
|
479
|
+
const nextState = computeOverflow();
|
|
480
|
+
setOverflowState((previous) => {
|
|
481
|
+
return areOverflowStatesEqual(previous, nextState) ? previous : nextState;
|
|
482
|
+
});
|
|
483
|
+
} finally {
|
|
484
|
+
clearComputingRafRef.current = targetWindow.requestAnimationFrame(
|
|
485
|
+
() => {
|
|
486
|
+
clearComputingRafRef.current = null;
|
|
487
|
+
isComputingRef.current = false;
|
|
488
|
+
if (pendingMeasureRef.current) {
|
|
489
|
+
pendingMeasureRef.current = false;
|
|
490
|
+
scheduleMeasureRef.current();
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
}, [computeOverflow, targetWindow]);
|
|
497
|
+
core.useIsomorphicLayoutEffect(() => {
|
|
498
|
+
scheduleMeasureRef.current = scheduleMeasure;
|
|
499
|
+
return () => {
|
|
500
|
+
scheduleMeasureRef.current = () => {
|
|
501
|
+
};
|
|
502
|
+
};
|
|
503
|
+
}, [scheduleMeasure]);
|
|
504
|
+
const getCachedWidthForObservedTarget = react.useCallback(
|
|
505
|
+
(target) => {
|
|
506
|
+
switch (target.kind) {
|
|
507
|
+
case "item":
|
|
508
|
+
return cachedItemWidths.current[target.id];
|
|
509
|
+
case "named-trigger":
|
|
510
|
+
case "named-trigger-measure":
|
|
511
|
+
return cachedNamedTriggerWidths.current[target.id];
|
|
512
|
+
case "shared-trigger-measure":
|
|
513
|
+
return cachedSharedTriggerWidths.current[target.groupKey];
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
[]
|
|
517
|
+
);
|
|
518
|
+
const setCachedWidthForObservedTarget = react.useCallback(
|
|
519
|
+
(target, width) => {
|
|
520
|
+
switch (target.kind) {
|
|
521
|
+
case "item":
|
|
522
|
+
cachedItemWidths.current[target.id] = width;
|
|
523
|
+
return;
|
|
524
|
+
case "named-trigger":
|
|
525
|
+
case "named-trigger-measure":
|
|
526
|
+
cachedNamedTriggerWidths.current[target.id] = width;
|
|
527
|
+
return;
|
|
528
|
+
case "shared-trigger-measure":
|
|
529
|
+
cachedSharedTriggerWidths.current[target.groupKey] = width;
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
[]
|
|
534
|
+
);
|
|
535
|
+
const observeWidthTarget = react.useCallback(
|
|
536
|
+
(node, target) => {
|
|
537
|
+
var _a;
|
|
538
|
+
if (!node) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
observedWidthTargetsRef.current.set(node, target);
|
|
542
|
+
(_a = resizeObserverRef.current) == null ? void 0 : _a.observe(node);
|
|
543
|
+
},
|
|
544
|
+
[]
|
|
545
|
+
);
|
|
546
|
+
const unobserveWidthTarget = react.useCallback((node) => {
|
|
547
|
+
var _a;
|
|
548
|
+
if (!node) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
observedWidthTargetsRef.current.delete(node);
|
|
552
|
+
(_a = resizeObserverRef.current) == null ? void 0 : _a.unobserve(node);
|
|
553
|
+
}, []);
|
|
554
|
+
const updateObservedNode = react.useCallback(
|
|
555
|
+
(nodes, key, node, target) => {
|
|
556
|
+
const previous = nodes[key];
|
|
557
|
+
if (previous === node) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (previous) {
|
|
561
|
+
unobserveWidthTarget(previous);
|
|
562
|
+
}
|
|
563
|
+
nodes[key] = node;
|
|
564
|
+
if (node) {
|
|
565
|
+
observeWidthTarget(node, target);
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
[observeWidthTarget, unobserveWidthTarget]
|
|
569
|
+
);
|
|
570
|
+
core.useIsomorphicLayoutEffect(() => {
|
|
571
|
+
scheduleMeasure();
|
|
572
|
+
}, [scheduleMeasure]);
|
|
573
|
+
react.useEffect(() => {
|
|
574
|
+
const container = containerRef.current;
|
|
575
|
+
if (!container) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
let cancelled = false;
|
|
579
|
+
const win = core.ownerWindow(container);
|
|
580
|
+
const resizeObserver = new win.ResizeObserver((entries) => {
|
|
581
|
+
let shouldMeasure = false;
|
|
582
|
+
for (const entry of entries) {
|
|
583
|
+
const target = observedWidthTargetsRef.current.get(entry.target);
|
|
584
|
+
if (!target) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
if (target.kind === "container") {
|
|
588
|
+
shouldMeasure = true;
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
const nextWidth = target.kind === "item" ? measureOverflowItemWidth(entry.target) : measureWidth(entry.target);
|
|
592
|
+
if (nextWidth <= 0) {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
const previousWidth = getCachedWidthForObservedTarget(target);
|
|
596
|
+
if (previousWidth !== nextWidth) {
|
|
597
|
+
setCachedWidthForObservedTarget(target, nextWidth);
|
|
598
|
+
shouldMeasure = true;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (shouldMeasure) {
|
|
602
|
+
scheduleMeasureRef.current();
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
resizeObserverRef.current = resizeObserver;
|
|
606
|
+
observeWidthTarget(container, { kind: "container" });
|
|
607
|
+
for (const node of observedWidthTargetsRef.current.keys()) {
|
|
608
|
+
resizeObserver.observe(node);
|
|
609
|
+
}
|
|
610
|
+
if (win.document.fonts) {
|
|
611
|
+
void win.document.fonts.ready.then(() => {
|
|
612
|
+
if (!cancelled) {
|
|
613
|
+
scheduleMeasureRef.current();
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
return () => {
|
|
618
|
+
cancelled = true;
|
|
619
|
+
resizeObserverRef.current = null;
|
|
620
|
+
resizeObserver.disconnect();
|
|
621
|
+
if (rafRef.current != null) {
|
|
622
|
+
win.cancelAnimationFrame(rafRef.current);
|
|
623
|
+
rafRef.current = null;
|
|
624
|
+
}
|
|
625
|
+
if (clearComputingRafRef.current != null) {
|
|
626
|
+
win.cancelAnimationFrame(clearComputingRafRef.current);
|
|
627
|
+
clearComputingRafRef.current = null;
|
|
628
|
+
}
|
|
629
|
+
isComputingRef.current = false;
|
|
630
|
+
pendingMeasureRef.current = false;
|
|
631
|
+
};
|
|
632
|
+
}, [
|
|
633
|
+
getCachedWidthForObservedTarget,
|
|
634
|
+
observeWidthTarget,
|
|
635
|
+
setCachedWidthForObservedTarget
|
|
636
|
+
]);
|
|
637
|
+
const getItemRef = react.useCallback(
|
|
638
|
+
(id) => {
|
|
639
|
+
const existing = itemRefCallbacks.current.get(id);
|
|
640
|
+
if (existing) {
|
|
641
|
+
return existing;
|
|
642
|
+
}
|
|
643
|
+
const callback = (node) => {
|
|
644
|
+
updateObservedNode(itemRefs.current, id, node, {
|
|
645
|
+
id,
|
|
646
|
+
kind: "item"
|
|
647
|
+
});
|
|
648
|
+
};
|
|
649
|
+
itemRefCallbacks.current.set(id, callback);
|
|
650
|
+
return callback;
|
|
651
|
+
},
|
|
652
|
+
[updateObservedNode]
|
|
653
|
+
);
|
|
654
|
+
const getNamedTriggerRef = react.useCallback(
|
|
655
|
+
(id) => {
|
|
656
|
+
const existing = namedTriggerRefCallbacks.current.get(id);
|
|
657
|
+
if (existing) {
|
|
658
|
+
return existing;
|
|
659
|
+
}
|
|
660
|
+
const callback = (node) => {
|
|
661
|
+
updateObservedNode(namedTriggerRefs.current, id, node, {
|
|
662
|
+
id,
|
|
663
|
+
kind: "named-trigger"
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
namedTriggerRefCallbacks.current.set(id, callback);
|
|
667
|
+
return callback;
|
|
668
|
+
},
|
|
669
|
+
[updateObservedNode]
|
|
670
|
+
);
|
|
671
|
+
const getNamedTriggerMeasureRef = react.useCallback(
|
|
672
|
+
(id) => {
|
|
673
|
+
const existing = namedTriggerMeasureCallbacks.current.get(id);
|
|
674
|
+
if (existing) {
|
|
675
|
+
return existing;
|
|
676
|
+
}
|
|
677
|
+
const callback = (node) => {
|
|
678
|
+
updateObservedNode(namedTriggerMeasureRefs.current, id, node, {
|
|
679
|
+
id,
|
|
680
|
+
kind: "named-trigger-measure"
|
|
681
|
+
});
|
|
682
|
+
};
|
|
683
|
+
namedTriggerMeasureCallbacks.current.set(id, callback);
|
|
684
|
+
return callback;
|
|
685
|
+
},
|
|
686
|
+
[updateObservedNode]
|
|
687
|
+
);
|
|
688
|
+
const getContentRef = react.useCallback((contentKey) => {
|
|
689
|
+
const existing = contentRefCallbacks.current.get(contentKey);
|
|
690
|
+
if (existing) {
|
|
691
|
+
return existing;
|
|
692
|
+
}
|
|
693
|
+
const callback = (node) => {
|
|
694
|
+
contentRefs.current[contentKey] = node;
|
|
695
|
+
};
|
|
696
|
+
contentRefCallbacks.current.set(contentKey, callback);
|
|
697
|
+
return callback;
|
|
698
|
+
}, []);
|
|
699
|
+
const getBandRef = react.useCallback((position) => {
|
|
700
|
+
const existing = bandRefCallbacks.current.get(position);
|
|
701
|
+
if (existing) {
|
|
702
|
+
return existing;
|
|
703
|
+
}
|
|
704
|
+
const callback = (node) => {
|
|
705
|
+
bandRefs.current[position] = node;
|
|
706
|
+
};
|
|
707
|
+
bandRefCallbacks.current.set(position, callback);
|
|
708
|
+
return callback;
|
|
709
|
+
}, []);
|
|
710
|
+
const getTriggerMeasureRef = react.useCallback(
|
|
711
|
+
(groupKey) => {
|
|
712
|
+
const existing = triggerMeasureCallbacks.current.get(groupKey);
|
|
713
|
+
if (existing) {
|
|
714
|
+
return existing;
|
|
715
|
+
}
|
|
716
|
+
const callback = (node) => {
|
|
717
|
+
updateObservedNode(triggerMeasureRefs.current, groupKey, node, {
|
|
718
|
+
groupKey,
|
|
719
|
+
kind: "shared-trigger-measure"
|
|
720
|
+
});
|
|
721
|
+
};
|
|
722
|
+
triggerMeasureCallbacks.current.set(groupKey, callback);
|
|
723
|
+
return callback;
|
|
724
|
+
},
|
|
725
|
+
[updateObservedNode]
|
|
726
|
+
);
|
|
727
|
+
return {
|
|
728
|
+
containerRef,
|
|
729
|
+
getBandRef,
|
|
730
|
+
getItemRef,
|
|
731
|
+
getNamedTriggerMeasureRef,
|
|
732
|
+
getNamedTriggerRef,
|
|
733
|
+
getContentRef,
|
|
734
|
+
getTriggerMeasureRef,
|
|
735
|
+
isOverflowing: overflowState.overflowGroups.length > 0,
|
|
736
|
+
overflowGroups: overflowState.overflowGroups,
|
|
737
|
+
overflowedIds: overflowState.overflowedIds,
|
|
738
|
+
overflowTriggerGroups: groupDefinitions
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
exports.useToolbarNextOverflow = useToolbarNextOverflow;
|
|
743
|
+
//# sourceMappingURL=useToolbarNextOverflow.js.map
|