@zag-js/splitter 0.2.6 → 0.2.8

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.js CHANGED
@@ -28,14 +28,7 @@ module.exports = __toCommonJS(src_exports);
28
28
 
29
29
  // src/splitter.anatomy.ts
30
30
  var import_anatomy = require("@zag-js/anatomy");
31
- var anatomy = (0, import_anatomy.createAnatomy)("splitter").parts(
32
- "root",
33
- "secondaryPane",
34
- "primaryPane",
35
- "toggleButton",
36
- "label",
37
- "splitter"
38
- );
31
+ var anatomy = (0, import_anatomy.createAnatomy)("splitter").parts("root", "panel", "toggleTrigger", "resizeTrigger");
39
32
  var parts = anatomy.build();
40
33
 
41
34
  // ../../utilities/dom/src/attrs.ts
@@ -108,25 +101,7 @@ function defineDomHelpers(helpers) {
108
101
  return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
109
102
  },
110
103
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
111
- getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id),
112
- createEmitter: (ctx, target) => {
113
- const win = dom2.getWin(ctx);
114
- return function emit(evt, detail, options) {
115
- const { bubbles = true, cancelable, composed = true } = options != null ? options : {};
116
- const eventName = `zag:${evt}`;
117
- const init = { bubbles, cancelable, composed, detail };
118
- const event = new win.CustomEvent(eventName, init);
119
- target.dispatchEvent(event);
120
- };
121
- },
122
- createListener: (target) => {
123
- return function listen(evt, handler) {
124
- const eventName = `zag:${evt}`;
125
- const listener = (e) => handler(e);
126
- target.addEventListener(eventName, listener);
127
- return () => target.removeEventListener(eventName, listener);
128
- };
129
- }
104
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
130
105
  };
