@zag-js/splitter 0.2.5 → 0.2.7

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.
@@ -0,0 +1,9 @@
1
+ // src/splitter.anatomy.ts
2
+ import { createAnatomy } from "@zag-js/anatomy";
3
+ var anatomy = createAnatomy("splitter").parts("root", "panel", "toggleTrigger", "resizeTrigger");
4
+ var parts = anatomy.build();
5
+
6
+ export {
7
+ anatomy,
8
+ parts
9
+ };
@@ -0,0 +1,556 @@
1
+ import {
2
+ dom
3
+ } from "./chunk-T56NFB6E.mjs";
4
+ import {
5
+ clamp,
6
+ getHandleBounds,
7
+ getHandlePanels,
8
+ getNormalizedPanels,
9
+ getPanelBounds
10
+ } from "./chunk-SQ3UMXCZ.mjs";
11
+
12
+ // src/splitter.machine.ts
13
+ import { createMachine } from "@zag-js/core";
14
+
15
+ // ../../utilities/core/src/functions.ts
16
+ var runIfFn = (v, ...a) => {
17
+ const res = typeof v === "function" ? v(...a) : v;
18
+ return res != null ? res : void 0;
19
+ };
20
+ var callAll = (...fns) => (...a) => {
21
+ fns.forEach(function(fn) {
22
+ fn == null ? void 0 : fn(...a);
23
+ });
24
+ };
25
+
26
+ // ../../utilities/core/src/guard.ts
27
+ var isArray = (v) => Array.isArray(v);
28
+ var isObject = (v) => !(v == null || typeof v !== "object" || isArray(v));
29
+ var hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
30
+
31
+ // ../../utilities/core/src/object.ts
32
+ function compact(obj) {
33
+ if (obj === void 0)
34
+ return obj;
35
+ return Object.fromEntries(
36
+ Object.entries(obj).filter(([, value]) => value !== void 0).map(([key, value]) => [key, isObject(value) ? compact(value) : value])
37
+ );
38
+ }
39
+
40
+ // ../../utilities/dom/src/platform.ts
41
+ var isDom = () => typeof window !== "undefined";
42
+ function getPlatform() {
43
+ var _a;
44
+ const agent = navigator.userAgentData;
45
+ return (_a = agent == null ? void 0 : agent.platform) != null ? _a : navigator.platform;
46
+ }
47
+ var pt = (v) => isDom() && v.test(getPlatform());
48
+ var isTouchDevice = () => isDom() && !!navigator.maxTouchPoints;
49
+ var isMac = () => pt(/^Mac/) && !isTouchDevice;
50
+ var isApple = () => pt(/mac|iphone|ipad|ipod/i);
51
+ var isIos = () => isApple() && !isMac();
52
+
53
+ // ../../utilities/dom/src/event.ts
54
+ var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
55
+ var supportsTouchEvent = () => isDom() && window.ontouchstart === null;
56
+ var supportsMouseEvent = () => isDom() && window.onmousedown === null;
57
+ var isMouseEvent = (v) => isObject(v) && hasProp(v, "button");
58
+ var isTouchEvent = (v) => isObject(v) && hasProp(v, "touches");
59
+ var isLeftClick = (v) => v.button === 0;
60
+
61
+ // ../../utilities/dom/src/get-element-offset.ts
62
+ function getElementOffset(element) {
63
+ let left = 0;
64
+ let top = 0;
65
+ let el = element;
66
+ if (el.parentNode) {
67
+ do {
68
+ left += el.offsetLeft;
69
+ top += el.offsetTop;
70
+ } while ((el = el.offsetParent) && el.nodeType < 9);
71
+ el = element;
72
+ do {
73
+ left -= el.scrollLeft;
74
+ top -= el.scrollTop;
75
+ } while ((el = el.parentNode) && !/body/i.test(el.nodeName));
76
+ }
77
+ return {
78
+ top,
79
+ right: innerWidth - left - element.offsetWidth,
80
+ bottom: innerHeight - top - element.offsetHeight,
81
+ left
82
+ };
83
+ }
84
+
85
+ // ../../utilities/dom/src/get-point-relative-to-element.ts
86
+ function getPointRelativeToNode(point, element) {
87
+ const offset = getElementOffset(element);
88
+ const x = point.x - offset.left;
89
+ const y = point.y - offset.top;
90
+ return { x, y };
91
+ }
92
+ var clampPercent = (value) => Math.max(0, Math.min(100, value));
93
+ function getPointPercentRelativeToNode(point, element) {
94
+ const relativePoint = getPointRelativeToNode(point, element);
95
+ const x = relativePoint.x / element.offsetWidth * 100;
96
+ const y = relativePoint.y / element.offsetHeight * 100;
97
+ return { x: clampPercent(x), y: clampPercent(y) };
98
+ }
99
+ function normalizePointValue(point, options) {
100
+ const { dir = "ltr", orientation = "horizontal" } = options;
101
+ const { x, y } = point;
102
+ let result = { x, y };
103
+ if (orientation === "horizontal" && dir === "rtl") {
104
+ result = { x: 100 - x, y };
105
+ }
106
+ return orientation === "horizontal" ? result.x : result.y;
107
+ }
108
+
109
+ // ../../utilities/dom/src/listener.ts
110
+ var isRef = (v) => hasProp(v, "current");
111
+ var fallback = { pageX: 0, pageY: 0, clientX: 0, clientY: 0 };
112
+ function extractInfo(event, type = "page") {
113
+ const point = isTouchEvent(event) ? event.touches[0] || event.changedTouches[0] || fallback : event;
114
+ return {
115
+ point: {
116
+ x: point[`${type}X`],
117
+ y: point[`${type}Y`]
118
+ }
119
+ };
120
+ }
121
+ function addDomEvent(target, eventName, handler, options) {
122
+ const node = isRef(target) ? target.current : runIfFn(target);
123
+ node == null ? void 0 : node.addEventListener(eventName, handler, options);
124
+ return () => {
125
+ node == null ? void 0 : node.removeEventListener(eventName, handler, options);
126
+ };
127
+ }
128
+ function addPointerEvent(target, event, listener, options) {
129
+ var _a;
130
+ const type = (_a = getEventName(event)) != null ? _a : event;
131
+ return addDomEvent(target, type, wrapHandler(listener, event === "pointerdown"), options);
132
+ }
133
+ function wrapHandler(fn, filter = false) {
134
+ const listener = (event) => {
135
+ fn(event, extractInfo(event));
136
+ };
137
+ return filter ? filterPrimaryPointer(listener) : listener;
138
+ }
139
+ function filterPrimaryPointer(fn) {
140
+ return (event) => {
141
+ var _a;
142
+ const win = (_a = event.view) != null ? _a : window;
143
+ const isMouseEvent2 = event instanceof win.MouseEvent;
144
+ const isPrimary = !isMouseEvent2 || isMouseEvent2 && event.button === 0;
145
+ if (isPrimary)
146
+ fn(event);
147
+ };
148
+ }
149
+ var mouseEventNames = {
150
+ pointerdown: "mousedown",
151
+ pointermove: "mousemove",
152
+ pointerup: "mouseup",
153
+ pointercancel: "mousecancel",
154
+ pointerover: "mouseover",
155
+ pointerout: "mouseout",
156
+ pointerenter: "mouseenter",
157
+ pointerleave: "mouseleave"
158
+ };
159
+ var touchEventNames = {
160
+ pointerdown: "touchstart",
161
+ pointermove: "touchmove",
162
+ pointerup: "touchend",
163
+ pointercancel: "touchcancel"
164
+ };
165
+ function getEventName(evt) {
166
+ if (supportsPointerEvent())
167
+ return evt;
168
+ if (supportsTouchEvent())
169
+ return touchEventNames[evt];
170
+ if (supportsMouseEvent())
171
+ return mouseEventNames[evt];
172
+ return evt;
173
+ }
174
+
175
+ // ../../utilities/dom/src/next-tick.ts
176
+ function nextTick(fn) {
177
+ const set = /* @__PURE__ */ new Set();
178
+ function raf2(fn2) {
179
+ const id = globalThis.requestAnimationFrame(fn2);
180
+ set.add(() => globalThis.cancelAnimationFrame(id));
181
+ }
182
+ raf2(() => raf2(fn));
183
+ return function cleanup() {
184
+ set.forEach(function(fn2) {
185
+ fn2();
186
+ });
187
+ };
188
+ }
189
+ function raf(fn) {
190
+ const id = globalThis.requestAnimationFrame(fn);
191
+ return function cleanup() {
192
+ globalThis.cancelAnimationFrame(id);
193
+ };
194
+ }
195
+
196
+ // ../../utilities/dom/src/text-selection.ts
197
+ var state = "default";
198
+ var savedUserSelect = "";
199
+ var modifiedElementMap = /* @__PURE__ */ new WeakMap();
200
+ function disableTextSelection({ target, doc } = {}) {
201
+ const _document = doc != null ? doc : document;
202
+ if (isIos()) {
203
+ if (state === "default") {
204
+ savedUserSelect = _document.documentElement.style.webkitUserSelect;
205
+ _document.documentElement.style.webkitUserSelect = "none";
206
+ }
207
+ state = "disabled";
208
+ } else if (target) {
209
+ modifiedElementMap.set(target, target.style.userSelect);
210
+ target.style.userSelect = "none";
211
+ }
212
+ return () => restoreTextSelection({ target, doc: _document });
213
+ }
214
+ function restoreTextSelection({ target, doc } = {}) {
215
+ const _document = doc != null ? doc : document;
216
+ if (isIos()) {
217
+ if (state !== "disabled")
218
+ return;
219
+ state = "restoring";
220
+ setTimeout(() => {
221
+ nextTick(() => {
222
+ if (state === "restoring") {
223
+ if (_document.documentElement.style.webkitUserSelect === "none") {
224
+ _document.documentElement.style.webkitUserSelect = savedUserSelect || "";
225
+ }
226
+ savedUserSelect = "";
227
+ state = "default";
228
+ }
229
+ });
230
+ }, 300);
231
+ } else {
232
+ if (target && modifiedElementMap.has(target)) {
233
+ let targetOldUserSelect = modifiedElementMap.get(target);
234
+ if (target.style.userSelect === "none") {
235
+ target.style.userSelect = targetOldUserSelect != null ? targetOldUserSelect : "";
236
+ }
237
+ if (target.getAttribute("style") === "") {
238
+ target.removeAttribute("style");
239
+ }
240
+ modifiedElementMap.delete(target);
241
+ }
242
+ }
243
+ }
244
+
245
+ // ../../utilities/dom/src/pointer-event.ts
246
+ var THRESHOLD = 5;
247
+ function trackPointerMove(doc, opts) {
248
+ const { onPointerMove, onPointerUp } = opts;
249
+ const handlePointerMove = (event, info) => {
250
+ const { point: p } = info;
251
+ const distance = Math.sqrt(p.x ** 2 + p.y ** 2);
252
+ if (distance < THRESHOLD)
253
+ return;
254
+ if (isMouseEvent(event) && isLeftClick(event)) {
255
+ onPointerUp();
256
+ return;
257
+ }
258
+ onPointerMove(info, event);
259
+ };
260
+ return callAll(
261
+ addPointerEvent(doc, "pointermove", handlePointerMove, false),
262
+ addPointerEvent(doc, "pointerup", onPointerUp, false),
263
+ addPointerEvent(doc, "pointercancel", onPointerUp, false),
264
+ addPointerEvent(doc, "contextmenu", onPointerUp, false),
265
+ disableTextSelection({ doc })
266
+ );
267
+ }
268
+
269
+ // src/splitter.machine.ts
270
+ function machine(userContext) {
271
+ const ctx = compact(userContext);
272
+ return createMachine(
273
+ {
274
+ id: "splitter",
275
+ initial: "unknown",
276
+ context: {
277
+ orientation: "horizontal",
278
+ activeResizeId: null,
279
+ previousPanels: [],
280
+ size: [],
281
+ initialSize: [],
282
+ activeResizeState: {
283
+ isAtMin: false,
284
+ isAtMax: false
285
+ },
286
+ ...ctx
287
+ },
288
+ created: ["setPreviousPanels", "setInitialSize"],
289
+ watch: {
290
+ size: ["setActiveResizeState"]
291
+ },
292
+ computed: {
293
+ isHorizontal: (ctx2) => ctx2.orientation === "horizontal",
294
+ panels: (ctx2) => getNormalizedPanels(ctx2)
295
+ },
296
+ on: {
297
+ COLLAPSE: {
298
+ actions: "setStartPanelToMin"
299
+ },
300
+ EXPAND: {
301
+ actions: "setStartPanelToMax"
302
+ },
303
+ TOGGLE: [
304
+ {
305
+ guard: "isStartPanelAtMin",
306
+ actions: "setStartPanelToMax"
307
+ },
308
+ {
309
+ actions: "setStartPanelToMin"
310
+ }
311
+ ]
312
+ },
313
+ states: {
314
+ unknown: {
315
+ on: {
316
+ SETUP: "idle"
317
+ }
318
+ },
319
+ idle: {
320
+ entry: ["clearActiveHandleId"],
321
+ on: {
322
+ POINTER_OVER: {
323
+ target: "hover:temp",
324
+ actions: ["setActiveHandleId"]
325
+ },
326
+ FOCUS: {
327
+ target: "focused",
328
+ actions: ["setActiveHandleId"]
329
+ },
330
+ DOUBLE_CLICK: {
331
+ actions: ["resetStartPanel", "setPreviousPanels"]
332
+ }
333
+ }
334
+ },
335
+ "hover:temp": {
336
+ after: {
337
+ HOVER_DELAY: "hover"
338
+ },
339
+ on: {
340
+ POINTER_DOWN: {
341
+ target: "dragging",
342
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
343
+ },
344
+ POINTER_LEAVE: "idle"
345
+ }
346
+ },
347
+ hover: {
348
+ tags: ["focus"],
349
+ on: {
350
+ POINTER_DOWN: {
351
+ target: "dragging",
352
+ actions: ["invokeOnResizeStart"]
353
+ },
354
+ POINTER_LEAVE: "idle"
355
+ }
356
+ },
357
+ focused: {
358
+ tags: ["focus"],
359
+ on: {
360
+ BLUR: "idle",
361
+ POINTER_DOWN: {
362
+ target: "dragging",
363
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
364
+ },
365
+ ARROW_LEFT: {
366
+ guard: "isHorizontal",
367
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
368
+ },
369
+ ARROW_RIGHT: {
370
+ guard: "isHorizontal",
371
+ actions: ["expandStartPanel", "setPreviousPanels"]
372
+ },
373
+ ARROW_UP: {
374
+ guard: "isVertical",
375
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
376
+ },
377
+ ARROW_DOWN: {
378
+ guard: "isVertical",
379
+ actions: ["expandStartPanel", "setPreviousPanels"]
380
+ },
381
+ ENTER: [
382
+ {
383
+ guard: "isStartPanelAtMax",
384
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
385
+ },
386
+ { actions: ["setStartPanelToMax", "setPreviousPanels"] }
387
+ ],
388
+ HOME: {
389
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
390
+ },
391
+ END: {
392
+ actions: ["setStartPanelToMax", "setPreviousPanels"]
393
+ }
394
+ }
395
+ },
396
+ dragging: {
397
+ tags: ["focus"],
398
+ entry: "focusResizeHandle",
399
+ activities: ["trackPointerMove"],
400
+ on: {
401
+ POINTER_MOVE: {
402
+ actions: ["setPointerValue", "setGlobalCursor"]
403
+ },
404
+ POINTER_UP: {
405
+ target: "focused",
406
+ actions: ["invokeOnResizeEnd", "setPreviousPanels", "clearGlobalCursor", "blurResizeHandle"]
407
+ }
408
+ }
409
+ }
410
+ }
411
+ },
412
+ {
413
+ activities: {
414
+ trackPointerMove: (ctx2, _evt, { send }) => {
415
+ const doc = dom.getDoc(ctx2);
416
+ return trackPointerMove(doc, {
417
+ onPointerMove(info) {
418
+ send({ type: "POINTER_MOVE", point: info.point });
419
+ },
420
+ onPointerUp() {
421
+ send("POINTER_UP");
422
+ }
423
+ });
424
+ }
425
+ },
426
+ guards: {
427
+ isStartPanelAtMin: (ctx2) => ctx2.activeResizeState.isAtMin,
428
+ isStartPanelAtMax: (ctx2) => ctx2.activeResizeState.isAtMax,
429
+ isHorizontal: (ctx2) => ctx2.isHorizontal,
430
+ isVertical: (ctx2) => !ctx2.isHorizontal
431
+ },
432
+ delays: {
433
+ HOVER_DELAY: 250
434
+ },
435
+ actions: {
436
+ setGlobalCursor(ctx2) {
437
+ dom.setupGlobalCursor(ctx2);
438
+ },
439
+ clearGlobalCursor(ctx2) {
440
+ dom.removeGlobalCursor(ctx2);
441
+ },
442
+ invokeOnResize(ctx2) {
443
+ var _a;
444
+ (_a = ctx2.onResize) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
445
+ },
446
+ invokeOnResizeStart(ctx2) {
447
+ var _a;
448
+ (_a = ctx2.onResizeStart) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
449
+ },
450
+ invokeOnResizeEnd(ctx2) {
451
+ var _a;
452
+ (_a = ctx2.onResizeEnd) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
453
+ },
454
+ setActiveHandleId(ctx2, evt) {
455
+ ctx2.activeResizeId = evt.id;
456
+ },
457
+ clearActiveHandleId(ctx2) {
458
+ ctx2.activeResizeId = null;
459
+ },
460
+ setInitialSize(ctx2) {
461
+ ctx2.initialSize = ctx2.panels.slice().map((panel) => ({
462
+ id: panel.id,
463
+ size: panel.size
464
+ }));
465
+ },
466
+ setStartPanelToMin(ctx2) {
467
+ const bounds = getPanelBounds(ctx2);
468
+ if (!bounds)
469
+ return;
470
+ const { before, after } = bounds;
471
+ ctx2.size[before.index].size = before.min;
472
+ ctx2.size[after.index].size = after.min;
473
+ },
474
+ setStartPanelToMax(ctx2) {
475
+ const bounds = getPanelBounds(ctx2);
476
+ if (!bounds)
477
+ return;
478
+ const { before, after } = bounds;
479
+ ctx2.size[before.index].size = before.max;
480
+ ctx2.size[after.index].size = after.max;
481
+ },
482
+ expandStartPanel(ctx2, evt) {
483
+ const bounds = getPanelBounds(ctx2);
484
+ if (!bounds)
485
+ return;
486
+ const { before, after } = bounds;
487
+ ctx2.size[before.index].size = before.up(evt.step);
488
+ ctx2.size[after.index].size = after.down(evt.step);
489
+ },
490
+ shrinkStartPanel(ctx2, evt) {
491
+ const bounds = getPanelBounds(ctx2);
492
+ if (!bounds)
493
+ return;
494
+ const { before, after } = bounds;
495
+ ctx2.size[before.index].size = before.down(evt.step);
496
+ ctx2.size[after.index].size = after.up(evt.step);
497
+ },
498
+ resetStartPanel(ctx2, evt) {
499
+ const bounds = getPanelBounds(ctx2, evt.id);
500
+ if (!bounds)
501
+ return;
502
+ const { before, after } = bounds;
503
+ ctx2.size[before.index].size = ctx2.initialSize[before.index].size;
504
+ ctx2.size[after.index].size = ctx2.initialSize[after.index].size;
505
+ },
506
+ focusResizeHandle(ctx2) {
507
+ raf(() => {
508
+ var _a;
509
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.focus();
510
+ });
511
+ },
512
+ blurResizeHandle(ctx2) {
513
+ raf(() => {
514
+ var _a;
515
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.blur();
516
+ });
517
+ },
518
+ setPreviousPanels(ctx2) {
519
+ ctx2.previousPanels = ctx2.panels.slice();
520
+ },
521
+ setActiveResizeState(ctx2) {
522
+ const panels = getPanelBounds(ctx2);
523
+ if (!panels)
524
+ return;
525
+ const { before } = panels;
526
+ ctx2.activeResizeState = {
527
+ isAtMin: before.isAtMin,
528
+ isAtMax: before.isAtMax
529
+ };
530
+ },
531
+ setPointerValue(ctx2, evt) {
532
+ const panels = getHandlePanels(ctx2);
533
+ const bounds = getHandleBounds(ctx2);
534
+ const rootEl = dom.getRootEl(ctx2);
535
+ if (!panels || !rootEl || !bounds)
536
+ return;
537
+ const percent = getPointPercentRelativeToNode(evt.point, rootEl);
538
+ let pointValue = normalizePointValue(percent, ctx2);
539
+ ctx2.activeResizeState = {
540
+ isAtMin: pointValue < bounds.min,
541
+ isAtMax: pointValue > bounds.max
542
+ };
543
+ pointValue = clamp(pointValue, bounds.min, bounds.max);
544
+ const { before, after } = panels;
545
+ const offset = pointValue - before.end;
546
+ ctx2.size[before.index].size = before.size + offset;
547
+ ctx2.size[after.index].size = after.size - offset;
548
+ }
549
+ }
550
+ }
551
+ );
552
+ }
553
+
554
+ export {
555
+ machine
556
+ };
@@ -0,0 +1,131 @@
1
+ // src/splitter.utils.ts
2
+ function validateSize(key, size) {
3
+ if (Math.floor(size) > 100) {
4
+ throw new Error(`Total ${key} of panels cannot be greater than 100`);
5
+ }
6
+ }
7
+ function getNormalizedPanels(ctx) {
8
+ let numOfPanelsWithoutSize = 0;
9
+ let totalSize = 0;
10
+ let totalMinSize = 0;
11
+ const panels = ctx.size.map((panel) => {
12
+ var _a, _b;
13
+ const minSize = (_a = panel.minSize) != null ? _a : 10;
14
+ const maxSize = (_b = panel.maxSize) != null ? _b : 100;
15
+ totalMinSize += minSize;
16
+ if (panel.size == null) {
17
+ numOfPanelsWithoutSize++;
18
+ } else {
19
+ totalSize += panel.size;
20
+ }
21
+ return {
22
+ ...panel,
23
+ minSize,
24
+ maxSize
25
+ };
26
+ });
27
+ validateSize("minSize", totalMinSize);
28
+ validateSize("size", totalSize);
29
+ let end = 0;
30
+ let remainingSize = 0;
31
+ const result = panels.map((panel) => {
32
+ let start = end;
33
+ if (panel.size != null) {
34
+ end += panel.size;
35
+ remainingSize = panel.size - panel.minSize;
36
+ return {
37
+ ...panel,
38
+ start,
39
+ end,
40
+ remainingSize
41
+ };
42
+ }
43
+ const size = (100 - totalSize) / numOfPanelsWithoutSize;
44
+ end += size;
45
+ remainingSize = size - panel.minSize;
46
+ return { ...panel, size, start, end, remainingSize };
47
+ });
48
+ return result;
49
+ }
50
+ function getHandlePanels(ctx, id = ctx.activeResizeId) {
51
+ var _a;
52
+ const [beforeId, afterId] = (_a = id == null ? void 0 : id.split(":")) != null ? _a : [];
53
+ if (!beforeId || !afterId)
54
+ return;
55
+ const beforeIndex = ctx.previousPanels.findIndex((panel) => panel.id === beforeId);
56
+ const afterIndex = ctx.previousPanels.findIndex((panel) => panel.id === afterId);
57
+ if (beforeIndex === -1 || afterIndex === -1)
58
+ return;
59
+ const before = ctx.previousPanels[beforeIndex];
60
+ const after = ctx.previousPanels[afterIndex];
61
+ return {
62
+ before: {
63
+ ...before,
64
+ index: beforeIndex
65
+ },
66
+ after: {
67
+ ...after,
68
+ index: afterIndex
69
+ }
70
+ };
71
+ }
72
+ function getHandleBounds(ctx, id = ctx.activeResizeId) {
73
+ const panels = getHandlePanels(ctx, id);
74
+ if (!panels)
75
+ return;
76
+ const { before, after } = panels;
77
+ return {
78
+ min: Math.max(before.start + before.minSize, after.end - after.maxSize),
79
+ max: Math.min(after.end - after.minSize, before.maxSize + before.start)
80
+ };
81
+ }
82
+ function getPanelBounds(ctx, id) {
83
+ const bounds = getHandleBounds(ctx, id);
84
+ const panels = getHandlePanels(ctx, id);
85
+ if (!bounds || !panels)
86
+ return;
87
+ const { before, after } = panels;
88
+ const beforeMin = Math.abs(before.start - bounds.min);
89
+ const afterMin = after.size + (before.size - beforeMin);
90
+ const beforeMax = Math.abs(before.start - bounds.max);
91
+ const afterMax = after.size - (beforeMax - before.size);
92
+ return {
93
+ before: {
94
+ index: before.index,
95
+ min: beforeMin,
96
+ max: beforeMax,
97
+ isAtMin: beforeMin === before.size,
98
+ isAtMax: beforeMax === before.size,
99
+ up(step) {
100
+ return Math.min(before.size + step, beforeMax);
101
+ },
102
+ down(step) {
103
+ return Math.max(before.size - step, beforeMin);
104
+ }
105
+ },
106
+ after: {
107
+ index: after.index,
108
+ min: afterMin,
109
+ max: afterMax,
110
+ isAtMin: afterMin === after.size,
111
+ isAtMax: afterMax === after.size,
112
+ up(step) {
113
+ return Math.min(after.size + step, afterMin);
114
+ },
115
+ down(step) {
116
+ return Math.max(after.size - step, afterMax);
117
+ }
118
+ }
119
+ };
120
+ }
121
+ function clamp(value, min, max) {
122
+ return Math.min(Math.max(value, min), max);
123
+ }
124
+
125
+ export {
126
+ getNormalizedPanels,
127
+ getHandlePanels,
128
+ getHandleBounds,
129
+ getPanelBounds,
130
+ clamp
131
+ };