@woven-canvas/core 0.1.3 → 1.0.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/build/_tsup-dts-rollup.d.cts +28 -4
- package/build/_tsup-dts-rollup.d.ts +28 -4
- package/build/index.cjs +308 -263
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +3 -1
- package/build/index.d.ts +3 -1
- package/build/index.js +311 -269
- package/build/index.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
EventType,
|
|
22
22
|
field as field28,
|
|
23
23
|
getBackrefs,
|
|
24
|
-
getResources as
|
|
24
|
+
getResources as getResources13,
|
|
25
25
|
hasComponent as hasComponent7,
|
|
26
26
|
isAlive,
|
|
27
27
|
MainThreadSystem as MainThreadSystem2,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
CanvasComponentDef as CanvasComponentDef6,
|
|
36
36
|
CanvasSingletonDef as CanvasSingletonDef10
|
|
37
37
|
} from "@woven-ecs/canvas-store";
|
|
38
|
-
import { getResources as
|
|
38
|
+
import { getResources as getResources12 } from "@woven-ecs/core";
|
|
39
39
|
|
|
40
40
|
// src/components/index.ts
|
|
41
41
|
var components_exports = {};
|
|
@@ -75,6 +75,261 @@ import { field as field2 } from "@woven-ecs/core";
|
|
|
75
75
|
import { Rect, Vec2 } from "@woven-canvas/math";
|
|
76
76
|
import { CanvasComponentDef } from "@woven-ecs/canvas-store";
|
|
77
77
|
import { field } from "@woven-ecs/core";
|
|
78
|
+
|
|
79
|
+
// src/types.ts
|
|
80
|
+
import { z } from "zod";
|
|
81
|
+
function generateUserColor() {
|
|
82
|
+
const colors = [
|
|
83
|
+
"#f43f5e",
|
|
84
|
+
// rose
|
|
85
|
+
"#ec4899",
|
|
86
|
+
// pink
|
|
87
|
+
"#a855f7",
|
|
88
|
+
// purple
|
|
89
|
+
"#6366f1",
|
|
90
|
+
// indigo
|
|
91
|
+
"#3b82f6",
|
|
92
|
+
// blue
|
|
93
|
+
"#0ea5e9",
|
|
94
|
+
// sky
|
|
95
|
+
"#14b8a6",
|
|
96
|
+
// teal
|
|
97
|
+
"#22c55e",
|
|
98
|
+
// green
|
|
99
|
+
"#eab308",
|
|
100
|
+
// yellow
|
|
101
|
+
"#f97316"
|
|
102
|
+
// orange
|
|
103
|
+
];
|
|
104
|
+
return colors[Math.floor(Math.random() * colors.length)];
|
|
105
|
+
}
|
|
106
|
+
var UserData = z.object({
|
|
107
|
+
userId: z.string().max(36).default(() => crypto.randomUUID()),
|
|
108
|
+
sessionId: z.string().max(36).default(() => crypto.randomUUID()),
|
|
109
|
+
color: z.string().max(7).default(generateUserColor),
|
|
110
|
+
name: z.string().max(100).default("Anonymous"),
|
|
111
|
+
avatar: z.string().max(500).default("")
|
|
112
|
+
});
|
|
113
|
+
function getPluginResources(ctx, pluginName) {
|
|
114
|
+
const resources = ctx.resources;
|
|
115
|
+
return resources.pluginResources[pluginName];
|
|
116
|
+
}
|
|
117
|
+
var GridOptions = z.object({
|
|
118
|
+
/**
|
|
119
|
+
* Whether grid snapping is enabled.
|
|
120
|
+
* @default true
|
|
121
|
+
*/
|
|
122
|
+
enabled: z.boolean().default(true),
|
|
123
|
+
/**
|
|
124
|
+
* Whether resized/rotated objects must stay aligned to the grid.
|
|
125
|
+
* If true, objects snap to grid during resize/rotate.
|
|
126
|
+
* If false, objects scale proportionally to the transform box, which may
|
|
127
|
+
* cause them to be unaligned with the grid.
|
|
128
|
+
* @default false
|
|
129
|
+
*/
|
|
130
|
+
strict: z.boolean().default(false),
|
|
131
|
+
/**
|
|
132
|
+
* Width of each grid column in world units.
|
|
133
|
+
* @default 20
|
|
134
|
+
*/
|
|
135
|
+
colWidth: z.number().nonnegative().default(20),
|
|
136
|
+
/**
|
|
137
|
+
* Height of each grid row in world units.
|
|
138
|
+
* @default 20
|
|
139
|
+
*/
|
|
140
|
+
rowHeight: z.number().nonnegative().default(20),
|
|
141
|
+
/**
|
|
142
|
+
* Angular snap increment in radians when grid is enabled.
|
|
143
|
+
* @default Math.PI / 36 (5 degrees)
|
|
144
|
+
*/
|
|
145
|
+
snapAngleRad: z.number().nonnegative().default(Math.PI / 36),
|
|
146
|
+
/**
|
|
147
|
+
* Angular snap increment in radians when shift key is held.
|
|
148
|
+
* @default Math.PI / 12 (15 degrees)
|
|
149
|
+
*/
|
|
150
|
+
shiftSnapAngleRad: z.number().nonnegative().default(Math.PI / 12)
|
|
151
|
+
});
|
|
152
|
+
var ControlsOptions = z.object({
|
|
153
|
+
/**
|
|
154
|
+
* Tool activated by left mouse button.
|
|
155
|
+
* @default 'select'
|
|
156
|
+
*/
|
|
157
|
+
leftMouseTool: z.string().max(32).default("select"),
|
|
158
|
+
/**
|
|
159
|
+
* Tool activated by middle mouse button.
|
|
160
|
+
* @default 'hand'
|
|
161
|
+
*/
|
|
162
|
+
middleMouseTool: z.string().max(32).default("hand"),
|
|
163
|
+
/**
|
|
164
|
+
* Tool activated by right mouse button.
|
|
165
|
+
* @default 'menu'
|
|
166
|
+
*/
|
|
167
|
+
rightMouseTool: z.string().max(32).default("menu"),
|
|
168
|
+
/**
|
|
169
|
+
* Tool activated by mouse wheel.
|
|
170
|
+
* @default 'scroll'
|
|
171
|
+
*/
|
|
172
|
+
wheelTool: z.string().max(32).default("scroll"),
|
|
173
|
+
/**
|
|
174
|
+
* Tool activated by mouse wheel with modifier key held.
|
|
175
|
+
* @default 'zoom'
|
|
176
|
+
*/
|
|
177
|
+
modWheelTool: z.string().max(32).default("zoom")
|
|
178
|
+
});
|
|
179
|
+
var EditorOptionsSchema = z.object({
|
|
180
|
+
/**
|
|
181
|
+
* Plugins to load.
|
|
182
|
+
* Plugins are sorted by dependencies automatically.
|
|
183
|
+
*/
|
|
184
|
+
plugins: z.array(z.custom()).default([]),
|
|
185
|
+
/**
|
|
186
|
+
* Maximum number of entities.
|
|
187
|
+
* @default 5_000
|
|
188
|
+
*/
|
|
189
|
+
maxEntities: z.number().default(5e3),
|
|
190
|
+
/**
|
|
191
|
+
* User data for presence tracking.
|
|
192
|
+
* All fields are optional - defaults will be applied.
|
|
193
|
+
*/
|
|
194
|
+
user: z.custom().default({}),
|
|
195
|
+
/**
|
|
196
|
+
* Grid configuration for snap-to-grid behavior.
|
|
197
|
+
* All fields are optional - defaults will be applied.
|
|
198
|
+
*/
|
|
199
|
+
grid: z.custom().default({}),
|
|
200
|
+
/**
|
|
201
|
+
* Custom block definitions.
|
|
202
|
+
* Accepts partial block definitions - defaults will be applied automatically.
|
|
203
|
+
*/
|
|
204
|
+
blockDefs: z.array(z.custom()).default([]),
|
|
205
|
+
/**
|
|
206
|
+
* Keybind definitions for keyboard shortcuts.
|
|
207
|
+
* These map key combinations to plugin commands.
|
|
208
|
+
*/
|
|
209
|
+
keybinds: z.array(z.custom()).default([]),
|
|
210
|
+
/**
|
|
211
|
+
* Custom cursor definitions.
|
|
212
|
+
* Override default cursors or define new ones for transform operations.
|
|
213
|
+
*/
|
|
214
|
+
cursors: z.record(z.string(), z.custom()).default({}),
|
|
215
|
+
/**
|
|
216
|
+
* Custom components to register without creating a plugin.
|
|
217
|
+
*/
|
|
218
|
+
components: z.array(z.custom()).default([]),
|
|
219
|
+
/**
|
|
220
|
+
* Custom singletons to register without creating a plugin.
|
|
221
|
+
*/
|
|
222
|
+
singletons: z.array(z.custom()).default([]),
|
|
223
|
+
/**
|
|
224
|
+
* Custom systems to register without creating a plugin.
|
|
225
|
+
* Each system specifies its phase and priority.
|
|
226
|
+
*/
|
|
227
|
+
systems: z.array(z.custom()).default([]),
|
|
228
|
+
/**
|
|
229
|
+
* Custom font families to load and make available in the font selector.
|
|
230
|
+
* Fonts will be loaded automatically during editor initialization.
|
|
231
|
+
*/
|
|
232
|
+
fonts: z.array(z.custom()).default([]),
|
|
233
|
+
/**
|
|
234
|
+
* If true, keybinds from plugins will be ignored.
|
|
235
|
+
* Use this when you want full control over keybinds.
|
|
236
|
+
*/
|
|
237
|
+
omitPluginKeybinds: z.boolean().default(false),
|
|
238
|
+
/**
|
|
239
|
+
* If true, cursors from plugins will be ignored.
|
|
240
|
+
* Use this when you want full control over cursors.
|
|
241
|
+
*/
|
|
242
|
+
omitPluginCursors: z.boolean().default(false),
|
|
243
|
+
/**
|
|
244
|
+
* If true, fonts from plugins will be ignored.
|
|
245
|
+
* Use this when you want full control over fonts.
|
|
246
|
+
*/
|
|
247
|
+
omitPluginFonts: z.boolean().default(false),
|
|
248
|
+
/**
|
|
249
|
+
* Initial controls configuration.
|
|
250
|
+
* Override default tool mappings for mouse buttons, wheel, etc.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* controls: {
|
|
255
|
+
* leftMouseTool: 'pen', // Start with pen tool active
|
|
256
|
+
* middleMouseTool: 'hand', // Middle mouse pans
|
|
257
|
+
* }
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
controls: z.custom().optional()
|
|
261
|
+
});
|
|
262
|
+
var Keybind = z.object({
|
|
263
|
+
/** The command to execute when this keybind is triggered */
|
|
264
|
+
command: z.string(),
|
|
265
|
+
/** The key index from the Key constants (e.g., Key.A, Key.Delete) */
|
|
266
|
+
key: z.number(),
|
|
267
|
+
/** Whether the modifier key (Cmd on Mac, Ctrl on Windows) must be held */
|
|
268
|
+
mod: z.boolean().optional(),
|
|
269
|
+
/** Whether the Shift key must be held */
|
|
270
|
+
shift: z.boolean().optional()
|
|
271
|
+
});
|
|
272
|
+
var CursorDef = z.object({
|
|
273
|
+
/** Function that generates the SVG string for a given rotation angle (in radians) */
|
|
274
|
+
makeSvg: z.function({ input: z.tuple([z.number()]), output: z.string() }),
|
|
275
|
+
/** Hotspot coordinates [x, y] for the cursor */
|
|
276
|
+
hotspot: z.tuple([z.number(), z.number()]),
|
|
277
|
+
/** Base rotation offset applied before the dynamic rotation */
|
|
278
|
+
rotationOffset: z.number()
|
|
279
|
+
});
|
|
280
|
+
var ResizeMode = {
|
|
281
|
+
Default: "default",
|
|
282
|
+
Scale: "scale",
|
|
283
|
+
Text: "text",
|
|
284
|
+
Free: "free",
|
|
285
|
+
GroupOnly: "groupOnly"
|
|
286
|
+
};
|
|
287
|
+
var VerticalAlignment = {
|
|
288
|
+
Top: "top",
|
|
289
|
+
Center: "center",
|
|
290
|
+
Bottom: "bottom"
|
|
291
|
+
};
|
|
292
|
+
var TextAlignment = {
|
|
293
|
+
Left: "left",
|
|
294
|
+
Center: "center",
|
|
295
|
+
Right: "right",
|
|
296
|
+
Justify: "justify"
|
|
297
|
+
};
|
|
298
|
+
var BlockDefEditOptions = z.object({
|
|
299
|
+
canEdit: z.boolean().default(false),
|
|
300
|
+
removeWhenTextEmpty: z.boolean().default(false)
|
|
301
|
+
});
|
|
302
|
+
var BlockDefConnectors = z.object({
|
|
303
|
+
/** Whether connectors are enabled for this block type */
|
|
304
|
+
enabled: z.boolean().default(true),
|
|
305
|
+
/** UV coordinates of terminal positions (0-1 range, where [0,0] is top-left) */
|
|
306
|
+
terminals: z.array(z.tuple([z.number(), z.number()])).default([
|
|
307
|
+
[0.5, 0],
|
|
308
|
+
// top
|
|
309
|
+
[0.5, 1],
|
|
310
|
+
// bottom
|
|
311
|
+
[0.5, 0.5],
|
|
312
|
+
// center
|
|
313
|
+
[0, 0.5],
|
|
314
|
+
// left
|
|
315
|
+
[1, 0.5]
|
|
316
|
+
// right
|
|
317
|
+
])
|
|
318
|
+
});
|
|
319
|
+
var Stratum = z.enum(["background", "content", "overlay"]);
|
|
320
|
+
var BlockDef = z.object({
|
|
321
|
+
tag: z.string(),
|
|
322
|
+
stratum: Stratum.default("content"),
|
|
323
|
+
editOptions: BlockDefEditOptions.default(BlockDefEditOptions.parse({})),
|
|
324
|
+
components: z.array(z.custom()).default([]),
|
|
325
|
+
resizeMode: z.enum([ResizeMode.Scale, ResizeMode.Text, ResizeMode.Free, ResizeMode.GroupOnly]).default(ResizeMode.Scale),
|
|
326
|
+
canRotate: z.boolean().default(true),
|
|
327
|
+
canScale: z.boolean().default(true),
|
|
328
|
+
selectable: z.boolean().default(true),
|
|
329
|
+
connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// src/components/Block.ts
|
|
78
333
|
var _aabbCorners = [
|
|
79
334
|
[0, 0],
|
|
80
335
|
[0, 0],
|
|
@@ -103,9 +358,11 @@ var BlockSchema = {
|
|
|
103
358
|
/** Flip state as [flipX, flipY] */
|
|
104
359
|
flip: field.tuple(field.boolean(), 2).default([false, false]),
|
|
105
360
|
/** Z-order rank (LexoRank string) */
|
|
106
|
-
rank: field.string().max(36).default("")
|
|
361
|
+
rank: field.string().max(36).default(""),
|
|
362
|
+
/** How the block can be resized */
|
|
363
|
+
resizeMode: field.enum(ResizeMode).default(ResizeMode.Default)
|
|
107
364
|
};
|
|
108
|
-
var
|
|
365
|
+
var BlockDef2 = class extends CanvasComponentDef {
|
|
109
366
|
constructor() {
|
|
110
367
|
super({ name: "block", sync: "document" }, BlockSchema);
|
|
111
368
|
}
|
|
@@ -247,7 +504,7 @@ var BlockDef = class extends CanvasComponentDef {
|
|
|
247
504
|
}
|
|
248
505
|
}
|
|
249
506
|
};
|
|
250
|
-
var Block = new
|
|
507
|
+
var Block = new BlockDef2();
|
|
251
508
|
|
|
252
509
|
// src/components/Aabb.ts
|
|
253
510
|
var LEFT = 0;
|
|
@@ -1030,253 +1287,6 @@ var Shape = defineCanvasComponent9(
|
|
|
1030
1287
|
// src/components/Text.ts
|
|
1031
1288
|
import { defineCanvasComponent as defineCanvasComponent10 } from "@woven-ecs/canvas-store";
|
|
1032
1289
|
import { field as field13 } from "@woven-ecs/core";
|
|
1033
|
-
|
|
1034
|
-
// src/types.ts
|
|
1035
|
-
import { z } from "zod";
|
|
1036
|
-
function generateUserColor() {
|
|
1037
|
-
const colors = [
|
|
1038
|
-
"#f43f5e",
|
|
1039
|
-
// rose
|
|
1040
|
-
"#ec4899",
|
|
1041
|
-
// pink
|
|
1042
|
-
"#a855f7",
|
|
1043
|
-
// purple
|
|
1044
|
-
"#6366f1",
|
|
1045
|
-
// indigo
|
|
1046
|
-
"#3b82f6",
|
|
1047
|
-
// blue
|
|
1048
|
-
"#0ea5e9",
|
|
1049
|
-
// sky
|
|
1050
|
-
"#14b8a6",
|
|
1051
|
-
// teal
|
|
1052
|
-
"#22c55e",
|
|
1053
|
-
// green
|
|
1054
|
-
"#eab308",
|
|
1055
|
-
// yellow
|
|
1056
|
-
"#f97316"
|
|
1057
|
-
// orange
|
|
1058
|
-
];
|
|
1059
|
-
return colors[Math.floor(Math.random() * colors.length)];
|
|
1060
|
-
}
|
|
1061
|
-
var UserData = z.object({
|
|
1062
|
-
userId: z.string().max(36).default(() => crypto.randomUUID()),
|
|
1063
|
-
sessionId: z.string().max(36).default(() => crypto.randomUUID()),
|
|
1064
|
-
color: z.string().max(7).default(generateUserColor),
|
|
1065
|
-
name: z.string().max(100).default("Anonymous"),
|
|
1066
|
-
avatar: z.string().max(500).default("")
|
|
1067
|
-
});
|
|
1068
|
-
function getPluginResources(ctx, pluginName) {
|
|
1069
|
-
const resources = ctx.resources;
|
|
1070
|
-
return resources.pluginResources[pluginName];
|
|
1071
|
-
}
|
|
1072
|
-
var GridOptions = z.object({
|
|
1073
|
-
/**
|
|
1074
|
-
* Whether grid snapping is enabled.
|
|
1075
|
-
* @default true
|
|
1076
|
-
*/
|
|
1077
|
-
enabled: z.boolean().default(true),
|
|
1078
|
-
/**
|
|
1079
|
-
* Whether resized/rotated objects must stay aligned to the grid.
|
|
1080
|
-
* If true, objects snap to grid during resize/rotate.
|
|
1081
|
-
* If false, objects scale proportionally to the transform box, which may
|
|
1082
|
-
* cause them to be unaligned with the grid.
|
|
1083
|
-
* @default false
|
|
1084
|
-
*/
|
|
1085
|
-
strict: z.boolean().default(false),
|
|
1086
|
-
/**
|
|
1087
|
-
* Width of each grid column in world units.
|
|
1088
|
-
* @default 20
|
|
1089
|
-
*/
|
|
1090
|
-
colWidth: z.number().nonnegative().default(20),
|
|
1091
|
-
/**
|
|
1092
|
-
* Height of each grid row in world units.
|
|
1093
|
-
* @default 20
|
|
1094
|
-
*/
|
|
1095
|
-
rowHeight: z.number().nonnegative().default(20),
|
|
1096
|
-
/**
|
|
1097
|
-
* Angular snap increment in radians when grid is enabled.
|
|
1098
|
-
* @default Math.PI / 36 (5 degrees)
|
|
1099
|
-
*/
|
|
1100
|
-
snapAngleRad: z.number().nonnegative().default(Math.PI / 36),
|
|
1101
|
-
/**
|
|
1102
|
-
* Angular snap increment in radians when shift key is held.
|
|
1103
|
-
* @default Math.PI / 12 (15 degrees)
|
|
1104
|
-
*/
|
|
1105
|
-
shiftSnapAngleRad: z.number().nonnegative().default(Math.PI / 12)
|
|
1106
|
-
});
|
|
1107
|
-
var ControlsOptions = z.object({
|
|
1108
|
-
/**
|
|
1109
|
-
* Tool activated by left mouse button.
|
|
1110
|
-
* @default 'select'
|
|
1111
|
-
*/
|
|
1112
|
-
leftMouseTool: z.string().max(32).default("select"),
|
|
1113
|
-
/**
|
|
1114
|
-
* Tool activated by middle mouse button.
|
|
1115
|
-
* @default 'hand'
|
|
1116
|
-
*/
|
|
1117
|
-
middleMouseTool: z.string().max(32).default("hand"),
|
|
1118
|
-
/**
|
|
1119
|
-
* Tool activated by right mouse button.
|
|
1120
|
-
* @default 'menu'
|
|
1121
|
-
*/
|
|
1122
|
-
rightMouseTool: z.string().max(32).default("menu"),
|
|
1123
|
-
/**
|
|
1124
|
-
* Tool activated by mouse wheel.
|
|
1125
|
-
* @default 'scroll'
|
|
1126
|
-
*/
|
|
1127
|
-
wheelTool: z.string().max(32).default("scroll"),
|
|
1128
|
-
/**
|
|
1129
|
-
* Tool activated by mouse wheel with modifier key held.
|
|
1130
|
-
* @default 'zoom'
|
|
1131
|
-
*/
|
|
1132
|
-
modWheelTool: z.string().max(32).default("zoom")
|
|
1133
|
-
});
|
|
1134
|
-
var EditorOptionsSchema = z.object({
|
|
1135
|
-
/**
|
|
1136
|
-
* Plugins to load.
|
|
1137
|
-
* Plugins are sorted by dependencies automatically.
|
|
1138
|
-
*/
|
|
1139
|
-
plugins: z.array(z.custom()).default([]),
|
|
1140
|
-
/**
|
|
1141
|
-
* Maximum number of entities.
|
|
1142
|
-
* @default 5_000
|
|
1143
|
-
*/
|
|
1144
|
-
maxEntities: z.number().default(5e3),
|
|
1145
|
-
/**
|
|
1146
|
-
* User data for presence tracking.
|
|
1147
|
-
* All fields are optional - defaults will be applied.
|
|
1148
|
-
*/
|
|
1149
|
-
user: z.custom().default({}),
|
|
1150
|
-
/**
|
|
1151
|
-
* Grid configuration for snap-to-grid behavior.
|
|
1152
|
-
* All fields are optional - defaults will be applied.
|
|
1153
|
-
*/
|
|
1154
|
-
grid: z.custom().default({}),
|
|
1155
|
-
/**
|
|
1156
|
-
* Custom block definitions.
|
|
1157
|
-
* Accepts partial block definitions - defaults will be applied automatically.
|
|
1158
|
-
*/
|
|
1159
|
-
blockDefs: z.array(z.custom()).default([]),
|
|
1160
|
-
/**
|
|
1161
|
-
* Keybind definitions for keyboard shortcuts.
|
|
1162
|
-
* These map key combinations to plugin commands.
|
|
1163
|
-
*/
|
|
1164
|
-
keybinds: z.array(z.custom()).default([]),
|
|
1165
|
-
/**
|
|
1166
|
-
* Custom cursor definitions.
|
|
1167
|
-
* Override default cursors or define new ones for transform operations.
|
|
1168
|
-
*/
|
|
1169
|
-
cursors: z.record(z.string(), z.custom()).default({}),
|
|
1170
|
-
/**
|
|
1171
|
-
* Custom components to register without creating a plugin.
|
|
1172
|
-
*/
|
|
1173
|
-
components: z.array(z.custom()).default([]),
|
|
1174
|
-
/**
|
|
1175
|
-
* Custom singletons to register without creating a plugin.
|
|
1176
|
-
*/
|
|
1177
|
-
singletons: z.array(z.custom()).default([]),
|
|
1178
|
-
/**
|
|
1179
|
-
* Custom systems to register without creating a plugin.
|
|
1180
|
-
* Each system specifies its phase and priority.
|
|
1181
|
-
*/
|
|
1182
|
-
systems: z.array(z.custom()).default([]),
|
|
1183
|
-
/**
|
|
1184
|
-
* Custom font families to load and make available in the font selector.
|
|
1185
|
-
* Fonts will be loaded automatically during editor initialization.
|
|
1186
|
-
*/
|
|
1187
|
-
fonts: z.array(z.custom()).default([]),
|
|
1188
|
-
/**
|
|
1189
|
-
* If true, keybinds from plugins will be ignored.
|
|
1190
|
-
* Use this when you want full control over keybinds.
|
|
1191
|
-
*/
|
|
1192
|
-
omitPluginKeybinds: z.boolean().default(false),
|
|
1193
|
-
/**
|
|
1194
|
-
* If true, cursors from plugins will be ignored.
|
|
1195
|
-
* Use this when you want full control over cursors.
|
|
1196
|
-
*/
|
|
1197
|
-
omitPluginCursors: z.boolean().default(false),
|
|
1198
|
-
/**
|
|
1199
|
-
* If true, fonts from plugins will be ignored.
|
|
1200
|
-
* Use this when you want full control over fonts.
|
|
1201
|
-
*/
|
|
1202
|
-
omitPluginFonts: z.boolean().default(false),
|
|
1203
|
-
/**
|
|
1204
|
-
* Initial controls configuration.
|
|
1205
|
-
* Override default tool mappings for mouse buttons, wheel, etc.
|
|
1206
|
-
*
|
|
1207
|
-
* @example
|
|
1208
|
-
* ```typescript
|
|
1209
|
-
* controls: {
|
|
1210
|
-
* leftMouseTool: 'pen', // Start with pen tool active
|
|
1211
|
-
* middleMouseTool: 'hand', // Middle mouse pans
|
|
1212
|
-
* }
|
|
1213
|
-
* ```
|
|
1214
|
-
*/
|
|
1215
|
-
controls: z.custom().optional()
|
|
1216
|
-
});
|
|
1217
|
-
var Keybind = z.object({
|
|
1218
|
-
/** The command to execute when this keybind is triggered */
|
|
1219
|
-
command: z.string(),
|
|
1220
|
-
/** The key index from the Key constants (e.g., Key.A, Key.Delete) */
|
|
1221
|
-
key: z.number(),
|
|
1222
|
-
/** Whether the modifier key (Cmd on Mac, Ctrl on Windows) must be held */
|
|
1223
|
-
mod: z.boolean().optional(),
|
|
1224
|
-
/** Whether the Shift key must be held */
|
|
1225
|
-
shift: z.boolean().optional()
|
|
1226
|
-
});
|
|
1227
|
-
var CursorDef = z.object({
|
|
1228
|
-
/** Function that generates the SVG string for a given rotation angle (in radians) */
|
|
1229
|
-
makeSvg: z.function({ input: z.tuple([z.number()]), output: z.string() }),
|
|
1230
|
-
/** Hotspot coordinates [x, y] for the cursor */
|
|
1231
|
-
hotspot: z.tuple([z.number(), z.number()]),
|
|
1232
|
-
/** Base rotation offset applied before the dynamic rotation */
|
|
1233
|
-
rotationOffset: z.number()
|
|
1234
|
-
});
|
|
1235
|
-
var VerticalAlignment = {
|
|
1236
|
-
Top: "top",
|
|
1237
|
-
Center: "center",
|
|
1238
|
-
Bottom: "bottom"
|
|
1239
|
-
};
|
|
1240
|
-
var TextAlignment = {
|
|
1241
|
-
Left: "left",
|
|
1242
|
-
Center: "center",
|
|
1243
|
-
Right: "right",
|
|
1244
|
-
Justify: "justify"
|
|
1245
|
-
};
|
|
1246
|
-
var BlockDefEditOptions = z.object({
|
|
1247
|
-
canEdit: z.boolean().default(false),
|
|
1248
|
-
removeWhenTextEmpty: z.boolean().default(false)
|
|
1249
|
-
});
|
|
1250
|
-
var BlockDefConnectors = z.object({
|
|
1251
|
-
/** Whether connectors are enabled for this block type */
|
|
1252
|
-
enabled: z.boolean().default(true),
|
|
1253
|
-
/** UV coordinates of terminal positions (0-1 range, where [0,0] is top-left) */
|
|
1254
|
-
terminals: z.array(z.tuple([z.number(), z.number()])).default([
|
|
1255
|
-
[0.5, 0],
|
|
1256
|
-
// top
|
|
1257
|
-
[0.5, 1],
|
|
1258
|
-
// bottom
|
|
1259
|
-
[0.5, 0.5],
|
|
1260
|
-
// center
|
|
1261
|
-
[0, 0.5],
|
|
1262
|
-
// left
|
|
1263
|
-
[1, 0.5]
|
|
1264
|
-
// right
|
|
1265
|
-
])
|
|
1266
|
-
});
|
|
1267
|
-
var Stratum = z.enum(["background", "content", "overlay"]);
|
|
1268
|
-
var BlockDef2 = z.object({
|
|
1269
|
-
tag: z.string(),
|
|
1270
|
-
stratum: Stratum.default("content"),
|
|
1271
|
-
editOptions: BlockDefEditOptions.default(BlockDefEditOptions.parse({})),
|
|
1272
|
-
components: z.array(z.custom()).default([]),
|
|
1273
|
-
resizeMode: z.enum(["scale", "text", "free", "groupOnly"]).default("scale"),
|
|
1274
|
-
canRotate: z.boolean().default(true),
|
|
1275
|
-
canScale: z.boolean().default(true),
|
|
1276
|
-
connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
|
|
1277
|
-
});
|
|
1278
|
-
|
|
1279
|
-
// src/components/Text.ts
|
|
1280
1290
|
var Text = defineCanvasComponent10(
|
|
1281
1291
|
{ name: "text", sync: "document" },
|
|
1282
1292
|
{
|
|
@@ -1323,7 +1333,7 @@ var VerticalAlign = defineCanvasComponent12(
|
|
|
1323
1333
|
);
|
|
1324
1334
|
|
|
1325
1335
|
// src/constants.ts
|
|
1326
|
-
var
|
|
1336
|
+
var CORE_PLUGIN_NAME = "core";
|
|
1327
1337
|
var STRATUM_ORDER = {
|
|
1328
1338
|
background: 0,
|
|
1329
1339
|
content: 1,
|
|
@@ -1489,7 +1499,7 @@ var ControlsSchema = {
|
|
|
1489
1499
|
/** Tool activated by mouse wheel with modifier key held */
|
|
1490
1500
|
modWheelTool: field18.string().max(32).default("zoom"),
|
|
1491
1501
|
/** JSON snapshot of block to place on next click (empty string = no placement active) */
|
|
1492
|
-
heldSnapshot: field18.string().max(
|
|
1502
|
+
heldSnapshot: field18.string().max(65536).default("")
|
|
1493
1503
|
};
|
|
1494
1504
|
var ControlsDef = class extends CanvasSingletonDef3 {
|
|
1495
1505
|
constructor() {
|
|
@@ -2061,7 +2071,9 @@ var MouseSchema = {
|
|
|
2061
2071
|
/** True for 1 frame when mouse enters the editor element */
|
|
2062
2072
|
enterTrigger: field24.boolean().default(false),
|
|
2063
2073
|
/** True for 1 frame when mouse leaves the editor element */
|
|
2064
|
-
leaveTrigger: field24.boolean().default(false)
|
|
2074
|
+
leaveTrigger: field24.boolean().default(false),
|
|
2075
|
+
/** Whether the mouse is over a UI element (not the canvas) */
|
|
2076
|
+
obscured: field24.boolean().default(false)
|
|
2065
2077
|
};
|
|
2066
2078
|
var MouseDef = class extends CanvasSingletonDef8 {
|
|
2067
2079
|
constructor() {
|
|
@@ -2093,6 +2105,10 @@ var MouseDef = class extends CanvasSingletonDef8 {
|
|
|
2093
2105
|
const m = this.read(ctx);
|
|
2094
2106
|
return [m.wheelDeltaX, m.wheelDeltaY];
|
|
2095
2107
|
}
|
|
2108
|
+
/** Check if mouse is over a UI element (not the canvas) */
|
|
2109
|
+
isObscured(ctx) {
|
|
2110
|
+
return this.read(ctx).obscured;
|
|
2111
|
+
}
|
|
2096
2112
|
};
|
|
2097
2113
|
var Mouse = new MouseDef();
|
|
2098
2114
|
|
|
@@ -2385,7 +2401,8 @@ function attachMouseListeners(domElement) {
|
|
|
2385
2401
|
state.eventsBuffer.push({
|
|
2386
2402
|
type: "mousemove",
|
|
2387
2403
|
clientX: e.clientX,
|
|
2388
|
-
clientY: e.clientY
|
|
2404
|
+
clientY: e.clientY,
|
|
2405
|
+
target: e.target
|
|
2389
2406
|
});
|
|
2390
2407
|
},
|
|
2391
2408
|
onWheel: (e) => {
|
|
@@ -2442,6 +2459,7 @@ var mouseSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
|
|
|
2442
2459
|
case "mousemove":
|
|
2443
2460
|
mouse.position = [event.clientX - screen.left, event.clientY - screen.top];
|
|
2444
2461
|
mouse.moveTrigger = true;
|
|
2462
|
+
mouse.obscured = event.target !== resources.domElement;
|
|
2445
2463
|
break;
|
|
2446
2464
|
case "wheel":
|
|
2447
2465
|
mouse.wheelDeltaX = event.deltaX;
|
|
@@ -2701,11 +2719,22 @@ function getBlockDefs(ctx) {
|
|
|
2701
2719
|
}
|
|
2702
2720
|
function getBlockDef(ctx, tag) {
|
|
2703
2721
|
const blockDefs = getBlockDefs(ctx);
|
|
2704
|
-
return blockDefs[tag] ??
|
|
2722
|
+
return blockDefs[tag] ?? BlockDef.parse({ tag });
|
|
2705
2723
|
}
|
|
2706
2724
|
function canBlockEdit(ctx, tag) {
|
|
2707
2725
|
return getBlockDef(ctx, tag).editOptions.canEdit;
|
|
2708
2726
|
}
|
|
2727
|
+
function canBlockSelect(ctx, tag) {
|
|
2728
|
+
return getBlockDef(ctx, tag).selectable;
|
|
2729
|
+
}
|
|
2730
|
+
function getBlockResizeMode(ctx, entityId) {
|
|
2731
|
+
const block = Block.read(ctx, entityId);
|
|
2732
|
+
if (block.resizeMode !== ResizeMode.Default) {
|
|
2733
|
+
return block.resizeMode;
|
|
2734
|
+
}
|
|
2735
|
+
const blockDef = getBlockDef(ctx, block.tag);
|
|
2736
|
+
return blockDef.resizeMode;
|
|
2737
|
+
}
|
|
2709
2738
|
|
|
2710
2739
|
// src/helpers/computeAabb.ts
|
|
2711
2740
|
import { Aabb as Aabb2 } from "@woven-canvas/math";
|
|
@@ -2906,7 +2935,7 @@ function updateUserPosition(ctx, position) {
|
|
|
2906
2935
|
}
|
|
2907
2936
|
|
|
2908
2937
|
// src/systems/preCapture/intersectSystem.ts
|
|
2909
|
-
import { addComponent as addComponent4, defineQuery as defineQuery6, hasComponent as hasComponent5, removeComponent } from "@woven-ecs/core";
|
|
2938
|
+
import { addComponent as addComponent4, defineQuery as defineQuery6, getResources as getResources11, hasComponent as hasComponent5, removeComponent } from "@woven-ecs/core";
|
|
2910
2939
|
var blocksChanged = defineQuery6((q) => q.tracking(Block));
|
|
2911
2940
|
var hitGeometryChanged = defineQuery6((q) => q.tracking(HitGeometry));
|
|
2912
2941
|
var heldQuery = defineQuery6((q) => q.with(Held).tracking(Held));
|
|
@@ -2945,6 +2974,7 @@ function arraysEqual(a, b) {
|
|
|
2945
2974
|
}
|
|
2946
2975
|
var added = /* @__PURE__ */ new Set();
|
|
2947
2976
|
var changed = /* @__PURE__ */ new Set();
|
|
2977
|
+
var prevObscuredByElement = /* @__PURE__ */ new WeakMap();
|
|
2948
2978
|
var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (ctx) => {
|
|
2949
2979
|
added.clear();
|
|
2950
2980
|
for (const entityId of blocksChanged.added(ctx)) {
|
|
@@ -2986,6 +3016,15 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
2986
3016
|
clearHovered(ctx);
|
|
2987
3017
|
return;
|
|
2988
3018
|
}
|
|
3019
|
+
const resources = getResources11(ctx);
|
|
3020
|
+
const isObscured = Mouse.isObscured(ctx);
|
|
3021
|
+
const wasObscured = prevObscuredByElement.get(resources.domElement) ?? false;
|
|
3022
|
+
const obscuredChanged = isObscured !== wasObscured;
|
|
3023
|
+
prevObscuredByElement.set(resources.domElement, isObscured);
|
|
3024
|
+
if (isObscured) {
|
|
3025
|
+
clearHovered(ctx);
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
2989
3028
|
const mousePos = Mouse.getPosition(ctx);
|
|
2990
3029
|
const worldPos = Camera.toWorld(ctx, mousePos);
|
|
2991
3030
|
const intersected = intersectPoint(ctx, worldPos);
|
|
@@ -2998,7 +3037,7 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
|
|
|
2998
3037
|
if (pointers.length > 0) {
|
|
2999
3038
|
return;
|
|
3000
3039
|
}
|
|
3001
|
-
if (intersectsChanged || heldChanged) {
|
|
3040
|
+
if (intersectsChanged || heldChanged || obscuredChanged) {
|
|
3002
3041
|
updateHovered(ctx, intersected);
|
|
3003
3042
|
}
|
|
3004
3043
|
});
|
|
@@ -3100,7 +3139,7 @@ function scaleBlock(ctx, entityId, zoom) {
|
|
|
3100
3139
|
|
|
3101
3140
|
// src/CorePlugin.ts
|
|
3102
3141
|
var CorePlugin = {
|
|
3103
|
-
name:
|
|
3142
|
+
name: CORE_PLUGIN_NAME,
|
|
3104
3143
|
singletons: Object.values(singletons_exports).filter((v) => v instanceof CanvasSingletonDef10),
|
|
3105
3144
|
components: Object.values(components_exports).filter((v) => v instanceof CanvasComponentDef6),
|
|
3106
3145
|
blockDefs: [
|
|
@@ -3114,7 +3153,7 @@ var CorePlugin = {
|
|
|
3114
3153
|
{
|
|
3115
3154
|
tag: "text",
|
|
3116
3155
|
components: [Text],
|
|
3117
|
-
resizeMode:
|
|
3156
|
+
resizeMode: ResizeMode.Text,
|
|
3118
3157
|
editOptions: {
|
|
3119
3158
|
canEdit: true,
|
|
3120
3159
|
removeWhenTextEmpty: true
|
|
@@ -3123,12 +3162,12 @@ var CorePlugin = {
|
|
|
3123
3162
|
{
|
|
3124
3163
|
tag: "image",
|
|
3125
3164
|
components: [Image, Asset],
|
|
3126
|
-
resizeMode:
|
|
3165
|
+
resizeMode: ResizeMode.Scale
|
|
3127
3166
|
},
|
|
3128
3167
|
{
|
|
3129
3168
|
tag: "shape",
|
|
3130
3169
|
components: [Shape, Text, VerticalAlign],
|
|
3131
|
-
resizeMode:
|
|
3170
|
+
resizeMode: ResizeMode.Free,
|
|
3132
3171
|
editOptions: {
|
|
3133
3172
|
canEdit: true
|
|
3134
3173
|
}
|
|
@@ -3159,14 +3198,14 @@ var CorePlugin = {
|
|
|
3159
3198
|
// priority: -100
|
|
3160
3199
|
],
|
|
3161
3200
|
setup(ctx) {
|
|
3162
|
-
const { domElement } =
|
|
3201
|
+
const { domElement } = getResources12(ctx);
|
|
3163
3202
|
attachKeyboardListeners(domElement);
|
|
3164
3203
|
attachMouseListeners(domElement);
|
|
3165
3204
|
attachScreenObserver(domElement);
|
|
3166
3205
|
attachPointerListeners(domElement);
|
|
3167
3206
|
},
|
|
3168
3207
|
teardown(ctx) {
|
|
3169
|
-
const { domElement } =
|
|
3208
|
+
const { domElement } = getResources12(ctx);
|
|
3170
3209
|
detachKeyboardListeners(domElement);
|
|
3171
3210
|
detachMouseListeners(domElement);
|
|
3172
3211
|
detachScreenObserver(domElement);
|
|
@@ -3419,13 +3458,13 @@ var Editor = class {
|
|
|
3419
3458
|
this.keybinds = keybinds;
|
|
3420
3459
|
const blockDefs = {};
|
|
3421
3460
|
for (const input of options.blockDefs) {
|
|
3422
|
-
const parsed =
|
|
3461
|
+
const parsed = BlockDef.parse(input);
|
|
3423
3462
|
blockDefs[parsed.tag] = parsed;
|
|
3424
3463
|
}
|
|
3425
3464
|
for (const plugin of sortedPlugins) {
|
|
3426
3465
|
if (plugin.blockDefs) {
|
|
3427
3466
|
for (const input of plugin.blockDefs) {
|
|
3428
|
-
const parsed =
|
|
3467
|
+
const parsed = BlockDef.parse(input);
|
|
3429
3468
|
blockDefs[parsed.tag] = parsed;
|
|
3430
3469
|
}
|
|
3431
3470
|
}
|
|
@@ -3950,7 +3989,7 @@ export {
|
|
|
3950
3989
|
Aabb,
|
|
3951
3990
|
Asset,
|
|
3952
3991
|
Block,
|
|
3953
|
-
|
|
3992
|
+
BlockDef,
|
|
3954
3993
|
Camera,
|
|
3955
3994
|
CanvasComponentDef7 as CanvasComponentDef,
|
|
3956
3995
|
CanvasSingletonDef12 as CanvasSingletonDef,
|
|
@@ -3991,6 +4030,7 @@ export {
|
|
|
3991
4030
|
RankBounds,
|
|
3992
4031
|
Redo,
|
|
3993
4032
|
ResetKeyboard,
|
|
4033
|
+
ResizeMode,
|
|
3994
4034
|
SINGLETON_ENTITY_ID,
|
|
3995
4035
|
STRATUM_ORDER,
|
|
3996
4036
|
ScaleWithZoom,
|
|
@@ -4010,6 +4050,7 @@ export {
|
|
|
4010
4050
|
VerticalAlignment,
|
|
4011
4051
|
addComponent6 as addComponent,
|
|
4012
4052
|
canBlockEdit,
|
|
4053
|
+
canBlockSelect,
|
|
4013
4054
|
clearPointerTrackingState,
|
|
4014
4055
|
createEntity5 as createEntity,
|
|
4015
4056
|
defineCanvasComponent13 as defineCanvasComponent,
|
|
@@ -4022,12 +4063,13 @@ export {
|
|
|
4022
4063
|
field28 as field,
|
|
4023
4064
|
getBackrefs,
|
|
4024
4065
|
getBlockDef,
|
|
4066
|
+
getBlockResizeMode,
|
|
4025
4067
|
getFrameInput,
|
|
4026
4068
|
getKeyboardInput,
|
|
4027
4069
|
getMouseInput,
|
|
4028
4070
|
getPluginResources,
|
|
4029
4071
|
getPointerInput,
|
|
4030
|
-
|
|
4072
|
+
getResources13 as getResources,
|
|
4031
4073
|
getTopmostBlockAtPoint,
|
|
4032
4074
|
hasComponent7 as hasComponent,
|
|
4033
4075
|
intersectAabb,
|