@weasel-js/core 1.3.0 → 1.4.0-pre.1

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.
@@ -1,7 +1,7 @@
1
- import { ActionDisabledReason, useOptionalDepRegistry, DepRegistryProvider, useActionsRegistry, ActionsProvider, useDepRegistry, reportRouteConflicts, buildDepsFromRequires, useDepSource, actionBindings } from './chunk-3ZV53ZW2.js';
2
- import { scratchKey, createTransformOp, snap, getScratch, createReparentOp, setScratch } from './chunk-AQS4JGRA.js';
3
- import { fixedCornerOf, DEFAULT_RESIZE_BEHAVIORS, CORNER_ANCHORS, cornerPoint } from './chunk-3FB44DBC.js';
4
- import { AUTO_POSE_DESCRIPTOR, resolveUnit, polygonFromPoints, starPath, regularPolygonPath, linePath, ellipsePath, rectPath, PATH_M, PATH_L, PATH_Z, RECT_POSE_DESCRIPTOR, pathPoseDescriptor, withinPxRadius, boundsOfPath, PATH_Q, PATH_C, DEFAULT_FLATTEN_TOLERANCE, flattenQuadratic, flattenCubic, PathBuilder, pointInPath, strokeHitTest, transformPath, translatePath, pxExtent, remapRotatedLeaf, withinPxBox, flattenCubicWithArcLen, flattenQuadraticWithArcLen, PATH_CMD_LENGTHS, pointToGridCell } from './chunk-F74NVEHT.js';
1
+ import { ActionDisabledReason, useOptionalDepRegistry, DepRegistryProvider, useActionsRegistry, ActionsProvider, useDepRegistry, reportRouteConflicts, buildDepsFromRequires, useDepSource, actionBindings } from './chunk-H6E6KPTU.js';
2
+ import { scratchKey, createTransformOp, snap, getScratch, createReparentOp, setScratch } from './chunk-Y5KS66G7.js';
3
+ import { fixedCornerOf, DEFAULT_RESIZE_BEHAVIORS, CORNER_ANCHORS, cornerPoint } from './chunk-BLJNRMKB.js';
4
+ import { AUTO_POSE_DESCRIPTOR, resolveUnit, polylineFromPoints, starPath, regularPolygonPath, linePath, ellipsePath, rectPath, polygonFromPoints, PATH_M, PATH_L, PATH_Z, RECT_POSE_DESCRIPTOR, pathPoseDescriptor, withinPxRadius, boundsOfPath, PATH_Q, PATH_C, DEFAULT_FLATTEN_TOLERANCE, flattenQuadratic, flattenCubic, PathBuilder, pointInPath, strokeHitTest, transformPath, translatePath, pxExtent, remapRotatedLeaf, withinPxBox, flattenCubicWithArcLen, flattenQuadraticWithArcLen, PATH_CMD_LENGTHS, pointToGridCell } from './chunk-SBFC6J3C.js';
5
5
  import { dispatchApplyBatch, dlog, dwarn, usePointerContext, PointerContextProvider, applyOpsTo, extractWeaselClipboardFromSvg, parseWeaselClipboardText, materializePaste, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, sniffWeaselClipboardText } from './chunk-67KE7SDP.js';
6
6
  import { createSetSelectionOp } from './chunk-ZB7UYJVG.js';
7
7
  import { registerOpFactory, createDeleteOp, createInsertOp, rebuildOp } from './chunk-2KKYDDDD.js';
