@woven-canvas/core 0.1.3 → 0.1.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/build/index.cjs CHANGED
@@ -23,7 +23,7 @@ __export(index_exports, {
23
23
  Aabb: () => Aabb,
24
24
  Asset: () => Asset,
25
25
  Block: () => Block,
26
- BlockDef: () => BlockDef2,
26
+ BlockDef: () => BlockDef,
27
27
  Camera: () => Camera,
28
28
  CanvasComponentDef: () => import_canvas_store34.CanvasComponentDef,
29
29
  CanvasSingletonDef: () => import_canvas_store34.CanvasSingletonDef,
@@ -64,6 +64,7 @@ __export(index_exports, {
64
64
  RankBounds: () => RankBounds,
65
65
  Redo: () => Redo,
66
66
  ResetKeyboard: () => ResetKeyboard,
67
+ ResizeMode: () => ResizeMode,
67
68
  SINGLETON_ENTITY_ID: () => import_core49.SINGLETON_ENTITY_ID,
68
69
  STRATUM_ORDER: () => STRATUM_ORDER,
69
70
  ScaleWithZoom: () => ScaleWithZoom,
@@ -95,6 +96,7 @@ __export(index_exports, {
95
96
  field: () => import_core49.field,
96
97
  getBackrefs: () => import_core49.getBackrefs,
97
98
  getBlockDef: () => getBlockDef,
99
+ getBlockResizeMode: () => getBlockResizeMode,
98
100
  getFrameInput: () => getFrameInput,
99
101
  getKeyboardInput: () => getKeyboardInput,
100
102
  getMouseInput: () => getMouseInput,
@@ -160,6 +162,260 @@ var import_core2 = require("@woven-ecs/core");
160
162
  var import_math = require("@woven-canvas/math");
161
163
  var import_canvas_store = require("@woven-ecs/canvas-store");
162
164
  var import_core = require("@woven-ecs/core");
165
+
166
+ // src/types.ts
167
+ var import_zod = require("zod");
168
+ function generateUserColor() {
169
+ const colors = [
170
+ "#f43f5e",
171
+ // rose
172
+ "#ec4899",
173
+ // pink
174
+ "#a855f7",
175
+ // purple
176
+ "#6366f1",
177
+ // indigo
178
+ "#3b82f6",
179
+ // blue
180
+ "#0ea5e9",
181
+ // sky
182
+ "#14b8a6",
183
+ // teal
184
+ "#22c55e",
185
+ // green
186
+ "#eab308",
187
+ // yellow
188
+ "#f97316"
189
+ // orange
190
+ ];
191
+ return colors[Math.floor(Math.random() * colors.length)];
192
+ }
193
+ var UserData = import_zod.z.object({
194
+ userId: import_zod.z.string().max(36).default(() => crypto.randomUUID()),
195
+ sessionId: import_zod.z.string().max(36).default(() => crypto.randomUUID()),
196
+ color: import_zod.z.string().max(7).default(generateUserColor),
197
+ name: import_zod.z.string().max(100).default("Anonymous"),
198
+ avatar: import_zod.z.string().max(500).default("")
199
+ });
200
+ function getPluginResources(ctx, pluginName) {
201
+ const resources = ctx.resources;
202
+ return resources.pluginResources[pluginName];
203
+ }
204
+ var GridOptions = import_zod.z.object({
205
+ /**
206
+ * Whether grid snapping is enabled.
207
+ * @default true
208
+ */
209
+ enabled: import_zod.z.boolean().default(true),
210
+ /**
211
+ * Whether resized/rotated objects must stay aligned to the grid.
212
+ * If true, objects snap to grid during resize/rotate.
213
+ * If false, objects scale proportionally to the transform box, which may
214
+ * cause them to be unaligned with the grid.
215
+ * @default false
216
+ */
217
+ strict: import_zod.z.boolean().default(false),
218
+ /**
219
+ * Width of each grid column in world units.
220
+ * @default 20
221
+ */
222
+ colWidth: import_zod.z.number().nonnegative().default(20),
223
+ /**
224
+ * Height of each grid row in world units.
225
+ * @default 20
226
+ */
227
+ rowHeight: import_zod.z.number().nonnegative().default(20),
228
+ /**
229
+ * Angular snap increment in radians when grid is enabled.
230
+ * @default Math.PI / 36 (5 degrees)
231
+ */
232
+ snapAngleRad: import_zod.z.number().nonnegative().default(Math.PI / 36),
233
+ /**
234
+ * Angular snap increment in radians when shift key is held.
235
+ * @default Math.PI / 12 (15 degrees)
236
+ */
237
+ shiftSnapAngleRad: import_zod.z.number().nonnegative().default(Math.PI / 12)
238
+ });
239
+ var ControlsOptions = import_zod.z.object({
240
+ /**
241
+ * Tool activated by left mouse button.
242
+ * @default 'select'
243
+ */
244
+ leftMouseTool: import_zod.z.string().max(32).default("select"),
245
+ /**
246
+ * Tool activated by middle mouse button.
247
+ * @default 'hand'
248
+ */
249
+ middleMouseTool: import_zod.z.string().max(32).default("hand"),
250
+ /**
251
+ * Tool activated by right mouse button.
252
+ * @default 'menu'
253
+ */
254
+ rightMouseTool: import_zod.z.string().max(32).default("menu"),
255
+ /**
256
+ * Tool activated by mouse wheel.
257
+ * @default 'scroll'
258
+ */
259
+ wheelTool: import_zod.z.string().max(32).default("scroll"),
260
+ /**
261
+ * Tool activated by mouse wheel with modifier key held.
262
+ * @default 'zoom'
263
+ */
264
+ modWheelTool: import_zod.z.string().max(32).default("zoom")
265
+ });
266
+ var EditorOptionsSchema = import_zod.z.object({
267
+ /**
268
+ * Plugins to load.
269
+ * Plugins are sorted by dependencies automatically.
270
+ */
271
+ plugins: import_zod.z.array(import_zod.z.custom()).default([]),
272
+ /**
273
+ * Maximum number of entities.
274
+ * @default 5_000
275
+ */
276
+ maxEntities: import_zod.z.number().default(5e3),
277
+ /**
278
+ * User data for presence tracking.
279
+ * All fields are optional - defaults will be applied.
280
+ */
281
+ user: import_zod.z.custom().default({}),
282
+ /**
283
+ * Grid configuration for snap-to-grid behavior.
284
+ * All fields are optional - defaults will be applied.
285
+ */
286
+ grid: import_zod.z.custom().default({}),
287
+ /**
288
+ * Custom block definitions.
289
+ * Accepts partial block definitions - defaults will be applied automatically.
290
+ */
291
+ blockDefs: import_zod.z.array(import_zod.z.custom()).default([]),
292
+ /**
293
+ * Keybind definitions for keyboard shortcuts.
294
+ * These map key combinations to plugin commands.
295
+ */
296
+ keybinds: import_zod.z.array(import_zod.z.custom()).default([]),
297
+ /**
298
+ * Custom cursor definitions.
299
+ * Override default cursors or define new ones for transform operations.
300
+ */
301
+ cursors: import_zod.z.record(import_zod.z.string(), import_zod.z.custom()).default({}),
302
+ /**
303
+ * Custom components to register without creating a plugin.
304
+ */
305
+ components: import_zod.z.array(import_zod.z.custom()).default([]),
306
+ /**
307
+ * Custom singletons to register without creating a plugin.
308
+ */
309
+ singletons: import_zod.z.array(import_zod.z.custom()).default([]),
310
+ /**
311
+ * Custom systems to register without creating a plugin.
312
+ * Each system specifies its phase and priority.
313
+ */
314
+ systems: import_zod.z.array(import_zod.z.custom()).default([]),
315
+ /**
316
+ * Custom font families to load and make available in the font selector.
317
+ * Fonts will be loaded automatically during editor initialization.
318
+ */
319
+ fonts: import_zod.z.array(import_zod.z.custom()).default([]),
320
+ /**
321
+ * If true, keybinds from plugins will be ignored.
322
+ * Use this when you want full control over keybinds.
323
+ */
324
+ omitPluginKeybinds: import_zod.z.boolean().default(false),
325
+ /**
326
+ * If true, cursors from plugins will be ignored.
327
+ * Use this when you want full control over cursors.
328
+ */
329
+ omitPluginCursors: import_zod.z.boolean().default(false),
330
+ /**
331
+ * If true, fonts from plugins will be ignored.
332
+ * Use this when you want full control over fonts.
333
+ */
334
+ omitPluginFonts: import_zod.z.boolean().default(false),
335
+ /**
336
+ * Initial controls configuration.
337
+ * Override default tool mappings for mouse buttons, wheel, etc.
338
+ *
339
+ * @example
340
+ * ```typescript
341
+ * controls: {
342
+ * leftMouseTool: 'pen', // Start with pen tool active
343
+ * middleMouseTool: 'hand', // Middle mouse pans
344
+ * }
345
+ * ```
346
+ */
347
+ controls: import_zod.z.custom().optional()
348
+ });
349
+ var Keybind = import_zod.z.object({
350
+ /** The command to execute when this keybind is triggered */
351
+ command: import_zod.z.string(),
352
+ /** The key index from the Key constants (e.g., Key.A, Key.Delete) */
353
+ key: import_zod.z.number(),
354
+ /** Whether the modifier key (Cmd on Mac, Ctrl on Windows) must be held */
355
+ mod: import_zod.z.boolean().optional(),
356
+ /** Whether the Shift key must be held */
357
+ shift: import_zod.z.boolean().optional()
358
+ });
359
+ var CursorDef = import_zod.z.object({
360
+ /** Function that generates the SVG string for a given rotation angle (in radians) */
361
+ makeSvg: import_zod.z.function({ input: import_zod.z.tuple([import_zod.z.number()]), output: import_zod.z.string() }),
362
+ /** Hotspot coordinates [x, y] for the cursor */
363
+ hotspot: import_zod.z.tuple([import_zod.z.number(), import_zod.z.number()]),
364
+ /** Base rotation offset applied before the dynamic rotation */
365
+ rotationOffset: import_zod.z.number()
366
+ });
367
+ var ResizeMode = {
368
+ Default: "default",
369
+ Scale: "scale",
370
+ Text: "text",
371
+ Free: "free",
372
+ GroupOnly: "groupOnly"
373
+ };
374
+ var VerticalAlignment = {
375
+ Top: "top",
376
+ Center: "center",
377
+ Bottom: "bottom"
378
+ };
379
+ var TextAlignment = {
380
+ Left: "left",
381
+ Center: "center",
382
+ Right: "right",
383
+ Justify: "justify"
384
+ };
385
+ var BlockDefEditOptions = import_zod.z.object({
386
+ canEdit: import_zod.z.boolean().default(false),
387
+ removeWhenTextEmpty: import_zod.z.boolean().default(false)
388
+ });
389
+ var BlockDefConnectors = import_zod.z.object({
390
+ /** Whether connectors are enabled for this block type */
391
+ enabled: import_zod.z.boolean().default(true),
392
+ /** UV coordinates of terminal positions (0-1 range, where [0,0] is top-left) */
393
+ terminals: import_zod.z.array(import_zod.z.tuple([import_zod.z.number(), import_zod.z.number()])).default([
394
+ [0.5, 0],
395
+ // top
396
+ [0.5, 1],
397
+ // bottom
398
+ [0.5, 0.5],
399
+ // center
400
+ [0, 0.5],
401
+ // left
402
+ [1, 0.5]
403
+ // right
404
+ ])
405
+ });
406
+ var Stratum = import_zod.z.enum(["background", "content", "overlay"]);
407
+ var BlockDef = import_zod.z.object({
408
+ tag: import_zod.z.string(),
409
+ stratum: Stratum.default("content"),
410
+ editOptions: BlockDefEditOptions.default(BlockDefEditOptions.parse({})),
411
+ components: import_zod.z.array(import_zod.z.custom()).default([]),
412
+ resizeMode: import_zod.z.enum([ResizeMode.Scale, ResizeMode.Text, ResizeMode.Free, ResizeMode.GroupOnly]).default(ResizeMode.Scale),
413
+ canRotate: import_zod.z.boolean().default(true),
414
+ canScale: import_zod.z.boolean().default(true),
415
+ connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
416
+ });
417
+
418
+ // src/components/Block.ts
163
419
  var _aabbCorners = [
164
420
  [0, 0],
165
421
  [0, 0],
@@ -188,9 +444,11 @@ var BlockSchema = {
188
444
  /** Flip state as [flipX, flipY] */
189
445
  flip: import_core.field.tuple(import_core.field.boolean(), 2).default([false, false]),
190
446
  /** Z-order rank (LexoRank string) */
191
- rank: import_core.field.string().max(36).default("")
447
+ rank: import_core.field.string().max(36).default(""),
448
+ /** How the block can be resized */
449
+ resizeMode: import_core.field.enum(ResizeMode).default(ResizeMode.Default)
192
450
  };
193
- var BlockDef = class extends import_canvas_store.CanvasComponentDef {
451
+ var BlockDef2 = class extends import_canvas_store.CanvasComponentDef {
194
452
  constructor() {
195
453
  super({ name: "block", sync: "document" }, BlockSchema);
196
454
  }
@@ -332,7 +590,7 @@ var BlockDef = class extends import_canvas_store.CanvasComponentDef {
332
590
  }
333
591
  }
334
592
  };
335
- var Block = new BlockDef();
593
+ var Block = new BlockDef2();
336
594
 
337
595
  // src/components/Aabb.ts
338
596
  var LEFT = 0;
@@ -1115,253 +1373,6 @@ var Shape = (0, import_canvas_store14.defineCanvasComponent)(
1115
1373
  // src/components/Text.ts
1116
1374
  var import_canvas_store15 = require("@woven-ecs/canvas-store");
1117
1375
  var import_core13 = require("@woven-ecs/core");
1118
-
1119
- // src/types.ts
1120
- var import_zod = require("zod");
1121
- function generateUserColor() {
1122
- const colors = [
1123
- "#f43f5e",
1124
- // rose
1125
- "#ec4899",
1126
- // pink
1127
- "#a855f7",
1128
- // purple
1129
- "#6366f1",
1130
- // indigo
1131
- "#3b82f6",
1132
- // blue
1133
- "#0ea5e9",
1134
- // sky
1135
- "#14b8a6",
1136
- // teal
1137
- "#22c55e",
1138
- // green
1139
- "#eab308",
1140
- // yellow
1141
- "#f97316"
1142
- // orange
1143
- ];
1144
- return colors[Math.floor(Math.random() * colors.length)];
1145
- }
1146
- var UserData = import_zod.z.object({
1147
- userId: import_zod.z.string().max(36).default(() => crypto.randomUUID()),
1148
- sessionId: import_zod.z.string().max(36).default(() => crypto.randomUUID()),
1149
- color: import_zod.z.string().max(7).default(generateUserColor),
1150
- name: import_zod.z.string().max(100).default("Anonymous"),
1151
- avatar: import_zod.z.string().max(500).default("")
1152
- });
1153
- function getPluginResources(ctx, pluginName) {
1154
- const resources = ctx.resources;
1155
- return resources.pluginResources[pluginName];
1156
- }
1157
- var GridOptions = import_zod.z.object({
1158
- /**
1159
- * Whether grid snapping is enabled.
1160
- * @default true
1161
- */
1162
- enabled: import_zod.z.boolean().default(true),
1163
- /**
1164
- * Whether resized/rotated objects must stay aligned to the grid.
1165
- * If true, objects snap to grid during resize/rotate.
1166
- * If false, objects scale proportionally to the transform box, which may
1167
- * cause them to be unaligned with the grid.
1168
- * @default false
1169
- */
1170
- strict: import_zod.z.boolean().default(false),
1171
- /**
1172
- * Width of each grid column in world units.
1173
- * @default 20
1174
- */
1175
- colWidth: import_zod.z.number().nonnegative().default(20),
1176
- /**
1177
- * Height of each grid row in world units.
1178
- * @default 20
1179
- */
1180
- rowHeight: import_zod.z.number().nonnegative().default(20),
1181
- /**
1182
- * Angular snap increment in radians when grid is enabled.
1183
- * @default Math.PI / 36 (5 degrees)
1184
- */
1185
- snapAngleRad: import_zod.z.number().nonnegative().default(Math.PI / 36),
1186
- /**
1187
- * Angular snap increment in radians when shift key is held.
1188
- * @default Math.PI / 12 (15 degrees)
1189
- */
1190
- shiftSnapAngleRad: import_zod.z.number().nonnegative().default(Math.PI / 12)
1191
- });
1192
- var ControlsOptions = import_zod.z.object({
1193
- /**
1194
- * Tool activated by left mouse button.
1195
- * @default 'select'
1196
- */
1197
- leftMouseTool: import_zod.z.string().max(32).default("select"),
1198
- /**
1199
- * Tool activated by middle mouse button.
1200
- * @default 'hand'
1201
- */
1202
- middleMouseTool: import_zod.z.string().max(32).default("hand"),
1203
- /**
1204
- * Tool activated by right mouse button.
1205
- * @default 'menu'
1206
- */
1207
- rightMouseTool: import_zod.z.string().max(32).default("menu"),
1208
- /**
1209
- * Tool activated by mouse wheel.
1210
- * @default 'scroll'
1211
- */
1212
- wheelTool: import_zod.z.string().max(32).default("scroll"),
1213
- /**
1214
- * Tool activated by mouse wheel with modifier key held.
1215
- * @default 'zoom'
1216
- */
1217
- modWheelTool: import_zod.z.string().max(32).default("zoom")
1218
- });
1219
- var EditorOptionsSchema = import_zod.z.object({
1220
- /**
1221
- * Plugins to load.
1222
- * Plugins are sorted by dependencies automatically.
1223
- */
1224
- plugins: import_zod.z.array(import_zod.z.custom()).default([]),
1225
- /**
1226
- * Maximum number of entities.
1227
- * @default 5_000
1228
- */
1229
- maxEntities: import_zod.z.number().default(5e3),
1230
- /**
1231
- * User data for presence tracking.
1232
- * All fields are optional - defaults will be applied.
1233
- */
1234
- user: import_zod.z.custom().default({}),
1235
- /**
1236
- * Grid configuration for snap-to-grid behavior.
1237
- * All fields are optional - defaults will be applied.
1238
- */
1239
- grid: import_zod.z.custom().default({}),
1240
- /**
1241
- * Custom block definitions.
1242
- * Accepts partial block definitions - defaults will be applied automatically.
1243
- */
1244
- blockDefs: import_zod.z.array(import_zod.z.custom()).default([]),
1245
- /**
1246
- * Keybind definitions for keyboard shortcuts.
1247
- * These map key combinations to plugin commands.
1248
- */
1249
- keybinds: import_zod.z.array(import_zod.z.custom()).default([]),
1250
- /**
1251
- * Custom cursor definitions.
1252
- * Override default cursors or define new ones for transform operations.
1253
- */
1254
- cursors: import_zod.z.record(import_zod.z.string(), import_zod.z.custom()).default({}),
1255
- /**
1256
- * Custom components to register without creating a plugin.
1257
- */
1258
- components: import_zod.z.array(import_zod.z.custom()).default([]),
1259
- /**
1260
- * Custom singletons to register without creating a plugin.
1261
- */
1262
- singletons: import_zod.z.array(import_zod.z.custom()).default([]),
1263
- /**
1264
- * Custom systems to register without creating a plugin.
1265
- * Each system specifies its phase and priority.
1266
- */
1267
- systems: import_zod.z.array(import_zod.z.custom()).default([]),
1268
- /**
1269
- * Custom font families to load and make available in the font selector.
1270
- * Fonts will be loaded automatically during editor initialization.
1271
- */
1272
- fonts: import_zod.z.array(import_zod.z.custom()).default([]),
1273
- /**
1274
- * If true, keybinds from plugins will be ignored.
1275
- * Use this when you want full control over keybinds.
1276
- */
1277
- omitPluginKeybinds: import_zod.z.boolean().default(false),
1278
- /**
1279
- * If true, cursors from plugins will be ignored.
1280
- * Use this when you want full control over cursors.
1281
- */
1282
- omitPluginCursors: import_zod.z.boolean().default(false),
1283
- /**
1284
- * If true, fonts from plugins will be ignored.
1285
- * Use this when you want full control over fonts.
1286
- */
1287
- omitPluginFonts: import_zod.z.boolean().default(false),
1288
- /**
1289
- * Initial controls configuration.
1290
- * Override default tool mappings for mouse buttons, wheel, etc.
1291
- *
1292
- * @example
1293
- * ```typescript
1294
- * controls: {
1295
- * leftMouseTool: 'pen', // Start with pen tool active
1296
- * middleMouseTool: 'hand', // Middle mouse pans
1297
- * }
1298
- * ```
1299
- */
1300
- controls: import_zod.z.custom().optional()
1301
- });
1302
- var Keybind = import_zod.z.object({
1303
- /** The command to execute when this keybind is triggered */
1304
- command: import_zod.z.string(),
1305
- /** The key index from the Key constants (e.g., Key.A, Key.Delete) */
1306
- key: import_zod.z.number(),
1307
- /** Whether the modifier key (Cmd on Mac, Ctrl on Windows) must be held */
1308
- mod: import_zod.z.boolean().optional(),
1309
- /** Whether the Shift key must be held */
1310
- shift: import_zod.z.boolean().optional()
1311
- });
1312
- var CursorDef = import_zod.z.object({
1313
- /** Function that generates the SVG string for a given rotation angle (in radians) */
1314
- makeSvg: import_zod.z.function({ input: import_zod.z.tuple([import_zod.z.number()]), output: import_zod.z.string() }),
1315
- /** Hotspot coordinates [x, y] for the cursor */
1316
- hotspot: import_zod.z.tuple([import_zod.z.number(), import_zod.z.number()]),
1317
- /** Base rotation offset applied before the dynamic rotation */
1318
- rotationOffset: import_zod.z.number()
1319
- });
1320
- var VerticalAlignment = {
1321
- Top: "top",
1322
- Center: "center",
1323
- Bottom: "bottom"
1324
- };
1325
- var TextAlignment = {
1326
- Left: "left",
1327
- Center: "center",
1328
- Right: "right",
1329
- Justify: "justify"
1330
- };
1331
- var BlockDefEditOptions = import_zod.z.object({
1332
- canEdit: import_zod.z.boolean().default(false),
1333
- removeWhenTextEmpty: import_zod.z.boolean().default(false)
1334
- });
1335
- var BlockDefConnectors = import_zod.z.object({
1336
- /** Whether connectors are enabled for this block type */
1337
- enabled: import_zod.z.boolean().default(true),
1338
- /** UV coordinates of terminal positions (0-1 range, where [0,0] is top-left) */
1339
- terminals: import_zod.z.array(import_zod.z.tuple([import_zod.z.number(), import_zod.z.number()])).default([
1340
- [0.5, 0],
1341
- // top
1342
- [0.5, 1],
1343
- // bottom
1344
- [0.5, 0.5],
1345
- // center
1346
- [0, 0.5],
1347
- // left
1348
- [1, 0.5]
1349
- // right
1350
- ])
1351
- });
1352
- var Stratum = import_zod.z.enum(["background", "content", "overlay"]);
1353
- var BlockDef2 = import_zod.z.object({
1354
- tag: import_zod.z.string(),
1355
- stratum: Stratum.default("content"),
1356
- editOptions: BlockDefEditOptions.default(BlockDefEditOptions.parse({})),
1357
- components: import_zod.z.array(import_zod.z.custom()).default([]),
1358
- resizeMode: import_zod.z.enum(["scale", "text", "free", "groupOnly"]).default("scale"),
1359
- canRotate: import_zod.z.boolean().default(true),
1360
- canScale: import_zod.z.boolean().default(true),
1361
- connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
1362
- });
1363
-
1364
- // src/components/Text.ts
1365
1376
  var Text = (0, import_canvas_store15.defineCanvasComponent)(
1366
1377
  { name: "text", sync: "document" },
1367
1378
  {
@@ -2778,11 +2789,19 @@ function getBlockDefs(ctx) {
2778
2789
  }
2779
2790
  function getBlockDef(ctx, tag) {
2780
2791
  const blockDefs = getBlockDefs(ctx);
2781
- return blockDefs[tag] ?? BlockDef2.parse({ tag });
2792
+ return blockDefs[tag] ?? BlockDef.parse({ tag });
2782
2793
  }
2783
2794
  function canBlockEdit(ctx, tag) {
2784
2795
  return getBlockDef(ctx, tag).editOptions.canEdit;
2785
2796
  }
2797
+ function getBlockResizeMode(ctx, entityId) {
2798
+ const block = Block.read(ctx, entityId);
2799
+ if (block.resizeMode !== ResizeMode.Default) {
2800
+ return block.resizeMode;
2801
+ }
2802
+ const blockDef = getBlockDef(ctx, block.tag);
2803
+ return blockDef.resizeMode;
2804
+ }
2786
2805
 
2787
2806
  // src/helpers/computeAabb.ts
2788
2807
  var import_math4 = require("@woven-canvas/math");
@@ -3191,7 +3210,7 @@ var CorePlugin = {
3191
3210
  {
3192
3211
  tag: "text",
3193
3212
  components: [Text],
3194
- resizeMode: "text",
3213
+ resizeMode: ResizeMode.Text,
3195
3214
  editOptions: {
3196
3215
  canEdit: true,
3197
3216
  removeWhenTextEmpty: true
@@ -3200,12 +3219,12 @@ var CorePlugin = {
3200
3219
  {
3201
3220
  tag: "image",
3202
3221
  components: [Image, Asset],
3203
- resizeMode: "scale"
3222
+ resizeMode: ResizeMode.Scale
3204
3223
  },
3205
3224
  {
3206
3225
  tag: "shape",
3207
3226
  components: [Shape, Text, VerticalAlign],
3208
- resizeMode: "free",
3227
+ resizeMode: ResizeMode.Free,
3209
3228
  editOptions: {
3210
3229
  canEdit: true
3211
3230
  }
@@ -3492,13 +3511,13 @@ var Editor = class {
3492
3511
  this.keybinds = keybinds;
3493
3512
  const blockDefs = {};
3494
3513
  for (const input of options.blockDefs) {
3495
- const parsed = BlockDef2.parse(input);
3514
+ const parsed = BlockDef.parse(input);
3496
3515
  blockDefs[parsed.tag] = parsed;
3497
3516
  }
3498
3517
  for (const plugin of sortedPlugins) {
3499
3518
  if (plugin.blockDefs) {
3500
3519
  for (const input of plugin.blockDefs) {
3501
- const parsed = BlockDef2.parse(input);
3520
+ const parsed = BlockDef.parse(input);
3502
3521
  blockDefs[parsed.tag] = parsed;
3503
3522
  }
3504
3523
  }
@@ -4065,6 +4084,7 @@ function clearPointerTrackingState(ctx) {
4065
4084
  RankBounds,
4066
4085
  Redo,
4067
4086
  ResetKeyboard,
4087
+ ResizeMode,
4068
4088
  SINGLETON_ENTITY_ID,
4069
4089
  STRATUM_ORDER,
4070
4090
  ScaleWithZoom,
@@ -4096,6 +4116,7 @@ function clearPointerTrackingState(ctx) {
4096
4116
  field,
4097
4117
  getBackrefs,
4098
4118
  getBlockDef,
4119
+ getBlockResizeMode,
4099
4120
  getFrameInput,
4100
4121
  getKeyboardInput,
4101
4122
  getMouseInput,