ember-primitives 0.61.0 → 0.62.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/README.md +14 -7
- package/declarations/components/command-palette.d.ts +316 -0
- package/declarations/components/command-palette.d.ts.map +1 -0
- package/declarations/components/dialog.d.ts +51 -1
- package/declarations/components/dialog.d.ts.map +1 -1
- package/declarations/components/resizable/state.d.ts.map +1 -1
- package/declarations/index.d.ts +2 -1
- package/declarations/index.d.ts.map +1 -1
- package/dist/components/command-palette.js +363 -0
- package/dist/components/command-palette.js.map +1 -0
- package/dist/components/dialog.js +50 -1
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/resizable/state.js +154 -120
- package/dist/components/resizable/state.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/components/command-palette.gts +719 -0
- package/src/components/dialog.gts +71 -1
- package/src/components/resizable/state.ts +180 -126
- package/src/index.ts +2 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const GROUP_SELECTOR = '.ember-primitives__resizable';
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const PANEL_CLASS = 'ember-primitives__resizable__panel';
|
|
3
|
+
const HANDLE_CLASS = 'ember-primitives__resizable__handle';
|
|
4
|
+
const MEMBER_SELECTOR = `.${PANEL_CLASS}, .${HANDLE_CLASS}`;
|
|
4
5
|
const DEFAULT_MIN = 0;
|
|
5
6
|
const DEFAULT_MAX = 100;
|
|
6
7
|
|
|
@@ -40,6 +41,44 @@ function isCollapsible(panel) {
|
|
|
40
41
|
function sameMembers(a, b) {
|
|
41
42
|
return a.length === b.length && a.every((element, index) => element === b[index]);
|
|
42
43
|
}
|
|
44
|
+
function precedes(a, b) {
|
|
45
|
+
return Boolean(b.compareDocumentPosition(a) & Node.DOCUMENT_POSITION_PRECEDING);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The `data-collapsed` attribute is the source of truth for collapse
|
|
50
|
+
* state (it is also the styling hook consumers use).
|
|
51
|
+
*/
|
|
52
|
+
function isCollapsed(panel) {
|
|
53
|
+
return isCollapsible(panel) && panel.hasAttribute('data-collapsed');
|
|
54
|
+
}
|
|
55
|
+
function setCollapsed(panel, collapsed) {
|
|
56
|
+
if (collapsed === panel.hasAttribute('data-collapsed')) return;
|
|
57
|
+
if (collapsed) {
|
|
58
|
+
panel.setAttribute('data-collapsed', '');
|
|
59
|
+
} else {
|
|
60
|
+
panel.removeAttribute('data-collapsed');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The panels immediately before and after the given handle element,
|
|
66
|
+
* in document order.
|
|
67
|
+
*/
|
|
68
|
+
function neighborsOf(handleElement, panels) {
|
|
69
|
+
let prev = null;
|
|
70
|
+
let next = null;
|
|
71
|
+
for (const panel of panels) {
|
|
72
|
+
const position = handleElement.compareDocumentPosition(panel);
|
|
73
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
|
|
74
|
+
prev = panel;
|
|
75
|
+
} else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
76
|
+
next = panel;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return [prev, next];
|
|
81
|
+
}
|
|
43
82
|
|
|
44
83
|
/**
|
|
45
84
|
* Sizes are floats that get re-derived (measurement, normalization),
|
|
@@ -119,16 +158,27 @@ class GroupState {
|
|
|
119
158
|
* Panels of nested groups belong to their own group, not this one.
|
|
120
159
|
*/
|
|
121
160
|
get panels() {
|
|
122
|
-
return this.#
|
|
161
|
+
return this.#members().panels;
|
|
123
162
|
}
|
|
124
163
|
get handles() {
|
|
125
|
-
return this.#
|
|
164
|
+
return this.#members().handles;
|
|
126
165
|
}
|
|
127
|
-
#
|
|
166
|
+
#members() {
|
|
167
|
+
const panels = [];
|
|
168
|
+
const handles = [];
|
|
128
169
|
const element = this.element;
|
|
129
|
-
if (!element) return
|
|
130
|
-
|
|
131
|
-
|
|
170
|
+
if (!element) return {
|
|
171
|
+
panels,
|
|
172
|
+
handles
|
|
173
|
+
};
|
|
174
|
+
for (const member of element.querySelectorAll(MEMBER_SELECTOR)) {
|
|
175
|
+
if (member.closest(GROUP_SELECTOR) !== element) continue;
|
|
176
|
+
(member.classList.contains(PANEL_CLASS) ? panels : handles).push(member);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
panels,
|
|
180
|
+
handles
|
|
181
|
+
};
|
|
132
182
|
}
|
|
133
183
|
get sizes() {
|
|
134
184
|
return this.panels.map(panel => this.#sizes.get(panel) ?? 0);
|
|
@@ -175,7 +225,8 @@ class GroupState {
|
|
|
175
225
|
if (group && !affected.has(group)) affected.set(group, false);
|
|
176
226
|
}
|
|
177
227
|
for (const [group, orientationChanged] of affected) {
|
|
178
|
-
|
|
228
|
+
const members = group.#members();
|
|
229
|
+
if (orientationChanged || group.#membershipChanged(members)) group.#layout(members);
|
|
179
230
|
}
|
|
180
231
|
}
|
|
181
232
|
static #observe(element, group) {
|
|
@@ -216,8 +267,8 @@ class GroupState {
|
|
|
216
267
|
this.element = null;
|
|
217
268
|
};
|
|
218
269
|
};
|
|
219
|
-
#membershipChanged() {
|
|
220
|
-
return !sameMembers(
|
|
270
|
+
#membershipChanged(members) {
|
|
271
|
+
return !sameMembers(members.panels, this.#knownPanels) || !sameMembers(members.handles, this.#knownHandles);
|
|
221
272
|
}
|
|
222
273
|
|
|
223
274
|
/**
|
|
@@ -225,17 +276,21 @@ class GroupState {
|
|
|
225
276
|
* keep it; new panels take a share of the remaining space; everything
|
|
226
277
|
* is normalized to 100.
|
|
227
278
|
*/
|
|
228
|
-
#layout() {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
279
|
+
#layout(members = this.#members()) {
|
|
280
|
+
const {
|
|
281
|
+
panels,
|
|
282
|
+
handles
|
|
283
|
+
} = members;
|
|
284
|
+
if (this.#drag) this.#drag.members = members;
|
|
285
|
+
this.#knownPanels = panels;
|
|
286
|
+
this.#knownHandles = handles;
|
|
233
287
|
if (panels.length === 0) return;
|
|
234
288
|
let changed = false;
|
|
235
289
|
|
|
236
290
|
// forget sizes of panels that left the DOM
|
|
237
|
-
|
|
238
|
-
|
|
291
|
+
const current = new Set(panels);
|
|
292
|
+
for (const known of this.#sizes.keys()) {
|
|
293
|
+
if (!current.has(known)) {
|
|
239
294
|
this.#sizes.delete(known);
|
|
240
295
|
changed = true;
|
|
241
296
|
}
|
|
@@ -252,7 +307,7 @@ class GroupState {
|
|
|
252
307
|
unspecified.push(panel);
|
|
253
308
|
continue;
|
|
254
309
|
}
|
|
255
|
-
const size =
|
|
310
|
+
const size = isCollapsed(panel) ? preferred : clamp(preferred, minSizeOf(panel), maxSizeOf(panel));
|
|
256
311
|
computed.set(panel, size);
|
|
257
312
|
specifiedTotal += size;
|
|
258
313
|
}
|
|
@@ -302,8 +357,8 @@ class GroupState {
|
|
|
302
357
|
changed = true;
|
|
303
358
|
}
|
|
304
359
|
}
|
|
305
|
-
this.#apply(changedPanels);
|
|
306
|
-
if (changed) this.#notify();
|
|
360
|
+
this.#apply(changedPanels, members);
|
|
361
|
+
if (changed) this.#notify(panels);
|
|
307
362
|
}
|
|
308
363
|
|
|
309
364
|
/**
|
|
@@ -314,24 +369,22 @@ class GroupState {
|
|
|
314
369
|
* points, not derived from sizes -- rendered pixel sizes include
|
|
315
370
|
* borders/padding, so a collapsed panel rarely measures exactly 0.)
|
|
316
371
|
*/
|
|
317
|
-
#apply(candidates) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
panel.style.flex = `${size / unit} 1 0px`;
|
|
332
|
-
}
|
|
372
|
+
#apply(candidates, members) {
|
|
373
|
+
/**
|
|
374
|
+
* With no unit fixed yet, nothing has ever been written, so every
|
|
375
|
+
* panel renders at the CSS default -- an equal 1/n share.
|
|
376
|
+
*/
|
|
377
|
+
const unit = this.#unit ?? 100 / members.panels.length;
|
|
378
|
+
for (const panel of candidates) {
|
|
379
|
+
const size = this.#sizes.get(panel);
|
|
380
|
+
if (size === undefined) continue;
|
|
381
|
+
const inlineGrow = panel.style.flexGrow;
|
|
382
|
+
const impliedPercent = (inlineGrow === '' ? 1 : parseFloat(inlineGrow)) * unit;
|
|
383
|
+
if (isSameSize(impliedPercent, size)) continue;
|
|
384
|
+
this.#unit ??= unit;
|
|
385
|
+
panel.style.flex = `${size / unit} 1 0px`;
|
|
333
386
|
}
|
|
334
|
-
this.#syncHandles();
|
|
387
|
+
this.#syncHandles(members);
|
|
335
388
|
}
|
|
336
389
|
|
|
337
390
|
/**
|
|
@@ -339,10 +392,21 @@ class GroupState {
|
|
|
339
392
|
* immediately before it. (A splitter between two side-by-side panes
|
|
340
393
|
* is oriented *vertically*, and vice-versa.)
|
|
341
394
|
*/
|
|
342
|
-
#syncHandles() {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
395
|
+
#syncHandles(members) {
|
|
396
|
+
const {
|
|
397
|
+
panels,
|
|
398
|
+
handles
|
|
399
|
+
} = members;
|
|
400
|
+
const ariaOrientation = this.#isHorizontal ? 'vertical' : 'horizontal';
|
|
401
|
+
let index = 0;
|
|
402
|
+
for (const handle of handles) {
|
|
403
|
+
let following = panels[index];
|
|
404
|
+
while (following && precedes(following, handle)) {
|
|
405
|
+
index++;
|
|
406
|
+
following = panels[index];
|
|
407
|
+
}
|
|
408
|
+
const prev = panels[index - 1];
|
|
409
|
+
setAttribute(handle, 'aria-orientation', ariaOrientation);
|
|
346
410
|
if (!prev) continue;
|
|
347
411
|
|
|
348
412
|
// Panels render their own (component-owned, incrementing) id
|
|
@@ -352,34 +416,17 @@ class GroupState {
|
|
|
352
416
|
setAttribute(handle, 'aria-valuenow', `${Math.round(this.#sizes.get(prev) ?? 0)}`);
|
|
353
417
|
}
|
|
354
418
|
}
|
|
355
|
-
#notify() {
|
|
356
|
-
this.#options.onLayoutChange()?.(this.
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* The `data-collapsed` attribute is the source of truth for collapse
|
|
361
|
-
* state (it is also the styling hook consumers use).
|
|
362
|
-
*/
|
|
363
|
-
#isCollapsed(panel) {
|
|
364
|
-
return isCollapsible(panel) && panel.hasAttribute('data-collapsed');
|
|
365
|
-
}
|
|
366
|
-
#setCollapsed(panel, collapsed) {
|
|
367
|
-
if (collapsed === panel.hasAttribute('data-collapsed')) return;
|
|
368
|
-
if (collapsed) {
|
|
369
|
-
panel.setAttribute('data-collapsed', '');
|
|
370
|
-
} else {
|
|
371
|
-
panel.removeAttribute('data-collapsed');
|
|
372
|
-
}
|
|
419
|
+
#notify(panels) {
|
|
420
|
+
this.#options.onLayoutChange()?.(panels.map(panel => this.#sizes.get(panel) ?? 0));
|
|
373
421
|
}
|
|
374
422
|
|
|
375
423
|
/**
|
|
376
424
|
* Re-derive percentage sizes from actual rendered pixels.
|
|
377
425
|
* Corrects any drift (e.g. from CSS min-sizes) before an interaction.
|
|
378
426
|
*/
|
|
379
|
-
#syncSizesFromDOM() {
|
|
380
|
-
const panels = this.panels;
|
|
427
|
+
#syncSizesFromDOM(panels, measured) {
|
|
381
428
|
// collapsed panels are 0 even though their borders/padding measure larger
|
|
382
|
-
const px = panels.map(panel =>
|
|
429
|
+
const px = panels.map((panel, index) => isCollapsed(panel) ? 0 : measured?.[index] ?? this.#pixelSizeOf(panel));
|
|
383
430
|
const total = px.reduce((sum, value) => sum + value, 0);
|
|
384
431
|
if (total <= 0) return;
|
|
385
432
|
panels.forEach((panel, index) => {
|
|
@@ -395,42 +442,26 @@ class GroupState {
|
|
|
395
442
|
return this.#isHorizontal ? box.width : box.height;
|
|
396
443
|
}
|
|
397
444
|
|
|
398
|
-
/**
|
|
399
|
-
* The panels immediately before and after the given handle element,
|
|
400
|
-
* in document order.
|
|
401
|
-
*/
|
|
402
|
-
#neighborsOf(handleElement) {
|
|
403
|
-
let prev = null;
|
|
404
|
-
let next = null;
|
|
405
|
-
for (const panel of this.panels) {
|
|
406
|
-
const position = handleElement.compareDocumentPosition(panel);
|
|
407
|
-
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
|
|
408
|
-
prev = panel;
|
|
409
|
-
} else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
410
|
-
next = panel;
|
|
411
|
-
break;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return [prev, next];
|
|
415
|
-
}
|
|
416
|
-
|
|
417
445
|
/**
|
|
418
446
|
* Moves the boundary between the two panels by `requestedDelta` (%),
|
|
419
447
|
* respecting both panels' min/max constraints.
|
|
420
448
|
*/
|
|
421
|
-
#applyDelta(prev, next, basePrevSize, baseNextSize, requestedDelta) {
|
|
449
|
+
#applyDelta(prev, next, basePrevSize, baseNextSize, requestedDelta, members) {
|
|
422
450
|
const total = basePrevSize + baseNextSize;
|
|
451
|
+
const prevMin = minSizeOf(prev);
|
|
452
|
+
const prevMax = maxSizeOf(prev);
|
|
453
|
+
const prevCollapsible = isCollapsible(prev);
|
|
423
454
|
let target = basePrevSize + requestedDelta;
|
|
424
|
-
if (
|
|
455
|
+
if (prevCollapsible && target < prevMin) {
|
|
425
456
|
/**
|
|
426
457
|
* Collapsible panels snap: below half the minimum they close
|
|
427
458
|
* entirely; between half and the minimum they hold at the minimum.
|
|
428
459
|
* (This also keeps a collapsed panel closed when its handle is
|
|
429
460
|
* dragged further in the closing direction.)
|
|
430
461
|
*/
|
|
431
|
-
target = target <
|
|
462
|
+
target = target < prevMin / 2 ? 0 : prevMin;
|
|
432
463
|
} else {
|
|
433
|
-
target = clamp(target,
|
|
464
|
+
target = clamp(target, prevMin, prevMax);
|
|
434
465
|
}
|
|
435
466
|
|
|
436
467
|
/**
|
|
@@ -443,7 +474,7 @@ class GroupState {
|
|
|
443
474
|
target = clamp(target, nextMin, nextMax);
|
|
444
475
|
|
|
445
476
|
// both panels' constraints cannot be satisfied at once
|
|
446
|
-
if (!
|
|
477
|
+
if (!prevCollapsible && (target < prevMin || target > prevMax)) return;
|
|
447
478
|
|
|
448
479
|
/**
|
|
449
480
|
* Nothing to do when the clamped result matches the current sizes
|
|
@@ -452,23 +483,25 @@ class GroupState {
|
|
|
452
483
|
if (isSameSize(this.#sizes.get(prev), target) && isSameSize(this.#sizes.get(next), total - target)) {
|
|
453
484
|
return;
|
|
454
485
|
}
|
|
455
|
-
if (
|
|
456
|
-
if (target === 0 && !
|
|
486
|
+
if (prevCollapsible) {
|
|
487
|
+
if (target === 0 && !isCollapsed(prev)) {
|
|
457
488
|
this.#previousSizes.set(prev, basePrevSize);
|
|
458
489
|
}
|
|
459
|
-
|
|
490
|
+
setCollapsed(prev, target === 0);
|
|
460
491
|
}
|
|
461
492
|
this.#sizes.set(prev, target);
|
|
462
493
|
this.#sizes.set(next, total - target);
|
|
463
|
-
this.#apply([prev, next]);
|
|
464
|
-
this.#notify();
|
|
494
|
+
this.#apply([prev, next], members);
|
|
495
|
+
this.#notify(members.panels);
|
|
465
496
|
}
|
|
466
497
|
startDrag(handleElement, event) {
|
|
467
498
|
if (event.button !== 0) return;
|
|
468
499
|
if (this.#drag) return;
|
|
469
|
-
const
|
|
500
|
+
const members = this.#members();
|
|
501
|
+
const [prev, next] = neighborsOf(handleElement, members.panels);
|
|
470
502
|
if (!prev || !next) return;
|
|
471
|
-
this.#
|
|
503
|
+
const measured = members.panels.map(panel => this.#pixelSizeOf(panel));
|
|
504
|
+
this.#syncSizesFromDOM(members.panels, measured);
|
|
472
505
|
const move = moveEvent => this.#dragMove(moveEvent);
|
|
473
506
|
const end = endEvent => this.#endDrag(handleElement, endEvent);
|
|
474
507
|
this.#drag = {
|
|
@@ -477,7 +510,8 @@ class GroupState {
|
|
|
477
510
|
startPrevSize: this.#sizes.get(prev) ?? 0,
|
|
478
511
|
startNextSize: this.#sizes.get(next) ?? 0,
|
|
479
512
|
startCoordinate: this.#isHorizontal ? event.clientX : event.clientY,
|
|
480
|
-
totalPx:
|
|
513
|
+
totalPx: measured.reduce((sum, value) => sum + value, 0),
|
|
514
|
+
members,
|
|
481
515
|
move,
|
|
482
516
|
end
|
|
483
517
|
};
|
|
@@ -490,9 +524,9 @@ class GroupState {
|
|
|
490
524
|
} catch {
|
|
491
525
|
// synthetic events (tests) may not have an active pointer
|
|
492
526
|
}
|
|
493
|
-
handleElement.addEventListener('pointermove',
|
|
494
|
-
handleElement.addEventListener('pointerup',
|
|
495
|
-
handleElement.addEventListener('pointercancel',
|
|
527
|
+
handleElement.addEventListener('pointermove', move);
|
|
528
|
+
handleElement.addEventListener('pointerup', end);
|
|
529
|
+
handleElement.addEventListener('pointercancel', end);
|
|
496
530
|
handleElement.setAttribute('data-resizing', '');
|
|
497
531
|
document.body.style.cursor = this.#isHorizontal ? 'col-resize' : 'row-resize';
|
|
498
532
|
document.body.style.userSelect = 'none';
|
|
@@ -503,7 +537,7 @@ class GroupState {
|
|
|
503
537
|
if (drag.totalPx <= 0) return;
|
|
504
538
|
const coordinate = this.#isHorizontal ? event.clientX : event.clientY;
|
|
505
539
|
const deltaPercent = (coordinate - drag.startCoordinate) / drag.totalPx * 100;
|
|
506
|
-
this.#applyDelta(drag.prev, drag.next, drag.startPrevSize, drag.startNextSize, deltaPercent);
|
|
540
|
+
this.#applyDelta(drag.prev, drag.next, drag.startPrevSize, drag.startNextSize, deltaPercent, drag.members);
|
|
507
541
|
}
|
|
508
542
|
#endDrag(handleElement, event) {
|
|
509
543
|
const drag = this.#drag;
|
|
@@ -526,41 +560,41 @@ class GroupState {
|
|
|
526
560
|
* Keyboard support for the WAI-ARIA window-splitter pattern.
|
|
527
561
|
*/
|
|
528
562
|
handleKeyDown(handleElement, event) {
|
|
529
|
-
const
|
|
563
|
+
const members = this.#members();
|
|
564
|
+
const [prev, next] = neighborsOf(handleElement, members.panels);
|
|
530
565
|
if (!prev || !next) return;
|
|
531
566
|
if (event.key === 'Enter') {
|
|
532
|
-
this.#toggleCollapse(prev, next);
|
|
567
|
+
this.#toggleCollapse(prev, next, members);
|
|
533
568
|
return;
|
|
534
569
|
}
|
|
535
570
|
const step = event.shiftKey ? KEYBOARD_STEP_COARSE : KEYBOARD_STEP;
|
|
536
571
|
const isHorizontal = this.#isHorizontal;
|
|
537
|
-
let
|
|
572
|
+
let toDelta = null;
|
|
538
573
|
switch (event.key) {
|
|
539
574
|
case 'ArrowLeft':
|
|
540
|
-
if (isHorizontal)
|
|
575
|
+
if (isHorizontal) toDelta = () => -step;
|
|
541
576
|
break;
|
|
542
577
|
case 'ArrowRight':
|
|
543
|
-
if (isHorizontal)
|
|
578
|
+
if (isHorizontal) toDelta = () => step;
|
|
544
579
|
break;
|
|
545
580
|
case 'ArrowUp':
|
|
546
|
-
if (!isHorizontal)
|
|
581
|
+
if (!isHorizontal) toDelta = () => -step;
|
|
547
582
|
break;
|
|
548
583
|
case 'ArrowDown':
|
|
549
|
-
if (!isHorizontal)
|
|
584
|
+
if (!isHorizontal) toDelta = () => step;
|
|
550
585
|
break;
|
|
551
586
|
case 'Home':
|
|
552
|
-
|
|
553
|
-
delta = minSizeOf(prev) - (this.#sizes.get(prev) ?? 0);
|
|
587
|
+
toDelta = prevSize => minSizeOf(prev) - prevSize;
|
|
554
588
|
break;
|
|
555
589
|
case 'End':
|
|
556
|
-
|
|
557
|
-
delta = maxSizeOf(prev) - (this.#sizes.get(prev) ?? 0);
|
|
590
|
+
toDelta = prevSize => maxSizeOf(prev) - prevSize;
|
|
558
591
|
break;
|
|
559
592
|
}
|
|
560
|
-
if (
|
|
593
|
+
if (!toDelta) return;
|
|
561
594
|
event.preventDefault();
|
|
562
|
-
this.#syncSizesFromDOM();
|
|
563
|
-
|
|
595
|
+
this.#syncSizesFromDOM(members.panels);
|
|
596
|
+
const prevSize = this.#sizes.get(prev) ?? 0;
|
|
597
|
+
this.#applyDelta(prev, next, prevSize, this.#sizes.get(next) ?? 0, toDelta(prevSize), members);
|
|
564
598
|
}
|
|
565
599
|
|
|
566
600
|
/**
|
|
@@ -569,27 +603,27 @@ class GroupState {
|
|
|
569
603
|
*
|
|
570
604
|
* Only does anything when the preceding panel is `@collapsible`.
|
|
571
605
|
*/
|
|
572
|
-
#toggleCollapse(prev, next) {
|
|
606
|
+
#toggleCollapse(prev, next, members) {
|
|
573
607
|
if (!isCollapsible(prev)) return;
|
|
574
|
-
this.#syncSizesFromDOM();
|
|
608
|
+
this.#syncSizesFromDOM(members.panels);
|
|
575
609
|
const prevSize = this.#sizes.get(prev) ?? 0;
|
|
576
610
|
const nextSize = this.#sizes.get(next) ?? 0;
|
|
577
|
-
if (
|
|
611
|
+
if (isCollapsed(prev)) {
|
|
578
612
|
const preferred = this.#previousSizes.get(prev) ?? requestedSizeOf(prev) ?? Math.max(minSizeOf(prev), 10);
|
|
579
613
|
const available = nextSize - minSizeOf(next);
|
|
580
614
|
const restored = Math.min(preferred, available);
|
|
581
615
|
if (restored <= 0) return;
|
|
582
|
-
|
|
616
|
+
setCollapsed(prev, false);
|
|
583
617
|
this.#sizes.set(prev, restored);
|
|
584
618
|
this.#sizes.set(next, nextSize - restored);
|
|
585
619
|
} else {
|
|
586
620
|
this.#previousSizes.set(prev, prevSize);
|
|
587
|
-
|
|
621
|
+
setCollapsed(prev, true);
|
|
588
622
|
this.#sizes.set(prev, 0);
|
|
589
623
|
this.#sizes.set(next, nextSize + prevSize);
|
|
590
624
|
}
|
|
591
|
-
this.#apply([prev, next]);
|
|
592
|
-
this.#notify();
|
|
625
|
+
this.#apply([prev, next], members);
|
|
626
|
+
this.#notify(members.panels);
|
|
593
627
|
}
|
|
594
628
|
}
|
|
595
629
|
|