@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.
package/build/index.js CHANGED
@@ -2037,6 +2037,8 @@ var KeyboardSchema = {
2037
2037
  * Uses field.buffer for zero-allocation subarray views.
2038
2038
  */
2039
2039
  keysDownTrigger: field24.buffer(field24.uint8()).size(KEY_BUFFER_SIZE),
2040
+ /** Native key-repeat triggers, available separately from initial presses. */
2041
+ keysRepeatTrigger: field24.buffer(field24.uint8()).size(KEY_BUFFER_SIZE),
2040
2042
  /**
2041
2043
  * Buffer for key-up triggers (true for exactly 1 frame when key is released).
2042
2044
  * Uses field.buffer for zero-allocation subarray views.
@@ -2075,6 +2077,10 @@ var KeyboardDef = class extends CanvasSingletonDef3 {
2075
2077
  isKeyDownTrigger(ctx, key) {
2076
2078
  return getBit(this.read(ctx).keysDownTrigger, key);
2077
2079
  }
2080
+ /** Check whether a native key-repeat event occurred this frame. */
2081
+ isKeyRepeatTrigger(ctx, key) {
2082
+ return getBit(this.read(ctx).keysRepeatTrigger, key);
2083
+ }
2078
2084
  /**
2079
2085
  * Check if a key was just released this frame.
2080
2086
  * @param ctx - Editor context
@@ -2091,6 +2097,7 @@ var KeyboardDef = class extends CanvasSingletonDef3 {
2091
2097
  const keyboard = this.write(ctx);
2092
2098
  clearBits(keyboard.keysDown);
2093
2099
  clearBits(keyboard.keysDownTrigger);
2100
+ clearBits(keyboard.keysRepeatTrigger);
2094
2101
  clearBits(keyboard.keysUpTrigger);
2095
2102
  keyboard.shiftDown = false;
2096
2103
  keyboard.altDown = false;
@@ -2555,7 +2562,14 @@ var FrameContainmentState = defineEditorState("frameContainmentState", {
2555
2562
  /** Current state machine state */
2556
2563
  state: field27.string().max(16).default(FrameContainmentStateEnum.Idle),
2557
2564
  /** EntityId of the frame currently highlighted as a drop target, or null */
2558
- highlightedFrame: field27.ref()
2565
+ highlightedFrame: field27.ref(),
2566
+ /**
2567
+ * The entity being dragged while Tracking (a block, or the TransformBox for a
2568
+ * multi-select), captured on pointerMove. The selection machine has already
2569
+ * left Dragging by the time our pointerUp runs, so the drop fallback can't
2570
+ * re-read it from SelectionState.
2571
+ */
2572
+ draggedEntity: field27.ref()
2559
2573
  });
2560
2574
 
2561
2575
  // src/singletons/Grid.ts
@@ -2908,10 +2922,10 @@ function getFrameInput(ctx) {
2908
2922
  }
2909
2923
 
2910
2924
  // src/events/keyboardInputEvents.ts
