@window-splitter/svelte 0.8.4
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/.storybook/main.ts +33 -0
- package/.storybook/preview.ts +14 -0
- package/.tshy/build.json +8 -0
- package/.tshy/commonjs.json +19 -0
- package/.tshy/esm.json +18 -0
- package/.turbo/turbo-build.log +6 -0
- package/CHANGELOG.md +20 -0
- package/README.md +58 -0
- package/dist/Panel.svelte +178 -0
- package/dist/Panel.svelte.d.ts +19 -0
- package/dist/Panel.svelte.d.ts.map +1 -0
- package/dist/PanelGroup.svelte +159 -0
- package/dist/PanelGroup.svelte.d.ts +18 -0
- package/dist/PanelGroup.svelte.d.ts.map +1 -0
- package/dist/PanelResizer.svelte +171 -0
- package/dist/PanelResizer.svelte.d.ts +8 -0
- package/dist/PanelResizer.svelte.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/eslint.config.js +24 -0
- package/package.json +92 -0
- package/src/SvelteWindowSplitter.test.svelte.ts +283 -0
- package/src/__snapshots__/SvelteWindowSplitter.test.svelte.ts.snap +56 -0
- package/src/__snapshots__/SvelteWindowSplitter.test.ts.snap +54 -0
- package/src/lib/Panel.svelte +178 -0
- package/src/lib/PanelGroup.svelte +159 -0
- package/src/lib/PanelResizer.svelte +171 -0
- package/src/lib/index.ts +3 -0
- package/src/stories/Autosave.svelte +52 -0
- package/src/stories/AutosaveCollapsible.svelte +65 -0
- package/src/stories/AutosaveCookie.svelte +63 -0
- package/src/stories/Collapsible.svelte +112 -0
- package/src/stories/Conditional.svelte +70 -0
- package/src/stories/DynamicConstraints.svelte +73 -0
- package/src/stories/Simple.svelte +48 -0
- package/src/stories/SvelteWindowSplitter.stories.svelte +468 -0
- package/src/stories/VerticalLayout.svelte +58 -0
- package/svelte.config.js +7 -0
- package/tsconfig.json +6 -0
- package/vite.config.js +7 -0
- package/vitest.config.js +19 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getContext } from "svelte";
|
|
3
|
+
import {
|
|
4
|
+
getCursor,
|
|
5
|
+
getGroupSize,
|
|
6
|
+
initializePanelHandleData,
|
|
7
|
+
isPanelData,
|
|
8
|
+
isPanelHandle,
|
|
9
|
+
getCollapsiblePanelForHandleId,
|
|
10
|
+
haveConstraintsChangedForPanelHandle,
|
|
11
|
+
} from "@window-splitter/state";
|
|
12
|
+
import type {
|
|
13
|
+
SendFn,
|
|
14
|
+
GroupMachineContextValue,
|
|
15
|
+
} from "@window-splitter/state";
|
|
16
|
+
import type { SharedPanelResizerProps } from "@window-splitter/interface";
|
|
17
|
+
import {
|
|
18
|
+
getPanelResizerDomAttributes,
|
|
19
|
+
move,
|
|
20
|
+
} from "@window-splitter/interface";
|
|
21
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
22
|
+
|
|
23
|
+
interface Props
|
|
24
|
+
extends SharedPanelResizerProps,
|
|
25
|
+
HTMLAttributes<HTMLDivElement> {}
|
|
26
|
+
|
|
27
|
+
let {
|
|
28
|
+
size = "0px",
|
|
29
|
+
id: _id,
|
|
30
|
+
onDragStart,
|
|
31
|
+
onDrag,
|
|
32
|
+
onDragEnd,
|
|
33
|
+
disabled,
|
|
34
|
+
...attrs
|
|
35
|
+
}: Props = $props();
|
|
36
|
+
|
|
37
|
+
const defaultId = $props.id();
|
|
38
|
+
const id = _id || defaultId;
|
|
39
|
+
const send = getContext<SendFn>("send");
|
|
40
|
+
const state = getContext<GroupMachineContextValue>("state");
|
|
41
|
+
const isPrerender = getContext<{ current: boolean }>("isPrerender");
|
|
42
|
+
const initHandle = () => initializePanelHandleData({ size, id });
|
|
43
|
+
const handleData = () => {
|
|
44
|
+
const item = state?.items.find((i) => i.id === id);
|
|
45
|
+
if (!item || !isPanelHandle(item)) return undefined;
|
|
46
|
+
return item;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
let dynamicPanelHandleIsMounting = false;
|
|
50
|
+
|
|
51
|
+
if (!handleData()) {
|
|
52
|
+
if (isPrerender.current) {
|
|
53
|
+
send({ type: "registerPanelHandle", data: initHandle() });
|
|
54
|
+
} else {
|
|
55
|
+
dynamicPanelHandleIsMounting = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
$effect(() => {
|
|
60
|
+
if (!dynamicPanelHandleIsMounting) return;
|
|
61
|
+
|
|
62
|
+
const groupElement = document.getElementById(state.groupId);
|
|
63
|
+
if (!groupElement) return;
|
|
64
|
+
|
|
65
|
+
const handleEl = document.getElementById(id);
|
|
66
|
+
if (!handleEl) return;
|
|
67
|
+
|
|
68
|
+
const order = Array.from(groupElement.children).indexOf(handleEl);
|
|
69
|
+
if (typeof order !== "number") return;
|
|
70
|
+
|
|
71
|
+
send({
|
|
72
|
+
type: "registerPanelHandle",
|
|
73
|
+
data: { ...initHandle(), order },
|
|
74
|
+
});
|
|
75
|
+
dynamicPanelHandleIsMounting = false;
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const contraintChanged = $derived(
|
|
79
|
+
!dynamicPanelHandleIsMounting &&
|
|
80
|
+
haveConstraintsChangedForPanelHandle(initHandle(), handleData())
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const dynamicPanelHandleData = initHandle();
|
|
84
|
+
$effect(() => {
|
|
85
|
+
if (!contraintChanged) return;
|
|
86
|
+
send({ type: "updateConstraints", data: dynamicPanelHandleData });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
$effect(() => () => {
|
|
90
|
+
requestAnimationFrame(() => {
|
|
91
|
+
send({ type: "unregisterPanelHandle", id });
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const { moveProps } = move({
|
|
96
|
+
onMoveStart: () => {
|
|
97
|
+
send({ type: "dragHandleStart", handleId: id });
|
|
98
|
+
onDragStart?.();
|
|
99
|
+
document.body.style.cursor = getCursor(state) || "auto";
|
|
100
|
+
},
|
|
101
|
+
onMove: (e) => {
|
|
102
|
+
send({ type: "dragHandle", handleId: id, value: e });
|
|
103
|
+
onDrag?.();
|
|
104
|
+
},
|
|
105
|
+
onMoveEnd: () => {
|
|
106
|
+
send({ type: "dragHandleEnd", handleId: id });
|
|
107
|
+
onDragEnd?.();
|
|
108
|
+
document.body.style.cursor = "auto";
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const itemIndex = 1;
|
|
113
|
+
const panelAttributes = () => {
|
|
114
|
+
const panelBeforeHandle = state?.items[itemIndex - 1];
|
|
115
|
+
|
|
116
|
+
if (!panelBeforeHandle || !isPanelData(panelBeforeHandle)) return { id };
|
|
117
|
+
|
|
118
|
+
return getPanelResizerDomAttributes({
|
|
119
|
+
groupId: state.groupId,
|
|
120
|
+
id,
|
|
121
|
+
orientation: state.orientation,
|
|
122
|
+
isDragging: state.activeDragHandleId === id,
|
|
123
|
+
activeDragHandleId: state.activeDragHandleId,
|
|
124
|
+
disabled: disabled,
|
|
125
|
+
controlsId: panelBeforeHandle.id,
|
|
126
|
+
min: panelBeforeHandle.min,
|
|
127
|
+
max: panelBeforeHandle.max,
|
|
128
|
+
currentValue: panelBeforeHandle.currentValue,
|
|
129
|
+
groupSize: getGroupSize(state),
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
const getDimensions = () => {
|
|
133
|
+
const handle = state.items.find((item) => item.id === id);
|
|
134
|
+
if (!handle || !isPanelHandle(handle)) return {};
|
|
135
|
+
return state.orientation === "horizontal"
|
|
136
|
+
? { width: `${handle.size.value.toNumber()}px`, height: "100%" }
|
|
137
|
+
: { height: `${handle.size.value.toNumber()}px`, width: "100%" };
|
|
138
|
+
};
|
|
139
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
140
|
+
try {
|
|
141
|
+
const collapsiblePanel = getCollapsiblePanelForHandleId(state, id);
|
|
142
|
+
|
|
143
|
+
if (e.key === "Enter" && collapsiblePanel) {
|
|
144
|
+
if (collapsiblePanel.collapsed) {
|
|
145
|
+
send({ type: "expandPanel", panelId: collapsiblePanel.id });
|
|
146
|
+
} else {
|
|
147
|
+
send({ type: "collapsePanel", panelId: collapsiblePanel.id });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
//
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
157
|
+
<div
|
|
158
|
+
{...attrs}
|
|
159
|
+
{...panelAttributes()}
|
|
160
|
+
onpointerdown={disabled ? undefined : moveProps.onPointerDown}
|
|
161
|
+
onkeydown={disabled
|
|
162
|
+
? undefined
|
|
163
|
+
: (e) => {
|
|
164
|
+
moveProps.onKeyDown(e);
|
|
165
|
+
onKeyDown(e);
|
|
166
|
+
}}
|
|
167
|
+
tabindex={disabled ? -1 : 0}
|
|
168
|
+
style:cursor={getCursor(state)}
|
|
169
|
+
style:width={getDimensions().width}
|
|
170
|
+
style:height={getDimensions().height}
|
|
171
|
+
></div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SharedPanelResizerProps } from "@window-splitter/interface";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
interface Props extends SharedPanelResizerProps, HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
}
|
|
5
|
+
declare const PanelResizer: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type PanelResizer = ReturnType<typeof PanelResizer>;
|
|
7
|
+
export default PanelResizer;
|
|
8
|
+
//# sourceMappingURL=PanelResizer.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelResizer.svelte.d.ts","sourceRoot":"","sources":["../src/lib/PanelResizer.svelte.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAK1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,UAAU,KACR,SAAQ,uBAAuB,EAC7B,cAAc,CAAC,cAAc,CAAC;CAAG;AAqJvC,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
package/eslint.config.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// eslint.config.js
|
|
2
|
+
import base from "@internal/eslint-config";
|
|
3
|
+
import svelte from "eslint-plugin-svelte";
|
|
4
|
+
import ts from "typescript-eslint";
|
|
5
|
+
import svelteConfig from "./svelte.config.js";
|
|
6
|
+
|
|
7
|
+
export default [
|
|
8
|
+
...base,
|
|
9
|
+
...svelte.configs["flat/recommended"],
|
|
10
|
+
{
|
|
11
|
+
files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parserOptions: {
|
|
14
|
+
projectService: true,
|
|
15
|
+
extraFileExtensions: [".svelte"],
|
|
16
|
+
parser: ts.parser,
|
|
17
|
+
svelteConfig,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
rules: {},
|
|
23
|
+
},
|
|
24
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "@window-splitter/svelte",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"version": "0.8.4",
|
|
6
|
+
"description": "A WAI-ARIA compliant window splitter for Svelte.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"url": "https://github.com/hipstersmoothie/window-splitter",
|
|
9
|
+
"directory": "packages/svelte"
|
|
10
|
+
},
|
|
11
|
+
"author": {
|
|
12
|
+
"name": "Andrew Lisowski",
|
|
13
|
+
"email": "lisowski54@gmail.com"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18.0.0"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "svelte-package",
|
|
23
|
+
"test": "CI=true vitest",
|
|
24
|
+
"dev": "svelte-package -w",
|
|
25
|
+
"lint": "eslint .",
|
|
26
|
+
"stats": "rsbuild --mode production build",
|
|
27
|
+
"storybook": "storybook dev -p 6006",
|
|
28
|
+
"build-storybook": "storybook build",
|
|
29
|
+
"clean": "rm -rf dist .turbo"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@internal/eslint-config": "0.8.4",
|
|
34
|
+
"@rsbuild/core": "^1.3.12",
|
|
35
|
+
"@rsdoctor/rspack-plugin": "^1.0.2",
|
|
36
|
+
"@storybook/addon-essentials": "^8.6.12",
|
|
37
|
+
"@storybook/addon-interactions": "^8.6.12",
|
|
38
|
+
"@storybook/addon-svelte-csf": "^5.0.0-next.0",
|
|
39
|
+
"@storybook/blocks": "^8.6.12",
|
|
40
|
+
"@storybook/svelte": "^8.6.12",
|
|
41
|
+
"@storybook/svelte-vite": "^8.6.12",
|
|
42
|
+
"@storybook/test": "^8.6.12",
|
|
43
|
+
"@sveltejs/package": "^2.3.11",
|
|
44
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
45
|
+
"@testing-library/jest-dom": "^6.4.8",
|
|
46
|
+
"@testing-library/svelte": "^5.2.7",
|
|
47
|
+
"@types/node": "^20.14.10",
|
|
48
|
+
"@vitest/browser": "^3.1.2",
|
|
49
|
+
"@vitest/coverage-istanbul": "^3.1.2",
|
|
50
|
+
"@vitest/coverage-v8": "^3.1.2",
|
|
51
|
+
"eslint": "^9.9.0",
|
|
52
|
+
"eslint-plugin-storybook": "^0.12.0",
|
|
53
|
+
"eslint-plugin-svelte": "^2.35.1",
|
|
54
|
+
"framer-motion": "^11.3.28",
|
|
55
|
+
"jsdom": "^24.1.1",
|
|
56
|
+
"playwright": "^1.46.0",
|
|
57
|
+
"storybook": "^8.6.12",
|
|
58
|
+
"svelte": "^5.28.2",
|
|
59
|
+
"tiny-cookie": "^2.5.1",
|
|
60
|
+
"typescript": "^5.5.4",
|
|
61
|
+
"vite": "^6.3.3",
|
|
62
|
+
"vitest": "^3.1.2"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"svelte": ">=5.x"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@window-splitter/interface": "0.8.4",
|
|
69
|
+
"@window-splitter/state": "0.8.4"
|
|
70
|
+
},
|
|
71
|
+
"type": "module",
|
|
72
|
+
"exports": {
|
|
73
|
+
".": {
|
|
74
|
+
"types": "./dist/index.d.ts",
|
|
75
|
+
"svelte": "./dist/index.js"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"module": "./dist/index.js",
|
|
79
|
+
"keywords": [
|
|
80
|
+
"svelte",
|
|
81
|
+
"panel",
|
|
82
|
+
"splitter",
|
|
83
|
+
"resizable",
|
|
84
|
+
"window"
|
|
85
|
+
],
|
|
86
|
+
"eslintConfig": {
|
|
87
|
+
"extends": [
|
|
88
|
+
"plugin:storybook/recommended"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
"gitHead": "b71dcbded56d12a3e78294802e56d97d179b0bf6"
|
|
92
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import "@testing-library/jest-dom/vitest";
|
|
2
|
+
|
|
3
|
+
import { cleanup, fireEvent, render, waitFor } from "@testing-library/svelte";
|
|
4
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
5
|
+
import * as Cookies from "tiny-cookie";
|
|
6
|
+
|
|
7
|
+
import Collapsible, {
|
|
8
|
+
handle as collapsibleHandle,
|
|
9
|
+
leftHandle,
|
|
10
|
+
rightHandle,
|
|
11
|
+
} from "./stories/Collapsible.svelte";
|
|
12
|
+
import AutosaveCookie from "./stories/AutosaveCookie.svelte";
|
|
13
|
+
import Autosave, { handle as autosaveHandle } from "./stories/Autosave.svelte";
|
|
14
|
+
import AutosaveCollapsible from "./stories/AutosaveCollapsible.svelte";
|
|
15
|
+
import DynamicConstraints, {
|
|
16
|
+
handle as dynamicConstraintsHandle,
|
|
17
|
+
} from "./stories/DynamicConstraints.svelte";
|
|
18
|
+
import Conditional, {
|
|
19
|
+
handle as conditionalHandle,
|
|
20
|
+
} from "./stories/Conditional.svelte";
|
|
21
|
+
import Simple, { handle as simpleHandle } from "./stories/Simple.svelte";
|
|
22
|
+
import VerticalLayout, {
|
|
23
|
+
handle as verticalHandle,
|
|
24
|
+
} from "./stories/VerticalLayout.svelte";
|
|
25
|
+
import { createTestUtils, dragHandle } from "@window-splitter/interface/test";
|
|
26
|
+
import { PanelGroupHandle } from "@window-splitter/interface";
|
|
27
|
+
|
|
28
|
+
const { expectTemplate, waitForMeasurement, waitForCondition } =
|
|
29
|
+
createTestUtils({
|
|
30
|
+
waitFor,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
cleanup();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("horizontal layout", async () => {
|
|
38
|
+
const component = render(Simple);
|
|
39
|
+
|
|
40
|
+
await waitForMeasurement(simpleHandle);
|
|
41
|
+
|
|
42
|
+
expect(component.getByText("Panel 1")).toBeInTheDocument();
|
|
43
|
+
expect(component.getByText("Panel 2")).toBeInTheDocument();
|
|
44
|
+
|
|
45
|
+
await expectTemplate(simpleHandle, "244px 10px 244px");
|
|
46
|
+
|
|
47
|
+
// Should respect the min
|
|
48
|
+
await dragHandle({ delta: 300 });
|
|
49
|
+
await expectTemplate(simpleHandle, "388px 10px 100px");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("vertical layout", async () => {
|
|
53
|
+
const component = render(VerticalLayout);
|
|
54
|
+
|
|
55
|
+
await waitForMeasurement(verticalHandle);
|
|
56
|
+
|
|
57
|
+
expect(component.getByText("top")).toBeInTheDocument();
|
|
58
|
+
expect(component.getByText("middle")).toBeInTheDocument();
|
|
59
|
+
expect(component.getByText("bottom")).toBeInTheDocument();
|
|
60
|
+
|
|
61
|
+
await expectTemplate(verticalHandle, "96px 10px 108px 10px 96px");
|
|
62
|
+
|
|
63
|
+
// Should respect the min
|
|
64
|
+
await dragHandle({ delta: 100, orientation: "vertical" });
|
|
65
|
+
await expectTemplate(verticalHandle, "172px 10px 64px 10px 64px");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("Conditional Panels", async () => {
|
|
69
|
+
const component = render(Conditional);
|
|
70
|
+
|
|
71
|
+
await waitForMeasurement(conditionalHandle);
|
|
72
|
+
await expectTemplate(conditionalHandle, "244px 10px 244px");
|
|
73
|
+
|
|
74
|
+
component.getByText("Expand").click();
|
|
75
|
+
await expectTemplate(conditionalHandle, "244px 10px 134px 10px 100px");
|
|
76
|
+
|
|
77
|
+
component.getByText("Close").click();
|
|
78
|
+
await expectTemplate(conditionalHandle, "244px 10px 244px");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("Dynamic constraints", async () => {
|
|
82
|
+
const component = render(DynamicConstraints);
|
|
83
|
+
|
|
84
|
+
await waitForMeasurement(dynamicConstraintsHandle);
|
|
85
|
+
await expectTemplate(dynamicConstraintsHandle, "100px 10px 178px 10px 700px");
|
|
86
|
+
|
|
87
|
+
component.getByText("Toggle Custom").click();
|
|
88
|
+
await expectTemplate(dynamicConstraintsHandle, "500px 10px 178px 10px 300px");
|
|
89
|
+
|
|
90
|
+
component.getByText("Toggle Custom").click();
|
|
91
|
+
await expectTemplate(dynamicConstraintsHandle, "400px 10px 178px 10px 400px");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("Autosave", () => {
|
|
95
|
+
test("localStorage", async () => {
|
|
96
|
+
localStorage.clear();
|
|
97
|
+
|
|
98
|
+
render(Autosave);
|
|
99
|
+
|
|
100
|
+
await waitForMeasurement(autosaveHandle);
|
|
101
|
+
await expectTemplate(autosaveHandle, "244px 10px 244px");
|
|
102
|
+
|
|
103
|
+
await dragHandle({ delta: 100 });
|
|
104
|
+
await expectTemplate(autosaveHandle, "342px 10px 146px");
|
|
105
|
+
|
|
106
|
+
await waitForCondition(() =>
|
|
107
|
+
Boolean(localStorage.getItem("autosave-example-svelte"))
|
|
108
|
+
);
|
|
109
|
+
const obj = JSON.parse(
|
|
110
|
+
localStorage.getItem("autosave-example-svelte") || "{}"
|
|
111
|
+
);
|
|
112
|
+
expect(obj.items).toMatchSnapshot();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("callback", async () => {
|
|
116
|
+
localStorage.clear();
|
|
117
|
+
|
|
118
|
+
const spy = vi.fn();
|
|
119
|
+
const handle = $state<{ current: PanelGroupHandle | null }>({
|
|
120
|
+
current: null,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
render(AutosaveCollapsible, {
|
|
124
|
+
props: { onCollapseChange: spy, handle },
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
await dragHandle({ delta: -200 });
|
|
128
|
+
await expectTemplate(handle.current!, "100px 10px 388px");
|
|
129
|
+
expect(spy).toHaveBeenCalledWith(true);
|
|
130
|
+
|
|
131
|
+
cleanup();
|
|
132
|
+
|
|
133
|
+
render(AutosaveCollapsible, {
|
|
134
|
+
props: { onCollapseChange: spy, handle },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await expectTemplate(handle.current!, "100px 10px 388px");
|
|
138
|
+
await dragHandle({ delta: 200 });
|
|
139
|
+
expect(spy).toHaveBeenCalledWith(false);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("cookie", async () => {
|
|
143
|
+
// clear cookies
|
|
144
|
+
document.cookie = "test=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
|
|
145
|
+
|
|
146
|
+
const handle = $state<{ current: PanelGroupHandle | null }>({
|
|
147
|
+
current: null,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
render(AutosaveCookie, {
|
|
151
|
+
props: { handle, snapshot: undefined },
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await waitForMeasurement(handle.current!);
|
|
155
|
+
await expectTemplate(handle.current!, "245px 10px 245px");
|
|
156
|
+
|
|
157
|
+
await dragHandle({ delta: 100 });
|
|
158
|
+
await expectTemplate(handle.current!, "343px 10px 147px");
|
|
159
|
+
|
|
160
|
+
await waitForCondition(() =>
|
|
161
|
+
document.cookie.includes("autosave-cookie-svelte")
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
expect(document.cookie).toMatchSnapshot();
|
|
165
|
+
|
|
166
|
+
const snapshot = Cookies.get("autosave-cookie-svelte");
|
|
167
|
+
|
|
168
|
+
cleanup();
|
|
169
|
+
|
|
170
|
+
render(AutosaveCookie, {
|
|
171
|
+
props: { snapshot: JSON.parse(snapshot || "{}"), handle },
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await expectTemplate(handle.current!, "343px 10px 147px");
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("imperative panel API", async () => {
|
|
179
|
+
test("panel group", async () => {
|
|
180
|
+
render(Collapsible);
|
|
181
|
+
|
|
182
|
+
await waitForMeasurement(collapsibleHandle);
|
|
183
|
+
|
|
184
|
+
expect(collapsibleHandle.getPercentageSizes()).toMatchInlineSnapshot(`
|
|
185
|
+
[
|
|
186
|
+
0.5,
|
|
187
|
+
0.020080321285140562,
|
|
188
|
+
0.5,
|
|
189
|
+
0.020080321285140562,
|
|
190
|
+
0.12048192771084337,
|
|
191
|
+
]
|
|
192
|
+
`);
|
|
193
|
+
|
|
194
|
+
expect(collapsibleHandle.getPixelSizes()).toMatchInlineSnapshot(`
|
|
195
|
+
[
|
|
196
|
+
209,
|
|
197
|
+
10,
|
|
198
|
+
209,
|
|
199
|
+
10,
|
|
200
|
+
60,
|
|
201
|
+
]
|
|
202
|
+
`);
|
|
203
|
+
|
|
204
|
+
await expectTemplate(collapsibleHandle, "209px 10px 209px 10px 60px");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("panel", async () => {
|
|
208
|
+
render(Collapsible);
|
|
209
|
+
|
|
210
|
+
await waitForMeasurement(collapsibleHandle);
|
|
211
|
+
|
|
212
|
+
expect(rightHandle.isCollapsed()).toBe(true);
|
|
213
|
+
expect(rightHandle.isExpanded()).toBe(false);
|
|
214
|
+
|
|
215
|
+
rightHandle.expand();
|
|
216
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
217
|
+
|
|
218
|
+
expect(rightHandle.isCollapsed()).toBe(false);
|
|
219
|
+
expect(rightHandle.isExpanded()).toBe(true);
|
|
220
|
+
|
|
221
|
+
rightHandle.collapse();
|
|
222
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
223
|
+
|
|
224
|
+
expect(rightHandle.isCollapsed()).toBe(true);
|
|
225
|
+
expect(rightHandle.isExpanded()).toBe(false);
|
|
226
|
+
|
|
227
|
+
// Test the non controlled version
|
|
228
|
+
|
|
229
|
+
expect(leftHandle.isCollapsed()).toBe(false);
|
|
230
|
+
expect(leftHandle.isExpanded()).toBe(true);
|
|
231
|
+
|
|
232
|
+
leftHandle.collapse();
|
|
233
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
234
|
+
|
|
235
|
+
expect(leftHandle.isCollapsed()).toBe(true);
|
|
236
|
+
expect(leftHandle.isExpanded()).toBe(false);
|
|
237
|
+
expect(rightHandle.getPercentageSize()).toBe(
|
|
238
|
+
leftHandle.getPercentageSize()
|
|
239
|
+
);
|
|
240
|
+
expect(rightHandle.getPixelSize()).toBe(leftHandle.getPixelSize());
|
|
241
|
+
|
|
242
|
+
leftHandle.expand();
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
244
|
+
|
|
245
|
+
expect(leftHandle.isCollapsed()).toBe(false);
|
|
246
|
+
expect(leftHandle.isExpanded()).toBe(true);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("Keyboard interactions with collapsed panels", async () => {
|
|
251
|
+
render(Collapsible);
|
|
252
|
+
|
|
253
|
+
await waitForMeasurement(collapsibleHandle);
|
|
254
|
+
await expectTemplate(collapsibleHandle, "209px 10px 209px 10px 60px");
|
|
255
|
+
|
|
256
|
+
const resizer2 = document.getElementById("resizer-2")!;
|
|
257
|
+
fireEvent.keyDown(resizer2, { key: "Enter" });
|
|
258
|
+
await expectTemplate(collapsibleHandle, "209px 10px 169px 10px 100px");
|
|
259
|
+
|
|
260
|
+
fireEvent.keyDown(resizer2, { key: "ArrowLeft" });
|
|
261
|
+
fireEvent.keyDown(resizer2, { key: "ArrowLeft" });
|
|
262
|
+
fireEvent.keyDown(resizer2, { key: "ArrowLeft" });
|
|
263
|
+
fireEvent.keyDown(resizer2, { key: "ArrowLeft" });
|
|
264
|
+
await expectTemplate(collapsibleHandle, "209px 10px 165px 10px 104px");
|
|
265
|
+
|
|
266
|
+
fireEvent.keyDown(resizer2, { key: "ArrowLeft", shiftKey: true });
|
|
267
|
+
await expectTemplate(
|
|
268
|
+
collapsibleHandle,
|
|
269
|
+
"209.03125px 10px 149.984375px 10px 118.984375px"
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
fireEvent.keyDown(resizer2, { key: "Enter" });
|
|
273
|
+
await expectTemplate(
|
|
274
|
+
collapsibleHandle,
|
|
275
|
+
"209.03125px 10px 208.96875px 10px 60px"
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
fireEvent.keyDown(resizer2, { key: "Enter" });
|
|
279
|
+
await expectTemplate(
|
|
280
|
+
collapsibleHandle,
|
|
281
|
+
"209.0625px 10px 149.96875px 10px 118.96875px"
|
|
282
|
+
);
|
|
283
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`Autosave > cookie 1`] = `"autosave-cookie-svelte=%7B%22size%22%3A%7B%22x%22%3A0%2C%22y%22%3A0%2C%22width%22%3A500%2C%22height%22%3A198%2C%22top%22%3A0%2C%22right%22%3A500%2C%22bottom%22%3A198%2C%22left%22%3A0%7D%2C%22items%22%3A%5B%7B%22type%22%3A%22panel%22%2C%22currentValue%22%3A%7B%22type%22%3A%22percent%22%2C%22value%22%3A%220.7%22%7D%2C%22min%22%3A%7B%22type%22%3A%22pixel%22%2C%22value%22%3A%220%22%7D%2C%22max%22%3A%221fr%22%2C%22collapsedSize%22%3A%7B%22type%22%3A%22pixel%22%2C%22value%22%3A%220%22%7D%2C%22onCollapseChange%22%3A%7B%7D%2C%22onResize%22%3A%7B%7D%2C%22collapseIsControlled%22%3Afalse%2C%22id%22%3A%221%22%7D%2C%7B%22type%22%3A%22handle%22%2C%22size%22%3A%7B%22type%22%3A%22pixel%22%2C%22value%22%3A%2210%22%7D%2C%22id%22%3A%22resizer%22%7D%2C%7B%22type%22%3A%22panel%22%2C%22currentValue%22%3A%7B%22type%22%3A%22percent%22%2C%22value%22%3A%220.3%22%7D%2C%22min%22%3A%7B%22type%22%3A%22pixel%22%2C%22value%22%3A%220%22%7D%2C%22max%22%3A%221fr%22%2C%22collapsedSize%22%3A%7B%22type%22%3A%22pixel%22%2C%22value%22%3A%220%22%7D%2C%22onCollapseChange%22%3A%7B%7D%2C%22onResize%22%3A%7B%7D%2C%22collapseIsControlled%22%3Afalse%2C%22id%22%3A%222%22%7D%5D%2C%22orientation%22%3A%22horizontal%22%2C%22dragOvershoot%22%3A%220%22%2C%22groupId%22%3A%22autosave-cookie-svelte%22%2C%22autosaveStrategy%22%3A%22cookie%22%7D"`;
|
|
4
|
+
|
|
5
|
+
exports[`Autosave > localStorage 1`] = `
|
|
6
|
+
[
|
|
7
|
+
{
|
|
8
|
+
"collapseIsControlled": false,
|
|
9
|
+
"collapsedSize": {
|
|
10
|
+
"type": "pixel",
|
|
11
|
+
"value": "0",
|
|
12
|
+
},
|
|
13
|
+
"currentValue": {
|
|
14
|
+
"type": "percent",
|
|
15
|
+
"value": "0.70081967213114754098",
|
|
16
|
+
},
|
|
17
|
+
"id": "1",
|
|
18
|
+
"max": "1fr",
|
|
19
|
+
"min": {
|
|
20
|
+
"type": "pixel",
|
|
21
|
+
"value": "0",
|
|
22
|
+
},
|
|
23
|
+
"onCollapseChange": {},
|
|
24
|
+
"onResize": {},
|
|
25
|
+
"type": "panel",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "resizer",
|
|
29
|
+
"size": {
|
|
30
|
+
"type": "pixel",
|
|
31
|
+
"value": "10",
|
|
32
|
+
},
|
|
33
|
+
"type": "handle",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"collapseIsControlled": false,
|
|
37
|
+
"collapsedSize": {
|
|
38
|
+
"type": "pixel",
|
|
39
|
+
"value": "0",
|
|
40
|
+
},
|
|
41
|
+
"currentValue": {
|
|
42
|
+
"type": "percent",
|
|
43
|
+
"value": "0.29918032786885245902",
|
|
44
|
+
},
|
|
45
|
+
"id": "2",
|
|
46
|
+
"max": "1fr",
|
|
47
|
+
"min": {
|
|
48
|
+
"type": "pixel",
|
|
49
|
+
"value": "0",
|
|
50
|
+
},
|
|
51
|
+
"onCollapseChange": {},
|
|
52
|
+
"onResize": {},
|
|
53
|
+
"type": "panel",
|
|
54
|
+
},
|
|
55
|
+
]
|
|
56
|
+
`;
|