@@ -14,16 +14,17 @@ export { DEFAULT_TEXT_STYLE, MARKDOWN_RUN_GRAMMAR, SCRIPT_METRICS, cachedLayoutR
14
14
  import earcut from 'earcut';
15
15
  import { dashForStrokeStyle, strokeDashStyleOf, alignedStrokeRect } from '@weasel-js/paint';
16
16
  export { STROKE_DASH_RATIOS, alignedStrokeRect, dashForStrokeStyle, strokeDashStyleOf } from '@weasel-js/paint';
17
- import { applyToPoint, rotateAboutPoint, boxToBox, pointInPolygon, segmentsCross, forEachSegment, pathCommandCoordCount, multiply as multiply$1, invert as invert$1, pointSegmentDist2 } from '@weasel-js/geom';
17
+ import { clampRectWithin, applyToPoint, rotateAboutPoint, boxToBox, pointInPolygon, segmentsCross, forEachSegment, pathCommandCoordCount, multiply as multiply$1, invert as invert$1, pointSegmentDist2 } from '@weasel-js/geom';
18
18
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
19
19
  import polygonClipping from 'polygon-clipping';
20
20
  import { matchSpec, RESERVED_ID_PREFIXES, RESERVED_ID_NAMES, parseTargetSpec, mimeMatchesGlob } from '@weasel-js/gestures';
21
21
  import { NORMAL, IMPLICIT_TAGS } from '@weasel-js/modes';
22
+ import { cursorFor } from '@weasel-js/cursor';
22
23
  import { createHistory } from '@weasel-js/history';
23
24
  export * from '@weasel-js/history';
24
25
 
25
26
  // src/version.ts
26
- var VERSION = "1.3.0" ;
27
+ var VERSION = "1.4.0-pre.1" ;
27
28
 
28
29
  // src/features/grid/roundToCell.ts
29
30
  function roundToCell(value, cellSize) {
@@ -1539,6 +1540,9 @@ function flattenPolygon(p, tolerance) {
1539
1540
  let coordIdx = 0;
1540
1541
  let prevX = 0;
1541
1542
  let prevY = 0;
1543
+ let startX = 0;
1544
+ let startY = 0;
1545
+ let startAnchor = -1;
1542
1546
  let prevAnchor = -1;
1543
1547
  let anchorCounter = 0;
1544
1548
  for (let cmdIdx = 0; cmdIdx < commands.length; cmdIdx++) {
@@ -1548,6 +1552,9 @@ function flattenPolygon(p, tolerance) {
1548
1552
  contourStarts.push(out.length / 2);
1549
1553
  prevX = coords[coordIdx];
1550
1554
  prevY = coords[coordIdx + 1];
1555
+ startX = prevX;
1556
+ startY = prevY;
1557
+ startAnchor = anchorCounter;
1551
1558
  out.push(prevX, prevY);
1552
1559
  anchorA.push(anchorCounter);
1553
1560
  anchorB.push(anchorCounter);
@@ -1617,6 +1624,9 @@ function flattenPolygon(p, tolerance) {
1617
1624
  break;
1618
1625
  }
1619
1626
  case PATH_Z: {
1627
+ prevX = startX;
1628
+ prevY = startY;
1629
+ prevAnchor = startAnchor;
1620
1630
  break;
1621
1631
  }
1622
1632
  default:
@@ -4489,6 +4499,7 @@ var WeaselRenderer = class {
4489
4499
  heightCss;
4490
4500
  dpr;
4491
4501
  canvas = null;
4502
+ target = null;
4492
4503
  imageMinification;
4493
4504
  flattenTolerance;
4494
4505
  bakeBudget;
@@ -4506,6 +4517,12 @@ var WeaselRenderer = class {
4506
4517
  const gl = opts.gl ?? opts.canvas.getContext("webgl2", { stencil: true });
4507
4518
  if (!gl) throw new Error("WeaselRenderer: WebGL2 not available");
4508
4519
  this.gl = gl;
4520
+ const attrs = typeof this.gl.getContextAttributes === "function" ? this.gl.getContextAttributes() : null;
4521
+ if (attrs && attrs.stencil === false) {
4522
+ throw new Error(
4523
+ "WeaselRenderer: the supplied WebGL2 context has no stencil buffer. Create it with { stencil: true } \u2014 clips and even-odd fills need one."
4524
+ );
4525
+ }
4509
4526
  this.widthCss = opts.width;
4510
4527
  this.heightCss = opts.height;
4511
4528
  this.dpr = opts.dpr;
@@ -4524,12 +4541,8 @@ var WeaselRenderer = class {
4524
4541
  this.canvas.addEventListener("webglcontextlost", this.boundOnLost);
4525
4542
  this.canvas.addEventListener("webglcontextrestored", this.boundOnRestored);
4526
4543
  }
4527
- this.gl.enable(this.gl.BLEND);
4528
- this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
4529
- this.gl.disable(this.gl.DEPTH_TEST);
4530
- this.gl.disable(this.gl.CULL_FACE);
4531
- this.gl.clearColor(0, 0, 0, 0);
4532
- this.applyViewport();
4544
+ this.applyGlState();
4545
+ this.applyTarget();
4533
4546
  this.pathFill = new ShaderProgram(this.gl, VERT_SRC, FRAG_SRC);
4534
4547
  this.pathFill.lookupUniforms(PATH_FILL_UNIFORMS);
4535
4548
  this.pathFill.lookupAttributes(PATH_FILL_ATTRIBUTES);
@@ -4619,8 +4632,42 @@ var WeaselRenderer = class {
4619
4632
  }
4620
4633
  return this.programRegistry.get(id) ?? null;
4621
4634
  }
4622
- applyViewport() {
4623
- this.gl.viewport(0, 0, this.widthCss * this.dpr, this.heightCss * this.dpr);
4635
+ /** The GL state every frame assumes. Applied per `render()` rather than once
4636
+ * at construction because a co-tenant sharing this context moves all of it
4637
+ * between our frames. */
4638
+ applyGlState() {
4639
+ const gl = this.gl;
4640
+ gl.enable(gl.BLEND);
4641
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
4642
+ gl.disable(gl.DEPTH_TEST);
4643
+ gl.disable(gl.CULL_FACE);
4644
+ gl.clearColor(0, 0, 0, 0);
4645
+ }
4646
+ /** Viewport and scissor for this frame. Re-applied inside `render()` because
4647
+ * a co-tenant on the same context moves both between our frames. */
4648
+ applyTarget() {
4649
+ const gl = this.gl;
4650
+ const w = Math.round(this.widthCss * this.dpr);
4651
+ const h = Math.round(this.heightCss * this.dpr);
4652
+ if (!this.target) {
4653
+ gl.disable(gl.SCISSOR_TEST);
4654
+ gl.viewport(0, 0, w, h);
4655
+ return;
4656
+ }
4657
+ const x = Math.round(this.target.origin.x * this.dpr);
4658
+ const y = gl.drawingBufferHeight - Math.round(this.target.origin.y * this.dpr) - h;
4659
+ gl.viewport(x, y, w, h);
4660
+ gl.scissor(x, y, w, h);
4661
+ gl.enable(gl.SCISSOR_TEST);
4662
+ }
4663
+ /** Confine this renderer to a rect of its drawing buffer, or pass null to
4664
+ * give it the whole buffer back. Takes effect from the next `render()`. */
4665
+ setTarget(target) {
4666
+ this.target = target;
4667
+ this.applyTarget();
4668
+ }
4669
+ getTarget() {
4670
+ return this.target;
4624
4671
  }
4625
4672
  isContextLost() {
4626
4673
  return this.contextLost;
@@ -4631,12 +4678,8 @@ var WeaselRenderer = class {
4631
4678
  }
4632
4679
  onContextRestored() {
4633
4680
  this.contextLost = false;
4634
- this.gl.enable(this.gl.BLEND);
4635
- this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
4636
- this.gl.disable(this.gl.DEPTH_TEST);
4637
- this.gl.disable(this.gl.CULL_FACE);
4638
- this.gl.clearColor(0, 0, 0, 0);
4639
- this.applyViewport();
4681
+ this.applyGlState();
4682
+ this.applyTarget();
4640
4683
  this.pathFill = new ShaderProgram(this.gl, VERT_SRC, FRAG_SRC);
4641
4684
  this.pathFill.lookupUniforms(PATH_FILL_UNIFORMS);
4642
4685
  this.pathFill.lookupAttributes(PATH_FILL_ATTRIBUTES);
@@ -4744,8 +4787,12 @@ var WeaselRenderer = class {
4744
4787
  this.meshCache.drainPendingDeletes();
4745
4788
  resetBakeBudget(this.bakeBudget);
4746
4789
  this.groupState.reset();
4747
- gl.stencilMask(255);
4748
- gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
4790
+ this.applyGlState();
4791
+ this.applyTarget();
4792
+ if (this.target?.clear !== false) {
4793
+ gl.stencilMask(255);
4794
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
4795
+ }
4749
4796
  const ctx = {
4750
4797
  gl,
4751
4798
  pathFill: this.pathFill,
@@ -4788,7 +4835,7 @@ var WeaselRenderer = class {
4788
4835
  this.canvas.style.height = `${dims.height}px`;
4789
4836
  }
4790
4837
  }
4791
- this.applyViewport();
4838
+ this.applyTarget();
4792
4839
  }
4793
4840
  /** @internal */
4794
4841
  _gl() {
@@ -5191,13 +5238,13 @@ function deriveParallaxView(outer, opts) {
5191
5238
 
5192
5239
  // src/features/parallax/createParallaxLayer.ts
5193
5240
  function createParallaxLayer(opts) {
5194
- const { id, label, source, pan, zoom, anchor } = opts;
5241
+ const { id, label, source, pan, zoom, anchor, getOuterView } = opts;
5195
5242
  return {
5196
5243
  id,
5197
5244
  label,
5198
5245
  space: "screen",
5199
5246
  draw: (data, outer, dims) => {
5200
- const inner = deriveParallaxView(outer, { pan, zoom, anchor });
5247
+ const inner = deriveParallaxView(getOuterView?.() ?? outer, { pan, zoom, anchor });
5201
5248
  return source.flatMap((layer) => layer.draw(data, inner, dims));
5202
5249
  }
5203
5250
  };
@@ -6160,11 +6207,13 @@ function fitToBounds(viewportW, viewportH, contentW, contentH, paddingPx = 0, cl
6160
6207
  };
6161
6208
  }
6162
6209
 
6210
+ // src/core/viewport/zoomBounds.ts
6211
+ var DEFAULT_MIN_ZOOM = 0.1;
6212
+ var DEFAULT_MAX_ZOOM = 8;
6213
+
6163
6214
  // src/core/viewport/fitViewToBounds.ts
6164
- var SYSTEM_MAX_SCALE = 10;
6165
- var SYSTEM_MIN_SCALE = 0.1;
6166
6215
  function fitViewToBounds(bounds, viewportDims, currentView, opts = {}) {
6167
- const { padding = 16, maxScale = SYSTEM_MAX_SCALE, minScale = SYSTEM_MIN_SCALE } = opts;
6216
+ const { padding = 16, maxScale = DEFAULT_MAX_ZOOM, minScale = DEFAULT_MIN_ZOOM } = opts;
6168
6217
  if (bounds.width <= 0 || bounds.height <= 0) {
6169
6218
  console.warn("[weasel] fitViewToBounds: bounds has zero or negative area; returning currentView unchanged.", bounds);
6170
6219
  return currentView;
@@ -6210,15 +6259,19 @@ function fitViewToBounds(bounds, viewportDims, currentView, opts = {}) {
6210
6259
  }
6211
6260
 
6212
6261
  // src/core/viewport/zoomAt.ts
6262
+ function clampScale(scale2, min, max) {
6263
+ const magnitude = Math.min(max, Math.max(min, Math.abs(scale2)));
6264
+ return scale2 < 0 ? -magnitude : magnitude;
6265
+ }
6213
6266
  function zoomAt(view, anchor, factor, opts) {
6214
6267
  const fx = typeof factor === "number" ? factor : factor.x;
6215
6268
  const fy = typeof factor === "number" ? factor : factor.y;
6216
- const minX = typeof opts?.min === "number" ? opts.min : opts?.min?.x ?? 0.1;
6217
- const minY = typeof opts?.min === "number" ? opts.min : opts?.min?.y ?? 0.1;
6218
- const maxX = typeof opts?.max === "number" ? opts.max : opts?.max?.x ?? 8;
6219
- const maxY = typeof opts?.max === "number" ? opts.max : opts?.max?.y ?? 8;
6220
- const nextX = Math.min(maxX, Math.max(minX, view.scale.x * fx));
6221
- const nextY = Math.min(maxY, Math.max(minY, view.scale.y * fy));
6269
+ const minX = typeof opts?.min === "number" ? opts.min : opts?.min?.x ?? DEFAULT_MIN_ZOOM;
6270
+ const minY = typeof opts?.min === "number" ? opts.min : opts?.min?.y ?? DEFAULT_MIN_ZOOM;
6271
+ const maxX = typeof opts?.max === "number" ? opts.max : opts?.max?.x ?? DEFAULT_MAX_ZOOM;
6272
+ const maxY = typeof opts?.max === "number" ? opts.max : opts?.max?.y ?? DEFAULT_MAX_ZOOM;
6273
+ const nextX = clampScale(view.scale.x * fx, minX, maxX);
6274
+ const nextY = clampScale(view.scale.y * fy, minY, maxY);
6222
6275
  const worldX = anchor.x / view.scale.x + view.x;
6223
6276
  const worldY = anchor.y / view.scale.y + view.y;
6224
6277
  return {
@@ -6230,22 +6283,24 @@ function zoomAt(view, anchor, factor, opts) {
6230
6283
 
6231
6284
  // src/core/viewport/clampView.ts
6232
6285
  function clampView(view, bounds, canvas) {
6233
- const visW = canvas.width / view.scale.x;
6234
- const visH = canvas.height / view.scale.y;
6286
+ const visW = Math.abs(canvas.width / view.scale.x);
6287
+ const visH = Math.abs(canvas.height / view.scale.y);
6288
+ const flipX = view.scale.x < 0;
6289
+ const flipY = view.scale.y < 0;
6235
6290
  let x;
6236
6291
  if (visW >= bounds.width) {
6237
- x = bounds.x + (bounds.width - visW) / 2;
6292
+ x = bounds.x + (bounds.width - visW) / 2 + (flipX ? visW : 0);
6238
6293
  } else {
6239
- const minX = bounds.x;
6240
- const maxX = bounds.x + bounds.width - visW;
6294
+ const minX = flipX ? bounds.x + visW : bounds.x;
6295
+ const maxX = flipX ? bounds.x + bounds.width : bounds.x + bounds.width - visW;
6241
6296
  x = view.x < minX ? minX : view.x > maxX ? maxX : view.x;
6242
6297
  }
6243
6298
  let y;
6244
6299
  if (visH >= bounds.height) {
6245
- y = bounds.y + (bounds.height - visH) / 2;
6300
+ y = bounds.y + (bounds.height - visH) / 2 + (flipY ? visH : 0);
6246
6301
  } else {
6247
- const minY = bounds.y;
6248
- const maxY = bounds.y + bounds.height - visH;
6302
+ const minY = flipY ? bounds.y + visH : bounds.y;
6303
+ const maxY = flipY ? bounds.y + bounds.height : bounds.y + bounds.height - visH;
6249
6304
  y = view.y < minY ? minY : view.y > maxY ? maxY : view.y;
6250
6305
  }
6251
6306
  return x === view.x && y === view.y ? view : { x, y, scale: view.scale };
@@ -6274,8 +6329,8 @@ function isEditableTarget(t) {
6274
6329
  return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT";
6275
6330
  }
6276
6331
  function useZoom(opts) {
6277
- const min = opts.min ?? 0.1;
6278
- const max = opts.max ?? 10;
6332
+ const min = opts.min ?? DEFAULT_MIN_ZOOM;
6333
+ const max = opts.max ?? DEFAULT_MAX_ZOOM;
6279
6334
  const wheelStep = opts.wheelStep ?? 1.1;
6280
6335
  const keyStep = opts.keyStep ?? 1.25;
6281
6336
  const sources = useMemo(
@@ -8208,7 +8263,7 @@ function keyAnchor(view) {
8208
8263
  }
8209
8264
  var WHEEL_STEP = 1.1;
8210
8265
  function makeViewportZoomAction(opts = {}) {
8211
- const clamp2 = { min: opts.min ?? 0.1, max: opts.max ?? 8 };
8266
+ const clamp2 = { min: opts.min ?? DEFAULT_MIN_ZOOM, max: opts.max ?? DEFAULT_MAX_ZOOM };
8212
8267
  const wheelSpec = opts.wheel === "plain" ? { kind: "wheel" } : { kind: "wheel", mods: { mod: true } };
8213
8268
  const rawAnimate = opts.animate === true ? {} : opts.animate || null;
8214
8269
  const { resetMs, ...animateRest } = rawAnimate ?? {};
@@ -8928,7 +8983,7 @@ var sliceAction = {
8928
8983
 
8929
8984
  // src/interactions/actions/defaults/pinchZoom.ts
8930
8985
  function makePinchZoomAction(opts = {}) {
8931
- const clamp2 = { min: opts.min ?? 0.1, max: opts.max ?? 8 };
8986
+ const clamp2 = { min: opts.min ?? DEFAULT_MIN_ZOOM, max: opts.max ?? DEFAULT_MAX_ZOOM };
8932
8987
  return {
8933
8988
  id: "viewport.pinchZoom",
8934
8989
  label: "Pinch Zoom",
@@ -13670,8 +13725,6 @@ function useGestureDispatcher(opts) {
13670
13725
  }
13671
13726
 
13672
13727
  // src/core/viewport/wheelHandler.ts
13673
- var DEFAULT_MIN_ZOOM = 0.1;
13674
- var DEFAULT_MAX_ZOOM = 10;
13675
13728
  function computeWheelAction(state, input, bounds = { min: DEFAULT_MIN_ZOOM, max: DEFAULT_MAX_ZOOM }) {
13676
13729
  if (input.shiftKey) {
13677
13730
  return {
@@ -14036,6 +14089,76 @@ var SPRING_PRESETS = {
14036
14089
  slow: { stiffness: 80, damping: 20, mass: 1 }
14037
14090
  };
14038
14091
 
14092
+ // src/animation/easingSpec.ts
14093
+ var NEWTON_ITERATIONS = 8;
14094
+ var NEWTON_MIN_SLOPE = 1e-3;
14095
+ var SUBDIVISION_EPSILON = 1e-7;
14096
+ var SUBDIVISION_MAX = 12;
14097
+ function bezierAt(t, a1, a2) {
14098
+ const c = 3 * a1;
14099
+ const b = 3 * (a2 - a1) - c;
14100
+ const a = 1 - c - b;
14101
+ return ((a * t + b) * t + c) * t;
14102
+ }
14103
+ function bezierSlope(t, a1, a2) {
14104
+ const c = 3 * a1;
14105
+ const b = 3 * (a2 - a1) - c;
14106
+ const a = 1 - c - b;
14107
+ return (3 * a * t + 2 * b) * t + c;
14108
+ }
14109
+ function solveForX(x, x1, x2) {
14110
+ let t = x;
14111
+ for (let i = 0; i < NEWTON_ITERATIONS; i++) {
14112
+ const slope = bezierSlope(t, x1, x2);
14113
+ if (slope < NEWTON_MIN_SLOPE) break;
14114
+ t -= (bezierAt(t, x1, x2) - x) / slope;
14115
+ }
14116
+ let lo = 0;
14117
+ let hi = 1;
14118
+ t = Math.min(1, Math.max(0, t));
14119
+ for (let i = 0; i < SUBDIVISION_MAX; i++) {
14120
+ const err = bezierAt(t, x1, x2) - x;
14121
+ if (Math.abs(err) < SUBDIVISION_EPSILON) return t;
14122
+ if (err > 0) hi = t;
14123
+ else lo = t;
14124
+ t = (lo + hi) / 2;
14125
+ }
14126
+ return t;
14127
+ }
14128
+ function cubicBezierEasing(x1, y1, x2, y2) {
14129
+ const cx1 = Math.min(1, Math.max(0, x1));
14130
+ const cx2 = Math.min(1, Math.max(0, x2));
14131
+ return (t) => {
14132
+ if (t <= 0) return 0;
14133
+ if (t >= 1) return 1;
14134
+ return bezierAt(solveForX(t, cx1, cx2), y1, y2);
14135
+ };
14136
+ }
14137
+ var bezierCache = /* @__PURE__ */ new Map();
14138
+ function isBezier(spec) {
14139
+ return typeof spec === "object" && spec !== null && "bezier" in spec;
14140
+ }
14141
+ function resolveEasing(spec) {
14142
+ if (spec === void 0) return EASINGS.linear;
14143
+ if (typeof spec === "function") return spec;
14144
+ if (typeof spec === "string") {
14145
+ const fn = EASINGS[spec];
14146
+ if (!fn) throw new Error(`resolveEasing: unknown easing name "${spec}"`);
14147
+ return fn;
14148
+ }
14149
+ if (isBezier(spec)) {
14150
+ const [x1, y1, x2, y2] = spec.bezier;
14151
+ const key = `${x1},${y1},${x2},${y2}`;
14152
+ let fn = bezierCache.get(key);
14153
+ if (!fn) {
14154
+ fn = cubicBezierEasing(x1, y1, x2, y2);
14155
+ bezierCache.set(key, fn);
14156
+ }
14157
+ return fn;
14158
+ }
14159
+ throw new Error("resolveEasing: unrecognized easing spec");
14160
+ }
14161
+
14039
14162
  // src/animation/loop.ts
14040
14163
  function createLoop(createSupervisor, factory, opts = {}) {
14041
14164
  const max = opts.count ?? Infinity;
@@ -14076,6 +14199,7 @@ function createLoop(createSupervisor, factory, opts = {}) {
14076
14199
  supervisor.setTimeScale(s);
14077
14200
  current?.setTimeScale(s);
14078
14201
  },
14202
+ timeScale: () => supervisor.timeScale(),
14079
14203
  isPaused: () => supervisor.isPaused()
14080
14204
  };
14081
14205
  }
@@ -14260,6 +14384,9 @@ var CompositeHandle = class {
14260
14384
  this.timeScale_ = s;
14261
14385
  for (const c of this.children) c.setTimeScale(s);
14262
14386
  }
14387
+ timeScale() {
14388
+ return this.timeScale_;
14389
+ }
14263
14390
  isPaused() {
14264
14391
  return this.paused_;
14265
14392
  }
@@ -14369,7 +14496,7 @@ function sampleTrack(track, t, segmentCache) {
14369
14496
  const b = keys[i + 1];
14370
14497
  const span = b.t - a.t;
14371
14498
  const raw = span <= 0 ? 1 : (t - a.t) / span;
14372
- const u = b.easing ? b.easing(raw) : raw;
14499
+ const u = b.easing ? resolveEasing(b.easing)(raw) : raw;
14373
14500
  if (track.interpolator) {
14374
14501
  let fn = segmentCache?.get(i + 1);
14375
14502
  if (!fn) {
@@ -14450,7 +14577,10 @@ function createTimeline(register, id, opts) {
14450
14577
  for (const track of tracks) {
14451
14578
  if (track.kind === "event") {
14452
14579
  const end = firstAfter(track.events, to);
14453
- for (let i = firstAfter(track.events, from); i < end; i += 1) track.events[i].fire();
14580
+ for (let i = firstAfter(track.events, from); i < end; i += 1) {
14581
+ const ev = track.events[i];
14582
+ ev.fire(to - ev.t);
14583
+ }
14454
14584
  } else if (track.kind === "timeline") {
14455
14585
  fireEvents(track.timeline.tracks, from - track.at, to - track.at);
14456
14586
  }
@@ -14530,6 +14660,7 @@ function createTimeline(register, id, opts) {
14530
14660
  wantScale = s;
14531
14661
  base.setTimeScale(s);
14532
14662
  },
14663
+ timeScale: () => live ? base.timeScale() : wantScale,
14533
14664
  isPaused: () => live ? base.isPaused() : wantPaused,
14534
14665
  seek(t) {
14535
14666
  offset = t - lastVirtual;
@@ -14540,6 +14671,10 @@ function createTimeline(register, id, opts) {
14540
14671
  time: () => playhead,
14541
14672
  duration: () => duration,
14542
14673
  tracks: () => opts.tracks,
14674
+ setLoop(loop) {
14675
+ loopsLeft = loop === true ? Infinity : loop === false ? 0 : loop;
14676
+ },
14677
+ loop: () => loopsLeft === Infinity ? true : loopsLeft === 0 ? false : loopsLeft,
14543
14678
  edit(fn) {
14544
14679
  fn();
14545
14680
  caches = /* @__PURE__ */ new WeakMap();
@@ -14758,6 +14893,7 @@ function useAnimator(opts = {}) {
14758
14893
  const a = animations.current.get(anim.id);
14759
14894
  if (a) a.timeScale = s;
14760
14895
  },
14896
+ timeScale: () => animations.current.get(anim.id)?.timeScale ?? 1,
14761
14897
  isPaused: () => animations.current.get(anim.id)?.paused ?? false
14762
14898
  };
14763
14899
  };
@@ -14779,6 +14915,7 @@ function useAnimator(opts = {}) {
14779
14915
  pause: base.pause,
14780
14916
  resume: base.resume,
14781
14917
  setTimeScale: base.setTimeScale,
14918
+ timeScale: base.timeScale,
14782
14919
  isPaused: base.isPaused,
14783
14920
  setOnCancel: (cb) => {
14784
14921
  onCancelCb = cb;
@@ -14789,7 +14926,7 @@ function useAnimator(opts = {}) {
14789
14926
  const tween = (o) => {
14790
14927
  const id = nextId.current++;
14791
14928
  const start = 0;
14792
- const easing = o.easing ?? easeOut;
14929
+ const easing = resolveEasing(o.easing ?? easeOut);
14793
14930
  const factoryFn = o.interpolator ? o.interpolator(o.from, o.to) : null;
14794
14931
  const perTickInterp = factoryFn ? null : o.interpolate ?? ((a, b, t) => {
14795
14932
  if (typeof a === "number" && typeof b === "number") {
@@ -14944,6 +15081,7 @@ function useAnimator(opts = {}) {
14944
15081
  setTimeScale: (s) => {
14945
15082
  globalTimeScale.current = s;
14946
15083
  },
15084
+ timeScale: () => globalTimeScale.current,
14947
15085
  pauseKey: (key) => {
14948
15086
  for (const a of animations.current.values()) if (a.cancelKey === key) a.paused = true;
14949
15087
  },
@@ -15601,6 +15739,21 @@ function LineIcon({ className, size = 20 }) {
15601
15739
  }
15602
15740
  );
15603
15741
  }
15742
+ function ArrowIcon({ className, size = 20 }) {
15743
+ return /* @__PURE__ */ jsxs(
15744
+ "svg",
15745
+ {
15746
+ ...ICON_SVG_BASE,
15747
+ className,
15748
+ width: size,
15749
+ height: size,
15750
+ children: [
15751
+ /* @__PURE__ */ jsx("path", { d: "M3.5 16.5 12.9 7.1", strokeLinecap: "round" }),
15752
+ /* @__PURE__ */ jsx("path", { d: "M16.5 3.5 11.06 5.98 14.03 8.95Z", fill: "currentColor", strokeLinejoin: "round" })
15753
+ ]
15754
+ }
15755
+ );
15756
+ }
15604
15757
  function PolygonIcon({ className, size = 20 }) {
15605
15758
  return /* @__PURE__ */ jsx(
15606
15759
  "svg",
@@ -16274,6 +16427,14 @@ var TEXT_PAINTER = {
16274
16427
  );
16275
16428
  if (boxes.length === 0) return null;
16276
16429
  return rectsToPath(boxes);
16430
+ },
16431
+ // `filled` is unconditional: a text node's `data.fill: null` still resolves
16432
+ // to the default in `ResolvedRun`, so there is no outline-only text to
16433
+ // report. The reach is the point — a heavily outlined glyph was unpickable
16434
+ // across the width of its own outline.
16435
+ ink: (node, _pose, ctx) => {
16436
+ const d = node.data;
16437
+ return { filled: true, ...inkReach(resolveNodeStroke(d.stroke), ctx?.scale) };
16277
16438
  }
16278
16439
  };
16279
16440
  function rectsToPath(rects) {
@@ -16539,10 +16700,10 @@ var RECT_FALLBACK_PAINTER = {
16539
16700
  };
16540
16701
  function registerBuiltInShapePainters() {
16541
16702
  registerNodeShape(TEXT_PAINTER);
16703
+ registerNodeShape(DERIVED_PAINTER);
16542
16704
  registerNodeShape(PATH_PAINTER);
16543
16705
  registerNodeShape(SHAPE_PAINTER);
16544
16706
  registerNodeShape(IMAGE_PAINTER);
16545
- registerNodeShape(DERIVED_PAINTER);
16546
16707
  registerNodeShape(RECT_FALLBACK_PAINTER);
16547
16708
  }
16548
16709
  registerBuiltInShapePainters();
@@ -17571,11 +17732,7 @@ function useRotateTool(adapter, options) {
17571
17732
  [overlay]
17572
17733
  );
17573
17734
  }
17574
- function useHandTool(opts = {}) {
17575
- const inertia = opts.inertia === false ? false : opts.inertia;
17576
- const axis = opts.axis ?? "both";
17577
- const tracker = useVelocityTracker();
17578
- const decay = useDecayLoop();
17735
+ function useHandTool(_opts = {}) {
17579
17736
  return useMemo(
17580
17737
  () => Object.assign(defineViewportTool({
17581
17738
  id: "hand",
@@ -17595,8 +17752,7 @@ function useHandTool(opts = {}) {
17595
17752
  // phase entry.
17596
17753
  bindings: [{ spec: { kind: "drag" }, actionId: "viewport.dragPan" }]
17597
17754
  }),
17598
- // eslint-disable-next-line react-hooks/exhaustive-deps
17599
- [inertia, axis, tracker, decay]
17755
+ []
17600
17756
  );
17601
17757
  }
17602
17758
  var PRESENTATION = {
@@ -17625,7 +17781,7 @@ function usePinchZoomTool(canvasRef, getView, setView, opts = {}) {
17625
17781
  getViewRef.current = getView;
17626
17782
  const setViewRef = useRef(setView);
17627
17783
  setViewRef.current = setView;
17628
- const { min = 0.1, max = 8, enabled = true } = opts;
17784
+ const { min = DEFAULT_MIN_ZOOM, max = DEFAULT_MAX_ZOOM, enabled = true } = opts;
17629
17785
  const resolveTargetRef = useRef(opts.resolveTarget);
17630
17786
  resolveTargetRef.current = opts.resolveTarget;
17631
17787
  usePinchGesture(canvasRef, (clientAnchor, scaleFactor) => {
@@ -17653,8 +17809,6 @@ function constrainTo45(dx, dy) {
17653
17809
  const snapped = Math.round(angle / step) * step;
17654
17810
  return { dx: Math.cos(snapped) * mag, dy: Math.sin(snapped) * mag };
17655
17811
  }
17656
-
17657
- // src/tools/builtin/pen/usePenTool.ts
17658
17812
  function freshScratch() {
17659
17813
  return {
17660
17814
  finishedSubpaths: [],
@@ -17893,7 +18047,7 @@ function usePenTool(options) {
17893
18047
  hookName: "usePenTool",
17894
18048
  // Reads the tool's own ref rather than a scratch handed in by a
17895
18049
  // dispatcher — the pen owns this state and nothing else needs it.
17896
- cursor: () => scratchRef.current?.closeHintActive ? "pointer" : "crosshair",
18050
+ cursor: () => scratchRef.current?.closeHintActive ? "pointer" : cursorFor("pen", { fallback: "crosshair" }),
17897
18051
  presentation: {
17898
18052
  label: "Pen",
17899
18053
  icon: createElement(PenIcon),
@@ -18069,7 +18223,7 @@ function useEyedropperTool(opts) {
18069
18223
  hookName: "useEyedropperTool",
18070
18224
  keybinding,
18071
18225
  hotkey,
18072
- cursor: "crosshair",
18226
+ cursor: cursorFor("eyedropper", { fallback: "crosshair" }),
18073
18227
  presentation: {
18074
18228
  label: "Eyedropper",
18075
18229
  icon: createElement(EyedropperIcon),
@@ -18367,7 +18521,7 @@ function usePencilTool() {
18367
18521
  id: "pencil",
18368
18522
  capabilities: ["creates-paths"],
18369
18523
  hookName: "usePencilTool",
18370
- cursor: "crosshair",
18524
+ cursor: cursorFor("pencil", { fallback: "crosshair" }),
18371
18525
  presentation: {
18372
18526
  label: "Pencil",
18373
18527
  group: "draw",
@@ -19466,14 +19620,91 @@ function wrapNodeOutput(cmds, pose, alpha) {
19466
19620
  }
19467
19621
  return rotated;
19468
19622
  }
19469
- function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19623
+ function insetAlong(start, extent, size, align, by) {
19624
+ if (align === "start") return start + by;
19625
+ if (align === "end") return start + extent - size - by;
19626
+ return start + (extent - size) / 2 + by;
19627
+ }
19628
+ function hostAnchorRect(input) {
19629
+ const { host, panel, viewport, align, offset, padding = 0 } = input;
19630
+ const desired = {
19631
+ x: insetAlong(host.x, host.width, panel.width, align.x, offset.x),
19632
+ y: insetAlong(host.y, host.height, panel.height, align.y, offset.y),
19633
+ width: panel.width,
19634
+ height: panel.height
19635
+ };
19636
+ return clampRectWithin(desired, { x: 0, y: 0, width: viewport.width, height: viewport.height }, padding);
19637
+ }
19638
+ function hostAnchorCss(rect, align, viewport) {
19639
+ return {
19640
+ ...align.y === "end" ? { bottom: viewport.height - rect.y - rect.height } : { top: rect.y },
19641
+ ...align.x === "end" ? { right: viewport.width - rect.x - rect.width } : { left: rect.x }
19642
+ };
19643
+ }
19644
+
19645
+ // src/canvas/useHostAnchor.ts
19646
+ function useHostAnchor(resolveHost, options) {
19647
+ const [panel, setPanel] = useState(null);
19648
+ const [style, setStyle] = useState(null);
19649
+ const ref = useCallback((el) => setPanel(el), []);
19650
+ const resolve = useRef(resolveHost);
19651
+ resolve.current = resolveHost;
19652
+ const { align, offset, padding = 0 } = options;
19653
+ const { x: alignX, y: alignY } = align;
19654
+ const { x: offsetX, y: offsetY } = offset;
19655
+ const recompute = useCallback(() => {
19656
+ const hostEl = resolve.current();
19657
+ if (!hostEl) {
19658
+ setStyle(null);
19659
+ return;
19660
+ }
19661
+ const h = hostEl.getBoundingClientRect();
19662
+ const p = panel?.getBoundingClientRect();
19663
+ const viewport = { width: window.innerWidth, height: window.innerHeight };
19664
+ const align2 = { x: alignX, y: alignY };
19665
+ const rect = hostAnchorRect({
19666
+ host: { x: h.left, y: h.top, width: h.width, height: h.height },
19667
+ panel: { width: p?.width ?? 0, height: p?.height ?? 0 },
19668
+ viewport,
19669
+ align: align2,
19670
+ offset: { x: offsetX, y: offsetY },
19671
+ padding
19672
+ });
19673
+ setStyle(hostAnchorCss(rect, align2, viewport));
19674
+ }, [panel, alignX, alignY, offsetX, offsetY, padding]);
19675
+ const raf = useVisibleRaf(recompute);
19676
+ useEffect(() => {
19677
+ recompute();
19678
+ const schedule = () => raf.request();
19679
+ window.addEventListener("scroll", schedule, true);
19680
+ window.addEventListener("resize", schedule);
19681
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(schedule) : null;
19682
+ if (panel) observer?.observe(panel);
19683
+ const hostEl = resolve.current();
19684
+ if (hostEl) observer?.observe(hostEl);
19685
+ return () => {
19686
+ window.removeEventListener("scroll", schedule, true);
19687
+ window.removeEventListener("resize", schedule);
19688
+ raf.cancel();
19689
+ observer?.disconnect();
19690
+ };
19691
+ }, [recompute, raf, panel]);
19692
+ return { ref, style };
19693
+ }
19694
+ function CursorCoordsHud({ canvasRef, anchorRef, viewRef, offset }) {
19470
19695
  const [state, setState] = useState({
19471
19696
  client: { x: 0, y: 0 },
19472
19697
  world: null,
19473
- inCanvas: false,
19474
- anchor: null
19698
+ inCanvas: false
19475
19699
  });
19476
19700
  const [fps, setFps] = useState(0);
19701
+ const { ref, style: anchorStyle } = useHostAnchor(
19702
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19703
+ {
19704
+ align: { x: "end", y: "start" },
19705
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 }
19706
+ }
19707
+ );
19477
19708
  const framesRef = useRef(0);
19478
19709
  const lastFlushRef = useRef(0);
19479
19710
  const fpsLoop = useVisibleRaf(
@@ -19503,49 +19734,33 @@ function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19503
19734
  return () => fpsLoop.cancel();
19504
19735
  }, [fpsLoop]);
19505
19736
  useEffect(() => {
19506
- const readAnchor = () => {
19507
- const canvas = canvasRef.current;
19508
- if (!canvas) return null;
19509
- const host = canvas.parentElement ?? canvas;
19510
- const rect = host.getBoundingClientRect();
19511
- return { top: rect.top, right: window.innerWidth - rect.right };
19512
- };
19513
19737
  const onMove = (e) => {
19514
19738
  const canvas = canvasRef.current;
19515
19739
  const view = viewRef.current;
19516
19740
  const client = { x: e.clientX, y: e.clientY };
19517
- const anchor = readAnchor();
19518
19741
  if (!canvas || !view) {
19519
- setState({ client, world: null, inCanvas: false, anchor });
19742
+ setState({ client, world: null, inCanvas: false });
19520
19743
  return;
19521
19744
  }
19522
19745
  const rect = canvas.getBoundingClientRect();
19523
19746
  const inCanvas = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
19524
19747
  const [wx, wy] = clientToWorld(e.clientX, e.clientY, rect, view);
19525
19748
  const world = { x: wx, y: wy };
19526
- setState({ client, world, inCanvas, anchor });
19749
+ setState({ client, world, inCanvas });
19527
19750
  };
19528
- const onLayout = () => setState((s) => ({ ...s, anchor: readAnchor() }));
19529
19751
  document.addEventListener("pointermove", onMove);
19530
- window.addEventListener("scroll", onLayout, true);
19531
- window.addEventListener("resize", onLayout);
19532
- setState((s) => ({ ...s, anchor: readAnchor() }));
19533
19752
  return () => {
19534
19753
  document.removeEventListener("pointermove", onMove);
19535
- window.removeEventListener("scroll", onLayout, true);
19536
- window.removeEventListener("resize", onLayout);
19537
19754
  };
19538
19755
  }, [canvasRef, viewRef]);
19539
- if (!state.anchor) return null;
19540
- const top = state.anchor.top + (offset?.top ?? 8);
19541
- const right = state.anchor.right + (offset?.right ?? 8);
19756
+ if (!anchorStyle) return null;
19542
19757
  return /* @__PURE__ */ jsxs(
19543
19758
  "div",
19544
19759
  {
19760
+ ref,
19545
19761
  style: {
19546
19762
  position: "fixed",
19547
- top,
19548
- right,
19763
+ ...anchorStyle,
19549
19764
  zIndex: 1e4,
19550
19765
  background: "rgba(0,0,0,0.7)",
19551
19766
  color: "#e8e8e8",
@@ -19570,33 +19785,31 @@ function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19570
19785
 
19571
19786
  // src/canvas/PickHud.module.css
19572
19787
  var PickHud_default = {};
19573
- function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19788
+ function PickHud({ canvasRef, anchorRef, viewRef, pickEvery, pickBest, offset }) {
19574
19789
  const [state, setState] = useState({
19575
19790
  ids: [],
19576
19791
  best: null,
19577
- inCanvas: false,
19578
- anchor: null
19792
+ inCanvas: false
19579
19793
  });
19794
+ const { ref, style } = useHostAnchor(
19795
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19796
+ {
19797
+ align: { x: "end", y: "start" },
19798
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 76 }
19799
+ }
19800
+ );
19580
19801
  useEffect(() => {
19581
- const readAnchor = () => {
19582
- const canvas = canvasRef.current;
19583
- if (!canvas) return null;
19584
- const host = canvas.parentElement ?? canvas;
19585
- const rect = host.getBoundingClientRect();
19586
- return { top: rect.top, right: window.innerWidth - rect.right };
19587
- };
19588
19802
  const onMove = (e) => {
19589
19803
  const canvas = canvasRef.current;
19590
19804
  const view = viewRef.current;
19591
- const anchor = readAnchor();
19592
19805
  if (!canvas || !view) {
19593
- setState({ ids: [], best: null, inCanvas: false, anchor });
19806
+ setState({ ids: [], best: null, inCanvas: false });
19594
19807
  return;
19595
19808
  }
19596
19809
  const rect = canvas.getBoundingClientRect();
19597
19810
  const inCanvas = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
19598
19811
  if (!inCanvas) {
19599
- setState({ ids: [], best: null, inCanvas: false, anchor });
19812
+ setState({ ids: [], best: null, inCanvas: false });
19600
19813
  return;
19601
19814
  }
19602
19815
  const worldX = (e.clientX - rect.left) / view.scale.x + view.x;
@@ -19615,24 +19828,15 @@ function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19615
19828
  best = null;
19616
19829
  }
19617
19830
  }
19618
- setState({ ids, best, inCanvas: true, anchor });
19831
+ setState({ ids, best, inCanvas: true });
19619
19832
  };
19620
- const onLayout = () => setState((s) => ({ ...s, anchor: readAnchor() }));
19621
19833
  document.addEventListener("pointermove", onMove);
19622
- window.addEventListener("scroll", onLayout, true);
19623
- window.addEventListener("resize", onLayout);
19624
- setState((s) => ({ ...s, anchor: readAnchor() }));
19625
19834
  return () => {
19626
19835
  document.removeEventListener("pointermove", onMove);
19627
- window.removeEventListener("scroll", onLayout, true);
19628
- window.removeEventListener("resize", onLayout);
19629
19836
  };
19630
19837
  }, [canvasRef, viewRef, pickEvery, pickBest]);
19631
- if (!state.anchor) return null;
19632
- const top = state.anchor.top + (offset?.top ?? 76);
19633
- const right = state.anchor.right + (offset?.right ?? 8);
19634
- const style = { top, right };
19635
- return /* @__PURE__ */ jsxs("div", { className: PickHud_default.hud, style, children: [
19838
+ if (!style) return null;
19839
+ return /* @__PURE__ */ jsxs("div", { ref, className: PickHud_default.hud, style, children: [
19636
19840
  /* @__PURE__ */ jsxs("div", { className: PickHud_default.header, children: [
19637
19841
  "pickEvery (",
19638
19842
  state.ids.length,
@@ -19651,34 +19855,20 @@ function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19651
19855
 
19652
19856
  // src/canvas/ModalityHud.module.css
19653
19857
  var ModalityHud_default = {};
19654
- function ModalityHud({ canvasRef, modeId, offset }) {
19858
+ function ModalityHud({ canvasRef, anchorRef, modeId, offset }) {
19655
19859
  const toolCtx = useOptionalActiveToolContext();
19656
- const [state, setState] = useState({ anchor: null });
19657
- useEffect(() => {
19658
- const readAnchor = () => {
19659
- const canvas = canvasRef.current;
19660
- if (!canvas) return null;
19661
- const host = canvas.parentElement ?? canvas;
19662
- const rect = host.getBoundingClientRect();
19663
- return { top: rect.top, right: window.innerWidth - rect.right };
19664
- };
19665
- const onLayout = () => setState({ anchor: readAnchor() });
19666
- onLayout();
19667
- window.addEventListener("scroll", onLayout, true);
19668
- window.addEventListener("resize", onLayout);
19669
- return () => {
19670
- window.removeEventListener("scroll", onLayout, true);
19671
- window.removeEventListener("resize", onLayout);
19672
- };
19673
- }, [canvasRef]);
19674
- if (!state.anchor) return null;
19675
- const top = state.anchor.top + (offset?.top ?? 220);
19676
- const right = state.anchor.right + (offset?.right ?? 8);
19677
- const style = { top, right };
19860
+ const { ref, style } = useHostAnchor(
19861
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19862
+ {
19863
+ align: { x: "end", y: "start" },
19864
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 220 }
19865
+ }
19866
+ );
19867
+ if (!style) return null;
19678
19868
  const active = toolCtx?.active ?? null;
19679
19869
  const hotkeys = toolCtx?.hotkeyStack ?? [];
19680
19870
  const hotkeyTop = hotkeys.length > 0 ? hotkeys[hotkeys.length - 1] : null;
19681
- return /* @__PURE__ */ jsxs("div", { className: ModalityHud_default.hud, style, children: [
19871
+ return /* @__PURE__ */ jsxs("div", { ref, className: ModalityHud_default.hud, style, children: [
19682
19872
  /* @__PURE__ */ jsxs("div", { className: ModalityHud_default.row, children: [
19683
19873
  /* @__PURE__ */ jsx("span", { className: ModalityHud_default.label, children: "mode" }),
19684
19874
  /* @__PURE__ */ jsx("span", { className: modeId ? ModalityHud_default.value : ModalityHud_default.valueMuted, children: modeId ?? "\u2014" })
@@ -19809,6 +19999,8 @@ function CanvasInner(props, ref) {
19809
19999
  boundsOf: boundsOf2,
19810
20000
  pickEvery,
19811
20001
  clientToWorld: clientToWorld2,
20002
+ paintInto,
20003
+ inputElement,
19812
20004
  geometry = AUTO_POSE_DESCRIPTOR,
19813
20005
  className,
19814
20006
  style,
@@ -19854,6 +20046,15 @@ function CanvasInner(props, ref) {
19854
20046
  debugSinkRefForCtx.current = debugSink;
19855
20047
  const adapter = adapterProp;
19856
20048
  const canvasRef = useRef(null);
20049
+ const ownCanvasRef = useRef(null);
20050
+ const detached = !!paintInto;
20051
+ if (detached) {
20052
+ canvasRef.current = inputElement ?? null;
20053
+ }
20054
+ const paintTargetRef = useRef(null);
20055
+ paintTargetRef.current = detached ? paintInto.canvas ?? null : null;
20056
+ const paintRectRef = useRef(null);
20057
+ paintRectRef.current = detached ? { x: paintInto.x, y: paintInto.y } : null;
19857
20058
  const helpersForLayersRef = useRef(null);
19858
20059
  const dimsRef = useRef({ width, height });
19859
20060
  dimsRef.current = { width, height };
@@ -19941,7 +20142,10 @@ function CanvasInner(props, ref) {
19941
20142
  };
19942
20143
  }, []);
19943
20144
  useImperativeHandle(ref, () => ({
19944
- element: canvasRef.current,
20145
+ // Named rather than read off `canvasRef` so the handle rebuilds when a
20146
+ // detached surface's input element arrives, which is a render later.
20147
+ element: detached ? inputElement ?? null : canvasRef.current,
20148
+ surface: detached ? paintInto?.canvas ?? null : ownCanvasRef.current,
19945
20149
  requestRedraw,
19946
20150
  subscribeFrame,
19947
20151
  registerLayer,
@@ -19952,6 +20156,10 @@ function CanvasInner(props, ref) {
19952
20156
  getPaintedVersion
19953
20157
  }), [
19954
20158
  canvasRef,
20159
+ ownCanvasRef,
20160
+ detached,
20161
+ inputElement,
20162
+ paintInto?.canvas,
19955
20163
  requestRedraw,
19956
20164
  subscribeFrame,
19957
20165
  registerLayer,
@@ -20247,8 +20455,9 @@ function CanvasInner(props, ref) {
20247
20455
  shaders
20248
20456
  };
20249
20457
  const paint = useCallback(() => {
20250
- const c = canvasRef.current;
20458
+ const c = paintTargetRef.current ?? ownCanvasRef.current;
20251
20459
  if (!c) return false;
20460
+ const rect = paintRectRef.current;
20252
20461
  const {
20253
20462
  layers: paintLayers,
20254
20463
  width: w,
@@ -20277,7 +20486,9 @@ function CanvasInner(props, ref) {
20277
20486
  try {
20278
20487
  renderer = new WeaselRenderer({
20279
20488
  gl,
20280
- canvas: c,
20489
+ // A shared buffer is the caller's to size. Handing the renderer the
20490
+ // element would have every co-tenant resize it to its own pane.
20491
+ ...rect ? {} : { canvas: c },
20281
20492
  width: w,
20282
20493
  height: h,
20283
20494
  dpr
@@ -20296,6 +20507,7 @@ function CanvasInner(props, ref) {
20296
20507
  lastResizeRef.current = { w, h, dpr };
20297
20508
  }
20298
20509
  }
20510
+ renderer.setTarget(rect ? { origin: { x: rect.x, y: rect.y } } : null);
20299
20511
  const view = viewRef.current;
20300
20512
  const commands = drawLayers(
20301
20513
  paintLayers,
@@ -20344,31 +20556,69 @@ function CanvasInner(props, ref) {
20344
20556
  }, [shaderIdKey]);
20345
20557
  const toolsCursor = tools ? resolveToolsCursor(tools, toolsCtxBase) : void 0;
20346
20558
  const effectiveStyle = toolsCursor ? { ...style, cursor: toolsCursor } : style;
20347
- return /* @__PURE__ */ jsxs(Fragment, { children: [
20348
- /* @__PURE__ */ jsx(
20349
- "canvas",
20559
+ const layersForMoveRef = useRef(layersWithDebug);
20560
+ layersForMoveRef.current = layersWithDebug;
20561
+ useEffect(() => {
20562
+ if (!detached || !inputElement) return;
20563
+ const el = inputElement;
20564
+ const onDown = () => {
20565
+ if (autoFocusOnPointerDown) el.focus();
20566
+ pointerDownRef.current = true;
20567
+ };
20568
+ const onMove = (e) => {
20569
+ if (pointerDownRef.current) return;
20570
+ const view = viewRef.current;
20571
+ const [worldX, worldY] = toWorld(
20572
+ el,
20573
+ e.clientX,
20574
+ e.clientY,
20575
+ view,
20576
+ clientToWorldRef.current
20577
+ );
20578
+ const dims = dimsRef.current;
20579
+ for (const layer of layersForMoveRef.current) {
20580
+ layer.onUncapturedMove?.(worldX, worldY, e, view, dims);
20581
+ }
20582
+ };
20583
+ const onUp = () => {
20584
+ pointerDownRef.current = false;
20585
+ };
20586
+ const onLeave = () => {
20587
+ pointerDownRef.current = false;
20588
+ for (const layer of layersForMoveRef.current) layer.onUncapturedLeave?.();
20589
+ };
20590
+ const onMenu = (e) => e.preventDefault();
20591
+ el.addEventListener("pointerdown", onDown);
20592
+ el.addEventListener("pointermove", onMove);
20593
+ el.addEventListener("pointerup", onUp);
20594
+ el.addEventListener("pointerleave", onLeave);
20595
+ el.addEventListener("contextmenu", onMenu);
20596
+ return () => {
20597
+ el.removeEventListener("pointerdown", onDown);
20598
+ el.removeEventListener("pointermove", onMove);
20599
+ el.removeEventListener("pointerup", onUp);
20600
+ el.removeEventListener("pointerleave", onLeave);
20601
+ el.removeEventListener("contextmenu", onMenu);
20602
+ };
20603
+ }, [detached, inputElement, autoFocusOnPointerDown]);
20604
+ useEffect(() => {
20605
+ if (!detached || !inputElement) return;
20606
+ inputElement.style.cursor = toolsCursor ?? "";
20607
+ }, [detached, inputElement, toolsCursor]);
20608
+ const huds = /* @__PURE__ */ jsxs(Fragment, { children: [
20609
+ cursorCoordsHud && /* @__PURE__ */ jsx(
20610
+ CursorCoordsHud,
20350
20611
  {
20351
- ref: canvasRef,
20352
- width,
20353
- height,
20354
- tabIndex,
20355
- className,
20356
- style: effectiveStyle,
20357
- onFocus,
20358
- onBlur,
20359
- onPointerDown: handlePointerDown,
20360
- onPointerMove: handlePointerMove,
20361
- onPointerUp: handlePointerUp,
20362
- onPointerCancel: handlePointerCancel,
20363
- onPointerLeave: handlePointerLeave,
20364
- onContextMenu: (e) => e.preventDefault()
20612
+ canvasRef,
20613
+ ...detached ? { anchorRef: canvasRef } : {},
20614
+ viewRef
20365
20615
  }
20366
20616
  ),
20367
- cursorCoordsHud && /* @__PURE__ */ jsx(CursorCoordsHud, { canvasRef, viewRef }),
20368
20617
  pickHud && /* @__PURE__ */ jsx(
20369
20618
  PickHud,
20370
20619
  {
20371
20620
  canvasRef,
20621
+ ...detached ? { anchorRef: canvasRef } : {},
20372
20622
  viewRef,
20373
20623
  pickEvery: stablePickEveryForHud,
20374
20624
  pickBest: stablePickBestForHud
@@ -20378,10 +20628,37 @@ function CanvasInner(props, ref) {
20378
20628
  ModalityHud,
20379
20629
  {
20380
20630
  canvasRef,
20631
+ ...detached ? { anchorRef: canvasRef } : {},
20381
20632
  modeId: typeof modalityHud === "object" ? modalityHud.modeId : void 0
20382
20633
  }
20383
20634
  )
20384
20635
  ] });
20636
+ if (detached) return inputElement ? huds : null;
20637
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
20638
+ /* @__PURE__ */ jsx(
20639
+ "canvas",
20640
+ {
20641
+ ref: (el) => {
20642
+ ownCanvasRef.current = el;
20643
+ canvasRef.current = el;
20644
+ },
20645
+ width,
20646
+ height,
20647
+ tabIndex,
20648
+ className,
20649
+ style: effectiveStyle,
20650
+ onFocus,
20651
+ onBlur,
20652
+ onPointerDown: handlePointerDown,
20653
+ onPointerMove: handlePointerMove,
20654
+ onPointerUp: handlePointerUp,
20655
+ onPointerCancel: handlePointerCancel,
20656
+ onPointerLeave: handlePointerLeave,
20657
+ onContextMenu: (e) => e.preventDefault()
20658
+ }
20659
+ ),
20660
+ huds
20661
+ ] });
20385
20662
  }
20386
20663
  var Canvas = forwardRef(CanvasInner);
20387
20664
 
@@ -23044,7 +23321,7 @@ function useDispatcherOverlayLayer(args) {
23044
23321
  break;
23045
23322
  case "pencil": {
23046
23323
  if (geom.samples.length < 2) break;
23047
- pathCmd = polygonFromPoints(projectPoints(geom.samples));
23324
+ pathCmd = polylineFromPoints(projectPoints(geom.samples));
23048
23325
  break;
23049
23326
  }
23050
23327
  }
@@ -23056,7 +23333,7 @@ function useDispatcherOverlayLayer(args) {
23056
23333
  stroke: { paint: { color: cfg.stroke }, width: cfg.lineWidth, dash: cfg.dash }
23057
23334
  };
23058
23335
  out.push(cmd);
23059
- if (ov.anchorPoint) {
23336
+ if (ov.anchorPoint && ov.shape !== "pencil") {
23060
23337
  const anchorScreen = projectPoint(ov.anchorPoint.x, ov.anchorPoint.y);
23061
23338
  out.push({
23062
23339
  kind: "path",
@@ -24979,7 +25256,7 @@ function SceneCanvasInner(props, ref) {
24979
25256
  boundary: inertiaObj.boundary,
24980
25257
  bounds: inertiaObj.bounds
24981
25258
  } : void 0;
24982
- const handTool = useHandTool(handToolInertia ? { inertia: handToolInertia } : {});
25259
+ const handTool = useHandTool(handToolInertia ? { } : {});
24983
25260
  const viewportAmbient = [];
24984
25261
  const baseRequestedTools = defaultTools ?? (toolBundle ? BUNDLE_TOOLS[toolBundle] : null) ?? (viewportRegistered ? ["select", "rotate", "hand"] : ["select", "rotate"]);
24985
25262
  const KNOWN_BUILTIN_IDS = /* @__PURE__ */ new Set([
@@ -25704,14 +25981,12 @@ function StandardActionsRegistrar({
25704
25981
  }, [registry2, actionsRegistryRef]);
25705
25982
  useEffect(() => {
25706
25983
  if (!registry2) return;
25707
- registry2.setDispatcher(dispatcher);
25708
- return () => registry2.setDispatcher(null);
25984
+ return registry2.setDispatcher(dispatcher);
25709
25985
  }, [registry2, dispatcher]);
25710
25986
  const wiredDepRegistry = useDepRegistry();
25711
25987
  useEffect(() => {
25712
25988
  if (!registry2) return;
25713
- registry2.setDepRegistry(wiredDepRegistry);
25714
- return () => registry2.setDepRegistry(null);
25989
+ return registry2.setDepRegistry(wiredDepRegistry);
25715
25990
  }, [registry2, wiredDepRegistry]);
25716
25991
  useEffect(() => {
25717
25992
  if (!registry2) return;
@@ -25927,9 +26202,9 @@ function shapeSchema(opts = {}) {
25927
26202
  fontWeight: { kind: "number", name: "Weight", description: "Font weight, 100\u2013900.", default: 400, min: 100, max: 900, step: 100, pair: "Size / weight" },
25928
26203
  fontStyle: { kind: "enum", name: "Style", description: "Upright or italic.", default: "normal", options: [{ value: "normal", label: "Normal" }, { value: "italic", label: "Italic" }] },
25929
26204
  letterSpacing: { kind: "number", name: "Tracking", description: "Extra advance per glyph, world units.", default: 0, step: 0.1 },
25930
- underline: { kind: "boolean", name: "Underline", description: "Underline the text.", default: false },
25931
- strikethrough: { kind: "boolean", name: "Strikethrough", description: "Strike through the text.", default: false },
25932
- overline: { kind: "boolean", name: "Overline", description: "Rule the text above its ascent.", default: false }
26205
+ underline: { kind: "boolean", name: "Underline", description: "Underline the text.", default: false, control: "toggle", short: "U", pair: "Decoration" },
26206
+ strikethrough: { kind: "boolean", name: "Strikethrough", description: "Strike through the text.", default: false, control: "toggle", short: "S", pair: "Decoration" },
26207
+ overline: { kind: "boolean", name: "Overline", description: "Rule the text above its ascent.", default: false, control: "toggle", short: "O", pair: "Decoration" }
25933
26208
  }
25934
26209
  },
25935
26210
  paragraph: {
@@ -26399,8 +26674,13 @@ function renderSceneToPixels(args) {
26399
26674
  renderer.dispose();
26400
26675
  }
26401
26676
  }
26402
- function WeaselProvider({ children }) {
26403
- return /* @__PURE__ */ jsx(DepRegistryProviderIfRoot, { children: /* @__PURE__ */ jsx(ActionsProviderIfRoot, { children: /* @__PURE__ */ jsx(ActiveToolContextProviderIfRoot, { children: /* @__PURE__ */ jsx(SelectionContextProviderIfRoot, { children: /* @__PURE__ */ jsx(PointerProviderIfRoot, { children }) }) }) }) });
26677
+ function WeaselProvider({ children, isolate = false }) {
26678
+ const Deps = isolate ? DepRegistryProvider : DepRegistryProviderIfRoot;
26679
+ const Actions = isolate ? ActionsProvider : ActionsProviderIfRoot;
26680
+ const ActiveTool = isolate ? ActiveToolContextProvider : ActiveToolContextProviderIfRoot;
26681
+ const Selection = isolate ? SelectionContextProvider : SelectionContextProviderIfRoot;
26682
+ const Pointer = isolate ? PointerContextProvider : PointerProviderIfRoot;
26683
+ return /* @__PURE__ */ jsx(Deps, { children: /* @__PURE__ */ jsx(Actions, { children: /* @__PURE__ */ jsx(ActiveTool, { children: /* @__PURE__ */ jsx(Selection, { children: /* @__PURE__ */ jsx(Pointer, { children }) }) }) }) });
26404
26684
  }
26405
26685
  function useCanvasFocus(options = {}) {
26406
26686
  const { initial = false, tabIndex = 0 } = options;
@@ -27557,7 +27837,7 @@ function useSceneTextEdit(scene, container, options = {}) {
27557
27837
  }
27558
27838
  });
27559
27839
  const onDoubleClick = useCallback((e) => {
27560
- const canvas = e.target instanceof HTMLCanvasElement ? e.target : null;
27840
+ const canvas = e.target instanceof HTMLElement ? e.target : null;
27561
27841
  if (!canvas) return;
27562
27842
  const [canvasX, canvasY] = clientToCanvas(canvas, e.clientX, e.clientY);
27563
27843
  const view = resolveView2(optsRef.current.view);
@@ -27802,6 +28082,8 @@ function polygonPathDistance(path, px, py) {
27802
28082
  if (d2 < best) best = d2;
27803
28083
  curX = startX;
27804
28084
  curY = startY;
28085
+ } else {
28086
+ throw new Error(`pathDistanceToPoint: unknown command code ${cmd}`);
27805
28087
  }
27806
28088
  }
27807
28089
  return best === Infinity ? Infinity : Math.sqrt(best);
@@ -29919,7 +30201,7 @@ function cycleVertexColors(animator, opts) {
29919
30201
  const interp = resolveInterpolator(opts);
29920
30202
  const { id, channel } = opts;
29921
30203
  const direction = opts.direction ?? 1;
29922
- const easing = opts.easing ?? ((t) => t);
30204
+ const easing = resolveEasing(opts.easing);
29923
30205
  const override = (base, tMs) => {
29924
30206
  const n = base.length / 4;
29925
30207
  if (n === 0) return base.slice();
@@ -29960,7 +30242,7 @@ function staggerVertexColors(animator, opts) {
29960
30242
  const interp = resolveInterpolator(opts);
29961
30243
  const { id, channel, from, to, anchorMs, perAnchorDelay } = opts;
29962
30244
  const n = from.length / 4;
29963
- const easing = opts.easing ?? ((t) => t);
30245
+ const easing = resolveEasing(opts.easing);
29964
30246
  const originIndex = opts.origin === "last" ? n - 1 : typeof opts.origin === "number" ? Math.max(0, Math.min(n - 1, opts.origin)) : 0;
29965
30247
  const maxDistance = Math.max(originIndex, n - 1 - originIndex);
29966
30248
  const totalMs = maxDistance * perAnchorDelay + anchorMs;
@@ -30402,6 +30684,6 @@ function mergeContributions(...bundles) {
30402
30684
  return out;
30403
30685
  }
30404
30686
 
30405
- export { ALWAYS, ANCHOR_HIT_BASE_PX, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUILTIN_MARKERS, BUNDLE_TOOLS, COARSE_TARGET_SCALE, CURVE_REPS, CanvasView, ColorOverrideRegistry, CropIcon, CursorCoordsHud, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_HANDLE_SIZE2 as DEFAULT_HANDLE_SIZE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_SHAPE_FILL, DEFAULT_STROKE_COLOR, DEFAULT_VELOCITY_DECAY, DepRegistryProviderIfRoot, DeviceProfileProvider, DivideIcon, EASINGS, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, GHOST_STROKE, HANDLE_BASE_PX, HandIcon, IDENTITY_COLOR_MATRIX, IDENTITY_JOINT, IDENTITY_POSE_COMPOSITION, ImageIcon, IntersectIcon, KIT_SHAPE_KINDS, LassoIcon, LineIcon, MIXED, MOVE_ANCHORS, MinimapCanvas, NEVER, OUTLINE_MIN_SCREEN_PX, PATH_ANCHOR_CHROME_ID, PenIcon, PencilIcon, PickHud, PointerProviderIfRoot, PolygonIcon, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, RectIcon, SPRING_PRESETS, SceneCanvas, SceneViewCanvas, SelectIcon, SelectionContextProvider, SelectionContextProviderIfRoot, ShaderCompileError, StarIcon, SubtractIcon, TOOL_PREF_KINDS, TextIcon, UnionIcon, UnknownIcon, VERSION, VIEW_ANIMATION_KEY, WeaselProvider, WeaselRenderer, _resetMarkersForTests, _resetPaintKindsForTests, aabbCenter, actionIs, actionShortcuts, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyBooleanOp, applyStyleToRange, areaSelectAction, arrayAdapter, asNodeId, asPaint, axisAlignedBounds, bezierCubic, bezierQuadratic, blendPoses, buildChromeCtx, buildGradientRamp, buildRuleCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, clipboardCopyAction, clipboardCutAction, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeRectPose, composeSelectionPose, composeWorldPose, computeFitView, computeFitViewport, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDispatcher, createGridLayer, createGuidesLayer, createHistory2 as createHistory, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetTextOp, createTextLayer, createViewResolver, createViewportLayer, cycleVertexColors, decomposePath, decomposeRectPose, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, defineViewportTool, deriveAlignmentGuides, deriveParallaxView, describeRule, domPositionToCharOffset, domToRuns, drawLayers, drawOneLayer, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, enterTextEditAction, enumerateAnchors, evaluate, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitViewToBounds, fitZoom, focused, forEachCoalesced, frameRect, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getMarker, getNodeShapes, getPaintKind, getStylusData, gradientForBounds, gradientGeometry, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, interpolateView, isBuiltinToolPref, isEditableTarget2 as isEditableTarget, isGradientFill, isLayerPainted, isLayerVisible, isPatternSpec, keySpecShortcut, lassoSelectAction, lerpColorArray, lerpOklab, lerpOklch, linear, listMarkers, listPaintKinds, liveScope, makePinchZoomAction, makeViewportZoomAction, markerDrawCommands, markerInset, markerKeyOf, markerSites, mat3, matchAlignment, matchesKeyBinding, meanScale, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, paintAlpha, paintKindOf, paintWithAlpha, paintWithColor, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInRotatedRect, pointInTextPose, poseRotationOf, pressureToWidth, rainbowVertexColors, rebaseLocalPose, rectCorners, registerContentHandler, registerMarker, registerNodeShape, registerPaintKind, registerProgram, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveFillPattern, resolveMarkerSize, resolveParams, resolvePatternSpec, resolveSkeleton, resolveStrokeWidth, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, sampleGradientStops, sampleTrack, sceneFromJSON, sceneNodeClientRect, sceneSelectionStore, sceneToAdapter, scopeBindings, screenToWorld, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, shapeCoversPoint, sliceAction, snapPoint, solid, solidVertexColors, specificity, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, startThresholdDrag, strokeInsets, strokeOf, strokeWith, styleAtRange, subscribeImageReady, tessellate, tessellateStroke, textCommand, textCommandFromRuns, tileGrid, toHex8, translatePoseViaDescriptor, translateRectPose, trimPolyline, tweenPose, tweenVertexColors, unionAABB, unionBounds, unionBoundsPath, useActiveToolContext, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, useNodeOverlayFrame, useOptionalActiveToolContext, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useVisibleRaf, useZoom, viewToMat3, viewToTransform, viewportDragPanAction, viewportZoomAction, viewportsAt, visualBoundsViaDescriptor, when, withAlpha01, withCoord, withGradientKind, worldEditToStorage, worldPoseLookup, worldToScreen, zoomAt, zoomAtLeast };
30406
- //# sourceMappingURL=chunk-N3T7D6AS.js.map
30407
- //# sourceMappingURL=chunk-N3T7D6AS.js.map
30687
+ export { ALWAYS, ANCHOR_HIT_BASE_PX, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, ArrowIcon, BUILTIN_MARKERS, BUNDLE_TOOLS, COARSE_TARGET_SCALE, CURVE_REPS, CanvasView, ColorOverrideRegistry, CropIcon, CursorCoordsHud, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_HANDLE_SIZE2 as DEFAULT_HANDLE_SIZE, DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_SHAPE_FILL, DEFAULT_STROKE_COLOR, DEFAULT_VELOCITY_DECAY, DepRegistryProviderIfRoot, DeviceProfileProvider, DivideIcon, EASINGS, EllipseIcon, ExcludeIcon, EyedropperIcon, FALLBACK_FIT_VIEW, GHOST_STROKE, HANDLE_BASE_PX, HandIcon, IDENTITY_COLOR_MATRIX, IDENTITY_JOINT, IDENTITY_POSE_COMPOSITION, ImageIcon, IntersectIcon, KIT_SHAPE_KINDS, LassoIcon, LineIcon, MIXED, MOVE_ANCHORS, MinimapCanvas, NEVER, OUTLINE_MIN_SCREEN_PX, PATH_ANCHOR_CHROME_ID, PenIcon, PencilIcon, PickHud, PointerProviderIfRoot, PolygonIcon, RECT_ALIGN_PROJECTION, ROTATION_HANDLE_BASE_PX, RectIcon, SPRING_PRESETS, SceneCanvas, SceneViewCanvas, SelectIcon, SelectionContextProvider, SelectionContextProviderIfRoot, ShaderCompileError, StarIcon, SubtractIcon, TOOL_PREF_KINDS, TextIcon, UnionIcon, UnknownIcon, VERSION, VIEW_ANIMATION_KEY, WeaselProvider, WeaselRenderer, _resetMarkersForTests, _resetPaintKindsForTests, aabbCenter, actionIs, actionShortcuts, alignDeltaFor, alignInsertBehavior, alignMoveBehavior, alignResizeBehavior, always, and, animateLifecycle, animateOnSetPose, annulusSemiAxes, applyBooleanOp, applyStyleToRange, areaSelectAction, arrayAdapter, asNodeId, asPaint, axisAlignedBounds, bezierCubic, bezierQuadratic, blendPoses, buildChromeCtx, buildGradientRamp, buildRuleCtx, buildSceneViewCommands, canBringForward, canHover, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, caretIndexAt, cellAt, charOffsetToDomPosition, clampView, clearSelectionAction, clientToCanvas, clipboardCopyAction, clipboardCutAction, cloneAction, coarsePointer, composeAffordanceLayer, composePath, composeRectPose, composeSelectionPose, composeWorldPose, computeFitView, computeFitViewport, computeIndicatorCommand, computeWheelAction, cond, constrainTo45, containedThenNearest, countPathAnchors, createCellHighlightLayer, createChildrenLayer, createCornerResizeAffordance, createDebugOverlayLayer, createDebugSink, createDispatcher, createGridLayer, createGuidesLayer, createHistory2 as createHistory, createMoveToIndexOp, createNodeProperties, createNodeRouting, createParallaxLayer, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathLayer, createPenPreviewLayer, createReorderOp, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetDataOp, createSetLayerOp, createSetPathOp, createSetTextOp, createTextLayer, createViewResolver, createViewportLayer, cubicBezierEasing, cycleVertexColors, decomposePath, decomposeRectPose, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultVisibilityRules, defineTool, defineViewportTool, deriveAlignmentGuides, deriveParallaxView, describeRule, domPositionToCharOffset, domToRuns, drawLayers, drawOneLayer, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, enterTextEditAction, enumerateAnchors, evaluate, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findShapeInk, findShapeSilhouette, fitTextPose, fitToBounds, fitViewToBounds, fitZoom, focused, forEachCoalesced, frameRect, freeform, gateLayer, gesturing, getAlpha01, getImageBitmap, getMarker, getNodeShapes, getPaintKind, getStylusData, gradientForBounds, gradientGeometry, hexToRgba, hitAffordanceRegions, hitAnchor, hitRotationHandle, hostAnchorCss, hostAnchorRect, hovering, hoveringSelected, imageStatus, inferredNodeProperties, inferredNodeRouting, insertAction, interpolateView, isBuiltinToolPref, isEditableTarget2 as isEditableTarget, isGradientFill, isLayerPainted, isLayerVisible, isPatternSpec, keySpecShortcut, lassoSelectAction, lerpColorArray, lerpOklab, lerpOklch, linear, listMarkers, listPaintKinds, liveScope, makePinchZoomAction, makeViewportZoomAction, markerDrawCommands, markerInset, markerKeyOf, markerSites, mat3, matchAlignment, matchesKeyBinding, meanScale, mergeAlphaFromPrev, mergeContributions, modeIn, modeIs, modeNot, modifierHeld, momentum, moveAction, multiActive, nearest, nearestWithin, nestedHitTester, never, nodeHasFlag, none, normalizeHex, not, nurbs, oklabToOklch, oklabToSrgbU8, oklchToOklab, openFilePicker, or, paintAlpha, paintKindOf, paintWithAlpha, paintWithColor, parseColor, parseColorToRgba255, parseDebugFlags, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathDivide, pathExclude, pathFromD, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathOriginProjection, pathSubtract, pathToAnchors, pathUnion, pickTopMostHit, pinchZoomAction, planPixelRender, pointInRotatedRect, pointInTextPose, poseRotationOf, pressureToWidth, rainbowVertexColors, rebaseLocalPose, rectCorners, registerContentHandler, registerMarker, registerNodeShape, registerPaintKind, registerProgram, renderLabel, renderSceneToCanvas, renderSceneToPixels, resizeAction, resolveColor, resolveDeviceProfile, resolveEasing, resolveFillPattern, resolveMarkerSize, resolveParams, resolvePatternSpec, resolveSkeleton, resolveStrokeWidth, resolveVisibility, rgbaToHex, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatedRectCorners, rotationDegreesUnit, rotationHandle, roundToCell, runsToDom, sampleGradientStops, sampleTrack, sceneFromJSON, sceneNodeClientRect, sceneSelectionStore, sceneToAdapter, scopeBindings, screenToWorld, selectFromLasso, selectionAtLeast, selectionEmpty, selectionIs, setFlagOverRange, shapeCoversPoint, sliceAction, snapPoint, solid, solidVertexColors, specificity, spiro, splitPathByLine, splitSubpaths, springPose, springVertexColors, srgbU8ToOklab, staggerVertexColors, startThresholdDrag, strokeInsets, strokeOf, strokeWith, styleAtRange, subscribeImageReady, tessellate, tessellateStroke, textCommand, textCommandFromRuns, tileGrid, toHex8, translatePoseViaDescriptor, translateRectPose, trimPolyline, tweenPose, tweenVertexColors, unionAABB, unionBounds, unionBoundsPath, useActiveToolContext, useAlign, useAnimator, useArrayAdapter, useAutoCenter, useBooleans, useBooleansAdapter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEllipseTool, useEyedropperTool, useGestureDispatcher, useGridCellHover, useGuides, useHandTool, useHandleDrag, useHostAnchor, useHoverTracking, useImageTool, useKeybindings, useLassoTool, useLineTool, useNodeOverlayFrame, useOptionalActiveToolContext, usePenTool, usePencilTool, usePinchGesture, usePinchZoomTool, usePointerStylus, usePolygonTool, usePublishSelection, useRectTool, useResizePolicy, useRotateTool, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useStandardActions, useStarTool, useTextEdit, useTextTool, useTools, useVelocityTracker, useViewAnimation, useVisibleRaf, useZoom, viewToMat3, viewToTransform, viewportDragPanAction, viewportZoomAction, viewportsAt, visualBoundsViaDescriptor, when, withAlpha01, withCoord, withGradientKind, worldEditToStorage, worldPoseLookup, worldToScreen, zoomAt, zoomAtLeast };
30688
+ //# sourceMappingURL=chunk-FUQWXDG3.js.map
30689
+ //# sourceMappingURL=chunk-FUQWXDG3.js.map