@zag-js/splitter 0.2.6 → 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.
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,339 @@ 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
558
  return {
427
- isCollapsed: isAtMin,
428
- isExpanded: isAtMax,
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(id) {
598
+ const ids = id.split(":");
599
+ const panelIds = ids.map((id2) => dom.getPanelId(state2.context, id2));
600
+ const panels = getHandleBounds(state2.context, id);
601
+ return {
602
+ isFocused: state2.context.activeResizeId === id && isFocused,
603
+ panelIds,
604
+ min: panels == null ? void 0 : panels.min,
605
+ max: panels == null ? void 0 : panels.max,
606
+ value: 0
607
+ };
608
+ },
609
+ getResizeTriggerProps(props) {
610
+ const { id, disabled, step = 1 } = props;
611
+ const triggerState = this.getResizeTriggerState(id);
612
+ return normalize.element({
613
+ ...parts.resizeTrigger.attrs,
614
+ dir: state2.context.dir,
615
+ id: dom.getResizeTriggerId(state2.context, id),
616
+ role: "separator",
617
+ "data-ownedby": dom.getRootId(state2.context),
618
+ tabIndex: disabled ? void 0 : 0,
619
+ "aria-valuenow": triggerState.value,
620
+ "aria-valuemin": triggerState.min,
621
+ "aria-valuemax": triggerState.max,
622
+ "data-orientation": state2.context.orientation,
623
+ "aria-orientation": state2.context.orientation,
624
+ "aria-controls": triggerState.panelIds.join(" "),
625
+ "data-focus": dataAttr(triggerState.isFocused),
626
+ "data-disabled": dataAttr(disabled),
627
+ style: {
628
+ touchAction: "none",
629
+ userSelect: "none",
630
+ flex: "0 0 auto",
631
+ pointerEvents: isDragging && !triggerState.isFocused ? "none" : void 0,
632
+ cursor: isHorizontal ? "col-resize" : "row-resize",
633
+ [isHorizontal ? "minHeight" : "minWidth"]: "0"
634
+ },
635
+ onPointerDown(event) {
636
+ if (disabled) {
637
+ event.preventDefault();
638
+ return;
567
639
  }
568
- };
569
- const key = getEventKey(event, state2.context);
570
- const exec = keyMap[key];
571
- if (exec) {
572
- exec(event);
640
+ send({ type: "POINTER_DOWN", id });
573
641
  event.preventDefault();
642
+ event.stopPropagation();
643
+ },
644
+ onPointerOver() {
645
+ if (disabled)
646
+ return;
647
+ send({ type: "POINTER_OVER", id });
648
+ },
649
+ onPointerLeave() {
650
+ if (disabled)
651
+ return;
652
+ send({ type: "POINTER_LEAVE", id });
653
+ },
654
+ onBlur() {
655
+ send("BLUR");
656
+ },
657
+ onFocus() {
658
+ send({ type: "FOCUS", id });
659
+ },
660
+ onDoubleClick() {
661
+ if (disabled)
662
+ return;
663
+ send({ type: "DOUBLE_CLICK", id });
664
+ },
665
+ onKeyDown(event) {
666
+ if (disabled)
667
+ return;
668
+ const moveStep = getEventStep(event) * step;
669
+ const keyMap = {
670
+ Enter() {
671
+ send("ENTER");
672
+ },
673
+ ArrowUp() {
674
+ send({ type: "ARROW_UP", step: moveStep });
675
+ },
676
+ ArrowDown() {
677
+ send({ type: "ARROW_DOWN", step: moveStep });
678
+ },
679
+ ArrowLeft() {
680
+ send({ type: "ARROW_LEFT", step: moveStep });
681
+ },
682
+ ArrowRight() {
683
+ send({ type: "ARROW_RIGHT", step: moveStep });
684
+ },
685
+ Home() {
686
+ send("HOME");
687
+ },
688
+ End() {
689
+ send("END");
690
+ }
691
+ };
692
+ const key = getEventKey(event, state2.context);
693
+ const exec = keyMap[key];
694
+ if (exec) {
695
+ exec(event);
696
+ event.preventDefault();
697
+ }
574
698
  }
575
- }
576
- })
699
+ });
700
+ }
577
701
  };
578
702
  }
579
703
 
580
704
  // src/splitter.machine.ts
581
705
  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
