@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.
package/build/index.d.cts CHANGED
@@ -199,6 +199,7 @@ export { FrameContainmentStateEnum } from './_tsup-dts-rollup.cjs';
199
199
  export { FrameContainmentStateValue } from './_tsup-dts-rollup.cjs';
200
200
  export { GridOptions } from './_tsup-dts-rollup.cjs';
201
201
  export { getPluginResources } from './_tsup-dts-rollup.cjs';
202
+ export { isReadonly } from './_tsup-dts-rollup.cjs';
202
203
  export { Keybind } from './_tsup-dts-rollup.cjs';
203
204
  export { ResizeMode } from './_tsup-dts-rollup.cjs';
204
205
  export { ScrollEdgesState } from './_tsup-dts-rollup.cjs';
package/build/index.d.ts CHANGED
@@ -199,6 +199,7 @@ export { FrameContainmentStateEnum } from './_tsup-dts-rollup.js';
199
199
  export { FrameContainmentStateValue } from './_tsup-dts-rollup.js';
200
200
  export { GridOptions } from './_tsup-dts-rollup.js';
201
201
  export { getPluginResources } from './_tsup-dts-rollup.js';
202
+ export { isReadonly } from './_tsup-dts-rollup.js';
202
203
  export { Keybind } from './_tsup-dts-rollup.js';
203
204
  export { ResizeMode } from './_tsup-dts-rollup.js';
204
205
  export { ScrollEdgesState } from './_tsup-dts-rollup.js';
package/build/index.js CHANGED
@@ -231,6 +231,9 @@ function getPluginResources(ctx, pluginName) {
231
231
  const resources = ctx.resources;
232
232
  return resources.pluginResources[pluginName];
233
233
  }
234
+ function isReadonly(ctx) {
235
+ return ctx.resources.readonly;
236
+ }
234
237
  var GridOptions = z.object({
235
238
  /**
236
239
  * Whether grid snapping is enabled.
@@ -392,7 +395,16 @@ var EditorOptionsSchema = z.object({
392
395
  * }
393
396
  * ```
394
397
  */
395
- controls: z.custom().optional()
398
+ controls: z.custom().optional(),
399
+ /**
400
+ * When true, user-initiated mutations are blocked — input systems skip
401
+ * their bodies and `editor.command()` is a no-op. Adapter-originated
402
+ * mutations (websocket, persistence) still apply, so remote edits remain
403
+ * visible. Useful for viewer-mode share links.
404
+ *
405
+ * @default false
406
+ */
407
+ readonly: z.boolean().default(false)
396
408
  });