131
106
  return {
132
107
  ...dom2,
@@ -173,6 +148,22 @@ function getPointRelativeToNode(point, element) {
173
148
  const y = point.y - offset.top;
174
149
  return { x, y };
175
150
  }
151
+ var clampPercent = (value) => Math.max(0, Math.min(100, value));
152
+ function getPointPercentRelativeToNode(point, element) {
153
+ const relativePoint = getPointRelativeToNode(point, element);
154
+ const x = relativePoint.x / element.offsetWidth * 100;
155
+ const y = relativePoint.y / element.offsetHeight * 100;
156
+ return { x: clampPercent(x), y: clampPercent(y) };
157
+ }
158
+ function normalizePointValue(point, options) {
159
+ const { dir = "ltr", orientation = "horizontal" } = options;
160
+ const { x, y } = point;
161
+ let result = { x, y };
162
+ if (orientation === "horizontal" && dir === "rtl") {
163
+ result = { x: 100 - x, y };
164
+ }
165
+ return orientation === "horizontal" ? result.x : result.y;
166
+ }
176
167
 
177
168
  // ../../utilities/dom/src/keyboard-event.ts
178
169
  var rtlKeyMap = {
@@ -298,6 +289,12 @@ function raf(fn) {
298
289
  };
299
290
  }
300
291
 
292
+ // ../../utilities/dom/src/nodelist.ts
293
+ function queryAll(root, selector) {
294
+ var _a;
295
+ return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
296
+ }
297
+
301
298
  // ../../utilities/dom/src/text-selection.ts
302
299
  var state = "default";
303
300
  var savedUserSelect = "";
@@ -373,261 +370,342 @@ function trackPointerMove(doc, opts) {
373
370
 
374
371
  // src/splitter.dom.ts
375
372
  var dom = defineDomHelpers({
376
- getRootId: (ctx) => {
377
- var _a, _b;
378
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `splitter:${ctx.id}`;
379
- },
380
- getSplitterId: (ctx) => {
381
- var _a, _b;
382
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.splitter) != null ? _b : `splitter:${ctx.id}:splitter`;
383
- },
384
- getToggleButtonId: (ctx) => {
385
- var _a, _b;
386
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.toggleBtn) != null ? _b : `splitter:${ctx.id}:toggle-btn`;
387
- },
388
- getLabelId: (ctx) => {
389
- var _a, _b;
390
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `splitter:${ctx.id}:label`;
391
- },
392
- getPrimaryPaneId: (ctx) => {
393
- var _a, _b;
394
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.primaryPane) != null ? _b : `splitter:${ctx.id}:primary`;
395
- },
396
- getSecondaryPaneId: (ctx) => {
397
- var _a, _b;
398
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.secondaryPane) != null ? _b : `splitter:${ctx.id}:secondary`;
399
- },
400
- getSplitterEl: (ctx) => dom.getById(ctx, dom.getSplitterId(ctx)),
401
- getPrimaryPaneEl: (ctx) => dom.getById(ctx, dom.getPrimaryPaneId(ctx)),
373
+ getRootId: (ctx) => `splitter:${ctx.id}`,
374
+ getResizeTriggerId: (ctx, id) => `splitter:${ctx.id}:splitter:${id}`,
375
+ getToggleTriggerId: (ctx) => `splitter:${ctx.id}:toggle-btn`,
376
+ getLabelId: (ctx) => `splitter:${ctx.id}:label`,
377
+ getPanelId: (ctx, id) => `splitter:${ctx.id}:panel:${id}`,
378
+ globalCursorId: (ctx) => `splitter:${ctx.id}:global-cursor`,
379
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
380
+ getResizeTriggerEl: (ctx, id) => dom.getById(ctx, dom.getResizeTriggerId(ctx, id)),
381
+ getPanelEl: (ctx, id) => dom.getById(ctx, dom.getPanelId(ctx, id)),
402
382
  getCursor(ctx) {
403
- if (ctx.disabled || ctx.fixed)
404
- return "default";
405
383
  const x = ctx.isHorizontal;
406
384
  let cursor = x ? "col-resize" : "row-resize";
407
- if (ctx.isAtMin)
385
+ if (ctx.activeResizeState.isAtMin)
408
386
  cursor = x ? "e-resize" : "s-resize";
409
- if (ctx.isAtMax)
387
+ if (ctx.activeResizeState.isAtMax)
410
388
  cursor = x ? "w-resize" : "n-resize";
411
389
  return cursor;
390
+ },
391
+ getPanelStyle(ctx, id) {
392
+ var _a, _b;
393
+ const flexGrow = (_b = (_a = ctx.panels.find((panel) => panel.id === id)) == null ? void 0 : _a.size) != null ? _b : "0";
394
+ return {
395
+ flexBasis: 0,
396
+ flexGrow,
397
+ flexShrink: 1,
398
+ overflow: "hidden"
399
+ };
400
+ },
401
+ getActiveHandleEl(ctx) {
402
+ const activeId = ctx.activeResizeId;
403
+ if (activeId == null)
404
+ return;
405
+ return dom.getById(ctx, dom.getResizeTriggerId(ctx, activeId));
406
+ },
407
+ getResizeTriggerEls(ctx) {
408
+ const ownerId = CSS.escape(dom.getRootId(ctx));
409
+ return queryAll(dom.getRootEl(ctx), `[role=separator][data-ownedby='${ownerId}']`);
410
+ },
411
+ setupGlobalCursor(ctx) {
412
+ const styleEl = dom.getById(ctx, dom.globalCursorId(ctx));
413
+ const textContent = `* { cursor: ${dom.getCursor(ctx)} !important; }`;
414
+ if (styleEl) {
415
+ styleEl.textContent = textContent;
416
+ } else {
417
+ const style = dom.getDoc(ctx).createElement("style");
418
+ style.id = dom.globalCursorId(ctx);
419
+ style.textContent = textContent;
420
+ dom.getDoc(ctx).head.appendChild(style);
421
+ }
422
+ },
423
+ removeGlobalCursor(ctx) {
424
+ var _a;
425
+ (_a = dom.getById(ctx, dom.globalCursorId(ctx))) == null ? void 0 : _a.remove();
412
426
  }
413
427
  });
414
428
 
