@destyler/splitter 0.0.7-beta.7 → 0.0.7-beta.9

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 DELETED
@@ -1,638 +0,0 @@
1
- import { createAnatomy } from '@zag-js/anatomy';
2
- import { getEventStep, getEventKey, getRelativePoint, trackPointerMove } from '@zag-js/dom-event';
3
- import { createScope, queryAll, dataAttr, raf } from '@zag-js/dom-query';
4
- import { createMachine } from '@zag-js/core';
5
- import { compact, createSplitProps } from '@zag-js/utils';
6
- import { createProps } from '@zag-js/types';
7
-
8
- const anatomy = createAnatomy("splitter").parts("root", "panel", "resizeTrigger");
9
- const parts = anatomy.build();
10
-
11
- const dom = createScope({
12
- getRootId: (ctx) => ctx.ids?.root ?? `splitter:${ctx.id}`,
13
- getResizeTriggerId: (ctx, id) => ctx.ids?.resizeTrigger?.(id) ?? `splitter:${ctx.id}:splitter:${id}`,
14
- getLabelId: (ctx) => ctx.ids?.label ?? `splitter:${ctx.id}:label`,
15
- getPanelId: (ctx, id) => ctx.ids?.panel?.(id) ?? `splitter:${ctx.id}:panel:${id}`,
16
- getGlobalCursorId: (ctx) => `splitter:${ctx.id}:global-cursor`,
17
- getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
18
- getResizeTriggerEl: (ctx, id) => dom.getById(ctx, dom.getResizeTriggerId(ctx, id)),
19
- getPanelEl: (ctx, id) => dom.getById(ctx, dom.getPanelId(ctx, id)),
20
- getCursor(ctx) {
21
- const x = ctx.isHorizontal;
22
- let cursor = x ? "col-resize" : "row-resize";
23
- if (ctx.activeResizeState.isAtMin)
24
- cursor = x ? "e-resize" : "s-resize";
25
- if (ctx.activeResizeState.isAtMax)
26
- cursor = x ? "w-resize" : "n-resize";
27
- return cursor;
28
- },
29
- getPanelStyle(ctx, id) {
30
- const flexGrow = ctx.panels.find((panel) => panel.id === id)?.size ?? "0";
31
- return {
32
- flexBasis: 0,
33
- flexGrow,
34
- flexShrink: 1,
35
- overflow: "hidden"
36
- };
37
- },
38
- getActiveHandleEl(ctx) {
39
- const activeId = ctx.activeResizeId;
40
- if (activeId == null)
41
- return;
42
- return dom.getById(ctx, dom.getResizeTriggerId(ctx, activeId));
43
- },
44
- getResizeTriggerEls(ctx) {
45
- const ownerId = CSS.escape(dom.getRootId(ctx));
46
- return queryAll(dom.getRootEl(ctx), `[role=separator][data-ownedby='${ownerId}']`);
47
- },
48
- setupGlobalCursor(ctx) {
49
- const styleEl = dom.getById(ctx, dom.getGlobalCursorId(ctx));
50
- const textContent = `* { cursor: ${dom.getCursor(ctx)} !important; }`;
51
- if (styleEl) {
52
- styleEl.textContent = textContent;
53
- } else {
54
- const style = dom.getDoc(ctx).createElement("style");
55
- style.id = dom.getGlobalCursorId(ctx);
56
- style.textContent = textContent;
57
- dom.getDoc(ctx).head.appendChild(style);
58
- }
59
- },
60
- removeGlobalCursor(ctx) {
61
- dom.getById(ctx, dom.getGlobalCursorId(ctx))?.remove();
62
- }
63
- });
64
-
65
- function validateSize(key, size) {
66
- if (Math.floor(size) > 100) {
67
- throw new Error(`Total ${key} of panels cannot be greater than 100`);
68
- }
69
- }
70
- function getNormalizedPanels(ctx) {
71
- let numOfPanelsWithoutSize = 0;
72
- let totalSize = 0;
73
- let totalMinSize = 0;
74
- const panels = ctx.size.map((panel) => {
75
- const minSize = panel.minSize ?? 0;
76
- const maxSize = panel.maxSize ?? 100;
77
- totalMinSize += minSize;
78
- if (panel.size == null) {
79
- numOfPanelsWithoutSize++;
80
- } else {
81
- totalSize += panel.size;
82
- }
83
- return {
84
- ...panel,
85
- minSize,
86
- maxSize
87
- };
88
- });
89
- validateSize("minSize", totalMinSize);
90
- validateSize("size", totalSize);
91
- let end = 0;
92
- let remainingSize = 0;
93
- const result = panels.map((panel) => {
94
- const start = end;
95
- if (panel.size != null) {
96
- end += panel.size;
97
- remainingSize = panel.size - panel.minSize;
98
- return {
99
- ...panel,
100
- start,
101
- end,
102
- remainingSize
103
- };
104
- }
105
- const size = (100 - totalSize) / numOfPanelsWithoutSize;
106
- end += size;
107
- remainingSize = size - panel.minSize;
108
- return { ...panel, size, start, end, remainingSize };
109
- });
110
- return result;
111
- }
112
- function getHandlePanels(ctx, id = ctx.activeResizeId) {
113
- const [beforeId, afterId] = id?.split(":") ?? [];
114
- if (!beforeId || !afterId)
115
- return;
116
- const beforeIndex = ctx.previousPanels.findIndex((panel) => panel.id === beforeId);
117
- const afterIndex = ctx.previousPanels.findIndex((panel) => panel.id === afterId);
118
- if (beforeIndex === -1 || afterIndex === -1)
119
- return;
120
- const before = ctx.previousPanels[beforeIndex];
121
- const after = ctx.previousPanels[afterIndex];
122
- return {
123
- before: {
124
- ...before,
125
- index: beforeIndex
126
- },
127
- after: {
128
- ...after,
129
- index: afterIndex
130
- }
131
- };
132
- }
133
- function getHandleBounds(ctx, id = ctx.activeResizeId) {
134
- const panels = getHandlePanels(ctx, id);
135
- if (!panels)
136
- return;
137
- const { before, after } = panels;
138
- return {
139
- min: Math.max(before.start + before.minSize, after.end - after.maxSize),
140
- max: Math.min(after.end - after.minSize, before.maxSize + before.start)
141
- };
142
- }
143
- function getPanelBounds(ctx, id) {
144
- const bounds = getHandleBounds(ctx, id);
145
- const panels = getHandlePanels(ctx, id);
146
- if (!bounds || !panels)
147
- return;
148
- const { before, after } = panels;
149
- const beforeMin = Math.abs(before.start - bounds.min);
150
- const afterMin = after.size + (before.size - beforeMin);
151
- const beforeMax = Math.abs(before.start - bounds.max);
152
- const afterMax = after.size - (beforeMax - before.size);
153
- return {
154
- before: {
155
- index: before.index,
156
- min: beforeMin,
157
- max: beforeMax,
158
- isAtMin: beforeMin === before.size,
159
- isAtMax: beforeMax === before.size,
160
- up(step) {
161
- return Math.min(before.size + step, beforeMax);
162
- },
163
- down(step) {
164
- return Math.max(before.size - step, beforeMin);
165
- }
166
- },
167
- after: {
168
- index: after.index,
169
- min: afterMin,
170
- max: afterMax,
171
- isAtMin: afterMin === after.size,
172
- isAtMax: afterMax === after.size,
173
- up(step) {
174
- return Math.min(after.size + step, afterMin);
175
- },
176
- down(step) {
177
- return Math.max(after.size - step, afterMax);
178
- }
179
- }
180
- };
181
- }
182
- function clamp(value, min, max) {
183
- return Math.min(Math.max(value, min), max);
184
- }
185
-
186
- function connect(state, send, normalize) {
187
- const horizontal = state.context.isHorizontal;
188
- const focused = state.hasTag("focus");
189
- const dragging = state.matches("dragging");
190
- const panels = state.context.panels;
191
- function getResizeTriggerState(props) {
192
- const { id, disabled } = props;
193
- const ids = id.split(":");
194
- const panelIds = ids.map((id2) => dom.getPanelId(state.context, id2));
195
- const panels2 = getHandleBounds(state.context, id);
196
- return {
197
- disabled: !!disabled,
198
- focused: state.context.activeResizeId === id && focused,
199
- panelIds,
200
- min: panels2?.min,
201
- max: panels2?.max,
202
- value: 0
203
- };
204
- }
205
- return {
206
- focused,
207
- dragging,
208
- getResizeTriggerState,
209
- bounds: getHandleBounds(state.context),
210
- setToMinSize(id) {
211
- const panel = panels.find((panel2) => panel2.id === id);
212
- send({ type: "SET_PANEL_SIZE", id, size: panel?.minSize, src: "setToMinSize" });
213
- },
214
- setToMaxSize(id) {
215
- const panel = panels.find((panel2) => panel2.id === id);
216
- send({ type: "SET_PANEL_SIZE", id, size: panel?.maxSize, src: "setToMaxSize" });
217
- },
218
- setSize(id, size) {
219
- send({ type: "SET_PANEL_SIZE", id, size });
220
- },
221
- getRootProps() {
222
- return normalize.element({
223
- ...parts.root.attrs,
224
- "data-orientation": state.context.orientation,
225
- "id": dom.getRootId(state.context),
226
- "dir": state.context.dir,
227
- "style": {
228
- display: "flex",
229
- flexDirection: horizontal ? "row" : "column",
230
- height: "100%",
231
- width: "100%",
232
- overflow: "hidden"
233
- }
234
- });
235
- },
236
- getPanelProps(props) {
237
- const { id } = props;
238
- return normalize.element({
239
- ...parts.panel.attrs,
240
- "data-orientation": state.context.orientation,
241
- "dir": state.context.dir,
242
- "id": dom.getPanelId(state.context, id),
243
- "data-ownedby": dom.getRootId(state.context),
244
- "style": dom.getPanelStyle(state.context, id)
245
- });
246
- },
247
- getResizeTriggerProps(props) {
248
- const { id, disabled, step = 1 } = props;
249
- const triggerState = getResizeTriggerState(props);
250
- return normalize.element({
251
- ...parts.resizeTrigger.attrs,
252
- "dir": state.context.dir,
253
- "id": dom.getResizeTriggerId(state.context, id),
254
- "role": "separator",
255
- "data-ownedby": dom.getRootId(state.context),
256
- "tabIndex": disabled ? void 0 : 0,
257
- "aria-valuenow": triggerState.value,
258
- "aria-valuemin": triggerState.min,
259
- "aria-valuemax": triggerState.max,
260
- "data-orientation": state.context.orientation,
261
- "aria-orientation": state.context.orientation,
262
- "aria-controls": triggerState.panelIds.join(" "),
263
- "data-focus": dataAttr(triggerState.focused),
264
- "data-disabled": dataAttr(disabled),
265
- "style": {
266
- touchAction: "none",
267
- userSelect: "none",
268
- WebkitUserSelect: "none",
269
- flex: "0 0 auto",
270
- pointerEvents: dragging && !triggerState.focused ? "none" : void 0,
271
- cursor: horizontal ? "col-resize" : "row-resize",
272
- [horizontal ? "minHeight" : "minWidth"]: "0"
273
- },
274
- onPointerDown(event) {
275
- if (disabled) {
276
- event.preventDefault();
277
- return;
278
- }
279
- send({ type: "POINTER_DOWN", id });
280
- event.currentTarget.setPointerCapture(event.pointerId);
281
- event.preventDefault();
282
- event.stopPropagation();
283
- },
284
- onPointerUp(event) {
285
- if (disabled)
286
- return;
287
- if (event.currentTarget.hasPointerCapture(event.pointerId)) {
288
- event.currentTarget.releasePointerCapture(event.pointerId);
289
- }
290
- },
291
- onPointerOver() {
292
- if (disabled)
293
- return;
294
- send({ type: "POINTER_OVER", id });
295
- },
296
- onPointerLeave() {
297
- if (disabled)
298
- return;
299
- send({ type: "POINTER_LEAVE", id });
300
- },
301
- onBlur() {
302
- send("BLUR");
303
- },
304
- onFocus() {
305
- send({ type: "FOCUS", id });
306
- },
307
- onDoubleClick() {
308
- if (disabled)
309
- return;
310
- send({ type: "DOUBLE_CLICK", id });
311
- },
312
- onKeyDown(event) {
313
- if (event.defaultPrevented)
314
- return;
315
- if (disabled)
316
- return;
317
- const moveStep = getEventStep(event) * step;
318
- const keyMap = {
319
- Enter() {
320
- send("ENTER");
321
- },
322
- ArrowUp() {
323
- send({ type: "ARROW_UP", step: moveStep });
324
- },
325
- ArrowDown() {
326
- send({ type: "ARROW_DOWN", step: moveStep });
327
- },
328
- ArrowLeft() {
329
- send({ type: "ARROW_LEFT", step: moveStep });
330
- },
331
- ArrowRight() {
332
- send({ type: "ARROW_RIGHT", step: moveStep });
333
- },
334
- Home() {
335
- send("HOME");
336
- },
337
- End() {
338
- send("END");
339
- }
340
- };
341
- const key = getEventKey(event, state.context);
342
- const exec = keyMap[key];
343
- if (exec) {
344
- exec(event);
345
- event.preventDefault();
346
- }
347
- }
348
- });
349
- }
350
- };
351
- }
352
-
353
- function machine(userContext) {
354
- const ctx = compact(userContext);
355
- return createMachine(
356
- {
357
- id: "splitter",
358
- initial: "idle",
359
- context: {
360
- orientation: "horizontal",
361
- activeResizeId: null,
362
- previousPanels: [],
363
- size: [],
364
- initialSize: [],
365
- activeResizeState: {
366
- isAtMin: false,
367
- isAtMax: false
368
- },
369
- ...ctx
370
- },
371
- created: ["setPreviousPanels", "setInitialSize"],
372
- watch: {
373
- size: ["setActiveResizeState"]
374
- },
375
- computed: {
376
- isHorizontal: (ctx2) => ctx2.orientation === "horizontal",
377
- panels: (ctx2) => getNormalizedPanels(ctx2)
378
- },
379
- on: {
380
- SET_PANEL_SIZE: {
381
- actions: "setPanelSize"
382
- }
383
- },
384
- states: {
385
- "idle": {
386
- entry: ["clearActiveHandleId"],
387
- on: {
388
- POINTER_OVER: {
389
- target: "hover:temp",
390
- actions: ["setActiveHandleId"]
391
- },
392
- FOCUS: {
393
- target: "focused",
394
- actions: ["setActiveHandleId"]
395
- },
396
- DOUBLE_CLICK: {
397
- actions: ["resetStartPanel", "setPreviousPanels"]
398
- }
399
- }
400
- },
401
- "hover:temp": {
402
- after: {
403
- HOVER_DELAY: "hover"
404
- },
405
- on: {
406
- POINTER_DOWN: {
407
- target: "dragging",
408
- actions: ["setActiveHandleId"]
409
- },
410
- POINTER_LEAVE: "idle"
411
- }
412
- },
413
- "hover": {
414
- tags: ["focus"],
415
- on: {
416
- POINTER_DOWN: "dragging",
417
- POINTER_LEAVE: "idle"
418
- }
419
- },
420
- "focused": {
421
- tags: ["focus"],
422
- on: {
423
- BLUR: "idle",
424
- POINTER_DOWN: {
425
- target: "dragging",
426
- actions: ["setActiveHandleId"]
427
- },
428
- ARROW_LEFT: {
429
- guard: "isHorizontal",
430
- actions: ["shrinkStartPanel", "setPreviousPanels"]
431
- },
432
- ARROW_RIGHT: {
433
- guard: "isHorizontal",
434
- actions: ["expandStartPanel", "setPreviousPanels"]
435
- },
436
- ARROW_UP: {
437
- guard: "isVertical",
438
- actions: ["shrinkStartPanel", "setPreviousPanels"]
439
- },
440
- ARROW_DOWN: {
441
- guard: "isVertical",
442
- actions: ["expandStartPanel", "setPreviousPanels"]
443
- },
444
- ENTER: [
445
- {
446
- guard: "isStartPanelAtMax",
447
- actions: ["setStartPanelToMin", "setPreviousPanels"]
448
- },
449
- { actions: ["setStartPanelToMax", "setPreviousPanels"] }
450
- ],
451
- HOME: {
452
- actions: ["setStartPanelToMin", "setPreviousPanels"]
453
- },
454
- END: {
455
- actions: ["setStartPanelToMax", "setPreviousPanels"]
456
- }
457
- }
458
- },
459
- "dragging": {
460
- tags: ["focus"],
461
- entry: "focusResizeHandle",
462
- activities: ["trackPointerMove"],
463
- on: {
464
- POINTER_MOVE: {
465
- actions: ["setPointerValue", "setGlobalCursor", "invokeOnResize"]
466
- },
467
- POINTER_UP: {
468
- target: "focused",
469
- actions: ["setPreviousPanels", "clearGlobalCursor", "blurResizeHandle", "invokeOnResizeEnd"]
470
- }
471
- }
472
- }
473
- }
474
- },
475
- {
476
- activities: {
477
- trackPointerMove: (ctx2, _evt, { send }) => {
478
- const doc = dom.getDoc(ctx2);
479
- return trackPointerMove(doc, {
480
- onPointerMove(info) {
481
- send({ type: "POINTER_MOVE", point: info.point });
482
- },
483
- onPointerUp() {
484
- send("POINTER_UP");
485
- }
486
- });
487
- }
488
- },
489
- guards: {
490
- isStartPanelAtMin: (ctx2) => ctx2.activeResizeState.isAtMin,
491
- isStartPanelAtMax: (ctx2) => ctx2.activeResizeState.isAtMax,
492
- isHorizontal: (ctx2) => ctx2.isHorizontal,
493
- isVertical: (ctx2) => !ctx2.isHorizontal
494
- },
495
- delays: {
496
- HOVER_DELAY: 250
497
- },
498
- actions: {
499
- setGlobalCursor(ctx2) {
500
- dom.setupGlobalCursor(ctx2);
501
- },
502
- clearGlobalCursor(ctx2) {
503
- dom.removeGlobalCursor(ctx2);
504
- },
505
- invokeOnResize(ctx2) {
506
- ctx2.onSizeChange?.({ size: Array.from(ctx2.size), activeHandleId: ctx2.activeResizeId });
507
- },
508
- invokeOnResizeEnd(ctx2) {
509
- ctx2.onSizeChangeEnd?.({ size: Array.from(ctx2.size), activeHandleId: ctx2.activeResizeId });
510
- },
511
- setActiveHandleId(ctx2, evt) {
512
- ctx2.activeResizeId = evt.id;
513
- },
514
- clearActiveHandleId(ctx2) {
515
- ctx2.activeResizeId = null;
516
- },
517
- setInitialSize(ctx2) {
518
- ctx2.initialSize = ctx2.panels.slice().map((panel) => ({
519
- id: panel.id,
520
- size: panel.size
521
- }));
522
- },
523
- setPanelSize(ctx2, evt) {
524
- const { id, size } = evt;
525
- ctx2.size = ctx2.size.map((panel) => {
526
- const panelSize = clamp(size, panel.minSize ?? 0, panel.maxSize ?? 100);
527
- return panel.id === id ? { ...panel, size: panelSize } : panel;
528
- });
529
- },
530
- setStartPanelToMin(ctx2) {
531
- const bounds = getPanelBounds(ctx2);
532
- if (!bounds)
533
- return;
534
- const { before, after } = bounds;
535
- ctx2.size[before.index].size = before.min;
536
- ctx2.size[after.index].size = after.min;
537
- },
538
- setStartPanelToMax(ctx2) {
539
- const bounds = getPanelBounds(ctx2);
540
- if (!bounds)
541
- return;
542
- const { before, after } = bounds;
543
- ctx2.size[before.index].size = before.max;
544
- ctx2.size[after.index].size = after.max;
545
- },
546
- expandStartPanel(ctx2, evt) {
547
- const bounds = getPanelBounds(ctx2);
548
- if (!bounds)
549
- return;
550
- const { before, after } = bounds;
551
- ctx2.size[before.index].size = before.up(evt.step);
552
- ctx2.size[after.index].size = after.down(evt.step);
553
- },
554
- shrinkStartPanel(ctx2, evt) {
555
- const bounds = getPanelBounds(ctx2);
556
- if (!bounds)
557
- return;
558
- const { before, after } = bounds;
559
- ctx2.size[before.index].size = before.down(evt.step);
560
- ctx2.size[after.index].size = after.up(evt.step);
561
- },
562
- resetStartPanel(ctx2, evt) {
563
- const bounds = getPanelBounds(ctx2, evt.id);
564
- if (!bounds)
565
- return;
566
- const { before, after } = bounds;
567
- ctx2.size[before.index].size = ctx2.initialSize[before.index].size;
568
- ctx2.size[after.index].size = ctx2.initialSize[after.index].size;
569
- },
570
- focusResizeHandle(ctx2) {
571
- raf(() => {
572
- dom.getActiveHandleEl(ctx2)?.focus({ preventScroll: true });
573
- });
574
- },
575
- blurResizeHandle(ctx2) {
576
- raf(() => {
577
- dom.getActiveHandleEl(ctx2)?.blur();
578
- });
579
- },
580
- setPreviousPanels(ctx2) {
581
- ctx2.previousPanels = ctx2.panels.slice();
582
- },
583
- setActiveResizeState(ctx2) {
584
- const panels = getPanelBounds(ctx2);
585
- if (!panels)
586
- return;
587
- const { before } = panels;
588
- ctx2.activeResizeState = {
589
- isAtMin: before.isAtMin,
590
- isAtMax: before.isAtMax
591
- };
592
- },
593
- setPointerValue(ctx2, evt) {
594
- const panels = getHandlePanels(ctx2);
595
- const bounds = getHandleBounds(ctx2);
596
- if (!panels || !bounds)
597
- return;
598
- const rootEl = dom.getRootEl(ctx2);
599
- if (!rootEl)
600
- return;
601
- const relativePoint = getRelativePoint(evt.point, rootEl);
602
- const percentValue = relativePoint.getPercentValue({
603
- dir: ctx2.dir,
604
- orientation: ctx2.orientation
605
- });
606
- let pointValue = percentValue * 100;
607
- ctx2.activeResizeState = {
608
- isAtMin: pointValue < bounds.min,
609
- isAtMax: pointValue > bounds.max
610
- };
611
- pointValue = clamp(pointValue, bounds.min, bounds.max);
612
- const { before, after } = panels;
613
- const offset = pointValue - before.end;
614
- ctx2.size[before.index].size = before.size + offset;
615
- ctx2.size[after.index].size = after.size - offset;
616
- }
617
- }
618
- }
619
- );
620
- }
621
-
622
- const props = createProps()([
623
- "dir",
624
- "getRootNode",
625
- "id",
626
- "ids",
627
- "onSizeChange",
628
- "onSizeChangeEnd",
629
- "orientation",
630
- "size"
631
- ]);
632
- const splitProps = createSplitProps(props);
633
- const panelProps = createProps()(["id", "snapSize"]);
634
- const splitPanelProps = createSplitProps(panelProps);
635
- const resizeTriggerProps = createProps()(["disabled", "id", "step"]);
636
- const splitResizeTriggerProps = createSplitProps(resizeTriggerProps);
637
-
638
- export { anatomy, connect, machine, panelProps, props, resizeTriggerProps, splitPanelProps, splitProps, splitResizeTriggerProps };