@woven-canvas/core 1.0.15 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -171,6 +171,7 @@ declare const BlockDef: z.ZodObject<{
171
171
  canScale: z.ZodDefault<z.ZodBoolean>;
172
172
  snappable: z.ZodDefault<z.ZodBoolean>;
173
173
  interactable: z.ZodDefault<z.ZodBoolean>;
174
+ showOperations: z.ZodDefault<z.ZodBoolean>;
174
175
  excludeFromRankBounds: z.ZodDefault<z.ZodBoolean>;
175
176
  connectors: z.ZodDefault<z.ZodObject<{
176
177
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -738,6 +739,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
738
739
  canScale?: boolean | undefined;
739
740
  snappable?: boolean | undefined;
740
741
  interactable?: boolean | undefined;
742
+ showOperations?: boolean | undefined;
741
743
  excludeFromRankBounds?: boolean | undefined;
742
744
  connectors?: {
743
745
  enabled?: boolean | undefined;
@@ -756,6 +758,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
756
758
  canScale?: boolean | undefined;
757
759
  snappable?: boolean | undefined;
758
760
  interactable?: boolean | undefined;
761
+ showOperations?: boolean | undefined;
759
762
  excludeFromRankBounds?: boolean | undefined;
760
763
  connectors?: {
761
764
  enabled?: boolean | undefined;
@@ -934,6 +937,11 @@ export { EventType }
934
937
 
935
938
  export { field }
936
939
 
940
+ declare function filterRoots(ctx: Context, entityIds: EntityId[]): EntityId[];
941
+ export { filterRoots }
942
+ export { filterRoots as filterRoots_alias_1 }
943
+ export { filterRoots as filterRoots_alias_2 }
944
+
937
945
  declare function findFrameAtPoint(ctx: Context, point: [number, number], exclude?: EntityId | null): EntityId | null;
938
946
  export { findFrameAtPoint }
939
947
  export { findFrameAtPoint as findFrameAtPoint_alias_1 }
@@ -1499,6 +1507,7 @@ declare interface MouseInput {
1499
1507
  wheelDeltaX: number;
1500
1508
  wheelDeltaY: number;
1501
1509
  wheelModKey: boolean;
1510
+ wheelShiftKey: boolean;
1502
1511
  }
1503
1512
  export { MouseInput }
1504
1513
  export { MouseInput as MouseInput_alias_1 }
@@ -1516,6 +1525,7 @@ declare const MouseSchema: {
1516
1525
  moveTrigger: BooleanFieldBuilder;
1517
1526
  wheelTrigger: BooleanFieldBuilder;
1518
1527
  wheelModKey: BooleanFieldBuilder;
1528
+ wheelShiftKey: BooleanFieldBuilder;
1519
1529
  enterTrigger: BooleanFieldBuilder;
1520
1530
  leaveTrigger: BooleanFieldBuilder;
1521
1531
  obscured: BooleanFieldBuilder;
@@ -171,6 +171,7 @@ declare const BlockDef: z.ZodObject<{
171
171
  canScale: z.ZodDefault<z.ZodBoolean>;
172
172
  snappable: z.ZodDefault<z.ZodBoolean>;
173
173
  interactable: z.ZodDefault<z.ZodBoolean>;
174
+ showOperations: z.ZodDefault<z.ZodBoolean>;
174
175
  excludeFromRankBounds: z.ZodDefault<z.ZodBoolean>;
175
176
  connectors: z.ZodDefault<z.ZodObject<{
176
177
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -738,6 +739,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
738
739
  canScale?: boolean | undefined;
739
740
  snappable?: boolean | undefined;
740
741
  interactable?: boolean | undefined;
742
+ showOperations?: boolean | undefined;
741
743
  excludeFromRankBounds?: boolean | undefined;
742
744
  connectors?: {
743
745
  enabled?: boolean | undefined;
@@ -756,6 +758,7 @@ export declare const EditorOptionsSchema: z.ZodObject<{
756
758
  canScale?: boolean | undefined;
757
759
  snappable?: boolean | undefined;
758
760
  interactable?: boolean | undefined;
761
+ showOperations?: boolean | undefined;
759
762
  excludeFromRankBounds?: boolean | undefined;
760
763
  connectors?: {
761
764
  enabled?: boolean | undefined;
@@ -934,6 +937,11 @@ export { EventType }
934
937
 
935
938
  export { field }
936
939
 
940
+ declare function filterRoots(ctx: Context, entityIds: EntityId[]): EntityId[];
941
+ export { filterRoots }
942
+ export { filterRoots as filterRoots_alias_1 }
943
+ export { filterRoots as filterRoots_alias_2 }
944
+
937
945
  declare function findFrameAtPoint(ctx: Context, point: [number, number], exclude?: EntityId | null): EntityId | null;
938
946
  export { findFrameAtPoint }
939
947
  export { findFrameAtPoint as findFrameAtPoint_alias_1 }
@@ -1499,6 +1507,7 @@ declare interface MouseInput {
1499
1507
  wheelDeltaX: number;
1500
1508
  wheelDeltaY: number;
1501
1509
  wheelModKey: boolean;
1510
+ wheelShiftKey: boolean;
1502
1511
  }
1503
1512
  export { MouseInput }
1504
1513
  export { MouseInput as MouseInput_alias_1 }
@@ -1516,6 +1525,7 @@ declare const MouseSchema: {
1516
1525
  moveTrigger: BooleanFieldBuilder;
1517
1526
  wheelTrigger: BooleanFieldBuilder;
1518
1527
  wheelModKey: BooleanFieldBuilder;
1528
+ wheelShiftKey: BooleanFieldBuilder;
1519
1529
  enterTrigger: BooleanFieldBuilder;
1520
1530
  leaveTrigger: BooleanFieldBuilder;
1521
1531
  obscured: BooleanFieldBuilder;
package/build/index.cjs CHANGED
@@ -156,6 +156,7 @@ __export(index_exports, {
156
156
  deselectBlock: () => deselectBlock,
157
157
  detectEmbedProvider: () => detectEmbedProvider,
158
158
  field: () => import_core74.field,
159
+ filterRoots: () => filterRoots,
159
160
  findFrameAtPoint: () => findFrameAtPoint,
160
161
  generateUuidBySeed: () => generateUuidBySeed,
161
162
  getBackrefs: () => import_core74.getBackrefs,
@@ -641,6 +642,7 @@ var BlockDef = import_zod.z.object({
641
642
  canScale: import_zod.z.boolean().default(true),
642
643
  snappable: import_zod.z.boolean().default(true),
643
644
  interactable: import_zod.z.boolean().default(true),
645
+ showOperations: import_zod.z.boolean().default(true),
644
646
  excludeFromRankBounds: import_zod.z.boolean().default(false),
645
647
  connectors: BlockDefConnectors.default(BlockDefConnectors.parse({}))
646
648
  });
@@ -2852,6 +2854,8 @@ var MouseSchema = {
2852
2854
  * wheel events with ctrlKey set.
2853
2855
  */
2854
2856
  wheelModKey: import_core30.field.boolean().default(false),
2857
+ /** Shift key was held during this frame's wheel event */
2858
+ wheelShiftKey: import_core30.field.boolean().default(false),
2855
2859
  /** True for 1 frame when mouse enters the editor element */
2856
2860
  enterTrigger: import_core30.field.boolean().default(false),
2857
2861
  /** True for 1 frame when mouse leaves the editor element */
@@ -3072,7 +3076,8 @@ function getMouseInput(ctx) {
3072
3076
  worldPosition: worldPos,
3073
3077
  wheelDeltaX: mouse.wheelDeltaX,
3074
3078
  wheelDeltaY: mouse.wheelDeltaY,
3075
- wheelModKey: mouse.wheelModKey
3079
+ wheelModKey: mouse.wheelModKey,
3080
+ wheelShiftKey: mouse.wheelShiftKey
3076
3081
  });
3077
3082
  }
3078
3083
  if (mouse.moveTrigger) {
@@ -3083,7 +3088,8 @@ function getMouseInput(ctx) {
3083
3088
  worldPosition: worldPos,
3084
3089
  wheelDeltaX: 0,
3085
3090
  wheelDeltaY: 0,
3086
- wheelModKey: false
3091
+ wheelModKey: false,
3092
+ wheelShiftKey: false
3087
3093
  });
3088
3094
  }
3089
3095
  return events;
@@ -3323,6 +3329,21 @@ function getDescendants(ctx, parentId) {
3323
3329
  }
3324
3330
  return result;
3325
3331
  }
3332
+ function filterRoots(ctx, entityIds) {
3333
+ const idSet = new Set(entityIds);
3334
+ return entityIds.filter((entityId) => {
3335
+ if (!(0, import_core41.hasComponent)(ctx, entityId, Block)) return false;
3336
+ let current = Block.read(ctx, entityId).parentId;
3337
+ const visited = /* @__PURE__ */ new Set();
3338
+ while (current !== null && (0, import_core41.hasComponent)(ctx, current, Block)) {
3339
+ if (idSet.has(current)) return false;
3340
+ if (visited.has(current)) break;
3341
+ visited.add(current);
3342
+ current = Block.read(ctx, current).parentId;
3343
+ }
3344
+ return true;
3345
+ });
3346
+ }
3326
3347
  function cascadeDelete(ctx, entityId) {
3327
3348
  const children = (0, import_core41.getBackrefs)(ctx, entityId, Block, "parentId");
3328
3349
  for (const childId of children) {
@@ -4477,7 +4498,8 @@ function attachMouseListeners(domElement) {
4477
4498
  deltaMode: e.deltaMode,
4478
4499
  // Trackpad pinch gestures arrive as wheel events with ctrlKey set,
4479
4500
  // without any keydown — capture the flags from the event itself.
4480
- modKey: e.ctrlKey || e.metaKey
4501
+ modKey: e.ctrlKey || e.metaKey,
4502
+ shiftKey: e.shiftKey
4481
4503
  });
4482
4504
  },
4483
4505
  onMouseEnter: () => {
@@ -4520,6 +4542,7 @@ var mouseSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4520
4542
  mouse.wheelDeltaX = 0;
4521
4543
  mouse.wheelDeltaY = 0;
4522
4544
  mouse.wheelModKey = false;
4545
+ mouse.wheelShiftKey = false;
4523
4546
  for (const event of state.eventsBuffer) {
4524
4547
  switch (event.type) {
4525
4548
  case "mousemove":
@@ -4532,6 +4555,7 @@ var mouseSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4532
4555
  mouse.wheelDeltaY = normalizeWheelDelta(event.deltaY, event.deltaMode);
4533
4556
  mouse.wheelTrigger = true;
4534
4557
  mouse.wheelModKey = event.modKey === true;
4558
+ mouse.wheelShiftKey = event.shiftKey === true;
4535
4559
  break;
4536
4560
  case "mouseenter":
4537
4561
  mouse.enterTrigger = true;
@@ -5925,6 +5949,7 @@ var blockSystem = defineEditorSystem({ phase: "update" }, (ctx) => {
5925
5949
  }
5926
5950
  }
5927
5951
  });
5952
+ on(ctx, DuplicateSelected, duplicateSelected);
5928
5953
  on(ctx, BringForwardSelected, bringForwardSelected);
5929
5954
  on(ctx, SendBackwardSelected, sendBackwardSelected);
5930
5955
  on(ctx, SetCursor, (ctx2, payload) => {
@@ -5950,6 +5975,23 @@ function deselectAllBlocks(ctx) {
5950
5975
  deselectBlock(ctx, entityId);
5951
5976
  }
5952
5977
  }
5978
+ var DUPLICATE_OFFSET = 20;
5979
+ function duplicateSelected(ctx) {
5980
+ const selectedBlocks = [...selectedBlocksQuery4.current(ctx)];
5981
+ if (selectedBlocks.length === 0) return;
5982
+ cloneEntities(ctx, selectedBlocks, [0, 0], crypto.randomUUID());
5983
+ const grid = Grid.read(ctx);
5984
+ const offset = grid.enabled && grid.colWidth > 0 && grid.rowHeight > 0 ? [grid.colWidth, grid.rowHeight] : [DUPLICATE_OFFSET, DUPLICATE_OFFSET];
5985
+ for (const entityId of filterRoots(ctx, selectedBlocks)) {
5986
+ const worldPos = Block.getWorldPosition(ctx, entityId);
5987
+ import_math12.Vec2.add(worldPos, offset);
5988
+ Block.setWorldPosition(ctx, entityId, worldPos);
5989
+ }
5990
+ const { transformBoxId } = TransformBoxStateSingleton.read(ctx);
5991
+ if (transformBoxId !== null) {
5992
+ UpdateTransformBox.spawn(ctx, { transformBoxId });
5993
+ }
5994
+ }
5953
5995
  function bringForwardSelected(ctx) {
5954
5996
  const selectedBlocks = [...selectedBlocksQuery4.current(ctx)];
5955
5997
  if (selectedBlocks.length === 0) return;
@@ -5987,7 +6029,6 @@ function sendBackwardSelected(ctx) {
5987
6029
  }
5988
6030
  }
5989
6031
  function cloneEntities(ctx, entityIds, offset, seed) {
5990
- const rootSet = new Set(entityIds);
5991
6032
  const allEntityIdsSet = new Set(entityIds);
5992
6033
  for (const entityId of entityIds) {
5993
6034
  for (const descendant of getDescendants(ctx, entityId)) {
@@ -5995,6 +6036,7 @@ function cloneEntities(ctx, entityIds, offset, seed) {
5995
6036
  }
5996
6037
  }
5997
6038
  entityIds = [...allEntityIdsSet];
6039
+ const rootSet = new Set(filterRoots(ctx, entityIds));
5998
6040
  const { componentsById } = (0, import_core67.getResources)(ctx);
5999
6041
  const documentComponents = new Map([...componentsById].filter(([, def]) => def.sync === "document"));
6000
6042
  const syncedComponentId = import_canvas_store46.Synced._getComponentId(ctx);
@@ -7406,6 +7448,7 @@ var Editor = class {
7406
7448
  deselectBlock,
7407
7449
  detectEmbedProvider,
7408
7450
  field,
7451
+ filterRoots,
7409
7452
  findFrameAtPoint,
7410
7453
  generateUuidBySeed,
7411
7454
  getBackrefs,