@weasel-js/labkit 1.4.0-pre.1 → 1.4.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.
Files changed (95) hide show
  1. package/dist/_dts/{CanvasStackContext-LnCfqNBA.d.ts → CanvasStackContext-D6M0o8cQ.d.ts} +1 -1
  2. package/dist/_dts/{frac-C-2c72Ij.d.ts → frac-QS7XzvpG.d.ts} +2 -2
  3. package/dist/_dts/{index-BDVzvRzQ.d.ts → index-B2X21G1c.d.ts} +8 -2
  4. package/dist/_dts/{types-D6s4b7if.d.ts → types-C1Zw7s5P.d.ts} +1 -0
  5. package/dist/_dts/{types-DYMaEvM5.d.ts → types-ChVJJHvk.d.ts} +3 -0
  6. package/dist/_dts/{useTrialState-gmMvZqPc.d.ts → useTrialState-Cdm13fvl.d.ts} +2 -1
  7. package/dist/canvas/index.d.ts +6 -6
  8. package/dist/canvas/index.js +2 -2
  9. package/dist/chrome/index.d.ts +4 -4
  10. package/dist/chrome/index.js +5 -5
  11. package/dist/chunk-2YILQ7Y5.js +33 -0
  12. package/dist/chunk-2YILQ7Y5.js.map +1 -0
  13. package/dist/{chunk-QB5SM4BM.js → chunk-4AMN4MMB.js} +5 -5
  14. package/dist/{chunk-QB5SM4BM.js.map → chunk-4AMN4MMB.js.map} +1 -1
  15. package/dist/{chunk-L5QJOOLV.js → chunk-7VW3S44V.js} +512 -56
  16. package/dist/chunk-7VW3S44V.js.map +1 -0
  17. package/dist/{chunk-ESIQNQ6K.js → chunk-B5VWJBWM.js} +12 -6
  18. package/dist/chunk-B5VWJBWM.js.map +1 -0
  19. package/dist/{chunk-RBGKL7NF.js → chunk-L5WBGUVR.js} +1664 -1628
  20. package/dist/chunk-L5WBGUVR.js.map +1 -0
  21. package/dist/{chunk-XJ6N32QP.js → chunk-LJSIUFYD.js} +14 -30
  22. package/dist/chunk-LJSIUFYD.js.map +1 -0
  23. package/dist/{chunk-HHGVISVZ.js → chunk-QR5V3AFG.js} +6 -4
  24. package/dist/chunk-QR5V3AFG.js.map +1 -0
  25. package/dist/{chunk-6OEYTYML.js → chunk-UD7TEHZT.js} +15 -15
  26. package/dist/chunk-UD7TEHZT.js.map +1 -0
  27. package/dist/{chunk-HMFODCOX.js → chunk-VHFQKAUL.js} +3 -3
  28. package/dist/{chunk-HMFODCOX.js.map → chunk-VHFQKAUL.js.map} +1 -1
  29. package/dist/{chunk-TO2FUOKF.js → chunk-W3KSUXXR.js} +16 -13
  30. package/dist/chunk-W3KSUXXR.js.map +1 -0
  31. package/dist/{chunk-AE5CNVRU.js → chunk-XCBCZEBO.js} +3 -3
  32. package/dist/{chunk-AE5CNVRU.js.map → chunk-XCBCZEBO.js.map} +1 -1
  33. package/dist/{chunk-E2UQVZ44.js → chunk-Y2HK44TG.js} +3 -3
  34. package/dist/{chunk-E2UQVZ44.js.map → chunk-Y2HK44TG.js.map} +1 -1
  35. package/dist/{chunk-M75ZU6ZZ.js → chunk-YQGQUBKA.js} +3 -3
  36. package/dist/{chunk-M75ZU6ZZ.js.map → chunk-YQGQUBKA.js.map} +1 -1
  37. package/dist/controls/index.d.ts +2 -2
  38. package/dist/controls/index.js +3 -3
  39. package/dist/dragdrop/index.d.ts +3 -3
  40. package/dist/dragdrop/index.js +2 -2
  41. package/dist/index.d.ts +55 -12
  42. package/dist/index.js +306 -159
  43. package/dist/index.js.map +1 -1
  44. package/dist/layers/index.d.ts +4 -4
  45. package/dist/layers/index.js +3 -3
  46. package/dist/loupe/index.d.ts +5 -5
  47. package/dist/loupe/index.js +2 -2
  48. package/dist/passthrough/weasel-canvas.js +1 -1
  49. package/dist/passthrough/weasel-ui.d.ts +336 -15
  50. package/dist/passthrough/weasel-ui.js +2 -2
  51. package/dist/primitives/index.js +4 -4
  52. package/dist/state/index.d.ts +3 -3
  53. package/dist/state/index.js +4 -2
  54. package/dist/state/index.js.map +1 -1
  55. package/dist/styles.css +64 -5
  56. package/dist/surface/index.d.ts +17 -2
  57. package/dist/surface/index.js +3 -2
  58. package/dist/ui/layers/index.js +2 -2
  59. package/dist/undo/index.d.ts +3 -3
  60. package/package.json +8 -8
  61. package/src/annotations/AnnotationOverlay.tsx +10 -6
  62. package/src/annotations/Annotations.less +6 -0
  63. package/src/annotations/Annotations.overlay.test.tsx +113 -0
  64. package/src/annotations/MarkList.tsx +3 -2
  65. package/src/config/builder.test.ts +5 -0
  66. package/src/config/builder.ts +6 -0
  67. package/src/config/types.ts +1 -0
  68. package/src/controls/ControlPanel.test.tsx +23 -0
  69. package/src/controls/ControlPanel.tsx +3 -0
  70. package/src/lab/Lab.surface.test.tsx +8 -3
  71. package/src/lab/LabHeader.test.tsx +12 -0
  72. package/src/lab/LabHeader.tsx +16 -6
  73. package/src/passthrough/weasel-ui.test.ts +9 -0
  74. package/src/passthrough/weasel-ui.ts +4 -0
  75. package/src/primitives/ZoomControl.tsx +2 -0
  76. package/src/state/store.ts +10 -0
  77. package/src/state/types.ts +3 -0
  78. package/src/surface/AGENTS.md +11 -1
  79. package/src/surface/index.ts +7 -1
  80. package/src/surface/useSurfaceTile.ts +20 -2
  81. package/src/surface/useTiledSurface.ts +4 -1
  82. package/src/theme/Interstellar.stories.tsx +4 -3
  83. package/src/theme/base.less +39 -1
  84. package/src/trial/Trial.less +27 -5
  85. package/src/trial/TrialBody.test.tsx +67 -0
  86. package/src/trial/TrialBody.tsx +155 -0
  87. package/src/trial/TrialChrome.tsx +18 -10
  88. package/src/trial/index.ts +2 -0
  89. package/dist/chunk-6OEYTYML.js.map +0 -1
  90. package/dist/chunk-ESIQNQ6K.js.map +0 -1
  91. package/dist/chunk-HHGVISVZ.js.map +0 -1
  92. package/dist/chunk-L5QJOOLV.js.map +0 -1
  93. package/dist/chunk-RBGKL7NF.js.map +0 -1
  94. package/dist/chunk-TO2FUOKF.js.map +0 -1
  95. package/dist/chunk-XJ6N32QP.js.map +0 -1
