@destyler/splitter 0.0.2 → 0.0.4

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/dist/index.mjs CHANGED
@@ -1,1825 +1,5 @@
1
- import { watchEffect, defineComponent, ref, computed, watch, h, toRefs, withDirectives, onMounted, onUnmounted } from 'vue';
2
- import { DestylerPrimitive } from '@destyler/primitive';
3
- import { isBrowser, createContext, areEqual } from '@destyler/shared';
4
- import { useDirection, useForwardExpose } from '@destyler/composition';
5
- import { BindOnceDirective } from '@destyler/directives';
6
- import { nanoid } from 'nanoid/non-secure';
7
-
8
- function useUniqueId(idFromParams = null) {
9
- if (!isBrowser && !idFromParams)
10
- console.warn("DestylerSplitter component required `id` for SSR. Or you can wrap the component with `<ClientOnly>`.");
11
- return idFromParams ?? nanoid(6);
12
- }
13
-
14
- function assert(expectedCondition, message = "Assertion failed!") {
15
- if (!expectedCondition) {
16
- console.error(message);
17
- throw new Error(message);
18
- }
19
- }
20
-
21
- function getPanelGroupElement(id, rootElement = document) {
22
- if (!isBrowser)
23
- return null;
24
- if (rootElement instanceof HTMLElement && rootElement?.dataset?.panelGroupId === id)
25
- return rootElement;
26
- const element = rootElement.querySelector(
27
- `[data-panel-group][data-panel-group-id="${id}"]`
28
- );
29
- if (element)
30
- return element;
31
- return null;
32
- }
33
- function getResizeHandleElement(id, scope = document) {
34
- if (!isBrowser)
35
- return null;
36
- const element = scope.querySelector(`[data-panel-resize-handle-id="${id}"]`);
37
- if (element)
38
- return element;
39
- return null;
40
- }
41
- function getResizeHandleElementIndex(groupId, id, scope = document) {
42
- if (!isBrowser)
43
- return null;
44
- const handles = getResizeHandleElementsForGroup(groupId, scope);
45
- const index = handles.findIndex(
46
- (handle) => handle.getAttribute("data-panel-resize-handle-id") === id
47
- );
48
- return index ?? null;
49
- }
50
- function getResizeHandleElementsForGroup(groupId, scope = document) {
51
- if (!isBrowser)
52
- return [];
53
- return Array.from(
54
- scope.querySelectorAll(
55
- `[data-panel-resize-handle-id][data-panel-group-id="${groupId}"]`
56
- )
57
- );
58
- }
59
- function getResizeHandlePanelIds(groupId, handleId, panelsArray, scope = document) {
60
- const handle = getResizeHandleElement(handleId, scope);
61
- const handles = getResizeHandleElementsForGroup(groupId, scope);
62
- const index = handle ? handles.indexOf(handle) : -1;
63
- const idBefore = panelsArray[index]?.id ?? null;
64
- const idAfter = panelsArray[index + 1]?.id ?? null;
65
- return [idBefore, idAfter];
66
- }
67
-
68
- function useWindowSplitterResizeHandlerBehavior({
69
- disabled,
70
- handleId,
71
- resizeHandler,
72
- panelGroupElement
73
- }) {
74
- watchEffect((onCleanup) => {
75
- const _panelGroupElement = panelGroupElement.value;
76
- if (disabled.value || resizeHandler.value === null || _panelGroupElement === null)
77
- return;
78
- const handleElement = getResizeHandleElement(handleId, _panelGroupElement);
79
- if (handleElement == null)
80
- return;
81
- const onKeyDown = (event) => {
82
- if (event.defaultPrevented)
83
- return;
84
- switch (event.key) {
85
- case "ArrowDown":
86
- case "ArrowLeft":
87
- case "ArrowRight":
88
- case "ArrowUp":
89
- case "End":
90
- case "Home": {
91
- event.preventDefault();
92
- resizeHandler.value?.(event);
93
- break;
94
- }
95
- case "F6": {
96
- event.preventDefault();
97
- const groupId = handleElement.getAttribute("data-panel-group-id");
98
- assert(groupId);
99
- const handles = getResizeHandleElementsForGroup(
100
- groupId,
101
- _panelGroupElement
102
- );
103
- const index = getResizeHandleElementIndex(
104
- groupId,
105
- handleId,
106
- _panelGroupElement
107
- );
108
- assert(index !== null);
109
- const nextIndex = event.shiftKey ? index > 0 ? index - 1 : handles.length - 1 : index + 1 < handles.length ? index + 1 : 0;
110
- const nextHandle = handles[nextIndex];
111
- nextHandle.focus();
112
- break;
113
- }
114
- }
115
- };
116
- handleElement.addEventListener("keydown", onKeyDown);
117
- onCleanup(() => {
118
- handleElement.removeEventListener("keydown", onKeyDown);
119
- });
120
- });
121
- }
122
-
123
- let currentCursorStyle = null;
124
- let styleElement = null;
125
- function getCursorStyle(state, constraintFlags) {
126
- if (constraintFlags) {
127
- const horizontalMin = (constraintFlags & EXCEEDED_HORIZONTAL_MIN) !== 0;
128
- const horizontalMax = (constraintFlags & EXCEEDED_HORIZONTAL_MAX) !== 0;
129
- const verticalMin = (constraintFlags & EXCEEDED_VERTICAL_MIN) !== 0;
130
- const verticalMax = (constraintFlags & EXCEEDED_VERTICAL_MAX) !== 0;
131
- if (horizontalMin) {
132
- if (verticalMin)
133
- return "se-resize";
134
- else if (verticalMax)
135
- return "ne-resize";
136
- else
137
- return "e-resize";
138
- } else if (horizontalMax) {
139
- if (verticalMin)
140
- return "sw-resize";
141
- else if (verticalMax)
142
- return "nw-resize";
143
- else
144
- return "w-resize";
145
- } else if (verticalMin) {
146
- return "s-resize";
147
- } else if (verticalMax) {
148
- return "n-resize";
149
- }
150
- }
151
- switch (state) {
152
- case "horizontal":
153
- return "ew-resize";
154
- case "intersection":
155
- return "move";
156
- case "vertical":
157
- return "ns-resize";
158
- }
159
- }
160
- function resetGlobalCursorStyle() {
161
- if (styleElement !== null) {
162
- document.head.removeChild(styleElement);
163
- currentCursorStyle = null;
164
- styleElement = null;
165
- }
166
- }
167
- function setGlobalCursorStyle(state, constraintFlags) {
168
- const style = getCursorStyle(state, constraintFlags);
169
- if (currentCursorStyle === style)
170
- return;
171
- currentCursorStyle = style;
172
- if (styleElement === null) {
173
- styleElement = document.createElement("style");
174
- document.head.appendChild(styleElement);
175
- }
176
- styleElement.innerHTML = `*{cursor: ${style}!important;}`;
177
- }
178
- function computePanelFlexBoxStyle({
179
- defaultSize,
180
- dragState,
181
- layout,
182
- panelData,
183
- panelIndex,
184
- precision = 3
185
- }) {
186
- const size = layout[panelIndex];
187
- let flexGrow;
188
- if (size == null) {
189
- flexGrow = defaultSize !== void 0 ? defaultSize.toPrecision(precision) : "1";
190
- } else if (panelData.length === 1) {
191
- flexGrow = "1";
192
- } else {
193
- flexGrow = size.toPrecision(precision);
194
- }
195
- return {
196
- flexBasis: 0,
197
- flexGrow,
198
- flexShrink: 1,
199
- // Without this, Panel sizes may be unintentionally overridden by their content
200
- overflow: "hidden",
201
- // Disable pointer events inside of a panel during resize
202
- // This avoid edge cases like nested iframes
203
- pointerEvents: dragState !== null ? "none" : void 0
204
- };
205
- }
206
-
207
- function isKeyDown(event) {
208
- return event.type === "keydown";
209
- }
210
- function isMouseEvent(event) {
211
- return event.type.startsWith("mouse");
212
- }
213
- function isTouchEvent(event) {
214
- return event.type.startsWith("touch");
215
- }
216
- function getResizeEventCoordinates(event) {
217
- if (isMouseEvent(event)) {
218
- return {
219
- x: event.clientX,
220
- y: event.clientY
221
- };
222
- } else if (isTouchEvent(event)) {
223
- const touch = event.touches[0];
224
- if (touch && touch.clientX && touch.clientY) {
225
- return {
226
- x: touch.clientX,
227
- y: touch.clientY
228
- };
229
- }
230
- }
231
- return {
232
- x: Number.POSITIVE_INFINITY,
233
- y: Number.POSITIVE_INFINITY
234
- };
235
- }
236
- function getResizeEventCursorPosition(direction, event) {
237
- const isHorizontal = direction === "horizontal";
238
- const { x, y } = getResizeEventCoordinates(event);
239
- return isHorizontal ? x : y;
240
- }
241
-
242
- function intersects(rectOne, rectTwo, strict) {
243
- if (strict) {
244
- return rectOne.x < rectTwo.x + rectTwo.width && rectOne.x + rectOne.width > rectTwo.x && rectOne.y < rectTwo.y + rectTwo.height && rectOne.y + rectOne.height > rectTwo.y;
245
- } else {
246
- return rectOne.x <= rectTwo.x + rectTwo.width && rectOne.x + rectOne.width >= rectTwo.x && rectOne.y <= rectTwo.y + rectTwo.height && rectOne.y + rectOne.height >= rectTwo.y;
247
- }
248
- }
249
-
250
- function compare(a, b) {
251
- if (a === b)
252
- throw new Error("Cannot compare node with itself");
253
- const ancestors = {
254
- a: getAncestors(a),
255
- b: getAncestors(b)
256
- };
257
- let common_ancestor;
258
- while (ancestors.a.at(-1) === ancestors.b.at(-1)) {
259
- a = ancestors.a.pop();
260
- b = ancestors.b.pop();
261
- common_ancestor = a;
262
- }
263
- assert(common_ancestor);
264
- const z_indexes = {
265
- a: getZIndex(findStackingContext(ancestors.a)),
266
- b: getZIndex(findStackingContext(ancestors.b))
267
- };
268
- if (z_indexes.a === z_indexes.b) {
269
- const children = common_ancestor.childNodes;
270
- const furthest_ancestors = {
271
- a: ancestors.a.at(-1),
272
- b: ancestors.b.at(-1)
273
- };
274
- let i = children.length;
275
- while (i--) {
276
- const child = children[i];
277
- if (child === furthest_ancestors.a)
278
- return 1;
279
- if (child === furthest_ancestors.b)
280
- return -1;
281
- }
282
- }
283
- return Math.sign(z_indexes.a - z_indexes.b);
284
- }
285
- const props = /\b(?:position|zIndex|opacity|transform|webkitTransform|mixBlendMode|filter|webkitFilter|isolation)\b/;
286
- function isFlexItem(node) {
287
- const display = getComputedStyle(getParent(node)).display;
288
- return display === "flex" || display === "inline-flex";
289
- }
290
- function createsStackingContext(node) {
291
- const style = getComputedStyle(node);
292
- if (style.position === "fixed")
293
- return true;
294
- if (style.zIndex !== "auto" && (style.position !== "static" || isFlexItem(node)))
295
- return true;
296
- if (+style.opacity < 1)
297
- return true;
298
- if ("transform" in style && style.transform !== "none")
299
- return true;
300
- if ("webkitTransform" in style && style.webkitTransform !== "none")
301
- return true;
302
- if ("mixBlendMode" in style && style.mixBlendMode !== "normal")
303
- return true;
304
- if ("filter" in style && style.filter !== "none")
305
- return true;
306
- if ("webkitFilter" in style && style.webkitFilter !== "none")
307
- return true;
308
- if ("isolation" in style && style.isolation === "isolate")
309
- return true;
310
- if (props.test(style.willChange))
311
- return true;
312
- if (style.webkitOverflowScrolling === "touch")
313
- return true;
314
- return false;
315
- }
316
- function findStackingContext(nodes) {
317
- let i = nodes.length;
318
- while (i--) {
319
- const node = nodes[i];
320
- assert(node);
321
- if (createsStackingContext(node))
322
- return node;
323
- }
324
- return null;
325
- }
326
- function getZIndex(node) {
327
- return node && Number(getComputedStyle(node).zIndex) || 0;
328
- }
329
- function getAncestors(node) {
330
- const ancestors = [];
331
- while (node) {
332
- ancestors.push(node);
333
- node = getParent(node);
334
- }
335
- return ancestors;
336
- }
337
- function getParent(node) {
338
- return node.parentNode?.host || node.parentNode;
339
- }
340
-
341
- const EXCEEDED_HORIZONTAL_MIN = 1;
342
- const EXCEEDED_HORIZONTAL_MAX = 2;
343
- const EXCEEDED_VERTICAL_MIN = 4;
344
- const EXCEEDED_VERTICAL_MAX = 8;
345
- function getInputType() {
346
- if (typeof matchMedia === "function")
347
- return matchMedia("(pointer:coarse)").matches ? "coarse" : "fine";
348
- }
349
- const isCoarsePointer = getInputType() === "coarse";
350
- const intersectingHandles = [];
351
- let isPointerDown = false;
352
- const ownerDocumentCounts = /* @__PURE__ */ new Map();
353
- const panelConstraintFlags = /* @__PURE__ */ new Map();
354
- const registeredResizeHandlers = /* @__PURE__ */ new Set();
355
- function registerResizeHandle(resizeHandleId, element, direction, hitAreaMargins, setResizeHandlerState) {
356
- const { ownerDocument } = element;
357
- const data = {
358
- direction,
359
- element,
360
- hitAreaMargins,
361
- setResizeHandlerState
362
- };
363
- const count = ownerDocumentCounts.get(ownerDocument) ?? 0;
364
- ownerDocumentCounts.set(ownerDocument, count + 1);
365
- registeredResizeHandlers.add(data);
366
- updateListeners();
367
- return function unregisterResizeHandle() {
368
- panelConstraintFlags.delete(resizeHandleId);
369
- registeredResizeHandlers.delete(data);
370
- const count2 = ownerDocumentCounts.get(ownerDocument) ?? 1;
371
- ownerDocumentCounts.set(ownerDocument, count2 - 1);
372
- updateListeners();
373
- if (count2 === 1)
374
- ownerDocumentCounts.delete(ownerDocument);
375
- };
376
- }
377
- function handlePointerDown(event) {
378
- const { target } = event;
379
- const { x, y } = getResizeEventCoordinates(event);
380
- isPointerDown = true;
381
- recalculateIntersectingHandles({ target, x, y });
382
- updateListeners();
383
- if (intersectingHandles.length > 0) {
384
- updateResizeHandlerStates("down", event);
385
- event.preventDefault();
386
- }
387
- }
388
- function handlePointerMove(event) {
389
- const { x, y } = getResizeEventCoordinates(event);
390
- if (!isPointerDown) {
391
- const { target } = event;
392
- recalculateIntersectingHandles({ target, x, y });
393
- }
394
- updateResizeHandlerStates("move", event);
395
- updateCursor();
396
- if (intersectingHandles.length > 0)
397
- event.preventDefault();
398
- }
399
- function handlePointerUp(event) {
400
- const { target } = event;
401
- const { x, y } = getResizeEventCoordinates(event);
402
- panelConstraintFlags.clear();
403
- isPointerDown = false;
404
- if (intersectingHandles.length > 0)
405
- event.preventDefault();
406
- updateResizeHandlerStates("up", event);
407
- recalculateIntersectingHandles({ target, x, y });
408
- updateCursor();
409
- updateListeners();
410
- }
411
- function recalculateIntersectingHandles({
412
- target,
413
- x,
414
- y
415
- }) {
416
- intersectingHandles.splice(0);
417
- let targetElement = null;
418
- if (target instanceof HTMLElement)
419
- targetElement = target;
420
- registeredResizeHandlers.forEach((data) => {
421
- const { element: dragHandleElement, hitAreaMargins } = data;
422
- const dragHandleRect = dragHandleElement.getBoundingClientRect();
423
- const { bottom, left, right, top } = dragHandleRect;
424
- const margin = isCoarsePointer ? hitAreaMargins.coarse : hitAreaMargins.fine;
425
- const eventIntersects = x >= left - margin && x <= right + margin && y >= top - margin && y <= bottom + margin;
426
- if (eventIntersects) {
427
- if (targetElement !== null && dragHandleElement !== targetElement && !dragHandleElement.contains(targetElement) && !targetElement.contains(dragHandleElement) && compare(targetElement, dragHandleElement) > 0) {
428
- let currentElement = targetElement;
429
- let didIntersect = false;
430
- while (currentElement) {
431
- if (currentElement.contains(dragHandleElement)) {
432
- break;
433
- } else if (intersects(
434
- currentElement.getBoundingClientRect(),
435
- dragHandleRect,
436
- true
437
- )) {
438
- didIntersect = true;
439
- break;
440
- }
441
- currentElement = currentElement.parentElement;
442
- }
443
- if (didIntersect)
444
- return;
445
- }
446
- intersectingHandles.push(data);
447
- }
448
- });
449
- }
450
- function reportConstraintsViolation(resizeHandleId, flag) {
451
- panelConstraintFlags.set(resizeHandleId, flag);
452
- }
453
- function updateCursor() {
454
- let intersectsHorizontal = false;
455
- let intersectsVertical = false;
456
- intersectingHandles.forEach((data) => {
457
- const { direction } = data;
458
- if (direction === "horizontal")
459
- intersectsHorizontal = true;
460
- else
461
- intersectsVertical = true;
462
- });
463
- let constraintFlags = 0;
464
- panelConstraintFlags.forEach((flag) => {
465
- constraintFlags |= flag;
466
- });
467
- if (intersectsHorizontal && intersectsVertical)
468
- setGlobalCursorStyle("intersection", constraintFlags);
469
- else if (intersectsHorizontal)
470
- setGlobalCursorStyle("horizontal", constraintFlags);
471
- else if (intersectsVertical)
472
- setGlobalCursorStyle("vertical", constraintFlags);
473
- else
474
- resetGlobalCursorStyle();
475
- }
476
- function updateListeners() {
477
- ownerDocumentCounts.forEach((_, ownerDocument) => {
478
- const { body } = ownerDocument;
479
- body.removeEventListener("contextmenu", handlePointerUp);
480
- body.removeEventListener("mousedown", handlePointerDown);
481
- body.removeEventListener("mouseleave", handlePointerMove);
482
- body.removeEventListener("mousemove", handlePointerMove);
483
- body.removeEventListener("touchmove", handlePointerMove);
484
- body.removeEventListener("touchstart", handlePointerDown);
485
- });
486
- window.removeEventListener("mouseup", handlePointerUp);
487
- window.removeEventListener("touchcancel", handlePointerUp);
488
- window.removeEventListener("touchend", handlePointerUp);
489
- if (registeredResizeHandlers.size > 0) {
490
- if (isPointerDown) {
491
- if (intersectingHandles.length > 0) {
492
- ownerDocumentCounts.forEach((count, ownerDocument) => {
493
- const { body } = ownerDocument;
494
- if (count > 0) {
495
- body.addEventListener("contextmenu", handlePointerUp);
496
- body.addEventListener("mouseleave", handlePointerMove);
497
- body.addEventListener("mousemove", handlePointerMove);
498
- body.addEventListener("touchmove", handlePointerMove, {
499
- passive: false
500
- });
501
- }
502
- });
503
- }
504
- window.addEventListener("mouseup", handlePointerUp);
505
- window.addEventListener("touchcancel", handlePointerUp);
506
- window.addEventListener("touchend", handlePointerUp);
507
- } else {
508
- ownerDocumentCounts.forEach((count, ownerDocument) => {
509
- const { body } = ownerDocument;
510
- if (count > 0) {
511
- body.addEventListener("mousedown", handlePointerDown);
512
- body.addEventListener("mousemove", handlePointerMove);
513
- body.addEventListener("touchmove", handlePointerMove, {
514
- passive: false
515
- });
516
- body.addEventListener("touchstart", handlePointerDown);
517
- }
518
- });
519
- }
520
- }
521
- }
522
- function updateResizeHandlerStates(action, event) {
523
- registeredResizeHandlers.forEach((data) => {
524
- const { setResizeHandlerState } = data;
525
- const isActive = intersectingHandles.includes(data);
526
- setResizeHandlerState(action, isActive, event);
527
- });
528
- }
529
-
530
- function debounce(callback, durationMs = 10) {
531
- let timeoutId = null;
532
- const callable = (...args) => {
533
- if (timeoutId !== null)
534
- clearTimeout(timeoutId);
535
- timeoutId = setTimeout(() => {
536
- callback(...args);
537
- }, durationMs);
538
- };
539
- return callable;
540
- }
541
-
542
- function determinePivotIndices(groupId, dragHandleId, panelGroupElement) {
543
- const index = getResizeHandleElementIndex(
544
- groupId,
545
- dragHandleId,
546
- panelGroupElement
547
- );
548
- return index != null ? [index, index + 1] : [-1, -1];
549
- }
550
-
551
- const PRECISION = 10;
552
-
553
- function fuzzyCompareNumbers(actual, expected, fractionDigits = PRECISION) {
554
- actual = Number.parseFloat(actual.toFixed(fractionDigits));
555
- expected = Number.parseFloat(expected.toFixed(fractionDigits));
556
- const delta = actual - expected;
557
- if (delta === 0)
558
- return 0;
559
- else
560
- return delta > 0 ? 1 : -1;
561
- }
562
- function fuzzyNumbersEqual(actual, expected, fractionDigits) {
563
- return fuzzyCompareNumbers(actual, expected, fractionDigits) === 0;
564
- }
565
-
566
- function resizePanel({
567
- panelConstraints: panelConstraintsArray,
568
- panelIndex,
569
- size
570
- }) {
571
- const panelConstraints = panelConstraintsArray[panelIndex];
572
- assert(panelConstraints != null);
573
- const { collapsedSize = 0, collapsible, maxSize = 100, minSize = 0 } = panelConstraints;
574
- if (fuzzyCompareNumbers(size, minSize) < 0) {
575
- if (collapsible) {
576
- const halfwayPoint = (collapsedSize + minSize) / 2;
577
- if (fuzzyCompareNumbers(size, halfwayPoint) < 0)
578
- size = collapsedSize;
579
- else
580
- size = minSize;
581
- } else {
582
- size = minSize;
583
- }
584
- }
585
- size = Math.min(maxSize, size);
586
- size = Number.parseFloat(size.toFixed(PRECISION));
587
- return size;
588
- }
589
-
590
- function validatePanelGroupLayout({
591
- layout: prevLayout,
592
- panelConstraints
593
- }) {
594
- const nextLayout = [...prevLayout];
595
- const nextLayoutTotalSize = nextLayout.reduce(
596
- (accumulated, current) => accumulated + current,
597
- 0
598
- );
599
- if (nextLayout.length !== panelConstraints.length) {
600
- throw new Error(
601
- `Invalid ${panelConstraints.length} panel layout: ${nextLayout.map((size) => `${size}%`).join(", ")}`
602
- );
603
- } else if (!fuzzyNumbersEqual(nextLayoutTotalSize, 100)) {
604
- {
605
- console.warn(
606
- `WARNING: Invalid layout total size: ${nextLayout.map((size) => `${size}%`).join(", ")}. Layout normalization will be applied.`
607
- );
608
- }
609
- for (let index = 0; index < panelConstraints.length; index++) {
610
- const unsafeSize = nextLayout[index];
611
- assert(unsafeSize != null);
612
- const safeSize = 100 / nextLayoutTotalSize * unsafeSize;
613
- nextLayout[index] = safeSize;
614
- }
615
- }
616
- let remainingSize = 0;
617
- for (let index = 0; index < panelConstraints.length; index++) {
618
- const unsafeSize = nextLayout[index];
619
- assert(unsafeSize != null);
620
- const safeSize = resizePanel({
621
- panelConstraints,
622
- panelIndex: index,
623
- size: unsafeSize
624
- });
625
- if (unsafeSize !== safeSize) {
626
- remainingSize += unsafeSize - safeSize;
627
- nextLayout[index] = safeSize;
628
- }
629
- }
630
- if (!fuzzyNumbersEqual(remainingSize, 0)) {
631
- for (let index = 0; index < panelConstraints.length; index++) {
632
- const prevSize = nextLayout[index];
633
- assert(prevSize != null);
634
- const unsafeSize = prevSize + remainingSize;
635
- const safeSize = resizePanel({
636
- panelConstraints,
637
- panelIndex: index,
638
- size: unsafeSize
639
- });
640
- if (prevSize !== safeSize) {
641
- remainingSize -= safeSize - prevSize;
642
- nextLayout[index] = safeSize;
643
- if (fuzzyNumbersEqual(remainingSize, 0))
644
- break;
645
- }
646
- }
647
- }
648
- return nextLayout;
649
- }
650
-
651
- function callPanelCallbacks(panelsArray, layout, panelIdToLastNotifiedSizeMap) {
652
- layout.forEach((size, index) => {
653
- const panelData = panelsArray[index];
654
- assert(panelData);
655
- const { callbacks, constraints, id: panelId } = panelData;
656
- const { collapsedSize = 0, collapsible } = constraints;
657
- const lastNotifiedSize = panelIdToLastNotifiedSizeMap[panelId];
658
- if (lastNotifiedSize == null || size !== lastNotifiedSize) {
659
- panelIdToLastNotifiedSizeMap[panelId] = size;
660
- const { onCollapse, onExpand, onResize } = callbacks;
661
- if (onResize)
662
- onResize(size, lastNotifiedSize);
663
- if (collapsible && (onCollapse || onExpand)) {
664
- if (onExpand && (lastNotifiedSize == null || lastNotifiedSize === collapsedSize) && size !== collapsedSize)
665
- onExpand();
666
- if (onCollapse && (lastNotifiedSize == null || lastNotifiedSize !== collapsedSize) && size === collapsedSize)
667
- onCollapse();
668
- }
669
- }
670
- });
671
- }
672
-
673
- function compareLayouts(a, b) {
674
- if (a.length !== b.length) {
675
- return false;
676
- } else {
677
- for (let index = 0; index < a.length; index++) {
678
- if (a[index] !== b[index])
679
- return false;
680
- }
681
- }
682
- return true;
683
- }
684
- function adjustLayoutByDelta({
685
- delta,
686
- layout: prevLayout,
687
- panelConstraints: panelConstraintsArray,
688
- pivotIndices,
689
- trigger
690
- }) {
691
- if (fuzzyNumbersEqual(delta, 0))
692
- return prevLayout;
693
- const nextLayout = [...prevLayout];
694
- const [firstPivotIndex, secondPivotIndex] = pivotIndices;
695
- assert(firstPivotIndex != null);
696
- assert(secondPivotIndex != null);
697
- let deltaApplied = 0;
698
- {
699
- if (trigger === "keyboard") {
700
- {
701
- const index = delta < 0 ? secondPivotIndex : firstPivotIndex;
702
- const panelConstraints = panelConstraintsArray[index];
703
- assert(panelConstraints);
704
- if (panelConstraints.collapsible) {
705
- const prevSize = prevLayout[index];
706
- assert(prevSize != null);
707
- const panelConstraints2 = panelConstraintsArray[index];
708
- assert(panelConstraints2);
709
- const { collapsedSize = 0, minSize = 0 } = panelConstraints2;
710
- if (fuzzyNumbersEqual(prevSize, collapsedSize)) {
711
- const localDelta = minSize - prevSize;
712
- if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0)
713
- delta = delta < 0 ? 0 - localDelta : localDelta;
714
- }
715
- }
716
- }
717
- {
718
- const index = delta < 0 ? firstPivotIndex : secondPivotIndex;
719
- const panelConstraints = panelConstraintsArray[index];
720
- assert(panelConstraints);
721
- const { collapsible } = panelConstraints;
722
- if (collapsible) {
723
- const prevSize = prevLayout[index];
724
- assert(prevSize != null);
725
- const panelConstraints2 = panelConstraintsArray[index];
726
- assert(panelConstraints2);
727
- const { collapsedSize = 0, minSize = 0 } = panelConstraints2;
728
- if (fuzzyNumbersEqual(prevSize, minSize)) {
729
- const localDelta = prevSize - collapsedSize;
730
- if (fuzzyCompareNumbers(localDelta, Math.abs(delta)) > 0)
731
- delta = delta < 0 ? 0 - localDelta : localDelta;
732
- }
733
- }
734
- }
735
- }
736
- }
737
- {
738
- const increment = delta < 0 ? 1 : -1;
739
- let index = delta < 0 ? secondPivotIndex : firstPivotIndex;
740
- let maxAvailableDelta = 0;
741
- while (true) {
742
- const prevSize = prevLayout[index];
743
- assert(prevSize != null);
744
- const maxSafeSize = resizePanel({
745
- panelConstraints: panelConstraintsArray,
746
- panelIndex: index,
747
- size: 100
748
- });
749
- const delta2 = maxSafeSize - prevSize;
750
- maxAvailableDelta += delta2;
751
- index += increment;
752
- if (index < 0 || index >= panelConstraintsArray.length)
753
- break;
754
- }
755
- const minAbsDelta = Math.min(Math.abs(delta), Math.abs(maxAvailableDelta));
756
- delta = delta < 0 ? 0 - minAbsDelta : minAbsDelta;
757
- }
758
- {
759
- const pivotIndex = delta < 0 ? firstPivotIndex : secondPivotIndex;
760
- let index = pivotIndex;
761
- while (index >= 0 && index < panelConstraintsArray.length) {
762
- const deltaRemaining = Math.abs(delta) - Math.abs(deltaApplied);
763
- const prevSize = prevLayout[index];
764
- assert(prevSize != null);
765
- const unsafeSize = prevSize - deltaRemaining;
766
- const safeSize = resizePanel({
767
- panelConstraints: panelConstraintsArray,
768
- panelIndex: index,
769
- size: unsafeSize
770
- });
771
- if (!fuzzyNumbersEqual(prevSize, safeSize)) {
772
- deltaApplied += prevSize - safeSize;
773
- nextLayout[index] = safeSize;
774
- if (deltaApplied.toPrecision(3).localeCompare(Math.abs(delta).toPrecision(3), void 0, {
775
- numeric: true
776
- }) >= 0)
777
- break;
778
- }
779
- if (delta < 0)
780
- index--;
781
- else
782
- index++;
783
- }
784
- }
785
- if (fuzzyNumbersEqual(deltaApplied, 0)) {
786
- return prevLayout;
787
- }
788
- {
789
- const pivotIndex = delta < 0 ? secondPivotIndex : firstPivotIndex;
790
- const prevSize = prevLayout[pivotIndex];
791
- assert(prevSize != null);
792
- const unsafeSize = prevSize + deltaApplied;
793
- const safeSize = resizePanel({
794
- panelConstraints: panelConstraintsArray,
795
- panelIndex: pivotIndex,
796
- size: unsafeSize
797
- });
798
- nextLayout[pivotIndex] = safeSize;
799
- if (!fuzzyNumbersEqual(safeSize, unsafeSize)) {
800
- let deltaRemaining = unsafeSize - safeSize;
801
- const pivotIndex2 = delta < 0 ? secondPivotIndex : firstPivotIndex;
802
- let index = pivotIndex2;
803
- while (index >= 0 && index < panelConstraintsArray.length) {
804
- const prevSize2 = nextLayout[index];
805
- assert(prevSize2 != null);
806
- const unsafeSize2 = prevSize2 + deltaRemaining;
807
- const safeSize2 = resizePanel({
808
- panelConstraints: panelConstraintsArray,
809
- panelIndex: index,
810
- size: unsafeSize2
811
- });
812
- if (!fuzzyNumbersEqual(prevSize2, safeSize2)) {
813
- deltaRemaining -= safeSize2 - prevSize2;
814
- nextLayout[index] = safeSize2;
815
- }
816
- if (fuzzyNumbersEqual(deltaRemaining, 0))
817
- break;
818
- if (delta > 0)
819
- index--;
820
- else
821
- index++;
822
- }
823
- }
824
- }
825
- const totalSize = nextLayout.reduce((total, size) => size + total, 0);
826
- if (!fuzzyNumbersEqual(totalSize, 100))
827
- return prevLayout;
828
- return nextLayout;
829
- }
830
-
831
- function calculateDragOffsetPercentage(event, dragHandleId, direction, initialDragState, panelGroupElement) {
832
- const isHorizontal = direction === "horizontal";
833
- const handleElement = getResizeHandleElement(dragHandleId, panelGroupElement);
834
- assert(handleElement);
835
- const groupId = handleElement.getAttribute("data-panel-group-id");
836
- assert(groupId);
837
- const { initialCursorPosition } = initialDragState;
838
- const cursorPosition = getResizeEventCursorPosition(direction, event);
839
- const groupElement = getPanelGroupElement(groupId, panelGroupElement);
840
- assert(groupElement);
841
- const groupRect = groupElement.getBoundingClientRect();
842
- const groupSizeInPixels = isHorizontal ? groupRect.width : groupRect.height;
843
- const offsetPixels = cursorPosition - initialCursorPosition;
844
- const offsetPercentage = offsetPixels / groupSizeInPixels * 100;
845
- return offsetPercentage;
846
- }
847
- function calculateDeltaPercentage(event, dragHandleId, direction, initialDragState, keyboardResizeBy, panelGroupElement) {
848
- if (isKeyDown(event)) {
849
- const isHorizontal = direction === "horizontal";
850
- let delta = 0;
851
- if (event.shiftKey)
852
- delta = 100;
853
- else
854
- delta = keyboardResizeBy ?? 10;
855
- let movement = 0;
856
- switch (event.key) {
857
- case "ArrowDown":
858
- movement = isHorizontal ? 0 : delta;
859
- break;
860
- case "ArrowLeft":
861
- movement = isHorizontal ? -delta : 0;
862
- break;
863
- case "ArrowRight":
864
- movement = isHorizontal ? delta : 0;
865
- break;
866
- case "ArrowUp":
867
- movement = isHorizontal ? 0 : -delta;
868
- break;
869
- case "End":
870
- movement = 100;
871
- break;
872
- case "Home":
873
- movement = -100;
874
- break;
875
- }
876
- return movement;
877
- } else {
878
- if (initialDragState == null)
879
- return 0;
880
- return calculateDragOffsetPercentage(
881
- event,
882
- dragHandleId,
883
- direction,
884
- initialDragState,
885
- panelGroupElement
886
- );
887
- }
888
- }
889
- function calculateAriaValues({
890
- layout,
891
- panelsArray,
892
- pivotIndices
893
- }) {
894
- let currentMinSize = 0;
895
- let currentMaxSize = 100;
896
- let totalMinSize = 0;
897
- let totalMaxSize = 0;
898
- const firstIndex = pivotIndices[0];
899
- assert(firstIndex != null);
900
- panelsArray.forEach((panelData, index) => {
901
- const { constraints } = panelData;
902
- const { maxSize = 100, minSize = 0 } = constraints;
903
- if (index === firstIndex) {
904
- currentMinSize = minSize;
905
- currentMaxSize = maxSize;
906
- } else {
907
- totalMinSize += minSize;
908
- totalMaxSize += maxSize;
909
- }
910
- });
911
- const valueMax = Math.min(currentMaxSize, 100 - totalMinSize);
912
- const valueMin = Math.max(currentMinSize, 100 - totalMaxSize);
913
- const valueNow = layout[firstIndex];
914
- return {
915
- valueMax,
916
- valueMin,
917
- valueNow
918
- };
919
- }
920
- function calculateUnsafeDefaultLayout({
921
- panelDataArray
922
- }) {
923
- const layout = Array(panelDataArray.length);
924
- const panelConstraintsArray = panelDataArray.map(
925
- (panelData) => panelData.constraints
926
- );
927
- let numPanelsWithSizes = 0;
928
- let remainingSize = 100;
929
- for (let index = 0; index < panelDataArray.length; index++) {
930
- const panelConstraints = panelConstraintsArray[index];
931
- assert(panelConstraints);
932
- const { defaultSize } = panelConstraints;
933
- if (defaultSize != null) {
934
- numPanelsWithSizes++;
935
- layout[index] = defaultSize;
936
- remainingSize -= defaultSize;
937
- }
938
- }
939
- for (let index = 0; index < panelDataArray.length; index++) {
940
- const panelConstraints = panelConstraintsArray[index];
941
- assert(panelConstraints);
942
- const { defaultSize } = panelConstraints;
943
- if (defaultSize != null)
944
- continue;
945
- const numRemainingPanels = panelDataArray.length - numPanelsWithSizes;
946
- const size = remainingSize / numRemainingPanels;
947
- numPanelsWithSizes++;
948
- layout[index] = size;
949
- remainingSize -= size;
950
- }
951
- return layout;
952
- }
953
-
954
- function initializeDefaultStorage(storageObject) {
955
- try {
956
- if (typeof localStorage !== "undefined") {
957
- storageObject.getItem = (name) => {
958
- return localStorage.getItem(name);
959
- };
960
- storageObject.setItem = (name, value) => {
961
- localStorage.setItem(name, value);
962
- };
963
- } else {
964
- throw new TypeError("localStorage not supported in this environment");
965
- }
966
- } catch (error) {
967
- console.error(error);
968
- storageObject.getItem = () => null;
969
- storageObject.setItem = () => {
970
- };
971
- }
972
- }
973
- function getPanelGroupKey(autoSaveId) {
974
- return `destyler:${autoSaveId}`;
975
- }
976
- function getPanelKey(panels) {
977
- return panels.map((panel) => {
978
- const { constraints, id, idIsFromProps, order } = panel;
979
- if (idIsFromProps) {
980
- return id;
981
- } else {
982
- return order ? `${order}:${JSON.stringify(constraints)}` : JSON.stringify(constraints);
983
- }
984
- }).sort((a, b) => a.localeCompare(b)).join(",");
985
- }
986
- function loadSerializedPanelGroupState(autoSaveId, storage) {
987
- try {
988
- const panelGroupKey = getPanelGroupKey(autoSaveId);
989
- const serialized = storage.getItem(panelGroupKey);
990
- if (serialized) {
991
- const parsed = JSON.parse(serialized);
992
- if (typeof parsed === "object" && parsed != null)
993
- return parsed;
994
- }
995
- } catch (error) {
996
- }
997
- return null;
998
- }
999
- function loadPanelGroupState(autoSaveId, panels, storage) {
1000
- const state = loadSerializedPanelGroupState(autoSaveId, storage) ?? {};
1001
- const panelKey = getPanelKey(panels);
1002
- return state[panelKey] ?? null;
1003
- }
1004
- function savePanelGroupState(autoSaveId, panels, panelSizesBeforeCollapse, sizes, storage) {
1005
- const panelGroupKey = getPanelGroupKey(autoSaveId);
1006
- const panelKey = getPanelKey(panels);
1007
- const state = loadSerializedPanelGroupState(autoSaveId, storage) ?? {};
1008
- state[panelKey] = {
1009
- expandToSizes: Object.fromEntries(panelSizesBeforeCollapse.entries()),
1010
- layout: sizes
1011
- };
1012
- try {
1013
- storage.setItem(panelGroupKey, JSON.stringify(state));
1014
- } catch (error) {
1015
- console.error(error);
1016
- }
1017
- }
1018
-
1019
- function useWindowSplitterPanelGroupBehavior({
1020
- eagerValuesRef,
1021
- groupId,
1022
- layout,
1023
- panelDataArray,
1024
- panelGroupElement,
1025
- setLayout
1026
- }) {
1027
- watchEffect((onCleanup) => {
1028
- const _panelGroupElement = panelGroupElement.value;
1029
- if (!_panelGroupElement)
1030
- return;
1031
- const resizeHandleElements = getResizeHandleElementsForGroup(
1032
- groupId,
1033
- _panelGroupElement
1034
- );
1035
- for (let index = 0; index < panelDataArray.length - 1; index++) {
1036
- const { valueMax, valueMin, valueNow } = calculateAriaValues({
1037
- layout: layout.value,
1038
- panelsArray: panelDataArray,
1039
- pivotIndices: [index, index + 1]
1040
- });
1041
- const resizeHandleElement = resizeHandleElements[index];
1042
- if (resizeHandleElement == null) {
1043
- if (import.meta.env.DEV)
1044
- console.warn(`WARNING: Missing resize handle for PanelGroup "${groupId}"`);
1045
- } else {
1046
- const panelData = panelDataArray[index];
1047
- assert(panelData);
1048
- resizeHandleElement.setAttribute("aria-controls", panelData.id);
1049
- resizeHandleElement.setAttribute(
1050
- "aria-valuemax",
1051
- `${Math.round(valueMax)}`
1052
- );
1053
- resizeHandleElement.setAttribute(
1054
- "aria-valuemin",
1055
- `${Math.round(valueMin)}`
1056
- );
1057
- resizeHandleElement.setAttribute(
1058
- "aria-valuenow",
1059
- valueNow != null ? `${Math.round(valueNow)}` : ""
1060
- );
1061
- }
1062
- }
1063
- onCleanup(() => {
1064
- resizeHandleElements.forEach((resizeHandleElement) => {
1065
- resizeHandleElement.removeAttribute("aria-controls");
1066
- resizeHandleElement.removeAttribute("aria-valuemax");
1067
- resizeHandleElement.removeAttribute("aria-valuemin");
1068
- resizeHandleElement.removeAttribute("aria-valuenow");
1069
- });
1070
- });
1071
- });
1072
- watchEffect((onCleanup) => {
1073
- const _panelGroupElement = panelGroupElement.value;
1074
- if (!_panelGroupElement)
1075
- return;
1076
- const eagerValues = eagerValuesRef.value;
1077
- assert(eagerValues);
1078
- const { panelDataArray: panelDataArray2 } = eagerValues;
1079
- const groupElement = getPanelGroupElement(groupId, _panelGroupElement);
1080
- assert(groupElement != null, `No group found for id "${groupId}"`);
1081
- const handles = getResizeHandleElementsForGroup(groupId, _panelGroupElement);
1082
- assert(handles);
1083
- const cleanupFunctions = handles.map((handle) => {
1084
- const handleId = handle.getAttribute("data-panel-resize-handle-id");
1085
- assert(handleId);
1086
- const [idBefore, idAfter] = getResizeHandlePanelIds(
1087
- groupId,
1088
- handleId,
1089
- panelDataArray2,
1090
- _panelGroupElement
1091
- );
1092
- if (idBefore == null || idAfter == null)
1093
- return () => {
1094
- };
1095
- const onKeyDown = (event) => {
1096
- if (event.defaultPrevented)
1097
- return;
1098
- switch (event.key) {
1099
- case "Enter": {
1100
- event.preventDefault();
1101
- const index = panelDataArray2.findIndex(
1102
- (panelData) => panelData.id === idBefore
1103
- );
1104
- if (index >= 0) {
1105
- const panelData = panelDataArray2[index];
1106
- assert(panelData);
1107
- const size = layout.value[index];
1108
- const {
1109
- collapsedSize = 0,
1110
- collapsible,
1111
- minSize = 0
1112
- } = panelData.constraints;
1113
- if (size != null && collapsible) {
1114
- const nextLayout = adjustLayoutByDelta({
1115
- delta: fuzzyNumbersEqual(size, collapsedSize) ? minSize - collapsedSize : collapsedSize - size,
1116
- layout: layout.value,
1117
- panelConstraints: panelDataArray2.map(
1118
- (panelData2) => panelData2.constraints
1119
- ),
1120
- pivotIndices: determinePivotIndices(
1121
- groupId,
1122
- handleId,
1123
- _panelGroupElement
1124
- ),
1125
- trigger: "keyboard"
1126
- });
1127
- if (layout.value !== nextLayout)
1128
- setLayout(nextLayout);
1129
- }
1130
- }
1131
- break;
1132
- }
1133
- }
1134
- };
1135
- handle.addEventListener("keydown", onKeyDown);
1136
- return () => {
1137
- handle.removeEventListener("keydown", onKeyDown);
1138
- };
1139
- });
1140
- onCleanup(() => {
1141
- cleanupFunctions.forEach((cleanupFunction) => cleanupFunction());
1142
- });
1143
- });
1144
- }
1145
-
1146
- const defaultStorage = {
1147
- getItem: (name) => {
1148
- initializeDefaultStorage(defaultStorage);
1149
- return defaultStorage.getItem(name);
1150
- },
1151
- setItem: (name, value) => {
1152
- initializeDefaultStorage(defaultStorage);
1153
- defaultStorage.setItem(name, value);
1154
- }
1155
- };
1156
- const destylerSplitterGroupProps = {
1157
- as: {
1158
- type: [String, Object],
1159
- required: false,
1160
- default: "div"
1161
- },
1162
- asChild: {
1163
- type: Boolean,
1164
- required: false,
1165
- default: false
1166
- },
1167
- id: {
1168
- type: String,
1169
- required: false
1170
- },
1171
- autoSaveId: {
1172
- type: String,
1173
- required: false,
1174
- default: null
1175
- },
1176
- direction: {
1177
- type: String,
1178
- required: true
1179
- },
1180
- keyboardResizeBy: {
1181
- type: Number,
1182
- required: false,
1183
- default: 10
1184
- },
1185
- storage: {
1186
- type: Object,
1187
- required: false,
1188
- default: () => defaultStorage
1189
- }
1190
- };
1191
- const [injectPanelGroupContext, providePanelGroupContext] = createContext("PanelGroup");
1192
- const DestylerSplitterGroup = defineComponent({
1193
- name: "DestylerSplitterGroup",
1194
- props: destylerSplitterGroupProps,
1195
- emits: ["layout"],
1196
- setup(props, { emit }) {
1197
- const LOCAL_STORAGE_DEBOUNCE_INTERVAL = 100;
1198
- const debounceMap = {};
1199
- const groupId = useUniqueId(props.id);
1200
- const dir = useDirection();
1201
- const { forwardRef, currentElement: panelGroupElementRef } = useForwardExpose();
1202
- const dragState = ref(null);
1203
- const layout = ref([]);
1204
- const panelIdToLastNotifiedSizeMapRef = ref({});
1205
- const panelSizeBeforeCollapseRef = ref(/* @__PURE__ */ new Map());
1206
- const prevDeltaRef = ref(0);
1207
- const committedValuesRef = computed(() => ({
1208
- autoSaveId: props.autoSaveId,
1209
- direction: props.direction,
1210
- dragState: dragState.value,
1211
- id: groupId,
1212
- keyboardResizeBy: props.keyboardResizeBy,
1213
- storage: props.storage
1214
- }));
1215
- const eagerValuesRef = ref({
1216
- layout: layout.value,
1217
- panelDataArray: [],
1218
- panelDataArrayChanged: false
1219
- });
1220
- const setLayout = (val) => layout.value = val;
1221
- useWindowSplitterPanelGroupBehavior({
1222
- eagerValuesRef,
1223
- groupId,
1224
- layout,
1225
- panelDataArray: eagerValuesRef.value.panelDataArray,
1226
- setLayout,
1227
- panelGroupElement: panelGroupElementRef
1228
- });
1229
- watchEffect(() => {
1230
- const { panelDataArray } = eagerValuesRef.value;
1231
- const { autoSaveId } = props;
1232
- if (autoSaveId) {
1233
- if (layout.value.length === 0 || layout.value.length !== panelDataArray.length)
1234
- return;
1235
- let debouncedSave = debounceMap[autoSaveId];
1236
- if (!debouncedSave) {
1237
- debouncedSave = debounce(
1238
- savePanelGroupState,
1239
- LOCAL_STORAGE_DEBOUNCE_INTERVAL
1240
- );
1241
- debounceMap[autoSaveId] = debouncedSave;
1242
- }
1243
- const clonedPanelDataArray = [...panelDataArray];
1244
- const clonedPanelSizesBeforeCollapse = new Map(
1245
- panelSizeBeforeCollapseRef.value
1246
- );
1247
- debouncedSave(
1248
- autoSaveId,
1249
- clonedPanelDataArray,
1250
- clonedPanelSizesBeforeCollapse,
1251
- layout.value,
1252
- props.storage
1253
- );
1254
- }
1255
- });
1256
- function getPanelStyle(panelData, defaultSize) {
1257
- const { panelDataArray } = eagerValuesRef.value;
1258
- const panelIndex = findPanelDataIndex(panelDataArray, panelData);
1259
- return computePanelFlexBoxStyle({
1260
- defaultSize,
1261
- dragState: dragState.value,
1262
- layout: layout.value,
1263
- panelData: panelDataArray,
1264
- panelIndex
1265
- });
1266
- }
1267
- function registerPanel(panelData) {
1268
- const { panelDataArray } = eagerValuesRef.value;
1269
- panelDataArray.push(panelData);
1270
- panelDataArray.sort((panelA, panelB) => {
1271
- const orderA = panelA.order;
1272
- const orderB = panelB.order;
1273
- if (orderA == null && orderB == null)
1274
- return 0;
1275
- else if (orderA == null)
1276
- return -1;
1277
- else if (orderB == null)
1278
- return 1;
1279
- else
1280
- return orderA - orderB;
1281
- });
1282
- eagerValuesRef.value.panelDataArrayChanged = true;
1283
- }
1284
- watch(() => eagerValuesRef.value.panelDataArrayChanged, () => {
1285
- if (eagerValuesRef.value.panelDataArrayChanged) {
1286
- eagerValuesRef.value.panelDataArrayChanged = false;
1287
- const { autoSaveId, storage } = committedValuesRef.value;
1288
- const { layout: prevLayout, panelDataArray } = eagerValuesRef.value;
1289
- let unsafeLayout = null;
1290
- if (autoSaveId) {
1291
- const state = loadPanelGroupState(autoSaveId, panelDataArray, storage);
1292
- if (state) {
1293
- panelSizeBeforeCollapseRef.value = new Map(
1294
- Object.entries(state.expandToSizes)
1295
- );
1296
- unsafeLayout = state.layout;
1297
- }
1298
- }
1299
- if (unsafeLayout === null) {
1300
- unsafeLayout = calculateUnsafeDefaultLayout({
1301
- panelDataArray
1302
- });
1303
- }
1304
- const nextLayout = validatePanelGroupLayout({
1305
- layout: unsafeLayout,
1306
- panelConstraints: panelDataArray.map(
1307
- (panelData) => panelData.constraints
1308
- )
1309
- });
1310
- if (!areEqual(prevLayout, nextLayout)) {
1311
- setLayout(nextLayout);
1312
- eagerValuesRef.value.layout = nextLayout;
1313
- emit("layout", nextLayout);
1314
- callPanelCallbacks(
1315
- panelDataArray,
1316
- nextLayout,
1317
- panelIdToLastNotifiedSizeMapRef.value
1318
- );
1319
- }
1320
- }
1321
- });
1322
- function registerResizeHandle(dragHandleId) {
1323
- return function resizeHandler(event) {
1324
- event.preventDefault();
1325
- const panelGroupElement = panelGroupElementRef.value;
1326
- if (!panelGroupElement)
1327
- return () => null;
1328
- const { direction, dragState: dragState2, id: groupId2, keyboardResizeBy } = committedValuesRef.value;
1329
- const { layout: prevLayout, panelDataArray } = eagerValuesRef.value;
1330
- const { initialLayout } = dragState2 ?? {};
1331
- const pivotIndices = determinePivotIndices(
1332
- groupId2,
1333
- dragHandleId,
1334
- panelGroupElement
1335
- );
1336
- let delta = calculateDeltaPercentage(
1337
- event,
1338
- dragHandleId,
1339
- direction,
1340
- dragState2,
1341
- keyboardResizeBy,
1342
- panelGroupElement
1343
- );
1344
- if (delta === 0)
1345
- return;
1346
- const isHorizontal = direction === "horizontal";
1347
- if (dir.value === "rtl" && isHorizontal)
1348
- delta = -delta;
1349
- const panelConstraints = panelDataArray.map((panelData) => panelData.constraints);
1350
- const nextLayout = adjustLayoutByDelta({
1351
- delta,
1352
- layout: initialLayout ?? prevLayout,
1353
- panelConstraints,
1354
- pivotIndices,
1355
- trigger: isKeyDown(event) ? "keyboard" : "mouse-or-touch"
1356
- });
1357
- const layoutChanged = !compareLayouts(prevLayout, nextLayout);
1358
- if (isMouseEvent(event) || isTouchEvent(event)) {
1359
- if (prevDeltaRef.value !== delta) {
1360
- prevDeltaRef.value = delta;
1361
- if (!layoutChanged) {
1362
- if (isHorizontal) {
1363
- reportConstraintsViolation(
1364
- dragHandleId,
1365
- delta < 0 ? EXCEEDED_HORIZONTAL_MIN : EXCEEDED_HORIZONTAL_MAX
1366
- );
1367
- } else {
1368
- reportConstraintsViolation(
1369
- dragHandleId,
1370
- delta < 0 ? EXCEEDED_VERTICAL_MIN : EXCEEDED_VERTICAL_MAX
1371
- );
1372
- }
1373
- } else {
1374
- reportConstraintsViolation(dragHandleId, 0);
1375
- }
1376
- }
1377
- }
1378
- if (layoutChanged) {
1379
- setLayout(nextLayout);
1380
- eagerValuesRef.value.layout = nextLayout;
1381
- emit("layout", nextLayout);
1382
- callPanelCallbacks(
1383
- panelDataArray,
1384
- nextLayout,
1385
- panelIdToLastNotifiedSizeMapRef.value
1386
- );
1387
- }
1388
- };
1389
- }
1390
- function resizePanel(panelData, unsafePanelSize) {
1391
- const { layout: prevLayout, panelDataArray } = eagerValuesRef.value;
1392
- const panelConstraintsArray = panelDataArray.map((panelData2) => panelData2.constraints);
1393
- const { panelSize, pivotIndices } = panelDataHelper(
1394
- panelDataArray,
1395
- panelData,
1396
- prevLayout
1397
- );
1398
- assert(panelSize != null);
1399
- const isLastPanel = findPanelDataIndex(panelDataArray, panelData) === panelDataArray.length - 1;
1400
- const delta = isLastPanel ? panelSize - unsafePanelSize : unsafePanelSize - panelSize;
1401
- const nextLayout = adjustLayoutByDelta({
1402
- delta,
1403
- layout: prevLayout,
1404
- panelConstraints: panelConstraintsArray,
1405
- pivotIndices,
1406
- trigger: "imperative-api"
1407
- });
1408
- if (!compareLayouts(prevLayout, nextLayout)) {
1409
- setLayout(nextLayout);
1410
- eagerValuesRef.value.layout = nextLayout;
1411
- emit("layout", nextLayout);
1412
- callPanelCallbacks(
1413
- panelDataArray,
1414
- nextLayout,
1415
- panelIdToLastNotifiedSizeMapRef.value
1416
- );
1417
- }
1418
- }
1419
- function reevaluatePanelConstraints(panelData, prevConstraints) {
1420
- const { layout: layout2, panelDataArray } = eagerValuesRef.value;
1421
- const {
1422
- collapsedSize: prevCollapsedSize = 0,
1423
- collapsible: prevCollapsible
1424
- } = prevConstraints;
1425
- const {
1426
- collapsedSize: nextCollapsedSize = 0,
1427
- collapsible: nextCollapsible,
1428
- maxSize: nextMaxSize = 100,
1429
- minSize: nextMinSize = 0
1430
- } = panelData.constraints;
1431
- const { panelSize: prevPanelSize } = panelDataHelper(
1432
- panelDataArray,
1433
- panelData,
1434
- layout2
1435
- );
1436
- if (prevPanelSize === null) {
1437
- return;
1438
- }
1439
- if (prevCollapsible && nextCollapsible && prevPanelSize === prevCollapsedSize) {
1440
- if (prevCollapsedSize !== nextCollapsedSize) {
1441
- resizePanel(panelData, nextCollapsedSize);
1442
- }
1443
- } else if (prevPanelSize < nextMinSize) {
1444
- resizePanel(panelData, nextMinSize);
1445
- } else if (prevPanelSize > nextMaxSize) {
1446
- resizePanel(panelData, nextMaxSize);
1447
- }
1448
- }
1449
- function startDragging(dragHandleId, event) {
1450
- const { direction } = committedValuesRef.value;
1451
- const { layout: layout2 } = eagerValuesRef.value;
1452
- if (!panelGroupElementRef.value)
1453
- return;
1454
- const handleElement = getResizeHandleElement(
1455
- dragHandleId,
1456
- panelGroupElementRef.value
1457
- );
1458
- assert(handleElement);
1459
- const initialCursorPosition = getResizeEventCursorPosition(
1460
- direction,
1461
- event
1462
- );
1463
- dragState.value = {
1464
- dragHandleId,
1465
- dragHandleRect: handleElement.getBoundingClientRect(),
1466
- initialCursorPosition,
1467
- initialLayout: layout2
1468
- };
1469
- }
1470
- function stopDragging() {
1471
- dragState.value = null;
1472
- }
1473
- function unregisterPanel(panelData) {
1474
- const { panelDataArray } = eagerValuesRef.value;
1475
- const index = findPanelDataIndex(panelDataArray, panelData);
1476
- if (index >= 0) {
1477
- panelDataArray.splice(index, 1);
1478
- delete panelIdToLastNotifiedSizeMapRef.value[panelData.id];
1479
- eagerValuesRef.value.panelDataArrayChanged = true;
1480
- }
1481
- }
1482
- providePanelGroupContext({
1483
- direction: props.direction,
1484
- dragState: dragState.value,
1485
- getPanelStyle,
1486
- groupId,
1487
- reevaluatePanelConstraints,
1488
- registerPanel,
1489
- registerResizeHandle,
1490
- resizePanel,
1491
- startDragging,
1492
- stopDragging,
1493
- unregisterPanel,
1494
- panelGroupElement: panelGroupElementRef
1495
- });
1496
- function findPanelDataIndex(panelDataArray, panelData) {
1497
- return panelDataArray.findIndex(
1498
- (prevPanelData) => prevPanelData === panelData || prevPanelData.id === panelData.id
1499
- );
1500
- }
1501
- function panelDataHelper(panelDataArray, panelData, layout2) {
1502
- const panelIndex = findPanelDataIndex(panelDataArray, panelData);
1503
- const isLastPanel = panelIndex === panelDataArray.length - 1;
1504
- const pivotIndices = isLastPanel ? [panelIndex - 1, panelIndex] : [panelIndex, panelIndex + 1];
1505
- const panelSize = layout2[panelIndex];
1506
- return {
1507
- ...panelData.constraints,
1508
- panelSize,
1509
- pivotIndices
1510
- };
1511
- }
1512
- return {
1513
- forwardRef,
1514
- groupId
1515
- };
1516
- },
1517
- render() {
1518
- return h(DestylerPrimitive, {
1519
- "as": this.$props.as,
1520
- "asChild": this.$props.asChild,
1521
- "ref": (el) => this.forwardRef(el),
1522
- "style": {
1523
- display: "flex",
1524
- flexDirection: this.$props.direction === "horizontal" ? "row" : "column",
1525
- height: "100%",
1526
- overflow: "hidden",
1527
- width: "100%"
1528
- },
1529
- "data-panel-group": "",
1530
- "data-orientation": this.$props.direction,
1531
- "data-panel-group-id": this.groupId
1532
- }, {
1533
- default: () => this.$slots.default?.()
1534
- });
1535
- }
1536
- });
1537
-
1538
- const destylerSplitterResizeHandleProps = {
1539
- as: {
1540
- type: [String, Object],
1541
- required: false,
1542
- default: "div"
1543
- },
1544
- asChild: {
1545
- type: Boolean,
1546
- required: false,
1547
- default: false
1548
- },
1549
- id: {
1550
- type: String,
1551
- required: false
1552
- },
1553
- hitAreaMargins: {
1554
- type: Object,
1555
- required: false
1556
- },
1557
- tabindex: {
1558
- type: Number,
1559
- required: false,
1560
- default: 0
1561
- },
1562
- disabled: {
1563
- type: Boolean,
1564
- required: false
1565
- }
1566
- };
1567
- const DestylerSplitterResizeHandle = defineComponent({
1568
- name: "DestylerSplitterResizeHandle",
1569
- props: destylerSplitterResizeHandleProps,
1570
- emits: ["dragging"],
1571
- setup(props, { emit }) {
1572
- const { forwardRef, currentElement } = useForwardExpose();
1573
- const { disabled } = toRefs(props);
1574
- const panelGroupContext = injectPanelGroupContext();
1575
- if (panelGroupContext === null) {
1576
- throw new Error(
1577
- "DestylerPanelResizeHandle components must be rendered within a PanelGroup container"
1578
- );
1579
- }
1580
- const {
1581
- direction,
1582
- groupId,
1583
- registerResizeHandle: registerResizeHandleWithParentGroup,
1584
- startDragging,
1585
- stopDragging,
1586
- panelGroupElement
1587
- } = panelGroupContext;
1588
- const resizeHandleId = useUniqueId(props.id);
1589
- const state = ref("inactive");
1590
- const isFocused = ref(false);
1591
- const resizeHandler = ref(null);
1592
- watch(disabled, () => {
1593
- if (!isBrowser)
1594
- return;
1595
- if (disabled.value)
1596
- resizeHandler.value = null;
1597
- else
1598
- resizeHandler.value = registerResizeHandleWithParentGroup(resizeHandleId);
1599
- }, { immediate: true });
1600
- watchEffect((onCleanup) => {
1601
- if (disabled.value || resizeHandler.value === null)
1602
- return;
1603
- const element = currentElement.value;
1604
- if (!element)
1605
- return;
1606
- assert(element);
1607
- const setResizeHandlerState = (action, isActive, event) => {
1608
- if (isActive) {
1609
- switch (action) {
1610
- case "down": {
1611
- state.value = "drag";
1612
- startDragging(resizeHandleId, event);
1613
- emit("dragging", true);
1614
- break;
1615
- }
1616
- case "move": {
1617
- if (state.value !== "drag")
1618
- state.value = "hover";
1619
- resizeHandler.value?.(event);
1620
- break;
1621
- }
1622
- case "up": {
1623
- state.value = "hover";
1624
- stopDragging();
1625
- emit("dragging", false);
1626
- break;
1627
- }
1628
- }
1629
- } else {
1630
- state.value = "inactive";
1631
- }
1632
- };
1633
- onCleanup(registerResizeHandle(
1634
- resizeHandleId,
1635
- element,
1636
- direction,
1637
- {
1638
- // Coarse inputs (e.g. finger/touch)
1639
- coarse: props.hitAreaMargins?.coarse ?? 15,
1640
- // Fine inputs (e.g. mouse)
1641
- fine: props.hitAreaMargins?.fine ?? 5
1642
- },
1643
- setResizeHandlerState
1644
- ));
1645
- });
1646
- useWindowSplitterResizeHandlerBehavior({
1647
- disabled,
1648
- resizeHandler,
1649
- handleId: resizeHandleId,
1650
- panelGroupElement
1651
- });
1652
- return {
1653
- resizeHandleId,
1654
- disabled,
1655
- state,
1656
- direction,
1657
- groupId,
1658
- isFocused,
1659
- forwardRef
1660
- };
1661
- },
1662
- render() {
1663
- return withDirectives(h(DestylerPrimitive, {
1664
- "ref": (el) => this.forwardRef(el),
1665
- "style": {
1666
- touchAction: "none",
1667
- userSelect: "none"
1668
- },
1669
- "role": "separator",
1670
- "data-resize-handle": "",
1671
- "tabindex": this.$props.tabindex,
1672
- "data-state": this.state,
1673
- "data-disabled": this.disabled ? "" : void 0,
1674
- "data-orientation": this.direction,
1675
- "data-panel-group-id": this.groupId,
1676
- "data-resize-handle-active": this.state === "drag" ? "pointer" : this.isFocused ? "keyboard" : void 0,
1677
- "data-resize-handle-state": this.state,
1678
- "data-panel-resize-handle-enabled": !this.disabled,
1679
- "data-panel-resize-handle-id": this.resizeHandleId,
1680
- "onBlur": () => {
1681
- this.isFocused = false;
1682
- },
1683
- "onFocus": () => {
1684
- this.isFocused = false;
1685
- }
1686
- }, {
1687
- default: () => this.$slots.default?.()
1688
- }), [
1689
- [BindOnceDirective, { id: this.resizeHandleId }]
1690
- ]);
1691
- }
1692
- });
1693
-
1694
- const destylerSplitterPanelProps = {
1695
- as: {
1696
- type: [String, Object],
1697
- required: false,
1698
- default: "div"
1699
- },
1700
- asChild: {
1701
- type: Boolean,
1702
- required: false,
1703
- default: false
1704
- },
1705
- collapsedSize: {
1706
- type: Number,
1707
- required: false
1708
- },
1709
- collapsible: {
1710
- type: Boolean,
1711
- required: false
1712
- },
1713
- defaultSize: {
1714
- type: Number,
1715
- required: false
1716
- },
1717
- id: {
1718
- type: String,
1719
- required: false
1720
- },
1721
- maxSize: {
1722
- type: Number,
1723
- required: false
1724
- },
1725
- minSize: {
1726
- type: Number,
1727
- required: false
1728
- },
1729
- order: {
1730
- type: Number,
1731
- required: false
1732
- }
1733
- };
1734
- const DestylerSplitterPanel = defineComponent({
1735
- name: "DestylerSplitterPanel",
1736
- props: destylerSplitterPanelProps,
1737
- emits: ["collapse", "expand", "resize"],
1738
- setup(props, { emit }) {
1739
- const panelGroupContext = injectPanelGroupContext();
1740
- if (panelGroupContext === null)
1741
- throw new Error("DestylerSplitterPanel components must be rendered within a SplitterGroup container");
1742
- const { getPanelStyle, groupId, reevaluatePanelConstraints, registerPanel, unregisterPanel } = panelGroupContext;
1743
- const panelId = useUniqueId(props.id);
1744
- const panelDataRef = computed(() => ({
1745
- callbacks: {
1746
- onCollapse: () => emit("collapse"),
1747
- onExpand: () => emit("expand"),
1748
- onResize: (...args) => emit("resize", ...args)
1749
- },
1750
- constraints: {
1751
- collapsedSize: props.collapsedSize,
1752
- collapsible: props.collapsible,
1753
- defaultSize: props.defaultSize,
1754
- maxSize: props.maxSize,
1755
- minSize: props.minSize
1756
- },
1757
- id: panelId,
1758
- idIsFromProps: props.id !== void 0,
1759
- order: props.order
1760
- }));
1761
- watch(() => panelDataRef.value.constraints, (prevConstraints, constraints) => {
1762
- if (prevConstraints.collapsedSize !== constraints.collapsedSize || prevConstraints.collapsible !== constraints.collapsible || prevConstraints.maxSize !== constraints.maxSize || prevConstraints.minSize !== constraints.minSize)
1763
- reevaluatePanelConstraints(panelDataRef.value, prevConstraints);
1764
- }, { deep: true });
1765
- onMounted(() => {
1766
- const panelData = panelDataRef.value;
1767
- registerPanel(panelData);
1768
- onUnmounted(() => {
1769
- unregisterPanel(panelData);
1770
- });
1771
- });
1772
- const style = computed(() => getPanelStyle(panelDataRef.value, props.defaultSize));
1773
- return {
1774
- groupId,
1775
- panelId,
1776
- style
1777
- };
1778
- },
1779
- render() {
1780
- return withDirectives(h(DestylerPrimitive, {
1781
- "as": this.$props.as,
1782
- "asChild": this.$props.asChild,
1783
- "style": this.style,
1784
- "data-panel": "",
1785
- "data-panel-collapsible": this.$props.collapsible || void 0,
1786
- "data-panel-group-id": this.groupId,
1787
- "data-panel-id": this.panelId,
1788
- "data-panel-size": Number.parseFloat(`${this.style.flexGrow}`).toFixed(1)
1789
- }, {
1790
- default: () => this.$slots.default?.()
1791
- }), [
1792
- [BindOnceDirective, { id: this.panelId }]
1793
- ]);
1794
- }
1795
- });
1796
-
1797
- const destylerSplitterRootProps = {
1798
- as: {
1799
- type: [String, Object],
1800
- required: false,
1801
- default: "div"
1802
- },
1803
- asChild: {
1804
- type: Boolean,
1805
- required: false,
1806
- default: false
1807
- }
1808
- };
1809
- const DestylerSplitterRoot = defineComponent({
1810
- name: "DestylerSplitterRoot",
1811
- props: destylerSplitterRootProps,
1812
- setup(_) {
1813
- useForwardExpose();
1814
- },
1815
- render() {
1816
- return h(DestylerPrimitive, {
1817
- as: this.$props.as,
1818
- asChild: this.$props.asChild
1819
- }, {
1820
- default: () => this.$slots.default?.()
1821
- });
1822
- }
1823
- });
1824
-
1825
- export { DestylerSplitterGroup, DestylerSplitterPanel, DestylerSplitterResizeHandle, DestylerSplitterRoot };
1
+ export { SplitterGroup, SplitterPanel, SplitterResizeHandle, SplitterRoot, splitterGroupProps, splitterPanelProps, splitterResizeHandleProps, splitterRootProps } from './component.mjs';
2
+ import 'vue';
3
+ import '@destyler/primitive';
4
+ import '@destyler/shared';
5
+ import '@destyler/composition';