@woven-canvas/core 1.3.2 → 1.3.3

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.
@@ -992,6 +992,7 @@ export declare const FRAME_EDGE_THICKNESS = 12;
992
992
  declare const FrameContainmentState: EditorStateDef< {
993
993
  state: StringFieldBuilder;
994
994
  highlightedFrame: RefFieldBuilder;
995
+ draggedEntity: RefFieldBuilder;
995
996
  }>;
996
997
  export { FrameContainmentState }
997
998
  export { FrameContainmentState as FrameContainmentState_alias_1 }
@@ -1067,7 +1068,9 @@ export { getFrameInput }
1067
1068
  export { getFrameInput as getFrameInput_alias_1 }
1068
1069
  export { getFrameInput as getFrameInput_alias_2 }
1069
1070
 
1070
- declare function getKeyboardInput(ctx: Context, keys: number[]): KeyboardInput[];
1071
+ declare function getKeyboardInput(ctx: Context, keys: number[], options?: {
1072
+ repeat?: boolean;
1073
+ }): KeyboardInput[];
1071
1074
  export { getKeyboardInput }
1072
1075
  export { getKeyboardInput as getKeyboardInput_alias_1 }
1073
1076
  export { getKeyboardInput as getKeyboardInput_alias_2 }
@@ -1417,6 +1420,7 @@ declare class KeyboardDef extends CanvasSingletonDef<typeof KeyboardSchema> {
1417
1420
  constructor();
1418
1421
  isKeyDown(ctx: Context, key: number): boolean;
1419
1422
  isKeyDownTrigger(ctx: Context, key: number): boolean;
1423
+ isKeyRepeatTrigger(ctx: Context, key: number): boolean;
1420
1424
  isKeyUpTrigger(ctx: Context, key: number): boolean;
1421
1425
  reset(ctx: Context): void;
1422
1426
  }
