@window-splitter/state 0.2.4 → 0.3.0
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/.turbo/turbo-build.log +4 -5
- package/.turbo/turbo-lint.log +9 -1
- package/.turbo/turbo-test.log +4717 -1160
- package/CHANGELOG.md +41 -0
- package/README.md +119 -1
- package/coverage/coverage-final.json +1 -1
- package/coverage/coverage-summary.json +3 -0
- package/coverage/index.html +19 -19
- package/coverage/index.ts.html +872 -377
- package/dist/commonjs/index.d.ts +22 -12
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +109 -25
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +22 -12
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +106 -25
- package/dist/esm/index.js.map +1 -1
- package/package.json +12 -9
- package/src/__snapshots__/machine.test.ts.snap +73 -0
- package/src/index.ts +151 -35
- package/src/machine.test.ts +327 -9
- package/src/utils.test.ts +86 -0
- package/vitest.config.ts +2 -0
- package/coverage/clover.xml +0 -363
package/src/index.ts
CHANGED
|
@@ -23,12 +23,12 @@ export type PercentUnit = `${number}%`;
|
|
|
23
23
|
export type Unit = PixelUnit | PercentUnit;
|
|
24
24
|
type Orientation = "horizontal" | "vertical";
|
|
25
25
|
|
|
26
|
-
interface ParsedPercentUnit {
|
|
26
|
+
export interface ParsedPercentUnit {
|
|
27
27
|
type: "percent";
|
|
28
28
|
value: Big.Big;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
interface ParsedPixelUnit {
|
|
31
|
+
export interface ParsedPixelUnit {
|
|
32
32
|
type: "pixel";
|
|
33
33
|
value: Big.Big;
|
|
34
34
|
}
|
|
@@ -88,6 +88,10 @@ export interface PanelData
|
|
|
88
88
|
onCollapseChange?: {
|
|
89
89
|
current: ((isCollapsed: boolean) => void) | null | undefined;
|
|
90
90
|
};
|
|
91
|
+
/** A ref to the latest "onResize" function provided by the user */
|
|
92
|
+
onResize?: {
|
|
93
|
+
current: OnResizeCallback | null | undefined;
|
|
94
|
+
};
|
|
91
95
|
/**
|
|
92
96
|
* The current value for the item in the grid
|
|
93
97
|
*/
|
|
@@ -113,8 +117,8 @@ function getCollapseAnimation(panel: PanelData) {
|
|
|
113
117
|
if (panel.collapseAnimation) {
|
|
114
118
|
if (typeof panel.collapseAnimation === "string") {
|
|
115
119
|
easeFn = collapseAnimations[panel.collapseAnimation];
|
|
116
|
-
} else
|
|
117
|
-
duration = panel.collapseAnimation.duration
|
|
120
|
+
} else {
|
|
121
|
+
duration = panel.collapseAnimation.duration;
|
|
118
122
|
easeFn =
|
|
119
123
|
typeof panel.collapseAnimation.easing === "function"
|
|
120
124
|
? panel.collapseAnimation.easing
|
|
@@ -178,7 +182,7 @@ export type InitializePanelHandleData = Omit<
|
|
|
178
182
|
PanelHandleData,
|
|
179
183
|
"type" | "size"
|
|
180
184
|
> & {
|
|
181
|
-
size: PixelUnit
|
|
185
|
+
size: PixelUnit;
|
|
182
186
|
};
|
|
183
187
|
|
|
184
188
|
interface RegisterPanelHandleEvent {
|
|
@@ -289,8 +293,6 @@ export interface GroupMachineContextValue {
|
|
|
289
293
|
orientation: Orientation;
|
|
290
294
|
/** How much the drag has overshot the handle */
|
|
291
295
|
dragOvershoot: Big.Big;
|
|
292
|
-
/** An id to use for autosaving the layout */
|
|
293
|
-
autosaveId?: string;
|
|
294
296
|
groupId: string;
|
|
295
297
|
}
|
|
296
298
|
|
|
@@ -320,6 +322,28 @@ type EventForType<T extends GroupMachineEvent["type"]> = Extract<
|
|
|
320
322
|
|
|
321
323
|
// #region Helpers
|
|
322
324
|
|
|
325
|
+
export function getCursor(
|
|
326
|
+
context: Pick<GroupMachineContextValue, "dragOvershoot" | "orientation">
|
|
327
|
+
) {
|
|
328
|
+
if (context.orientation === "horizontal") {
|
|
329
|
+
if (context.dragOvershoot.gt(0)) {
|
|
330
|
+
return "w-resize";
|
|
331
|
+
} else if (context.dragOvershoot.lt(0)) {
|
|
332
|
+
return "e-resize";
|
|
333
|
+
} else {
|
|
334
|
+
return "ew-resize";
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
if (context.dragOvershoot.gt(0)) {
|
|
338
|
+
return "n-resize";
|
|
339
|
+
} else if (context.dragOvershoot.lt(0)) {
|
|
340
|
+
return "s-resize";
|
|
341
|
+
} else {
|
|
342
|
+
return "ns-resize";
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
323
347
|
export function prepareSnapshot(snapshot: Snapshot<unknown>) {
|
|
324
348
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
325
349
|
const snapshotContext = (snapshot as any)
|
|
@@ -330,14 +354,8 @@ export function prepareSnapshot(snapshot: Snapshot<unknown>) {
|
|
|
330
354
|
for (const item of snapshotContext.items) {
|
|
331
355
|
if (isPanelData(item)) {
|
|
332
356
|
item.currentValue.value = new Big(item.currentValue.value);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
item.collapsedSize.value = new Big(item.collapsedSize.value);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (item.min) {
|
|
339
|
-
item.min.value = new Big(item.min.value);
|
|
340
|
-
}
|
|
357
|
+
item.collapsedSize.value = new Big(item.collapsedSize.value);
|
|
358
|
+
item.min.value = new Big(item.min.value);
|
|
341
359
|
|
|
342
360
|
if (item.max && item.max !== "1fr") {
|
|
343
361
|
item.max.value = new Big(item.max.value);
|
|
@@ -381,6 +399,13 @@ export function isPanelHandle(value: unknown): value is PanelHandleData {
|
|
|
381
399
|
);
|
|
382
400
|
}
|
|
383
401
|
|
|
402
|
+
type OnResizeSize = {
|
|
403
|
+
pixel: number;
|
|
404
|
+
percentage: number;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
export type OnResizeCallback = (size: OnResizeSize) => void;
|
|
408
|
+
|
|
384
409
|
interface InitializePanelOptions {
|
|
385
410
|
min?: Unit;
|
|
386
411
|
max?: Unit;
|
|
@@ -391,6 +416,9 @@ interface InitializePanelOptions {
|
|
|
391
416
|
onCollapseChange?: {
|
|
392
417
|
current: ((isCollapsed: boolean) => void) | null | undefined;
|
|
393
418
|
};
|
|
419
|
+
onResize?: {
|
|
420
|
+
current: OnResizeCallback | null | undefined;
|
|
421
|
+
};
|
|
394
422
|
collapseAnimation?: PanelData["collapseAnimation"];
|
|
395
423
|
defaultCollapsed?: boolean;
|
|
396
424
|
id?: string;
|
|
@@ -405,6 +433,25 @@ export function initializePanel(
|
|
|
405
433
|
export function initializePanel(
|
|
406
434
|
item: InitializePanelOptions | InitializePanelOptionsWithId
|
|
407
435
|
): PanelData | Omit<PanelData, "id"> {
|
|
436
|
+
const onResize = () => {
|
|
437
|
+
let lastCall: OnResizeSize | null = null;
|
|
438
|
+
|
|
439
|
+
// Memo-ize so we only call the callback once per size
|
|
440
|
+
return ((size) => {
|
|
441
|
+
if (
|
|
442
|
+
!lastCall ||
|
|
443
|
+
(lastCall.pixel === size.pixel &&
|
|
444
|
+
lastCall.percentage === size.percentage)
|
|
445
|
+
) {
|
|
446
|
+
lastCall = size;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
lastCall = size;
|
|
451
|
+
item.onResize?.current?.(size);
|
|
452
|
+
}) satisfies OnResizeCallback;
|
|
453
|
+
};
|
|
454
|
+
|
|
408
455
|
const data = {
|
|
409
456
|
type: "panel" as const,
|
|
410
457
|
min: parseUnit(item.min || "0px"),
|
|
@@ -415,6 +462,7 @@ export function initializePanel(
|
|
|
415
462
|
collapsible: item.collapsible,
|
|
416
463
|
collapsedSize: parseUnit(item.collapsedSize ?? "0px"),
|
|
417
464
|
onCollapseChange: item.onCollapseChange,
|
|
465
|
+
onResize: { current: onResize() },
|
|
418
466
|
collapseIsControlled: typeof item.collapsed !== "undefined",
|
|
419
467
|
sizeBeforeCollapse: undefined,
|
|
420
468
|
id: item.id,
|
|
@@ -432,7 +480,10 @@ export function initializePanelHandleData(item: InitializePanelHandleData) {
|
|
|
432
480
|
return {
|
|
433
481
|
type: "handle" as const,
|
|
434
482
|
...item,
|
|
435
|
-
size:
|
|
483
|
+
size:
|
|
484
|
+
typeof item.size === "string"
|
|
485
|
+
? (parseUnit(item.size) as ParsedPixelUnit)
|
|
486
|
+
: item.size,
|
|
436
487
|
};
|
|
437
488
|
}
|
|
438
489
|
|
|
@@ -469,7 +520,7 @@ export function getGroupSize(context: GroupMachineContextValue) {
|
|
|
469
520
|
}
|
|
470
521
|
|
|
471
522
|
/** Get the size of a panel in pixels */
|
|
472
|
-
|
|
523
|
+
function getUnitPixelValue(
|
|
473
524
|
context: GroupMachineContextValue,
|
|
474
525
|
unit: ParsedUnit | "1fr"
|
|
475
526
|
) {
|
|
@@ -695,6 +746,52 @@ function formatUnit(unit: ParsedUnit): Unit {
|
|
|
695
746
|
return `${unit.value.toNumber()}%`;
|
|
696
747
|
}
|
|
697
748
|
|
|
749
|
+
export function getPanelGroupPixelSizes(context: GroupMachineContextValue) {
|
|
750
|
+
return prepareItems(context).map((i) =>
|
|
751
|
+
isPanelData(i)
|
|
752
|
+
? i.currentValue.value.toNumber()
|
|
753
|
+
: getUnitPixelValue(context, i.size).toNumber()
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
export function getPanelPixelSize(
|
|
758
|
+
context: GroupMachineContextValue,
|
|
759
|
+
panelId: string
|
|
760
|
+
) {
|
|
761
|
+
const p = getPanelWithId(
|
|
762
|
+
{ ...context, items: prepareItems(context) },
|
|
763
|
+
panelId
|
|
764
|
+
);
|
|
765
|
+
|
|
766
|
+
return p.currentValue.value.toNumber();
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
export function getPanelGroupPercentageSizes(
|
|
770
|
+
context: GroupMachineContextValue
|
|
771
|
+
) {
|
|
772
|
+
const clamped = commitLayout({
|
|
773
|
+
...context,
|
|
774
|
+
items: prepareItems(context),
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
return clamped.map((i) => {
|
|
778
|
+
if (isPanelHandle(i)) {
|
|
779
|
+
return getUnitPercentageValue(getGroupSize(context), i.size);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return getUnitPercentageValue(getGroupSize(context), i.currentValue);
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
export function getPanelPercentageSize(
|
|
787
|
+
context: GroupMachineContextValue,
|
|
788
|
+
panelId: string
|
|
789
|
+
) {
|
|
790
|
+
const items = prepareItems(context);
|
|
791
|
+
const p = getPanelWithId({ ...context, items }, panelId);
|
|
792
|
+
return getUnitPercentageValue(getGroupSize(context), p.currentValue);
|
|
793
|
+
}
|
|
794
|
+
|
|
698
795
|
/** Build the grid template from the item values. */
|
|
699
796
|
export function buildTemplate(context: GroupMachineContextValue) {
|
|
700
797
|
const staticWidth = getStaticWidth(context);
|
|
@@ -708,10 +805,6 @@ export function buildTemplate(context: GroupMachineContextValue) {
|
|
|
708
805
|
item.currentValue.type === "pixel" &&
|
|
709
806
|
item.currentValue.value.toNumber() !== -1
|
|
710
807
|
) {
|
|
711
|
-
if (item.currentValue.value.toNumber() < 0) {
|
|
712
|
-
return "0px";
|
|
713
|
-
}
|
|
714
|
-
|
|
715
808
|
return formatUnit(item.currentValue);
|
|
716
809
|
} else if (item.currentValue.type === "percent") {
|
|
717
810
|
const max = item.max === "1fr" ? "100%" : formatUnit(item.max);
|
|
@@ -1071,7 +1164,7 @@ function updateLayout(
|
|
|
1071
1164
|
)
|
|
1072
1165
|
);
|
|
1073
1166
|
|
|
1074
|
-
if (leftoverSpace.
|
|
1167
|
+
if (!leftoverSpace.eq(0)) {
|
|
1075
1168
|
panelBefore.currentValue.value =
|
|
1076
1169
|
panelBefore.currentValue.value.add(leftoverSpace);
|
|
1077
1170
|
}
|
|
@@ -1080,7 +1173,7 @@ function updateLayout(
|
|
|
1080
1173
|
}
|
|
1081
1174
|
|
|
1082
1175
|
/** Converts the items to percentages */
|
|
1083
|
-
|
|
1176
|
+
function commitLayout(context: GroupMachineContextValue) {
|
|
1084
1177
|
const newItems = [...context.items];
|
|
1085
1178
|
|
|
1086
1179
|
// First set all the static width
|
|
@@ -1120,11 +1213,11 @@ export function commitLayout(context: GroupMachineContextValue) {
|
|
|
1120
1213
|
|
|
1121
1214
|
export function dragHandlePayload({
|
|
1122
1215
|
delta,
|
|
1123
|
-
orientation,
|
|
1216
|
+
orientation = "horizontal",
|
|
1124
1217
|
shiftKey = false,
|
|
1125
1218
|
}: {
|
|
1126
1219
|
delta: number;
|
|
1127
|
-
orientation
|
|
1220
|
+
orientation?: Orientation;
|
|
1128
1221
|
shiftKey?: boolean;
|
|
1129
1222
|
}) {
|
|
1130
1223
|
return {
|
|
@@ -1308,7 +1401,6 @@ export const groupMachine = createMachine(
|
|
|
1308
1401
|
context: {} as GroupMachineContextValue,
|
|
1309
1402
|
events: {} as GroupMachineEvent,
|
|
1310
1403
|
input: {} as {
|
|
1311
|
-
autosaveId?: string;
|
|
1312
1404
|
orientation?: Orientation;
|
|
1313
1405
|
groupId: string;
|
|
1314
1406
|
initialItems?: Item[];
|
|
@@ -1319,7 +1411,6 @@ export const groupMachine = createMachine(
|
|
|
1319
1411
|
items: input.initialItems || [],
|
|
1320
1412
|
orientation: input.orientation || "horizontal",
|
|
1321
1413
|
dragOvershoot: new Big(0),
|
|
1322
|
-
autosaveId: input.autosaveId,
|
|
1323
1414
|
groupId: input.groupId,
|
|
1324
1415
|
}),
|
|
1325
1416
|
states: {
|
|
@@ -1328,7 +1419,13 @@ export const groupMachine = createMachine(
|
|
|
1328
1419
|
setActualItemsSize: { actions: ["recordActualItemSize"] },
|
|
1329
1420
|
dragHandleStart: { target: "dragging" },
|
|
1330
1421
|
setPanelPixelSize: {
|
|
1331
|
-
actions: [
|
|
1422
|
+
actions: [
|
|
1423
|
+
"prepare",
|
|
1424
|
+
"onSetPanelSize",
|
|
1425
|
+
"commit",
|
|
1426
|
+
"onResize",
|
|
1427
|
+
"onAutosave",
|
|
1428
|
+
],
|
|
1332
1429
|
},
|
|
1333
1430
|
collapsePanel: [
|
|
1334
1431
|
{
|
|
@@ -1349,7 +1446,7 @@ export const groupMachine = createMachine(
|
|
|
1349
1446
|
dragging: {
|
|
1350
1447
|
entry: ["prepare"],
|
|
1351
1448
|
on: {
|
|
1352
|
-
dragHandle: { actions: ["onDragHandle"] },
|
|
1449
|
+
dragHandle: { actions: ["onDragHandle", "onResize"] },
|
|
1353
1450
|
dragHandleEnd: { target: "idle" },
|
|
1354
1451
|
collapsePanel: {
|
|
1355
1452
|
guard: "shouldCollapseToggle",
|
|
@@ -1373,24 +1470,30 @@ export const groupMachine = createMachine(
|
|
|
1373
1470
|
},
|
|
1374
1471
|
},
|
|
1375
1472
|
on: {
|
|
1376
|
-
applyDelta: { actions: ["onApplyDelta"] },
|
|
1473
|
+
applyDelta: { actions: ["onApplyDelta", "onResize"] },
|
|
1377
1474
|
},
|
|
1378
1475
|
},
|
|
1379
1476
|
},
|
|
1380
1477
|
on: {
|
|
1381
1478
|
registerPanel: { actions: ["assignPanelData"] },
|
|
1382
1479
|
registerDynamicPanel: {
|
|
1383
|
-
actions: [
|
|
1480
|
+
actions: [
|
|
1481
|
+
"prepare",
|
|
1482
|
+
"onRegisterDynamicPanel",
|
|
1483
|
+
"commit",
|
|
1484
|
+
"onResize",
|
|
1485
|
+
"onAutosave",
|
|
1486
|
+
],
|
|
1384
1487
|
},
|
|
1385
1488
|
unregisterPanel: {
|
|
1386
|
-
actions: ["prepare", "removeItem", "commit", "onAutosave"],
|
|
1489
|
+
actions: ["prepare", "removeItem", "commit", "onResize", "onAutosave"],
|
|
1387
1490
|
},
|
|
1388
1491
|
registerPanelHandle: { actions: ["assignPanelHandleData"] },
|
|
1389
1492
|
unregisterPanelHandle: {
|
|
1390
|
-
actions: ["prepare", "removeItem", "commit", "onAutosave"],
|
|
1493
|
+
actions: ["prepare", "removeItem", "commit", "onResize", "onAutosave"],
|
|
1391
1494
|
},
|
|
1392
|
-
setSize: { actions: ["updateSize"] },
|
|
1393
|
-
setOrientation: { actions: ["updateOrientation"] },
|
|
1495
|
+
setSize: { actions: ["updateSize", "onResize"] },
|
|
1496
|
+
setOrientation: { actions: ["updateOrientation", "onResize"] },
|
|
1394
1497
|
},
|
|
1395
1498
|
},
|
|
1396
1499
|
{
|
|
@@ -1630,6 +1733,19 @@ export const groupMachine = createMachine(
|
|
|
1630
1733
|
})
|
|
1631
1734
|
);
|
|
1632
1735
|
}),
|
|
1736
|
+
onResize: ({ context }) => {
|
|
1737
|
+
for (const item of context.items) {
|
|
1738
|
+
if (isPanelData(item)) {
|
|
1739
|
+
item.onResize?.current?.({
|
|
1740
|
+
pixel: getUnitPixelValue(context, item.currentValue).toNumber(),
|
|
1741
|
+
percentage: getUnitPercentageValue(
|
|
1742
|
+
getGroupSize(context),
|
|
1743
|
+
item.currentValue
|
|
1744
|
+
),
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
},
|
|
1633
1749
|
},
|
|
1634
1750
|
}
|
|
1635
1751
|
);
|