@@ -1,9 +1,9 @@
1
- import { createContext, createElement, forwardRef, useMemo, useRef, useCallback, useState, useImperativeHandle, useSyncExternalStore, useEffect, useLayoutEffect, useContext, useId, useReducer } from 'react';
1
+ import { createContext, createElement, forwardRef, useMemo, useRef, useCallback, useState, useEffect, useImperativeHandle, useSyncExternalStore, useLayoutEffect, useContext, useId, useReducer } from 'react';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import earcut from 'earcut';
4
4
  import polygonClipping from 'polygon-clipping';
5
5
 
6
- // ../core/dist/chunk-H6E6KPTU.js
6
+ // ../core/dist/chunk-UTIFY2UU.js
7
7
 
8
8
  // ../gestures/dist/index.js
9
9
  var GESTURE_DESCRIPTORS = [
@@ -287,7 +287,7 @@ function matchSpec(e, spec, isMac, phaseCtx) {
287
287
  }
288
288
  var EMPTY_ENGAGED = /* @__PURE__ */ new Set();
289
289
 
290
- // ../core/dist/chunk-H6E6KPTU.js
290
+ // ../core/dist/chunk-UTIFY2UU.js
291
291
  var DepRegistryContext = createContext(null);
292
292
  function DepRegistryProvider({ children }) {
293
293
  const sourcesRef = useRef(/* @__PURE__ */ new Map());
@@ -3845,30 +3845,65 @@ function eligibleContribution(reg, entry) {
3845
3845
  var CURSOR_INK = "#141418";
3846
3846
  var CURSOR_HALO = "#ffffff";
3847
3847
  var CURSOR_HALO_WIDTH = 2.6;
3848
+ var CURSOR_ANGLE_STEPS = 16;
3848
3849
  var CURSOR_MAX_CSS_PX = 128;
3849
- function renderHalo(p) {
3850
+ function halo(p, k) {
3850
3851
  switch (p.role) {
3851
3852
  case "ink":
3852
3853
  case "accent":
3853
- return `<path d="${p.d}" fill="${CURSOR_HALO}" stroke="${CURSOR_HALO}" stroke-width="${CURSOR_HALO_WIDTH}" stroke-linejoin="round"/>`;
3854
+ return { d: p.d, fill: CURSOR_HALO, stroke: { color: CURSOR_HALO, width: CURSOR_HALO_WIDTH * k } };
3854
3855
  case "stroke":
3855
- return `<path d="${p.d}" fill="none" stroke="${CURSOR_HALO}" stroke-width="${p.width + CURSOR_HALO_WIDTH}" stroke-linecap="round" stroke-linejoin="round"/>`;
3856
+ return { d: p.d, stroke: { color: CURSOR_HALO, width: (p.width + CURSOR_HALO_WIDTH) * k } };
3856
3857
  // A detail IS halo-coloured and sits on top of the ink; it has no halo.
3857
3858
  case "detail":
3858
- return "";
3859
+ return null;
3859
3860
  }
3860
3861
  }
3861
- function renderInk(p) {
3862
+ function ink(p, k) {
3862
3863
  switch (p.role) {
3863
3864
  case "ink":
3864
- return `<path d="${p.d}" fill="${CURSOR_INK}"/>`;
3865
+ return { d: p.d, fill: CURSOR_INK };
3865
3866
  case "stroke":
3866
- return `<path d="${p.d}" fill="none" stroke="${CURSOR_INK}" stroke-width="${p.width}" stroke-linecap="round" stroke-linejoin="round"/>`;
3867
+ return { d: p.d, stroke: { color: CURSOR_INK, width: p.width * k } };
3867
3868
  case "detail":
3868
- return `<path d="${p.d}" fill="none" stroke="${CURSOR_HALO}" stroke-width="${p.width}" stroke-linecap="round"/>`;
3869
+ return { d: p.d, stroke: { color: CURSOR_HALO, width: p.width * k } };
3869
3870
  case "accent":
3870
- return `<path d="${p.d}" fill="${p.fill}"/>`;
3871
+ return { d: p.d, fill: p.fill };
3872
+ }
3873
+ }
3874
+ function cursorPaintOps(glyph, opts = {}) {
3875
+ const k = opts.lineWidthScale ?? 1;
3876
+ const out = [];
3877
+ for (const p of glyph.paths) {
3878
+ const h = halo(p, k);
3879
+ if (h) out.push(h);
3871
3880
  }
3881
+ for (const p of glyph.paths) out.push(ink(p, k));
3882
+ return out;
3883
+ }
3884
+ function cursorPaintMatrix(glyph, placement) {
3885
+ const s = placement.size / glyph.box;
3886
+ const theta = placement.angle ?? 0;
3887
+ const a = s * Math.cos(theta);
3888
+ const b = s * Math.sin(theta);
3889
+ const [hx, hy] = glyph.hotspot;
3890
+ return [a, b, -b, a, placement.at.x - (a * hx - b * hy), placement.at.y - (b * hx + a * hy)];
3891
+ }
3892
+ function cursorWorldSize(glyph, worldRadius, scale2) {
3893
+ const r = glyph.radius ?? glyph.box / 2;
3894
+ return worldRadius * scale2 * glyph.box / r;
3895
+ }
3896
+ function chromeLineWidthScale(glyph, size) {
3897
+ return glyph.box / size;
3898
+ }
3899
+ function quantizeCursorAngle(angle) {
3900
+ const i = Math.round(angle / (Math.PI * 2) * CURSOR_ANGLE_STEPS);
3901
+ return (i % CURSOR_ANGLE_STEPS + CURSOR_ANGLE_STEPS) % CURSOR_ANGLE_STEPS;
3902
+ }
3903
+ function renderOp(op) {
3904
+ const fill = op.fill === void 0 ? "none" : op.fill;
3905
+ const stroke = op.stroke ? ` stroke="${op.stroke.color}" stroke-width="${op.stroke.width}" stroke-linecap="round" stroke-linejoin="round"` : "";
3906
+ return `<path d="${op.d}" fill="${fill}"${stroke}/>`;
3872
3907
  }
3873
3908
  function bakeCursor(glyph, opts = {}) {
3874
3909
  const size = opts.size ?? 24;
@@ -3877,10 +3912,18 @@ function bakeCursor(glyph, opts = {}) {
3877
3912
  `cursor size ${size} exceeds the ${CURSOR_MAX_CSS_PX}px cap: the browser would drop the image and silently fall back. Use the painted tier.`
3878
3913
  );
3879
3914
  }
3880
- const body = glyph.paths.map(renderHalo).join("") + glyph.paths.map(renderInk).join("");
3915
+ const paths = cursorPaintOps(glyph).map(renderOp).join("");
3916
+ const c = glyph.box / 2;
3917
+ const step = quantizeCursorAngle(opts.angle ?? 0);
3918
+ const theta = step / CURSOR_ANGLE_STEPS * Math.PI * 2;
3919
+ const body = step === 0 ? paths : `<g transform="rotate(${step * 360 / CURSOR_ANGLE_STEPS} ${c} ${c})">${paths}</g>`;
3881
3920
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${glyph.box} ${glyph.box}">${body}</svg>`;
3882
- const hx = Math.round(glyph.hotspot[0] / glyph.box * size);
3883
- const hy = Math.round(glyph.hotspot[1] / glyph.box * size);
3921
+ const dx = glyph.hotspot[0] - c;
3922
+ const dy = glyph.hotspot[1] - c;
3923
+ const cos = Math.cos(theta);
3924
+ const sin = Math.sin(theta);
3925
+ const hx = Math.round((c + cos * dx - sin * dy) / glyph.box * size);
3926
+ const hy = Math.round((c + sin * dx + cos * dy) / glyph.box * size);
3884
3927
  const uri = `data:image/svg+xml,${encodeURIComponent(svg)}`;
3885
3928
  return `url("${uri}") ${hx} ${hy}, ${opts.fallback ?? "default"}`;
3886
3929
  }
@@ -3937,23 +3980,263 @@ var GLYPHS = {
3937
3980
  "d": "M 18.2 2.6 A 3.2 3.2 0 1 0 18.2 9 A 3.2 3.2 0 1 0 18.2 2.6 Z"
3938
3981
  }
3939
3982
  ]
3983
+ },
3984
+ "brush": {
3985
+ "box": 24,
3986
+ "hotspot": [
3987
+ 12,
3988
+ 12
3989
+ ],
3990
+ "radius": 9.9,
3991
+ "paths": [
3992
+ {
3993
+ "role": "stroke",
3994
+ "d": "M 12 2.1 A 9.9 9.9 0 1 0 12 21.9 A 9.9 9.9 0 1 0 12 2.1 Z",
3995
+ "width": 1.6
3996
+ }
3997
+ ]
3998
+ },
3999
+ "crosshairRect": {
4000
+ "box": 24,
4001
+ "hotspot": [
4002
+ 9,
4003
+ 9
4004
+ ],
4005
+ "paths": [
4006
+ {
4007
+ "role": "stroke",
4008
+ "d": "M 1.6 9 L 6.4 9",
4009
+ "width": 1.6
4010
+ },
4011
+ {
4012
+ "role": "stroke",
4013
+ "d": "M 11.6 9 L 16.4 9",
4014
+ "width": 1.6
4015
+ },
4016
+ {
4017
+ "role": "stroke",
4018
+ "d": "M 9 1.6 L 9 6.4",
4019
+ "width": 1.6
4020
+ },
4021
+ {
4022
+ "role": "stroke",
4023
+ "d": "M 9 11.6 L 9 16.4",
4024
+ "width": 1.6
4025
+ },
4026
+ {
4027
+ "role": "ink",
4028
+ "d": "M 14.2 14.2 L 21 14.2 L 21 21 L 14.2 21 Z"
4029
+ }
4030
+ ]
4031
+ },
4032
+ "crosshairEllipse": {
4033
+ "box": 24,
4034
+ "hotspot": [
4035
+ 9,
4036
+ 9
4037
+ ],
4038
+ "paths": [
4039
+ {
4040
+ "role": "stroke",
4041
+ "d": "M 1.6 9 L 6.4 9",
4042
+ "width": 1.6
4043
+ },
4044
+ {
4045
+ "role": "stroke",
4046
+ "d": "M 11.6 9 L 16.4 9",
4047
+ "width": 1.6
4048
+ },
4049
+ {
4050
+ "role": "stroke",
4051
+ "d": "M 9 1.6 L 9 6.4",
4052
+ "width": 1.6
4053
+ },
4054
+ {
4055
+ "role": "stroke",
4056
+ "d": "M 9 11.6 L 9 16.4",
4057
+ "width": 1.6
4058
+ },
4059
+ {
4060
+ "role": "ink",
4061
+ "d": "M 17.6 13.9 A 3.7 3.7 0 1 0 17.6 21.3 A 3.7 3.7 0 1 0 17.6 13.9 Z"
4062
+ }
4063
+ ]
4064
+ },
4065
+ "crosshairLine": {
4066
+ "box": 24,
4067
+ "hotspot": [
4068
+ 9,
4069
+ 9
4070
+ ],
4071
+ "paths": [
4072
+ {
4073
+ "role": "stroke",
4074
+ "d": "M 1.6 9 L 6.4 9",
4075
+ "width": 1.6
4076
+ },
4077
+ {
4078
+ "role": "stroke",
4079
+ "d": "M 11.6 9 L 16.4 9",
4080
+ "width": 1.6
4081
+ },
4082
+ {
4083
+ "role": "stroke",
4084
+ "d": "M 9 1.6 L 9 6.4",
4085
+ "width": 1.6
4086
+ },
4087
+ {
4088
+ "role": "stroke",
4089
+ "d": "M 9 11.6 L 9 16.4",
4090
+ "width": 1.6
4091
+ },
4092
+ {
4093
+ "role": "stroke",
4094
+ "d": "M 14.2 21 L 21 14.2",
4095
+ "width": 2.2
4096
+ }
4097
+ ]
4098
+ },
4099
+ "crosshairStar": {
4100
+ "box": 24,
4101
+ "hotspot": [
4102
+ 9,
4103
+ 9
4104
+ ],
4105
+ "paths": [
4106
+ {
4107
+ "role": "stroke",
4108
+ "d": "M 1.6 9 L 6.4 9",
4109
+ "width": 1.6
4110
+ },
4111
+ {
4112
+ "role": "stroke",
4113
+ "d": "M 11.6 9 L 16.4 9",
4114
+ "width": 1.6
4115
+ },
4116
+ {
4117
+ "role": "stroke",
4118
+ "d": "M 9 1.6 L 9 6.4",
4119
+ "width": 1.6
4120
+ },
4121
+ {
4122
+ "role": "stroke",
4123
+ "d": "M 9 11.6 L 9 16.4",
4124
+ "width": 1.6
4125
+ },
4126
+ {
4127
+ "role": "ink",
4128
+ "d": "M 17.6 13.4 L 18.72 16.06 L 21.59 16.3 L 19.41 18.19 L 20.07 21 L 17.6 19.5 L 15.13 21 L 15.79 18.19 L 13.61 16.3 L 16.48 16.06 Z"
4129
+ }
4130
+ ]
4131
+ },
4132
+ "crosshairPolygon": {
4133
+ "box": 24,
4134
+ "hotspot": [
4135
+ 9,
4136
+ 9
4137
+ ],
4138
+ "paths": [
4139
+ {
4140
+ "role": "stroke",
4141
+ "d": "M 1.6 9 L 6.4 9",
4142
+ "width": 1.6
4143
+ },
4144
+ {
4145
+ "role": "stroke",
4146
+ "d": "M 11.6 9 L 16.4 9",
4147
+ "width": 1.6
4148
+ },
4149
+ {
4150
+ "role": "stroke",
4151
+ "d": "M 9 1.6 L 9 6.4",
4152
+ "width": 1.6
4153
+ },
4154
+ {
4155
+ "role": "stroke",
4156
+ "d": "M 9 11.6 L 9 16.4",
4157
+ "width": 1.6
4158
+ },
4159
+ {
4160
+ "role": "ink",
4161
+ "d": "M 17.6 13.5 L 21.5 16.33 L 20.01 20.92 L 15.19 20.92 L 13.7 16.33 Z"
4162
+ }
4163
+ ]
4164
+ },
4165
+ "resize": {
4166
+ "box": 24,
4167
+ "hotspot": [
4168
+ 12,
4169
+ 12
4170
+ ],
4171
+ "paths": [
4172
+ {
4173
+ "role": "ink",
4174
+ "d": "M 2.5 12 L 7 8.8 L 7 10.7 L 17 10.7 L 17 8.8 L 21.5 12 L 17 15.2 L 17 13.3 L 7 13.3 L 7 15.2 Z"
4175
+ }
4176
+ ]
4177
+ },
4178
+ "rotate": {
4179
+ "box": 24,
4180
+ "hotspot": [
4181
+ 12,
4182
+ 12
4183
+ ],
4184
+ "paths": [
4185
+ {
4186
+ "role": "stroke",
4187
+ "d": "M 5.8 9.74 A 6.6 6.6 0 0 1 18.2 9.74",
4188
+ "width": 2.8
4189
+ },
4190
+ {
4191
+ "role": "ink",
4192
+ "d": "M 4.22 14.07 L 2.98 8.72 L 8.62 10.77 Z"
4193
+ },
4194
+ {
4195
+ "role": "ink",
4196
+ "d": "M 19.78 14.07 L 15.38 10.77 L 21.02 8.72 Z"
4197
+ }
4198
+ ]
3940
4199
  }
3941
4200
  };
3942
4201
  var cache2 = /* @__PURE__ */ new Map();
3943
4202
  function cursorFor(name, opts = {}) {
3944
4203
  const size = opts.size ?? 24;
3945
4204
  const fallback = opts.fallback ?? "default";
3946
- const key = `${name}|${size}|${fallback}`;
4205
+ const step = quantizeCursorAngle(opts.angle ?? 0);
4206
+ const key = `${name}|${size}|${step}|${fallback}`;
3947
4207
  const hit = cache2.get(key);
3948
4208
  if (hit !== void 0) return hit;
3949
4209
  const glyph = GLYPHS[name];
3950
4210
  if (glyph === void 0) {
3951
4211
  throw new Error(`unknown cursor glyph: ${String(name)}`);
3952
4212
  }
3953
- const css = bakeCursor(glyph, { size, fallback });
4213
+ const css = bakeCursor(glyph, { size, fallback, angle: opts.angle ?? 0 });
3954
4214
  cache2.set(key, css);
3955
4215
  return css;
3956
4216
  }
4217
+ function resolveCursorTier(spec) {
4218
+ if (typeof spec === "string") return { kind: "css", css: spec };
4219
+ const { glyph, size, worldRadius, angle = 0, fallback } = spec;
4220
+ if (worldRadius !== void 0) {
4221
+ return { kind: "painted", glyph, angle, worldRadius };
4222
+ }
4223
+ if (size !== void 0 && size > CURSOR_MAX_CSS_PX) {
4224
+ return { kind: "painted", glyph, angle, size };
4225
+ }
4226
+ return {
4227
+ kind: "css",
4228
+ css: cursorFor(glyph, {
4229
+ ...size !== void 0 ? { size } : {},
4230
+ ...fallback !== void 0 ? { fallback } : {},
4231
+ angle
4232
+ })
4233
+ };
4234
+ }
4235
+ function resolveCursor(spec) {
4236
+ if (spec === void 0) return void 0;
4237
+ const r = resolveCursorTier(spec);
4238
+ return r.kind === "css" ? r.css : "none";
4239
+ }
3957
4240
 
3958
4241
  // ../history/dist/index.js
3959
4242
  var RESUMERS = /* @__PURE__ */ new WeakMap();
@@ -4377,7 +4660,7 @@ function serialToEntry(se, custom, logger) {
4377
4660
  };
4378
4661
  }