@@ -1438,6 +1442,7 @@ export { KeyboardInputType as KeyboardInputType_alias_2 }
1438
1442
  declare const KeyboardSchema: {
1439
1443
  keysDown: BufferFieldBuilder<"uint8">;
1440
1444
  keysDownTrigger: BufferFieldBuilder<"uint8">;
1445
+ keysRepeatTrigger: BufferFieldBuilder<"uint8">;
1441
1446
  keysUpTrigger: BufferFieldBuilder<"uint8">;
1442
1447
  shiftDown: BooleanFieldBuilder;
1443
1448
  altDown: BooleanFieldBuilder;
@@ -992,6 +992,7 @@ export declare const FRAME_EDGE_THICKNESS = 12;
992
992
  declare const FrameContainmentState: EditorStateDef< {
993
993
  state: StringFieldBuilder;
994
994
  highlightedFrame: RefFieldBuilder;
995
+ draggedEntity: RefFieldBuilder;
995
996
  }>;
996
997
  export { FrameContainmentState }
997
998
  export { FrameContainmentState as FrameContainmentState_alias_1 }
@@ -1067,7 +1068,9 @@ export { getFrameInput }
1067
1068
  export { getFrameInput as getFrameInput_alias_1 }
1068
1069
  export { getFrameInput as getFrameInput_alias_2 }
1069
1070
 
1070
- declare function getKeyboardInput(ctx: Context, keys: number[]): KeyboardInput[];
1071
+ declare function getKeyboardInput(ctx: Context, keys: number[], options?: {
1072
+ repeat?: boolean;
1073
+ }): KeyboardInput[];
1071
1074
  export { getKeyboardInput }
1072
1075
  export { getKeyboardInput as getKeyboardInput_alias_1 }
1073
1076
  export { getKeyboardInput as getKeyboardInput_alias_2 }
@@ -1417,6 +1420,7 @@ declare class KeyboardDef extends CanvasSingletonDef<typeof KeyboardSchema> {
1417
1420
  constructor();
1418
1421
  isKeyDown(ctx: Context, key: number): boolean;
1419
1422
  isKeyDownTrigger(ctx: Context, key: number): boolean;
1423
+ isKeyRepeatTrigger(ctx: Context, key: number): boolean;
1420
1424
  isKeyUpTrigger(ctx: Context, key: number): boolean;
1421
1425
  reset(ctx: Context): void;
1422
1426
  }
@@ -1438,6 +1442,7 @@ export { KeyboardInputType as KeyboardInputType_alias_2 }
1438
1442
  declare const KeyboardSchema: {
1439
1443
  keysDown: BufferFieldBuilder<"uint8">;
1440
1444
  keysDownTrigger: BufferFieldBuilder<"uint8">;
1445
+ keysRepeatTrigger: BufferFieldBuilder<"uint8">;
1441
1446
  keysUpTrigger: BufferFieldBuilder<"uint8">;
1442
1447
  shiftDown: BooleanFieldBuilder;
1443
1448
  altDown: BooleanFieldBuilder;
package/build/index.cjs CHANGED
@@ -2196,6 +2196,8 @@ var KeyboardSchema = {
2196
2196
  * Uses field.buffer for zero-allocation subarray views.
2197
2197
  */
2198
2198
  keysDownTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
2199
+ /** Native key-repeat triggers, available separately from initial presses. */
2200
+ keysRepeatTrigger: import_core24.field.buffer(import_core24.field.uint8()).size(KEY_BUFFER_SIZE),
2199
2201
  /**
2200
2202
  * Buffer for key-up triggers (true for exactly 1 frame when key is released).
2201
2203
  * Uses field.buffer for zero-allocation subarray views.
@@ -2234,6 +2236,10 @@ var KeyboardDef = class extends import_canvas_store30.CanvasSingletonDef {
2234
2236
  isKeyDownTrigger(ctx, key) {
2235
2237
  return getBit(this.read(ctx).keysDownTrigger, key);
2236
2238
  }
2239
+ /** Check whether a native key-repeat event occurred this frame. */
2240
+ isKeyRepeatTrigger(ctx, key) {
2241
+ return getBit(this.read(ctx).keysRepeatTrigger, key);
2242
+ }
2237
2243
  /**
2238
2244
  * Check if a key was just released this frame.
2239
2245
  * @param ctx - Editor context
@@ -2250,6 +2256,7 @@ var KeyboardDef = class extends import_canvas_store30.CanvasSingletonDef {
2250
2256
  const keyboard = this.write(ctx);
2251
2257
  clearBits(keyboard.keysDown);
2252
2258
  clearBits(keyboard.keysDownTrigger);
2259
+ clearBits(keyboard.keysRepeatTrigger);
2253
2260
  clearBits(keyboard.keysUpTrigger);
2254
2261
  keyboard.shiftDown = false;
2255
2262
  keyboard.altDown = false;
@@ -2714,7 +2721,14 @@ var FrameContainmentState = defineEditorState("frameContainmentState", {
2714
2721
  /** Current state machine state */
2715
2722
  state: import_core27.field.string().max(16).default(FrameContainmentStateEnum.Idle),
2716
2723
  /** EntityId of the frame currently highlighted as a drop target, or null */
2717
- highlightedFrame: import_core27.field.ref()
2724
+ highlightedFrame: import_core27.field.ref(),
2725
+ /**
2726
+ * The entity being dragged while Tracking (a block, or the TransformBox for a
2727
+ * multi-select), captured on pointerMove. The selection machine has already
2728
+ * left Dragging by the time our pointerUp runs, so the drop fallback can't
2729
+ * re-read it from SelectionState.
2730
+ */
2731
+ draggedEntity: import_core27.field.ref()
2718
2732
  });
2719
2733
 
2720
2734
  // src/singletons/Grid.ts
@@ -3067,10 +3081,10 @@ function getFrameInput(ctx) {
3067
3081
  }
3068
3082
 
3069
3083
  // src/events/keyboardInputEvents.ts
3070
- function getKeyboardInput(ctx, keys) {
3084
+ function getKeyboardInput(ctx, keys, options = {}) {
3071
3085
  const events = [];
3072
3086
  for (const key of keys) {
3073
- if (Keyboard.isKeyDownTrigger(ctx, key)) {
3087
+ if (Keyboard.isKeyDownTrigger(ctx, key) || options.repeat && Keyboard.isKeyRepeatTrigger(ctx, key)) {
3074
3088
  events.push({ type: "keyDown", key, ctx });
3075
3089
  }
3076
3090
  if (Keyboard.isKeyUpTrigger(ctx, key)) {
@@ -3924,8 +3938,7 @@ function clearPointerTrackingState(ctx) {
3924
3938
 
3925
3939
  // src/systems/capture/captureFrameContainmentSystem.ts
3926
3940
  var selectedQuery2 = (0, import_core51.defineQuery)((q) => q.with(Block, Selected));
3927
- function spawnAssignments(ctx, targetFrame) {
3928
- const draggedEntity = getDraggedEntity(ctx);
3941
+ function spawnAssignments(ctx, draggedEntity, targetFrame) {
3929
3942
  if (draggedEntity === null) return;
3930
3943
  const assignments = [];
3931
3944
  if ((0, import_core51.hasComponent)(ctx, draggedEntity, TransformBox)) {
@@ -3973,25 +3986,44 @@ var frameContainmentMachine = (0, import_xstate2.setup)({
3973
3986
  if (targetFrame !== null) {
3974
3987
  AddFrameHighlight.spawn(ctx, { frameId: targetFrame });
3975
3988
  }
3976
- spawnAssignments(ctx, targetFrame);
3989
+ spawnAssignments(ctx, getDraggedEntity(ctx), targetFrame);
3977
3990
  }
3978
3991
  return targetFrame;
3979
- }
3992
+ },
3993
+ draggedEntity: ({ context, event }) => getDraggedEntity(event.ctx) ?? context.draggedEntity
3980
3994
  }),
3981
3995
  clearHighlight: ({ context, event }) => {
3982
3996
  if (context.highlightedFrame !== null) {
3983
3997
  RemoveFrameHighlight.spawn(event.ctx, { frameId: context.highlightedFrame });
3984
3998
  }
3985
3999
  },
4000
+ // Drop fallback. Tracking resolves the target frame from the CURSOR so the
4001
+ // highlight follows the hand, but a drag can release with the cursor off every
4002
+ // frame (the gutter between two pages, just past an edge) while the dragged
4003
+ // block itself still sits on one. Without this the block goes loose
4004
+ // (`parentId: null`) yet looks untouched — and anything that only renders a
4005
+ // frame's children (page captures / print) silently drops it. On pointerUp
4006
+ // with no cursor target, re-resolve by the dragged block's center — the same
4007
+ // rule paste and PlaceBlockEvent use — and parent it there.
4008
+ dropByCenter: ({ context, event }) => {
4009
+ if (context.highlightedFrame !== null) return;
4010
+ const ctx = event.ctx;
4011
+ const draggedEntity = context.draggedEntity;
4012
+ if (draggedEntity === null || !(0, import_core51.hasComponent)(ctx, draggedEntity, Block)) return;
4013
+ const targetFrame = findFrameAtPoint(ctx, Block.getCenter(ctx, draggedEntity), draggedEntity);
4014
+ if (targetFrame !== null) spawnAssignments(ctx, draggedEntity, targetFrame);
4015
+ },
3986
4016
  resetContext: (0, import_xstate2.assign)({
3987
- highlightedFrame: () => null
4017
+ highlightedFrame: () => null,
4018
+ draggedEntity: () => null
3988
4019
  })
3989
4020
  }
3990
4021
  }).createMachine({
3991
4022
  id: "frameContainment",
3992
4023
  initial: FrameContainmentStateEnum.Idle,
3993
4024
  context: {
3994
- highlightedFrame: null
4025
+ highlightedFrame: null,
4026
+ draggedEntity: null
3995
4027
  },
3996
4028
  states: {
3997
4029
  [FrameContainmentStateEnum.Idle]: {
@@ -4010,7 +4042,7 @@ var frameContainmentMachine = (0, import_xstate2.setup)({
4010
4042
  actions: "updateHighlight"
4011
4043
  },
4012
4044
  pointerUp: {
4013
- actions: "clearHighlight",
4045
+ actions: ["dropByCenter", "clearHighlight"],
4014
4046
  target: FrameContainmentStateEnum.Idle
4015
4047
  },
4016
4048
  cancel: {
@@ -4389,7 +4421,10 @@ function attachKeyboardListeners(domElement) {
4389
4421
  const state = {
4390
4422
  eventsBuffer: [],
4391
4423
  onKeyDown: (e) => {
4392
- if (e.key === "Tab" || e.key === "Alt" || e.key === " ") {
4424
+ if (e.defaultPrevented) return;
4425
+ if (e.target instanceof Element && e.target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"]'))
4426
+ return;
4427
+ if (e.key === "Tab" || e.key === "Alt" || e.key === " " || e.code.startsWith("Arrow")) {
4393
4428
  e.preventDefault();
4394
4429
  }
4395
4430
  state.eventsBuffer.push(e);
@@ -4424,14 +4459,17 @@ var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4424
4459
  });
4425
4460
  const hasEvents = state.eventsBuffer.length > 0;
4426
4461
  const keyboardRead = Keyboard.read(ctx);
4427
- const triggersNeedClearing = !isZeroed(keyboardRead.keysDownTrigger) || !isZeroed(keyboardRead.keysUpTrigger);
4462
+ const triggersNeedClearing = !isZeroed(keyboardRead.keysDownTrigger) || !isZeroed(keyboardRead.keysUpTrigger) || !isZeroed(keyboardRead.keysRepeatTrigger);
4428
4463
  if (!hasEvents && !triggersNeedClearing) return;
4429
4464
  const keyboard = Keyboard.write(ctx);
4430
4465
  clearBits(keyboard.keysDownTrigger);
4466
+ clearBits(keyboard.keysRepeatTrigger);
4431
4467
  clearBits(keyboard.keysUpTrigger);
4432
4468
  for (const event of state.eventsBuffer) {
4433
4469
  if (event.type === "blur") {
4434
4470
  clearBits(keyboard.keysDown);
4471
+ clearBits(keyboard.keysDownTrigger);
4472
+ clearBits(keyboard.keysRepeatTrigger);
4435
4473
  keyboard.shiftDown = false;
4436
4474
  keyboard.altDown = false;
4437
4475
  keyboard.modDown = false;
@@ -4444,6 +4482,7 @@ var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4444
4482
  if (!wasDown || !event.repeat) {
4445
4483
  setBit(keyboard.keysDownTrigger, keyIndex, true);
4446
4484
  }
4485
+ if (event.repeat) setBit(keyboard.keysRepeatTrigger, keyIndex, true);
4447
4486
  setBit(keyboard.keysDown, keyIndex, true);
4448
4487
  } else if (event.type === "keyup") {
4449
4488
  setBit(keyboard.keysDown, keyIndex, false);