stickyflow 0.9.3 → 0.11.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 (66) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/dist/binding/index.cjs +9 -9
  4. package/dist/binding/index.d.cts +4 -4
  5. package/dist/binding/index.d.ts +4 -4
  6. package/dist/binding/index.js +3 -3
  7. package/dist/{chunk-EURX7QT3.cjs → chunk-5G3BEXQU.cjs} +1300 -891
  8. package/dist/chunk-5G3BEXQU.cjs.map +1 -0
  9. package/dist/{chunk-AAP24GBG.js → chunk-BFQWCOEC.js} +3 -3
  10. package/dist/chunk-BFQWCOEC.js.map +1 -0
  11. package/dist/{chunk-3EOG34QN.cjs → chunk-F24JURN2.cjs} +561 -258
  12. package/dist/chunk-F24JURN2.cjs.map +1 -0
  13. package/dist/{chunk-2GKXPZRL.cjs → chunk-FXGXUWSI.cjs} +23 -23
  14. package/dist/chunk-FXGXUWSI.cjs.map +1 -0
  15. package/dist/{chunk-Q6FBISNP.js → chunk-G6IW2IX3.js} +601 -350
  16. package/dist/chunk-G6IW2IX3.js.map +1 -0
  17. package/dist/{chunk-G2N3KJYJ.js → chunk-Q6QLU6YQ.js} +662 -253
  18. package/dist/chunk-Q6QLU6YQ.js.map +1 -0
  19. package/dist/{chunk-C3LVKPWQ.js → chunk-RQYZNW2I.js} +532 -229
  20. package/dist/chunk-RQYZNW2I.js.map +1 -0
  21. package/dist/{chunk-XNNNIOJU.js → chunk-UB2ANTWF.js} +5 -5
  22. package/dist/{chunk-XNNNIOJU.js.map → chunk-UB2ANTWF.js.map} +1 -1
  23. package/dist/{chunk-C25NWWIH.cjs → chunk-UHKFJBY5.cjs} +605 -350
  24. package/dist/chunk-UHKFJBY5.cjs.map +1 -0
  25. package/dist/{chunk-MR32IJQO.cjs → chunk-WZA3DJJH.cjs} +15 -15
  26. package/dist/chunk-WZA3DJJH.cjs.map +1 -0
  27. package/dist/index.cjs +36 -36
  28. package/dist/index.d.cts +35 -30
  29. package/dist/index.d.ts +35 -30
  30. package/dist/index.js +5 -5
  31. package/dist/interaction/index.cjs +319 -352
  32. package/dist/interaction/index.cjs.map +1 -1
  33. package/dist/interaction/index.d.cts +3 -3
  34. package/dist/interaction/index.d.ts +3 -3
  35. package/dist/interaction/index.js +94 -127
  36. package/dist/interaction/index.js.map +1 -1
  37. package/dist/{render-DU4lYbRl.d.ts → render-BDO4S5uF.d.cts} +16 -0
  38. package/dist/{render-DU4lYbRl.d.cts → render-BDO4S5uF.d.ts} +16 -0
  39. package/dist/{runtime-DG8X3Fwf.d.cts → runtime-C-C5v9po.d.cts} +2 -2
  40. package/dist/{runtime-kqD1RS17.d.ts → runtime-lCAfU-1Q.d.ts} +2 -2
  41. package/dist/{runtimeTypes-vRaHOIHi.d.ts → runtimeTypes-B7p6b1Bi.d.cts} +2 -2
  42. package/dist/{runtimeTypes-CvjlBZds.d.cts → runtimeTypes-BDA_CfWh.d.ts} +2 -2
  43. package/dist/stickyflow-diagram.global.js +197 -44
  44. package/dist/stickyflow-diagram.global.js.map +1 -1
  45. package/dist/{types-B5jrEEcF.d.cts → types-CZJzycKw.d.cts} +1 -1
  46. package/dist/{types-B7IkZ0w4.d.ts → types-Dp8JVZLB.d.ts} +1 -1
  47. package/dist/viewer/index.cjs +9 -9
  48. package/dist/viewer/index.d.cts +4 -4
  49. package/dist/viewer/index.d.ts +4 -4
  50. package/dist/viewer/index.js +4 -4
  51. package/dist/web-component/index.cjs +6 -6
  52. package/dist/web-component/index.cjs.map +1 -1
  53. package/dist/web-component/index.d.cts +2 -2
  54. package/dist/web-component/index.d.ts +2 -2
  55. package/dist/web-component/index.js +4 -4
  56. package/dist/web-component/index.js.map +1 -1
  57. package/package.json +1 -1
  58. package/dist/chunk-2GKXPZRL.cjs.map +0 -1
  59. package/dist/chunk-3EOG34QN.cjs.map +0 -1
  60. package/dist/chunk-AAP24GBG.js.map +0 -1
  61. package/dist/chunk-C25NWWIH.cjs.map +0 -1
  62. package/dist/chunk-C3LVKPWQ.js.map +0 -1
  63. package/dist/chunk-EURX7QT3.cjs.map +0 -1
  64. package/dist/chunk-G2N3KJYJ.js.map +0 -1
  65. package/dist/chunk-MR32IJQO.cjs.map +0 -1
  66. package/dist/chunk-Q6FBISNP.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkEURX7QT3_cjs = require('./chunk-EURX7QT3.cjs');
4
- var chunkMR32IJQO_cjs = require('./chunk-MR32IJQO.cjs');
5
- var chunkC25NWWIH_cjs = require('./chunk-C25NWWIH.cjs');
3
+ var chunk5G3BEXQU_cjs = require('./chunk-5G3BEXQU.cjs');
4
+ var chunkWZA3DJJH_cjs = require('./chunk-WZA3DJJH.cjs');
5
+ var chunkUHKFJBY5_cjs = require('./chunk-UHKFJBY5.cjs');
6
6
 
7
7
  // src/runtime/viewer/components/rollingNumberDom.ts
8
8
  var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