429
+ // src/splitter.utils.ts
430
+ function validateSize(key, size) {
431
+ if (Math.floor(size) > 100) {
432
+ throw new Error(`Total ${key} of panels cannot be greater than 100`);
433
+ }
434
+ }
435
+ function getNormalizedPanels(ctx) {
436
+ let numOfPanelsWithoutSize = 0;
437
+ let totalSize = 0;
438
+ let totalMinSize = 0;
439
+ const panels = ctx.size.map((panel) => {
440
+ var _a, _b;
441
+ const minSize = (_a = panel.minSize) != null ? _a : 10;
442
+ const maxSize = (_b = panel.maxSize) != null ? _b : 100;
443
+ totalMinSize += minSize;
444
+ if (panel.size == null) {
445
+ numOfPanelsWithoutSize++;
446
+ } else {
447
+ totalSize += panel.size;
448
+ }
449
+ return {
450
+ ...panel,
451
+ minSize,
452
+ maxSize
453
+ };
454
+ });
455
+ validateSize("minSize", totalMinSize);
456
+ validateSize("size", totalSize);
457
+ let end = 0;
458
+ let remainingSize = 0;
459
+ const result = panels.map((panel) => {
460
+ let start = end;
461
+ if (panel.size != null) {
462
+ end += panel.size;
463
+ remainingSize = panel.size - panel.minSize;
464
+ return {
465
+ ...panel,
466
+ start,
467
+ end,
468
+ remainingSize
469
+ };
470
+ }
471
+ const size = (100 - totalSize) / numOfPanelsWithoutSize;
472
+ end += size;
473
+ remainingSize = size - panel.minSize;
474
+ return { ...panel, size, start, end, remainingSize };
475
+ });
476
+ return result;
477
+ }
478
+ function getHandlePanels(ctx, id = ctx.activeResizeId) {
479
+ var _a;
480
+ const [beforeId, afterId] = (_a = id == null ? void 0 : id.split(":")) != null ? _a : [];
481
+ if (!beforeId || !afterId)
482
+ return;
483
+ const beforeIndex = ctx.previousPanels.findIndex((panel) => panel.id === beforeId);
484
+ const afterIndex = ctx.previousPanels.findIndex((panel) => panel.id === afterId);
485
+ if (beforeIndex === -1 || afterIndex === -1)
486
+ return;
487
+ const before = ctx.previousPanels[beforeIndex];
488
+ const after = ctx.previousPanels[afterIndex];
489
+ return {
490
+ before: {
491
+ ...before,
492
+ index: beforeIndex
493
+ },
494
+ after: {
495
+ ...after,
496
+ index: afterIndex
497
+ }
498
+ };
499
+ }
500
+ function getHandleBounds(ctx, id = ctx.activeResizeId) {
501
+ const panels = getHandlePanels(ctx, id);
502
+ if (!panels)
503
+ return;
504
+ const { before, after } = panels;
505
+ return {
506
+ min: Math.max(before.start + before.minSize, after.end - after.maxSize),
507
+ max: Math.min(after.end - after.minSize, before.maxSize + before.start)
508
+ };
509
+ }
510
+ function getPanelBounds(ctx, id) {
511
+ const bounds = getHandleBounds(ctx, id);
512
+ const panels = getHandlePanels(ctx, id);
513
+ if (!bounds || !panels)
514
+ return;
515
+ const { before, after } = panels;
516
+ const beforeMin = Math.abs(before.start - bounds.min);
517
+ const afterMin = after.size + (before.size - beforeMin);
518
+ const beforeMax = Math.abs(before.start - bounds.max);
519
+ const afterMax = after.size - (beforeMax - before.size);
520
+ return {
521
+ before: {
522
+ index: before.index,
523
+ min: beforeMin,
524
+ max: beforeMax,
525
+ isAtMin: beforeMin === before.size,
526
+ isAtMax: beforeMax === before.size,
527
+ up(step) {
528
+ return Math.min(before.size + step, beforeMax);
529
+ },
530
+ down(step) {
531
+ return Math.max(before.size - step, beforeMin);
532
+ }
533
+ },
534
+ after: {
535
+ index: after.index,
536
+ min: afterMin,
537
+ max: afterMax,
538
+ isAtMin: afterMin === after.size,
539
+ isAtMax: afterMax === after.size,
540
+ up(step) {
541
+ return Math.min(after.size + step, afterMin);
542
+ },
543
+ down(step) {
544
+ return Math.max(after.size - step, afterMax);
545
+ }
546
+ }
547
+ };
548
+ }
549
+ function clamp(value, min, max) {
550
+ return Math.min(Math.max(value, min), max);
551
+ }
552
+
415
553
  // src/splitter.connect.ts
