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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,7 +14,7 @@ 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';
@@ -23,7 +23,7 @@ import { createHistory } from '@weasel-js/history';
23
23
  export * from '@weasel-js/history';
24
24
 
25
25
  // src/version.ts
26
- var VERSION = "1.3.0" ;
26
+ var VERSION = "1.4.0-pre.0" ;
27
27
 
28
28
  // src/features/grid/roundToCell.ts
29
29
  function roundToCell(value, cellSize) {
@@ -1539,6 +1539,9 @@ function flattenPolygon(p, tolerance) {
1539
1539
  let coordIdx = 0;
1540
1540
  let prevX = 0;
1541
1541
  let prevY = 0;
1542
+ let startX = 0;
1543
+ let startY = 0;
1544
+ let startAnchor = -1;
1542
1545
  let prevAnchor = -1;
1543
1546
  let anchorCounter = 0;
1544
1547
  for (let cmdIdx = 0; cmdIdx < commands.length; cmdIdx++) {
@@ -1548,6 +1551,9 @@ function flattenPolygon(p, tolerance) {
1548
1551
  contourStarts.push(out.length / 2);
1549
1552
  prevX = coords[coordIdx];
1550
1553
  prevY = coords[coordIdx + 1];
1554
+ startX = prevX;
1555
+ startY = prevY;
1556
+ startAnchor = anchorCounter;
1551
1557
  out.push(prevX, prevY);
1552
1558
  anchorA.push(anchorCounter);
1553
1559
  anchorB.push(anchorCounter);
@@ -1617,6 +1623,9 @@ function flattenPolygon(p, tolerance) {
1617
1623
  break;
1618
1624
  }
1619
1625
  case PATH_Z: {
1626
+ prevX = startX;
1627
+ prevY = startY;
1628
+ prevAnchor = startAnchor;
1620
1629
  break;
1621
1630
  }
1622
1631
  default:
@@ -4489,6 +4498,7 @@ var WeaselRenderer = class {
4489
4498
  heightCss;
4490
4499
  dpr;
4491
4500
  canvas = null;
4501
+ target = null;
4492
4502
  imageMinification;
4493
4503
  flattenTolerance;
4494
4504
  bakeBudget;
@@ -4506,6 +4516,12 @@ var WeaselRenderer = class {
4506
4516
  const gl = opts.gl ?? opts.canvas.getContext("webgl2", { stencil: true });
4507
4517
  if (!gl) throw new Error("WeaselRenderer: WebGL2 not available");
4508
4518
  this.gl = gl;
4519
+ const attrs = typeof this.gl.getContextAttributes === "function" ? this.gl.getContextAttributes() : null;
4520
+ if (attrs && attrs.stencil === false) {
4521
+ throw new Error(
4522
+ "WeaselRenderer: the supplied WebGL2 context has no stencil buffer. Create it with { stencil: true } \u2014 clips and even-odd fills need one."
4523
+ );
4524
+ }
4509
4525
  this.widthCss = opts.width;
4510
4526
  this.heightCss = opts.height;
4511
4527
  this.dpr = opts.dpr;
@@ -4524,12 +4540,8 @@ var WeaselRenderer = class {
4524
4540
  this.canvas.addEventListener("webglcontextlost", this.boundOnLost);
4525
4541
  this.canvas.addEventListener("webglcontextrestored", this.boundOnRestored);
4526
4542
  }
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();
4543
+ this.applyGlState();
4544
+ this.applyTarget();
4533
4545
  this.pathFill = new ShaderProgram(this.gl, VERT_SRC, FRAG_SRC);
4534
4546
  this.pathFill.lookupUniforms(PATH_FILL_UNIFORMS);
4535
4547
  this.pathFill.lookupAttributes(PATH_FILL_ATTRIBUTES);
@@ -4619,8 +4631,42 @@ var WeaselRenderer = class {
4619
4631
  }
4620
4632
  return this.programRegistry.get(id) ?? null;
4621
4633
  }
4622
- applyViewport() {
4623
- this.gl.viewport(0, 0, this.widthCss * this.dpr, this.heightCss * this.dpr);
4634
+ /** The GL state every frame assumes. Applied per `render()` rather than once
4635
+ * at construction because a co-tenant sharing this context moves all of it
4636
+ * between our frames. */
4637
+ applyGlState() {
4638
+ const gl = this.gl;
4639
+ gl.enable(gl.BLEND);
4640
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
4641
+ gl.disable(gl.DEPTH_TEST);
4642
+ gl.disable(gl.CULL_FACE);
4643
+ gl.clearColor(0, 0, 0, 0);
4644
+ }
4645
+ /** Viewport and scissor for this frame. Re-applied inside `render()` because
4646
+ * a co-tenant on the same context moves both between our frames. */
4647
+ applyTarget() {
4648
+ const gl = this.gl;
4649
+ const w = Math.round(this.widthCss * this.dpr);
4650
+ const h = Math.round(this.heightCss * this.dpr);
4651
+ if (!this.target) {
4652
+ gl.disable(gl.SCISSOR_TEST);
4653
+ gl.viewport(0, 0, w, h);
4654
+ return;
4655
+ }
4656
+ const x = Math.round(this.target.origin.x * this.dpr);
4657
+ const y = gl.drawingBufferHeight - Math.round(this.target.origin.y * this.dpr) - h;
4658
+ gl.viewport(x, y, w, h);
4659
+ gl.scissor(x, y, w, h);
4660
+ gl.enable(gl.SCISSOR_TEST);
4661
+ }
4662
+ /** Confine this renderer to a rect of its drawing buffer, or pass null to
4663
+ * give it the whole buffer back. Takes effect from the next `render()`. */
4664
+ setTarget(target) {
4665
+ this.target = target;
4666
+ this.applyTarget();
4667
+ }
4668
+ getTarget() {
4669
+ return this.target;
4624
4670
  }
4625
4671
  isContextLost() {
4626
4672
  return this.contextLost;
@@ -4631,12 +4677,8 @@ var WeaselRenderer = class {
4631
4677
  }
4632
4678
  onContextRestored() {
4633
4679
  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();
4680
+ this.applyGlState();
4681
+ this.applyTarget();
4640
4682
  this.pathFill = new ShaderProgram(this.gl, VERT_SRC, FRAG_SRC);
4641
4683
  this.pathFill.lookupUniforms(PATH_FILL_UNIFORMS);
4642
4684
  this.pathFill.lookupAttributes(PATH_FILL_ATTRIBUTES);
@@ -4744,8 +4786,12 @@ var WeaselRenderer = class {
4744
4786
  this.meshCache.drainPendingDeletes();
4745
4787
  resetBakeBudget(this.bakeBudget);
4746
4788
  this.groupState.reset();
4747
- gl.stencilMask(255);
4748
- gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
4789
+ this.applyGlState();
4790
+ this.applyTarget();
4791
+ if (this.target?.clear !== false) {
4792
+ gl.stencilMask(255);
4793
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
4794
+ }
4749
4795
  const ctx = {
4750
4796
  gl,
4751
4797
  pathFill: this.pathFill,
@@ -4788,7 +4834,7 @@ var WeaselRenderer = class {
4788
4834
  this.canvas.style.height = `${dims.height}px`;
4789
4835
  }
4790
4836
  }
4791
- this.applyViewport();
4837
+ this.applyTarget();
4792
4838
  }
4793
4839
  /** @internal */
4794
4840
  _gl() {
@@ -5191,13 +5237,13 @@ function deriveParallaxView(outer, opts) {
5191
5237
 
5192
5238
  // src/features/parallax/createParallaxLayer.ts
5193
5239
  function createParallaxLayer(opts) {
5194
- const { id, label, source, pan, zoom, anchor } = opts;
5240
+ const { id, label, source, pan, zoom, anchor, getOuterView } = opts;
5195
5241
  return {
5196
5242
  id,
5197
5243
  label,
5198
5244
  space: "screen",
5199
5245
  draw: (data, outer, dims) => {
5200
- const inner = deriveParallaxView(outer, { pan, zoom, anchor });
5246
+ const inner = deriveParallaxView(getOuterView?.() ?? outer, { pan, zoom, anchor });
5201
5247
  return source.flatMap((layer) => layer.draw(data, inner, dims));
5202
5248
  }
5203
5249
  };
@@ -6160,11 +6206,13 @@ function fitToBounds(viewportW, viewportH, contentW, contentH, paddingPx = 0, cl
6160
6206
  };
6161
6207
  }
6162
6208
 
6209
+ // src/core/viewport/zoomBounds.ts
6210
+ var DEFAULT_MIN_ZOOM = 0.1;
6211
+ var DEFAULT_MAX_ZOOM = 8;
6212
+
6163
6213
  // src/core/viewport/fitViewToBounds.ts
6164
- var SYSTEM_MAX_SCALE = 10;
6165
- var SYSTEM_MIN_SCALE = 0.1;
6166
6214
  function fitViewToBounds(bounds, viewportDims, currentView, opts = {}) {
6167
- const { padding = 16, maxScale = SYSTEM_MAX_SCALE, minScale = SYSTEM_MIN_SCALE } = opts;
6215
+ const { padding = 16, maxScale = DEFAULT_MAX_ZOOM, minScale = DEFAULT_MIN_ZOOM } = opts;
6168
6216
  if (bounds.width <= 0 || bounds.height <= 0) {
6169
6217
  console.warn("[weasel] fitViewToBounds: bounds has zero or negative area; returning currentView unchanged.", bounds);
6170
6218
  return currentView;
@@ -6210,15 +6258,19 @@ function fitViewToBounds(bounds, viewportDims, currentView, opts = {}) {
6210
6258
  }
6211
6259
 
6212
6260
  // src/core/viewport/zoomAt.ts
6261
+ function clampScale(scale2, min, max) {
6262
+ const magnitude = Math.min(max, Math.max(min, Math.abs(scale2)));
6263
+ return scale2 < 0 ? -magnitude : magnitude;
6264
+ }
6213
6265
  function zoomAt(view, anchor, factor, opts) {
6214
6266
  const fx = typeof factor === "number" ? factor : factor.x;
6215
6267
  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));
6268
+ const minX = typeof opts?.min === "number" ? opts.min : opts?.min?.x ?? DEFAULT_MIN_ZOOM;
6269
+ const minY = typeof opts?.min === "number" ? opts.min : opts?.min?.y ?? DEFAULT_MIN_ZOOM;
6270
+ const maxX = typeof opts?.max === "number" ? opts.max : opts?.max?.x ?? DEFAULT_MAX_ZOOM;
6271
+ const maxY = typeof opts?.max === "number" ? opts.max : opts?.max?.y ?? DEFAULT_MAX_ZOOM;
6272
+ const nextX = clampScale(view.scale.x * fx, minX, maxX);
6273
+ const nextY = clampScale(view.scale.y * fy, minY, maxY);
6222
6274
  const worldX = anchor.x / view.scale.x + view.x;
6223
6275
  const worldY = anchor.y / view.scale.y + view.y;
6224
6276
  return {
@@ -6230,22 +6282,24 @@ function zoomAt(view, anchor, factor, opts) {
6230
6282
 
6231
6283
  // src/core/viewport/clampView.ts
6232
6284
  function clampView(view, bounds, canvas) {
6233
- const visW = canvas.width / view.scale.x;
6234
- const visH = canvas.height / view.scale.y;
6285
+ const visW = Math.abs(canvas.width / view.scale.x);
6286
+ const visH = Math.abs(canvas.height / view.scale.y);
6287
+ const flipX = view.scale.x < 0;
6288
+ const flipY = view.scale.y < 0;
6235
6289
  let x;
6236
6290
  if (visW >= bounds.width) {
6237
- x = bounds.x + (bounds.width - visW) / 2;
6291
+ x = bounds.x + (bounds.width - visW) / 2 + (flipX ? visW : 0);
6238
6292
  } else {
6239
- const minX = bounds.x;
6240
- const maxX = bounds.x + bounds.width - visW;
6293
+ const minX = flipX ? bounds.x + visW : bounds.x;
6294
+ const maxX = flipX ? bounds.x + bounds.width : bounds.x + bounds.width - visW;
6241
6295
  x = view.x < minX ? minX : view.x > maxX ? maxX : view.x;
6242
6296
  }
6243
6297
  let y;
6244
6298
  if (visH >= bounds.height) {
6245
- y = bounds.y + (bounds.height - visH) / 2;
6299
+ y = bounds.y + (bounds.height - visH) / 2 + (flipY ? visH : 0);
6246
6300
  } else {
6247
- const minY = bounds.y;
6248
- const maxY = bounds.y + bounds.height - visH;
6301
+ const minY = flipY ? bounds.y + visH : bounds.y;
6302
+ const maxY = flipY ? bounds.y + bounds.height : bounds.y + bounds.height - visH;
6249
6303
  y = view.y < minY ? minY : view.y > maxY ? maxY : view.y;
6250
6304
  }
6251
6305
  return x === view.x && y === view.y ? view : { x, y, scale: view.scale };
@@ -6274,8 +6328,8 @@ function isEditableTarget(t) {
6274
6328
  return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT";
6275
6329
  }
6276
6330
  function useZoom(opts) {
6277
- const min = opts.min ?? 0.1;
6278
- const max = opts.max ?? 10;
6331
+ const min = opts.min ?? DEFAULT_MIN_ZOOM;
6332
+ const max = opts.max ?? DEFAULT_MAX_ZOOM;
6279
6333
  const wheelStep = opts.wheelStep ?? 1.1;
6280
6334
  const keyStep = opts.keyStep ?? 1.25;
6281
6335
  const sources = useMemo(
@@ -8208,7 +8262,7 @@ function keyAnchor(view) {
8208
8262
  }
8209
8263
  var WHEEL_STEP = 1.1;
8210
8264
  function makeViewportZoomAction(opts = {}) {
8211
- const clamp2 = { min: opts.min ?? 0.1, max: opts.max ?? 8 };
8265
+ const clamp2 = { min: opts.min ?? DEFAULT_MIN_ZOOM, max: opts.max ?? DEFAULT_MAX_ZOOM };
8212
8266
  const wheelSpec = opts.wheel === "plain" ? { kind: "wheel" } : { kind: "wheel", mods: { mod: true } };
8213
8267
  const rawAnimate = opts.animate === true ? {} : opts.animate || null;
8214
8268
  const { resetMs, ...animateRest } = rawAnimate ?? {};
@@ -8928,7 +8982,7 @@ var sliceAction = {
8928
8982
 
8929
8983
  // src/interactions/actions/defaults/pinchZoom.ts
8930
8984
  function makePinchZoomAction(opts = {}) {
8931
- const clamp2 = { min: opts.min ?? 0.1, max: opts.max ?? 8 };
8985
+ const clamp2 = { min: opts.min ?? DEFAULT_MIN_ZOOM, max: opts.max ?? DEFAULT_MAX_ZOOM };
8932
8986
  return {
8933
8987
  id: "viewport.pinchZoom",
8934
8988
  label: "Pinch Zoom",
@@ -13670,8 +13724,6 @@ function useGestureDispatcher(opts) {
13670
13724
  }
13671
13725
 
13672
13726
  // src/core/viewport/wheelHandler.ts
13673
- var DEFAULT_MIN_ZOOM = 0.1;
13674
- var DEFAULT_MAX_ZOOM = 10;
13675
13727
  function computeWheelAction(state, input, bounds = { min: DEFAULT_MIN_ZOOM, max: DEFAULT_MAX_ZOOM }) {
13676
13728
  if (input.shiftKey) {
13677
13729
  return {
@@ -14036,6 +14088,76 @@ var SPRING_PRESETS = {
14036
14088
  slow: { stiffness: 80, damping: 20, mass: 1 }
14037
14089
  };
14038
14090
 
14091
+ // src/animation/easingSpec.ts
14092
+ var NEWTON_ITERATIONS = 8;
14093
+ var NEWTON_MIN_SLOPE = 1e-3;
14094
+ var SUBDIVISION_EPSILON = 1e-7;
14095
+ var SUBDIVISION_MAX = 12;
14096
+ function bezierAt(t, a1, a2) {
14097
+ const c = 3 * a1;
14098
+ const b = 3 * (a2 - a1) - c;
14099
+ const a = 1 - c - b;
14100
+ return ((a * t + b) * t + c) * t;
14101
+ }
14102
+ function bezierSlope(t, a1, a2) {
14103
+ const c = 3 * a1;
14104
+ const b = 3 * (a2 - a1) - c;
14105
+ const a = 1 - c - b;
14106
+ return (3 * a * t + 2 * b) * t + c;
14107
+ }
14108
+ function solveForX(x, x1, x2) {
14109
+ let t = x;
14110
+ for (let i = 0; i < NEWTON_ITERATIONS; i++) {
14111
+ const slope = bezierSlope(t, x1, x2);
14112
+ if (slope < NEWTON_MIN_SLOPE) break;
14113
+ t -= (bezierAt(t, x1, x2) - x) / slope;
14114
+ }
14115
+ let lo = 0;
14116
+ let hi = 1;
14117
+ t = Math.min(1, Math.max(0, t));
14118
+ for (let i = 0; i < SUBDIVISION_MAX; i++) {
14119
+ const err = bezierAt(t, x1, x2) - x;
14120
+ if (Math.abs(err) < SUBDIVISION_EPSILON) return t;
14121
+ if (err > 0) hi = t;
14122
+ else lo = t;
14123
+ t = (lo + hi) / 2;
14124
+ }
14125
+ return t;
14126
+ }
14127
+ function cubicBezierEasing(x1, y1, x2, y2) {
14128
+ const cx1 = Math.min(1, Math.max(0, x1));
14129
+ const cx2 = Math.min(1, Math.max(0, x2));
14130
+ return (t) => {
14131
+ if (t <= 0) return 0;
14132
+ if (t >= 1) return 1;
14133
+ return bezierAt(solveForX(t, cx1, cx2), y1, y2);
14134
+ };
14135
+ }
14136
+ var bezierCache = /* @__PURE__ */ new Map();
14137
+ function isBezier(spec) {
14138
+ return typeof spec === "object" && spec !== null && "bezier" in spec;
14139
+ }
14140
+ function resolveEasing(spec) {
14141
+ if (spec === void 0) return EASINGS.linear;
14142
+ if (typeof spec === "function") return spec;
14143
+ if (typeof spec === "string") {
14144
+ const fn = EASINGS[spec];
14145
+ if (!fn) throw new Error(`resolveEasing: unknown easing name "${spec}"`);
14146
+ return fn;
14147
+ }
14148
+ if (isBezier(spec)) {
14149
+ const [x1, y1, x2, y2] = spec.bezier;
14150
+ const key = `${x1},${y1},${x2},${y2}`;
14151
+ let fn = bezierCache.get(key);
14152
+ if (!fn) {
14153
+ fn = cubicBezierEasing(x1, y1, x2, y2);
14154
+ bezierCache.set(key, fn);
14155
+ }
14156
+ return fn;
14157
+ }
14158
+ throw new Error("resolveEasing: unrecognized easing spec");
14159
+ }
14160
+
14039
14161
  // src/animation/loop.ts
14040
14162
  function createLoop(createSupervisor, factory, opts = {}) {
14041
14163
  const max = opts.count ?? Infinity;
@@ -14076,6 +14198,7 @@ function createLoop(createSupervisor, factory, opts = {}) {
14076
14198
  supervisor.setTimeScale(s);
14077
14199
  current?.setTimeScale(s);
14078
14200
  },
14201
+ timeScale: () => supervisor.timeScale(),
14079
14202
  isPaused: () => supervisor.isPaused()
14080
14203
  };
14081
14204
  }
@@ -14260,6 +14383,9 @@ var CompositeHandle = class {
14260
14383
  this.timeScale_ = s;
14261
14384
  for (const c of this.children) c.setTimeScale(s);
14262
14385
  }
14386
+ timeScale() {
14387
+ return this.timeScale_;
14388
+ }
14263
14389
  isPaused() {
14264
14390
  return this.paused_;
14265
14391
  }
@@ -14369,7 +14495,7 @@ function sampleTrack(track, t, segmentCache) {
14369
14495
  const b = keys[i + 1];
14370
14496
  const span = b.t - a.t;
14371
14497
  const raw = span <= 0 ? 1 : (t - a.t) / span;
14372
- const u = b.easing ? b.easing(raw) : raw;
14498
+ const u = b.easing ? resolveEasing(b.easing)(raw) : raw;
14373
14499
  if (track.interpolator) {
14374
14500
  let fn = segmentCache?.get(i + 1);
14375
14501
  if (!fn) {
@@ -14450,7 +14576,10 @@ function createTimeline(register, id, opts) {
14450
14576
  for (const track of tracks) {
14451
14577
  if (track.kind === "event") {
14452
14578
  const end = firstAfter(track.events, to);
14453
- for (let i = firstAfter(track.events, from); i < end; i += 1) track.events[i].fire();
14579
+ for (let i = firstAfter(track.events, from); i < end; i += 1) {
14580
+ const ev = track.events[i];
14581
+ ev.fire(to - ev.t);
14582
+ }
14454
14583
  } else if (track.kind === "timeline") {
14455
14584
  fireEvents(track.timeline.tracks, from - track.at, to - track.at);
14456
14585
  }
@@ -14530,6 +14659,7 @@ function createTimeline(register, id, opts) {
14530
14659
  wantScale = s;
14531
14660
  base.setTimeScale(s);
14532
14661
  },
14662
+ timeScale: () => live ? base.timeScale() : wantScale,
14533
14663
  isPaused: () => live ? base.isPaused() : wantPaused,
14534
14664
  seek(t) {
14535
14665
  offset = t - lastVirtual;
@@ -14540,6 +14670,10 @@ function createTimeline(register, id, opts) {
14540
14670
  time: () => playhead,
14541
14671
  duration: () => duration,
14542
14672
  tracks: () => opts.tracks,
14673
+ setLoop(loop) {
14674
+ loopsLeft = loop === true ? Infinity : loop === false ? 0 : loop;
14675
+ },
14676
+ loop: () => loopsLeft === Infinity ? true : loopsLeft === 0 ? false : loopsLeft,
14543
14677
  edit(fn) {
14544
14678
  fn();
14545
14679
  caches = /* @__PURE__ */ new WeakMap();
@@ -14758,6 +14892,7 @@ function useAnimator(opts = {}) {
14758
14892
  const a = animations.current.get(anim.id);
14759
14893
  if (a) a.timeScale = s;
14760
14894
  },
14895
+ timeScale: () => animations.current.get(anim.id)?.timeScale ?? 1,
14761
14896
  isPaused: () => animations.current.get(anim.id)?.paused ?? false
14762
14897
  };
14763
14898
  };
@@ -14779,6 +14914,7 @@ function useAnimator(opts = {}) {
14779
14914
  pause: base.pause,
14780
14915
  resume: base.resume,
14781
14916
  setTimeScale: base.setTimeScale,
14917
+ timeScale: base.timeScale,
14782
14918
  isPaused: base.isPaused,
14783
14919
  setOnCancel: (cb) => {
14784
14920
  onCancelCb = cb;
@@ -14789,7 +14925,7 @@ function useAnimator(opts = {}) {
14789
14925
  const tween = (o) => {
14790
14926
  const id = nextId.current++;
14791
14927
  const start = 0;
14792
- const easing = o.easing ?? easeOut;
14928
+ const easing = resolveEasing(o.easing ?? easeOut);
14793
14929
  const factoryFn = o.interpolator ? o.interpolator(o.from, o.to) : null;
14794
14930
  const perTickInterp = factoryFn ? null : o.interpolate ?? ((a, b, t) => {
14795
14931
  if (typeof a === "number" && typeof b === "number") {
@@ -14944,6 +15080,7 @@ function useAnimator(opts = {}) {
14944
15080
  setTimeScale: (s) => {
14945
15081
  globalTimeScale.current = s;
14946
15082
  },
15083
+ timeScale: () => globalTimeScale.current,
14947
15084
  pauseKey: (key) => {
14948
15085
  for (const a of animations.current.values()) if (a.cancelKey === key) a.paused = true;
14949
15086
  },
@@ -15601,6 +15738,21 @@ function LineIcon({ className, size = 20 }) {
15601
15738
  }
15602
15739
  );
15603
15740
  }
15741
+ function ArrowIcon({ className, size = 20 }) {
15742
+ return /* @__PURE__ */ jsxs(
15743
+ "svg",
15744
+ {
15745
+ ...ICON_SVG_BASE,
15746
+ className,
15747
+ width: size,
15748
+ height: size,
15749
+ children: [
15750
+ /* @__PURE__ */ jsx("path", { d: "M3.5 16.5 12.9 7.1", strokeLinecap: "round" }),
15751
+ /* @__PURE__ */ jsx("path", { d: "M16.5 3.5 11.06 5.98 14.03 8.95Z", fill: "currentColor", strokeLinejoin: "round" })
15752
+ ]
15753
+ }
15754
+ );
15755
+ }
15604
15756
  function PolygonIcon({ className, size = 20 }) {
15605
15757
  return /* @__PURE__ */ jsx(
15606
15758
  "svg",
@@ -16274,6 +16426,14 @@ var TEXT_PAINTER = {
16274
16426
  );
16275
16427
  if (boxes.length === 0) return null;
16276
16428
  return rectsToPath(boxes);
16429
+ },
16430
+ // `filled` is unconditional: a text node's `data.fill: null` still resolves
16431
+ // to the default in `ResolvedRun`, so there is no outline-only text to
16432
+ // report. The reach is the point — a heavily outlined glyph was unpickable
16433
+ // across the width of its own outline.
16434
+ ink: (node, _pose, ctx) => {
16435
+ const d = node.data;
16436
+ return { filled: true, ...inkReach(resolveNodeStroke(d.stroke), ctx?.scale) };
16277
16437
  }
16278
16438
  };
16279
16439
  function rectsToPath(rects) {
@@ -16539,10 +16699,10 @@ var RECT_FALLBACK_PAINTER = {
16539
16699
  };
16540
16700
  function registerBuiltInShapePainters() {
16541
16701
  registerNodeShape(TEXT_PAINTER);
16702
+ registerNodeShape(DERIVED_PAINTER);
16542
16703
  registerNodeShape(PATH_PAINTER);
16543
16704
  registerNodeShape(SHAPE_PAINTER);
16544
16705
  registerNodeShape(IMAGE_PAINTER);
16545
- registerNodeShape(DERIVED_PAINTER);
16546
16706
  registerNodeShape(RECT_FALLBACK_PAINTER);
16547
16707
  }
16548
16708
  registerBuiltInShapePainters();
@@ -17571,11 +17731,7 @@ function useRotateTool(adapter, options) {
17571
17731
  [overlay]
17572
17732
  );
17573
17733
  }
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();
17734
+ function useHandTool(_opts = {}) {
17579
17735
  return useMemo(
17580
17736
  () => Object.assign(defineViewportTool({
17581
17737
  id: "hand",
@@ -17595,8 +17751,7 @@ function useHandTool(opts = {}) {
17595
17751
  // phase entry.
17596
17752
  bindings: [{ spec: { kind: "drag" }, actionId: "viewport.dragPan" }]
17597
17753
  }),
17598
- // eslint-disable-next-line react-hooks/exhaustive-deps
17599
- [inertia, axis, tracker, decay]
17754
+ []
17600
17755
  );
17601
17756
  }
17602
17757
  var PRESENTATION = {
@@ -17625,7 +17780,7 @@ function usePinchZoomTool(canvasRef, getView, setView, opts = {}) {
17625
17780
  getViewRef.current = getView;
17626
17781
  const setViewRef = useRef(setView);
17627
17782
  setViewRef.current = setView;
17628
- const { min = 0.1, max = 8, enabled = true } = opts;
17783
+ const { min = DEFAULT_MIN_ZOOM, max = DEFAULT_MAX_ZOOM, enabled = true } = opts;
17629
17784
  const resolveTargetRef = useRef(opts.resolveTarget);
17630
17785
  resolveTargetRef.current = opts.resolveTarget;
17631
17786
  usePinchGesture(canvasRef, (clientAnchor, scaleFactor) => {
@@ -19466,14 +19621,91 @@ function wrapNodeOutput(cmds, pose, alpha) {
19466
19621
  }
19467
19622
  return rotated;
19468
19623
  }
19469
- function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19624
+ function insetAlong(start, extent, size, align, by) {
19625
+ if (align === "start") return start + by;
19626
+ if (align === "end") return start + extent - size - by;
19627
+ return start + (extent - size) / 2 + by;
19628
+ }
19629
+ function hostAnchorRect(input) {
19630
+ const { host, panel, viewport, align, offset, padding = 0 } = input;
19631
+ const desired = {
19632
+ x: insetAlong(host.x, host.width, panel.width, align.x, offset.x),
19633
+ y: insetAlong(host.y, host.height, panel.height, align.y, offset.y),
19634
+ width: panel.width,
19635
+ height: panel.height
19636
+ };
19637
+ return clampRectWithin(desired, { x: 0, y: 0, width: viewport.width, height: viewport.height }, padding);
19638
+ }
19639
+ function hostAnchorCss(rect, align, viewport) {
19640
+ return {
19641
+ ...align.y === "end" ? { bottom: viewport.height - rect.y - rect.height } : { top: rect.y },
19642
+ ...align.x === "end" ? { right: viewport.width - rect.x - rect.width } : { left: rect.x }
19643
+ };
19644
+ }
19645
+
19646
+ // src/canvas/useHostAnchor.ts
19647
+ function useHostAnchor(resolveHost, options) {
19648
+ const [panel, setPanel] = useState(null);
19649
+ const [style, setStyle] = useState(null);
19650
+ const ref = useCallback((el) => setPanel(el), []);
19651
+ const resolve = useRef(resolveHost);
19652
+ resolve.current = resolveHost;
19653
+ const { align, offset, padding = 0 } = options;
19654
+ const { x: alignX, y: alignY } = align;
19655
+ const { x: offsetX, y: offsetY } = offset;
19656
+ const recompute = useCallback(() => {
19657
+ const hostEl = resolve.current();
19658
+ if (!hostEl) {
19659
+ setStyle(null);
19660
+ return;
19661
+ }
19662
+ const h = hostEl.getBoundingClientRect();
19663
+ const p = panel?.getBoundingClientRect();
19664
+ const viewport = { width: window.innerWidth, height: window.innerHeight };
19665
+ const align2 = { x: alignX, y: alignY };
19666
+ const rect = hostAnchorRect({
19667
+ host: { x: h.left, y: h.top, width: h.width, height: h.height },
19668
+ panel: { width: p?.width ?? 0, height: p?.height ?? 0 },
19669
+ viewport,
19670
+ align: align2,
19671
+ offset: { x: offsetX, y: offsetY },
19672
+ padding
19673
+ });
19674
+ setStyle(hostAnchorCss(rect, align2, viewport));
19675
+ }, [panel, alignX, alignY, offsetX, offsetY, padding]);
19676
+ const raf = useVisibleRaf(recompute);
19677
+ useEffect(() => {
19678
+ recompute();
19679
+ const schedule = () => raf.request();
19680
+ window.addEventListener("scroll", schedule, true);
19681
+ window.addEventListener("resize", schedule);
19682
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(schedule) : null;
19683
+ if (panel) observer?.observe(panel);
19684
+ const hostEl = resolve.current();
19685
+ if (hostEl) observer?.observe(hostEl);
19686
+ return () => {
19687
+ window.removeEventListener("scroll", schedule, true);
19688
+ window.removeEventListener("resize", schedule);
19689
+ raf.cancel();
19690
+ observer?.disconnect();
19691
+ };
19692
+ }, [recompute, raf, panel]);
19693
+ return { ref, style };
19694
+ }
19695
+ function CursorCoordsHud({ canvasRef, anchorRef, viewRef, offset }) {
19470
19696
  const [state, setState] = useState({
19471
19697
  client: { x: 0, y: 0 },
19472
19698
  world: null,
19473
- inCanvas: false,
19474
- anchor: null
19699
+ inCanvas: false
19475
19700
  });
19476
19701
  const [fps, setFps] = useState(0);
19702
+ const { ref, style: anchorStyle } = useHostAnchor(
19703
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19704
+ {
19705
+ align: { x: "end", y: "start" },
19706
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 }
19707
+ }
19708
+ );
19477
19709
  const framesRef = useRef(0);
19478
19710
  const lastFlushRef = useRef(0);
19479
19711
  const fpsLoop = useVisibleRaf(
@@ -19503,49 +19735,33 @@ function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19503
19735
  return () => fpsLoop.cancel();
19504
19736
  }, [fpsLoop]);
19505
19737
  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
19738
  const onMove = (e) => {
19514
19739
  const canvas = canvasRef.current;
19515
19740
  const view = viewRef.current;
19516
19741
  const client = { x: e.clientX, y: e.clientY };
19517
- const anchor = readAnchor();
19518
19742
  if (!canvas || !view) {
19519
- setState({ client, world: null, inCanvas: false, anchor });
19743
+ setState({ client, world: null, inCanvas: false });
19520
19744
  return;
19521
19745
  }
19522
19746
  const rect = canvas.getBoundingClientRect();
19523
19747
  const inCanvas = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
19524
19748
  const [wx, wy] = clientToWorld(e.clientX, e.clientY, rect, view);
19525
19749
  const world = { x: wx, y: wy };
19526
- setState({ client, world, inCanvas, anchor });
19750
+ setState({ client, world, inCanvas });
19527
19751
  };
19528
- const onLayout = () => setState((s) => ({ ...s, anchor: readAnchor() }));
19529
19752
  document.addEventListener("pointermove", onMove);
19530
- window.addEventListener("scroll", onLayout, true);
19531
- window.addEventListener("resize", onLayout);
19532
- setState((s) => ({ ...s, anchor: readAnchor() }));
19533
19753
  return () => {
19534
19754
  document.removeEventListener("pointermove", onMove);
19535
- window.removeEventListener("scroll", onLayout, true);
19536
- window.removeEventListener("resize", onLayout);
19537
19755
  };
19538
19756
  }, [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);
19757
+ if (!anchorStyle) return null;
19542
19758
  return /* @__PURE__ */ jsxs(
19543
19759
  "div",
19544
19760
  {
19761
+ ref,
19545
19762
  style: {
19546
19763
  position: "fixed",
19547
- top,
19548
- right,
19764
+ ...anchorStyle,
19549
19765
  zIndex: 1e4,
19550
19766
  background: "rgba(0,0,0,0.7)",
19551
19767
  color: "#e8e8e8",
@@ -19570,33 +19786,31 @@ function CursorCoordsHud({ canvasRef, viewRef, offset }) {
19570
19786
 
19571
19787
  // src/canvas/PickHud.module.css
19572
19788
  var PickHud_default = {};
19573
- function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19789
+ function PickHud({ canvasRef, anchorRef, viewRef, pickEvery, pickBest, offset }) {
19574
19790
  const [state, setState] = useState({
19575
19791
  ids: [],
19576
19792
  best: null,
19577
- inCanvas: false,
19578
- anchor: null
19793
+ inCanvas: false
19579
19794
  });
19795
+ const { ref, style } = useHostAnchor(
19796
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19797
+ {
19798
+ align: { x: "end", y: "start" },
19799
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 76 }
19800
+ }
19801
+ );
19580
19802
  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
19803
  const onMove = (e) => {
19589
19804
  const canvas = canvasRef.current;
19590
19805
  const view = viewRef.current;
19591
- const anchor = readAnchor();
19592
19806
  if (!canvas || !view) {
19593
- setState({ ids: [], best: null, inCanvas: false, anchor });
19807
+ setState({ ids: [], best: null, inCanvas: false });
19594
19808
  return;
19595
19809
  }
19596
19810
  const rect = canvas.getBoundingClientRect();
19597
19811
  const inCanvas = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
19598
19812
  if (!inCanvas) {
19599
- setState({ ids: [], best: null, inCanvas: false, anchor });
19813
+ setState({ ids: [], best: null, inCanvas: false });
19600
19814
  return;
19601
19815
  }
19602
19816
  const worldX = (e.clientX - rect.left) / view.scale.x + view.x;
@@ -19615,24 +19829,15 @@ function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19615
19829
  best = null;
19616
19830
  }
19617
19831
  }
19618
- setState({ ids, best, inCanvas: true, anchor });
19832
+ setState({ ids, best, inCanvas: true });
19619
19833
  };
19620
- const onLayout = () => setState((s) => ({ ...s, anchor: readAnchor() }));
19621
19834
  document.addEventListener("pointermove", onMove);
19622
- window.addEventListener("scroll", onLayout, true);
19623
- window.addEventListener("resize", onLayout);
19624
- setState((s) => ({ ...s, anchor: readAnchor() }));
19625
19835
  return () => {
19626
19836
  document.removeEventListener("pointermove", onMove);
19627
- window.removeEventListener("scroll", onLayout, true);
19628
- window.removeEventListener("resize", onLayout);
19629
19837
  };
19630
19838
  }, [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: [
19839
+ if (!style) return null;
19840
+ return /* @__PURE__ */ jsxs("div", { ref, className: PickHud_default.hud, style, children: [
19636
19841
  /* @__PURE__ */ jsxs("div", { className: PickHud_default.header, children: [
19637
19842
  "pickEvery (",
19638
19843
  state.ids.length,
@@ -19651,34 +19856,20 @@ function PickHud({ canvasRef, viewRef, pickEvery, pickBest, offset }) {
19651
19856
 
19652
19857
  // src/canvas/ModalityHud.module.css
19653
19858
  var ModalityHud_default = {};
19654
- function ModalityHud({ canvasRef, modeId, offset }) {
19859
+ function ModalityHud({ canvasRef, anchorRef, modeId, offset }) {
19655
19860
  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 };
19861
+ const { ref, style } = useHostAnchor(
19862
+ () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,
19863
+ {
19864
+ align: { x: "end", y: "start" },
19865
+ offset: { x: offset?.right ?? 8, y: offset?.top ?? 220 }
19866
+ }
19867
+ );
19868
+ if (!style) return null;
19678
19869
  const active = toolCtx?.active ?? null;
19679
19870
  const hotkeys = toolCtx?.hotkeyStack ?? [];
19680
19871
  const hotkeyTop = hotkeys.length > 0 ? hotkeys[hotkeys.length - 1] : null;
19681
- return /* @__PURE__ */ jsxs("div", { className: ModalityHud_default.hud, style, children: [
19872
+ return /* @__PURE__ */ jsxs("div", { ref, className: ModalityHud_default.hud, style, children: [
19682
19873
  /* @__PURE__ */ jsxs("div", { className: ModalityHud_default.row, children: [
19683
19874
  /* @__PURE__ */ jsx("span", { className: ModalityHud_default.label, children: "mode" }),
19684
19875
  /* @__PURE__ */ jsx("span", { className: modeId ? ModalityHud_default.value : ModalityHud_default.valueMuted, children: modeId ?? "\u2014" })
@@ -19809,6 +20000,8 @@ function CanvasInner(props, ref) {
19809
20000
  boundsOf: boundsOf2,
19810
20001
  pickEvery,
19811
20002
  clientToWorld: clientToWorld2,
20003
+ paintInto,
20004
+ inputElement,
19812
20005
  geometry = AUTO_POSE_DESCRIPTOR,
19813
20006
  className,
19814
20007
  style,
@@ -19854,6 +20047,15 @@ function CanvasInner(props, ref) {
19854
20047
  debugSinkRefForCtx.current = debugSink;
19855
20048
  const adapter = adapterProp;
19856
20049
  const canvasRef = useRef(null);
20050
+ const ownCanvasRef = useRef(null);
20051
+ const detached = !!paintInto;
20052
+ if (detached) {
20053
+ canvasRef.current = inputElement ?? null;
20054
+ }
20055
+ const paintTargetRef = useRef(null);
20056
+ paintTargetRef.current = detached ? paintInto.canvas ?? null : null;
20057
+ const paintRectRef = useRef(null);
20058
+ paintRectRef.current = detached ? { x: paintInto.x, y: paintInto.y } : null;
19857
20059
  const helpersForLayersRef = useRef(null);
19858
20060
  const dimsRef = useRef({ width, height });
19859
20061
  dimsRef.current = { width, height };
@@ -19941,7 +20143,10 @@ function CanvasInner(props, ref) {
19941
20143
  };
19942
20144
  }, []);
19943
20145
  useImperativeHandle(ref, () => ({
19944
- element: canvasRef.current,
20146
+ // Named rather than read off `canvasRef` so the handle rebuilds when a
20147
+ // detached surface's input element arrives, which is a render later.
20148
+ element: detached ? inputElement ?? null : canvasRef.current,
20149
+ surface: detached ? paintInto?.canvas ?? null : ownCanvasRef.current,
19945
20150
  requestRedraw,
19946
20151
  subscribeFrame,
19947
20152
  registerLayer,
@@ -19952,6 +20157,10 @@ function CanvasInner(props, ref) {
19952
20157
  getPaintedVersion
19953
20158
  }), [
19954
20159
  canvasRef,
20160
+ ownCanvasRef,
20161
+ detached,
20162
+ inputElement,
20163
+ paintInto?.canvas,
19955
20164
  requestRedraw,
19956
20165
  subscribeFrame,
19957
20166
  registerLayer,
@@ -20247,8 +20456,9 @@ function CanvasInner(props, ref) {
20247
20456
  shaders
20248
20457
  };
20249
20458
  const paint = useCallback(() => {
20250
- const c = canvasRef.current;
20459
+ const c = paintTargetRef.current ?? ownCanvasRef.current;
20251
20460
  if (!c) return false;
20461
+ const rect = paintRectRef.current;
20252
20462
  const {
20253
20463
  layers: paintLayers,
20254
20464
  width: w,
@@ -20277,7 +20487,9 @@ function CanvasInner(props, ref) {
20277
20487
  try {
20278
20488
  renderer = new WeaselRenderer({
20279
20489
  gl,
20280
- canvas: c,
20490
+ // A shared buffer is the caller's to size. Handing the renderer the
20491
+ // element would have every co-tenant resize it to its own pane.
20492
+ ...rect ? {} : { canvas: c },
20281
20493
  width: w,
20282
20494
  height: h,
20283
20495
  dpr
@@ -20296,6 +20508,7 @@ function CanvasInner(props, ref) {
20296
20508
  lastResizeRef.current = { w, h, dpr };
20297
20509
  }
20298
20510
  }
20511
+ renderer.setTarget(rect ? { origin: { x: rect.x, y: rect.y } } : null);
20299
20512
  const view = viewRef.current;
20300
20513
  const commands = drawLayers(
20301
20514
  paintLayers,
@@ -20344,31 +20557,69 @@ function CanvasInner(props, ref) {
20344
20557
  }, [shaderIdKey]);
20345
20558
  const toolsCursor = tools ? resolveToolsCursor(tools, toolsCtxBase) : void 0;
20346
20559
  const effectiveStyle = toolsCursor ? { ...style, cursor: toolsCursor } : style;
20347
- return /* @__PURE__ */ jsxs(Fragment, { children: [
20348
- /* @__PURE__ */ jsx(
20349
- "canvas",
20560
+ const layersForMoveRef = useRef(layersWithDebug);
20561
+ layersForMoveRef.current = layersWithDebug;
20562
+ useEffect(() => {
20563
+ if (!detached || !inputElement) return;
20564
+ const el = inputElement;
20565
+ const onDown = () => {
20566
+ if (autoFocusOnPointerDown) el.focus();
20567
+ pointerDownRef.current = true;
20568
+ };
20569
+ const onMove = (e) => {
20570
+ if (pointerDownRef.current) return;
20571
+ const view = viewRef.current;
20572
+ const [worldX, worldY] = toWorld(
20573
+ el,
20574
+ e.clientX,
20575
+ e.clientY,
20576
+ view,
20577
+ clientToWorldRef.current
20578
+ );
20579
+ const dims = dimsRef.current;
20580
+ for (const layer of layersForMoveRef.current) {
20581
+ layer.onUncapturedMove?.(worldX, worldY, e, view, dims);
20582
+ }
20583
+ };
20584
+ const onUp = () => {
20585
+ pointerDownRef.current = false;
20586
+ };
20587
+ const onLeave = () => {
20588
+ pointerDownRef.current = false;
20589
+ for (const layer of layersForMoveRef.current) layer.onUncapturedLeave?.();
20590
+ };
20591
+ const onMenu = (e) => e.preventDefault();
20592
+ el.addEventListener("pointerdown", onDown);
20593
+ el.addEventListener("pointermove", onMove);
20594
+ el.addEventListener("pointerup", onUp);
20595
+ el.addEventListener("pointerleave", onLeave);
20596
+ el.addEventListener("contextmenu", onMenu);
20597
+ return () => {
20598
+ el.removeEventListener("pointerdown", onDown);
20599
+ el.removeEventListener("pointermove", onMove);
20600
+ el.removeEventListener("pointerup", onUp);
20601
+ el.removeEventListener("pointerleave", onLeave);
20602
+ el.removeEventListener("contextmenu", onMenu);
20603
+ };
20604
+ }, [detached, inputElement, autoFocusOnPointerDown]);
20605
+ useEffect(() => {
20606
+ if (!detached || !inputElement) return;
20607
+ inputElement.style.cursor = toolsCursor ?? "";
20608
+ }, [detached, inputElement, toolsCursor]);
20609
+ const huds = /* @__PURE__ */ jsxs(Fragment, { children: [
20610
+ cursorCoordsHud && /* @__PURE__ */ jsx(
20611
+ CursorCoordsHud,
20350
20612
  {
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()
20613
+ canvasRef,
20614
+ ...detached ? { anchorRef: canvasRef } : {},
20615
+ viewRef
20365
20616
  }
20366
20617
  ),
20367
- cursorCoordsHud && /* @__PURE__ */ jsx(CursorCoordsHud, { canvasRef, viewRef }),
20368
20618
  pickHud && /* @__PURE__ */ jsx(
20369
20619
  PickHud,
20370
20620
  {
20371
20621
  canvasRef,
20622
+ ...detached ? { anchorRef: canvasRef } : {},
20372
20623
  viewRef,
20373
20624
  pickEvery: stablePickEveryForHud,
20374
20625
  pickBest: stablePickBestForHud
@@ -20378,10 +20629,37 @@ function CanvasInner(props, ref) {
20378
20629
  ModalityHud,
20379
20630
  {
20380
20631
  canvasRef,
20632
+ ...detached ? { anchorRef: canvasRef } : {},
20381
20633
  modeId: typeof modalityHud === "object" ? modalityHud.modeId : void 0
20382
20634
  }
20383
20635
  )
20384
20636
  ] });
20637
+ if (detached) return inputElement ? huds : null;
20638
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
20639
+ /* @__PURE__ */ jsx(
20640
+ "canvas",
20641
+ {
20642
+ ref: (el) => {
20643
+ ownCanvasRef.current = el;
20644
+ canvasRef.current = el;
20645
+ },
20646
+ width,
20647
+ height,
20648
+ tabIndex,
20649
+ className,
20650
+ style: effectiveStyle,
20651
+ onFocus,
20652
+ onBlur,
20653
+ onPointerDown: handlePointerDown,
20654
+ onPointerMove: handlePointerMove,
20655
+ onPointerUp: handlePointerUp,
20656
+ onPointerCancel: handlePointerCancel,
20657
+ onPointerLeave: handlePointerLeave,
20658
+ onContextMenu: (e) => e.preventDefault()
20659
+ }
20660
+ ),
20661
+ huds
20662
+ ] });
20385
20663
  }
20386
20664
  var Canvas = forwardRef(CanvasInner);
20387
20665
 
@@ -23044,7 +23322,7 @@ function useDispatcherOverlayLayer(args) {
23044
23322
  break;
23045
23323
  case "pencil": {
23046
23324
  if (geom.samples.length < 2) break;
23047
- pathCmd = polygonFromPoints(projectPoints(geom.samples));
23325
+ pathCmd = polylineFromPoints(projectPoints(geom.samples));
23048
23326
  break;
23049
23327
  }
23050
23328
  }
@@ -23056,7 +23334,7 @@ function useDispatcherOverlayLayer(args) {
23056
23334
  stroke: { paint: { color: cfg.stroke }, width: cfg.lineWidth, dash: cfg.dash }
23057
23335
  };
23058
23336
  out.push(cmd);
23059
- if (ov.anchorPoint) {
23337
+ if (ov.anchorPoint && ov.shape !== "pencil") {
23060
23338
  const anchorScreen = projectPoint(ov.anchorPoint.x, ov.anchorPoint.y);
23061
23339
  out.push({
23062
23340
  kind: "path",
@@ -24979,7 +25257,7 @@ function SceneCanvasInner(props, ref) {
24979
25257
  boundary: inertiaObj.boundary,
24980
25258
  bounds: inertiaObj.bounds
24981
25259
  } : void 0;
24982
- const handTool = useHandTool(handToolInertia ? { inertia: handToolInertia } : {});
25260
+ const handTool = useHandTool(handToolInertia ? { } : {});
24983
25261
  const viewportAmbient = [];
24984
25262
  const baseRequestedTools = defaultTools ?? (toolBundle ? BUNDLE_TOOLS[toolBundle] : null) ?? (viewportRegistered ? ["select", "rotate", "hand"] : ["select", "rotate"]);
24985
25263
  const KNOWN_BUILTIN_IDS = /* @__PURE__ */ new Set([
@@ -25704,14 +25982,12 @@ function StandardActionsRegistrar({
25704
25982
  }, [registry2, actionsRegistryRef]);
25705
25983
  useEffect(() => {
25706
25984
  if (!registry2) return;
25707
- registry2.setDispatcher(dispatcher);
25708
- return () => registry2.setDispatcher(null);
25985
+ return registry2.setDispatcher(dispatcher);
25709
25986
  }, [registry2, dispatcher]);
25710
25987
  const wiredDepRegistry = useDepRegistry();
25711
25988
  useEffect(() => {
25712
25989
  if (!registry2) return;
25713
- registry2.setDepRegistry(wiredDepRegistry);
25714
- return () => registry2.setDepRegistry(null);
25990
+ return registry2.setDepRegistry(wiredDepRegistry);
25715
25991
  }, [registry2, wiredDepRegistry]);
25716
25992
  useEffect(() => {
25717
25993
  if (!registry2) return;
@@ -25927,9 +26203,9 @@ function shapeSchema(opts = {}) {
25927
26203
  fontWeight: { kind: "number", name: "Weight", description: "Font weight, 100\u2013900.", default: 400, min: 100, max: 900, step: 100, pair: "Size / weight" },
25928
26204
  fontStyle: { kind: "enum", name: "Style", description: "Upright or italic.", default: "normal", options: [{ value: "normal", label: "Normal" }, { value: "italic", label: "Italic" }] },
25929
26205
  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 }
26206
+ underline: { kind: "boolean", name: "Underline", description: "Underline the text.", default: false, control: "toggle", short: "U", pair: "Decoration" },
26207
+ strikethrough: { kind: "boolean", name: "Strikethrough", description: "Strike through the text.", default: false, control: "toggle", short: "S", pair: "Decoration" },
26208
+ overline: { kind: "boolean", name: "Overline", description: "Rule the text above its ascent.", default: false, control: "toggle", short: "O", pair: "Decoration" }
25933
26209
  }
25934
26210
  },
25935
26211
  paragraph: {
@@ -26399,8 +26675,13 @@ function renderSceneToPixels(args) {
26399
26675
  renderer.dispose();
26400
26676
  }
26401
26677
  }
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 }) }) }) }) });
26678
+ function WeaselProvider({ children, isolate = false }) {
26679
+ const Deps = isolate ? DepRegistryProvider : DepRegistryProviderIfRoot;
26680
+ const Actions = isolate ? ActionsProvider : ActionsProviderIfRoot;
26681
+ const ActiveTool = isolate ? ActiveToolContextProvider : ActiveToolContextProviderIfRoot;
26682
+ const Selection = isolate ? SelectionContextProvider : SelectionContextProviderIfRoot;
26683
+ const Pointer = isolate ? PointerContextProvider : PointerProviderIfRoot;
26684
+ return /* @__PURE__ */ jsx(Deps, { children: /* @__PURE__ */ jsx(Actions, { children: /* @__PURE__ */ jsx(ActiveTool, { children: /* @__PURE__ */ jsx(Selection, { children: /* @__PURE__ */ jsx(Pointer, { children }) }) }) }) });
26404
26685
  }
26405
26686
  function useCanvasFocus(options = {}) {
26406
26687
  const { initial = false, tabIndex = 0 } = options;
@@ -27557,7 +27838,7 @@ function useSceneTextEdit(scene, container, options = {}) {
27557
27838
  }
27558
27839
  });
27559
27840
  const onDoubleClick = useCallback((e) => {
27560
- const canvas = e.target instanceof HTMLCanvasElement ? e.target : null;
27841
+ const canvas = e.target instanceof HTMLElement ? e.target : null;
27561
27842
  if (!canvas) return;
27562
27843
  const [canvasX, canvasY] = clientToCanvas(canvas, e.clientX, e.clientY);
27563
27844
  const view = resolveView2(optsRef.current.view);
@@ -27802,6 +28083,8 @@ function polygonPathDistance(path, px, py) {
27802
28083
  if (d2 < best) best = d2;
27803
28084
  curX = startX;
27804
28085
  curY = startY;
28086
+ } else {
28087
+ throw new Error(`pathDistanceToPoint: unknown command code ${cmd}`);
27805
28088
  }
27806
28089
  }
27807
28090
  return best === Infinity ? Infinity : Math.sqrt(best);
@@ -29919,7 +30202,7 @@ function cycleVertexColors(animator, opts) {
29919
30202
  const interp = resolveInterpolator(opts);
29920
30203
  const { id, channel } = opts;
29921
30204
  const direction = opts.direction ?? 1;
29922
- const easing = opts.easing ?? ((t) => t);
30205
+ const easing = resolveEasing(opts.easing);
29923
30206
  const override = (base, tMs) => {
29924
30207
  const n = base.length / 4;
29925
30208
  if (n === 0) return base.slice();
@@ -29960,7 +30243,7 @@ function staggerVertexColors(animator, opts) {
29960
30243
  const interp = resolveInterpolator(opts);
29961
30244
  const { id, channel, from, to, anchorMs, perAnchorDelay } = opts;
29962
30245
  const n = from.length / 4;
29963
- const easing = opts.easing ?? ((t) => t);
30246
+ const easing = resolveEasing(opts.easing);
29964
30247
  const originIndex = opts.origin === "last" ? n - 1 : typeof opts.origin === "number" ? Math.max(0, Math.min(n - 1, opts.origin)) : 0;
29965
30248
  const maxDistance = Math.max(originIndex, n - 1 - originIndex);
29966
30249
  const totalMs = maxDistance * perAnchorDelay + anchorMs;
@@ -30402,6 +30685,6 @@ function mergeContributions(...bundles) {
30402
30685
  return out;
30403
30686
  }
30404
30687
 
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
30688
+ 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 };
30689
+ //# sourceMappingURL=chunk-IMFXEINV.js.map
30690
+ //# sourceMappingURL=chunk-IMFXEINV.js.map