@fieldnotes/core 0.50.2 → 0.50.4

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/dist/index.cjs CHANGED
@@ -2320,6 +2320,9 @@ var MAX_DEPTH = 8;
2320
2320
  function intersects(a, b) {
2321
2321
  return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;
2322
2322
  }
2323
+ function contains(outer, inner) {
2324
+ return inner.x >= outer.x && inner.x + inner.w <= outer.x + outer.w && inner.y >= outer.y && inner.y + inner.h <= outer.y + outer.h;
2325
+ }
2323
2326
  var QuadNode = class _QuadNode {
2324
2327
  constructor(bounds, depth) {
2325
2328
  this.bounds = bounds;
@@ -2372,6 +2375,14 @@ var QuadNode = class _QuadNode {
2372
2375
  }
2373
2376
  }
2374
2377
  }
2378
+ collect(result) {
2379
+ result.push(...this.items);
2380
+ if (this.children) {
2381
+ for (const child of this.children) {
2382
+ child.collect(result);
2383
+ }
2384
+ }
2385
+ }
2375
2386
  getChildIndex(itemBounds) {
2376
2387
  const midX = this.bounds.x + this.bounds.w / 2;
2377
2388
  const midY = this.bounds.y + this.bounds.h / 2;
@@ -2435,6 +2446,7 @@ var Quadtree = class {
2435
2446
  return this._size;
2436
2447
  }
2437
2448
  insert(id, bounds) {
2449
+ this.expandToFit(bounds);
2438
2450
  this.root.insert({ id, bounds });
2439
2451
  this._size++;
2440
2452
  }
@@ -2459,6 +2471,24 @@ var Quadtree = class {
2459
2471
  this.root = new QuadNode(this.worldBounds, 0);
2460
2472
  this._size = 0;
2461
2473
  }
2474
+ expandToFit(bounds) {
2475
+ const current = this.root.bounds;
2476
+ if (contains(current, bounds)) return;
2477
+ const currentRight = current.x + current.w;
2478
+ const currentBottom = current.y + current.h;
2479
+ const requiredWidth = Math.max(currentRight, bounds.x + bounds.w) - Math.min(current.x, bounds.x);
2480
+ const requiredHeight = Math.max(currentBottom, bounds.y + bounds.h) - Math.min(current.y, bounds.y);
2481
+ const width = Math.max(current.w * 2, requiredWidth);
2482
+ const height = Math.max(current.h * 2, requiredHeight);
2483
+ const x = bounds.x < current.x ? currentRight - width : current.x;
2484
+ const y = bounds.y < current.y ? currentBottom - height : current.y;
2485
+ const entries = [];
2486
+ this.root.collect(entries);
2487
+ this.root = new QuadNode({ x, y, w: width, h: height }, 0);
2488
+ for (const entry of entries) {
2489
+ this.root.insert(entry);
2490
+ }
2491
+ }
2462
2492
  };
2463
2493
 
2464
2494
  // src/elements/stroke-smoothing.ts