397
409
  var Keybind = z.object({
398
410
  /** The command to execute when this keybind is triggered */
@@ -461,6 +473,7 @@ var BlockDef = z.object({
461
473
  canRotate: z.boolean().default(true),
462
474
  canScale: z.boolean().default(true),
463
475
  interactable: z.boolean().default(true),
476
+ excludeFromRankBounds: z.boolean().default(false),
464
477
  connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
465
478
  });
466
479
  var SelectionState = {
@@ -3145,6 +3158,8 @@ function intersectPoint(ctx, point, entityIds) {
3145
3158
  const intersects = [];
3146
3159
  const entities = entityIds ?? blocksWithAabb.current(ctx);
3147
3160
  for (const entityId of entities) {
3161
+ const block = Block.read(ctx, entityId);
3162
+ if (!canBlockInteract(ctx, block.tag)) continue;
3148
3163
  if (!Aabb.containsPoint(ctx, entityId, point)) {
3149
3164
  continue;
3150
3165
  }
@@ -3168,6 +3183,8 @@ function intersectAabb(ctx, bounds, entityIds) {
3168
3183
  const intersecting = [];
3169
3184
  const entities = entityIds ?? blocksWithAabb.current(ctx);
3170
3185
  for (const entityId of entities) {
3186
+ const block = Block.read(ctx, entityId);
3187
+ if (!canBlockInteract(ctx, block.tag)) continue;
3171
3188
  const { value: entityAabb } = Aabb.read(ctx, entityId);
3172
3189
  if (!Aabb3.intersects(bounds, entityAabb)) {
3173
3190
  continue;
@@ -3697,6 +3714,7 @@ var hoverCursorSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
3697
3714
  // src/systems/capture/keybindSystem.ts
3698
3715
  import { addComponent as addComponent3, createEntity as createEntity2, getResources as getResources6 } from "@woven-ecs/core";
3699
3716
  var keybindSystem = defineEditorSystem({ phase: "capture" }, (ctx) => {
3717
+ if (isReadonly(ctx)) return;
3700
3718
  const keyboard = Keyboard.read(ctx);
3701
3719
  const { editor } = getResources6(ctx);
3702
3720
  for (const keybind of editor.keybinds) {
@@ -4447,8 +4465,9 @@ var cursorSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx)
4447
4465
  // src/systems/postRender/presenceSystem.ts
4448
4466
  import { defineQuery as defineQuery11 } from "@woven-ecs/core";
4449
4467
  var pointerQuery2 = defineQuery11((q) => q.tracking(Pointer));
4468
+ var cameraChangedQuery = defineQuery11((q) => q.tracking(Camera));
4450
4469
  var presenceSystem = defineEditorSystem({ phase: "render", priority: -100 }, (ctx) => {
4451
- if (Mouse.didMove(ctx)) {
4470
+ if (Mouse.didMove(ctx) || cameraChangedQuery.changed(ctx).length > 0) {
4452
4471
  const mouse = Mouse.read(ctx);
4453
4472
  updateUserPosition(ctx, mouse.position);
4454
4473
  return;
@@ -4968,6 +4987,10 @@ function clearHovered(ctx) {
4968
4987
  function findValidHoverTarget(ctx, intersected) {
4969
4988
  for (const entityId of intersected) {
4970
4989
  if (isHeldByRemote(ctx, entityId)) return void 0;
4990
+ if (hasComponent13(ctx, entityId, Block)) {
4991
+ const block = Block.read(ctx, entityId);
4992
+ if (!canBlockInteract(ctx, block.tag)) continue;
4993
+ }
4971
4994
  return entityId;
4972
4995
  }
4973
4996
  return void 0;
@@ -5018,10 +5041,6 @@ var intersectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (c
5018
5041
  addDescendants(ctx, entityId, changed);
5019
5042
  }
5020
5043
  for (const entityId of added) {
5021
- if (hasComponent13(ctx, entityId, Block)) {
5022
- const block = Block.read(ctx, entityId);
5023
- if (!canBlockInteract(ctx, block.tag)) continue;
5024
- }
5025
5044
  if (!hasComponent13(ctx, entityId, Aabb)) {
5026
5045
  addComponent6(ctx, entityId, Aabb, { value: [0, 0, 0, 0] });
5027
5046
  }
@@ -5405,6 +5424,7 @@ var selectionMachine = setup4({
5405
5424
  }
5406
5425
  });
5407
5426
  var selectSystem = defineEditorSystem({ phase: "capture", priority: 100 }, (ctx) => {
5427
+ if (isReadonly(ctx)) return;
5408
5428
  let buttons = Controls.getButtons(ctx, "select");
5409
5429
  const state = SelectionStateSingleton.read(ctx);
5410
5430
  if (state.state === SelectionState.Dragging && buttons.length === 0) {
@@ -5423,6 +5443,7 @@ var rankBoundsSystem = defineEditorSystem({ phase: "input", priority: 100 }, (ct
5423
5443
  const added2 = blocksQuery.added(ctx);
5424
5444
  for (const entityId of added2) {
5425
5445
  const block = Block.read(ctx, entityId);
5446
+ if (getBlockDef(ctx, block.tag).excludeFromRankBounds) continue;
5426
5447
  if (block.rank === "") {
5427
5448
  const writableBlock = Block.write(ctx, entityId);
5428
5449
  writableBlock.rank = RankBounds.genNext(ctx);
@@ -6617,7 +6638,8 @@ var Editor = class {
6617
6638
  componentsByName,
6618
6639
  singletonsByName,
6619
6640
  componentsById,
6620
- singletonsById
6641
+ singletonsById,
6642
+ readonly: options.readonly
6621
6643
  };
6622
6644
  this.world = new World(allDefs, {
6623
6645
  maxEntities,
@@ -6762,6 +6784,10 @@ var Editor = class {
6762
6784
  def.spawn(ctx, payload);
6763
6785
  });
6764
6786
  }
6787
+ /** Runtime readonly flag. Input systems and command() check this to gate mutations. */
6788
+ get readonly() {
6789
+ return this.ctx.resources.readonly;
6790
+ }
6765
6791
  /**
6766
6792
  * Subscribe to query changes.
6767
6793
  *
@@ -7008,6 +7034,7 @@ export {
7008
7034
  isAlive3 as isAlive,
7009
7035
  isAncestor,
7010
7036
  isHeldByRemote,
7037
+ isReadonly,
7011
7038
  on,
7012
7039
  parsePlugin,
7013
7040
  removeComponent7 as removeComponent,