2911
- function getKeyboardInput(ctx, keys) {
2925
+ function getKeyboardInput(ctx, keys, options = {}) {
2912
2926
  const events = [];
2913
2927
  for (const key of keys) {
2914
- if (Keyboard.isKeyDownTrigger(ctx, key)) {
2928
+ if (Keyboard.isKeyDownTrigger(ctx, key) || options.repeat && Keyboard.isKeyRepeatTrigger(ctx, key)) {
2915
2929
  events.push({ type: "keyDown", key, ctx });
2916
2930
  }
2917
2931
  if (Keyboard.isKeyUpTrigger(ctx, key)) {
@@ -3771,8 +3785,7 @@ function clearPointerTrackingState(ctx) {
3771
3785
 
3772
3786
  // src/systems/capture/captureFrameContainmentSystem.ts
3773
3787
  var selectedQuery2 = defineQuery7((q) => q.with(Block, Selected));
3774
- function spawnAssignments(ctx, targetFrame) {
3775
- const draggedEntity = getDraggedEntity(ctx);
3788
+ function spawnAssignments(ctx, draggedEntity, targetFrame) {
3776
3789
  if (draggedEntity === null) return;
3777
3790
  const assignments = [];
3778
3791
  if (hasComponent11(ctx, draggedEntity, TransformBox)) {
@@ -3820,25 +3833,44 @@ var frameContainmentMachine = setup({
3820
3833
  if (targetFrame !== null) {
3821
3834
  AddFrameHighlight.spawn(ctx, { frameId: targetFrame });
3822
3835
  }
3823
- spawnAssignments(ctx, targetFrame);
3836
+ spawnAssignments(ctx, getDraggedEntity(ctx), targetFrame);
3824
3837
  }
3825
3838
  return targetFrame;
3826
- }
3839
+ },
3840
+ draggedEntity: ({ context, event }) => getDraggedEntity(event.ctx) ?? context.draggedEntity
3827
3841
  }),
3828
3842
  clearHighlight: ({ context, event }) => {
3829
3843
  if (context.highlightedFrame !== null) {
3830
3844
  RemoveFrameHighlight.spawn(event.ctx, { frameId: context.highlightedFrame });
3831
3845
  }
3832
3846
  },
3847
+ // Drop fallback. Tracking resolves the target frame from the CURSOR so the
3848
+ // highlight follows the hand, but a drag can release with the cursor off every
3849
+ // frame (the gutter between two pages, just past an edge) while the dragged
3850
+ // block itself still sits on one. Without this the block goes loose
3851
+ // (`parentId: null`) yet looks untouched — and anything that only renders a
3852
+ // frame's children (page captures / print) silently drops it. On pointerUp
3853
+ // with no cursor target, re-resolve by the dragged block's center — the same
3854
+ // rule paste and PlaceBlockEvent use — and parent it there.
3855
+ dropByCenter: ({ context, event }) => {
3856
+ if (context.highlightedFrame !== null) return;
3857
+ const ctx = event.ctx;
3858
+ const draggedEntity = context.draggedEntity;
3859
+ if (draggedEntity === null || !hasComponent11(ctx, draggedEntity, Block)) return;
3860
+ const targetFrame = findFrameAtPoint(ctx, Block.getCenter(ctx, draggedEntity), draggedEntity);
3861
+ if (targetFrame !== null) spawnAssignments(ctx, draggedEntity, targetFrame);
3862
+ },
3833
3863
  resetContext: assign({
3834
- highlightedFrame: () => null
3864
+ highlightedFrame: () => null,
3865
+ draggedEntity: () => null
3835
3866
  })
3836
3867
  }
3837
3868
  }).createMachine({
3838
3869
  id: "frameContainment",
3839
3870
  initial: FrameContainmentStateEnum.Idle,
3840
3871
  context: {
3841
- highlightedFrame: null
3872
+ highlightedFrame: null,
3873
+ draggedEntity: null
3842
3874
  },
3843
3875
  states: {
3844
3876
  [FrameContainmentStateEnum.Idle]: {
@@ -3857,7 +3889,7 @@ var frameContainmentMachine = setup({
3857
3889
  actions: "updateHighlight"
3858
3890
  },
3859
3891
  pointerUp: {
3860
- actions: "clearHighlight",
3892
+ actions: ["dropByCenter", "clearHighlight"],
3861
3893
  target: FrameContainmentStateEnum.Idle
3862
3894
  },
3863
3895
  cancel: {
@@ -4236,7 +4268,10 @@ function attachKeyboardListeners(domElement) {
4236
4268
  const state = {
4237
4269
  eventsBuffer: [],
4238
4270
  onKeyDown: (e) => {
4239
- if (e.key === "Tab" || e.key === "Alt" || e.key === " ") {
4271
+ if (e.defaultPrevented) return;
4272
+ if (e.target instanceof Element && e.target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"]'))
4273
+ return;
4274
+ if (e.key === "Tab" || e.key === "Alt" || e.key === " " || e.code.startsWith("Arrow")) {
4240
4275
  e.preventDefault();
4241
4276
  }
4242
4277
  state.eventsBuffer.push(e);
@@ -4271,14 +4306,17 @@ var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4271
4306
  });
4272
4307
  const hasEvents = state.eventsBuffer.length > 0;
4273
4308
  const keyboardRead = Keyboard.read(ctx);
4274
- const triggersNeedClearing = !isZeroed(keyboardRead.keysDownTrigger) || !isZeroed(keyboardRead.keysUpTrigger);
4309
+ const triggersNeedClearing = !isZeroed(keyboardRead.keysDownTrigger) || !isZeroed(keyboardRead.keysUpTrigger) || !isZeroed(keyboardRead.keysRepeatTrigger);
4275
4310
  if (!hasEvents && !triggersNeedClearing) return;
4276
4311
  const keyboard = Keyboard.write(ctx);
4277
4312
  clearBits(keyboard.keysDownTrigger);
4313
+ clearBits(keyboard.keysRepeatTrigger);
4278
4314
  clearBits(keyboard.keysUpTrigger);
4279
4315
  for (const event of state.eventsBuffer) {
4280
4316
  if (event.type === "blur") {
4281
4317
  clearBits(keyboard.keysDown);
4318
+ clearBits(keyboard.keysDownTrigger);
4319
+ clearBits(keyboard.keysRepeatTrigger);
4282
4320
  keyboard.shiftDown = false;
4283
4321
  keyboard.altDown = false;
4284
4322
  keyboard.modDown = false;
@@ -4291,6 +4329,7 @@ var keyboardSystem = defineEditorSystem({ phase: "input" }, (ctx) => {
4291
4329
  if (!wasDown || !event.repeat) {
4292
4330
  setBit(keyboard.keysDownTrigger, keyIndex, true);
4293
4331
  }
4332
+ if (event.repeat) setBit(keyboard.keysRepeatTrigger, keyIndex, true);
4294
4333
  setBit(keyboard.keysDown, keyIndex, true);
4295
4334
  } else if (event.type === "keyup") {
4296
4335
  setBit(keyboard.keysDown, keyIndex, false);