@@ -162,12 +162,12 @@ function componentDigits(surface) {
162
162
  function componentStyle(surface) {
163
163
  const encoded = surface.getAttribute("data-sf-widget-style");
164
164
  if (!encoded) {
165
- return chunkC25NWWIH_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
165
+ return chunkUHKFJBY5_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
166
166
  }
167
167
  try {
168
- return { ...chunkC25NWWIH_cjs.DEFAULT_ROLLING_NUMBER_STYLE, ...JSON.parse(encoded) };
168
+ return { ...chunkUHKFJBY5_cjs.DEFAULT_ROLLING_NUMBER_STYLE, ...JSON.parse(encoded) };
169
169
  } catch {
170
- return chunkC25NWWIH_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
170
+ return chunkUHKFJBY5_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
171
171
  }
172
172
  }
173
173
  function positiveInteger(value) {
@@ -191,7 +191,7 @@ function setRollingNumber(surface, value, animate) {
191
191
  return false;
192
192
  }
193
193
  const previousValue = surface.getAttribute("data-sf-widget-value") ?? "";
194
- const nextValue = chunkC25NWWIH_cjs.formatRollingNumber(value, positiveInteger(surface.getAttribute("data-sf-widget-digits")));
194
+ const nextValue = chunkUHKFJBY5_cjs.formatRollingNumber(value, positiveInteger(surface.getAttribute("data-sf-widget-digits")));
195
195
  if (previousValue === nextValue) {
196
196
  return true;
197
197
  }
@@ -277,10 +277,14 @@ function parameters(surface) {
277
277
  function positive(value, fallback) {
278
278
  return Number(value) > 0 ? Number(value) : fallback;
279
279
  }
280
+ function rangeOf(params) {
281
+ return {
282
+ min: Number(params.min) || 0,
283
+ max: Number.isFinite(Number(params.max)) && params.max !== void 0 ? Number(params.max) : 100
284
+ };
285
+ }
280
286
  function rulerProgress(surface, value) {
281
- const params = parameters(surface);
282
- const min = Number(params.min) || 0;
283
- const max = Number.isFinite(Number(params.max)) && params.max !== void 0 ? Number(params.max) : 100;
287
+ const { min, max } = rangeOf(parameters(surface));
284
288
  return clamp01(max === min ? 0 : (value - min) / (max - min));
285
289
  }
286
290
  function move(node, dx, dy) {
@@ -291,19 +295,11 @@ function move(node, dx, dy) {
291
295
  written.set(node, next);
292
296
  node.setAttribute("transform", next);
293
297
  }
294
- function hexToRgb(value) {
295
- const match = /^#([0-9a-f]{6})$/i.exec(value.trim());
296
- if (!match) {
297
- return null;
298
- }
299
- const number2 = parseInt(match[1], 16);
300
- return [number2 >> 16 & 255, number2 >> 8 & 255, number2 & 255];
301
- }
302
298
  var WHITE = [255, 255, 255];
303
299
  function shade(node, bump, target) {
304
300
  const base = fills.get(node) ?? node.getAttribute("fill") ?? "";
305
301
  fills.set(node, base);
306
- const rgb = hexToRgb(base);
302
+ const rgb = chunkUHKFJBY5_cjs.parseHexRgb(base);
307
303
  if (!rgb) {
308
304
  return;
309
305
  }
@@ -314,61 +310,84 @@ function shade(node, bump, target) {
314
310
  child.style.fill = fill;
315
311
  }
316
312
  }
313
+ function rulerOf(surface, progressOf) {
314
+ const params = parameters(surface);
315
+ const id = surface.getAttribute("data-sf-id") ?? "";
316
+ const width = Number(surface.getAttribute("width"));
317
+ const height = Number(surface.getAttribute("height"));
318
+ const horizontal = params.axis === "horizontal";
319
+ const across = horizontal ? height : width;
320
+ const dent = params.dent === void 0 ? 1 : Number(params.dent);
321
+ return {
322
+ id,
323
+ params,
324
+ x: Number(surface.getAttribute("x")),
325
+ y: Number(surface.getAttribute("y")),
326
+ width,
327
+ height,
328
+ horizontal,
329
+ progress: clamp01(progressOf(id) ?? Number(params.progress)),
330
+ inset: positive(params.inset, 0.05),
331
+ extent: horizontal ? width : height,
332
+ across,
333
+ depth: (dent < 0 ? 1 : dent) * 0.16 * across
334
+ };
335
+ }
336
+ function placeKnob(svg, ruler) {
337
+ const { params, x, y, width, height, horizontal, across, depth } = ruler;
338
+ const knobId = typeof params.knob === "string" ? params.knob : "";
339
+ if (!knobId) {
340
+ return void 0;
341
+ }
342
+ const nodes = [...svg.querySelectorAll(`[data-sf-id="${CSS.escape(knobId)}"]`)];
343
+ const primary = nodes.find((node) => node.hasAttribute("data-sf-primary"));
344
+ if (!primary?.getBBox) {
345
+ return void 0;
346
+ }
347
+ move(primary, 0, 0);
348
+ const box = primary.getBBox();
349
+ const half = (horizontal ? box.height : box.width) / 2;
350
+ const along = ruler.inset + (1 - 2 * ruler.inset) * ruler.progress;
351
+ const line = positive(params.line, 0.7);
352
+ const gap = (params.gap === void 0 ? 0.04 : Number(params.gap)) * across;
353
+ const side = line * across - depth + half + gap;
354
+ const target = horizontal ? { x: x + width * along, y: y + side } : { x: x + side, y: y + height * (1 - along) };
355
+ const dx = target.x - (box.x + box.width / 2);
356
+ const dy = target.y - (box.y + box.height / 2);
357
+ for (const node of nodes) {
358
+ move(node, dx, dy);
359
+ }
360
+ return half / across;
361
+ }
362
+ function liftLabels(svg, ruler) {
363
+ const { id, params, horizontal, extent, inset, progress, depth } = ruler;
364
+ const { min, max } = rangeOf(params);
365
+ const peak = (typeof params.peak === "string" ? chunkUHKFJBY5_cjs.parseHexRgb(params.peak) : null) ?? WHITE;
366
+ const spread = positive(params.spread, 0.07) * extent;
367
+ const start = inset * extent;
368
+ const span = (1 - 2 * inset) * extent;
369
+ const knobAt = start + span * progress;
370
+ for (const label of svg.querySelectorAll(`text[data-sf-id="${CSS.escape(id)}"]`)) {
371
+ const value = Number(label.textContent);
372
+ if (!Number.isFinite(value) || max === min) {
373
+ continue;
374
+ }
375
+ const labelAt = start + span * clamp01((value - min) / (max - min));
376
+ const bump = Math.exp(-(((labelAt - knobAt) / spread) ** 2));
377
+ const shift = depth * 0.4 * bump;
378
+ move(label, horizontal ? 0 : -shift, horizontal ? -shift : 0);
379
+ shade(label, bump, peak);
380
+ }
381
+ }
317
382
  function placeRulerKnobs(svg, progressOf) {
318
383
  const radii = /* @__PURE__ */ new Map();
319
384
  for (const surface of svg.querySelectorAll('foreignObject[data-sf-shader="ruler"]')) {
320
- const params = parameters(surface);
321
- const peak = (typeof params.peak === "string" ? hexToRgb(params.peak) : null) ?? WHITE;
322
- const id = surface.getAttribute("data-sf-id") ?? "";
323
- const x = Number(surface.getAttribute("x"));
324
- const y = Number(surface.getAttribute("y"));
325
- const width = Number(surface.getAttribute("width"));
326
- const height = Number(surface.getAttribute("height"));
327
- const horizontal = params.axis === "horizontal";
328
- const progress = clamp01(progressOf(id) ?? Number(params.progress));
329
- const inset = positive(params.inset, 0.05);
330
- const line = positive(params.line, 0.7);
331
- const extent = horizontal ? width : height;
332
- const across = horizontal ? height : width;
333
- const along = inset + (1 - 2 * inset) * progress;
334
- const dent = params.dent === void 0 ? 1 : Number(params.dent);
335
- const depth = (dent < 0 ? 1 : dent) * 0.16 * across;
336
- const knobId = typeof params.knob === "string" ? params.knob : "";
337
- if (knobId) {
338
- const nodes = [...svg.querySelectorAll(`[data-sf-id="${CSS.escape(knobId)}"]`)];
339
- const primary = nodes.find((node) => node.hasAttribute("data-sf-primary"));
340
- if (primary?.getBBox) {
341
- move(primary, 0, 0);
342
- const box = primary.getBBox();
343
- const half = (horizontal ? box.height : box.width) / 2;
344
- radii.set(id, half / across);
345
- const gap = (params.gap === void 0 ? 0.04 : Number(params.gap)) * across;
346
- const side = line * across - depth + half + gap;
347
- const target = horizontal ? { x: x + width * along, y: y + side } : { x: x + side, y: y + height * (1 - along) };
348
- const dx = target.x - (box.x + box.width / 2);
349
- const dy = target.y - (box.y + box.height / 2);
350
- for (const node of nodes) {
351
- move(node, dx, dy);
352
- }
353
- }
354
- }
355
- const min = Number(params.min) || 0;
356
- const max = Number.isFinite(Number(params.max)) && params.max !== void 0 ? Number(params.max) : 100;
357
- const spread = positive(params.spread, 0.07) * extent;
358
- const start = inset * extent;
359
- const span = (1 - 2 * inset) * extent;
360
- const knobAt = start + span * progress;
361
- for (const label of svg.querySelectorAll(`text[data-sf-id="${CSS.escape(id)}"]`)) {
362
- const value = Number(label.textContent);
363
- if (!Number.isFinite(value) || max === min) {
364
- continue;
365
- }
366
- const labelAt = start + span * clamp01((value - min) / (max - min));
367
- const bump = Math.exp(-(((labelAt - knobAt) / spread) ** 2));
368
- const shift = depth * 0.4 * bump;
369
- move(label, horizontal ? 0 : -shift, horizontal ? -shift : 0);
370
- shade(label, bump, peak);
385
+ const ruler = rulerOf(surface, progressOf);
386
+ const radius = placeKnob(svg, ruler);
387
+ if (radius !== void 0) {
388
+ radii.set(ruler.id, radius);
371
389
  }
390
+ liftLabels(svg, ruler);
372
391
  }
373
392
  return radii;
374
393
  }
@@ -671,7 +690,7 @@ function mountDisplay(container, svgString) {
671
690
  }
672
691
 
673
692
  // src/runtime/viewer/events.ts
674
- var Emitter2 = class extends chunkMR32IJQO_cjs.Emitter {
693
+ var Emitter2 = class extends chunkWZA3DJJH_cjs.Emitter {
675
694
  };
676
695
 
677
696
  // src/runtime/viewer/export/raster.ts
@@ -761,11 +780,11 @@ function svgElement(document, name, attributes) {
761
780
  function readComponentStyle(surface) {
762
781
  try {
763
782
  return {
764
- ...chunkC25NWWIH_cjs.DEFAULT_ROLLING_NUMBER_STYLE,
783
+ ...chunkUHKFJBY5_cjs.DEFAULT_ROLLING_NUMBER_STYLE,
765
784
  ...JSON.parse(surface.getAttribute("data-sf-widget-style") ?? "{}")
766
785
  };
767
786
  } catch {
768
- return chunkC25NWWIH_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
787
+ return chunkUHKFJBY5_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
769
788
  }
770
789
  }
771
790
  function cellsOf(box, plain, fontSize = 0) {
@@ -905,7 +924,7 @@ function serializeSvgSnapshot(svg, captures) {
905
924
  // src/runtime/viewer/interaction/changeFlash.ts
906
925
  function createChangeFlash(svg) {
907
926
  const timers = /* @__PURE__ */ new Map();
908
- const flash = (ownerIds, color2 = chunkMR32IJQO_cjs.CHANGE_COLOR) => {
927
+ const flash = (ownerIds, color2 = chunkWZA3DJJH_cjs.CHANGE_COLOR) => {
909
928
  const ids = [...new Set(ownerIds)];
910
929
  if (ids.length === 0) {
911
930
  return;
@@ -913,7 +932,7 @@ function createChangeFlash(svg) {
913
932
  const doc = svg.ownerDocument;
914
933
  const reducedMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
915
934
  for (const id of ids) {
916
- const primary = chunkMR32IJQO_cjs.findOwnerNode(svg, id, chunkMR32IJQO_cjs.isPrimary);
935
+ const primary = chunkWZA3DJJH_cjs.findOwnerNode(svg, id, chunkWZA3DJJH_cjs.isPrimary);
917
936
  if (!primary) {
918
937
  continue;
919
938
  }
@@ -924,10 +943,10 @@ function createChangeFlash(svg) {
924
943
  for (const stale of svg.querySelectorAll(`[data-sf-change-overlay="${CSS.escape(id)}"]`)) {
925
944
  stale.remove();
926
945
  }
927
- const overlay = primary.getAttribute("data-sf-role") === "link" ? chunkMR32IJQO_cjs.linkChangeOverlay(doc, primary, id, color2) : chunkMR32IJQO_cjs.shapeChangeOverlay(doc, primary, id, color2);
946
+ const overlay = primary.getAttribute("data-sf-role") === "link" ? chunkWZA3DJJH_cjs.linkChangeOverlay(doc, primary, id, color2) : chunkWZA3DJJH_cjs.shapeChangeOverlay(doc, primary, id, color2);
928
947
  svg.appendChild(overlay);
929
- chunkMR32IJQO_cjs.startChangeFade(overlay, reducedMotion);
930
- const duration = reducedMotion ? chunkMR32IJQO_cjs.REDUCED_MOTION_DURATION_MS : chunkMR32IJQO_cjs.FLASH_DURATION_MS;
948
+ chunkWZA3DJJH_cjs.startChangeFade(overlay, reducedMotion);
949
+ const duration = reducedMotion ? chunkWZA3DJJH_cjs.REDUCED_MOTION_DURATION_MS : chunkWZA3DJJH_cjs.FLASH_DURATION_MS;
931
950
  timers.set(
932
951
  id,
933
952
  setTimeout(() => {
@@ -1014,7 +1033,7 @@ var OwnerPointerController = class {
1014
1033
  this.#selection = selection;
1015
1034
  }
1016
1035
  hover(event) {
1017
- const owner = chunkMR32IJQO_cjs.resolveOwner(event.target);
1036
+ const owner = chunkWZA3DJJH_cjs.resolveOwner(event.target);
1018
1037
  this.#emitter.emit(
1019
1038
  "ownerHover",
1020
1039
  owner ? { diagramId: this.#diagramId, owner, modifiers: modifiersOf(event) } : { diagramId: this.#diagramId, owner: null }
@@ -1022,7 +1041,7 @@ var OwnerPointerController = class {
1022
1041
  }
1023
1042
  select(event) {
1024
1043
  const target = event.target;
1025
- const owner = chunkMR32IJQO_cjs.resolveOwner(target);
1044
+ const owner = chunkWZA3DJJH_cjs.resolveOwner(target);
1026
1045
  if (!owner) {
1027
1046
  this.#clearWhenOutsideOverlay(target);
1028
1047
  return;
@@ -1043,7 +1062,7 @@ var OwnerPointerController = class {
1043
1062
  owner,
1044
1063
  modifiers
1045
1064
  });
1046
- const node = chunkMR32IJQO_cjs.findOwnerNode(this.#svg, owner.id, chunkMR32IJQO_cjs.isPrimary);
1065
+ const node = chunkWZA3DJJH_cjs.findOwnerNode(this.#svg, owner.id, chunkWZA3DJJH_cjs.isPrimary);
1047
1066
  if (node && !node.hasAttribute("tabindex")) {
1048
1067
  node.setAttribute("tabindex", "-1");
1049
1068
  }
@@ -1071,12 +1090,12 @@ var PointerInteractionSession = class {
1071
1090
  }
1072
1091
  #onPointerDown = (event) => {
1073
1092
  const target = event.target;
1074
- const overContent = Boolean(chunkMR32IJQO_cjs.resolveOwner(target)) || isSelectionOverlayControl(target);
1093
+ const overContent = Boolean(chunkWZA3DJJH_cjs.resolveOwner(target)) || isSelectionOverlayControl(target);
1075
1094
  this.#down = {
1076
1095
  x: event.clientX,
1077
1096
  y: event.clientY,
1078
1097
  moved: false,
1079
- panable: chunkMR32IJQO_cjs.isCameraGesture(event) || !overContent
1098
+ panable: chunkWZA3DJJH_cjs.isCameraGesture(event) || !overContent
1080
1099
  };
1081
1100
  };
1082
1101
  #onPointerMove = (event) => {
@@ -1104,7 +1123,7 @@ var PointerInteractionSession = class {
1104
1123
  if (!this.#down.moved) {
1105
1124
  return false;
1106
1125
  }
1107
- if (this.#down.panable && chunkMR32IJQO_cjs.isCameraGesture(event)) {
1126
+ if (this.#down.panable && chunkWZA3DJJH_cjs.isCameraGesture(event)) {
1108
1127
  this.#display.panBy(event.movementX, event.movementY);
1109
1128
  }
1110
1129
  return true;
@@ -1128,15 +1147,15 @@ function paintSelectionOverlays(svg, selectedIds, owners) {
1128
1147
  }
1129
1148
  const document = svg.ownerDocument;
1130
1149
  for (const id of selectedIds) {
1131
- const primary = chunkMR32IJQO_cjs.findOwnerNode(svg, id, chunkMR32IJQO_cjs.isPrimary);
1150
+ const primary = chunkWZA3DJJH_cjs.findOwnerNode(svg, id, chunkWZA3DJJH_cjs.isPrimary);
1132
1151
  if (!primary) {
1133
1152
  continue;
1134
1153
  }
1135
1154
  const owner = owners.get(id);
1136
- const overlay = owner?.role === "link" ? chunkMR32IJQO_cjs.linkSelectionOverlay(document, primary, id, svg) : owner?.role === "path" ? chunkMR32IJQO_cjs.pathSelectionOverlay(document, primary, id, svg) : owner?.role === "isometric" ? chunkMR32IJQO_cjs.isometricSelectionOverlay(document, primary, id, svg) : chunkMR32IJQO_cjs.shapeSelectionOverlay(document, primary, id, svg, owner ? chunkMR32IJQO_cjs.DERIVED_HEIGHT_ROLES.has(owner.role) : false);
1155
+ const overlay = owner?.role === "link" ? chunkWZA3DJJH_cjs.linkSelectionOverlay(document, primary, id, svg) : owner?.role === "path" ? chunkWZA3DJJH_cjs.pathSelectionOverlay(document, primary, id, svg) : owner?.role === "isometric" ? chunkWZA3DJJH_cjs.isometricSelectionOverlay(document, primary, id, svg) : chunkWZA3DJJH_cjs.shapeSelectionOverlay(document, primary, id, svg, owner ? chunkWZA3DJJH_cjs.DERIVED_HEIGHT_ROLES.has(owner.role) : false);
1137
1156
  svg.appendChild(overlay);
1138
1157
  if (owner?.role === "shape" && selectedIds.size === 1) {
1139
- svg.appendChild(chunkMR32IJQO_cjs.quickDuplicateBubbles(document, primary, id, svg));
1158
+ svg.appendChild(chunkWZA3DJJH_cjs.quickDuplicateBubbles(document, primary, id, svg));
1140
1159
  }
1141
1160
  }
1142
1161
  }
@@ -1175,7 +1194,7 @@ var SelectionController = class {
1175
1194
  selectIds(ids) {
1176
1195
  for (const id of ids) {
1177
1196
  const element = this.#svg.querySelector(`[data-sf-id="${CSS.escape(id)}"]`);
1178
- const owner = chunkMR32IJQO_cjs.resolveOwner(element);
1197
+ const owner = chunkWZA3DJJH_cjs.resolveOwner(element);
1179
1198
  if (owner) {
1180
1199
  this.remember(owner);
1181
1200
  }
@@ -1187,7 +1206,7 @@ var SelectionController = class {
1187
1206
  // src/runtime/viewer/interaction/wheel.ts
1188
1207
  function bindWheelZoom(display, selection) {
1189
1208
  const onWheel = (event) => {
1190
- if (!chunkMR32IJQO_cjs.isCameraGesture(event)) {
1209
+ if (!chunkWZA3DJJH_cjs.isCameraGesture(event)) {
1191
1210
  return;
1192
1211
  }
1193
1212
  event.preventDefault();
@@ -2952,9 +2971,7 @@ float roundedBoxDistance(vec2 point, vec2 halfSize, float radius) {
2952
2971
  }
2953
2972
 
2954
2973
  float random(vec2 point) {
2955
- vec3 value = fract(vec3(point.xyx) * 0.1031);
2956
- value += dot(value, value.yzx + 33.33);
2957
- return fract((value.x + value.y) * value.z);
2974
+ return fract(sin(dot(mod(point, 289.0), vec2(127.1, 311.7))) * 43758.5453123);
2958
2975
  }
2959
2976
 
2960
2977
  void main() {
@@ -3565,6 +3582,218 @@ var violetGlassLightProgram = {
3565
3582
  fragmentSource: fragmentSource26
3566
3583
  };
3567
3584
 
3585
+ // src/runtime/viewer/shaders/builtins/vortex.ts
3586
+ var fragmentSource27 = `
3587
+ precision highp float;
3588
+
3589
+ uniform float uTime;
3590
+ uniform float uSpeed;
3591
+ uniform float uIntensity;
3592
+ uniform float uRings;
3593
+ uniform float uRingWidth;
3594
+ uniform float uTwist;
3595
+ uniform float uArms;
3596
+ uniform float uWobble;
3597
+ uniform float uVariation;
3598
+ uniform float uOffsetX;
3599
+ uniform float uOffsetY;
3600
+ uniform float uSquash;
3601
+ uniform float uEye;
3602
+ uniform float uAngle;
3603
+ uniform float uSpread;
3604
+ uniform float uGlow;
3605
+ uniform float uGloss;
3606
+ uniform float uGlossHeight;
3607
+ uniform float uVignette;
3608
+ uniform float uGrain;
3609
+ uniform vec3 uColor;
3610
+ uniform vec3 uAccent;
3611
+ uniform vec3 uCool;
3612
+ varying vec2 vUv;
3613
+
3614
+ float hash(vec2 p) {
3615
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
3616
+ }
3617
+
3618
+ void main() {
3619
+ vec2 p = vUv * 2.0 - 1.0;
3620
+ float edge = length(p);
3621
+ if (edge > 1.0) discard;
3622
+
3623
+ float time = uTime * max(uSpeed, 0.0);
3624
+
3625
+ // The rings are measured from a middle that can lie off the middle of the face, and squeezed to give a little depth.
3626
+ vec2 q = p - vec2(uOffsetX, uOffsetY);
3627
+ q.y /= max(uSquash, 0.2);
3628
+ float radius = length(q);
3629
+ float around = atan(q.y, q.x);
3630
+ float turn = around / 6.2831853;
3631
+ // The twist turns the pattern more the nearer it is to the middle. The rings themselves stay round.
3632
+ float angle = around + uTwist * pow(1.0 - radius, 2.0) * 3.0 + time * 0.3 * (1.0 - radius);
3633
+
3634
+ // The phase of the rings: outwards from the middle, drifting inwards with time. Whole arms make the rings join into a spiral, and a
3635
+ // whole number leaves no seam. The wobble bends the rings so no two are alike.
3636
+ float bend = uWobble * (0.12 * sin(angle * 2.0 + time * 0.6 + radius * 3.0) + 0.06 * sin(angle * 3.0 - time * 0.45));
3637
+ float phase = (radius + bend) * uRings - time * 0.25 + floor(uArms + 0.5) * turn;
3638
+ float away = abs(fract(phase) - 0.5);
3639
+ float width = mix(0.04, 0.32, clamp(uRingWidth, 0.0, 1.0));
3640
+ // Every ring has a brightness of its own, so a few stand out and the others are faint.
3641
+ float own = mix(1.0, 0.25 + 1.0 * hash(vec2(floor(phase), 3.7)), clamp(uVariation, 0.0, 1.0));
3642
+ float ring = exp(-pow(away / width, 2.0)) * own;
3643
+ float fineAway = abs(fract(phase * 2.3 + 0.5) - 0.5);
3644
+ float fine = exp(-pow(fineAway / (width * 0.8), 2.0)) * 0.5;
3645
+ float halo = exp(-pow(away / (width * 3.0), 2.0));
3646
+
3647
+ // Rings fade in from the eye and out towards the rim, and some arcs of a ring are brighter than the rest.
3648
+ float envelope = smoothstep(uEye, uEye + 0.3, radius) * (1.0 - smoothstep(0.72, 1.05, edge));
3649
+ float arcs = 0.45 + 0.55 * (0.5 + 0.5 * sin(angle * 2.0 + radius * 4.0 + time * 0.5 + 1.0));
3650
+
3651
+ // One side of the face is warm and the other cool, and the spread says how sharp the change is.
3652
+ float side = cos(angle - radians(uAngle));
3653
+ float warm = mix(0.5, smoothstep(-0.7, 0.9, side), clamp(uSpread, 0.0, 1.0));
3654
+ vec3 hue = mix(uCool, uAccent, warm);
3655
+
3656
+ vec3 color = uColor * (0.4 + 0.5 * (1.0 - edge));
3657
+ color += hue * (ring * 0.9 + fine * 0.3) * envelope * arcs * uGlow;
3658
+ color += hue * halo * envelope * 0.1 * uGlow;
3659
+ // The dark eye.
3660
+ color *= 0.55 + 0.45 * smoothstep(0.0, uEye + 0.12, radius);
3661
+
3662
+ // A soft light on the glass at the bottom, with a clear lower edge.
3663
+ float below = smoothstep(-1.0 + uGlossHeight, -1.0 + uGlossHeight * 0.35, p.y);
3664
+ float across = 1.0 - smoothstep(0.45, 1.0, abs(p.x));
3665
+ color += mix(uCool, vec3(1.0), 0.5) * below * across * uGloss;
3666
+
3667
+ color *= 1.0 - smoothstep(0.55, 1.0, edge) * uVignette;
3668
+ color += (hash(gl_FragCoord.xy + time) - 0.5) * uGrain;
3669
+
3670
+ float alpha = 1.0 - smoothstep(0.985, 1.0, edge);
3671
+ gl_FragColor = vec4(clamp(color * max(uIntensity, 0.0), 0.0, 1.0), alpha);
3672
+ }
3673
+ `;
3674
+ var vortexProgram = {
3675
+ name: "vortex",
3676
+ fragmentSource: fragmentSource27,
3677
+ defaultParameters: {
3678
+ speed: 0.3,
3679
+ intensity: 1,
3680
+ rings: 12,
3681
+ ringWidth: 0.28,
3682
+ twist: 0.6,
3683
+ arms: 0,
3684
+ wobble: 0.12,
3685
+ variation: 0.85,
3686
+ offsetX: 0,
3687
+ offsetY: 0,
3688
+ squash: 1,
3689
+ eye: 0.3,
3690
+ angle: 215,
3691
+ spread: 0.6,
3692
+ glow: 0.6,
3693
+ gloss: 0.45,
3694
+ glossHeight: 0.4,
3695
+ vignette: 0.6,
3696
+ grain: 0.02,
3697
+ color: "#05060f",
3698
+ accent: "#e0368f",
3699
+ cool: "#3d4bff"
3700
+ }
3701
+ };
3702
+
3703
+ // src/runtime/viewer/shaders/builtins/waves.ts
3704
+ var fragmentSource28 = `
3705
+ precision highp float;
3706
+
3707
+ uniform float uTime;
3708
+ uniform float uSpeed;
3709
+ uniform float uIntensity;
3710
+ uniform float uLayers;
3711
+ uniform float uLevel;
3712
+ uniform float uAmplitude;
3713
+ uniform float uFrequency;
3714
+ uniform float uTilt;
3715
+ uniform float uSoftness;
3716
+ uniform float uEdge;
3717
+ uniform float uShade;
3718
+ uniform float uGlow;
3719
+ uniform float uVignette;
3720
+ uniform float uGrain;
3721
+ uniform vec3 uColor;
3722
+ uniform vec3 uAccent;
3723
+ uniform vec3 uCool;
3724
+ uniform vec3 uHighlight;
3725
+ varying vec2 vUv;
3726
+
3727
+ float hash(vec2 p) {
3728
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
3729
+ }
3730
+
3731
+ void main() {
3732
+ vec2 p = vUv * 2.0 - 1.0;
3733
+ float edge = length(p);
3734
+ if (edge > 1.0) discard;
3735
+
3736
+ float time = uTime * max(uSpeed, 0.0);
3737
+ float angle = radians(uTilt);
3738
+ vec2 q = vec2(cos(angle) * p.x - sin(angle) * p.y, sin(angle) * p.x + cos(angle) * p.y);
3739
+
3740
+ // The ground, a little lighter in the middle.
3741
+ vec3 color = uColor * (0.6 + 0.4 * (1.0 - edge));
3742
+ float count = clamp(uLayers, 1.0, 8.0);
3743
+ float soft = max(uSoftness, 0.004);
3744
+
3745
+ // The layers lie one behind the other, the farthest first. Each one fills the area under a wave line, and the line itself catches the light.
3746
+ for (int i = 0; i < 8; i++) {
3747
+ float index = float(i);
3748
+ if (index >= count) break;
3749
+ float depth = index / max(count - 1.0, 1.0);
3750
+ float base = uLevel + mix(0.5, -0.55, depth);
3751
+ float swing = uAmplitude * (0.55 + 0.45 * depth);
3752
+ float line = base
3753
+ + swing * 0.6 * sin(q.x * uFrequency * (1.0 + 0.3 * index) + index * 1.7 + time * (0.4 + 0.08 * index))
3754
+ + swing * 0.4 * sin(q.x * uFrequency * 2.1 - index * 2.3 - time * 0.3);
3755
+ float under = smoothstep(soft, -soft, q.y - line);
3756
+ // A layer is lit at its crest and falls into shadow below it, so it reads as a fold of cloth and not as a flat band.
3757
+ float sink = clamp((line - q.y) / 0.35, 0.0, 1.0);
3758
+ vec3 layer = mix(uAccent, uCool, depth) * mix(1.15, 1.0 - 0.6 * uShade, sink);
3759
+ color = mix(color, layer, under * (0.5 + 0.2 * depth));
3760
+ float crest = exp(-pow((q.y - line) / (0.012 + soft * 0.5), 2.0));
3761
+ color += uHighlight * crest * uEdge * (0.35 + 0.65 * (1.0 - depth));
3762
+ }
3763
+
3764
+ // A soft light over the surface, and a dark edge.
3765
+ color += uHighlight * uGlow * 0.18 * exp(-pow((q.y - 0.55) / 0.45, 2.0));
3766
+ color *= 1.0 - smoothstep(0.6, 1.0, edge) * uVignette;
3767
+ color += (hash(gl_FragCoord.xy + time) - 0.5) * uGrain;
3768
+
3769
+ float alpha = 1.0 - smoothstep(0.985, 1.0, edge);
3770
+ gl_FragColor = vec4(clamp(color * max(uIntensity, 0.0), 0.0, 1.0), alpha);
3771
+ }
3772
+ `;
3773
+ var wavesProgram = {
3774
+ name: "waves",
3775
+ fragmentSource: fragmentSource28,
3776
+ defaultParameters: {
3777
+ speed: 0.25,
3778
+ intensity: 1,
3779
+ layers: 5,
3780
+ level: 0,
3781
+ amplitude: 0.14,
3782
+ frequency: 3.2,
3783
+ tilt: -12,
3784
+ softness: 0.05,
3785
+ edge: 0.5,
3786
+ shade: 0.6,
3787
+ glow: 0.5,
3788
+ vignette: 0.4,
3789
+ grain: 0.02,
3790
+ color: "#0e0828",
3791
+ accent: "#6b3fd4",
3792
+ cool: "#2f5fe0",
3793
+ highlight: "#b9a0ff"
3794
+ }
3795
+ };
3796
+
3568
3797
  // src/runtime/viewer/shaders/programs.ts
3569
3798
  var builtins = [
3570
3799
  orbProgram,
@@ -3592,7 +3821,9 @@ var builtins = [
3592
3821
  lightBandProgram,
3593
3822
  silkFoldsProgram,
3594
3823
  glowCardProgram,
3595
- glassDotsProgram
3824
+ glassDotsProgram,
3825
+ vortexProgram,
3826
+ wavesProgram
3596
3827
  ];
3597
3828
  var programs = new Map(builtins.map((program) => [program.name, program]));
3598
3829
  function registerShaderProgram(program) {
@@ -3773,9 +4004,9 @@ function compile(gl, type, source) {
3773
4004
  }
3774
4005
  return shader;
3775
4006
  }
3776
- function linkProgram(gl, fragmentSource27) {
4007
+ function linkProgram(gl, fragmentSource29) {
3777
4008
  const vertex = compile(gl, gl.VERTEX_SHADER, VERTEX_SOURCE);
3778
- const fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource27);
4009
+ const fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource29);
3779
4010
  if (!vertex || !fragment) {
3780
4011
  if (vertex) {
3781
4012
  gl.deleteShader(vertex);
@@ -3876,6 +4107,7 @@ function createSurface(canvas) {
3876
4107
  const baseFill = baseGeometry?.getAttribute("fill");
3877
4108
  baseGeometry?.setAttribute("fill", "none");
3878
4109
  return {
4110
+ programName: definition.name,
3879
4111
  owner,
3880
4112
  canvas,
3881
4113
  gl,
@@ -3912,6 +4144,22 @@ function releaseSurface(surface) {
3912
4144
  surface.baseGeometry.setAttribute("fill", surface.baseFill);
3913
4145
  }
3914
4146
  }
4147
+ function refreshSurface(surface, svg) {
4148
+ const owner = surface.canvas.closest("[data-sf-shader]");
4149
+ const name = owner?.getAttribute("data-sf-shader");
4150
+ const definition = name ? shaderProgram(name) : void 0;
4151
+ if (!owner || !svg.contains(surface.canvas) || !definition) {
4152
+ return false;
4153
+ }
4154
+ if (definition.name !== surface.programName || definition.replacesBaseFill || surface.baseGeometry) {
4155
+ return false;
4156
+ }
4157
+ surface.owner = owner;
4158
+ surface.parameters = { ...definition.defaultParameters, ...parametersOf(owner) };
4159
+ surface.surfacePadding = surfacePaddingOf(owner);
4160
+ surface.shapeColor = color(owner.getAttribute("data-sf-shader-fill") ?? void 0, [1, 1, 1]);
4161
+ return true;
4162
+ }
3915
4163
 
3916
4164
  // src/runtime/viewer/shaders/reactiveLightField.ts
3917
4165
  function geometryOf(surface) {
@@ -4044,8 +4292,7 @@ function applyBackdrop(surface, backdrop) {
4044
4292
  }
4045
4293
  var MAX_SURFACE_PIXELS = 2560;
4046
4294
  var TRAIL_LENGTH = 16;
4047
- function renderSurface(surface, seconds) {
4048
- const { canvas, gl, parameters: parameters3 } = surface;
4295
+ function fitCanvas(canvas) {
4049
4296
  const shown = canvas.getBoundingClientRect();
4050
4297
  const density = Math.min(globalThis.devicePixelRatio || 1, 3);
4051
4298
  const fit = Math.min(1, MAX_SURFACE_PIXELS / Math.max(1, shown.width * density, shown.height * density));
@@ -4055,32 +4302,22 @@ function renderSurface(surface, seconds) {
4055
4302
  canvas.width = width;
4056
4303
  canvas.height = height;
4057
4304
  }
4058
- gl.viewport(0, 0, width, height);
4059
- gl.clearColor(0, 0, 0, 0);
4060
- gl.clear(gl.COLOR_BUFFER_BIT);
4061
- gl.useProgram(surface.program);
4062
- const resolution = gl.getUniformLocation(surface.program, "uResolution");
4063
- if (resolution) {
4064
- gl.uniform2f(resolution, width, height);
4065
- }
4066
- const logicalWidth = Number(surface.owner.getAttribute("width"));
4067
- uniform1f(
4068
- surface,
4069
- "uPixelScale",
4070
- Number.isFinite(logicalWidth) && logicalWidth > 0 ? width / logicalWidth : density * fit
4071
- );
4072
- uniform1f(surface, "uTime", seconds);
4073
- if (surface.backdropTexture) {
4074
- syncBackdropBounds(surface);
4075
- gl.activeTexture(gl.TEXTURE0);
4076
- gl.bindTexture(gl.TEXTURE_2D, surface.backdropTexture);
4077
- const sampler = gl.getUniformLocation(surface.program, "uBackdrop");
4078
- if (sampler) {
4079
- gl.uniform1i(sampler, 0);
4080
- }
4081
- uniform2f(surface, "uBackdropOrigin", surface.backdropOrigin);
4082
- uniform2f(surface, "uBackdropScale", surface.backdropScale);
4305
+ return { width, height, density, fit };
4306
+ }
4307
+ function bindBackdrop(surface, texture) {
4308
+ const { gl } = surface;
4309
+ syncBackdropBounds(surface);
4310
+ gl.activeTexture(gl.TEXTURE0);
4311
+ gl.bindTexture(gl.TEXTURE_2D, texture);
4312
+ const sampler = gl.getUniformLocation(surface.program, "uBackdrop");
4313
+ if (sampler) {
4314
+ gl.uniform1i(sampler, 0);
4083
4315
  }
4316
+ uniform2f(surface, "uBackdropOrigin", surface.backdropOrigin);
4317
+ uniform2f(surface, "uBackdropScale", surface.backdropScale);
4318
+ }
4319
+ function uploadParameters(surface) {
4320
+ const { parameters: parameters3 } = surface;
4084
4321
  for (const [key, fallback] of Object.entries(SHADER_DEFAULTS.numbers)) {
4085
4322
  uniform1f(surface, uniformName(key), number(parameters3[key], fallback));
4086
4323
  }
@@ -4088,9 +4325,9 @@ function renderSurface(surface, seconds) {
4088
4325
  uniform3f(surface, uniformName(key), color(parameters3[key], [...fallback]));
4089
4326
  }
4090
4327
  uniform3f(surface, "uShapeColor", surface.shapeColor);
4091
- const elapsed = surface.lastSeconds === void 0 ? 0 : Math.max(0, Math.min(seconds - surface.lastSeconds, 0.1));
4092
- surface.lastSeconds = seconds;
4093
- applyParameters(surface, elapsed);
4328
+ }
4329
+ function uploadPointer(surface, seconds, elapsed) {
4330
+ const { gl, parameters: parameters3 } = surface;
4094
4331
  surface.hover += ((surface.hovering ? 1 : 0) - surface.hover) * (1 - Math.exp(-elapsed / 0.18));
4095
4332
  uniform2f(surface, "uPointer", [surface.pointer.x, surface.pointer.y]);
4096
4333
  uniform1f(surface, "uHover", surface.hover);
@@ -4105,13 +4342,44 @@ function renderSurface(surface, seconds) {
4105
4342
  if (trail) {
4106
4343
  gl.uniform3fv(trail, places);
4107
4344
  }
4108
- if (surface.reactiveLight) {
4109
- uniform1f(surface, "uLightX", surface.reactiveLight.x);
4110
- uniform1f(surface, "uLightY", surface.reactiveLight.y);
4111
- uniform1f(surface, "uLightStrength", surface.reactiveLight.strength);
4112
- uniform1f(surface, "uGlowRadius", surface.reactiveLight.radius);
4113
- uniform3f(surface, "uLightColor", surface.reactiveLight.color);
4345
+ }
4346
+ function uploadReactiveLight(surface) {
4347
+ if (!surface.reactiveLight) {
4348
+ return;
4349
+ }
4350
+ uniform1f(surface, "uLightX", surface.reactiveLight.x);
4351
+ uniform1f(surface, "uLightY", surface.reactiveLight.y);
4352
+ uniform1f(surface, "uLightStrength", surface.reactiveLight.strength);
4353
+ uniform1f(surface, "uGlowRadius", surface.reactiveLight.radius);
4354
+ uniform3f(surface, "uLightColor", surface.reactiveLight.color);
4355
+ }
4356
+ function renderSurface(surface, seconds) {
4357
+ const { canvas, gl } = surface;
4358
+ const { width, height, density, fit } = fitCanvas(canvas);
4359
+ gl.viewport(0, 0, width, height);
4360
+ gl.clearColor(0, 0, 0, 0);
4361
+ gl.clear(gl.COLOR_BUFFER_BIT);
4362
+ gl.useProgram(surface.program);
4363
+ const resolution = gl.getUniformLocation(surface.program, "uResolution");
4364
+ if (resolution) {
4365
+ gl.uniform2f(resolution, width, height);
4114
4366
  }
4367
+ const logicalWidth = Number(surface.owner.getAttribute("width"));
4368
+ uniform1f(
4369
+ surface,
4370
+ "uPixelScale",
4371
+ Number.isFinite(logicalWidth) && logicalWidth > 0 ? width / logicalWidth : density * fit
4372
+ );
4373
+ uniform1f(surface, "uTime", seconds);
4374
+ if (surface.backdropTexture) {
4375
+ bindBackdrop(surface, surface.backdropTexture);
4376
+ }
4377
+ uploadParameters(surface);
4378
+ const elapsed = surface.lastSeconds === void 0 ? 0 : Math.max(0, Math.min(seconds - surface.lastSeconds, 0.1));
4379
+ surface.lastSeconds = seconds;
4380
+ applyParameters(surface, elapsed);
4381
+ uploadPointer(surface, seconds, elapsed);
4382
+ uploadReactiveLight(surface);
4115
4383
  uniform1f(surface, "uSurfacePadding", surface.surfacePadding);
4116
4384
  gl.drawArrays(gl.TRIANGLES, 0, 6);
4117
4385
  }
@@ -4186,171 +4454,206 @@ function watchSvgChanges(svg, view, onChange) {
4186
4454
  sizes?.disconnect();
4187
4455
  };
4188
4456
  }
4189
- function mountShaderSurfaces(svg) {
4190
- let surfaces = [];
4191
- let frame;
4192
- let backdropGeneration = 0;
4193
- let recapture;
4194
- const view = svg.ownerDocument.defaultView;
4195
- const clock = createSurfaceClock(view);
4196
- const draw = (milliseconds) => {
4197
- if (!clock.paused()) {
4198
- updateReactiveLightFields(surfaces);
4199
- for (const surface of surfaces) {
4200
- renderSurface(surface, milliseconds / 1e3 - clock.spent());
4457
+ function rememberSurfaces(surfaces) {
4458
+ return new Map(
4459
+ surfaces.flatMap((surface) => {
4460
+ const ownerId = surface.owner.getAttribute("data-sf-id");
4461
+ return ownerId ? [
4462
+ [
4463
+ ownerId,
4464
+ {
4465
+ smoothed: new Map(surface.smoothed),
4466
+ reactiveLight: surface.reactiveLight,
4467
+ pointer: surface.pointer,
4468
+ hover: surface.hover,
4469
+ hovering: surface.hovering,
4470
+ trail: surface.trail
4471
+ }
4472
+ ]
4473
+ ] : [];
4474
+ })
4475
+ );
4476
+ }
4477
+ function createSurfaces(svg, memory, kept) {
4478
+ return [...svg.querySelectorAll("canvas[data-sf-shader-canvas]")].flatMap((canvas) => {
4479
+ const keptSurface = kept.get(canvas);
4480
+ if (keptSurface) {
4481
+ return [keptSurface];
4482
+ }
4483
+ const surface = createSurface(canvas);
4484
+ const ownerId = surface?.owner.getAttribute("data-sf-id");
4485
+ const previous = ownerId ? memory.get(ownerId) : void 0;
4486
+ if (surface && previous) {
4487
+ Object.assign(surface, previous);
4488
+ }
4489
+ return surface ? [surface] : [];
4490
+ });
4491
+ }
4492
+ function followPointer(surface, event, now) {
4493
+ const box = surface.canvas.getBoundingClientRect();
4494
+ const inside = box.width > 0 && box.height > 0 && event.clientX >= box.left && event.clientX <= box.right && event.clientY >= box.top && event.clientY <= box.bottom;
4495
+ surface.hovering = inside;
4496
+ if (!inside) {
4497
+ return;
4498
+ }
4499
+ surface.pointer = { x: (event.clientX - box.left) / box.width, y: 1 - (event.clientY - box.top) / box.height };
4500
+ const last = surface.trail[surface.trail.length - 1];
4501
+ if (!last || now - last.at >= TRAIL_SPACING) {
4502
+ surface.trail.push({ ...surface.pointer, at: now });
4503
+ if (surface.trail.length > TRAIL_LENGTH2) {
4504
+ surface.trail.shift();
4505
+ }
4506
+ }
4507
+ }
4508
+ var ShaderSurfaces = class {
4509
+ constructor(svg) {
4510
+ this.svg = svg;
4511
+ this.view = svg.ownerDocument.defaultView;
4512
+ this.clock = createSurfaceClock(this.view);
4513
+ this.unwatch = watchSvgChanges(svg, this.view, this.scheduleRecapture);
4514
+ svg.addEventListener("pointermove", this.track);
4515
+ svg.addEventListener("pointerleave", this.leave);
4516
+ this.refresh();
4517
+ }
4518
+ svg;
4519
+ surfaces = [];
4520
+ frame;
4521
+ backdropGeneration = 0;
4522
+ recapture;
4523
+ view;
4524
+ clock;
4525
+ unwatch;
4526
+ capture() {
4527
+ return capturePngs(this.svg, this.surfaces, this.clock.now());
4528
+ }
4529
+ setParameters(ownerId, parameters3) {
4530
+ return updateParameters(this.surfaces, ownerId, parameters3, this.clock.now());
4531
+ }
4532
+ setPaused(paused) {
4533
+ this.clock.setPaused(paused);
4534
+ }
4535
+ refresh() {
4536
+ const memory = rememberSurfaces(this.surfaces);
4537
+ this.cancelFrame();
4538
+ const kept = /* @__PURE__ */ new Map();
4539
+ for (const surface of this.surfaces) {
4540
+ if (refreshSurface(surface, this.svg)) {
4541
+ kept.set(surface.canvas, surface);
4201
4542
  }
4202
4543
  }
4203
- frame = view?.requestAnimationFrame(draw);
4544
+ for (const surface of this.surfaces) {
4545
+ if (!kept.has(surface.canvas)) {
4546
+ releaseSurface(surface);
4547
+ }
4548
+ }
4549
+ const generation = ++this.backdropGeneration;
4550
+ this.surfaces = createSurfaces(this.svg, memory, kept);
4551
+ updateReactiveLightFields(this.surfaces);
4552
+ this.captureBackdrops(generation);
4553
+ if (this.surfaces.length > 0) {
4554
+ this.startFrames();
4555
+ }
4556
+ }
4557
+ destroy() {
4558
+ this.backdropGeneration += 1;
4559
+ this.unwatch();
4560
+ this.svg.removeEventListener("pointermove", this.track);
4561
+ this.svg.removeEventListener("pointerleave", this.leave);
4562
+ if (this.recapture !== void 0) {
4563
+ this.view?.clearTimeout(this.recapture);
4564
+ }
4565
+ this.stop();
4566
+ }
4567
+ draw = (milliseconds) => {
4568
+ if (!this.clock.paused()) {
4569
+ updateReactiveLightFields(this.surfaces);
4570
+ for (const surface of this.surfaces) {
4571
+ renderSurface(surface, milliseconds / 1e3 - this.clock.spent());
4572
+ }
4573
+ }
4574
+ this.frame = this.view?.requestAnimationFrame(this.draw);
4204
4575
  };
4205
- const stop = () => {
4206
- if (frame !== void 0) {
4207
- view?.cancelAnimationFrame(frame);
4208
- frame = void 0;
4576
+ cancelFrame() {
4577
+ if (this.frame !== void 0) {
4578
+ this.view?.cancelAnimationFrame(this.frame);
4579
+ this.frame = void 0;
4209
4580
  }
4210
- for (const surface of surfaces) {
4581
+ }
4582
+ stop() {
4583
+ this.cancelFrame();
4584
+ for (const surface of this.surfaces) {
4211
4585
  releaseSurface(surface);
4212
4586
  }
4213
- surfaces = [];
4214
- };
4215
- const captureBackdrops = (generation) => {
4216
- for (const surface of surfaces) {
4587
+ this.surfaces = [];
4588
+ }
4589
+ captureBackdrops(generation) {
4590
+ for (const surface of this.surfaces) {
4217
4591
  if (!surface.usesBackdrop) {
4218
4592
  continue;
4219
4593
  }
4220
- void captureShaderBackdrop(svg, surface.owner).then((backdrop) => {
4221
- if (backdrop && generation === backdropGeneration) {
4594
+ void captureShaderBackdrop(this.svg, surface.owner).then((backdrop) => {
4595
+ if (backdrop && generation === this.backdropGeneration) {
4222
4596
  applyBackdrop(surface, backdrop);
4223
4597
  }
4224
4598
  });
4225
4599
  }
4226
- };
4227
- const startFrames = () => {
4228
- if (!view?.requestAnimationFrame) {
4229
- for (const surface of surfaces) {
4600
+ }
4601
+ startFrames() {
4602
+ if (!this.view?.requestAnimationFrame) {
4603
+ for (const surface of this.surfaces) {
4230
4604
  renderSurface(surface, 0);
4231
4605
  }
4232
4606
  return;
4233
4607
  }
4234
- if (clock.paused()) {
4235
- for (const surface of surfaces) {
4236
- renderSurface(surface, clock.now());
4608
+ if (this.clock.paused()) {
4609
+ for (const surface of this.surfaces) {
4610
+ renderSurface(surface, this.clock.now());
4237
4611
  }
4238
4612
  }
4239
- frame = view.requestAnimationFrame(draw);
4240
- };
4241
- const refresh = () => {
4242
- const previousState = new Map(
4243
- surfaces.flatMap((surface) => {
4244
- const ownerId = surface.owner.getAttribute("data-sf-id");
4245
- return ownerId ? [
4246
- [
4247
- ownerId,
4248
- {
4249
- smoothed: new Map(surface.smoothed),
4250
- reactiveLight: surface.reactiveLight,
4251
- pointer: surface.pointer,
4252
- hover: surface.hover,
4253
- hovering: surface.hovering,
4254
- trail: surface.trail
4255
- }
4256
- ]
4257
- ] : [];
4258
- })
4259
- );
4260
- stop();
4261
- const generation = ++backdropGeneration;
4262
- surfaces = [...svg.querySelectorAll("canvas[data-sf-shader-canvas]")].flatMap((canvas) => {
4263
- const surface = createSurface(canvas);
4264
- const ownerId = surface?.owner.getAttribute("data-sf-id");
4265
- const previous = ownerId ? previousState.get(ownerId) : void 0;
4266
- if (surface && previous) {
4267
- surface.smoothed = previous.smoothed;
4268
- surface.reactiveLight = previous.reactiveLight;
4269
- surface.pointer = previous.pointer;
4270
- surface.hover = previous.hover;
4271
- surface.hovering = previous.hovering;
4272
- surface.trail = previous.trail;
4273
- }
4274
- return surface ? [surface] : [];
4275
- });
4276
- updateReactiveLightFields(surfaces);
4277
- captureBackdrops(generation);
4278
- if (surfaces.length > 0) {
4279
- startFrames();
4280
- }
4281
- };
4282
- const scheduleRecapture = () => {
4283
- if (recapture !== void 0) {
4284
- view?.clearTimeout(recapture);
4613
+ this.frame = this.view.requestAnimationFrame(this.draw);
4614
+ }
4615
+ scheduleRecapture = () => {
4616
+ if (this.recapture !== void 0) {
4617
+ this.view?.clearTimeout(this.recapture);
4285
4618
  }
4286
- recapture = view?.setTimeout(() => {
4287
- recapture = void 0;
4288
- captureBackdrops(backdropGeneration);
4619
+ this.recapture = this.view?.setTimeout(() => {
4620
+ this.recapture = void 0;
4621
+ this.captureBackdrops(this.backdropGeneration);
4289
4622
  }, RECAPTURE_DELAY_MS);
4290
4623
  };
4291
- const unwatch = watchSvgChanges(svg, view, scheduleRecapture);
4292
- const track = (event) => {
4293
- for (const surface of surfaces) {
4294
- const box = surface.canvas.getBoundingClientRect();
4295
- const inside = box.width > 0 && box.height > 0 && event.clientX >= box.left && event.clientX <= box.right && event.clientY >= box.top && event.clientY <= box.bottom;
4296
- surface.hovering = inside;
4297
- if (inside) {
4298
- surface.pointer = { x: (event.clientX - box.left) / box.width, y: 1 - (event.clientY - box.top) / box.height };
4299
- const now = clock.now();
4300
- const last = surface.trail[surface.trail.length - 1];
4301
- if (!last || now - last.at >= TRAIL_SPACING) {
4302
- surface.trail.push({ ...surface.pointer, at: now });
4303
- if (surface.trail.length > TRAIL_LENGTH2) {
4304
- surface.trail.shift();
4305
- }
4306
- }
4307
- }
4624
+ track = (event) => {
4625
+ const now = this.clock.now();
4626
+ for (const surface of this.surfaces) {
4627
+ followPointer(surface, event, now);
4308
4628
  }
4309
4629
  };
4310
- const leave = () => {
4311
- for (const surface of surfaces) {
4630
+ leave = () => {
4631
+ for (const surface of this.surfaces) {
4312
4632
  surface.hovering = false;
4313
4633
  }
4314
4634
  };
4315
- svg.addEventListener("pointermove", track);
4316
- svg.addEventListener("pointerleave", leave);
4317
- refresh();
4318
- const destroy = () => {
4319
- backdropGeneration += 1;
4320
- unwatch();
4321
- svg.removeEventListener("pointermove", track);
4322
- svg.removeEventListener("pointerleave", leave);
4323
- if (recapture !== void 0) {
4324
- view?.clearTimeout(recapture);
4325
- }
4326
- stop();
4327
- };
4328
- return {
4329
- capture: () => capturePngs(svg, surfaces, clock.now()),
4330
- setParameters: (ownerId, parameters3) => updateParameters(surfaces, ownerId, parameters3, clock.now()),
4331
- setPaused: clock.setPaused,
4332
- refresh,
4333
- destroy
4334
- };
4635
+ };
4636
+ function mountShaderSurfaces(svg) {
4637
+ return new ShaderSurfaces(svg);
4335
4638
  }
4336
4639
 
4337
4640
  // src/runtime/viewer/source.ts
4338
4641
  function renderViewerSource(next, defaultRenderOptions) {
4339
- const svg = next.svg ?? (next.source != null ? chunkEURX7QT3_cjs.render(next.source, { ...next.renderOptions ?? defaultRenderOptions, linkHitAreas: true }).svg : null);
4642
+ const svg = next.svg ?? (next.source != null ? chunk5G3BEXQU_cjs.render(next.source, { ...next.renderOptions ?? defaultRenderOptions, linkHitAreas: true }).svg : null);
4340
4643
  if (svg == null) {
4341
4644
  throw new Error("createViewer: provide either `source` (SFL) or `svg`.");
4342
4645
  }
4343
4646
  return svg;
4344
4647
  }
4345
4648
  function assertCreateViewerContract(svg) {
4346
- const version = chunkMR32IJQO_cjs.parseContractVersion(svg);
4347
- if (!chunkMR32IJQO_cjs.isContractCompatible(version)) {
4649
+ const version = chunkWZA3DJJH_cjs.parseContractVersion(svg);
4650
+ if (!chunkWZA3DJJH_cjs.isContractCompatible(version)) {
4348
4651
  throw new Error(`createViewer: incompatible DOM contract (svg=${version}). Renderer and viewer versions differ.`);
4349
4652
  }
4350
4653
  }
4351
4654
  function assertViewerUpdateContract(svg) {
4352
- const version = chunkMR32IJQO_cjs.parseContractVersion(svg);
4353
- if (!chunkMR32IJQO_cjs.isContractCompatible(version)) {
4655
+ const version = chunkWZA3DJJH_cjs.parseContractVersion(svg);
4656
+ if (!chunkWZA3DJJH_cjs.isContractCompatible(version)) {
4354
4657
  throw new Error(`viewer.update: incompatible DOM contract (svg=${version}). Renderer and viewer versions differ.`);
4355
4658
  }
4356
4659
  }
@@ -4584,7 +4887,7 @@ function trackScales(wiring, event) {
4584
4887
  }
4585
4888
  function driveValue(wiring, id, event) {
4586
4889
  const { runtime, svg } = wiring;
4587
- const kind = chunkC25NWWIH_cjs.getComponentDescriptor(runtime.graph.elements.get(id)?.componentType)?.interaction;
4890
+ const kind = chunkUHKFJBY5_cjs.getComponentDescriptor(runtime.graph.elements.get(id)?.componentType)?.interaction;
4588
4891
  if (kind !== "slide" && kind !== "pick" && kind !== "turn" && kind !== "range") {
4589
4892
  return;
4590
4893
  }
@@ -4723,5 +5026,5 @@ exports.connectInteraction = connectInteraction;
4723
5026
  exports.createViewer = createViewer;
4724
5027
  exports.registerShaderProgram = registerShaderProgram;
4725
5028
  exports.shaderProgram = shaderProgram;
4726
- //# sourceMappingURL=chunk-3EOG34QN.cjs.map
4727
- //# sourceMappingURL=chunk-3EOG34QN.cjs.map
5029
+ //# sourceMappingURL=chunk-F24JURN2.cjs.map
5030
+ //# sourceMappingURL=chunk-F24JURN2.cjs.map