@johly/bits-ui 2.18.2 → 2.18.3
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.
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
let scrollable = $state(false);
|
|
22
22
|
let atStart = $state(true);
|
|
23
23
|
let atEnd = $state(true);
|
|
24
|
+
let rowWidthFrame: number | null = null;
|
|
25
|
+
let appliedRowWidth: string | null = null;
|
|
24
26
|
const listState = $derived<DataListChildrenSnippetProps<TMeta>>({
|
|
25
27
|
search: surface.search,
|
|
26
28
|
nodes: surface.displayNodes,
|
|
@@ -45,19 +47,111 @@
|
|
|
45
47
|
atEnd = ref.scrollTop >= maxScrollTop - 1;
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
function getRowWidthTarget(node: HTMLElement) {
|
|
51
|
+
return node.closest<HTMLElement>(
|
|
52
|
+
[
|
|
53
|
+
"[data-menu-content]",
|
|
54
|
+
"[data-menu-sub-content]",
|
|
55
|
+
"[data-dropdown-menu-content]",
|
|
56
|
+
"[data-dropdown-menu-sub-content]",
|
|
57
|
+
"[data-context-menu-content]",
|
|
58
|
+
"[data-context-menu-sub-content]",
|
|
59
|
+
"[data-menubar-content]",
|
|
60
|
+
"[data-menubar-sub-content]",
|
|
61
|
+
].join(",")
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getRowCandidates(node: HTMLElement) {
|
|
66
|
+
const selector = [
|
|
67
|
+
"[data-menu-item]",
|
|
68
|
+
"[data-menu-checkbox-item]",
|
|
69
|
+
"[data-menu-radio-item]",
|
|
70
|
+
"[data-menu-sub-trigger]",
|
|
71
|
+
"[data-dropdown-menu-item]",
|
|
72
|
+
"[data-dropdown-menu-checkbox-item]",
|
|
73
|
+
"[data-dropdown-menu-radio-item]",
|
|
74
|
+
"[data-dropdown-menu-sub-trigger]",
|
|
75
|
+
"[data-context-menu-item]",
|
|
76
|
+
"[data-context-menu-checkbox-item]",
|
|
77
|
+
"[data-context-menu-radio-item]",
|
|
78
|
+
"[data-context-menu-sub-trigger]",
|
|
79
|
+
"[data-menubar-item]",
|
|
80
|
+
"[data-menubar-checkbox-item]",
|
|
81
|
+
"[data-menubar-radio-item]",
|
|
82
|
+
"[data-menubar-sub-trigger]",
|
|
83
|
+
].join(",");
|
|
84
|
+
const rows = Array.from(node.querySelectorAll<HTMLElement>(selector));
|
|
85
|
+
return rows.length
|
|
86
|
+
? rows
|
|
87
|
+
: Array.from(node.children).filter(
|
|
88
|
+
(child): child is HTMLElement => child instanceof HTMLElement
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function updateRowWidth() {
|
|
93
|
+
rowWidthFrame = null;
|
|
94
|
+
if (!ref) return;
|
|
95
|
+
const rows = getRowCandidates(ref);
|
|
96
|
+
if (!rows.length) {
|
|
97
|
+
if (appliedRowWidth !== null) {
|
|
98
|
+
ref.style.removeProperty("--row-width");
|
|
99
|
+
getRowWidthTarget(ref)?.style.removeProperty("--row-width");
|
|
100
|
+
appliedRowWidth = null;
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let maxWidth = 0;
|
|
106
|
+
const restore: Array<() => void> = [];
|
|
107
|
+
for (const row of rows) {
|
|
108
|
+
const previousWidth = row.style.width;
|
|
109
|
+
row.style.width = "max-content";
|
|
110
|
+
restore.push(() => (row.style.width = previousWidth));
|
|
111
|
+
maxWidth = Math.max(maxWidth, row.scrollWidth, row.offsetWidth);
|
|
112
|
+
}
|
|
113
|
+
for (const restoreRow of restore) restoreRow();
|
|
114
|
+
|
|
115
|
+
if (maxWidth <= 0) return;
|
|
116
|
+
const width = `${Math.ceil(Math.min(maxWidth + 1, 500))}px`;
|
|
117
|
+
if (appliedRowWidth === width) return;
|
|
118
|
+
appliedRowWidth = width;
|
|
119
|
+
ref.style.setProperty("--row-width", width);
|
|
120
|
+
getRowWidthTarget(ref)?.style.setProperty("--row-width", width);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function queueUpdateRowWidth() {
|
|
124
|
+
if (!ref) return;
|
|
125
|
+
const win = ref.ownerDocument.defaultView;
|
|
126
|
+
if (!win) return;
|
|
127
|
+
if (rowWidthFrame !== null) win.cancelAnimationFrame(rowWidthFrame);
|
|
128
|
+
rowWidthFrame = win.requestAnimationFrame(updateRowWidth);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function clearRowWidthFrame() {
|
|
132
|
+
if (rowWidthFrame === null || !ref) return;
|
|
133
|
+
ref.ownerDocument.defaultView?.cancelAnimationFrame(rowWidthFrame);
|
|
134
|
+
rowWidthFrame = null;
|
|
135
|
+
}
|
|
136
|
+
|
|
48
137
|
$effect(() => {
|
|
49
138
|
const node = ref;
|
|
50
139
|
if (!node) return;
|
|
51
140
|
updateScrollState();
|
|
141
|
+
queueUpdateRowWidth();
|
|
52
142
|
const win = node.ownerDocument.defaultView;
|
|
53
143
|
if (!win) return;
|
|
54
|
-
const
|
|
144
|
+
const updateMeasurements = () => {
|
|
145
|
+
updateScrollState();
|
|
146
|
+
queueUpdateRowWidth();
|
|
147
|
+
};
|
|
148
|
+
const resizeObserver = new win.ResizeObserver(updateMeasurements);
|
|
55
149
|
resizeObserver.observe(node);
|
|
56
150
|
for (const child of Array.from(node.children)) {
|
|
57
151
|
resizeObserver.observe(child);
|
|
58
152
|
}
|
|
59
153
|
const mutationObserver = new win.MutationObserver(() => {
|
|
60
|
-
|
|
154
|
+
updateMeasurements();
|
|
61
155
|
for (const child of Array.from(node.children)) {
|
|
62
156
|
resizeObserver.observe(child);
|
|
63
157
|
}
|
|
@@ -68,12 +162,16 @@
|
|
|
68
162
|
node.removeEventListener("scroll", updateScrollState);
|
|
69
163
|
mutationObserver.disconnect();
|
|
70
164
|
resizeObserver.disconnect();
|
|
165
|
+
clearRowWidthFrame();
|
|
71
166
|
};
|
|
72
167
|
});
|
|
73
168
|
|
|
74
169
|
$effect(() => {
|
|
75
170
|
surface.displayNodes;
|
|
76
|
-
afterTick(
|
|
171
|
+
afterTick(() => {
|
|
172
|
+
updateScrollState();
|
|
173
|
+
queueUpdateRowWidth();
|
|
174
|
+
});
|
|
77
175
|
});
|
|
78
176
|
|
|
79
177
|
function stopNavigationEvent(event: KeyboardEvent) {
|