706
  function machine(userContext) {
632
707
  const ctx = compact(userContext);
633
708
  return (0, import_core.createMachine)(
@@ -636,32 +711,38 @@ function machine(userContext) {
636
711
  initial: "unknown",
637
712
  context: {
638
713
  orientation: "horizontal",
639
- min: 224,
640
- max: 340,
641
- step: 1,
642
- value: 256,
643
- snapOffset: 0,
714
+ activeResizeId: null,
715
+ previousPanels: [],
716
+ size: [],
717
+ initialSize: [],
718
+ activeResizeState: {
719
+ isAtMin: false,
720
+ isAtMax: false
721
+ },
644
722
  ...ctx
645
723
  },
724
+ created: ["setPreviousPanels", "setInitialSize"],
725
+ watch: {
726
+ size: ["setActiveResizeState"]
727
+ },
646
728
  computed: {
647
729
  isHorizontal: (ctx2) => ctx2.orientation === "horizontal",
648
- isAtMin: (ctx2) => ctx2.value === ctx2.min,
649
- isAtMax: (ctx2) => ctx2.value === ctx2.max
730
+ panels: (ctx2) => getNormalizedPanels(ctx2)
650
731
  },
651
732
  on: {
652
733
  COLLAPSE: {
653
- actions: "setToMin"
734
+ actions: "setStartPanelToMin"
654
735
  },
655
736
  EXPAND: {
656
- actions: "setToMax"
737
+ actions: "setStartPanelToMax"
657
738
  },
658
739
  TOGGLE: [
659
740
  {
660
- guard: "isCollapsed",
661
- actions: "setToMax"
741
+ guard: "isStartPanelAtMin",
742
+ actions: "setStartPanelToMax"
662
743
  },
663
744
  {
664
- actions: "setToMin"
745
+ actions: "setStartPanelToMin"
665
746
  }
666
747
  ]
667
748
  },
@@ -672,13 +753,19 @@ function machine(userContext) {
672
753
  }
673
754
  },
674
755
  idle: {
756
+ entry: ["clearActiveHandleId"],
675
757
  on: {
676
758
  POINTER_OVER: {
677
- guard: not("isFixed"),
678
- target: "hover:temp"
759
+ target: "hover:temp",
760
+ actions: ["setActiveHandleId"]
679
761
  },
680
- POINTER_LEAVE: "idle",
681
- FOCUS: "focused"
762
+ FOCUS: {
763
+ target: "focused",
764
+ actions: ["setActiveHandleId"]
765
+ },
766
+ DOUBLE_CLICK: {
767
+ actions: ["resetStartPanel", "setPreviousPanels"]
768
+ }
682
769
  }
683
770
  },
684
771
  "hover:temp": {
@@ -688,7 +775,7 @@ function machine(userContext) {
688
775
  on: {
689
776
  POINTER_DOWN: {
690
777
  target: "dragging",
691
- actions: ["invokeOnChangeStart"]
778
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
692
779
  },
693
780
  POINTER_LEAVE: "idle"
694
781
  }
@@ -698,7 +785,7 @@ function machine(userContext) {
698
785
  on: {
699
786
  POINTER_DOWN: {
700
787
  target: "dragging",
701
- actions: ["invokeOnChangeStart"]
788
+ actions: ["invokeOnResizeStart"]
702
789
  },
703
790
  POINTER_LEAVE: "idle"
704
791
  }
@@ -709,57 +796,50 @@ function machine(userContext) {
709
796
  BLUR: "idle",
710
797
  POINTER_DOWN: {
711
798
  target: "dragging",
712
- actions: ["invokeOnChangeStart"]
799
+ actions: ["setActiveHandleId", "invokeOnResizeStart"]
713
800
  },
714
801
  ARROW_LEFT: {
715
802
  guard: "isHorizontal",
716
- actions: "decrement"
803
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
717
804
  },
718
805
  ARROW_RIGHT: {
719
806
  guard: "isHorizontal",
720
- actions: "increment"
807
+ actions: ["expandStartPanel", "setPreviousPanels"]
721
808
  },
722
809
  ARROW_UP: {
723
810
  guard: "isVertical",
724
- actions: "increment"
811
+ actions: ["shrinkStartPanel", "setPreviousPanels"]
725
812
  },
726
813
  ARROW_DOWN: {
727
814
  guard: "isVertical",
728
- actions: "decrement"
815
+ actions: ["expandStartPanel", "setPreviousPanels"]
729
816
  },
730
817
  ENTER: [
731
818
  {
732
- guard: "isCollapsed",
733
- actions: "setToMin"
819
+ guard: "isStartPanelAtMax",
820
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
734
821
  },
735
- { actions: "setToMin" }
822
+ { actions: ["setStartPanelToMax", "setPreviousPanels"] }
736
823
  ],
737
824
  HOME: {
738
- actions: "setToMin"
825
+ actions: ["setStartPanelToMin", "setPreviousPanels"]
739
826
  },
740
827
  END: {
741
- actions: "setToMax"
742
- },
743
- DOUBLE_CLICK: [
744
- {
745
- guard: "isCollapsed",
746
- actions: "setToMax"
747
- },
748
- { actions: "setToMin" }
749
- ]
828
+ actions: ["setStartPanelToMax", "setPreviousPanels"]
829
+ }
750
830
  }
751
831
  },
752
832
  dragging: {
753
833
  tags: ["focus"],
754
- entry: "focusSplitter",
755
- activities: "trackPointerMove",
834
+ entry: "focusResizeHandle",
835
+ activities: ["trackPointerMove"],
756
836
  on: {
837
+ POINTER_MOVE: {
838
+ actions: ["setPointerValue", "setGlobalCursor"]
839
+ },
757
840
  POINTER_UP: {
758
841
  target: "focused",
759
- actions: ["invokeOnChangeEnd"]
760
- },
761
- POINTER_MOVE: {
762
- actions: "setPointerValue"
842
+ actions: ["invokeOnResizeEnd", "setPreviousPanels", "clearGlobalCursor", "blurResizeHandle"]
763
843
  }
764
844
  }
765
845
  }
@@ -772,70 +852,135 @@ function machine(userContext) {
772
852
  return trackPointerMove(doc, {
773
853
  onPointerMove(info) {
774
854
  send({ type: "POINTER_MOVE", point: info.point });
775
- doc.documentElement.style.cursor = dom.getCursor(ctx2);
776
855
  },
777
856
  onPointerUp() {
778
857
  send("POINTER_UP");
779
- doc.documentElement.style.cursor = "";
780
858
  }
781
859
  });
782
860
  }
783
861
  },
784
862
  guards: {
785
- isCollapsed: (ctx2) => ctx2.isAtMin,
863
+ isStartPanelAtMin: (ctx2) => ctx2.activeResizeState.isAtMin,
864
+ isStartPanelAtMax: (ctx2) => ctx2.activeResizeState.isAtMax,
786
865
  isHorizontal: (ctx2) => ctx2.isHorizontal,
787
- isVertical: (ctx2) => !ctx2.isHorizontal,
788
- isFixed: (ctx2) => !!ctx2.fixed
866
+ isVertical: (ctx2) => !ctx2.isHorizontal
789
867
  },
790
868
  delays: {
791
869
  HOVER_DELAY: 250
792
870
  },
793
871
  actions: {
794
- invokeOnChange(ctx2, evt) {
872
+ setGlobalCursor(ctx2) {
873
+ dom.setupGlobalCursor(ctx2);
874
+ },
875
+ clearGlobalCursor(ctx2) {
876
+ dom.removeGlobalCursor(ctx2);
877
+ },
878
+ invokeOnResize(ctx2) {
795
879
  var _a;
796
- if (evt.type !== "SETUP") {
797
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
798
- }
880
+ (_a = ctx2.onResize) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
799
881
  },
800
- invokeOnChangeStart(ctx2) {
882
+ invokeOnResizeStart(ctx2) {
801
883
  var _a;
802
- (_a = ctx2.onChangeStart) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
884
+ (_a = ctx2.onResizeStart) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
803
885
  },
804
- invokeOnChangeEnd(ctx2) {
886
+ invokeOnResizeEnd(ctx2) {
805
887
  var _a;
806
- (_a = ctx2.onChangeEnd) == null ? void 0 : _a.call(ctx2, { value: ctx2.value });
888
+ (_a = ctx2.onResizeEnd) == null ? void 0 : _a.call(ctx2, { size: ctx2.size, activeHandleId: ctx2.activeResizeId });
889
+ },
890
+ setActiveHandleId(ctx2, evt) {
891
+ ctx2.activeResizeId = evt.id;
892
+ },
893
+ clearActiveHandleId(ctx2) {
894
+ ctx2.activeResizeId = null;
895
+ },
896
+ setInitialSize(ctx2) {
897
+ ctx2.initialSize = ctx2.panels.slice().map((panel) => ({
898
+ id: panel.id,
899
+ size: panel.size
900
+ }));
807
901
  },
808
- setToMin(ctx2) {
809
- ctx2.value = ctx2.min;
902
+ setStartPanelToMin(ctx2) {
903
+ const bounds = getPanelBounds(ctx2);
904
+ if (!bounds)
905
+ return;
906
+ const { before, after } = bounds;
907
+ ctx2.size[before.index].size = before.min;
908
+ ctx2.size[after.index].size = after.min;
810
909
  },
811
- setToMax(ctx2) {
812
- ctx2.value = ctx2.max;
910
+ setStartPanelToMax(ctx2) {
911
+ const bounds = getPanelBounds(ctx2);
912
+ if (!bounds)
913
+ return;
914
+ const { before, after } = bounds;
915
+ ctx2.size[before.index].size = before.max;
916
+ ctx2.size[after.index].size = after.max;
813
917
  },
814
- increment(ctx2, evt) {
815
- ctx2.value = clamp(increment(ctx2.value, evt.step), ctx2);
918
+ expandStartPanel(ctx2, evt) {
919
+ const bounds = getPanelBounds(ctx2);
920
+ if (!bounds)
921
+ return;
922
+ const { before, after } = bounds;
923
+ ctx2.size[before.index].size = before.up(evt.step);
924
+ ctx2.size[after.index].size = after.down(evt.step);
816
925
  },
817
- decrement(ctx2, evt) {
818
- ctx2.value = clamp(decrement(ctx2.value, evt.step), ctx2);
926
+ shrinkStartPanel(ctx2, evt) {
927
+ const bounds = getPanelBounds(ctx2);
928
+ if (!bounds)
929
+ return;
930
+ const { before, after } = bounds;
931
+ ctx2.size[before.index].size = before.down(evt.step);
932
+ ctx2.size[after.index].size = after.up(evt.step);
819
933
  },
820
- focusSplitter(ctx2) {
934
+ resetStartPanel(ctx2, evt) {
935
+ const bounds = getPanelBounds(ctx2, evt.id);
936
+ if (!bounds)
937
+ return;
938
+ const { before, after } = bounds;
939
+ ctx2.size[before.index].size = ctx2.initialSize[before.index].size;
940
+ ctx2.size[after.index].size = ctx2.initialSize[after.index].size;
941
+ },
942
+ focusResizeHandle(ctx2) {
943
+ raf(() => {
944
+ var _a;
945
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.focus();
946
+ });
947
+ },
948
+ blurResizeHandle(ctx2) {
821
949
  raf(() => {
822
950
  var _a;
823
- return (_a = dom.getSplitterEl(ctx2)) == null ? void 0 : _a.focus();
951
+ (_a = dom.getActiveHandleEl(ctx2)) == null ? void 0 : _a.blur();
824
952
  });
825
953
  },
954
+ setPreviousPanels(ctx2) {
955
+ ctx2.previousPanels = ctx2.panels.slice();
956
+ },
957
+ setActiveResizeState(ctx2) {
958
+ const panels = getPanelBounds(ctx2);
959
+ if (!panels)
960
+ return;
961
+ const { before } = panels;
962
+ ctx2.activeResizeState = {
963
+ isAtMin: before.isAtMin,
964
+ isAtMax: before.isAtMax
965
+ };
966
+ },
826
967
  setPointerValue(ctx2, evt) {
827
- const el = dom.getPrimaryPaneEl(ctx2);
828
- if (!el)
968
+ const panels = getHandlePanels(ctx2);
969
+ const bounds = getHandleBounds(ctx2);
970
+ const rootEl = dom.getRootEl(ctx2);
971
+ if (!panels || !rootEl || !bounds)
829
972
  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;
973
+ const percent = getPointPercentRelativeToNode(evt.point, rootEl);
974
+ let pointValue = normalizePointValue(percent, ctx2);
975
+ ctx2.activeResizeState = {
976
+ isAtMin: pointValue < bounds.min,
977
+ isAtMax: pointValue > bounds.max
978
+ };
979
+ pointValue = clamp(pointValue, bounds.min, bounds.max);
980
+ const { before, after } = panels;
981
+ const offset = pointValue - before.end;
982
+ ctx2.size[before.index].size = before.size + offset;
983
+ ctx2.size[after.index].size = after.size - offset;
839
984
  }
840
985
  }
841
986
  }