4379
4662
 
4380
- // ../core/dist/chunk-FUQWXDG3.js
4663
+ // ../core/dist/chunk-HYJL7OOJ.js
4381
4664
  function worldToScreen(worldX, worldY, view) {
4382
4665
  return [view.panX + worldX * view.zoom.x, view.panY + worldY * view.zoom.y];
4383
4666
  }
@@ -9882,8 +10165,8 @@ function runLayoutPass(scratch, moveCtx) {
9882
10165
  for (const [cid, pose] of srcLayout.childPoses(srcContainer, srcChildren)) {
9883
10166
  const cur = composeWorldPose(poseAdapter, cid, pc.compose);
9884
10167
  const next = pose;
9885
- const same = cur.x === next.x && cur.y === next.y && cur.width === next.width && cur.height === next.height;
9886
- if (same) continue;
10168
+ const same2 = cur.x === next.x && cur.y === next.y && cur.width === next.width && cur.height === next.height;
10169
+ if (same2) continue;
9887
10170
  sourceReflow.set(cid, pose);
9888
10171
  const parent = scene.get(asNodeId(cid))?.parent ?? null;
9889
10172
  scratch.previews.set(asNodeId(cid), rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));
@@ -11237,6 +11520,11 @@ var cloneAction = {
11237
11520
  id: "clone",
11238
11521
  label: "Clone",
11239
11522
  defaultBinding: { kind: "drag" },
11523
+ // The platform's duplicate cursor, and the whole reason this field is
11524
+ // modifier-aware: the select tool binds clone behind `mods: { alt: true }`,
11525
+ // so the pump predicts it — and shows this — only while Alt is down.
11526
+ cursor: "copy",
11527
+ activeCursor: "copy",
11240
11528
  eligible: { capability: ["edits-page", "creates-selection"] },
11241
11529
  requires: ["selection", "scene", "applyOps"],
11242
11530
  invoker: {
@@ -15627,7 +15915,7 @@ function createDispatcher(opts) {
15627
15915
  }
15628
15916
  function inFlightCursor() {
15629
15917
  for (const action of inFlightActions.values()) {
15630
- const cursor = action.activeCursor ?? action.cursor;
15918
+ const cursor = resolveCursor(action.activeCursor ?? action.cursor);
15631
15919
  if (cursor) return cursor;
15632
15920
  }
15633
15921
  return null;
@@ -15849,7 +16137,7 @@ function computeMultiTouchGeometry(positions) {
15849
16137
  return { centroid, spread };
15850
16138
  }
15851
16139
  function useGestureDispatcher(opts) {
15852
- const { canvasRef, actions, toolsById, enabled = true, keyboard = true, affordanceAt, classifyTarget, dispatcher: dispatcherOpt, clientToWorld: clientToWorld2, requestRedraw, getRuleCtx, onDoubleClick, views } = opts;
16140
+ const { canvasRef, actions, toolsById, enabled = true, keyboard = true, affordanceAt, classifyTarget, dispatcher: dispatcherOpt, clientToWorld: clientToWorld2, requestRedraw, paintedCursor, getRuleCtx, onDoubleClick, views } = opts;
15853
16141
  const onDoubleClickRef = useRef(onDoubleClick);
15854
16142
  onDoubleClickRef.current = onDoubleClick;
15855
16143
  const activeTool = useActiveToolContext();
@@ -15898,6 +16186,8 @@ function useGestureDispatcher(opts) {
15898
16186
  ];
15899
16187
  const requestRedrawRef = useRef(requestRedraw);
15900
16188
  requestRedrawRef.current = requestRedraw;
16189
+ const paintedCursorRef = useRef(paintedCursor);
16190
+ paintedCursorRef.current = paintedCursor;
15901
16191
  const lastClickRef = useRef(null);
15902
16192
  const prevActiveRef = useRef(activeTool.active);
15903
16193
  useEffect(() => {
@@ -16237,20 +16527,39 @@ function useGestureDispatcher(opts) {
16237
16527
  let lastHover = null;
16238
16528
  let cursorOverridden = false;
16239
16529
  const clearHoverCursor = () => {
16530
+ paintedCursorRef.current?.()?.setOverride(null);
16240
16531
  if (cursorOverridden && canvas) {
16241
16532
  canvas.style.cursor = "";
16242
16533
  cursorOverridden = false;
16243
16534
  }
16244
16535
  };
16245
- const applyHoverCursor = (cursor) => {
16246
- if (cursor && canvas) {
16247
- canvas.style.cursor = cursor;
16248
- cursorOverridden = true;
16249
- } else {
16536
+ const applyHoverCursor = (spec) => {
16537
+ const tier = spec === null ? null : resolveCursorTier(spec);
16538
+ if (!tier || !canvas) {
16250
16539
  clearHoverCursor();
16540
+ return;
16541
+ }
16542
+ const painted = tier.kind === "painted" ? tier : null;
16543
+ paintedCursorRef.current?.()?.setOverride(painted);
16544
+ const cursor = tier.kind === "css" ? tier.css : "none";
16545
+ if (!cursor) {
16546
+ clearHoverCursor();
16547
+ return;
16251
16548
  }
16549
+ canvas.style.cursor = cursor;
16550
+ cursorOverridden = true;
16252
16551
  };
16552
+ function pushPaintedPointer() {
16553
+ const painted = paintedCursorRef.current?.();
16554
+ if (!painted?.active() || !canvas || !lastHover) return;
16555
+ const r = canvas.getBoundingClientRect();
16556
+ painted.setPointer(lastHover.clientX - r.left, lastHover.clientY - r.top);
16557
+ }
16253
16558
  function refreshHoverCursor() {
16559
+ resolveHoverCursor();
16560
+ pushPaintedPointer();
16561
+ }
16562
+ function resolveHoverCursor() {
16254
16563
  if (!canvas || !lastHover) return;
16255
16564
  if (activePointers.size > 0 || dispatcherNow().inFlight().size > 0) {
16256
16565
  applyHoverCursor(dispatcherNow().inFlightCursor());
@@ -16302,6 +16611,7 @@ function useGestureDispatcher(opts) {
16302
16611
  };
16303
16612
  const onHoverPointerLeave = () => {
16304
16613
  lastHover = null;
16614
+ paintedCursorRef.current?.()?.clearPointer();
16305
16615
  clearHoverCursor();
16306
16616
  };
16307
16617
  const onPointerUp = (e) => {
@@ -17811,7 +18121,7 @@ function validateId(id, kind) {
17811
18121
  }
17812
18122
  function defineTool(def) {
17813
18123
  validateId(def.id, "tool");
17814
- const resolveCursor = (ctx) => {
18124
+ const resolveCursor3 = (ctx) => {
17815
18125
  if (def.cursor == null) return "";
17816
18126
  return typeof def.cursor === "function" ? def.cursor(ctx) : def.cursor;
17817
18127
  };
@@ -17829,7 +18139,7 @@ function defineTool(def) {
17829
18139
  onActivate: def.onActivate,
17830
18140
  onDeactivate: def.onDeactivate,
17831
18141
  initScratch: def.initScratch ?? (() => null),
17832
- cursor: resolveCursor,
18142
+ cursor: resolveCursor3,
17833
18143
  bindings: def.bindings,
17834
18144
  overlay: def.overlay,
17835
18145
  overlayPosition: def.overlayPosition
@@ -18829,10 +19139,10 @@ function findShapeInk(node, pose, ctx) {
18829
19139
  function shapeCoversPoint(node, pose, x, y, opts = {}) {
18830
19140
  const sil = findShapeSilhouette(node, pose, { derivedPath: opts.derivedPath });
18831
19141
  if (sil === null) return true;
18832
- const ink = findShapeInk(node, pose, { scale: opts.scale }) ?? DEFAULT_INK;
19142
+ const ink2 = findShapeInk(node, pose, { scale: opts.scale }) ?? DEFAULT_INK;
18833
19143
  const inside = pathContainsPoint(sil, x, y);
18834
- if (ink.filled && inside) return true;
18835
- const reach = (inside ? ink.inset : ink.outset) + (opts.tolerance ?? 0);
19144
+ if (ink2.filled && inside) return true;
19145
+ const reach = (inside ? ink2.inset : ink2.outset) + (opts.tolerance ?? 0);
18836
19146
  return reach > 0 && strokeHitTest(sil, x, y, reach);
18837
19147
  }
18838
19148
  var TEXT_PAINTER = {
@@ -19731,6 +20041,9 @@ function transformOf(state, targetId) {
19731
20041
  identity: false
19732
20042
  };
19733
20043
  }
20044
+ function angleOf(xf) {
20045
+ return xf.identity ? 0 : Math.atan2(xf.sin, xf.cos);
20046
+ }
19734
20047
  function localToWorld(xf, lx, ly) {
19735
20048
  if (xf.identity) return { x: lx, y: ly };
19736
20049
  const dx = lx - xf.cx;
@@ -20030,11 +20343,7 @@ var DEFAULT_PAINT = {
20030
20343
  insetPx: 10
20031
20344
  };
20032
20345
  function createRotationAffordance(opts = {}) {
20033
- const {
20034
- bandPx = 24,
20035
- paint = DEFAULT_PAINT,
20036
- cursor = "grab"
20037
- } = opts;
20346
+ const { bandPx = 24, paint = DEFAULT_PAINT, cursor } = opts;
20038
20347
  const annulusPaint = (() => {
20039
20348
  if (!paint) return null;
20040
20349
  if ("paint" in paint) {
@@ -20072,7 +20381,14 @@ function createRotationAffordance(opts = {}) {
20072
20381
  },
20073
20382
  ...annulusPaint ? { paint: annulusPaint } : {},
20074
20383
  hitKind: "rotate-handle",
20075
- cursor,
20384
+ // Turned with the target, so the arc follows the selection it rotates.
20385
+ // Resolved per region rather than defaulted in the option list because
20386
+ // the angle is only known once a target is picked.
20387
+ cursor: cursor ?? {
20388
+ glyph: "rotate",
20389
+ angle: angleOf(transformOf(state, target.id)),
20390
+ fallback: "grab"
20391
+ },
20076
20392
  bind: () => ({
20077
20393
  initialScratch: {
20078
20394
  targetId: target.id,
@@ -20551,7 +20867,7 @@ function useRectTool() {
20551
20867
  id: "rect",
20552
20868
  capabilities: ["creates-shapes"],
20553
20869
  hookName: "useRectTool",
20554
- cursor: "crosshair",
20870
+ cursor: cursorFor("crosshairRect", { fallback: "crosshair" }),
20555
20871
  presentation: {
20556
20872
  label: "Rectangle",
20557
20873
  icon: createElement(RectIcon),
@@ -20577,7 +20893,7 @@ function useEllipseTool() {
20577
20893
  id: "ellipse",
20578
20894
  capabilities: ["creates-shapes"],
20579
20895
  hookName: "useEllipseTool",
20580
- cursor: "crosshair",
20896
+ cursor: cursorFor("crosshairEllipse", { fallback: "crosshair" }),
20581
20897
  presentation: {
20582
20898
  label: "Ellipse",
20583
20899
  group: "shape",
@@ -20600,7 +20916,7 @@ function useLineTool() {
20600
20916
  id: "line",
20601
20917
  capabilities: ["creates-shapes"],
20602
20918
  hookName: "useLineTool",
20603
- cursor: "crosshair",
20919
+ cursor: cursorFor("crosshairLine", { fallback: "crosshair" }),
20604
20920
  presentation: {
20605
20921
  label: "Line",
20606
20922
  group: "shape",
@@ -20711,7 +21027,7 @@ function usePolygonTool(options = {}) {
20711
21027
  id: "polygon",
20712
21028
  capabilities: ["creates-shapes"],
20713
21029
  hookName: "usePolygonTool",
20714
- cursor: "crosshair",
21030
+ cursor: cursorFor("crosshairPolygon", { fallback: "crosshair" }),
20715
21031
  // Registered by <ToolActionsMounter>, inside the ActionsProvider —
20716
21032
  // see `ToolDef.actions` for why the hook can't register it itself.
20717
21033
  actions: [adjustSidesAction],
@@ -20811,7 +21127,7 @@ function useStarTool(options = {}) {
20811
21127
  id: "star",
20812
21128
  capabilities: ["creates-shapes"],
20813
21129
  hookName: "useStarTool",
20814
- cursor: "crosshair",
21130
+ cursor: cursorFor("crosshairStar", { fallback: "crosshair" }),
20815
21131
  // Registered by <ToolActionsMounter>, inside the ActionsProvider —
20816
21132
  // see `ToolDef.actions` for why the hook can't register it itself.
20817
21133
  actions: [adjustPointsAction],
@@ -21848,6 +22164,111 @@ function buildSceneTree(adapter, drawOne, view, forLayer, derivedPathOf) {
21848
22164
  }
21849
22165
  return out;
21850
22166
  }
22167
+ function same(a, b) {
22168
+ if (a === b) return true;
22169
+ if (!a || !b) return false;
22170
+ return a.glyph === b.glyph && a.angle === b.angle && a.size === b.size && a.worldRadius === b.worldRadius;
22171
+ }
22172
+ function createPaintedCursorState() {
22173
+ let base = null;
22174
+ let override = null;
22175
+ let at = null;
22176
+ const subs = /* @__PURE__ */ new Set();
22177
+ const notify2 = () => {
22178
+ for (const fn of subs) fn();
22179
+ };
22180
+ return {
22181
+ setBase(cursor) {
22182
+ if (same(base, cursor)) return;
22183
+ base = cursor;
22184
+ notify2();
22185
+ },
22186
+ setOverride(cursor) {
22187
+ if (same(override, cursor)) return;
22188
+ override = cursor;
22189
+ notify2();
22190
+ },
22191
+ setPointer(x, y) {
22192
+ if (at && at.x === x && at.y === y) return;
22193
+ at = { x, y };
22194
+ if (override ?? base) notify2();
22195
+ },
22196
+ clearPointer() {
22197
+ if (at === null) return;
22198
+ at = null;
22199
+ notify2();
22200
+ },
22201
+ active() {
22202
+ return (override ?? base) !== null;
22203
+ },
22204
+ current() {
22205
+ const cursor = override ?? base;
22206
+ if (!cursor || !at) return null;
22207
+ return { cursor, at };
22208
+ },
22209
+ subscribe(fn) {
22210
+ subs.add(fn);
22211
+ return () => {
22212
+ subs.delete(fn);
22213
+ };
22214
+ }
22215
+ };
22216
+ }
22217
+ var PAINTED_CURSOR_LAYER_ID = "painted-cursor";
22218
+ var pathCache = /* @__PURE__ */ new Map();
22219
+ function pathFor(d) {
22220
+ let p = pathCache.get(d);
22221
+ if (p === void 0) {
22222
+ p = pathFromD(d);
22223
+ pathCache.set(d, p);
22224
+ }
22225
+ return p;
22226
+ }
22227
+ function commandFor2(op) {
22228
+ return {
22229
+ kind: "path",
22230
+ path: pathFor(op.d),
22231
+ ...op.fill !== void 0 ? { fill: { color: op.fill } } : {},
22232
+ ...op.stroke !== void 0 ? {
22233
+ stroke: {
22234
+ paint: { color: op.stroke.color },
22235
+ width: op.stroke.width,
22236
+ cap: "round",
22237
+ join: "round"
22238
+ }
22239
+ } : {}
22240
+ };
22241
+ }
22242
+ function createPaintedCursorLayer(state) {
22243
+ return {
22244
+ id: PAINTED_CURSOR_LAYER_ID,
22245
+ label: "Painted cursor",
22246
+ space: "screen",
22247
+ draw: (_data, view) => {
22248
+ const frame = state.current();
22249
+ if (!frame) return [];
22250
+ const { cursor, at } = frame;
22251
+ const glyph = GLYPHS[cursor.glyph];
22252
+ if (!glyph) return [];
22253
+ const scale2 = (view.scale.x + view.scale.y) / 2;
22254
+ const worldSized = cursor.worldRadius !== void 0;
22255
+ const size = worldSized ? cursorWorldSize(glyph, cursor.worldRadius, scale2) : cursor.size ?? 24;
22256
+ if (!(size > 0) || !Number.isFinite(size)) return [];
22257
+ const ops = cursorPaintOps(
22258
+ glyph,
22259
+ worldSized ? { lineWidthScale: chromeLineWidthScale(glyph, size) } : {}
22260
+ );
22261
+ const [a, b, c, d, e, f] = cursorPaintMatrix(glyph, {
22262
+ size,
22263
+ angle: cursor.angle,
22264
+ at
22265
+ });
22266
+ const transform = new Float32Array([a, b, 0, c, d, 0, e, f, 1]);
22267
+ const children = ops.map(commandFor2);
22268
+ return [{ kind: "group", transform, children }];
22269
+ }
22270
+ };
22271
+ }
21851
22272
  function mat3ToRenderMatrix(m) {
21852
22273
  return new Float32Array([m[0], m[1], 0, m[2], m[3], 0, m[4], m[5], 1]);
21853
22274
  }
@@ -22217,11 +22638,11 @@ function resolveToolsCursor(tools, ctxBase) {
22217
22638
  const id = tools.hotkeyEngaged ?? tools.active;
22218
22639
  const tool = tools.registry[id];
22219
22640
  if (!tool?.cursor) return void 0;
22220
- if (typeof tool.cursor === "string") return tool.cursor;
22641
+ if (typeof tool.cursor !== "function") return resolveCursorTier(tool.cursor);
22221
22642
  if (!ctxBase) return void 0;
22222
22643
  try {
22223
22644
  const base = ctxBase();
22224
- return tool.cursor({ ...base, scratch: null });
22645
+ return resolveCursorTier(tool.cursor({ ...base, scratch: null }));
22225
22646
  } catch {
22226
22647
  return void 0;
22227
22648
  }
@@ -22386,6 +22807,14 @@ function CanvasInner(props, ref) {
22386
22807
  viewSubsRef.current.delete(fn);
22387
22808
  };
22388
22809
  }, []);
22810
+ const paintedCursor = useMemo(() => createPaintedCursorState(), []);
22811
+ const paintedCursorLayer = useMemo(
22812
+ () => createPaintedCursorLayer(paintedCursor),
22813
+ [paintedCursor]
22814
+ );
22815
+ useEffect(() => paintedCursor.subscribe(() => {
22816
+ requestRedraw();
22817
+ }), [paintedCursor, requestRedraw]);
22389
22818
  useImperativeHandle(ref, () => ({
22390
22819
  // Named rather than read off `canvasRef` so the handle rebuilds when a
22391
22820
  // detached surface's input element arrives, which is a render later.
@@ -22398,7 +22827,8 @@ function CanvasInner(props, ref) {
22398
22827
  getView,
22399
22828
  setView,
22400
22829
  subscribeView,
22401
- getPaintedVersion
22830
+ getPaintedVersion,
22831
+ paintedCursor
22402
22832
  }), [
22403
22833
  canvasRef,
22404
22834
  ownCanvasRef,
@@ -22412,7 +22842,8 @@ function CanvasInner(props, ref) {
22412
22842
  getView,
22413
22843
  setView,
22414
22844
  subscribeView,
22415
- getPaintedVersion
22845
+ getPaintedVersion,
22846
+ paintedCursor
22416
22847
  ]);
22417
22848
  const glRendererRef = useRef(null);
22418
22849
  const layerCacheRef = useRef(/* @__PURE__ */ new Map());
@@ -22676,8 +23107,16 @@ function CanvasInner(props, ref) {
22676
23107
  const layersWithDebug = useMemo(() => {
22677
23108
  const withViews = viewRegistry ? [...layers, ...viewRegistry.list().map((r) => r.layer)] : layers;
22678
23109
  const base = debugSink && resolvedDebugConfig ? [...withViews, createDebugOverlayLayer({ sink: debugSink, config: resolvedDebugConfig })] : withViews;
22679
- return [...base, ...extrasRef.current];
22680
- }, [layers, debugSink, resolvedDebugConfig, extrasVersion, viewRegistry, viewRegistryVersion]);
23110
+ return [...base, ...extrasRef.current, paintedCursorLayer];
23111
+ }, [
23112
+ layers,
23113
+ debugSink,
23114
+ resolvedDebugConfig,
23115
+ extrasVersion,
23116
+ viewRegistry,
23117
+ viewRegistryVersion,
23118
+ paintedCursorLayer
23119
+ ]);
22681
23120
  const shaderIdKey = shaders?.map((h) => h.id).join("|") ?? "";
22682
23121
  const paintInputsRef = useRef({
22683
23122
  layers: layersWithDebug,
@@ -22799,8 +23238,14 @@ function CanvasInner(props, ref) {
22799
23238
  if (!renderer) return;
22800
23239
  registerShadersOnRenderer(renderer, shaders);
22801
23240
  }, [shaderIdKey]);
22802
- const toolsCursor = tools ? resolveToolsCursor(tools, toolsCtxBase) : void 0;
23241
+ const toolsCursorTier = tools ? resolveToolsCursor(tools, toolsCtxBase) : void 0;
23242
+ const toolsCursor = toolsCursorTier === void 0 ? void 0 : toolsCursorTier.kind === "css" ? toolsCursorTier.css : "none";
22803
23243
  const effectiveStyle = toolsCursor ? { ...style, cursor: toolsCursor } : style;
23244
+ const toolsPainted = toolsCursorTier?.kind === "painted" ? toolsCursorTier : null;
23245
+ const toolsPaintedKey = toolsPainted ? `${toolsPainted.glyph}|${toolsPainted.angle}|${toolsPainted.size}|${toolsPainted.worldRadius}` : "";
23246
+ useEffect(() => {
23247
+ paintedCursor.setBase(toolsPainted);
23248
+ }, [paintedCursor, toolsPaintedKey]);
22804
23249
  const layersForMoveRef = useRef(layersWithDebug);
22805
23250
  layersForMoveRef.current = layersWithDebug;
22806
23251
  useEffect(() => {
@@ -24120,10 +24565,16 @@ function createCornerResizeAffordance(opts = {}) {
24120
24565
  hitKind: c.kind,
24121
24566
  // Diagonal by fixed-corner parity: a matched-axis anchor (min-min /
24122
24567
  // max-max fixed) means the dragged corner sits on the ↘ diagonal;
24123
- // mixed axes sit on the ↗ diagonal. Not rotation-aware — a rotated
24124
- // target keeps the unrotated hint, the same policy as every
24125
- // mainstream editor short of Figma.
24126
- cursor: c.anchor.x === c.anchor.y ? "nwse-resize" : "nesw-resize",
24568
+ // mixed axes sit on the ↗ diagonal. The glyph is horizontal at angle
24569
+ // 0, so the diagonal is a half-quarter-turn either way, plus the
24570
+ // target's own rotation. The keyword is the fallback rather than the
24571
+ // answer: CSS has four of them, which cannot express a target
24572
+ // rotated to anything but a multiple of 45°.
24573
+ cursor: {
24574
+ glyph: "resize",
24575
+ angle: (c.anchor.x === c.anchor.y ? Math.PI / 4 : -Math.PI / 4) + angleOf(xf),
24576
+ fallback: c.anchor.x === c.anchor.y ? "nwse-resize" : "nesw-resize"
24577
+ },
24127
24578
  bind: () => ({
24128
24579
  initialScratch: {
24129
24580
  anchor: c.anchor,
@@ -28060,6 +28511,10 @@ function GestureDispatcherMounter({
28060
28511
  const requestRedraw = useCallback(() => {
28061
28512
  canvasApiRef?.current?.requestRedraw?.();
28062
28513
  }, [canvasApiRef]);
28514
+ const paintedCursor = useCallback(
28515
+ () => canvasApiRef?.current?.paintedCursor,
28516
+ [canvasApiRef]
28517
+ );
28063
28518
  const views = useMemo(() => {
28064
28519
  if (!viewRegistry) return void 0;
28065
28520
  return {
@@ -28078,6 +28533,7 @@ function GestureDispatcherMounter({
28078
28533
  dispatcher,
28079
28534
  clientToWorld: clientToWorld2,
28080
28535
  requestRedraw,
28536
+ paintedCursor,
28081
28537
  getRuleCtx,
28082
28538
  onDoubleClick,
28083
28539
  ...views ? { views } : {}
@@ -28930,5 +29386,5 @@ function oklchToOklab(L, C, h) {
28930
29386
  }
28931
29387
 
28932
29388
  export { ArrowIcon, EllipseIcon, FALLBACK_FIT_VIEW, LineIcon, MinimapCanvas, PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z, PathBuilder, PencilIcon, RectIcon, SCRIPT_METRICS, SceneCanvas, SceneViewCanvas, SelectIcon, TextIcon, UnknownIcon, WeaselProvider, asNodeId, boundsOfPath, buildSceneViewCommands, computeFitView, computeIndicatorCommand, createScene, eligibleContribution, ellipsePath, evaluateEnabled, getMarker, getPaintKind, isBuiltinToolPref, linePath, markerDrawCommands, oklabToSrgbU8, oklchToOklab, rectPath, renderSceneToCanvas, renderSceneToPixels, resolveStrokeWidth, rgbaToHex, sceneFromJSON, textCommand, tileGeometry, useActionsRegistry, useActiveToolContext, useOptionalDepRegistry, useVisibleRaf };
28933
- //# sourceMappingURL=chunk-L5QJOOLV.js.map
28934
- //# sourceMappingURL=chunk-L5QJOOLV.js.map
29389
+ //# sourceMappingURL=chunk-7VW3S44V.js.map
29390
+ //# sourceMappingURL=chunk-7VW3S44V.js.map