416
554
  function connect(state2, send, normalize) {
417
555
  const isHorizontal = state2.context.isHorizontal;
418
- const isDisabled = state2.context.disabled;
419
556
  const isFocused = state2.hasTag("focus");
420
557
  const isDragging = state2.matches("dragging");
421
- const isAtMin = state2.context.isAtMin;
422
- const isAtMax = state2.context.isAtMax;
423
- const min = state2.context.min;
424
- const max = state2.context.max;
425
- const value = state2.context.value;
426
- return {
427
- isCollapsed: isAtMin,
428
- isExpanded: isAtMax,
558
+ const api = {
429
559
  isFocused,
430
560
  isDragging,
431
- value,
432
- collapse() {
433
- send("COLLAPSE");
561
+ bounds: getHandleBounds(state2.context),
562
+ collapse(id) {
563
+ send({ type: "COLLAPSE", id });
434
564
  },
435
- expand() {
436
- send("EXPAND");
565
+ expand(id) {
566
+ send({ type: "EXPAND", id });
437
567
  },
438
- toggle() {
439
- send("TOGGLE");
568
+ toggle(id) {
569
+ send({ type: "TOGGLE", id });
440
570
  },
441
- setSize(size) {
442
- send({ type: "SET_SIZE", size });
571
+ setSize(id, size) {
572
+ send({ type: "SET_SIZE", id, size });
443
573
  },
444
574
  rootProps: normalize.element({
445
575
  ...parts.root.attrs,
446
576
  "data-orientation": state2.context.orientation,
447
- "data-disabled": dataAttr(isDisabled),
448
577
  id: dom.getRootId(state2.context),
578
+ dir: state2.context.dir,
449
579
  style: {
450
580
  display: "flex",
451
- flex: "1 1 0%",
452
- flexDirection: isHorizontal ? "row" : "column"
453
- }
454
- }),
455
- secondaryPaneProps: normalize.element({
456
- ...parts.secondaryPane.attrs,
457
- "data-disabled": dataAttr(isDisabled),
458
- id: dom.getSecondaryPaneId(state2.context),
459
- style: {
460
- height: isHorizontal ? "100%" : "auto",
461
- width: isHorizontal ? "auto" : "100%",
462
- flex: "1 1 auto",
463
- position: "relative"
464
- }
465
- }),
466
- primaryPaneProps: normalize.element({
467
- ...parts.primaryPane.attrs,
468
- id: dom.getPrimaryPaneId(state2.context),
469
- "data-disabled": dataAttr(isDisabled),
470
- "data-state": isAtMax ? "at-max" : isAtMin ? "at-min" : "between",
471
- style: {
472
- visibility: "visible",
473
- flex: `0 0 ${value}px`,
474
- position: "relative",
475
- userSelect: isDragging ? "none" : "auto",
476
- ...isHorizontal ? { minWidth: `${min}px`, maxWidth: `${max}px` } : { minHeight: `${min}px`, maxHeight: `${max}px` }
581
+ flexDirection: isHorizontal ? "row" : "column",
582
+ height: "100%",
583
+ width: "100%",
584
+ overflow: "hidden"
477
585
  }
478
586
  }),
479
- toggleButtonProps: normalize.element({
480
- ...parts.toggleButton.attrs,
481
- id: dom.getToggleButtonId(state2.context),
482
- "aria-label": state2.context.isAtMin ? "Expand Primary Pane" : "Collapse Primary Pane",
483
- onClick() {
484
- send("TOGGLE");
485
- }
486
- }),
487
- labelProps: normalize.element({
488
- ...parts.label.attrs,
489
- id: dom.getLabelId(state2.context)
490
- }),
491
- splitterProps: normalize.element({
492
- ...parts.splitter.attrs,
493
- id: dom.getSplitterId(state2.context),
494
- role: "separator",
495
- tabIndex: isDisabled ? void 0 : 0,
496
- "aria-valuenow": value,
497
- "aria-valuemin": min,
498
- "aria-valuemax": max,
499
- "aria-orientation": state2.context.orientation,
500
- "aria-labelledby": dom.getLabelId(state2.context),
501
- "aria-controls": dom.getPrimaryPaneId(state2.context),
502
- "data-orientation": state2.context.orientation,
503
- "data-focus": dataAttr(isFocused),
504
- "data-disabled": dataAttr(isDisabled),
505
- style: {
506
- touchAction: "none",
507
- userSelect: "none",
508
- WebkitUserSelect: "none",
509
- msUserSelect: "none",
510
- flex: "0 0 auto",
511
- cursor: dom.getCursor(state2.context),
512
- minHeight: isHorizontal ? "0px" : void 0,
513
- minWidth: isHorizontal ? void 0 : "0px"
514
- },
515
- onPointerDown(event) {
516
- if (isDisabled) {
517
- event.preventDefault();
518
- return;
519
- }
520
- send("POINTER_DOWN");
521
- event.preventDefault();
522
- event.stopPropagation();
523
- },
524
- onPointerOver() {
525
- if (isDisabled)
526
- return;
527
- send("POINTER_OVER");
528
- },
529
- onPointerLeave() {
530
- if (isDisabled)
531
- return;
532
- send("POINTER_LEAVE");
533
- },
534
- onBlur() {
535
- send("BLUR");
536
- },
537
- onFocus() {
538
- send("FOCUS");
539
- },
540
- onDoubleClick() {
541
- if (isDisabled)
542
- return;
543
- send("DOUBLE_CLICK");
544
- },
545
- onKeyDown(event) {
546
- if (isDisabled)
547
- return;
548
- const step = getEventStep(event) * state2.context.step;
549
- const keyMap = {
550
- ArrowUp() {
551
- send({ type: "ARROW_UP", step });
552
- },
553
- ArrowDown() {
554
- send({ type: "ARROW_DOWN", step });
555
- },
556
- ArrowLeft() {
557
- send({ type: "ARROW_LEFT", step });
558
- },
559
- ArrowRight() {
560
- send({ type: "ARROW_RIGHT", step });
561
- },
562
- Home() {
563
- send("HOME");
564
- },
565
- End() {
566
- send("END");
587
+ getPanelProps(props) {
588
+ const { id } = props;
589
+ return normalize.element({
590
+ ...parts.panel.attrs,
591
+ dir: state2.context.dir,
592
+ id: dom.getPanelId(state2.context, id),
593
+ "data-ownedby": dom.getRootId(state2.context),
594
+ style: dom.getPanelStyle(state2.context, id)
595
+ });
596
+ },
597
+ getResizeTriggerState(props) {
598
+ const { id, disabled } = props;
599
+ const ids = id.split(":");
600
+ const panelIds = ids.map((id2) => dom.getPanelId(state2.context, id2));
601
+ const panels = getHandleBounds(state2.context, id);
602
+ return {
603
+ isDisabled: !!disabled,
604
+ isFocused: state2.context.activeResizeId === id && isFocused,
605
+ panelIds,
606
+ min: panels == null ? void 0 : panels.min,
607
+ max: panels == null ? void 0 : panels.max,
608
+ value: 0
609
+ };
610
+ },
611
+ getResizeTriggerProps(props) {
612
+ const { id, disabled, step = 1 } = props;
613
+ const triggerState = api.getResizeTriggerState(props);
614
+ return normalize.element({
615
+ ...parts.resizeTrigger.attrs,
616
+ dir: state2.context.dir,
617
+ id: dom.getResizeTriggerId(state2.context, id),
618
+ role: "separator",
619
+ "data-ownedby": dom.getRootId(state2.context),
620
+ tabIndex: disabled ? void 0 : 0,
621
+ "aria-valuenow": triggerState.value,
622
+ "aria-valuemin": triggerState.min,
623
+ "aria-valuemax": triggerState.max,
624
+ "data-orientation": state2.context.orientation,
625
+ "aria-orientation": state2.context.orientation,
626
+ "aria-controls": triggerState.panelIds.join(" "),
627
+ "data-focus": dataAttr(triggerState.isFocused),
628
+ "data-disabled": dataAttr(disabled),
629
+ style: {
630
+ touchAction: "none",
631
+ userSelect: "none",
632
+ flex: "0 0 auto",
633
+ pointerEvents: isDragging && !triggerState.isFocused ? "none" : void 0,
634
+ cursor: isHorizontal ? "col-resize" : "row-resize",
635
+ [isHorizontal ? "minHeight" : "minWidth"]: "0"
636
+ },
637
+ onPointerDown(event) {
638
+ if (disabled) {
639
+ event.preventDefault();
640
+ return;
567
641
  }
568
- };
569
- const key = getEventKey(event, state2.context);
570
- const exec = keyMap[key];
571
- if (exec) {
572
- exec(event);
642
+ send({ type: "POINTER_DOWN", id });
573
643
  event.preventDefault();
644
+ event.stopPropagation();
645
+ },
646
+ onPointerOver() {
647
+ if (disabled)
648
+ return;
649
+ send({ type: "POINTER_OVER", id });
650
+ },
651
+ onPointerLeave() {
652
+ if (disabled)
653
+ return;
654
+ send({ type: "POINTER_LEAVE", id });
655
+ },
656
+ onBlur() {
657
+ send("BLUR");
658
+ },
659
+ onFocus() {
660
+ send({ type: "FOCUS", id });
661
+ },
662
+ onDoubleClick() {
663
+ if (disabled)
664
+ return;
665
+ send({ type: "DOUBLE_CLICK", id });
666
+ },
667
+ onKeyDown(event) {
668
+ if (disabled)
669
+ return;
670
+ const moveStep = getEventStep(event) * step;
671
+ const keyMap = {
672
+ Enter() {
673
+ send("ENTER");
674
+ },
675
+ ArrowUp() {
676
+ send({ type: "ARROW_UP", step: moveStep });
677
+ },
678
+ ArrowDown() {
679
+ send({ type: "ARROW_DOWN", step: moveStep });
680
+ },
681
+ ArrowLeft() {
682
+ send({ type: "ARROW_LEFT", step: moveStep });
683
+ },
684
+ ArrowRight() {
685
+ send({ type: "ARROW_RIGHT", step: moveStep });
686
+ },
687
+ Home() {
688
+ send("HOME");
689
+ },
690
+ End() {
691
+ send("END");
692
+ }
693
+ };
694
+ const key = getEventKey(event, state2.context);
695
+ const exec = keyMap[key];
696
+ if (exec) {
697
+ exec(event);
698
+ event.preventDefault();
699
+ }
574
700
  }
575
- }
576
- })
701
+ });
702
+ }
577
703
  };
704
+ return api;
578
705
  }
579
706
 
580
707
  // src/splitter.machine.ts
581
708
  var import_core = require("@zag-js/core");
582
-
583
- // ../../utilities/number/src/number.ts
584
- function round(v, t) {
585
- let num = valueOf(v);
586
- const p = 10 ** (t != null ? t : 10);
587
- num = Math.round(num * p) / p;
588
- return t ? num.toFixed(t) : v.toString();
589
- }
590
- function clamp(v, o) {
591
- return Math.min(Math.max(valueOf(v), o.min), o.max);
592
- }
593
- function countDecimals(value) {
594
- if (!Number.isFinite(value))
595
- return 0;
596
- let e = 1, p = 0;
597
- while (Math.round(value * e) / e !== value) {
598
- e *= 10;
599
- p += 1;
600
- }
601
- return p;
602
- }
603
- var increment = (v, s) => decimalOperation(valueOf(v), "+", s);
604
- var decrement = (v, s) => decimalOperation(valueOf(v), "-", s);
605
- function snapToStep(value, step) {
606
- const num = valueOf(value);
607
- const p = countDecimals(step);
608
- const v = Math.round(num / step) * step;
609
- return round(v, p);
610
- }
611
- function valueOf(v) {
612
- if (typeof v === "number")
613
- return v;
614
- const num = parseFloat(v.toString().replace(/[^\w.-]+/g, ""));
615
- return !Number.isNaN(num) ? num : 0;
616
- }
617
- function decimalOperation(a, op, b) {
618
- let result = op === "+" ? a + b : a - b;
619
- if (a % 1 !== 0 || b % 1 !== 0) {
620
- const multiplier = 10 ** Math.max(countDecimals(a), countDecimals(b));
621
- a = Math.round(a * multiplier);
622
- b = Math.round(b * multiplier);
623
- result = op === "+" ? a + b : a - b;
624
- result /= multiplier;
625
- }
626
- return result;
627
- }
628
-
629
- // src/splitter.machine.ts
630
- var { not } = import_core.guards;
631
709
  function machine(userContext) {
632
710
  const ctx = compact(userContext);
633
711
  return (0, import_core.createMachine)(
@@ -636,32 +714,38 @@ function machine(userContext) {
636
714
  initial: "unknown",
637
715
  context: {
638
716
  orientation: "horizontal",
639
- min: 224,
640
- max: 340,
641
- step: 1,
642
- value: 256,
643
- snapOffset: 0,
717
+ activeResizeId: null,
718
+ previousPanels: [],
719
+ size: [],
720
+ initialSize: [],
721
+ activeResizeState: {
722
+ isAtMin: false,
723
+ isAtMax: false
724
+ },
644
725
  ...ctx
645
726
  },
727
+ created: ["setPreviousPanels", "setInitialSize"],
728
+ watch: {
729
+ size: ["setActiveResizeState"]
730
+ },
646
731
  computed: {
647
732
  isHorizontal: (ctx2) => ctx2.orientation === "horizontal",
648
- isAtMin: (ctx2) => ctx2.value === ctx2.min,
649
- isAtMax: (ctx2) => ctx2.value === ctx2.max
733
+ panels: (ctx2) => getNormalizedPanels(ctx2)
650
734
  },
651
735
  on: {
652
736
  COLLAPSE: {
653
- actions: "setToMin"
737
+ actions: "setStartPanelToMin"
654
738
  },
655
739
  EXPAND: {
656
- actions: "setToMax"
740
+ actions: "setStartPanelToMax"
657
741
  },
658
742
  TOGGLE: [
659
743
  {
660
- guard: "isCollapsed",
661
- actions: "setToMax"
744
+ guard: "isStartPanelAtMin",
745
+ actions: "setStartPanelToMax"
662
746
  },
663
747
  {
664
- actions: "setToMin"
748
+ actions: "setStartPanelToMin"
665
749
  }
666
750
  ]
667
751
  },
@@ -672,13 +756,19 @@ function machine(userContext) {
672
756
  }
673
757
  },
674
758
  idle: {
759
+ entry: ["clearActiveHandleId"],
675
760
  on: {
676
761
  POINTER_OVER: {
677
- guard: not("isFixed"),
678
- target: "hover:temp"
762
+ target: "hover:temp",
763
+ actions: ["setActiveHandleId"]
679
764
  },
680
- POINTER_LEAVE: "idle",
681
- FOCUS: "focused"
765
+ FOCUS: {
766
+ target: "focused",
767
+ actions: ["setActiveHandleId"]
768
+ },
769
+ DOUBLE_CLICK: {
770
+ actions: ["resetStartPanel", "setPreviousPanels"]
771
+ }
682
772
  }
683
773
  },
684
774
  "hover:temp": {
@@ -688,7 +778,7 @@ function machine(userContext) {
688
778
  on: {
689
779
  POINTER_DOWN: {
690
780
  target: "dragging",
691
- actions: ["invokeOnChangeStart"]
781
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
692
782
  },
693
783
  POINTER_LEAVE: "idle"
694
784
  }
@@ -698,7 +788,7 @@ function machine(userContext) {
698
788
  on: {
699
789
  POINTER_DOWN: {
700
790
  target: "dragging",
701
- actions: ["invokeOnChangeStart"]
791
+ actions: ["invokeOnResizeStart"]
702
792
  },
703
793
  POINTER_LEAVE: "idle"
704
794
  }
@@ -709,57 +799,50 @@ function machine(userContext) {
709
799
  BLUR: "idle",
710
800
  POINTER_DOWN: {
711
801
  target: "dragging",
712
- actions: ["invokeOnChangeStart"]
802
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
713
803
  },
714
804
  ARROW_LEFT: {
715
805
  guard: "isHorizontal",
716
- actions: "decrement"
806
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
717
807
  },
718
808
  ARROW_RIGHT: {
719
809
  guard: "isHorizontal",
720
- actions: "increment"
810
+ actions: ["expandStartPanel", "setPreviousPanels"]
721
811
  },
722
812
  ARROW_UP: {
723
813
  guard: "isVertical",
724
- actions: "increment"
814
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
725
815
  },
726
816
  ARROW_DOWN: {
727
817
  guard: "isVertical",
728
- actions: "decrement"
818
+ actions: ["expandStartPanel", "setPreviousPanels"]
729
819
  },
730
820
  ENTER: [
731
821
  {
732
- guard: "isCollapsed",
733
- actions: "setToMin"
822
+ guard: "isStartPanelAtMax",
823
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
734
824
  },
735
- { actions: "setToMin" }
825
+ { actions: ["setStartPanelToMax", "setPreviousPanels"] }
736
826
  ],
737
827
  HOME: {
738
- actions: "setToMin"
828
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
739
829
  },
740
830
  END: {
741
- actions: "setToMax"
742
- },
743
- DOUBLE_CLICK: [
744
- {
745
- guard: "isCollapsed",
746
- actions: "setToMax"
747
- },
748
- { actions: "setToMin" }
749
- ]
831
+ actions: ["setStartPanelToMax", "setPreviousPanels"]
832
+ }
750
833
  }
751
834
  },
752
835
  dragging: {
753
836
  tags: ["focus"],
754
- entry: "focusSplitter",
755
- activities: "trackPointerMove",
837
+ entry: "focusResizeHandle",
838
+ activities: ["trackPointerMove"],
756
839
  on: {
840
+ POINTER_MOVE: {
841
+ actions: ["setPointerValue", "setGlobalCursor"]
842
+ },
757
843
  POINTER_UP: {
758
844
  target: "focused",
759
- actions: ["invokeOnChangeEnd"]
760
- },
761
- POINTER_MOVE: {
762
- actions: "setPointerValue"
845
+ actions: ["invokeOnResizeEnd", "setPreviousPanels", "clearGlobalCursor", "blurResizeHandle"]
763
846
  }
764
847
  }
765
848
  }
@@ -772,70 +855,135 @@ function machine(userContext) {
772
855
  return trackPointerMove(doc, {
773
856
  onPointerMove(info) {
774
857
  send({ type: "POINTER_MOVE", point: info.point });
775
- doc.documentElement.style.cursor = dom.getCursor(ctx2);
776
858
  },
777
859
  onPointerUp() {
778
860
  send("POINTER_UP");
779
- doc.documentElement.style.cursor = "";
780
861
  }
781
862
  });
782
863
  }
783
864
  },
784
865
  guards: {
785
- isCollapsed: (ctx2) => ctx2.isAtMin,
866
+ isStartPanelAtMin: (ctx2) => ctx2.activeResizeState.isAtMin,
867
+ isStartPanelAtMax: (ctx2) => ctx2.activeResizeState.isAtMax,
786
868
  isHorizontal: (ctx2) => ctx2.isHorizontal,
787
- isVertical: (ctx2) => !ctx2.isHorizontal,
788
- isFixed: (ctx2) => !!ctx2.fixed
869
+ isVertical: (ctx2) => !ctx2.isHorizontal
789
870
  },
790
871
  delays: {
791
872
  HOVER_DELAY: 250
792
873
  },
793
874
  actions: {
794
- invokeOnChange(ctx2, evt) {
875
+ setGlobalCursor(ctx2) {
876
+ dom.setupGlobalCursor(ctx2);
877
+ },
878
+ clearGlobalCursor(ctx2) {
879
+ dom.removeGlobalCursor(ctx2);
880
+ },
881
+ invokeOnResize(ctx2) {
795
882
  var _a;
796
- if (evt.type !== "SETUP") {
797
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
798
- }
883
+ (_a = ctx2.onResize) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
799
884
  },
800
- invokeOnChangeStart(ctx2) {
885
+ invokeOnResizeStart(ctx2) {
801
886
  var _a;
802
- (_a = ctx2.onChangeStart) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
887
+ (_a = ctx2.onResizeStart) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
803
888
  },
804
- invokeOnChangeEnd(ctx2) {
889
+ invokeOnResizeEnd(ctx2) {
805
890
  var _a;
806
- (_a = ctx2.onChangeEnd) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
891
+ (_a = ctx2.onResizeEnd) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
892
+ },
893
+ setActiveHandleId(ctx2, evt) {
894
+ ctx2.activeResizeId = evt.id;
895
+ },
896
+ clearActiveHandleId(ctx2) {
897
+ ctx2.activeResizeId = null;
898
+ },
899
+ setInitialSize(ctx2) {
900
+ ctx2.initialSize = ctx2.panels.slice().map((panel) => ({
901
+ id: panel.id,
902
+ size: panel.size
903
+ }));
807
904
  },
808
- setToMin(ctx2) {
809
- ctx2.value = ctx2.min;
905
+ setStartPanelToMin(ctx2) {
906
+ const bounds = getPanelBounds(ctx2);
907
+ if (!bounds)
908
+ return;
909
+ const { before, after } = bounds;
910
+ ctx2.size[before.index].size = before.min;
911
+ ctx2.size[after.index].size = after.min;
810
912
  },
811
- setToMax(ctx2) {
812
- ctx2.value = ctx2.max;
913
+ setStartPanelToMax(ctx2) {
914
+ const bounds = getPanelBounds(ctx2);
915
+ if (!bounds)
916
+ return;
917
+ const { before, after } = bounds;
918
+ ctx2.size[before.index].size = before.max;
919
+ ctx2.size[after.index].size = after.max;
813
920
  },
814
- increment(ctx2, evt) {
815
- ctx2.value = clamp(increment(ctx2.value, evt.step), ctx2);
921
+ expandStartPanel(ctx2, evt) {
922
+ const bounds = getPanelBounds(ctx2);
923
+ if (!bounds)
924
+ return;
925
+ const { before, after } = bounds;
926
+ ctx2.size[before.index].size = before.up(evt.step);
927
+ ctx2.size[after.index].size = after.down(evt.step);
816
928
  },
817
- decrement(ctx2, evt) {
818
- ctx2.value = clamp(decrement(ctx2.value, evt.step), ctx2);
929
+ shrinkStartPanel(ctx2, evt) {
930
+ const bounds = getPanelBounds(ctx2);
931
+ if (!bounds)
932
+ return;
933
+ const { before, after } = bounds;
934
+ ctx2.size[before.index].size = before.down(evt.step);
935
+ ctx2.size[after.index].size = after.up(evt.step);
819
936
  },
820
- focusSplitter(ctx2) {
937
+ resetStartPanel(ctx2, evt) {
938
+ const bounds = getPanelBounds(ctx2, evt.id);
939
+ if (!bounds)
940
+ return;
941
+ const { before, after } = bounds;
942
+ ctx2.size[before.index].size = ctx2.initialSize[before.index].size;
943
+ ctx2.size[after.index].size = ctx2.initialSize[after.index].size;
944
+ },
945
+ focusResizeHandle(ctx2) {
946
+ raf(() => {
947
+ var _a;
948
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.focus();
949
+ });
950
+ },
951
+ blurResizeHandle(ctx2) {
821
952
  raf(() => {
822
953
  var _a;
823
- return (_a = dom.getSplitterEl(ctx2)) == null ? void 0 : _a.focus();
954
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.blur();
824
955
  });
825
956
  },
957
+ setPreviousPanels(ctx2) {
958
+ ctx2.previousPanels = ctx2.panels.slice();
959
+ },
960
+ setActiveResizeState(ctx2) {
961
+ const panels = getPanelBounds(ctx2);
962
+ if (!panels)
963
+ return;
964
+ const { before } = panels;
965
+ ctx2.activeResizeState = {
966
+ isAtMin: before.isAtMin,
967
+ isAtMax: before.isAtMax
968
+ };
969
+ },
826
970
  setPointerValue(ctx2, evt) {
827
- const el = dom.getPrimaryPaneEl(ctx2);
828
- if (!el)
971
+ const panels = getHandlePanels(ctx2);
972
+ const bounds = getHandleBounds(ctx2);
973
+ const rootEl = dom.getRootEl(ctx2);
974
+ if (!panels || !rootEl || !bounds)
829
975
  return;
830
- const relativePoint = getPointRelativeToNode(evt.point, el);
831
- let currentPoint = ctx2.isHorizontal ? relativePoint.x : relativePoint.y;
832
- let value = parseFloat(snapToStep(clamp(currentPoint, ctx2), ctx2.step));
833
- if (Math.abs(value - ctx2.min) <= ctx2.snapOffset) {
834
- value = ctx2.min;
835
- } else if (Math.abs(value - ctx2.max) <= ctx2.snapOffset) {
836
- value = ctx2.max;
837
- }
838
- ctx2.value = value;
976
+ const percent = getPointPercentRelativeToNode(evt.point, rootEl);
977
+ let pointValue = normalizePointValue(percent, ctx2);
978
+ ctx2.activeResizeState = {
979
+ isAtMin: pointValue < bounds.min,
980
+ isAtMax: pointValue > bounds.max
981
+ };
982
+ pointValue = clamp(pointValue, bounds.min, bounds.max);
983
+ const { before, after } = panels;
984
+ const offset = pointValue - before.end;
985
+ ctx2.size[before.index].size = before.size + offset;
986
+ ctx2.size[after.index].size = after.size - offset;
839
987
  }
840
988
  }
841
989
  }