@woven-canvas/core 1.0.0 → 1.0.2

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
@@ -25,11 +25,11 @@ __export(index_exports, {
25
25
  Block: () => Block,
26
26
  BlockDef: () => BlockDef,
27
27
  Camera: () => Camera,
28
- CanvasComponentDef: () => import_canvas_store34.CanvasComponentDef,
29
- CanvasSingletonDef: () => import_canvas_store34.CanvasSingletonDef,
28
+ CanvasComponentDef: () => import_canvas_store35.CanvasComponentDef,
29
+ CanvasSingletonDef: () => import_canvas_store35.CanvasSingletonDef,
30
30
  Color: () => Color,
31
31
  CommandMarker: () => CommandMarker,
32
- ComponentDef: () => import_core49.ComponentDef,
32
+ ComponentDef: () => import_core50.ComponentDef,
33
33
  Connector: () => Connector,
34
34
  Controls: () => Controls,
35
35
  ControlsOptions: () => ControlsOptions,
@@ -39,7 +39,9 @@ __export(index_exports, {
39
39
  Edited: () => Edited,
40
40
  Editor: () => Editor,
41
41
  EditorStateDef: () => EditorStateDef,
42
- EventType: () => import_core49.EventType,
42
+ Embed: () => Embed,
43
+ EmbedProvider: () => EmbedProvider,
44
+ EventType: () => import_core50.EventType,
43
45
  FontFamily: () => FontFamily,
44
46
  FontLoader: () => FontLoader,
45
47
  Frame: () => Frame,
@@ -55,7 +57,7 @@ __export(index_exports, {
55
57
  Keyboard: () => Keyboard,
56
58
  MAX_HIT_ARCS: () => MAX_HIT_ARCS,
57
59
  MAX_HIT_CAPSULES: () => MAX_HIT_CAPSULES,
58
- MainThreadSystem: () => import_core49.MainThreadSystem,
60
+ MainThreadSystem: () => import_core50.MainThreadSystem,
59
61
  Mouse: () => Mouse,
60
62
  Opacity: () => Opacity,
61
63
  Pointer: () => Pointer,
@@ -65,7 +67,7 @@ __export(index_exports, {
65
67
  Redo: () => Redo,
66
68
  ResetKeyboard: () => ResetKeyboard,
67
69
  ResizeMode: () => ResizeMode,
68
- SINGLETON_ENTITY_ID: () => import_core49.SINGLETON_ENTITY_ID,
70
+ SINGLETON_ENTITY_ID: () => import_core50.SINGLETON_ENTITY_ID,
69
71
  STRATUM_ORDER: () => STRATUM_ORDER,
70
72
  ScaleWithZoom: () => ScaleWithZoom,
71
73
  ScaleWithZoomState: () => ScaleWithZoomState,
@@ -73,7 +75,7 @@ __export(index_exports, {
73
75
  Shape: () => Shape,
74
76
  Stratum: () => Stratum,
75
77
  StrokeKind: () => StrokeKind,
76
- Synced: () => import_canvas_store34.Synced,
78
+ Synced: () => import_canvas_store35.Synced,
77
79
  Text: () => Text,
78
80
  TextAlignment: () => TextAlignment,
79
81
  Undo: () => Undo,
@@ -82,20 +84,21 @@ __export(index_exports, {
82
84
  UserData: () => UserData,
83
85
  VerticalAlign: () => VerticalAlign,
84
86
  VerticalAlignment: () => VerticalAlignment,
85
- addComponent: () => import_core49.addComponent,
87
+ addComponent: () => import_core50.addComponent,
86
88
  canBlockEdit: () => canBlockEdit,
87
- canBlockSelect: () => canBlockSelect,
89
+ canBlockInteract: () => canBlockInteract,
88
90
  clearPointerTrackingState: () => clearPointerTrackingState,
89
- createEntity: () => import_core49.createEntity,
90
- defineCanvasComponent: () => import_canvas_store34.defineCanvasComponent,
91
- defineCanvasSingleton: () => import_canvas_store34.defineCanvasSingleton,
91
+ createEntity: () => import_core50.createEntity,
92
+ defineCanvasComponent: () => import_canvas_store35.defineCanvasComponent,
93
+ defineCanvasSingleton: () => import_canvas_store35.defineCanvasSingleton,
92
94
  defineCommand: () => defineCommand,
93
95
  defineEditorState: () => defineEditorState,
94
96
  defineEditorSystem: () => defineEditorSystem,
95
- defineQuery: () => import_core49.defineQuery,
96
- defineSystem: () => import_core49.defineSystem,
97
- field: () => import_core49.field,
98
- getBackrefs: () => import_core49.getBackrefs,
97
+ defineQuery: () => import_core50.defineQuery,
98
+ defineSystem: () => import_core50.defineSystem,
99
+ detectEmbedProvider: () => detectEmbedProvider,
100
+ field: () => import_core50.field,
101
+ getBackrefs: () => import_core50.getBackrefs,
99
102
  getBlockDef: () => getBlockDef,
100
103
  getBlockResizeMode: () => getBlockResizeMode,
101
104
  getFrameInput: () => getFrameInput,
@@ -103,27 +106,29 @@ __export(index_exports, {
103
106
  getMouseInput: () => getMouseInput,
104
107
  getPluginResources: () => getPluginResources,
105
108
  getPointerInput: () => getPointerInput,
106
- getResources: () => import_core49.getResources,
109
+ getResources: () => import_core50.getResources,
107
110
  getTopmostBlockAtPoint: () => getTopmostBlockAtPoint,
108
- hasComponent: () => import_core49.hasComponent,
111
+ hasComponent: () => import_core50.hasComponent,
109
112
  intersectAabb: () => intersectAabb,
110
113
  intersectCapsule: () => intersectCapsule,
111
114
  intersectPoint: () => intersectPoint,
112
- isAlive: () => import_core49.isAlive,
115
+ isAlive: () => import_core50.isAlive,
113
116
  isHeldByRemote: () => isHeldByRemote,
114
117
  on: () => on,
115
118
  parsePlugin: () => parsePlugin,
116
- removeComponent: () => import_core49.removeComponent,
117
- removeEntity: () => import_core49.removeEntity,
118
- runMachine: () => runMachine
119
+ removeComponent: () => import_core50.removeComponent,
120
+ removeEntity: () => import_core50.removeEntity,
121
+ resolveEmbedUrl: () => resolveEmbedUrl,
122
+ runMachine: () => runMachine,
123
+ validateEmbedUrl: () => validateEmbedUrl
119
124
  });
120
125
  module.exports = __toCommonJS(index_exports);
121
- var import_canvas_store34 = require("@woven-ecs/canvas-store");
122
- var import_core49 = require("@woven-ecs/core");
126
+ var import_canvas_store35 = require("@woven-ecs/canvas-store");
127
+ var import_core50 = require("@woven-ecs/core");
123
128
 
124
129
  // src/CorePlugin.ts
125
- var import_canvas_store31 = require("@woven-ecs/canvas-store");
126
- var import_core46 = require("@woven-ecs/core");
130
+ var import_canvas_store32 = require("@woven-ecs/canvas-store");
131
+ var import_core47 = require("@woven-ecs/core");
127
132
 
128
133
  // src/components/index.ts
129
134
  var components_exports = {};
@@ -134,6 +139,8 @@ __export(components_exports, {
134
139
  Color: () => Color,
135
140
  Connector: () => Connector,
136
141
  Edited: () => Edited,
142
+ Embed: () => Embed,
143
+ EmbedProvider: () => EmbedProvider,
137
144
  Held: () => Held,
138
145
  HitGeometry: () => HitGeometry,
139
146
  Hovered: () => Hovered,
@@ -252,7 +259,7 @@ var ControlsOptions = import_zod.z.object({
252
259
  * Tool activated by right mouse button.
253
260
  * @default 'menu'
254
261
  */
255
- rightMouseTool: import_zod.z.string().max(32).default("menu"),
262
+ rightMouseTool: import_zod.z.string().max(32).default("hand"),
256
263
  /**
257
264
  * Tool activated by mouse wheel.
258
265
  * @default 'scroll'
@@ -413,7 +420,7 @@ var BlockDef = import_zod.z.object({
413
420
  resizeMode: import_zod.z.enum([ResizeMode.Scale, ResizeMode.Text, ResizeMode.Free, ResizeMode.GroupOnly]).default(ResizeMode.Scale),
414
421
  canRotate: import_zod.z.boolean().default(true),
415
422
  canScale: import_zod.z.boolean().default(true),
416
- selectable: import_zod.z.boolean().default(true),
423
+ interactable: import_zod.z.boolean().default(true),
417
424
  connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
418
425
  });
419
426
 
@@ -810,32 +817,59 @@ var Connector = (0, import_canvas_store5.defineCanvasComponent)(
810
817
  var import_canvas_store6 = require("@woven-ecs/canvas-store");
811
818
  var Edited = (0, import_canvas_store6.defineCanvasComponent)({ name: "edited" }, {});
812
819
 
813
- // src/components/Held.ts
820
+ // src/components/Embed.ts
814
821
  var import_canvas_store7 = require("@woven-ecs/canvas-store");
815
822
  var import_core6 = require("@woven-ecs/core");
816
- var Held = (0, import_canvas_store7.defineCanvasComponent)(
823
+ var EmbedProvider = /* @__PURE__ */ ((EmbedProvider2) => {
824
+ EmbedProvider2["GoogleMaps"] = "google-maps";
825
+ EmbedProvider2["GoogleCalendar"] = "google-calendar";
826
+ EmbedProvider2["GoogleSlides"] = "google-slides";
827
+ EmbedProvider2["Tldraw"] = "tldraw";
828
+ EmbedProvider2["Figma"] = "figma";
829
+ EmbedProvider2["GithubGist"] = "github-gist";
830
+ EmbedProvider2["Youtube"] = "youtube";
831
+ EmbedProvider2["Spotify"] = "spotify";
832
+ EmbedProvider2["Unknown"] = "unknown";
833
+ return EmbedProvider2;
834
+ })(EmbedProvider || {});
835
+ var Embed = (0, import_canvas_store7.defineCanvasComponent)(
836
+ { name: "embed", sync: "document" },
837
+ {
838
+ /** The original URL provided by the user */
839
+ url: import_core6.field.string().max(2048).default(""),
840
+ /** The resolved embed/iframe URL */
841
+ embedUrl: import_core6.field.string().max(2048).default(""),
842
+ /** The embed provider (used for provider-specific styling/behavior) */
843
+ provider: import_core6.field.enum(EmbedProvider).default("unknown" /* Unknown */)
844
+ }
845
+ );
846
+
847
+ // src/components/Held.ts
848
+ var import_canvas_store8 = require("@woven-ecs/canvas-store");
849
+ var import_core7 = require("@woven-ecs/core");
850
+ var Held = (0, import_canvas_store8.defineCanvasComponent)(
817
851
  { name: "held", sync: "ephemeral" },
818
852
  {
819
- sessionId: import_core6.field.string().max(36).default("")
853
+ sessionId: import_core7.field.string().max(36).default("")
820
854
  }
821
855
  );
822
856
 
823
857
  // src/components/HitGeometry.ts
824
858
  var import_math3 = require("@woven-canvas/math");
825
- var import_canvas_store8 = require("@woven-ecs/canvas-store");
826
- var import_core7 = require("@woven-ecs/core");
859
+ var import_canvas_store9 = require("@woven-ecs/canvas-store");
860
+ var import_core8 = require("@woven-ecs/core");
827
861
  var _uvToWorldMatrix = [1, 0, 0, 1, 0, 0];
828
862
  var MAX_HIT_CAPSULES = 64;
829
863
  var FLOATS_PER_CAPSULE = 5;
830
864
  var MAX_HIT_ARCS = 2;
831
865
  var FLOATS_PER_ARC = 7;
832
866
  var HitGeometrySchema = {
833
- hitCapsules: import_core7.field.buffer(import_core7.field.float32()).size(MAX_HIT_CAPSULES * FLOATS_PER_CAPSULE),
834
- capsuleCount: import_core7.field.uint16().default(0),
835
- hitArcs: import_core7.field.buffer(import_core7.field.float32()).size(MAX_HIT_ARCS * FLOATS_PER_ARC),
836
- arcCount: import_core7.field.uint16().default(0)
867
+ hitCapsules: import_core8.field.buffer(import_core8.field.float32()).size(MAX_HIT_CAPSULES * FLOATS_PER_CAPSULE),
868
+ capsuleCount: import_core8.field.uint16().default(0),
869
+ hitArcs: import_core8.field.buffer(import_core8.field.float32()).size(MAX_HIT_ARCS * FLOATS_PER_ARC),
870
+ arcCount: import_core8.field.uint16().default(0)
837
871
  };
838
- var HitGeometryDef = class extends import_canvas_store8.CanvasComponentDef {
872
+ var HitGeometryDef = class extends import_canvas_store9.CanvasComponentDef {
839
873
  constructor() {
840
874
  super({ name: "hitHeometry" }, HitGeometrySchema);
841
875
  }
@@ -1139,37 +1173,37 @@ var HitGeometryDef = class extends import_canvas_store8.CanvasComponentDef {
1139
1173
  var HitGeometry = new HitGeometryDef();
1140
1174
 
1141
1175
  // src/components/Hovered.ts
1142
- var import_canvas_store9 = require("@woven-ecs/canvas-store");
1143
- var Hovered = (0, import_canvas_store9.defineCanvasComponent)({ name: "hovered" }, {});
1176
+ var import_canvas_store10 = require("@woven-ecs/canvas-store");
1177
+ var Hovered = (0, import_canvas_store10.defineCanvasComponent)({ name: "hovered" }, {});
1144
1178
 
1145
1179
  // src/components/Image.ts
1146
- var import_canvas_store10 = require("@woven-ecs/canvas-store");
1147
- var import_core8 = require("@woven-ecs/core");
1148
- var Image = (0, import_canvas_store10.defineCanvasComponent)(
1180
+ var import_canvas_store11 = require("@woven-ecs/canvas-store");
1181
+ var import_core9 = require("@woven-ecs/core");
1182
+ var Image = (0, import_canvas_store11.defineCanvasComponent)(
1149
1183
  { name: "image", sync: "document" },
1150
1184
  {
1151
1185
  /** Image width in pixels */
1152
- width: import_core8.field.uint16().default(0),
1186
+ width: import_core9.field.uint16().default(0),
1153
1187
  /** Image height in pixels */
1154
- height: import_core8.field.uint16().default(0),
1188
+ height: import_core9.field.uint16().default(0),
1155
1189
  /** Alt text for accessibility */
1156
- alt: import_core8.field.string().max(256).default("")
1190
+ alt: import_core9.field.string().max(256).default("")
1157
1191
  }
1158
1192
  );
1159
1193
 
1160
1194
  // src/components/Opacity.ts
1161
- var import_canvas_store11 = require("@woven-ecs/canvas-store");
1162
- var import_core9 = require("@woven-ecs/core");
1163
- var Opacity = (0, import_canvas_store11.defineCanvasComponent)(
1195
+ var import_canvas_store12 = require("@woven-ecs/canvas-store");
1196
+ var import_core10 = require("@woven-ecs/core");
1197
+ var Opacity = (0, import_canvas_store12.defineCanvasComponent)(
1164
1198
  { name: "opacity" },
1165
1199
  {
1166
- value: import_core9.field.uint8().default(255)
1200
+ value: import_core10.field.uint8().default(255)
1167
1201
  }
1168
1202
  );
1169
1203
 
1170
1204
  // src/components/Pointer.ts
1171
- var import_canvas_store12 = require("@woven-ecs/canvas-store");
1172
- var import_core10 = require("@woven-ecs/core");
1205
+ var import_canvas_store13 = require("@woven-ecs/canvas-store");
1206
+ var import_core11 = require("@woven-ecs/core");
1173
1207
  var PointerButton = {
1174
1208
  None: "none",
1175
1209
  Left: "left",
@@ -1186,32 +1220,32 @@ var PointerType = {
1186
1220
  var SAMPLE_COUNT = 6;
1187
1221
  var PointerSchema = {
1188
1222
  /** Unique pointer ID (from PointerEvent.pointerId) */
1189
- pointerId: import_core10.field.uint16().default(0),
1223
+ pointerId: import_core11.field.uint16().default(0),
1190
1224
  /** Current position relative to the editor element [x, y] */
1191
- position: import_core10.field.tuple(import_core10.field.float32(), 2).default([0, 0]),
1225
+ position: import_core11.field.tuple(import_core11.field.float32(), 2).default([0, 0]),
1192
1226
  /** Position where the pointer went down [x, y] */
1193
- downPosition: import_core10.field.tuple(import_core10.field.float32(), 2).default([0, 0]),
1227
+ downPosition: import_core11.field.tuple(import_core11.field.float32(), 2).default([0, 0]),
1194
1228
  /** Frame number when the pointer went down (for click detection) */
1195
- downFrame: import_core10.field.uint32().default(0),
1229
+ downFrame: import_core11.field.uint32().default(0),
1196
1230
  /** Which button is pressed */
1197
- button: import_core10.field.enum(PointerButton).default(PointerButton.None),
1231
+ button: import_core11.field.enum(PointerButton).default(PointerButton.None),
1198
1232
  /** Type of pointer device */
1199
- pointerType: import_core10.field.enum(PointerType).default(PointerType.Mouse),
1233
+ pointerType: import_core11.field.enum(PointerType).default(PointerType.Mouse),
1200
1234
  /** Pressure from 0 to 1 (for pen/touch) */
1201
- pressure: import_core10.field.float32().default(0),
1235
+ pressure: import_core11.field.float32().default(0),
1202
1236
  /** Whether the pointer event target was not the editor element */
1203
- obscured: import_core10.field.boolean().default(false),
1237
+ obscured: import_core11.field.boolean().default(false),
1204
1238
  // Velocity tracking (ring buffer for position samples)
1205
1239
  /** Ring buffer of previous positions [x0, y0, x1, y1, ...] @internal */
1206
- _prevPositions: import_core10.field.array(import_core10.field.float32(), SAMPLE_COUNT * 2),
1240
+ _prevPositions: import_core11.field.array(import_core11.field.float32(), SAMPLE_COUNT * 2),
1207
1241
  /** Ring buffer of timestamps for each position sample @internal */
1208
- _prevTimes: import_core10.field.array(import_core10.field.float32(), SAMPLE_COUNT),
1242
+ _prevTimes: import_core11.field.array(import_core11.field.float32(), SAMPLE_COUNT),
1209
1243
  /** Total number of samples added (used for ring buffer indexing) @internal */
1210
- _sampleCount: import_core10.field.int32().default(0),
1244
+ _sampleCount: import_core11.field.int32().default(0),
1211
1245
  /** Computed velocity [vx, vy] in pixels per second @internal */
1212
- _velocity: import_core10.field.tuple(import_core10.field.float32(), 2).default([0, 0])
1246
+ _velocity: import_core11.field.tuple(import_core11.field.float32(), 2).default([0, 0])
1213
1247
  };
1214
- var PointerDef = class extends import_canvas_store12.CanvasComponentDef {
1248
+ var PointerDef = class extends import_canvas_store13.CanvasComponentDef {
1215
1249
  constructor() {
1216
1250
  super({ name: "pointer" }, PointerSchema);
1217
1251
  }
@@ -1320,103 +1354,103 @@ function addPointerSample(pointer, position, time) {
1320
1354
  }
1321
1355
 
1322
1356
  // src/components/ScaleWithZoom.ts
1323
- var import_canvas_store13 = require("@woven-ecs/canvas-store");
1324
- var import_core11 = require("@woven-ecs/core");
1325
- var ScaleWithZoom = (0, import_canvas_store13.defineCanvasComponent)(
1357
+ var import_canvas_store14 = require("@woven-ecs/canvas-store");
1358
+ var import_core12 = require("@woven-ecs/core");
1359
+ var ScaleWithZoom = (0, import_canvas_store14.defineCanvasComponent)(
1326
1360
  { name: "scaleWithZoom" },
1327
1361
  {
1328
1362
  /** Pivot point for scaling as [x, y] (0-1, default 0.5,0.5 = center) */
1329
- anchor: import_core11.field.tuple(import_core11.field.float64(), 2).default([0.5, 0.5]),
1363
+ anchor: import_core12.field.tuple(import_core12.field.float64(), 2).default([0.5, 0.5]),
1330
1364
  /** Initial position as [left, top] at zoom=1 */
1331
- startPosition: import_core11.field.tuple(import_core11.field.float64(), 2).default([0, 0]),
1365
+ startPosition: import_core12.field.tuple(import_core12.field.float64(), 2).default([0, 0]),
1332
1366
  /** Initial size as [width, height] at zoom=1 */
1333
- startSize: import_core11.field.tuple(import_core11.field.float64(), 2).default([0, 0]),
1367
+ startSize: import_core12.field.tuple(import_core12.field.float64(), 2).default([0, 0]),
1334
1368
  /** Scale multiplier per dimension: [x, y] (0 = no zoom effect, 1 = full zoom effect, 0.5 = half effect) */
1335
- scaleMultiplier: import_core11.field.tuple(import_core11.field.float64(), 2).default([1, 1])
1369
+ scaleMultiplier: import_core12.field.tuple(import_core12.field.float64(), 2).default([1, 1])
1336
1370
  }
1337
1371
  );
1338
1372
 
1339
1373
  // src/components/Shape.ts
1340
- var import_canvas_store14 = require("@woven-ecs/canvas-store");
1341
- var import_core12 = require("@woven-ecs/core");
1374
+ var import_canvas_store15 = require("@woven-ecs/canvas-store");
1375
+ var import_core13 = require("@woven-ecs/core");
1342
1376
  var StrokeKind = {
1343
1377
  Solid: "solid",
1344
1378
  Dashed: "dashed",
1345
1379
  None: "none"
1346
1380
  };
1347
- var Shape = (0, import_canvas_store14.defineCanvasComponent)(
1381
+ var Shape = (0, import_canvas_store15.defineCanvasComponent)(
1348
1382
  { name: "shape", sync: "document" },
1349
1383
  {
1350
1384
  /** The kind of shape to render (e.g. 'rectangle', 'ellipse', or custom shape key) */
1351
- kind: import_core12.field.string().default("rectangle"),
1385
+ kind: import_core13.field.string().default("rectangle"),
1352
1386
  /** Stroke style */
1353
- strokeKind: import_core12.field.enum(StrokeKind).default(StrokeKind.Solid),
1387
+ strokeKind: import_core13.field.enum(StrokeKind).default(StrokeKind.Solid),
1354
1388
  /** Stroke width in pixels */
1355
- strokeWidth: import_core12.field.uint16().default(2),
1389
+ strokeWidth: import_core13.field.uint16().default(2),
1356
1390
  /** Stroke color - red component (0-255) */
1357
- strokeRed: import_core12.field.uint8().default(0),
1391
+ strokeRed: import_core13.field.uint8().default(0),
1358
1392
  /** Stroke color - green component (0-255) */
1359
- strokeGreen: import_core12.field.uint8().default(0),
1393
+ strokeGreen: import_core13.field.uint8().default(0),
1360
1394
  /** Stroke color - blue component (0-255) */
1361
- strokeBlue: import_core12.field.uint8().default(0),
1395
+ strokeBlue: import_core13.field.uint8().default(0),
1362
1396
  /** Stroke color - alpha component (0-255) */
1363
- strokeAlpha: import_core12.field.uint8().default(255),
1397
+ strokeAlpha: import_core13.field.uint8().default(255),
1364
1398
  /** Fill color - red component (0-255) */
1365
- fillRed: import_core12.field.uint8().default(255),
1399
+ fillRed: import_core13.field.uint8().default(255),
1366
1400
  /** Fill color - green component (0-255) */
1367
- fillGreen: import_core12.field.uint8().default(255),
1401
+ fillGreen: import_core13.field.uint8().default(255),
1368
1402
  /** Fill color - blue component (0-255) */
1369
- fillBlue: import_core12.field.uint8().default(255),
1403
+ fillBlue: import_core13.field.uint8().default(255),
1370
1404
  /** Fill color - alpha component (0-255) */
1371
- fillAlpha: import_core12.field.uint8().default(0)
1405
+ fillAlpha: import_core13.field.uint8().default(0)
1372
1406
  }
1373
1407
  );
1374
1408
 
1375
1409
  // src/components/Text.ts
1376
- var import_canvas_store15 = require("@woven-ecs/canvas-store");
1377
- var import_core13 = require("@woven-ecs/core");
1378
- var Text = (0, import_canvas_store15.defineCanvasComponent)(
1410
+ var import_canvas_store16 = require("@woven-ecs/canvas-store");
1411
+ var import_core14 = require("@woven-ecs/core");
1412
+ var Text = (0, import_canvas_store16.defineCanvasComponent)(
1379
1413
  { name: "text", sync: "document" },
1380
1414
  {
1381
1415
  /** HTML content (supports rich text formatting) */
1382
- content: import_core13.field.string().max(1e4).default(""),
1416
+ content: import_core14.field.string().max(1e4).default(""),
1383
1417
  /** Font size in pixels */
1384
- fontSizePx: import_core13.field.float64().default(24),
1418
+ fontSizePx: import_core14.field.float64().default(24),
1385
1419
  /** Font family name */
1386
- fontFamily: import_core13.field.string().max(64).default("Figtree"),
1420
+ fontFamily: import_core14.field.string().max(64).default("Figtree"),
1387
1421
  /** Line height multiplier */
1388
- lineHeight: import_core13.field.float64().default(1.2),
1422
+ lineHeight: import_core14.field.float64().default(1.2),
1389
1423
  /** Letter spacing in em units */
1390
- letterSpacingEm: import_core13.field.float64().default(0),
1424
+ letterSpacingEm: import_core14.field.float64().default(0),
1391
1425
  /** Whether width is constrained (text wraps) */
1392
- constrainWidth: import_core13.field.boolean().default(true),
1426
+ constrainWidth: import_core14.field.boolean().default(true),
1393
1427
  /** Default text alignment for new paragraphs */
1394
- defaultAlignment: import_core13.field.enum(TextAlignment).default(TextAlignment.Left)
1428
+ defaultAlignment: import_core14.field.enum(TextAlignment).default(TextAlignment.Left)
1395
1429
  }
1396
1430
  );
1397
1431
 
1398
1432
  // src/components/User.ts
1399
- var import_canvas_store16 = require("@woven-ecs/canvas-store");
1400
- var import_core14 = require("@woven-ecs/core");
1401
- var User = (0, import_canvas_store16.defineCanvasComponent)(
1433
+ var import_canvas_store17 = require("@woven-ecs/canvas-store");
1434
+ var import_core15 = require("@woven-ecs/core");
1435
+ var User = (0, import_canvas_store17.defineCanvasComponent)(
1402
1436
  { name: "user", sync: "ephemeral" },
1403
1437
  {
1404
- userId: import_core14.field.string().max(36),
1405
- sessionId: import_core14.field.string().max(36),
1406
- color: import_core14.field.string().max(7),
1407
- name: import_core14.field.string().max(100),
1408
- avatar: import_core14.field.string().max(500),
1409
- position: import_core14.field.tuple(import_core14.field.float32(), 2).default([0, 0])
1438
+ userId: import_core15.field.string().max(36),
1439
+ sessionId: import_core15.field.string().max(36),
1440
+ color: import_core15.field.string().max(7),
1441
+ name: import_core15.field.string().max(100),
1442
+ avatar: import_core15.field.string().max(500),
1443
+ position: import_core15.field.tuple(import_core15.field.float32(), 2).default([0, 0])
1410
1444
  }
1411
1445
  );
1412
1446
 
1413
1447
  // src/components/VerticalAlign.ts
1414
- var import_canvas_store17 = require("@woven-ecs/canvas-store");
1415
- var import_core15 = require("@woven-ecs/core");
1416
- var VerticalAlign = (0, import_canvas_store17.defineCanvasComponent)(
1448
+ var import_canvas_store18 = require("@woven-ecs/canvas-store");
1449
+ var import_core16 = require("@woven-ecs/core");
1450
+ var VerticalAlign = (0, import_canvas_store18.defineCanvasComponent)(
1417
1451
  { name: "verticalAlign", sync: "document" },
1418
1452
  {
1419
- value: import_core15.field.enum(VerticalAlignment).default(VerticalAlignment.Top)
1453
+ value: import_core16.field.enum(VerticalAlignment).default(VerticalAlignment.Top)
1420
1454
  }
1421
1455
  );
1422
1456
 
@@ -1449,23 +1483,23 @@ __export(singletons_exports, {
1449
1483
  });
1450
1484
 
1451
1485
  // src/singletons/Camera.ts
1452
- var import_canvas_store19 = require("@woven-ecs/canvas-store");
1453
- var import_core17 = require("@woven-ecs/core");
1486
+ var import_canvas_store20 = require("@woven-ecs/canvas-store");
1487
+ var import_core18 = require("@woven-ecs/core");
1454
1488
 
1455
1489
  // src/singletons/Screen.ts
1456
- var import_canvas_store18 = require("@woven-ecs/canvas-store");
1457
- var import_core16 = require("@woven-ecs/core");
1490
+ var import_canvas_store19 = require("@woven-ecs/canvas-store");
1491
+ var import_core17 = require("@woven-ecs/core");
1458
1492
  var ScreenSchema = {
1459
1493
  /** Width of the editor element in pixels */
1460
- width: import_core16.field.float64().default(0),
1494
+ width: import_core17.field.float64().default(0),
1461
1495
  /** Height of the editor element in pixels */
1462
- height: import_core16.field.float64().default(0),
1496
+ height: import_core17.field.float64().default(0),
1463
1497
  /** Left offset of the editor element relative to the viewport */
1464
- left: import_core16.field.float64().default(0),
1498
+ left: import_core17.field.float64().default(0),
1465
1499
  /** Top offset of the editor element relative to the viewport */
1466
- top: import_core16.field.float64().default(0)
1500
+ top: import_core17.field.float64().default(0)
1467
1501
  };
1468
- var ScreenDef = class extends import_canvas_store18.CanvasSingletonDef {
1502
+ var ScreenDef = class extends import_canvas_store19.CanvasSingletonDef {
1469
1503
  constructor() {
1470
1504
  super({ name: "screen" }, ScreenSchema);
1471
1505
  }
@@ -1490,17 +1524,17 @@ var Screen = new ScreenDef();
1490
1524
  // src/singletons/Camera.ts
1491
1525
  var CameraSchema = {
1492
1526
  /** Top position of the camera in world coordinates */
1493
- top: import_core17.field.float64().default(0),
1527
+ top: import_core18.field.float64().default(0),
1494
1528
  /** Left position of the camera in world coordinates */
1495
- left: import_core17.field.float64().default(0),
1529
+ left: import_core18.field.float64().default(0),
1496
1530
  /** Zoom level (1 = 100%, 2 = 200%, 0.5 = 50%) */
1497
- zoom: import_core17.field.float64().default(1),
1531
+ zoom: import_core18.field.float64().default(1),
1498
1532
  /** Whether the camera viewport intersects any blocks */
1499
- canSeeBlocks: import_core17.field.boolean().default(true),
1533
+ canSeeBlocks: import_core18.field.boolean().default(true),
1500
1534
  /** Reference to a block that the camera can currently see (for optimization) */
1501
- lastSeenBlock: import_core17.field.ref()
1535
+ lastSeenBlock: import_core18.field.ref()
1502
1536
  };
1503
- var CameraDef = class extends import_canvas_store19.CanvasSingletonDef {
1537
+ var CameraDef = class extends import_canvas_store20.CanvasSingletonDef {
1504
1538
  constructor() {
1505
1539
  super({ name: "camera", sync: "local" }, CameraSchema);
1506
1540
  }
@@ -1573,23 +1607,23 @@ var CameraDef = class extends import_canvas_store19.CanvasSingletonDef {
1573
1607
  var Camera = new CameraDef();
1574
1608
 
1575
1609
  // src/singletons/Controls.ts
1576
- var import_canvas_store20 = require("@woven-ecs/canvas-store");
1577
- var import_core18 = require("@woven-ecs/core");
1610
+ var import_canvas_store21 = require("@woven-ecs/canvas-store");
1611
+ var import_core19 = require("@woven-ecs/core");
1578
1612
  var ControlsSchema = {
1579
1613
  /** Tool activated by left mouse button */
1580
- leftMouseTool: import_core18.field.string().max(32).default("select"),
1614
+ leftMouseTool: import_core19.field.string().max(32).default("select"),
1581
1615
  /** Tool activated by middle mouse button */
1582
- middleMouseTool: import_core18.field.string().max(32).default("hand"),
1616
+ middleMouseTool: import_core19.field.string().max(32).default("hand"),
1583
1617
  /** Tool activated by right mouse button */
1584
- rightMouseTool: import_core18.field.string().max(32).default("menu"),
1618
+ rightMouseTool: import_core19.field.string().max(32).default("hand"),
1585
1619
  /** Tool activated by mouse wheel */
1586
- wheelTool: import_core18.field.string().max(32).default("scroll"),
1620
+ wheelTool: import_core19.field.string().max(32).default("scroll"),
1587
1621
  /** Tool activated by mouse wheel with modifier key held */
1588
- modWheelTool: import_core18.field.string().max(32).default("zoom"),
1622
+ modWheelTool: import_core19.field.string().max(32).default("zoom"),
1589
1623
  /** JSON snapshot of block to place on next click (empty string = no placement active) */
1590
- heldSnapshot: import_core18.field.string().max(65536).default("")
1624
+ heldSnapshot: import_core19.field.string().max(65536).default("")
1591
1625
  };
1592
- var ControlsDef = class extends import_canvas_store20.CanvasSingletonDef {
1626
+ var ControlsDef = class extends import_canvas_store21.CanvasSingletonDef {
1593
1627
  constructor() {
1594
1628
  super({ name: "controls" }, ControlsSchema);
1595
1629
  }
@@ -1628,19 +1662,19 @@ var ControlsDef = class extends import_canvas_store20.CanvasSingletonDef {
1628
1662
  var Controls = new ControlsDef();
1629
1663
 
1630
1664
  // src/singletons/Cursor.ts
1631
- var import_canvas_store21 = require("@woven-ecs/canvas-store");
1632
- var import_core19 = require("@woven-ecs/core");
1665
+ var import_canvas_store22 = require("@woven-ecs/canvas-store");
1666
+ var import_core20 = require("@woven-ecs/core");
1633
1667
  var CursorSchema = {
1634
1668
  /** Base cursor kind (from current tool) */
1635
- cursorKind: import_core19.field.string().max(64).default("select"),
1669
+ cursorKind: import_core20.field.string().max(64).default("select"),
1636
1670
  /** Base cursor rotation in radians */
1637
- rotation: import_core19.field.float64().default(0),
1671
+ rotation: import_core20.field.float64().default(0),
1638
1672
  /** Context-specific cursor kind (overrides cursorKind when set, e.g., during drag/hover) */
1639
- contextCursorKind: import_core19.field.string().max(64).default(""),
1673
+ contextCursorKind: import_core20.field.string().max(64).default(""),
1640
1674
  /** Context cursor rotation in radians */
1641
- contextRotation: import_core19.field.float64().default(0)
1675
+ contextRotation: import_core20.field.float64().default(0)
1642
1676
  };
1643
- var CursorDef2 = class extends import_canvas_store21.CanvasSingletonDef {
1677
+ var CursorDef2 = class extends import_canvas_store22.CanvasSingletonDef {
1644
1678
  constructor() {
1645
1679
  super({ name: "cursor" }, CursorSchema);
1646
1680
  }
@@ -1685,40 +1719,40 @@ var CursorDef2 = class extends import_canvas_store21.CanvasSingletonDef {
1685
1719
  var Cursor = new CursorDef2();
1686
1720
 
1687
1721
  // src/singletons/Frame.ts
1688
- var import_canvas_store22 = require("@woven-ecs/canvas-store");
1689
- var import_core20 = require("@woven-ecs/core");
1690
- var Frame = (0, import_canvas_store22.defineCanvasSingleton)(
1722
+ var import_canvas_store23 = require("@woven-ecs/canvas-store");
1723
+ var import_core21 = require("@woven-ecs/core");
1724
+ var Frame = (0, import_canvas_store23.defineCanvasSingleton)(
1691
1725
  { name: "frame" },
1692
1726
  {
1693
1727
  /** Current frame number (increments each tick) */
1694
- number: import_core20.field.uint32().default(0),
1728
+ number: import_core21.field.uint32().default(0),
1695
1729
  /** Time since last frame in seconds */
1696
- delta: import_core20.field.float64().default(0),
1730
+ delta: import_core21.field.float64().default(0),
1697
1731
  /** Timestamp of current frame in milliseconds (from performance.now()) */
1698
- time: import_core20.field.float64().default(0),
1732
+ time: import_core21.field.float64().default(0),
1699
1733
  /** Timestamp of previous frame in milliseconds (0 if first frame) */
1700
- lastTime: import_core20.field.float64().default(0)
1734
+ lastTime: import_core21.field.float64().default(0)
1701
1735
  }
1702
1736
  );
1703
1737
 
1704
1738
  // src/singletons/Grid.ts
1705
- var import_canvas_store23 = require("@woven-ecs/canvas-store");
1706
- var import_core21 = require("@woven-ecs/core");
1739
+ var import_canvas_store24 = require("@woven-ecs/canvas-store");
1740
+ var import_core22 = require("@woven-ecs/core");
1707
1741
  var GridSchema = {
1708
1742
  /** Whether grid snapping is enabled */
1709
- enabled: import_core21.field.boolean().default(false),
1743
+ enabled: import_core22.field.boolean().default(false),
1710
1744
  /** Whether resized/rotated objects must stay aligned to the grid */
1711
- strict: import_core21.field.boolean().default(false),
1745
+ strict: import_core22.field.boolean().default(false),
1712
1746
  /** Width of each grid column in world units */
1713
- colWidth: import_core21.field.float64().default(20),
1747
+ colWidth: import_core22.field.float64().default(20),
1714
1748
  /** Height of each grid row in world units */
1715
- rowHeight: import_core21.field.float64().default(20),
1749
+ rowHeight: import_core22.field.float64().default(20),
1716
1750
  /** Angular snap increment in radians when grid is enabled */
1717
- snapAngleRad: import_core21.field.float64().default(Math.PI / 36),
1751
+ snapAngleRad: import_core22.field.float64().default(Math.PI / 36),
1718
1752
  /** Angular snap increment in radians when shift key is held */
1719
- shiftSnapAngleRad: import_core21.field.float64().default(Math.PI / 12)
1753
+ shiftSnapAngleRad: import_core22.field.float64().default(Math.PI / 12)
1720
1754
  };
1721
- var GridDef = class extends import_canvas_store23.CanvasSingletonDef {
1755
+ var GridDef = class extends import_canvas_store24.CanvasSingletonDef {
1722
1756
  constructor() {
1723
1757
  super({ name: "grid" }, GridSchema);
1724
1758
  }
@@ -1778,17 +1812,17 @@ var GridDef = class extends import_canvas_store23.CanvasSingletonDef {
1778
1812
  var Grid = new GridDef();
1779
1813
 
1780
1814
  // src/singletons/Intersect.ts
1781
- var import_canvas_store24 = require("@woven-ecs/canvas-store");
1782
- var import_core22 = require("@woven-ecs/core");
1815
+ var import_canvas_store25 = require("@woven-ecs/canvas-store");
1816
+ var import_core23 = require("@woven-ecs/core");
1783
1817
  var IntersectSchema = {
1784
1818
  // Store up to 5 intersected entity IDs
1785
- entity1: import_core22.field.ref(),
1786
- entity2: import_core22.field.ref(),
1787
- entity3: import_core22.field.ref(),
1788
- entity4: import_core22.field.ref(),
1789
- entity5: import_core22.field.ref()
1819
+ entity1: import_core23.field.ref(),
1820
+ entity2: import_core23.field.ref(),
1821
+ entity3: import_core23.field.ref(),
1822
+ entity4: import_core23.field.ref(),
1823
+ entity5: import_core23.field.ref()
1790
1824
  };
1791
- var IntersectDef = class extends import_canvas_store24.CanvasSingletonDef {
1825
+ var IntersectDef = class extends import_canvas_store25.CanvasSingletonDef {
1792
1826
  constructor() {
1793
1827
  super({ name: "intersect" }, IntersectSchema);
1794
1828
  }
@@ -1837,31 +1871,31 @@ var IntersectDef = class extends import_canvas_store24.CanvasSingletonDef {
1837
1871
  var Intersect = new IntersectDef();
1838
1872
 
1839
1873
  // src/singletons/Keyboard.ts
1840
- var import_canvas_store25 = require("@woven-ecs/canvas-store");
1841
- var import_core23 = require("@woven-ecs/core");
1874
+ var import_canvas_store26 = require("@woven-ecs/canvas-store");
1875
+ var import_core24 = require("@woven-ecs/core");
1842
1876
  var KEY_BUFFER_SIZE = 32;
1843
1877
  var KeyboardSchema = {
1844
1878
  /**
1845
1879
  * Buffer where each bit represents whether a key is currently pressed.
1846
1880
  * Uses field.buffer for zero-allocation subarray views.
1847
1881
  */
1848
- keysDown: import_core23.field.buffer(import_core23.field.uint8()).size(KEY_BUFFER_SIZE),
1882
+ keysDown: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
1849
1883
  /**
1850
1884
  * Buffer for key-down triggers (true for exactly 1 frame when key is pressed).
1851
1885
  * Uses field.buffer for zero-allocation subarray views.
1852
1886
  */
1853
- keysDownTrigger: import_core23.field.buffer(import_core23.field.uint8()).size(KEY_BUFFER_SIZE),
1887
+ keysDownTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
1854
1888
  /**
1855
1889
  * Buffer for key-up triggers (true for exactly 1 frame when key is released).
1856
1890
  * Uses field.buffer for zero-allocation subarray views.
1857
1891
  */
1858
- keysUpTrigger: import_core23.field.buffer(import_core23.field.uint8()).size(KEY_BUFFER_SIZE),
1892
+ keysUpTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
1859
1893
  /** Common modifier - Shift key is down */
1860
- shiftDown: import_core23.field.boolean().default(false),
1894
+ shiftDown: import_core24.field.boolean().default(false),
1861
1895
  /** Common modifier - Alt/Option key is down */
1862
- altDown: import_core23.field.boolean().default(false),
1896
+ altDown: import_core24.field.boolean().default(false),
1863
1897
  /** Common modifier - Ctrl (Windows/Linux) or Cmd (Mac) is down */
1864
- modDown: import_core23.field.boolean().default(false)
1898
+ modDown: import_core24.field.boolean().default(false)
1865
1899
  };
1866
1900
  function getBit(buffer, bitIndex) {
1867
1901
  if (bitIndex < 0 || bitIndex >= buffer.length * 8) return false;
@@ -1869,7 +1903,7 @@ function getBit(buffer, bitIndex) {
1869
1903
  const bitOffset = bitIndex % 8;
1870
1904
  return (buffer[byteIndex] & 1 << bitOffset) !== 0;
1871
1905
  }
1872
- var KeyboardDef = class extends import_canvas_store25.CanvasSingletonDef {
1906
+ var KeyboardDef = class extends import_canvas_store26.CanvasSingletonDef {
1873
1907
  constructor() {
1874
1908
  super({ name: "keyboard" }, KeyboardSchema);
1875
1909
  }
@@ -2143,27 +2177,27 @@ var Key = {
2143
2177
  };
2144
2178
 
2145
2179
  // src/singletons/Mouse.ts
2146
- var import_canvas_store26 = require("@woven-ecs/canvas-store");
2147
- var import_core24 = require("@woven-ecs/core");
2180
+ var import_canvas_store27 = require("@woven-ecs/canvas-store");
2181
+ var import_core25 = require("@woven-ecs/core");
2148
2182
  var MouseSchema = {
2149
2183
  /** Current mouse position relative to the editor element [x, y] */
2150
- position: import_core24.field.tuple(import_core24.field.float32(), 2).default([0, 0]),
2184
+ position: import_core25.field.tuple(import_core25.field.float32(), 2).default([0, 0]),
2151
2185
  /** Horizontal wheel delta (positive = scroll right) */
2152
- wheelDeltaX: import_core24.field.float32().default(0),
2186
+ wheelDeltaX: import_core25.field.float32().default(0),
2153
2187
  /** Vertical wheel delta (positive = scroll down), normalized across browsers */
2154
- wheelDeltaY: import_core24.field.float32().default(0),
2188
+ wheelDeltaY: import_core25.field.float32().default(0),
2155
2189
  /** True for 1 frame when mouse moves */
2156
- moveTrigger: import_core24.field.boolean().default(false),
2190
+ moveTrigger: import_core25.field.boolean().default(false),
2157
2191
  /** True for 1 frame when wheel is scrolled */
2158
- wheelTrigger: import_core24.field.boolean().default(false),
2192
+ wheelTrigger: import_core25.field.boolean().default(false),
2159
2193
  /** True for 1 frame when mouse enters the editor element */
2160
- enterTrigger: import_core24.field.boolean().default(false),
2194
+ enterTrigger: import_core25.field.boolean().default(false),
2161
2195
  /** True for 1 frame when mouse leaves the editor element */
2162
- leaveTrigger: import_core24.field.boolean().default(false),
2196
+ leaveTrigger: import_core25.field.boolean().default(false),
2163
2197
  /** Whether the mouse is over a UI element (not the canvas) */
2164
- obscured: import_core24.field.boolean().default(false)
2198
+ obscured: import_core25.field.boolean().default(false)
2165
2199
  };
2166
- var MouseDef = class extends import_canvas_store26.CanvasSingletonDef {
2200
+ var MouseDef = class extends import_canvas_store27.CanvasSingletonDef {
2167
2201
  constructor() {
2168
2202
  super({ name: "mouse" }, MouseSchema);
2169
2203
  }
@@ -2201,14 +2235,14 @@ var MouseDef = class extends import_canvas_store26.CanvasSingletonDef {
2201
2235
  var Mouse = new MouseDef();
2202
2236
 
2203
2237
  // src/singletons/RankBounds.ts
2204
- var import_canvas_store27 = require("@woven-ecs/canvas-store");
2205
- var import_core25 = require("@woven-ecs/core");
2238
+ var import_canvas_store28 = require("@woven-ecs/canvas-store");
2239
+ var import_core26 = require("@woven-ecs/core");
2206
2240
  var import_fractional_indexing_jittered = require("fractional-indexing-jittered");
2207
2241
  var RankBoundsSchema = {
2208
- minRank: import_core25.field.string().max(36).default(""),
2209
- maxRank: import_core25.field.string().max(36).default("")
2242
+ minRank: import_core26.field.string().max(36).default(""),
2243
+ maxRank: import_core26.field.string().max(36).default("")
2210
2244
  };
2211
- var RankBoundsDef = class extends import_canvas_store27.CanvasSingletonDef {
2245
+ var RankBoundsDef = class extends import_canvas_store28.CanvasSingletonDef {
2212
2246
  constructor() {
2213
2247
  super({ name: "rankBounds" }, RankBoundsSchema);
2214
2248
  }
@@ -2264,27 +2298,27 @@ var RankBoundsDef = class extends import_canvas_store27.CanvasSingletonDef {
2264
2298
  var RankBounds = new RankBoundsDef();
2265
2299
 
2266
2300
  // src/singletons/ScaleWithZoomState.ts
2267
- var import_canvas_store28 = require("@woven-ecs/canvas-store");
2268
- var import_core26 = require("@woven-ecs/core");
2269
- var ScaleWithZoomState = (0, import_canvas_store28.defineCanvasSingleton)(
2301
+ var import_canvas_store29 = require("@woven-ecs/canvas-store");
2302
+ var import_core27 = require("@woven-ecs/core");
2303
+ var ScaleWithZoomState = (0, import_canvas_store29.defineCanvasSingleton)(
2270
2304
  { name: "scaleWithZoomState" },
2271
2305
  {
2272
2306
  /** Last processed zoom level */
2273
- lastZoom: import_core26.field.float64().default(1)
2307
+ lastZoom: import_core27.field.float64().default(1)
2274
2308
  }
2275
2309
  );
2276
2310
 
2277
2311
  // src/systems/capture/keybindSystem.ts
2278
- var import_core29 = require("@woven-ecs/core");
2312
+ var import_core30 = require("@woven-ecs/core");
2279
2313
 
2280
2314
  // src/command.ts
2281
- var import_core27 = require("@woven-ecs/core");
2282
- var CommandMarker = (0, import_core27.defineComponent)({
2283
- name: import_core27.field.string().max(128)
2315
+ var import_core28 = require("@woven-ecs/core");
2316
+ var CommandMarker = (0, import_core28.defineComponent)({
2317
+ name: import_core28.field.string().max(128)
2284
2318
  });
2285
2319
  var editorPayloads = /* @__PURE__ */ new WeakMap();
2286
2320
  function getPayloadMap(ctx) {
2287
- const { editor } = (0, import_core27.getResources)(ctx);
2321
+ const { editor } = (0, import_core28.getResources)(ctx);
2288
2322
  let map = editorPayloads.get(editor);
2289
2323
  if (!map) {
2290
2324
  map = /* @__PURE__ */ new Map();
@@ -2292,13 +2326,13 @@ function getPayloadMap(ctx) {
2292
2326
  }
2293
2327
  return map;
2294
2328
  }
2295
- var commands = (0, import_core27.defineQuery)((q) => q.with(CommandMarker));
2329
+ var commands = (0, import_core28.defineQuery)((q) => q.with(CommandMarker));
2296
2330
  function defineCommand(name) {
2297
2331
  return {
2298
2332
  name,
2299
2333
  spawn(ctx, payload) {
2300
- const eid = (0, import_core27.createEntity)(ctx);
2301
- (0, import_core27.addComponent)(ctx, eid, CommandMarker, { name });
2334
+ const eid = (0, import_core28.createEntity)(ctx);
2335
+ (0, import_core28.addComponent)(ctx, eid, CommandMarker, { name });
2302
2336
  getPayloadMap(ctx).set(eid, payload);
2303
2337
  return eid;
2304
2338
  },
@@ -2327,7 +2361,7 @@ function cleanupCommands(ctx) {
2327
2361
  const payloads = getPayloadMap(ctx);
2328
2362
  for (const eid of commands.current(ctx)) {
2329
2363
  payloads.delete(eid);
2330
- (0, import_core27.removeEntity)(ctx, eid);
2364
+ (0, import_core28.removeEntity)(ctx, eid);
2331
2365
  }
2332
2366
  }
2333
2367
  function on(ctx, def, handler) {
@@ -2340,11 +2374,11 @@ var Redo = defineCommand("redo");
2340
2374
  var ResetKeyboard = defineCommand("reset-keyboard");
2341
2375
 
2342
2376
  // src/EditorSystem.ts
2343
- var import_core28 = require("@woven-ecs/core");
2377
+ var import_core29 = require("@woven-ecs/core");
2344
2378
  var DEFAULT_PRIORITY = 0;
2345
2379
  function defineEditorSystem(options, execute) {
2346
2380
  return {
2347
- _system: new import_core28.MainThreadSystem(execute),
2381
+ _system: new import_core29.MainThreadSystem(execute),
2348
2382
  phase: options.phase,
2349
2383
  priority: options.priority ?? DEFAULT_PRIORITY
2350
2384
  };
@@ -2353,14 +2387,14 @@ function defineEditorSystem(options, execute) {
2353
2387
  // src/systems/capture/keybindSystem.ts
2354
2388
  var keybindSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
2355
2389
  const keyboard = Keyboard.read(ctx);
2356
- const { editor } = (0, import_core29.getResources)(ctx);
2390
+ const { editor } = (0, import_core30.getResources)(ctx);
2357
2391
  for (const keybind of editor.keybinds) {
2358
2392
  let triggered = Keyboard.isKeyDownTrigger(ctx, keybind.key);
2359
2393
  triggered &&= !!keybind.mod === keyboard.modDown;
2360
2394
  triggered &&= !!keybind.shift === keyboard.shiftDown;
2361
2395
  if (triggered) {
2362
- const eid = (0, import_core29.createEntity)(ctx);
2363
- (0, import_core29.addComponent)(ctx, eid, CommandMarker, { name: keybind.command });
2396
+ const eid = (0, import_core30.createEntity)(ctx);
2397
+ (0, import_core30.addComponent)(ctx, eid, CommandMarker, { name: keybind.command });
2364
2398
  break;
2365
2399
  }
2366
2400
  }
@@ -2382,7 +2416,7 @@ var frameSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ctx) =>
2382
2416
  });
2383
2417
 
2384
2418
  // src/systems/input/keyboardSystem.ts
2385
- var import_core30 = require("@woven-ecs/core");
2419
+ var import_core31 = require("@woven-ecs/core");
2386
2420
  var instanceState = /* @__PURE__ */ new WeakMap();
2387
2421
  function attachKeyboardListeners(domElement) {
2388
2422
  if (instanceState.has(domElement)) return;
@@ -2418,7 +2452,8 @@ function detachKeyboardListeners(domElement) {
2418
2452
  instanceState.delete(domElement);
2419
2453
  }
2420
2454
  var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2421
- const resources = (0, import_core30.getResources)(ctx);
2455
+ const resources = (0, import_core31.getResources)(ctx);
2456
+ if (!resources.domElement) return;
2422
2457
  const state = instanceState.get(resources.domElement);
2423
2458
  if (!state) return;
2424
2459
  on(ctx, ResetKeyboard, () => {
@@ -2471,7 +2506,7 @@ function isZeroed(buffer) {
2471
2506
  }
2472
2507
 
2473
2508
  // src/systems/input/mouseSystem.ts
2474
- var import_core31 = require("@woven-ecs/core");
2509
+ var import_core32 = require("@woven-ecs/core");
2475
2510
  var instanceState2 = /* @__PURE__ */ new WeakMap();
2476
2511
  function attachMouseListeners(domElement) {
2477
2512
  if (instanceState2.has(domElement)) return;
@@ -2519,7 +2554,8 @@ function detachMouseListeners(domElement) {
2519
2554
  instanceState2.delete(domElement);
2520
2555
  }
2521
2556
  var mouseSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2522
- const resources = (0, import_core31.getResources)(ctx);
2557
+ const resources = (0, import_core32.getResources)(ctx);
2558
+ if (!resources.domElement) return;
2523
2559
  const state = instanceState2.get(resources.domElement);
2524
2560
  if (!state) return;
2525
2561
  const currentMouse = Mouse.read(ctx);
@@ -2575,7 +2611,7 @@ function normalizeWheelDelta(deltaY, deltaMode) {
2575
2611
  }
2576
2612
 
2577
2613
  // src/systems/input/pointerSystem.ts
2578
- var import_core32 = require("@woven-ecs/core");
2614
+ var import_core33 = require("@woven-ecs/core");
2579
2615
  var instanceState3 = /* @__PURE__ */ new WeakMap();
2580
2616
  function attachPointerListeners(domElement) {
2581
2617
  if (instanceState3.has(domElement)) return;
@@ -2596,9 +2632,12 @@ function attachPointerListeners(domElement) {
2596
2632
  });
2597
2633
  },
2598
2634
  onContextMenu: (e) => {
2635
+ if (e.target instanceof HTMLElement && e.target.closest('[contenteditable="true"]')) return;
2599
2636
  e.preventDefault();
2600
- const hasPointerDown = state.eventsBuffer.some((evt) => evt.type === "pointerdown");
2601
- if (hasPointerDown) return;
2637
+ const hasRightButtonEvent = state.eventsBuffer.some(
2638
+ (evt) => evt.button === 2 && (evt.type === "pointerdown" || evt.type === "pointerup")
2639
+ );
2640
+ if (hasRightButtonEvent) return;
2602
2641
  state.eventsBuffer.push({
2603
2642
  type: "pointerdown",
2604
2643
  pointerId: 0,
@@ -2666,8 +2705,9 @@ function detachPointerListeners(domElement) {
2666
2705
  instanceState3.delete(domElement);
2667
2706
  }
2668
2707
  var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2669
- const resources = (0, import_core32.getResources)(ctx);
2708
+ const resources = (0, import_core33.getResources)(ctx);
2670
2709
  const { domElement } = resources;
2710
+ if (!domElement) return;
2671
2711
  const state = instanceState3.get(domElement);
2672
2712
  if (!state) return;
2673
2713
  state.frameCount++;
@@ -2677,8 +2717,8 @@ var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2677
2717
  switch (event.type) {
2678
2718
  case "pointerdown": {
2679
2719
  const position = [event.clientX - screen.left, event.clientY - screen.top];
2680
- const entityId = (0, import_core32.createEntity)(ctx);
2681
- (0, import_core32.addComponent)(ctx, entityId, Pointer, {
2720
+ const entityId = (0, import_core33.createEntity)(ctx);
2721
+ (0, import_core33.addComponent)(ctx, entityId, Pointer, {
2682
2722
  pointerId: event.pointerId,
2683
2723
  position,
2684
2724
  downPosition: position,
@@ -2710,7 +2750,7 @@ var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2710
2750
  const position = [event.clientX - screen.left, event.clientY - screen.top];
2711
2751
  const pointer = Pointer.write(ctx, entityId);
2712
2752
  addPointerSample(pointer, position, time);
2713
- (0, import_core32.removeEntity)(ctx, entityId);
2753
+ (0, import_core33.removeEntity)(ctx, entityId);
2714
2754
  state.pointerEntityMap.delete(event.pointerId);
2715
2755
  break;
2716
2756
  }
@@ -2720,7 +2760,7 @@ var pointerSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2720
2760
  });
2721
2761
 
2722
2762
  // src/systems/input/screenSystem.ts
2723
- var import_core33 = require("@woven-ecs/core");
2763
+ var import_core34 = require("@woven-ecs/core");
2724
2764
  var instanceState4 = /* @__PURE__ */ new WeakMap();
2725
2765
  function attachScreenObserver(domElement) {
2726
2766
  if (instanceState4.has(domElement)) return;
@@ -2745,8 +2785,9 @@ function detachScreenObserver(domElement) {
2745
2785
  instanceState4.delete(domElement);
2746
2786
  }
2747
2787
  var screenSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2748
- const resources = (0, import_core33.getResources)(ctx);
2788
+ const resources = (0, import_core34.getResources)(ctx);
2749
2789
  const { domElement } = resources;
2790
+ if (!domElement) return;
2750
2791
  const state = instanceState4.get(domElement);
2751
2792
  if (!state) return;
2752
2793
  const frame = Frame.read(ctx);
@@ -2764,8 +2805,8 @@ var screenSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
2764
2805
  });
2765
2806
 
2766
2807
  // src/systems/postRender/cursorSystem.ts
2767
- var import_core34 = require("@woven-ecs/core");
2768
- var cursorQuery = (0, import_core34.defineQuery)((q) => q.tracking(Cursor));
2808
+ var import_core35 = require("@woven-ecs/core");
2809
+ var cursorQuery = (0, import_core35.defineQuery)((q) => q.tracking(Cursor));
2769
2810
  function getCursorSvg(cursors, kind, rotateZ) {
2770
2811
  const def = cursors[kind];
2771
2812
  if (!def) return "auto";
@@ -2773,6 +2814,7 @@ function getCursorSvg(cursors, kind, rotateZ) {
2773
2814
  return `url("data:image/svg+xml,${encodeURIComponent(svg.trim())}") ${def.hotspot[0]} ${def.hotspot[1]}, auto`;
2774
2815
  }
2775
2816
  var cursorSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx) => {
2817
+ if (typeof document === "undefined") return;
2776
2818
  const changedCursors = cursorQuery.changed(ctx);
2777
2819
  const frame = Frame.read(ctx);
2778
2820
  if (changedCursors.length === 0 && frame.number !== 1) {
@@ -2783,18 +2825,18 @@ var cursorSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx)
2783
2825
  document.body.style.cursor = "default";
2784
2826
  return;
2785
2827
  }
2786
- const { editor } = (0, import_core34.getResources)(ctx);
2828
+ const { editor } = (0, import_core35.getResources)(ctx);
2787
2829
  const cursorValue = getCursorSvg(editor.cursors, cursorKind, rotation);
2788
2830
  document.body.style.cursor = cursorValue;
2789
2831
  });
2790
2832
 
2791
2833
  // src/systems/postRender/presenceSystem.ts
2792
- var import_core41 = require("@woven-ecs/core");
2834
+ var import_core42 = require("@woven-ecs/core");
2793
2835
 
2794
2836
  // src/helpers/blockDefs.ts
2795
- var import_core35 = require("@woven-ecs/core");
2837
+ var import_core36 = require("@woven-ecs/core");
2796
2838
  function getBlockDefs(ctx) {
2797
- const { editor } = (0, import_core35.getResources)(ctx);
2839
+ const { editor } = (0, import_core36.getResources)(ctx);
2798
2840
  return editor.blockDefs;
2799
2841
  }
2800
2842
  function getBlockDef(ctx, tag) {
@@ -2804,8 +2846,8 @@ function getBlockDef(ctx, tag) {
2804
2846
  function canBlockEdit(ctx, tag) {
2805
2847
  return getBlockDef(ctx, tag).editOptions.canEdit;
2806
2848
  }
2807
- function canBlockSelect(ctx, tag) {
2808
- return getBlockDef(ctx, tag).selectable;
2849
+ function canBlockInteract(ctx, tag) {
2850
+ return getBlockDef(ctx, tag).interactable;
2809
2851
  }
2810
2852
  function getBlockResizeMode(ctx, entityId) {
2811
2853
  const block = Block.read(ctx, entityId);
@@ -2818,9 +2860,9 @@ function getBlockResizeMode(ctx, entityId) {
2818
2860
 
2819
2861
  // src/helpers/computeAabb.ts
2820
2862
  var import_math4 = require("@woven-canvas/math");
2821
- var import_core36 = require("@woven-ecs/core");
2863
+ var import_core37 = require("@woven-ecs/core");
2822
2864
  function computeAabb(ctx, entityId, out) {
2823
- if ((0, import_core36.hasComponent)(ctx, entityId, HitGeometry)) {
2865
+ if ((0, import_core37.hasComponent)(ctx, entityId, HitGeometry)) {
2824
2866
  const pts = HitGeometry.getExtremaWorld(ctx, entityId);
2825
2867
  import_math4.Aabb.setFromPoints(out, pts);
2826
2868
  } else {
@@ -2829,19 +2871,149 @@ function computeAabb(ctx, entityId, out) {
2829
2871
  }
2830
2872
  }
2831
2873
 
2874
+ // src/helpers/embed.ts
2875
+ function detectEmbedProvider(url) {
2876
+ try {
2877
+ const parsed = new URL(url);
2878
+ const host = parsed.hostname.replace(/^www\./, "");
2879
+ if (host === "youtube.com" || host === "youtu.be") return "youtube" /* Youtube */;
2880
+ if (host === "open.spotify.com" || host === "spotify.com") return "spotify" /* Spotify */;
2881
+ if (host === "google.com" && parsed.pathname.startsWith("/maps")) return "google-maps" /* GoogleMaps */;
2882
+ if (host === "maps.google.com") return "google-maps" /* GoogleMaps */;
2883
+ if (host === "calendar.google.com") return "google-calendar" /* GoogleCalendar */;
2884
+ if (host === "docs.google.com" && parsed.pathname.includes("/presentation")) return "google-slides" /* GoogleSlides */;
2885
+ if (host === "figma.com" || host.endsWith(".figma.com")) return "figma" /* Figma */;
2886
+ if (host === "gist.github.com") return "github-gist" /* GithubGist */;
2887
+ if (host === "tldraw.com" || host.endsWith(".tldraw.com")) return "tldraw" /* Tldraw */;
2888
+ return "unknown" /* Unknown */;
2889
+ } catch {
2890
+ return "unknown" /* Unknown */;
2891
+ }
2892
+ }
2893
+ function validateEmbedUrl(url, provider) {
2894
+ try {
2895
+ const parsed = new URL(url);
2896
+ const host = parsed.hostname.replace(/^www\./, "");
2897
+ switch (provider) {
2898
+ case "youtube" /* Youtube */: {
2899
+ if (host === "youtu.be") return null;
2900
+ if (host !== "youtube.com") return "URL must be from youtube.com";
2901
+ if (parsed.pathname === "/watch" && parsed.searchParams.has("v")) return null;
2902
+ if (parsed.pathname.startsWith("/embed/")) return null;
2903
+ return "Paste a YouTube video link (e.g. youtube.com/watch?v=...)";
2904
+ }
2905
+ case "spotify" /* Spotify */: {
2906
+ if (host !== "open.spotify.com" && host !== "spotify.com") return "URL must be from open.spotify.com";
2907
+ if (parsed.pathname.length <= 1) return "Paste a Spotify track, album, or playlist link";
2908
+ return null;
2909
+ }
2910
+ case "google-maps" /* GoogleMaps */: {
2911
+ if (host !== "google.com" && host !== "maps.google.com") return "URL must be from google.com/maps";
2912
+ if (!parsed.pathname.startsWith("/maps") && host !== "maps.google.com") return "Paste a Google Maps link";
2913
+ return null;
2914
+ }
2915
+ case "google-calendar" /* GoogleCalendar */: {
2916
+ if (host !== "calendar.google.com") return "URL must be from calendar.google.com";
2917
+ return null;
2918
+ }
2919
+ case "google-slides" /* GoogleSlides */: {
2920
+ if (host !== "docs.google.com") return "URL must be from docs.google.com";
2921
+ if (!parsed.pathname.includes("/presentation/")) return "Paste a Google Slides presentation link";
2922
+ return null;
2923
+ }
2924
+ case "figma" /* Figma */: {
2925
+ if (host !== "figma.com" && !host.endsWith(".figma.com")) return "URL must be from figma.com";
2926
+ return null;
2927
+ }
2928
+ case "github-gist" /* GithubGist */: {
2929
+ if (host !== "gist.github.com") return "URL must be from gist.github.com";
2930
+ return null;
2931
+ }
2932
+ case "tldraw" /* Tldraw */: {
2933
+ if (host !== "tldraw.com" && !host.endsWith(".tldraw.com")) return "URL must be from tldraw.com";
2934
+ return null;
2935
+ }
2936
+ default:
2937
+ return null;
2938
+ }
2939
+ } catch {
2940
+ return "Please enter a valid URL";
2941
+ }
2942
+ }
2943
+ function resolveEmbedUrl(url, provider) {
2944
+ const p = provider ?? detectEmbedProvider(url);
2945
+ try {
2946
+ const parsed = new URL(url);
2947
+ switch (p) {
2948
+ case "youtube" /* Youtube */: {
2949
+ const host = parsed.hostname.replace(/^www\./, "");
2950
+ if (host === "youtu.be") {
2951
+ const videoId2 = parsed.pathname.slice(1);
2952
+ return `https://www.youtube.com/embed/${videoId2}`;
2953
+ }
2954
+ const videoId = parsed.searchParams.get("v");
2955
+ if (videoId && parsed.pathname === "/watch") {
2956
+ return `https://www.youtube.com/embed/${videoId}`;
2957
+ }
2958
+ return url;
2959
+ }
2960
+ case "spotify" /* Spotify */: {
2961
+ if (!parsed.pathname.startsWith("/embed/")) {
2962
+ return `https://open.spotify.com/embed${parsed.pathname}`;
2963
+ }
2964
+ return url;
2965
+ }
2966
+ case "google-maps" /* GoogleMaps */: {
2967
+ if (parsed.pathname.startsWith("/maps/embed")) return url;
2968
+ if (parsed.searchParams.get("output") === "embed") return url;
2969
+ const placeMatch = parsed.pathname.match(/\/maps\/place\/([^/]+)/);
2970
+ if (placeMatch) {
2971
+ return `https://www.google.com/maps?q=${encodeURIComponent(decodeURIComponent(placeMatch[1]))}&output=embed`;
2972
+ }
2973
+ const q = parsed.searchParams.get("q");
2974
+ if (q) {
2975
+ return `https://www.google.com/maps?q=${encodeURIComponent(q)}&output=embed`;
2976
+ }
2977
+ const atMatch = parsed.pathname.match(/\/@(-?[\d.]+),(-?[\d.]+),(\d+\.?\d*)z/);
2978
+ if (atMatch) {
2979
+ const [, lat, lng, zoom] = atMatch;
2980
+ return `https://www.google.com/maps?q=${lat},${lng}&z=${Math.round(parseFloat(zoom))}&output=embed`;
2981
+ }
2982
+ return `https://www.google.com/maps?q=${encodeURIComponent(url)}&output=embed`;
2983
+ }
2984
+ case "google-slides" /* GoogleSlides */: {
2985
+ return url.replace(/\/(edit|pub)(#.*)?(\?.*)?$/, "/embed");
2986
+ }
2987
+ case "figma" /* Figma */: {
2988
+ return `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(url)}`;
2989
+ }
2990
+ case "github-gist" /* GithubGist */: {
2991
+ if (!url.endsWith(".pibb")) {
2992
+ return `${url}.pibb`;
2993
+ }
2994
+ return url;
2995
+ }
2996
+ default:
2997
+ return url;
2998
+ }
2999
+ } catch {
3000
+ return url;
3001
+ }
3002
+ }
3003
+
2832
3004
  // src/helpers/held.ts
2833
- var import_core37 = require("@woven-ecs/core");
3005
+ var import_core38 = require("@woven-ecs/core");
2834
3006
  function isHeldByRemote(ctx, entityId) {
2835
- if (!(0, import_core37.hasComponent)(ctx, entityId, Held)) return false;
2836
- const { sessionId } = (0, import_core37.getResources)(ctx);
3007
+ if (!(0, import_core38.hasComponent)(ctx, entityId, Held)) return false;
3008
+ const { sessionId } = (0, import_core38.getResources)(ctx);
2837
3009
  const held = Held.read(ctx, entityId);
2838
3010
  return held.sessionId !== "" && held.sessionId !== sessionId;
2839
3011
  }
2840
3012
 
2841
3013
  // src/helpers/intersect.ts
2842
3014
  var import_math5 = require("@woven-canvas/math");
2843
- var import_core38 = require("@woven-ecs/core");
2844
- var blocksWithAabb = (0, import_core38.defineQuery)((q) => q.with(Block, Aabb));
3015
+ var import_core39 = require("@woven-ecs/core");
3016
+ var blocksWithAabb = (0, import_core39.defineQuery)((q) => q.with(Block, Aabb));
2845
3017
  function intersectPoint(ctx, point, entityIds) {
2846
3018
  const intersects = [];
2847
3019
  const entities = entityIds ?? blocksWithAabb.current(ctx);
@@ -2849,7 +3021,7 @@ function intersectPoint(ctx, point, entityIds) {
2849
3021
  if (!Aabb.containsPoint(ctx, entityId, point)) {
2850
3022
  continue;
2851
3023
  }
2852
- if ((0, import_core38.hasComponent)(ctx, entityId, HitGeometry)) {
3024
+ if ((0, import_core39.hasComponent)(ctx, entityId, HitGeometry)) {
2853
3025
  if (!HitGeometry.containsPointWorld(ctx, entityId, point)) {
2854
3026
  continue;
2855
3027
  }
@@ -2874,7 +3046,7 @@ function intersectAabb(ctx, bounds, entityIds) {
2874
3046
  intersecting.push(entityId);
2875
3047
  continue;
2876
3048
  }
2877
- if ((0, import_core38.hasComponent)(ctx, entityId, HitGeometry)) {
3049
+ if ((0, import_core39.hasComponent)(ctx, entityId, HitGeometry)) {
2878
3050
  if (HitGeometry.intersectsAabbWorld(ctx, entityId, bounds)) {
2879
3051
  intersecting.push(entityId);
2880
3052
  }
@@ -2914,7 +3086,7 @@ function getTopmostBlockAtPoint(ctx, point) {
2914
3086
 
2915
3087
  // src/helpers/intersectCapsule.ts
2916
3088
  var import_math6 = require("@woven-canvas/math");
2917
- var import_core39 = require("@woven-ecs/core");
3089
+ var import_core40 = require("@woven-ecs/core");
2918
3090
  var _uvToWorldMatrix2 = [1, 0, 0, 1, 0, 0];
2919
3091
  function intersectCapsule(ctx, capsule, entityIds) {
2920
3092
  const intersects = [];
@@ -2924,7 +3096,7 @@ function intersectCapsule(ctx, capsule, entityIds) {
2924
3096
  if (!import_math6.Aabb.intersects(capsuleBounds, aabb.value)) {
2925
3097
  continue;
2926
3098
  }
2927
- if ((0, import_core39.hasComponent)(ctx, entityId, HitGeometry)) {
3099
+ if ((0, import_core40.hasComponent)(ctx, entityId, HitGeometry)) {
2928
3100
  if (intersectsCapsuleHitGeometry(ctx, entityId, capsule)) {
2929
3101
  intersects.push(entityId);
2930
3102
  }
@@ -2971,10 +3143,10 @@ function intersectsCapsuleHitGeometry(ctx, entityId, capsule) {
2971
3143
  }
2972
3144
 
2973
3145
  // src/helpers/user.ts
2974
- var import_core40 = require("@woven-ecs/core");
2975
- var userQuery = (0, import_core40.defineQuery)((q) => q.with(User));
3146
+ var import_core41 = require("@woven-ecs/core");
3147
+ var userQuery = (0, import_core41.defineQuery)((q) => q.with(User));
2976
3148
  function getMyUserEntityId(ctx) {
2977
- const mySessionId = (0, import_core40.getResources)(ctx).sessionId;
3149
+ const mySessionId = (0, import_core41.getResources)(ctx).sessionId;
2978
3150
  for (const eid of userQuery.current(ctx)) {
2979
3151
  const user = User.read(ctx, eid);
2980
3152
  if (user.sessionId === mySessionId) {
@@ -2985,7 +3157,7 @@ function getMyUserEntityId(ctx) {
2985
3157
  }
2986
3158
 
2987
3159
  // src/systems/postRender/presenceSystem.ts
2988
- var pointerQuery = (0, import_core41.defineQuery)((q) => q.tracking(Pointer));
3160
+ var pointerQuery = (0, import_core42.defineQuery)((q) => q.tracking(Pointer));
2989
3161
  var presenceSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx) => {
2990
3162
  if (Mouse.didMove(ctx)) {
2991
3163
  const mouse = Mouse.read(ctx);
@@ -3015,16 +3187,16 @@ function updateUserPosition(ctx, position) {
3015
3187
  }
3016
3188
 
3017
3189
  // src/systems/preCapture/intersectSystem.ts
3018
- var import_core42 = require("@woven-ecs/core");
3019
- var blocksChanged = (0, import_core42.defineQuery)((q) => q.tracking(Block));
3020
- var hitGeometryChanged = (0, import_core42.defineQuery)((q) => q.tracking(HitGeometry));
3021
- var heldQuery = (0, import_core42.defineQuery)((q) => q.with(Held).tracking(Held));
3022
- var hoveredQuery = (0, import_core42.defineQuery)((q) => q.with(Hovered));
3023
- var pointerQuery2 = (0, import_core42.defineQuery)((q) => q.with(Pointer));
3190
+ var import_core43 = require("@woven-ecs/core");
3191
+ var blocksChanged = (0, import_core43.defineQuery)((q) => q.tracking(Block));
3192
+ var hitGeometryChanged = (0, import_core43.defineQuery)((q) => q.tracking(HitGeometry));
3193
+ var heldQuery = (0, import_core43.defineQuery)((q) => q.with(Held).tracking(Held));
3194
+ var hoveredQuery = (0, import_core43.defineQuery)((q) => q.with(Hovered));
3195
+ var pointerQuery2 = (0, import_core43.defineQuery)((q) => q.with(Pointer));
3024
3196
  function clearHovered(ctx) {
3025
3197
  for (const entityId of hoveredQuery.current(ctx)) {
3026
- if ((0, import_core42.hasComponent)(ctx, entityId, Hovered)) {
3027
- (0, import_core42.removeComponent)(ctx, entityId, Hovered);
3198
+ if ((0, import_core43.hasComponent)(ctx, entityId, Hovered)) {
3199
+ (0, import_core43.removeComponent)(ctx, entityId, Hovered);
3028
3200
  }
3029
3201
  }
3030
3202
  }
@@ -3042,7 +3214,7 @@ function updateHovered(ctx, intersected) {
3042
3214
  if (!selectToolActive) return;
3043
3215
  const newHoveredId = findValidHoverTarget(ctx, intersected);
3044
3216
  if (newHoveredId !== void 0) {
3045
- (0, import_core42.addComponent)(ctx, newHoveredId, Hovered, {});
3217
+ (0, import_core43.addComponent)(ctx, newHoveredId, Hovered, {});
3046
3218
  }
3047
3219
  }
3048
3220
  function arraysEqual(a, b) {
@@ -3071,13 +3243,18 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
3071
3243
  changed.add(entityId);
3072
3244
  }
3073
3245
  for (const entityId of added) {
3074
- if (!(0, import_core42.hasComponent)(ctx, entityId, Aabb)) {
3075
- (0, import_core42.addComponent)(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
3246
+ if ((0, import_core43.hasComponent)(ctx, entityId, Block)) {
3247
+ const block = Block.read(ctx, entityId);
3248
+ if (!canBlockInteract(ctx, block.tag)) continue;
3249
+ }
3250
+ if (!(0, import_core43.hasComponent)(ctx, entityId, Aabb)) {
3251
+ (0, import_core43.addComponent)(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
3076
3252
  }
3077
3253
  const aabb = Aabb.write(ctx, entityId);
3078
3254
  computeAabb(ctx, entityId, aabb.value);
3079
3255
  }
3080
3256
  for (const entityId of changed) {
3257
+ if (!(0, import_core43.hasComponent)(ctx, entityId, Aabb)) continue;
3081
3258
  const aabb = Aabb.write(ctx, entityId);
3082
3259
  computeAabb(ctx, entityId, aabb.value);
3083
3260
  }
@@ -3096,11 +3273,13 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
3096
3273
  clearHovered(ctx);
3097
3274
  return;
3098
3275
  }
3099
- const resources = (0, import_core42.getResources)(ctx);
3276
+ const resources = (0, import_core43.getResources)(ctx);
3100
3277
  const isObscured = Mouse.isObscured(ctx);
3101
- const wasObscured = prevObscuredByElement.get(resources.domElement) ?? false;
3278
+ const wasObscured = resources.domElement ? prevObscuredByElement.get(resources.domElement) ?? false : false;
3102
3279
  const obscuredChanged = isObscured !== wasObscured;
3103
- prevObscuredByElement.set(resources.domElement, isObscured);
3280
+ if (resources.domElement) {
3281
+ prevObscuredByElement.set(resources.domElement, isObscured);
3282
+ }
3104
3283
  if (isObscured) {
3105
3284
  clearHovered(ctx);
3106
3285
  return;
@@ -3123,9 +3302,9 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
3123
3302
  });
3124
3303
 
3125
3304
  // src/systems/preInput/rankBoundsSystem.ts
3126
- var import_canvas_store29 = require("@woven-ecs/canvas-store");
3127
- var import_core43 = require("@woven-ecs/core");
3128
- var blocksQuery = (0, import_core43.defineQuery)((q) => q.with(import_canvas_store29.Synced, Block));
3305
+ var import_canvas_store30 = require("@woven-ecs/canvas-store");
3306
+ var import_core44 = require("@woven-ecs/core");
3307
+ var blocksQuery = (0, import_core44.defineQuery)((q) => q.with(import_canvas_store30.Synced, Block));
3129
3308
  var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ctx) => {
3130
3309
  const added2 = blocksQuery.added(ctx);
3131
3310
  for (const entityId of added2) {
@@ -3141,11 +3320,11 @@ var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ct
3141
3320
 
3142
3321
  // src/systems/preRender/canSeeBlocksSystem.ts
3143
3322
  var import_math7 = require("@woven-canvas/math");
3144
- var import_canvas_store30 = require("@woven-ecs/canvas-store");
3145
- var import_core44 = require("@woven-ecs/core");
3146
- var camerasQuery = (0, import_core44.defineQuery)((q) => q.tracking(Camera));
3147
- var blocksQuery2 = (0, import_core44.defineQuery)((q) => q.with(import_canvas_store30.Synced, Block, Aabb));
3148
- var syncedBlocksQuery = (0, import_core44.defineQuery)((q) => q.with(import_canvas_store30.Synced, Block, Aabb));
3323
+ var import_canvas_store31 = require("@woven-ecs/canvas-store");
3324
+ var import_core45 = require("@woven-ecs/core");
3325
+ var camerasQuery = (0, import_core45.defineQuery)((q) => q.tracking(Camera));
3326
+ var blocksQuery2 = (0, import_core45.defineQuery)((q) => q.with(import_canvas_store31.Synced, Block, Aabb));
3327
+ var syncedBlocksQuery = (0, import_core45.defineQuery)((q) => q.with(import_canvas_store31.Synced, Block, Aabb));
3149
3328
  var _cameraAabb = [0, 0, 0, 0];
3150
3329
  var canSeeBlocksSystem = defineEditorSystem({ phase: "render", priority: 90 }, (ctx) => {
3151
3330
  if (camerasQuery.changed(ctx).length === 0 && syncedBlocksQuery.addedOrRemoved(ctx).length === 0) {
@@ -3154,7 +3333,7 @@ var canSeeBlocksSystem = defineEditorSystem({ phase: "render", priority: 90 }, (
3154
3333
  const camera = Camera.read(ctx);
3155
3334
  const cameraAabb = Camera.getAabb(ctx, _cameraAabb);
3156
3335
  if (camera.canSeeBlocks && camera.lastSeenBlock !== null) {
3157
- if ((0, import_core44.hasComponent)(ctx, camera.lastSeenBlock, Aabb)) {
3336
+ if ((0, import_core45.hasComponent)(ctx, camera.lastSeenBlock, Aabb)) {
3158
3337
  const aabb = Aabb.read(ctx, camera.lastSeenBlock);
3159
3338
  if (import_math7.Aabb.intersects(cameraAabb, aabb.value)) {
3160
3339
  return;
@@ -3183,10 +3362,11 @@ var canSeeBlocksSystem = defineEditorSystem({ phase: "render", priority: 90 }, (
3183
3362
 
3184
3363
  // src/systems/preRender/scaleWithZoomSystem.ts
3185
3364
  var import_math8 = require("@woven-canvas/math");
3186
- var import_core45 = require("@woven-ecs/core");
3187
- var scaleWithZoomQuery = (0, import_core45.defineQuery)((q) => q.with(Block).tracking(ScaleWithZoom));
3365
+ var import_core46 = require("@woven-ecs/core");
3366
+ var scaleWithZoomQuery = (0, import_core46.defineQuery)((q) => q.with(Block).tracking(ScaleWithZoom));
3188
3367
  var _scaledSize = [0, 0];
3189
3368
  var _anchorOffset = [0, 0];
3369
+ var _anchorAdj = [0, 0];
3190
3370
  var scaleWithZoomSystem = defineEditorSystem({ phase: "render", priority: 100 }, (ctx) => {
3191
3371
  const camera = Camera.read(ctx);
3192
3372
  const state = ScaleWithZoomState.read(ctx);
@@ -3211,7 +3391,15 @@ function scaleBlock(ctx, entityId, zoom) {
3211
3391
  _scaledSize[1] = swz.startSize[1] * scaleY;
3212
3392
  import_math8.Vec2.copy(_anchorOffset, swz.startSize);
3213
3393
  import_math8.Vec2.sub(_anchorOffset, _scaledSize);
3214
- import_math8.Vec2.multiply(_anchorOffset, swz.anchor);
3394
+ if (block.rotateZ !== 0) {
3395
+ _anchorAdj[0] = _anchorOffset[0] * (swz.anchor[0] - 0.5);
3396
+ _anchorAdj[1] = _anchorOffset[1] * (swz.anchor[1] - 0.5);
3397
+ import_math8.Vec2.rotate(_anchorAdj, block.rotateZ);
3398
+ _anchorOffset[0] = _anchorOffset[0] * 0.5 + _anchorAdj[0];
3399
+ _anchorOffset[1] = _anchorOffset[1] * 0.5 + _anchorAdj[1];
3400
+ } else {
3401
+ import_math8.Vec2.multiply(_anchorOffset, swz.anchor);
3402
+ }
3215
3403
  import_math8.Vec2.copy(block.position, swz.startPosition);
3216
3404
  import_math8.Vec2.add(block.position, _anchorOffset);
3217
3405
  import_math8.Vec2.copy(block.size, _scaledSize);
@@ -3220,8 +3408,8 @@ function scaleBlock(ctx, entityId, zoom) {
3220
3408
  // src/CorePlugin.ts
3221
3409
  var CorePlugin = {
3222
3410
  name: CORE_PLUGIN_NAME,
3223
- singletons: Object.values(singletons_exports).filter((v) => v instanceof import_canvas_store31.CanvasSingletonDef),
3224
- components: Object.values(components_exports).filter((v) => v instanceof import_canvas_store31.CanvasComponentDef),
3411
+ singletons: Object.values(singletons_exports).filter((v) => v instanceof import_canvas_store32.CanvasSingletonDef),
3412
+ components: Object.values(components_exports).filter((v) => v instanceof import_canvas_store32.CanvasComponentDef),
3225
3413
  blockDefs: [
3226
3414
  {
3227
3415
  tag: "sticky-note",
@@ -3251,6 +3439,14 @@ var CorePlugin = {
3251
3439
  editOptions: {
3252
3440
  canEdit: true
3253
3441
  }
3442
+ },
3443
+ {
3444
+ tag: "embed",
3445
+ components: [Embed],
3446
+ resizeMode: ResizeMode.Free,
3447
+ editOptions: {
3448
+ canEdit: true
3449
+ }
3254
3450
  }
3255
3451
  ],
3256
3452
  systems: [
@@ -3278,14 +3474,16 @@ var CorePlugin = {
3278
3474
  // priority: -100
3279
3475
  ],
3280
3476
  setup(ctx) {
3281
- const { domElement } = (0, import_core46.getResources)(ctx);
3477
+ const { domElement } = (0, import_core47.getResources)(ctx);
3478
+ if (!domElement) return;
3282
3479
  attachKeyboardListeners(domElement);
3283
3480
  attachMouseListeners(domElement);
3284
3481
  attachScreenObserver(domElement);
3285
3482
  attachPointerListeners(domElement);
3286
3483
  },
3287
3484
  teardown(ctx) {
3288
- const { domElement } = (0, import_core46.getResources)(ctx);
3485
+ const { domElement } = (0, import_core47.getResources)(ctx);
3486
+ if (!domElement) return;
3289
3487
  detachKeyboardListeners(domElement);
3290
3488
  detachMouseListeners(domElement);
3291
3489
  detachScreenObserver(domElement);
@@ -3294,8 +3492,8 @@ var CorePlugin = {
3294
3492
  };
3295
3493
 
3296
3494
  // src/Editor.ts
3297
- var import_canvas_store32 = require("@woven-ecs/canvas-store");
3298
- var import_core47 = require("@woven-ecs/core");
3495
+ var import_canvas_store33 = require("@woven-ecs/canvas-store");
3496
+ var import_core48 = require("@woven-ecs/core");
3299
3497
 
3300
3498
  // src/FontLoader.ts
3301
3499
  var import_zod2 = require("zod");
@@ -3382,6 +3580,9 @@ var FontLoader = class {
3382
3580
  */
3383
3581
  loadSingleFont(family) {
3384
3582
  this.loadedFonts.add(family.name);
3583
+ if (typeof document === "undefined") {
3584
+ return Promise.resolve();
3585
+ }
3385
3586
  return new Promise((resolve, reject) => {
3386
3587
  const link = document.createElement("link");
3387
3588
  link.rel = "stylesheet";
@@ -3512,7 +3713,7 @@ var Editor = class {
3512
3713
  this.controlsOptions = ControlsOptions.parse(options.controls ?? {});
3513
3714
  const plugins = pluginInputs.map(parsePlugin);
3514
3715
  const sortedPlugins = sortPluginsByDependencies([CorePlugin, ...plugins]);
3515
- const allDefs = [CommandMarker, import_canvas_store32.Synced];
3716
+ const allDefs = [CommandMarker, import_canvas_store33.Synced];
3516
3717
  for (const plugin of sortedPlugins) {
3517
3718
  if (plugin.components) {
3518
3719
  allDefs.push(...plugin.components);
@@ -3587,7 +3788,7 @@ var Editor = class {
3587
3788
  componentsById,
3588
3789
  singletonsById
3589
3790
  };
3590
- this.world = new import_core47.World(allDefs, {
3791
+ this.world = new import_core48.World(allDefs, {
3591
3792
  maxEntities,
3592
3793
  resources: allResources
3593
3794
  });
@@ -3647,11 +3848,11 @@ var Editor = class {
3647
3848
  Grid.copy(this.ctx, this.gridOptions);
3648
3849
  Controls.copy(this.ctx, this.controlsOptions);
3649
3850
  this.nextTick((ctx) => {
3650
- const userEntity = (0, import_core47.createEntity)(ctx);
3651
- (0, import_core47.addComponent)(ctx, userEntity, import_canvas_store32.Synced, {
3851
+ const userEntity = (0, import_core48.createEntity)(ctx);
3852
+ (0, import_core48.addComponent)(ctx, userEntity, import_canvas_store33.Synced, {
3652
3853
  id: crypto.randomUUID()
3653
3854
  });
3654
- (0, import_core47.addComponent)(ctx, userEntity, User, {
3855
+ (0, import_core48.addComponent)(ctx, userEntity, User, {
3655
3856
  userId: this.userData.userId,
3656
3857
  sessionId: this.userData.sessionId,
3657
3858
  color: this.userData.color,
@@ -3760,11 +3961,54 @@ var Editor = class {
3760
3961
  _getContext() {
3761
3962
  return this.ctx;
3762
3963
  }
3964
+ /**
3965
+ * Attach a DOM element to a headless editor.
3966
+ * Use this after SSR to connect input listeners and enable rendering.
3967
+ *
3968
+ * @param domElement - The DOM element to attach to
3969
+ *
3970
+ * @example
3971
+ * ```typescript
3972
+ * // SSR: create headless editor
3973
+ * const editor = new Editor(null, { plugins: [...] });
3974
+ * await editor.initialize();
3975
+ * editor.tick(); // process initial state
3976
+ *
3977
+ * // Client hydration: attach the DOM
3978
+ * editor.attachDom(document.getElementById('canvas')!);
3979
+ * ```
3980
+ */
3981
+ attachDom(domElement) {
3982
+ const resources = this.ctx.resources;
3983
+ if (resources.domElement) {
3984
+ throw new Error("Editor already has a DOM element attached. Call detachDom() first.");
3985
+ }
3986
+ resources.domElement = domElement;
3987
+ attachKeyboardListeners(domElement);
3988
+ attachMouseListeners(domElement);
3989
+ attachScreenObserver(domElement);
3990
+ attachPointerListeners(domElement);
3991
+ }
3992
+ /**
3993
+ * Detach the current DOM element.
3994
+ * Removes all input listeners. The editor continues to run headless.
3995
+ */
3996
+ detachDom() {
3997
+ const resources = this.ctx.resources;
3998
+ const { domElement } = resources;
3999
+ if (!domElement) return;
4000
+ detachKeyboardListeners(domElement);
4001
+ detachMouseListeners(domElement);
4002
+ detachScreenObserver(domElement);
4003
+ detachPointerListeners(domElement);
4004
+ resources.domElement = null;
4005
+ }
3763
4006
  /**
3764
4007
  * Clean up the editor.
3765
4008
  * Call this when done to release resources.
3766
4009
  */
3767
4010
  dispose() {
4011
+ this.detachDom();
3768
4012
  const plugins = Array.from(this.plugins.values()).reverse();
3769
4013
  for (const plugin of plugins) {
3770
4014
  if (plugin.teardown) {
@@ -3778,7 +4022,7 @@ var Editor = class {
3778
4022
  };
3779
4023
 
3780
4024
  // src/EditorStateDef.ts
3781
- var import_canvas_store33 = require("@woven-ecs/canvas-store");
4025
+ var import_canvas_store34 = require("@woven-ecs/canvas-store");
3782
4026
 
3783
4027
  // src/machine.ts
3784
4028
  var import_xstate = require("xstate");
@@ -3806,7 +4050,7 @@ function runMachine(machine, currentState, context, events) {
3806
4050
  }
3807
4051
 
3808
4052
  // src/EditorStateDef.ts
3809
- var EditorStateDef = class extends import_canvas_store33.CanvasSingletonDef {
4053
+ var EditorStateDef = class extends import_canvas_store34.CanvasSingletonDef {
3810
4054
  constructor(name, schema) {
3811
4055
  super({ name, sync: "none" }, schema);
3812
4056
  }
@@ -3937,10 +4181,10 @@ function getMouseInput(ctx) {
3937
4181
 
3938
4182
  // src/events/pointerInputEvents.ts
3939
4183
  var import_math9 = require("@woven-canvas/math");
3940
- var import_core48 = require("@woven-ecs/core");
4184
+ var import_core49 = require("@woven-ecs/core");
3941
4185
  var DEFAULT_CLICK_MOVE_THRESHOLD = 3;
3942
4186
  var DEFAULT_CLICK_FRAME_THRESHOLD = 30;
3943
- var pointerQuery3 = (0, import_core48.defineQuery)((q) => q.tracking(Pointer));
4187
+ var pointerQuery3 = (0, import_core49.defineQuery)((q) => q.tracking(Pointer));
3944
4188
  var trackingState = /* @__PURE__ */ new Map();
3945
4189
  function getTrackingState(ctx) {
3946
4190
  const key = ctx.readerId;
@@ -4082,6 +4326,8 @@ function clearPointerTrackingState(ctx) {
4082
4326
  Edited,
4083
4327
  Editor,
4084
4328
  EditorStateDef,
4329
+ Embed,
4330
+ EmbedProvider,
4085
4331
  EventType,
4086
4332
  FontFamily,
4087
4333
  FontLoader,
@@ -4127,7 +4373,7 @@ function clearPointerTrackingState(ctx) {
4127
4373
  VerticalAlignment,
4128
4374
  addComponent,
4129
4375
  canBlockEdit,
4130
- canBlockSelect,
4376
+ canBlockInteract,
4131
4377
  clearPointerTrackingState,
4132
4378
  createEntity,
4133
4379
  defineCanvasComponent,
@@ -4137,6 +4383,7 @@ function clearPointerTrackingState(ctx) {
4137
4383
  defineEditorSystem,
4138
4384
  defineQuery,
4139
4385
  defineSystem,
4386
+ detectEmbedProvider,
4140
4387
  field,
4141
4388
  getBackrefs,
4142
4389
  getBlockDef,
@@ -4158,6 +4405,8 @@ function clearPointerTrackingState(ctx) {
4158
4405
  parsePlugin,
4159
4406
  removeComponent,
4160
4407
  removeEntity,
4161
- runMachine
4408
+ resolveEmbedUrl,
4409
+ runMachine,
4410
+ validateEmbedUrl
4162
4411
  });
4163
4412
  //# sourceMappingURL=index.cjs.map