@@ -8417,7 +8447,8 @@ function hitTestArrowHandles(world, selectedIds, ctx) {
8417
8447
  const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;
8418
8448
  for (const id of selectedIds) {
8419
8449
  const el = ctx.store.getById(id);
8420
- if (!el || el.type !== "arrow") continue;
8450
+ if (!el || el.type !== "arrow" || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false))
8451
+ continue;
8421
8452
  const handles = getArrowHandlePositions(el);
8422
8453
  for (const [handle, pos] of handles) {
8423
8454
  const dx = world.x - pos.x;
@@ -8431,7 +8462,7 @@ function hitTestArrowHandles(world, selectedIds, ctx) {
8431
8462
  }
8432
8463
  function applyArrowHandleDrag(handle, elementId, world, ctx) {
8433
8464
  const el = ctx.store.getById(elementId);
8434
- if (!el || el.type !== "arrow") return;
8465
+ if (!el || el.type !== "arrow" || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) return;
8435
8466
  const threshold = BIND_THRESHOLD / ctx.camera.zoom;
8436
8467
  const layerFilter = (candidate) => candidate.layerId === el.layerId;
8437
8468
  switch (handle) {
@@ -8482,7 +8513,9 @@ function applyArrowHandleDrag(handle, elementId, world, ctx) {
8482
8513
  function getArrowHandleDragTarget(handle, elementId, world, ctx) {
8483
8514
  if (handle === "mid") return null;
8484
8515
  const el = ctx.store.getById(elementId);
8485
- if (!el || el.type !== "arrow") return null;
8516
+ if (!el || el.type !== "arrow" || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) {
8517
+ return null;
8518
+ }
8486
8519
  const threshold = BIND_THRESHOLD / ctx.camera.zoom;
8487
8520
  const excludeId = handle === "start" ? el.toBinding?.elementId : el.fromBinding?.elementId;
8488
8521
  const layerFilter = (candidate) => candidate.layerId === el.layerId;
@@ -8674,22 +8707,25 @@ function renderSelectionBoxes(ctx, p) {
8674
8707
  for (const id of p.selectedIds) {
8675
8708
  const el = p.store.getById(id);
8676
8709
  if (!el) continue;
8710
+ const locked = el.locked || (p.isLayerLocked?.(el.layerId) ?? false);
8677
8711
  if (el.type === "arrow") {
8678
- renderArrowHandles(ctx, el, zoom);
8712
+ if (!locked) renderArrowHandles(ctx, el, zoom);
8679
8713
  renderBindingHighlights(ctx, el, zoom, p.store);
8680
8714
  continue;
8681
8715
  }
8682
8716
  if (el.type === "shape" && el.shape === "line") {
8683
- ctx.setLineDash([]);
8684
- ctx.fillStyle = "#ffffff";
8685
- const r = handleWorldSize / 2;
8686
- for (const pt of lineEndpoints(el)) {
8687
- ctx.beginPath();
8688
- ctx.arc(pt.x, pt.y, r, 0, Math.PI * 2);
8689
- ctx.fill();
8690
- ctx.stroke();
8717
+ if (!locked) {
8718
+ ctx.setLineDash([]);
8719
+ ctx.fillStyle = "#ffffff";
8720
+ const r = handleWorldSize / 2;
8721
+ for (const pt of lineEndpoints(el)) {
8722
+ ctx.beginPath();
8723
+ ctx.arc(pt.x, pt.y, r, 0, Math.PI * 2);
8724
+ ctx.fill();
8725
+ ctx.stroke();
8726
+ }
8727
+ ctx.setLineDash([4 / zoom, 4 / zoom]);
8691
8728
  }
8692
- ctx.setLineDash([4 / zoom, 4 / zoom]);
8693
8729
  continue;
8694
8730
  }
8695
8731
  const bounds = getElementBounds(el);
@@ -8924,7 +8960,8 @@ function hitTestLineHandles(world, ctx, selectedIds) {
8924
8960
  const r2 = r * r;
8925
8961
  for (const id of selectedIds) {
8926
8962
  const el = ctx.store.getById(id);
8927
- if (!el || el.type !== "shape" || el.shape !== "line") continue;
8963
+ if (!el || el.type !== "shape" || el.shape !== "line" || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false))
8964
+ continue;
8928
8965
  const [a, b] = lineEndpoints(el);
8929
8966
  if ((world.x - a.x) ** 2 + (world.y - a.y) ** 2 <= r2) return { elementId: id, fixed: b };
8930
8967
  if ((world.x - b.x) ** 2 + (world.y - b.y) ** 2 <= r2) return { elementId: id, fixed: a };
@@ -9358,10 +9395,10 @@ var SelectTool = class {
9358
9395
  if (this.mode.type === "line-handle") {
9359
9396
  ctx.setCursor?.("grabbing");
9360
9397
  const el = ctx.store.getById(this.mode.elementId);
9361
- if (el && el.type === "shape") {
9398
+ if (el && el.type === "shape" && el.shape === "line" && !el.locked && !(ctx.isLayerLocked?.(el.layerId) ?? false)) {
9362
9399
  ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));
9400
+ ctx.requestRender();
9363
9401
  }
9364
- ctx.requestRender();
9365
9402
  return;
9366
9403
  }
9367
9404
  if (this.mode.type === "resizing-template") {
@@ -9519,7 +9556,8 @@ var SelectTool = class {
9519
9556
  renderSelectionBoxes(canvasCtx, {
9520
9557
  selectedIds: this._selectedIds,
9521
9558
  store: this.ctx.store,
9522
- zoom: this.ctx.camera.zoom
9559
+ zoom: this.ctx.camera.zoom,
9560
+ isLayerLocked: this.ctx.isLayerLocked
9523
9561
  });
9524
9562
  if (this.mode.type === "arrow-handle" && this.ctx) {
9525
9563
  const target = getArrowHandleDragTarget(
@@ -10676,7 +10714,7 @@ var LaserTool = class {
10676
10714
  };
10677
10715
 
10678
10716
  // src/index.ts
10679
- var VERSION = "0.50.2";
10717
+ var VERSION = "0.50.4";
10680
10718
  // Annotate the CommonJS export names for ESM import in node:
10681
10719
  0 && (module.exports = {
10682
10720
  ArrowTool,