@woven-canvas/core 1.0.5 → 1.0.6

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.
@@ -170,6 +170,7 @@ declare const BlockDef: z.ZodObject<{
170
170
  canRotate: z.ZodDefault<z.ZodBoolean>;
171
171
  canScale: z.ZodDefault<z.ZodBoolean>;
172
172
  interactable: z.ZodDefault<z.ZodBoolean>;
173
+ excludeFromRankBounds: z.ZodDefault<z.ZodBoolean>;
173
174
  connectors: z.ZodDefault<z.ZodObject<{
174
175
  enabled: z.ZodDefault<z.ZodBoolean>;
175
176
  terminals: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>;
@@ -382,7 +383,6 @@ export { Connector as Connector_alias_1 }
382
383
  export { Connector as Connector_alias_2 }
383
384
 
384
385
  export { Context }
385
- export { Context as Context_alias_1 }
386
386
 
387
387
  declare const Controls: ControlsDef;
388
388
  export { Controls }
@@ -635,6 +635,7 @@ declare class Editor {
635
635
  tick(): Promise<void>;
636
636
  nextTick(callback: (ctx: Context) => void): () => void;
637
637
  command<T>(def: CommandDef<T>, ...args: T extends void ? [] : [T]): void;
638
+ get readonly(): boolean;
638
639
  subscribe(query: QueryDef, callback: QueryCallback): () => void;
639
640
  _getContext(): Context;
640
641
  attachDom(domElement: HTMLElement): void;
@@ -708,6 +709,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
708
709
  canRotate?: boolean | undefined;
709
710
  canScale?: boolean | undefined;
710
711
  interactable?: boolean | undefined;
712
+ excludeFromRankBounds?: boolean | undefined;
711
713
  connectors?: {
712
714
  enabled?: boolean | undefined;
713
715
  terminals?: [number, number][] | undefined;
@@ -724,6 +726,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
724
726
  canRotate?: boolean | undefined;
725
727
  canScale?: boolean | undefined;
726
728
  interactable?: boolean | undefined;
729
+ excludeFromRankBounds?: boolean | undefined;
727
730
  connectors?: {
728
731
  enabled?: boolean | undefined;
729
732
  terminals?: [number, number][] | undefined;
@@ -785,6 +788,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
785
788
  wheelTool?: string | undefined;
786
789
  modWheelTool?: string | undefined;
787
790
  }>>;
791
+ readonly: z.ZodDefault<z.ZodBoolean>;
788
792
  }, z.core.$strip>;
789
793
 
790
794
  declare interface EditorPlugin<TResources = unknown> {
@@ -822,6 +826,7 @@ declare interface EditorResources {
822
826
  singletonsByName: Map<string, AnyCanvasSingletonDef>;
823
827
  componentsById: Map<number, AnyCanvasComponentDef>;
824
828
  singletonsById: Map<number, AnyCanvasSingletonDef>;
829
+ readonly: boolean;
825
830
  }
826
831
  export { EditorResources }
827
832
  export { EditorResources as EditorResources_alias_1 }
@@ -1223,6 +1228,10 @@ export { isHeldByRemote }
1223
1228
  export { isHeldByRemote as isHeldByRemote_alias_1 }
1224
1229
  export { isHeldByRemote as isHeldByRemote_alias_2 }
1225
1230
 
1231
+ declare function isReadonly(ctx: Context): boolean;
1232
+ export { isReadonly }
1233
+ export { isReadonly as isReadonly_alias_1 }
1234
+
1226
1235
  declare const Key: {
1227
1236
  readonly A: number;
1228
1237
  readonly B: number;
@@ -170,6 +170,7 @@ declare const BlockDef: z.ZodObject<{
170
170
  canRotate: z.ZodDefault<z.ZodBoolean>;
171
171
  canScale: z.ZodDefault<z.ZodBoolean>;
172
172
  interactable: z.ZodDefault<z.ZodBoolean>;
173
+ excludeFromRankBounds: z.ZodDefault<z.ZodBoolean>;
173
174
  connectors: z.ZodDefault<z.ZodObject<{
174
175
  enabled: z.ZodDefault<z.ZodBoolean>;
175
176
  terminals: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>>;
@@ -382,7 +383,6 @@ export { Connector as Connector_alias_1 }
382
383
  export { Connector as Connector_alias_2 }
383
384
 
384
385
  export { Context }
385
- export { Context as Context_alias_1 }
386
386
 
387
387
  declare const Controls: ControlsDef;
388
388
  export { Controls }
@@ -635,6 +635,7 @@ declare class Editor {
635
635
  tick(): Promise<void>;
636
636
  nextTick(callback: (ctx: Context) => void): () => void;
637
637
  command<T>(def: CommandDef<T>, ...args: T extends void ? [] : [T]): void;
638
+ get readonly(): boolean;
638
639
  subscribe(query: QueryDef, callback: QueryCallback): () => void;
639
640
  _getContext(): Context;
640
641
  attachDom(domElement: HTMLElement): void;
@@ -708,6 +709,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
708
709
  canRotate?: boolean | undefined;
709
710
  canScale?: boolean | undefined;
710
711
  interactable?: boolean | undefined;
712
+ excludeFromRankBounds?: boolean | undefined;
711
713
  connectors?: {
712
714
  enabled?: boolean | undefined;
713
715
  terminals?: [number, number][] | undefined;
@@ -724,6 +726,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
724
726
  canRotate?: boolean | undefined;
725
727
  canScale?: boolean | undefined;
726
728
  interactable?: boolean | undefined;
729
+ excludeFromRankBounds?: boolean | undefined;
727
730
  connectors?: {
728
731
  enabled?: boolean | undefined;
729
732
  terminals?: [number, number][] | undefined;
@@ -785,6 +788,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
785
788
  wheelTool?: string | undefined;
786
789
  modWheelTool?: string | undefined;
787
790
  }>>;
791
+ readonly: z.ZodDefault<z.ZodBoolean>;
788
792
  }, z.core.$strip>;
789
793
 
790
794
  declare interface EditorPlugin<TResources = unknown> {
@@ -822,6 +826,7 @@ declare interface EditorResources {
822
826
  singletonsByName: Map<string, AnyCanvasSingletonDef>;
823
827
  componentsById: Map<number, AnyCanvasComponentDef>;
824
828
  singletonsById: Map<number, AnyCanvasSingletonDef>;
829
+ readonly: boolean;
825
830
  }
826
831
  export { EditorResources }
827
832
  export { EditorResources as EditorResources_alias_1 }
@@ -1223,6 +1228,10 @@ export { isHeldByRemote }
1223
1228
  export { isHeldByRemote as isHeldByRemote_alias_1 }
1224
1229
  export { isHeldByRemote as isHeldByRemote_alias_2 }
1225
1230
 
1231
+ declare function isReadonly(ctx: Context): boolean;
1232
+ export { isReadonly }
1233
+ export { isReadonly as isReadonly_alias_1 }
1234
+
1226
1235
  declare const Key: {
1227
1236
  readonly A: number;
1228
1237
  readonly B: number;
package/build/index.cjs CHANGED
@@ -176,6 +176,7 @@ __export(index_exports, {
176
176
  isAlive: () => import_core71.isAlive,
177
177
  isAncestor: () => isAncestor,
178
178
  isHeldByRemote: () => isHeldByRemote,
179
+ isReadonly: () => isReadonly,
179
180
  on: () => on,
180
181
  parsePlugin: () => parsePlugin,
181
182
  removeComponent: () => import_core71.removeComponent,
@@ -382,6 +383,9 @@ function getPluginResources(ctx, pluginName) {
382
383
  const resources = ctx.resources;
383
384
  return resources.pluginResources[pluginName];
384
385
  }
386
+ function isReadonly(ctx) {
387
+ return ctx.resources.readonly;
388
+ }
385
389
  var GridOptions = import_zod.z.object({
386
390
  /**
387
391
  * Whether grid snapping is enabled.
@@ -543,7 +547,16 @@ var EditorOptionsSchema = import_zod.z.object({
543
547
  * }
544
548
  * ```
545
549
  */
546
- controls: import_zod.z.custom().optional()
550
+ controls: import_zod.z.custom().optional(),
551
+ /**
552
+ * When true, user-initiated mutations are blocked — input systems skip
553
+ * their bodies and `editor.command()` is a no-op. Adapter-originated
554
+ * mutations (websocket, persistence) still apply, so remote edits remain
555
+ * visible. Useful for viewer-mode share links.
556
+ *
557
+ * @default false
558
+ */
559
+ readonly: import_zod.z.boolean().default(false)
547
560
  });
548
561
  var Keybind = import_zod.z.object({
549
562
  /** The command to execute when this keybind is triggered */
@@ -612,6 +625,7 @@ var BlockDef = import_zod.z.object({
612
625
  canRotate: import_zod.z.boolean().default(true),
613
626
  canScale: import_zod.z.boolean().default(true),
614
627
  interactable: import_zod.z.boolean().default(true),
628
+ excludeFromRankBounds: import_zod.z.boolean().default(false),
615
629
  connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
616
630
  });
617
631
  var SelectionState = {
@@ -3296,6 +3310,8 @@ function intersectPoint(ctx, point, entityIds) {
3296
3310
  const intersects = [];
3297
3311
  const entities = entityIds ?? blocksWithAabb.current(ctx);
3298
3312
  for (const entityId of entities) {
3313
+ const block = Block.read(ctx, entityId);
3314
+ if (!canBlockInteract(ctx, block.tag)) continue;
3299
3315
  if (!Aabb.containsPoint(ctx, entityId, point)) {
3300
3316
  continue;
3301
3317
  }
@@ -3319,6 +3335,8 @@ function intersectAabb(ctx, bounds, entityIds) {
3319
3335
  const intersecting = [];
3320
3336
  const entities = entityIds ?? blocksWithAabb.current(ctx);
3321
3337
  for (const entityId of entities) {
3338
+ const block = Block.read(ctx, entityId);
3339
+ if (!canBlockInteract(ctx, block.tag)) continue;
3322
3340
  const { value: entityAabb } = Aabb.read(ctx, entityId);
3323
3341
  if (!import_math5.Aabb.intersects(bounds, entityAabb)) {
3324
3342
  continue;
@@ -3842,6 +3860,7 @@ var hoverCursorSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
3842
3860
  // src/systems/capture/keybindSystem.ts
3843
3861
  var import_core50 = require("@woven-ecs/core");
3844
3862
  var keybindSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
3863
+ if (isReadonly(ctx)) return;
3845
3864
  const keyboard = Keyboard.read(ctx);
3846
3865
  const { editor } = (0, import_core50.getResources)(ctx);
3847
3866
  for (const keybind of editor.keybinds) {
@@ -4592,8 +4611,9 @@ var cursorSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx)
4592
4611
  // src/systems/postRender/presenceSystem.ts
4593
4612
  var import_core57 = require("@woven-ecs/core");
4594
4613
  var pointerQuery2 = (0, import_core57.defineQuery)((q) => q.tracking(Pointer));
4614
+ var cameraChangedQuery = (0, import_core57.defineQuery)((q) => q.tracking(Camera));
4595
4615
  var presenceSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx) => {
4596
- if (Mouse.didMove(ctx)) {
4616
+ if (Mouse.didMove(ctx) || cameraChangedQuery.changed(ctx).length > 0) {
4597
4617
  const mouse = Mouse.read(ctx);
4598
4618
  updateUserPosition(ctx, mouse.position);
4599
4619
  return;
@@ -5097,6 +5117,10 @@ function clearHovered(ctx) {
5097
5117
  function findValidHoverTarget(ctx, intersected) {
5098
5118
  for (const entityId of intersected) {
5099
5119
  if (isHeldByRemote(ctx, entityId)) return void 0;
5120
+ if ((0, import_core59.hasComponent)(ctx, entityId, Block)) {
5121
+ const block = Block.read(ctx, entityId);
5122
+ if (!canBlockInteract(ctx, block.tag)) continue;
5123
+ }
5100
5124
  return entityId;
5101
5125
  }
5102
5126
  return void 0;
@@ -5147,10 +5171,6 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
5147
5171
  addDescendants(ctx, entityId, changed);
5148
5172
  }
5149
5173
  for (const entityId of added) {
5150
- if ((0, import_core59.hasComponent)(ctx, entityId, Block)) {
5151
- const block = Block.read(ctx, entityId);
5152
- if (!canBlockInteract(ctx, block.tag)) continue;
5153
- }
5154
5174
  if (!(0, import_core59.hasComponent)(ctx, entityId, Aabb)) {
5155
5175
  (0, import_core59.addComponent)(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
5156
5176
  }
@@ -5534,6 +5554,7 @@ var selectionMachine = (0, import_xstate5.setup)({
5534
5554
  }
5535
5555
  });
5536
5556
  var selectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (ctx) => {
5557
+ if (isReadonly(ctx)) return;
5537
5558
  let buttons = Controls.getButtons(ctx, "select");
5538
5559
  const state = SelectionStateSingleton.read(ctx);
5539
5560
  if (state.state === SelectionState.Dragging && buttons.length === 0) {
@@ -5552,6 +5573,7 @@ var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ct
5552
5573
  const added2 = blocksQuery.added(ctx);
5553
5574
  for (const entityId of added2) {
5554
5575
  const block = Block.read(ctx, entityId);
5576
+ if (getBlockDef(ctx, block.tag).excludeFromRankBounds) continue;
5555
5577
  if (block.rank === "") {
5556
5578
  const writableBlock = Block.write(ctx, entityId);
5557
5579
  writableBlock.rank = RankBounds.genNext(ctx);
@@ -6732,7 +6754,8 @@ var Editor = class {
6732
6754
  componentsByName,
6733
6755
  singletonsByName,
6734
6756
  componentsById,
6735
- singletonsById
6757
+ singletonsById,
6758
+ readonly: options.readonly
6736
6759
  };
6737
6760
  this.world = new import_core70.World(allDefs, {
6738
6761
  maxEntities,
@@ -6877,6 +6900,10 @@ var Editor = class {
6877
6900
  def.spawn(ctx, payload);
6878
6901
  });
6879
6902
  }
6903
+ /** Runtime readonly flag. Input systems and command() check this to gate mutations. */
6904
+ get readonly() {
6905
+ return this.ctx.resources.readonly;
6906
+ }
6880
6907
  /**
6881
6908
  * Subscribe to query changes.
6882
6909
  *
@@ -7124,6 +7151,7 @@ var Editor = class {
7124
7151
  isAlive,
7125
7152
  isAncestor,
7126
7153
  isHeldByRemote,
7154
+ isReadonly,
7127
7155
  on,
7128
7156
  parsePlugin,
7129
7157
  removeComponent,