@witchcraft/layout 0.1.3 → 0.2.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/README.md +27 -24
- package/dist/module.json +1 -1
- package/dist/runtime/components/FrameDragHandle.d.vue.ts +15 -0
- package/dist/runtime/components/FrameDragHandle.vue +28 -0
- package/dist/runtime/components/FrameDragHandle.vue.d.ts +15 -0
- package/dist/runtime/components/LayoutDecos.d.vue.ts +2 -4
- package/dist/runtime/components/LayoutDecos.vue +10 -29
- package/dist/runtime/components/LayoutDecos.vue.d.ts +2 -4
- package/dist/runtime/components/LayoutEdges.d.vue.ts +3 -3
- package/dist/runtime/components/LayoutEdges.vue +8 -8
- package/dist/runtime/components/LayoutEdges.vue.d.ts +3 -3
- package/dist/runtime/components/LayoutFrame.d.vue.ts +1 -1
- package/dist/runtime/components/LayoutFrame.vue +0 -1
- package/dist/runtime/components/LayoutFrame.vue.d.ts +1 -1
- package/dist/runtime/components/LayoutShapeSquare.d.vue.ts +3 -1
- package/dist/runtime/components/LayoutShapeSquare.vue.d.ts +3 -1
- package/dist/runtime/components/LayoutWindow.d.vue.ts +26 -12
- package/dist/runtime/components/LayoutWindow.vue +95 -84
- package/dist/runtime/components/LayoutWindow.vue.d.ts +26 -12
- package/dist/runtime/composables/useFrames.d.ts +15 -13
- package/dist/runtime/composables/useFrames.js +59 -39
- package/dist/runtime/demo/App.vue +116 -30
- package/dist/runtime/demo/DemoControls.d.vue.ts +4 -1
- package/dist/runtime/demo/DemoControls.vue +98 -4
- package/dist/runtime/demo/DemoControls.vue.d.ts +4 -1
- package/dist/runtime/drag/CloseAction.d.ts +26 -5
- package/dist/runtime/drag/CloseAction.js +87 -40
- package/dist/runtime/drag/DragActionHandler.d.ts +20 -8
- package/dist/runtime/drag/DragActionHandler.js +47 -12
- package/dist/runtime/drag/FrameDragAction.d.ts +45 -0
- package/dist/runtime/drag/FrameDragAction.js +143 -0
- package/dist/runtime/drag/SplitAction.d.ts +32 -11
- package/dist/runtime/drag/SplitAction.js +82 -24
- package/dist/runtime/drag/createDefaultHandlers.d.ts +9 -0
- package/dist/runtime/drag/createDefaultHandlers.js +10 -0
- package/dist/runtime/drag/defaultDragActions.d.ts +9 -0
- package/dist/runtime/drag/defaultDragActions.js +10 -0
- package/dist/runtime/drag/types.d.ts +82 -13
- package/dist/runtime/drag/types.js +1 -0
- package/dist/runtime/helpers/createZoneSideClipPath.d.ts +12 -0
- package/dist/runtime/helpers/createZoneSideClipPath.js +17 -0
- package/dist/runtime/helpers/doEdgesOverlap.d.ts +3 -1
- package/dist/runtime/helpers/doEdgesOverlap.js +5 -5
- package/dist/runtime/helpers/getDockBoundaries.d.ts +19 -0
- package/dist/runtime/helpers/getDockBoundaries.js +14 -0
- package/dist/runtime/helpers/getEdgeLength.d.ts +2 -0
- package/dist/runtime/helpers/getEdgeLength.js +5 -0
- package/dist/runtime/helpers/getIntersections.js +2 -2
- package/dist/runtime/helpers/getIntersectionsCss.js +2 -2
- package/dist/runtime/helpers/getMoveEdgeInfo.js +2 -2
- package/dist/runtime/helpers/getResizeLimit.js +2 -2
- package/dist/runtime/helpers/getShapeSquareCss.js +2 -2
- package/dist/runtime/helpers/getVisualEdgeCss.js +2 -2
- package/dist/runtime/helpers/getVisualEdges.d.ts +1 -1
- package/dist/runtime/helpers/getVisualEdges.js +4 -3
- package/dist/runtime/helpers/index.d.ts +4 -0
- package/dist/runtime/helpers/index.js +4 -0
- package/dist/runtime/helpers/isEdgeEqual.js +2 -4
- package/dist/runtime/helpers/isWindowEdge.js +2 -2
- package/dist/runtime/helpers/isWindowEdgePoint.js +2 -2
- package/dist/runtime/helpers/moveEdge.js +2 -2
- package/dist/runtime/helpers/numberToScaledPercent.d.ts +1 -1
- package/dist/runtime/helpers/numberToScaledPercent.js +2 -2
- package/dist/runtime/helpers/numberToScaledSize.js +2 -2
- package/dist/runtime/helpers/rotateFrames.d.ts +7 -0
- package/dist/runtime/helpers/rotateFrames.js +36 -0
- package/dist/runtime/helpers/scaledPointToPx.d.ts +13 -0
- package/dist/runtime/helpers/scaledPointToPx.js +7 -0
- package/dist/runtime/helpers/toWindowCoord.js +2 -2
- package/dist/runtime/layout/applyFrameChanges.d.ts +10 -0
- package/dist/runtime/layout/applyFrameChanges.js +29 -0
- package/dist/runtime/layout/createSplitDecoFromDrag.d.ts +6 -1
- package/dist/runtime/layout/createSplitDecoFromDrag.js +4 -4
- package/dist/runtime/layout/createSplitDecoShapes.d.ts +7 -0
- package/dist/runtime/layout/{createSplitDecoEdge.js → createSplitDecoShapes.js} +6 -3
- package/dist/runtime/layout/debugFrame.js +2 -1
- package/dist/runtime/layout/findSafeSplitEdge.js +2 -2
- package/dist/runtime/layout/frameCreate.js +2 -2
- package/dist/runtime/layout/getCloseFrameInfo.d.ts +7 -6
- package/dist/runtime/layout/getCloseFrameInfo.js +10 -3
- package/dist/runtime/layout/getDragZones.d.ts +8 -0
- package/dist/runtime/layout/getDragZones.js +32 -0
- package/dist/runtime/layout/getFillEmptySpaceInfo.d.ts +65 -0
- package/dist/runtime/layout/getFillEmptySpaceInfo.js +69 -0
- package/dist/runtime/layout/getFrameCollapseInfo.d.ts +13 -0
- package/dist/runtime/layout/getFrameCollapseInfo.js +93 -0
- package/dist/runtime/layout/getFrameDockInfo.d.ts +9 -0
- package/dist/runtime/layout/getFrameDockInfo.js +82 -0
- package/dist/runtime/layout/getFrameDragZones.d.ts +16 -0
- package/dist/runtime/layout/getFrameDragZones.js +74 -0
- package/dist/runtime/layout/getFrameRearrangeInfo.d.ts +139 -0
- package/dist/runtime/layout/getFrameRearrangeInfo.js +87 -0
- package/dist/runtime/layout/getFrameSplitInfo.d.ts +7 -5
- package/dist/runtime/layout/getFrameSplitInfo.js +10 -3
- package/dist/runtime/layout/getFrameSwapInfo.d.ts +9 -0
- package/dist/runtime/layout/getFrameSwapInfo.js +27 -0
- package/dist/runtime/layout/getFrameTo.js +2 -2
- package/dist/runtime/layout/getFrameUncollapseInfo.d.ts +12 -0
- package/dist/runtime/layout/getFrameUncollapseInfo.js +88 -0
- package/dist/runtime/layout/getFrameUndockInfo.d.ts +13 -0
- package/dist/runtime/layout/getFrameUndockInfo.js +51 -0
- package/dist/runtime/layout/getFramesRedistributeInfo.d.ts +29 -0
- package/dist/runtime/layout/getFramesRedistributeInfo.js +53 -0
- package/dist/runtime/layout/getWindowDragZones.d.ts +6 -0
- package/dist/runtime/layout/getWindowDragZones.js +49 -0
- package/dist/runtime/layout/index.d.ts +14 -5
- package/dist/runtime/layout/index.js +14 -5
- package/dist/runtime/layout/isPointInRect.d.ts +7 -0
- package/dist/runtime/layout/{isPointInFrame.js → isPointInRect.js} +1 -1
- package/dist/runtime/layout/resizeFrame.js +2 -2
- package/dist/runtime/settings.d.ts +41 -16
- package/dist/runtime/settings.js +95 -53
- package/dist/runtime/types/index.d.ts +324 -54
- package/dist/runtime/types/index.js +54 -20
- package/package.json +28 -29
- package/src/runtime/components/FrameDragHandle.vue +30 -0
- package/src/runtime/components/LayoutDecos.vue +12 -36
- package/src/runtime/components/LayoutEdges.vue +27 -23
- package/src/runtime/components/LayoutFrame.vue +6 -5
- package/src/runtime/components/LayoutShapeSquare.vue +9 -3
- package/src/runtime/components/LayoutWindow.vue +110 -101
- package/src/runtime/composables/useFrames.ts +80 -50
- package/src/runtime/demo/App.vue +126 -36
- package/src/runtime/demo/DemoControls.vue +115 -6
- package/src/runtime/drag/CloseAction.ts +106 -44
- package/src/runtime/drag/DragActionHandler.ts +71 -20
- package/src/runtime/drag/FrameDragAction.ts +202 -0
- package/src/runtime/drag/SplitAction.ts +106 -34
- package/src/runtime/drag/createDefaultHandlers.ts +19 -0
- package/src/runtime/drag/defaultDragActions.ts +19 -0
- package/src/runtime/drag/types.ts +90 -20
- package/src/runtime/helpers/createZoneSideClipPath.ts +41 -0
- package/src/runtime/helpers/doEdgesOverlap.ts +11 -5
- package/src/runtime/helpers/getDockBoundaries.ts +36 -0
- package/src/runtime/helpers/getEdgeLength.ts +10 -0
- package/src/runtime/helpers/getIntersections.ts +2 -2
- package/src/runtime/helpers/getIntersectionsCss.ts +2 -2
- package/src/runtime/helpers/getMoveEdgeInfo.ts +2 -2
- package/src/runtime/helpers/getResizeLimit.ts +2 -2
- package/src/runtime/helpers/getShapeSquareCss.ts +2 -2
- package/src/runtime/helpers/getVisualEdgeCss.ts +2 -2
- package/src/runtime/helpers/getVisualEdges.ts +5 -4
- package/src/runtime/helpers/index.ts +4 -0
- package/src/runtime/helpers/isEdgeEqual.ts +2 -4
- package/src/runtime/helpers/isWindowEdge.ts +2 -2
- package/src/runtime/helpers/isWindowEdgePoint.ts +2 -2
- package/src/runtime/helpers/moveEdge.ts +2 -2
- package/src/runtime/helpers/numberToScaledPercent.ts +3 -3
- package/src/runtime/helpers/numberToScaledSize.ts +2 -2
- package/src/runtime/helpers/rotateFrames.ts +45 -0
- package/src/runtime/helpers/scaledPointToPx.ts +13 -0
- package/src/runtime/helpers/toWindowCoord.ts +2 -2
- package/src/runtime/layout/applyFrameChanges.ts +39 -0
- package/src/runtime/layout/createSplitDecoFromDrag.ts +12 -6
- package/src/runtime/layout/{createSplitDecoEdge.ts → createSplitDecoShapes.ts} +17 -7
- package/src/runtime/layout/debugFrame.ts +1 -1
- package/src/runtime/layout/findSafeSplitEdge.ts +3 -3
- package/src/runtime/layout/frameCreate.ts +2 -2
- package/src/runtime/layout/getCloseFrameInfo.ts +21 -8
- package/src/runtime/layout/getDragZones.ts +48 -0
- package/src/runtime/layout/getFillEmptySpaceInfo.ts +177 -0
- package/src/runtime/layout/getFrameCollapseInfo.ts +164 -0
- package/src/runtime/layout/getFrameDockInfo.ts +126 -0
- package/src/runtime/layout/getFrameDragZones.ts +100 -0
- package/src/runtime/layout/getFrameRearrangeInfo.ts +261 -0
- package/src/runtime/layout/getFrameSplitInfo.ts +21 -8
- package/src/runtime/layout/getFrameSwapInfo.ts +45 -0
- package/src/runtime/layout/getFrameTo.ts +2 -2
- package/src/runtime/layout/getFrameUncollapseInfo.ts +160 -0
- package/src/runtime/layout/getFrameUndockInfo.ts +97 -0
- package/src/runtime/layout/getFramesRedistributeInfo.ts +98 -0
- package/src/runtime/layout/getWindowDragZones.ts +59 -0
- package/src/runtime/layout/index.ts +14 -5
- package/src/runtime/layout/isPointInRect.ts +7 -0
- package/src/runtime/layout/resizeFrame.ts +2 -2
- package/src/runtime/settings.ts +69 -49
- package/src/runtime/types/index.ts +143 -28
- package/dist/runtime/layout/closeFrame.d.ts +0 -5
- package/dist/runtime/layout/closeFrame.js +0 -13
- package/dist/runtime/layout/closeFrames.d.ts +0 -2
- package/dist/runtime/layout/closeFrames.js +0 -8
- package/dist/runtime/layout/createSplitDecoEdge.d.ts +0 -2
- package/dist/runtime/layout/frameSplit.d.ts +0 -16
- package/dist/runtime/layout/frameSplit.js +0 -9
- package/dist/runtime/layout/isPointInFrame.d.ts +0 -2
- package/src/runtime/layout/closeFrame.ts +0 -33
- package/src/runtime/layout/closeFrames.ts +0 -14
- package/src/runtime/layout/frameSplit.ts +0 -31
- package/src/runtime/layout/isPointInFrame.ts +0 -7
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { enumFromArray } from "@alanscodelog/utils/enumFromArray";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
export * from "../drag/types.js";
|
|
4
|
-
import {
|
|
4
|
+
import { settings } from "../settings.js";
|
|
5
5
|
export const zUuid = z.uuid();
|
|
6
6
|
export const zWindowIdConstants = z.enum(["ACTIVE"]);
|
|
7
7
|
export const zWinId = z.uuid().or(zWindowIdConstants);
|
|
8
8
|
export const zFrameIdConstants = z.enum(["ACTIVE"]);
|
|
9
9
|
export const zFrameId = z.uuid().or(zFrameIdConstants);
|
|
10
|
-
export const zScaledIntPercentage = z.number().int().min(0).max(
|
|
10
|
+
export const zScaledIntPercentage = z.number().int().min(0).max(settings.maxInt).nonnegative();
|
|
11
11
|
const zPx = z.number().int().nonnegative();
|
|
12
12
|
export const zPos = z.object({
|
|
13
13
|
x: zScaledIntPercentage,
|
|
@@ -41,9 +41,11 @@ export const zSide = z.enum(["top", "bottom", "left", "right"]);
|
|
|
41
41
|
export const zOrientation = z.enum(["horizontal", "vertical"]);
|
|
42
42
|
export const zExtendedSide = z.union([zSide, zOrientation]);
|
|
43
43
|
export const zBaseSquare = zSize.extend(zPos.shape);
|
|
44
|
-
export const zLayoutFrame =
|
|
45
|
-
id: z.uuid()
|
|
46
|
-
|
|
44
|
+
export const zLayoutFrame = zBaseSquare.extend({
|
|
45
|
+
id: z.uuid(),
|
|
46
|
+
docked: zSide.optional(),
|
|
47
|
+
collapsed: z.union([z.literal(false), z.number()]).optional()
|
|
48
|
+
}).loose();
|
|
47
49
|
export const zLayoutFrameLoose = zLayoutFrame.loose();
|
|
48
50
|
const baseLayoutWindow = z.object({
|
|
49
51
|
id: z.uuid(),
|
|
@@ -52,7 +54,24 @@ const baseLayoutWindow = z.object({
|
|
|
52
54
|
}).extend(zPxSize.shape).extend(zPxPos.shape);
|
|
53
55
|
export const zLayoutWindow = baseLayoutWindow;
|
|
54
56
|
export const zLayoutWindowLoose = baseLayoutWindow.loose();
|
|
55
|
-
const baseWorkspace =
|
|
57
|
+
const baseWorkspace = baseLayoutWindow.pick({ activeFrame: true, frames: true }).superRefine((data, ctx) => {
|
|
58
|
+
for (const [frameId, frame] of Object.entries(data.frames ?? {})) {
|
|
59
|
+
if (frame.docked === void 0) continue;
|
|
60
|
+
const edge = frame.docked;
|
|
61
|
+
if (edge === "left" && frame.x !== 0) {
|
|
62
|
+
ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on left edge must have x=0`, path: ["frames", frameId, "x"] });
|
|
63
|
+
}
|
|
64
|
+
if (edge === "right" && frame.x + frame.width !== settings.maxInt) {
|
|
65
|
+
ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on right edge must have x+width=maxInt`, path: ["frames", frameId, "x"] });
|
|
66
|
+
}
|
|
67
|
+
if (edge === "top" && frame.y !== 0) {
|
|
68
|
+
ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on top edge must have y=0`, path: ["frames", frameId, "y"] });
|
|
69
|
+
}
|
|
70
|
+
if (edge === "bottom" && frame.y + frame.height !== settings.maxInt) {
|
|
71
|
+
ctx.addIssue({ code: "custom", message: `Docked frame ${frameId} on bottom edge must have y+height=maxInt`, path: ["frames", frameId, "y"] });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
56
75
|
export const zWorkspace = baseWorkspace.strict();
|
|
57
76
|
export const zWorkspaceLoose = zWorkspace.loose();
|
|
58
77
|
const baseLayout = z.object({
|
|
@@ -68,32 +87,34 @@ export const zInitializedLayout = zLayout.required({
|
|
|
68
87
|
}
|
|
69
88
|
return zLayoutWindow.safeParse(layout.windows[layout.activeWindow]).success;
|
|
70
89
|
}, { message: "An initialized layout's active window must exist and be valid." });
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
const zLayoutShape = z.discriminatedUnion("type", [
|
|
91
|
+
z.object({ type: z.literal("square"), data: zBaseSquare, attrs: z.record(z.string(), z.string()).optional() }),
|
|
92
|
+
z.object({ type: z.literal("edge"), data: zEdge, attrs: z.record(z.string(), z.string()).optional() })
|
|
93
|
+
]);
|
|
94
|
+
const zBaseDeco = z.object({
|
|
95
|
+
shapes: z.array(zLayoutShape).default([])
|
|
96
|
+
});
|
|
97
|
+
export const zSplitDeco = zBaseDeco.extend({
|
|
76
98
|
id: z.uuid(),
|
|
77
99
|
type: z.literal("split"),
|
|
78
100
|
position: zScaledIntPercentage,
|
|
79
|
-
direction: zDirection
|
|
80
|
-
|
|
81
|
-
}).strict();
|
|
101
|
+
direction: zDirection
|
|
102
|
+
});
|
|
82
103
|
export const zRawSplitDeco = zSplitDeco.omit({ shapes: true });
|
|
83
|
-
const zCloseDeco =
|
|
104
|
+
const zCloseDeco = zBaseDeco.extend({
|
|
84
105
|
id: z.uuid(),
|
|
85
106
|
type: z.literal("close"),
|
|
86
107
|
force: z.boolean().optional()
|
|
87
|
-
})
|
|
88
|
-
const
|
|
108
|
+
});
|
|
109
|
+
const zFrameDragDeco = zBaseDeco.extend({
|
|
89
110
|
id: z.uuid(),
|
|
90
111
|
type: z.literal("drop"),
|
|
91
112
|
position: zSide.or(z.enum(["center"]))
|
|
92
|
-
})
|
|
113
|
+
});
|
|
93
114
|
export const zDeco = z.union([
|
|
94
115
|
zSplitDeco,
|
|
95
116
|
zCloseDeco,
|
|
96
|
-
|
|
117
|
+
zFrameDragDeco
|
|
97
118
|
]);
|
|
98
119
|
export const LAYOUT_ERROR = enumFromArray([
|
|
99
120
|
"INVALID_ID",
|
|
@@ -105,7 +126,20 @@ export const LAYOUT_ERROR = enumFromArray([
|
|
|
105
126
|
"CANT_CLOSE_NEARBY_FRAMES_TOO_SMALL",
|
|
106
127
|
"CANT_CLOSE_SINGLE_FRAME",
|
|
107
128
|
"CANT_SPLIT_FRAME_TOO_SMALL",
|
|
108
|
-
"CANT_CLOSE_WITHOUT_FORCE"
|
|
129
|
+
"CANT_CLOSE_WITHOUT_FORCE",
|
|
130
|
+
"CANT_SWAP_WITH_SELF",
|
|
131
|
+
"CANT_REARRANGE_TO_SAME_RELATIVE_POSITION",
|
|
132
|
+
"CANT_REARRANGE_WITH_DOCKED_EDGES",
|
|
133
|
+
"CANT_REARRANGE_DOCKED_WITH_NON_DOCKED",
|
|
134
|
+
"CANT_SPLIT_DOCKED_FRAME",
|
|
135
|
+
"NO_SPACE_TO_REDISTRIBUTE",
|
|
136
|
+
"REDISTRIBUTE_OUT_OF_BOUNDS",
|
|
137
|
+
"FRAME_ALREADY_DOCKED_ON_SIDE",
|
|
138
|
+
"CANT_LEAVE_NO_UNDOCKED_FRAMES",
|
|
139
|
+
"CANT_UNDOCK_COLLAPSED_FRAME",
|
|
140
|
+
"CANT_COLLAPSE_NOT_DOCKED",
|
|
141
|
+
"CANT_UNCOLLAPSE_NOT_COLLAPSED",
|
|
142
|
+
"NO_FILL_CANDIDATES"
|
|
109
143
|
]);
|
|
110
144
|
export const zWindowCreate = zLayoutWindowLoose.partial({ id: true, pxWidth: true, pxHeight: true, pxX: true, pxY: true }).extend({ frames: zLayoutWindow.shape.frames.optional() });
|
|
111
145
|
export const zLayoutCreate = baseLayout.loose().extend({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@witchcraft/layout",
|
|
3
3
|
"description": "Headless layout manager.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"main": "./dist/runtime/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@alanscodelog/utils": "^6.2.0",
|
|
32
|
-
"@iconify/json": "^2.2.
|
|
33
|
-
"es-toolkit": "^1.
|
|
32
|
+
"@iconify/json": "^2.2.474",
|
|
33
|
+
"es-toolkit": "^1.46.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@witchcraft/nuxt-utils": "^0.3.6",
|
|
37
|
-
"@witchcraft/ui": "^0.4.
|
|
37
|
+
"@witchcraft/ui": "^0.4.4"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@witchcraft/ui": {
|
|
@@ -46,43 +46,43 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@alanscodelog/commitlint-config": "^3.1.2",
|
|
49
|
-
"@alanscodelog/eslint-config": "^6.3.
|
|
49
|
+
"@alanscodelog/eslint-config": "^6.3.1",
|
|
50
50
|
"@alanscodelog/semantic-release-config": "^6.0.2",
|
|
51
51
|
"@alanscodelog/tsconfigs": "^6.3.0",
|
|
52
|
-
"@alanscodelog/vite-config": "^0.0.
|
|
52
|
+
"@alanscodelog/vite-config": "^0.0.7",
|
|
53
53
|
"@commitlint/cli": "^19.8.1",
|
|
54
|
-
"@nuxt/eslint-config": "^1.
|
|
55
|
-
"@nuxt/kit": "^4.
|
|
54
|
+
"@nuxt/eslint-config": "^1.15.2",
|
|
55
|
+
"@nuxt/kit": "^4.4.6",
|
|
56
56
|
"@nuxt/module-builder": "^1.0.2",
|
|
57
|
-
"@nuxt/schema": "^4.
|
|
57
|
+
"@nuxt/schema": "^4.4.6",
|
|
58
58
|
"@nuxt/types": "^2.18.1",
|
|
59
|
-
"@tailwindcss/vite": "^4.
|
|
60
|
-
"@types/node": "^24.
|
|
61
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
62
|
-
"@vitest/coverage-
|
|
59
|
+
"@tailwindcss/vite": "^4.3.0",
|
|
60
|
+
"@types/node": "^24.12.4",
|
|
61
|
+
"@vitejs/plugin-vue": "^6.0.7",
|
|
62
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
63
63
|
"@witchcraft/nuxt-utils": "^0.3.6",
|
|
64
|
-
"@witchcraft/ui": "^0.4.
|
|
64
|
+
"@witchcraft/ui": "^0.4.4",
|
|
65
65
|
"concurrently": "^9.2.1",
|
|
66
|
-
"cross-env": "^10.
|
|
66
|
+
"cross-env": "^10.1.0",
|
|
67
67
|
"fast-glob": "^3.3.3",
|
|
68
68
|
"http-server": "^14.1.1",
|
|
69
69
|
"husky": "^9.1.7",
|
|
70
70
|
"indexit": "2.1.0-beta.3",
|
|
71
71
|
"madge": "^8.0.0",
|
|
72
|
-
"nuxt": "^4.
|
|
72
|
+
"nuxt": "^4.4.6",
|
|
73
73
|
"onchange": "^7.1.0",
|
|
74
|
-
"semantic-release": "^24.2.
|
|
75
|
-
"tailwindcss": "^4.
|
|
76
|
-
"typedoc": "0.28.
|
|
77
|
-
"typescript": "^5.
|
|
78
|
-
"unplugin-icons": "^22.
|
|
79
|
-
"unplugin-vue-components": "^29.
|
|
80
|
-
"uuid": "^13.0.
|
|
81
|
-
"vite": "^7.
|
|
74
|
+
"semantic-release": "^24.2.9",
|
|
75
|
+
"tailwindcss": "^4.3.0",
|
|
76
|
+
"typedoc": "0.28.19",
|
|
77
|
+
"typescript": "^5.9.3",
|
|
78
|
+
"unplugin-icons": "^22.5.0",
|
|
79
|
+
"unplugin-vue-components": "^29.2.0",
|
|
80
|
+
"uuid": "^13.0.2",
|
|
81
|
+
"vite": "^7.3.3",
|
|
82
82
|
"vitest": "^3.2.4",
|
|
83
|
-
"vue": "^3.5.
|
|
83
|
+
"vue": "^3.5.34",
|
|
84
84
|
"vue-tsc": "^2.2.12",
|
|
85
|
-
"zod": "^4.
|
|
85
|
+
"zod": "^4.4.3"
|
|
86
86
|
},
|
|
87
87
|
"author": "Alan <alanscodelog@gmail.com>",
|
|
88
88
|
"repository": "https://github.com/witchcraftjs/layout",
|
|
@@ -132,15 +132,14 @@
|
|
|
132
132
|
"dev:vite": "vite --mode development --config vite.dev.config.ts",
|
|
133
133
|
"//dev": "The module needs to be build, not stubbed, for vite's dev to work.",
|
|
134
134
|
"dev": "pnpm dev:vite",
|
|
135
|
-
"lint:eslint": "eslint \"{src,tests,bin}/**/*.{cjs,js,ts}\" \"*.{cjs,js,ts}\" --max-warnings=
|
|
135
|
+
"lint:eslint": "eslint \"{src,tests,bin}/**/*.{cjs,js,ts}\" \"*.{cjs,js,ts}\" --max-warnings=0 --report-unused-disable-directives",
|
|
136
136
|
"lint:commits": "commitlint --from-last-tag --to HEAD --verbose",
|
|
137
137
|
"lint:imports": "echo disabled madge --circular --extensions ts ./src",
|
|
138
138
|
"lint": "pnpm lint:eslint && pnpm lint:types && pnpm lint:commits && pnpm lint:imports",
|
|
139
139
|
"lint:types": "vue-tsc --noEmit",
|
|
140
140
|
"coverage": "vitest --coverage",
|
|
141
141
|
"coverage:dev": "vitest --watch --coverage",
|
|
142
|
-
"test": "
|
|
143
|
-
"test:watch": "vitest --watch",
|
|
142
|
+
"test": "vitest",
|
|
144
143
|
"doc": "typedoc",
|
|
145
144
|
"doc:watch": "onchange -i \"src/**/*.ts\" \"typedoc.config.js\" -- pnpm doc",
|
|
146
145
|
"doc:serve": "http-server docs --port=5001",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="cursor-grabbing"
|
|
4
|
+
@pointerdown="handlePointerDown"
|
|
5
|
+
>
|
|
6
|
+
<slot/>
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
import { inject, onBeforeUnmount } from "vue"
|
|
11
|
+
import { dragContextInjectionKey } from "../drag/types.js";
|
|
12
|
+
|
|
13
|
+
const props = defineProps<{
|
|
14
|
+
frameId: string
|
|
15
|
+
}>()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const dragContext = inject(dragContextInjectionKey)
|
|
19
|
+
if (!dragContext) {
|
|
20
|
+
throw new Error("FrameDragHandle must be used inside a LayoutWindow and drag context returned by useFrames must be injected.")
|
|
21
|
+
}
|
|
22
|
+
function handlePointerDown(e: PointerEvent): void {
|
|
23
|
+
e.preventDefault()
|
|
24
|
+
e.stopPropagation()
|
|
25
|
+
dragContext!.dragStart( e,"frame", {frameId: props.frameId})
|
|
26
|
+
}
|
|
27
|
+
onBeforeUnmount(() => {
|
|
28
|
+
dragContext.cancel()
|
|
29
|
+
})
|
|
30
|
+
</script>
|
|
@@ -1,52 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<template
|
|
3
|
-
v-for="(
|
|
4
|
-
|
|
3
|
+
v-for="(shape, i) of shapes"
|
|
4
|
+
:key="`${shape.type}-${i}`"
|
|
5
5
|
>
|
|
6
6
|
<LayoutShapeSquare
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
:css="getShapeSquareCss( deco.shapes.newFrame, `var(--layoutEdgeWidth,2px)`)"
|
|
7
|
+
v-if="shape.type === 'square'"
|
|
8
|
+
:css="getShapeSquareCss(shape.data, `var(--layoutEdgeWidth,2px)`)"
|
|
9
|
+
v-bind="shape.attrs ?? {}"
|
|
12
10
|
/>
|
|
13
11
|
<LayoutShapeSquare
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
:css="getVisualEdgeCss(deco.shapes.edge, {padLongAxis:`var(--layoutEdgeWidth,2px)`})"
|
|
19
|
-
/>
|
|
20
|
-
</template>
|
|
21
|
-
<template
|
|
22
|
-
v-for="deco of closeDecos"
|
|
23
|
-
:key="deco.id"
|
|
24
|
-
>
|
|
25
|
-
<LayoutShapeSquare
|
|
26
|
-
:class="`
|
|
27
|
-
${deco.force ? 'deco-close-force-frame' : 'deco-close-frame'}
|
|
28
|
-
bg-red-500/50
|
|
29
|
-
`"
|
|
30
|
-
:css="getShapeSquareCss( frames[deco.id], `var(--layoutEdgeWidth,2px)`)"
|
|
12
|
+
v-else-if="shape.type === 'edge'"
|
|
13
|
+
:css="getVisualEdgeCss(shape.data, { padLongAxis: 'var(--layoutEdgeWidth,2px)' })"
|
|
14
|
+
v-bind="shape.attrs ?? {}"
|
|
31
15
|
/>
|
|
32
16
|
</template>
|
|
33
17
|
</template>
|
|
34
18
|
<script lang="ts" setup>
|
|
35
|
-
|
|
36
19
|
import LayoutShapeSquare from "./LayoutShapeSquare.vue"
|
|
37
20
|
|
|
38
21
|
import { getShapeSquareCss } from "../helpers/getShapeSquareCss"
|
|
39
22
|
import { getVisualEdgeCss } from "../helpers/getVisualEdgeCss"
|
|
40
|
-
import
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const props = withDefaults(defineProps<{
|
|
44
|
-
frames: LayoutFrames
|
|
45
|
-
splitDecos: SplitDeco[]
|
|
46
|
-
closeDecos: CloseDeco[]
|
|
47
|
-
} >(),{
|
|
48
|
-
})
|
|
49
|
-
|
|
23
|
+
import type { LayoutShape } from "../types/index.js"
|
|
50
24
|
|
|
25
|
+
defineProps<{
|
|
26
|
+
shapes: LayoutShape[]
|
|
27
|
+
}>()
|
|
51
28
|
</script>
|
|
52
|
-
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
z-0
|
|
9
9
|
border-blue-500
|
|
10
10
|
border
|
|
11
|
-
rounded-md
|
|
12
11
|
`,
|
|
13
12
|
($attrs as any).class
|
|
14
13
|
)"
|
|
15
|
-
v-bind="{...$attrs, class: undefined}"
|
|
14
|
+
v-bind="{ ...$attrs, class: undefined }"
|
|
16
15
|
/>
|
|
17
|
-
|
|
16
|
+
|
|
18
17
|
<template
|
|
19
18
|
v-for="css, i of cssDragEdges"
|
|
20
19
|
:key="i"
|
|
@@ -27,9 +26,9 @@
|
|
|
27
26
|
hover:cursor-pointer
|
|
28
27
|
[&:hover+.edge]:bg-blue-500/50
|
|
29
28
|
`)"
|
|
30
|
-
@pointerdown="emit('dragStart', $event, {edge:edges[i]})"
|
|
29
|
+
@pointerdown="emit('dragStart', $event, 'edge', { edge: edges[i] })"
|
|
31
30
|
/>
|
|
32
|
-
|
|
31
|
+
<LayoutShapeSquare
|
|
33
32
|
:css="css.thin"
|
|
34
33
|
:class="twMerge(`
|
|
35
34
|
pointer-events-none
|
|
@@ -48,7 +47,10 @@
|
|
|
48
47
|
v-for="css, i of cssDragEdge"
|
|
49
48
|
:key="i"
|
|
50
49
|
/>
|
|
51
|
-
<template
|
|
50
|
+
<template
|
|
51
|
+
v-for="css, i of cssDragIntersections"
|
|
52
|
+
:key="i"
|
|
53
|
+
>
|
|
52
54
|
<LayoutShapeSquare
|
|
53
55
|
:css="css.thick"
|
|
54
56
|
:class="twMerge(`
|
|
@@ -57,9 +59,9 @@
|
|
|
57
59
|
rounded-full
|
|
58
60
|
hover:cursor-pointer
|
|
59
61
|
[&:hover+.intersection]:bg-blue-500/50
|
|
60
|
-
|
|
62
|
+
`
|
|
61
63
|
)"
|
|
62
|
-
@pointerdown="emit('dragStart', $event, { intersection:wantedIntersections[i]})"
|
|
64
|
+
@pointerdown="emit('dragStart', $event, 'edge', { intersection: wantedIntersections[i] })"
|
|
63
65
|
/>
|
|
64
66
|
<LayoutShapeSquare
|
|
65
67
|
:css="css.thin"
|
|
@@ -69,14 +71,15 @@
|
|
|
69
71
|
rounded-full
|
|
70
72
|
pointer-events-none
|
|
71
73
|
`,
|
|
72
|
-
css.thin._shifted && `w-[7px] h-[7px]
|
|
74
|
+
css.thin._shifted && `w-[7px] h-[7px]`
|
|
73
75
|
)"
|
|
74
76
|
/>
|
|
75
77
|
</template>
|
|
76
78
|
</template>
|
|
79
|
+
|
|
77
80
|
<script lang="ts" setup>
|
|
78
81
|
import { twMerge } from "@witchcraft/ui/utils/twMerge"
|
|
79
|
-
import { computed,useAttrs } from "vue"
|
|
82
|
+
import { computed, useAttrs } from "vue"
|
|
80
83
|
|
|
81
84
|
import LayoutShapeSquare from "./LayoutShapeSquare.vue"
|
|
82
85
|
|
|
@@ -84,25 +87,27 @@ import { getIntersectionsCss } from "../helpers/getIntersectionsCss.js"
|
|
|
84
87
|
import { getShapeSquareCss } from "../helpers/getShapeSquareCss.js"
|
|
85
88
|
import { getVisualEdgesCss } from "../helpers/getVisualEdgesCss.js"
|
|
86
89
|
import { isEdgeEqual } from "../helpers/isEdgeEqual.js"
|
|
87
|
-
import {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
import type {
|
|
91
|
+
Edge,
|
|
92
|
+
EdgeCss,
|
|
93
|
+
IntersectionEntry,
|
|
94
|
+
LayoutEdgesProps
|
|
92
95
|
} from "../types/index.js"
|
|
96
|
+
|
|
93
97
|
const $attrs = useAttrs()
|
|
94
98
|
|
|
95
99
|
defineOptions({
|
|
96
|
-
inheritAttrs: false
|
|
100
|
+
inheritAttrs: false
|
|
97
101
|
})
|
|
98
102
|
|
|
99
103
|
const emit = defineEmits<{
|
|
100
|
-
dragStart: [e: PointerEvent, { edge?: Edge, intersection?: IntersectionEntry }]
|
|
104
|
+
dragStart: [e: PointerEvent, type:"edge", opts:{ edge?: Edge, intersection?: IntersectionEntry }]
|
|
101
105
|
}>()
|
|
106
|
+
|
|
102
107
|
const props = withDefaults(defineProps<LayoutEdgesProps>(), {
|
|
103
108
|
activeFrame: undefined,
|
|
104
109
|
draggingEdge: undefined,
|
|
105
|
-
draggingIntersection: undefined
|
|
110
|
+
draggingIntersection: undefined
|
|
106
111
|
})
|
|
107
112
|
|
|
108
113
|
|
|
@@ -120,12 +125,12 @@ const cssDragEdges = computed(() => {
|
|
|
120
125
|
: props.edges,
|
|
121
126
|
{
|
|
122
127
|
edgeWidth: `var(--layoutHandleWidth, 8px)`,
|
|
123
|
-
padLongAxis: `var(--layoutEdgeWidth, 2px)
|
|
128
|
+
padLongAxis: `var(--layoutEdgeWidth, 2px)`
|
|
124
129
|
}
|
|
125
130
|
)
|
|
126
131
|
const thinEdges = getVisualEdgesCss(props.edges, {
|
|
127
132
|
edgeWidth: `var(--layoutEdgeWidth, 2px)`,
|
|
128
|
-
padLongAxis: `(var(--layoutEdgeWidth, 2px) + var(--layoutExtraDragEdgePadding, 0px))
|
|
133
|
+
padLongAxis: `(var(--layoutEdgeWidth, 2px) + var(--layoutExtraDragEdgePadding, 0px))`
|
|
129
134
|
})
|
|
130
135
|
const edges: { thin: EdgeCss, thick: EdgeCss }[] = []
|
|
131
136
|
for (let i = 0; i < thickEdges.length; i++) {
|
|
@@ -138,7 +143,7 @@ const cssDragEdge = computed(() => {
|
|
|
138
143
|
if (!props.draggingEdge) return []
|
|
139
144
|
return getVisualEdgesCss([props.draggingEdge], {
|
|
140
145
|
edgeWidth: `var(--layoutEdgeWidth, 2px)`,
|
|
141
|
-
padLongAxis: `(var(--layoutEdgeWidth, 2px) + var(--layoutExtraDragEdgePadding, 0px))
|
|
146
|
+
padLongAxis: `(var(--layoutEdgeWidth, 2px) + var(--layoutExtraDragEdgePadding, 0px))`
|
|
142
147
|
})
|
|
143
148
|
})
|
|
144
149
|
|
|
@@ -152,7 +157,7 @@ const cssDragIntersections = computed(() => {
|
|
|
152
157
|
thin: ReturnType<typeof getIntersectionsCss>[number]
|
|
153
158
|
}[] = []
|
|
154
159
|
const thick = getIntersectionsCss(wantedIntersections.value, {
|
|
155
|
-
intersectionWidth: `var(--layoutIntersectionWidth, 15px)
|
|
160
|
+
intersectionWidth: `var(--layoutIntersectionWidth, 15px)`
|
|
156
161
|
})
|
|
157
162
|
const thin = getIntersectionsCss(wantedIntersections.value, {
|
|
158
163
|
})
|
|
@@ -161,6 +166,5 @@ const cssDragIntersections = computed(() => {
|
|
|
161
166
|
}
|
|
162
167
|
return intersections
|
|
163
168
|
})
|
|
164
|
-
|
|
165
169
|
</script>
|
|
166
170
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
`,
|
|
11
11
|
($attrs as any).class
|
|
12
12
|
)"
|
|
13
|
-
v-bind="{...$attrs, class: undefined}"
|
|
13
|
+
v-bind="{ ...$attrs, class: undefined }"
|
|
14
14
|
@focus="emit('focus')"
|
|
15
15
|
>
|
|
16
16
|
<slot>
|
|
@@ -21,20 +21,22 @@
|
|
|
21
21
|
</slot>
|
|
22
22
|
</LayoutShapeSquare>
|
|
23
23
|
</template>
|
|
24
|
+
|
|
24
25
|
<script lang="ts" setup>
|
|
25
26
|
import { twMerge } from "@witchcraft/ui/utils/twMerge"
|
|
26
27
|
import { useAttrs } from "vue"
|
|
28
|
+
|
|
27
29
|
const $attrs = useAttrs()
|
|
28
30
|
|
|
29
31
|
defineOptions({
|
|
30
|
-
inheritAttrs: false
|
|
32
|
+
inheritAttrs: false
|
|
31
33
|
})
|
|
32
34
|
|
|
33
35
|
import LayoutShapeSquare from "./LayoutShapeSquare.vue"
|
|
34
36
|
|
|
35
37
|
import { getShapeSquareCss } from "../helpers/getShapeSquareCss"
|
|
36
38
|
import { debugFrame } from "../layout/debugFrame.js"
|
|
37
|
-
import {
|
|
39
|
+
import type { LayoutFrameProps } from "../types/index.js"
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
const emit = defineEmits<{
|
|
@@ -42,6 +44,5 @@ const emit = defineEmits<{
|
|
|
42
44
|
(e: "focus"): void
|
|
43
45
|
}>()
|
|
44
46
|
|
|
45
|
-
/* const props = */defineProps<LayoutFrameProps>(
|
|
46
|
-
)
|
|
47
|
+
/* const props = */defineProps<LayoutFrameProps>()
|
|
47
48
|
</script>
|
|
@@ -17,21 +17,27 @@
|
|
|
17
17
|
css.translate && `[transform:var(--translate)]`,
|
|
18
18
|
($attrs as any).class
|
|
19
19
|
)"
|
|
20
|
-
v-bind="{...$attrs, class: undefined}"
|
|
20
|
+
v-bind="{ ...$attrs, class: undefined }"
|
|
21
21
|
>
|
|
22
22
|
<slot/>
|
|
23
23
|
</div>
|
|
24
24
|
</template>
|
|
25
|
+
|
|
25
26
|
<script setup lang="ts">
|
|
26
27
|
import { twMerge } from "@witchcraft/ui/utils/twMerge"
|
|
27
28
|
import { useAttrs } from "vue"
|
|
29
|
+
import type { HTMLAttributes } from "vue"
|
|
28
30
|
|
|
29
31
|
import type { LayoutShapeSquareProps } from "../types/index.js"
|
|
32
|
+
|
|
30
33
|
const $attrs = useAttrs()
|
|
31
34
|
|
|
32
35
|
defineOptions({
|
|
33
|
-
inheritAttrs: false
|
|
36
|
+
inheritAttrs: false
|
|
34
37
|
})
|
|
35
38
|
|
|
36
|
-
const props = defineProps<
|
|
39
|
+
const props = defineProps<
|
|
40
|
+
& LayoutShapeSquareProps
|
|
41
|
+
& /** @vue-ignore */ HTMLAttributes
|
|
42
|
+
>()
|
|
37
43
|
</script>
|