stickyflow 0.5.0 → 0.7.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 (62) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/binding/index.cjs +9 -9
  3. package/dist/binding/index.d.cts +4 -4
  4. package/dist/binding/index.d.ts +4 -4
  5. package/dist/binding/index.js +3 -3
  6. package/dist/{chunk-ZMLQIMJK.cjs → chunk-A73UJ5AQ.cjs} +1537 -738
  7. package/dist/chunk-A73UJ5AQ.cjs.map +1 -0
  8. package/dist/{chunk-VK3T6O5Z.cjs → chunk-BUOWM3LC.cjs} +745 -62
  9. package/dist/chunk-BUOWM3LC.cjs.map +1 -0
  10. package/dist/{chunk-L3VJXZFD.cjs → chunk-EKAWJFJQ.cjs} +15 -15
  11. package/dist/{chunk-L3VJXZFD.cjs.map → chunk-EKAWJFJQ.cjs.map} +1 -1
  12. package/dist/{chunk-BODZN3ZI.js → chunk-JCRPLPKV.js} +156 -23
  13. package/dist/chunk-JCRPLPKV.js.map +1 -0
  14. package/dist/{chunk-IEHE6WVN.js → chunk-JQK4IGXJ.js} +489 -51
  15. package/dist/chunk-JQK4IGXJ.js.map +1 -0
  16. package/dist/{chunk-XY2GZUHC.cjs → chunk-KXYSO6GC.cjs} +498 -50
  17. package/dist/chunk-KXYSO6GC.cjs.map +1 -0
  18. package/dist/{chunk-G7NRK5AG.js → chunk-MUKIGLR5.js} +717 -34
  19. package/dist/chunk-MUKIGLR5.js.map +1 -0
  20. package/dist/{chunk-TWDLOXRM.cjs → chunk-OWNVXKXN.cjs} +170 -37
  21. package/dist/chunk-OWNVXKXN.cjs.map +1 -0
  22. package/dist/{chunk-LTGF5OHP.js → chunk-SDMQRSRW.js} +941 -143
  23. package/dist/chunk-SDMQRSRW.js.map +1 -0
  24. package/dist/{chunk-7VW2XKVB.js → chunk-ZNHYW47T.js} +3 -3
  25. package/dist/{chunk-7VW2XKVB.js.map → chunk-ZNHYW47T.js.map} +1 -1
  26. package/dist/index.cjs +57 -29
  27. package/dist/index.d.cts +80 -7
  28. package/dist/index.d.ts +80 -7
  29. package/dist/index.js +5 -5
  30. package/dist/interaction/index.cjs +245 -235
  31. package/dist/interaction/index.cjs.map +1 -1
  32. package/dist/interaction/index.d.cts +3 -2
  33. package/dist/interaction/index.d.ts +3 -2
  34. package/dist/interaction/index.js +17 -7
  35. package/dist/interaction/index.js.map +1 -1
  36. package/dist/{render-CgX_y15a.d.ts → render-BU2uYzjG.d.cts} +40 -16
  37. package/dist/{render-CgX_y15a.d.cts → render-BU2uYzjG.d.ts} +40 -16
  38. package/dist/{runtime-reWgr7MP.d.cts → runtime-B7KiTmn8.d.cts} +2 -2
  39. package/dist/{runtime-DnUxca3Y.d.ts → runtime-BPzyD-Nd.d.ts} +2 -2
  40. package/dist/{runtimeTypes-D60w6nyF.d.cts → runtimeTypes-BIP70z72.d.cts} +3 -2
  41. package/dist/{runtimeTypes-CEBGueYM.d.ts → runtimeTypes-DalvhScn.d.ts} +3 -2
  42. package/dist/stickyflow-diagram.global.js +387 -36
  43. package/dist/stickyflow-diagram.global.js.map +1 -1
  44. package/dist/{types-DYLC_lsk.d.ts → types-DMWs27Hn.d.ts} +1 -1
  45. package/dist/{types-DvhMpqrL.d.cts → types-D_2NZ6lL.d.cts} +1 -1
  46. package/dist/viewer/index.cjs +9 -9
  47. package/dist/viewer/index.d.cts +5 -4
  48. package/dist/viewer/index.d.ts +5 -4
  49. package/dist/viewer/index.js +4 -4
  50. package/dist/web-component/index.cjs +6 -6
  51. package/dist/web-component/index.d.cts +2 -2
  52. package/dist/web-component/index.d.ts +2 -2
  53. package/dist/web-component/index.js +4 -4
  54. package/package.json +1 -1
  55. package/dist/chunk-BODZN3ZI.js.map +0 -1
  56. package/dist/chunk-G7NRK5AG.js.map +0 -1
  57. package/dist/chunk-IEHE6WVN.js.map +0 -1
  58. package/dist/chunk-LTGF5OHP.js.map +0 -1
  59. package/dist/chunk-TWDLOXRM.cjs.map +0 -1
  60. package/dist/chunk-VK3T6O5Z.cjs.map +0 -1
  61. package/dist/chunk-XY2GZUHC.cjs.map +0 -1
  62. package/dist/chunk-ZMLQIMJK.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkZMLQIMJK_cjs = require('./chunk-ZMLQIMJK.cjs');
4
- var chunkL3VJXZFD_cjs = require('./chunk-L3VJXZFD.cjs');
5
- var chunkXY2GZUHC_cjs = require('./chunk-XY2GZUHC.cjs');
3
+ var chunkA73UJ5AQ_cjs = require('./chunk-A73UJ5AQ.cjs');
4
+ var chunkEKAWJFJQ_cjs = require('./chunk-EKAWJFJQ.cjs');
5
+ var chunkKXYSO6GC_cjs = require('./chunk-KXYSO6GC.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 chunkXY2GZUHC_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
165
+ return chunkKXYSO6GC_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
166
166
  }
167
167
  try {
168
- return { ...chunkXY2GZUHC_cjs.DEFAULT_ROLLING_NUMBER_STYLE, ...JSON.parse(encoded) };
168
+ return { ...chunkKXYSO6GC_cjs.DEFAULT_ROLLING_NUMBER_STYLE, ...JSON.parse(encoded) };
169
169
  } catch {
170
- return chunkXY2GZUHC_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
170
+ return chunkKXYSO6GC_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 = chunkXY2GZUHC_cjs.formatRollingNumber(value, positiveInteger(surface.getAttribute("data-sf-widget-digits")));
194
+ const nextValue = chunkKXYSO6GC_cjs.formatRollingNumber(value, positiveInteger(surface.getAttribute("data-sf-widget-digits")));
195
195
  if (previousValue === nextValue) {
196
196
  return true;
197
197
  }
@@ -667,7 +667,7 @@ function mountDisplay(container, svgString) {
667
667
  }
668
668
 
669
669
  // src/runtime/viewer/events.ts
670
- var Emitter2 = class extends chunkL3VJXZFD_cjs.Emitter {
670
+ var Emitter2 = class extends chunkEKAWJFJQ_cjs.Emitter {
671
671
  };
672
672
 
673
673
  // src/runtime/viewer/export/raster.ts
@@ -757,11 +757,11 @@ function svgElement(document, name, attributes) {
757
757
  function readComponentStyle(surface) {
758
758
  try {
759
759
  return {
760
- ...chunkXY2GZUHC_cjs.DEFAULT_ROLLING_NUMBER_STYLE,
760
+ ...chunkKXYSO6GC_cjs.DEFAULT_ROLLING_NUMBER_STYLE,
761
761
  ...JSON.parse(surface.getAttribute("data-sf-widget-style") ?? "{}")
762
762
  };
763
763
  } catch {
764
- return chunkXY2GZUHC_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
764
+ return chunkKXYSO6GC_cjs.DEFAULT_ROLLING_NUMBER_STYLE;
765
765
  }
766
766
  }
767
767
  function cellsOf(box, plain, fontSize = 0) {
@@ -901,7 +901,7 @@ function serializeSvgSnapshot(svg, captures) {
901
901
  // src/runtime/viewer/interaction/changeFlash.ts
902
902
  function createChangeFlash(svg) {
903
903
  const timers = /* @__PURE__ */ new Map();
904
- const flash = (ownerIds, color2 = chunkL3VJXZFD_cjs.CHANGE_COLOR) => {
904
+ const flash = (ownerIds, color2 = chunkEKAWJFJQ_cjs.CHANGE_COLOR) => {
905
905
  const ids = [...new Set(ownerIds)];
906
906
  if (ids.length === 0) {
907
907
  return;
@@ -909,7 +909,7 @@ function createChangeFlash(svg) {
909
909
  const doc = svg.ownerDocument;
910
910
  const reducedMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
911
911
  for (const id of ids) {
912
- const primary = chunkL3VJXZFD_cjs.findOwnerNode(svg, id, chunkL3VJXZFD_cjs.isPrimary);
912
+ const primary = chunkEKAWJFJQ_cjs.findOwnerNode(svg, id, chunkEKAWJFJQ_cjs.isPrimary);
913
913
  if (!primary) {
914
914
  continue;
915
915
  }
@@ -920,10 +920,10 @@ function createChangeFlash(svg) {
920
920
  for (const stale of svg.querySelectorAll(`[data-sf-change-overlay="${CSS.escape(id)}"]`)) {
921
921
  stale.remove();
922
922
  }
923
- const overlay = primary.getAttribute("data-sf-role") === "link" ? chunkL3VJXZFD_cjs.linkChangeOverlay(doc, primary, id, color2) : chunkL3VJXZFD_cjs.shapeChangeOverlay(doc, primary, id, color2);
923
+ const overlay = primary.getAttribute("data-sf-role") === "link" ? chunkEKAWJFJQ_cjs.linkChangeOverlay(doc, primary, id, color2) : chunkEKAWJFJQ_cjs.shapeChangeOverlay(doc, primary, id, color2);
924
924
  svg.appendChild(overlay);
925
- chunkL3VJXZFD_cjs.startChangeFade(overlay, reducedMotion);
926
- const duration = reducedMotion ? chunkL3VJXZFD_cjs.REDUCED_MOTION_DURATION_MS : chunkL3VJXZFD_cjs.FLASH_DURATION_MS;
925
+ chunkEKAWJFJQ_cjs.startChangeFade(overlay, reducedMotion);
926
+ const duration = reducedMotion ? chunkEKAWJFJQ_cjs.REDUCED_MOTION_DURATION_MS : chunkEKAWJFJQ_cjs.FLASH_DURATION_MS;
927
927
  timers.set(
928
928
  id,
929
929
  setTimeout(() => {
@@ -1010,7 +1010,7 @@ var OwnerPointerController = class {
1010
1010
  this.#selection = selection;
1011
1011
  }
1012
1012
  hover(event) {
1013
- const owner = chunkL3VJXZFD_cjs.resolveOwner(event.target);
1013
+ const owner = chunkEKAWJFJQ_cjs.resolveOwner(event.target);
1014
1014
  this.#emitter.emit(
1015
1015
  "ownerHover",
1016
1016
  owner ? { diagramId: this.#diagramId, owner, modifiers: modifiersOf(event) } : { diagramId: this.#diagramId, owner: null }
@@ -1018,7 +1018,7 @@ var OwnerPointerController = class {
1018
1018
  }
1019
1019
  select(event) {
1020
1020
  const target = event.target;
1021
- const owner = chunkL3VJXZFD_cjs.resolveOwner(target);
1021
+ const owner = chunkEKAWJFJQ_cjs.resolveOwner(target);
1022
1022
  if (!owner) {
1023
1023
  this.#clearWhenOutsideOverlay(target);
1024
1024
  return;
@@ -1039,7 +1039,7 @@ var OwnerPointerController = class {
1039
1039
  owner,
1040
1040
  modifiers
1041
1041
  });
1042
- const node = chunkL3VJXZFD_cjs.findOwnerNode(this.#svg, owner.id, chunkL3VJXZFD_cjs.isPrimary);
1042
+ const node = chunkEKAWJFJQ_cjs.findOwnerNode(this.#svg, owner.id, chunkEKAWJFJQ_cjs.isPrimary);
1043
1043
  if (node && !node.hasAttribute("tabindex")) {
1044
1044
  node.setAttribute("tabindex", "-1");
1045
1045
  }
@@ -1067,12 +1067,12 @@ var PointerInteractionSession = class {
1067
1067
  }
1068
1068
  #onPointerDown = (event) => {
1069
1069
  const target = event.target;
1070
- const overContent = Boolean(chunkL3VJXZFD_cjs.resolveOwner(target)) || isSelectionOverlayControl(target);
1070
+ const overContent = Boolean(chunkEKAWJFJQ_cjs.resolveOwner(target)) || isSelectionOverlayControl(target);
1071
1071
  this.#down = {
1072
1072
  x: event.clientX,
1073
1073
  y: event.clientY,
1074
1074
  moved: false,
1075
- panable: chunkL3VJXZFD_cjs.isCameraGesture(event) || !overContent
1075
+ panable: chunkEKAWJFJQ_cjs.isCameraGesture(event) || !overContent
1076
1076
  };
1077
1077
  };
1078
1078
  #onPointerMove = (event) => {
@@ -1100,7 +1100,7 @@ var PointerInteractionSession = class {
1100
1100
  if (!this.#down.moved) {
1101
1101
  return false;
1102
1102
  }
1103
- if (this.#down.panable && chunkL3VJXZFD_cjs.isCameraGesture(event)) {
1103
+ if (this.#down.panable && chunkEKAWJFJQ_cjs.isCameraGesture(event)) {
1104
1104
  this.#display.panBy(event.movementX, event.movementY);
1105
1105
  }
1106
1106
  return true;
@@ -1124,15 +1124,15 @@ function paintSelectionOverlays(svg, selectedIds, owners) {
1124
1124
  }
1125
1125
  const document = svg.ownerDocument;
1126
1126
  for (const id of selectedIds) {
1127
- const primary = chunkL3VJXZFD_cjs.findOwnerNode(svg, id, chunkL3VJXZFD_cjs.isPrimary);
1127
+ const primary = chunkEKAWJFJQ_cjs.findOwnerNode(svg, id, chunkEKAWJFJQ_cjs.isPrimary);
1128
1128
  if (!primary) {
1129
1129
  continue;
1130
1130
  }
1131
1131
  const owner = owners.get(id);
1132
- const overlay = owner?.role === "link" ? chunkL3VJXZFD_cjs.linkSelectionOverlay(document, primary, id, svg) : owner?.role === "path" ? chunkL3VJXZFD_cjs.pathSelectionOverlay(document, primary, id, svg) : owner?.role === "isometric" ? chunkL3VJXZFD_cjs.isometricSelectionOverlay(document, primary, id, svg) : chunkL3VJXZFD_cjs.shapeSelectionOverlay(document, primary, id, svg, owner ? chunkL3VJXZFD_cjs.DERIVED_HEIGHT_ROLES.has(owner.role) : false);
1132
+ const overlay = owner?.role === "link" ? chunkEKAWJFJQ_cjs.linkSelectionOverlay(document, primary, id, svg) : owner?.role === "path" ? chunkEKAWJFJQ_cjs.pathSelectionOverlay(document, primary, id, svg) : owner?.role === "isometric" ? chunkEKAWJFJQ_cjs.isometricSelectionOverlay(document, primary, id, svg) : chunkEKAWJFJQ_cjs.shapeSelectionOverlay(document, primary, id, svg, owner ? chunkEKAWJFJQ_cjs.DERIVED_HEIGHT_ROLES.has(owner.role) : false);
1133
1133
  svg.appendChild(overlay);
1134
1134
  if (owner?.role === "shape" && selectedIds.size === 1) {
1135
- svg.appendChild(chunkL3VJXZFD_cjs.quickDuplicateBubbles(document, primary, id, svg));
1135
+ svg.appendChild(chunkEKAWJFJQ_cjs.quickDuplicateBubbles(document, primary, id, svg));
1136
1136
  }
1137
1137
  }
1138
1138
  }
@@ -1171,7 +1171,7 @@ var SelectionController = class {
1171
1171
  selectIds(ids) {
1172
1172
  for (const id of ids) {
1173
1173
  const element = this.#svg.querySelector(`[data-sf-id="${CSS.escape(id)}"]`);
1174
- const owner = chunkL3VJXZFD_cjs.resolveOwner(element);
1174
+ const owner = chunkEKAWJFJQ_cjs.resolveOwner(element);
1175
1175
  if (owner) {
1176
1176
  this.remember(owner);
1177
1177
  }
@@ -1183,7 +1183,7 @@ var SelectionController = class {
1183
1183
  // src/runtime/viewer/interaction/wheel.ts
1184
1184
  function bindWheelZoom(display, selection) {
1185
1185
  const onWheel = (event) => {
1186
- if (!chunkL3VJXZFD_cjs.isCameraGesture(event)) {
1186
+ if (!chunkEKAWJFJQ_cjs.isCameraGesture(event)) {
1187
1187
  return;
1188
1188
  }
1189
1189
  event.preventDefault();
@@ -1929,10 +1929,234 @@ var haloProgram = {
1929
1929
  fragmentSource: fragmentSource9
1930
1930
  };
1931
1931
 
1932
- // src/runtime/viewer/shaders/builtins/lumenPortal.ts
1932
+ // src/runtime/viewer/shaders/builtins/ledMatrix.ts
1933
1933
  var fragmentSource10 = `
1934
1934
  precision highp float;
1935
1935
 
1936
+ uniform vec2 uResolution;
1937
+ uniform float uTime;
1938
+ uniform float uSpeed;
1939
+ uniform float uIntensity;
1940
+ uniform float uColumns;
1941
+ uniform float uCellAspect;
1942
+ uniform float uGap;
1943
+ uniform float uGlow;
1944
+ uniform float uDepth;
1945
+ uniform float uGrain;
1946
+ uniform float uRotation;
1947
+ uniform float uRipple;
1948
+ uniform float uWave;
1949
+ uniform float uVariation;
1950
+ uniform float uFade;
1951
+ uniform float uOriginX;
1952
+ uniform float uOriginY;
1953
+ uniform float uSpread;
1954
+ uniform float uDrift;
1955
+ uniform float uReaction;
1956
+ uniform float uPointerSize;
1957
+ uniform float uHover;
1958
+ uniform vec2 uPointer;
1959
+ uniform vec3 uWake[16];
1960
+ uniform float uCornerRadius;
1961
+ uniform vec3 uBaseColor;
1962
+ uniform vec3 uOffColor;
1963
+ uniform vec3 uColor;
1964
+ uniform vec3 uHotColor;
1965
+ varying vec2 vUv;
1966
+
1967
+ float boxMask(vec2 uv) {
1968
+ vec2 halfBox = uResolution * 0.5;
1969
+ float radius = uCornerRadius * min(uResolution.x, uResolution.y);
1970
+ vec2 q = abs(uv * uResolution - halfBox) - halfBox + radius;
1971
+ float d = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
1972
+ return 1.0 - smoothstep(-1.0, 1.0, d);
1973
+ }
1974
+
1975
+ float roundedBox(vec2 point, vec2 halfSize, float radius) {
1976
+ vec2 q = abs(point) - halfSize + radius;
1977
+ return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
1978
+ }
1979
+
1980
+ float hash(vec2 p) {
1981
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
1982
+ }
1983
+
1984
+ void main() {
1985
+ float shape = boxMask(vUv);
1986
+ if (shape <= 0.0) discard;
1987
+
1988
+ float time = uTime * max(uSpeed, 0.0);
1989
+ float columns = max(uColumns, 2.0);
1990
+ vec2 cellPx = vec2(uResolution.x / columns);
1991
+ cellPx.y *= max(uCellAspect, 0.2);
1992
+ vec2 rows = uResolution / cellPx;
1993
+
1994
+ // The grid can be turned around the middle of the surface.
1995
+ float angle = radians(uRotation);
1996
+ vec2 centered = (vUv - 0.5) * uResolution;
1997
+ vec2 turned = vec2(cos(angle) * centered.x - sin(angle) * centered.y, sin(angle) * centered.x + cos(angle) * centered.y);
1998
+ vec2 turnedUv = turned / uResolution + 0.5;
1999
+ vec2 grid = vec2(turnedUv.x, 1.0 - turnedUv.y) * rows;
2000
+ vec2 cell = floor(grid);
2001
+ vec2 local = (fract(grid) - 0.5) * cellPx;
2002
+ vec2 center = (cell + 0.5) / rows;
2003
+
2004
+ // The light of the surface sits at its origin, sways to the sides, and falls off with the spread. A spread of 0 puts it out.
2005
+ float spread = max(uSpread, 0.05);
2006
+ float lit = smoothstep(0.0, 0.05, uSpread);
2007
+ vec2 p = vec2(center.x, 1.0 - center.y);
2008
+ vec2 origin = vec2(uOriginX + uDrift * sin(time * 0.7), uOriginY);
2009
+ float aspect = uResolution.x / uResolution.y;
2010
+ float blob = exp(-pow(length((p - origin) * vec2(1.0, 1.55)) / spread, 2.0) * 5.5) * lit;
2011
+ float wave = 0.5 + 0.5 * sin(p.x * 5.0 + time * 1.3 + sin(p.y * 3.0 - time));
2012
+ float rise = pow(max(1.0 - abs(p.y - uOriginY) / spread, 0.0), 3.0) * (1.0 - 0.7 * uWave + 0.7 * uWave * wave) * lit;
2013
+ float glowLevel = blob * 1.15 + rise * 0.5 + 0.03;
2014
+
2015
+ // Rings that run outward from the light, and a different brightness for every light.
2016
+ float rings = 1.0 + uRipple * 0.5 * sin(length((p - origin) * vec2(1.0, 1.55)) * 16.0 - time * 2.5);
2017
+ float jitter = 1.0 - uVariation * 0.55 * hash(cell);
2018
+ float vignette = 1.0 - clamp(uFade, 0.0, 1.0) * smoothstep(0.3, 0.8, length(p - 0.5) * 1.3);
2019
+
2020
+ // The lights near the pointer glow up while it is over the surface, and the places it has been dim down one after the other.
2021
+ float near = exp(-pow(length((p - uPointer) * vec2(aspect, 1.0)) / max(uPointerSize, 0.01), 2.0)) * uHover;
2022
+ float wake = 0.0;
2023
+ for (int i = 0; i < 16; i++) {
2024
+ wake += uWake[i].z * exp(-pow(length((p - uWake[i].xy) * vec2(aspect, 1.0)) / max(uPointerSize * 0.88, 0.01), 2.0));
2025
+ }
2026
+ float touch = min(near + wake, 1.3) * max(uReaction, 0.0);
2027
+ float level = clamp(glowLevel * rings * jitter * vignette * max(uIntensity, 0.0) + touch * 1.1, 0.0, 1.0);
2028
+
2029
+ vec3 tint = mix(uOffColor, uColor, smoothstep(0.0, 0.6, level));
2030
+ tint = mix(tint, uHotColor, smoothstep(0.55, 1.0, level));
2031
+
2032
+ vec2 halfSize = cellPx * 0.5 * (1.0 - clamp(uGap, 0.0, 0.8));
2033
+ float d = roundedBox(local, halfSize, min(halfSize.x, halfSize.y));
2034
+ float body = 1.0 - smoothstep(-0.9, 0.9, d);
2035
+ // Depth shades a light like a small bulb: bright in the upper part, darker at the rim.
2036
+ float sheen = 1.0 - smoothstep(0.0, halfSize.y * 1.2, abs(local.y + halfSize.y * 0.35));
2037
+ float rim = smoothstep(-halfSize.x * 0.7, 0.0, d);
2038
+ float depth = clamp(uDepth, 0.0, 1.0);
2039
+ vec3 cellColor = tint * (1.0 - 0.4 * depth + 0.4 * depth * sheen) * (1.0 - 0.35 * depth * rim);
2040
+
2041
+ vec3 color = uBaseColor + tint * level * max(uGlow, 0.0) * 0.18;
2042
+ color = mix(color, cellColor, body);
2043
+ color += (hash(gl_FragCoord.xy) - 0.5) * max(uGrain, 0.0) * 0.2;
2044
+ gl_FragColor = vec4(clamp(color, 0.0, 1.0), shape);
2045
+ }
2046
+ `;
2047
+ var ledMatrixProgram = {
2048
+ name: "ledMatrix",
2049
+ fragmentSource: fragmentSource10,
2050
+ defaultParameters: {
2051
+ speed: 0.25,
2052
+ intensity: 1,
2053
+ columns: 44,
2054
+ cellAspect: 1.7,
2055
+ gap: 0.3,
2056
+ originX: 0.42,
2057
+ originY: 0.04,
2058
+ spread: 1,
2059
+ drift: 0.2,
2060
+ depth: 0.5,
2061
+ glow: 1,
2062
+ grain: 0.2,
2063
+ rotation: 0,
2064
+ ripple: 0.3,
2065
+ wave: 1,
2066
+ variation: 0.2,
2067
+ fade: 0.3,
2068
+ reaction: 1,
2069
+ pointerSize: 0.17,
2070
+ trail: 1.4,
2071
+ cornerRadius: 0.025,
2072
+ baseColor: "#050505",
2073
+ offColor: "#262626",
2074
+ color: "#a3a3a3",
2075
+ hotColor: "#ffffff"
2076
+ }
2077
+ };
2078
+
2079
+ // src/runtime/viewer/shaders/builtins/lightBand.ts
2080
+ var fragmentSource11 = `
2081
+ precision highp float;
2082
+
2083
+ uniform vec2 uResolution;
2084
+ uniform float uTime;
2085
+ uniform float uSpeed;
2086
+ uniform float uIntensity;
2087
+ uniform float uThickness;
2088
+ uniform float uBloom;
2089
+ uniform float uWave;
2090
+ uniform float uGrain;
2091
+ uniform float uCornerRadius;
2092
+ uniform vec3 uBaseColor;
2093
+ uniform vec3 uColorA;
2094
+ uniform vec3 uColorB;
2095
+ uniform vec3 uColorC;
2096
+ varying vec2 vUv;
2097
+
2098
+ float boxMask(vec2 uv) {
2099
+ vec2 halfBox = uResolution * 0.5;
2100
+ float radius = uCornerRadius * min(uResolution.x, uResolution.y);
2101
+ vec2 q = abs(uv * uResolution - halfBox) - halfBox + radius;
2102
+ float d = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
2103
+ return 1.0 - smoothstep(-1.0, 1.0, d);
2104
+ }
2105
+
2106
+ float hash(vec2 p) {
2107
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
2108
+ }
2109
+
2110
+ void main() {
2111
+ float shape = boxMask(vUv);
2112
+ if (shape <= 0.0) discard;
2113
+
2114
+ float t = uTime * max(uSpeed, 0.0);
2115
+ float aspect = uResolution.x / uResolution.y;
2116
+ vec2 p = vec2(vUv.x, 1.0 - vUv.y);
2117
+
2118
+ // The middle of the band wanders across the surface, and its width breathes along the way.
2119
+ float middle = 0.5 + uWave * (0.11 * sin(p.x * 3.4 + t) + 0.05 * sin(p.x * 7.1 - t * 1.4));
2120
+ float width = max(uThickness, 0.002) * (0.65 + 0.35 * sin(p.x * 2.4 + t * 0.6));
2121
+ float offset = (p.y - middle) * aspect * 0.6;
2122
+ float core = exp(-pow(offset / width, 2.0));
2123
+ float halo = exp(-pow(offset / (width * (2.5 + uBloom * 5.0)), 2.0));
2124
+
2125
+ // Blue at one end, pink at the other, and the colors drift a little.
2126
+ float along = clamp(p.x + 0.12 * sin(t * 0.8), 0.0, 1.0);
2127
+ vec3 tint = along < 0.5 ? mix(uColorA, uColorB, along * 2.0) : mix(uColorB, uColorC, along * 2.0 - 1.0);
2128
+ float pulse = 0.6 + 0.4 * sin(p.x * 6.0 - t * 2.0);
2129
+
2130
+ vec3 color = uBaseColor;
2131
+ color += tint * halo * 0.55 * pulse * max(uBloom, 0.0);
2132
+ color += mix(tint, vec3(1.0), 0.55) * core * (0.55 + 0.45 * pulse);
2133
+ color *= max(uIntensity, 0.0);
2134
+ color += (hash(gl_FragCoord.xy + t) - 0.5) * max(uGrain, 0.0);
2135
+ gl_FragColor = vec4(clamp(color, 0.0, 1.0), shape);
2136
+ }
2137
+ `;
2138
+ var lightBandProgram = {
2139
+ name: "lightBand",
2140
+ fragmentSource: fragmentSource11,
2141
+ defaultParameters: {
2142
+ speed: 0.3,
2143
+ intensity: 1,
2144
+ thickness: 0.035,
2145
+ bloom: 1,
2146
+ wave: 1,
2147
+ grain: 0.02,
2148
+ cornerRadius: 0.02,
2149
+ baseColor: "#0f0e14",
2150
+ colorA: "#7ea8ff",
2151
+ colorB: "#c13fd6",
2152
+ colorC: "#ff6fb8"
2153
+ }
2154
+ };
2155
+
2156
+ // src/runtime/viewer/shaders/builtins/lumenPortal.ts
2157
+ var fragmentSource12 = `
2158
+ precision highp float;
2159
+
1936
2160
  uniform float uTime;
1937
2161
  uniform float uSpeed;
1938
2162
  uniform float uIntensity;
@@ -1988,11 +2212,11 @@ void main() {
1988
2212
  `;
1989
2213
  var lumenPortalProgram = {
1990
2214
  name: "lumenPortal",
1991
- fragmentSource: fragmentSource10
2215
+ fragmentSource: fragmentSource12
1992
2216
  };
1993
2217
 
1994
2218
  // src/runtime/viewer/shaders/builtins/lumenPortalLight.ts
1995
- var fragmentSource11 = `
2219
+ var fragmentSource13 = `
1996
2220
  precision highp float;
1997
2221
 
1998
2222
  uniform float uTime;
@@ -2051,11 +2275,11 @@ void main() {
2051
2275
  `;
2052
2276
  var lumenPortalLightProgram = {
2053
2277
  name: "lumenPortalLight",
2054
- fragmentSource: fragmentSource11
2278
+ fragmentSource: fragmentSource13
2055
2279
  };
2056
2280
 
2057
2281
  // src/runtime/viewer/shaders/builtins/orb.ts
2058
- var fragmentSource12 = `
2282
+ var fragmentSource14 = `
2059
2283
  precision highp float;
2060
2284
 
2061
2285
  uniform vec2 uResolution;
@@ -2091,11 +2315,11 @@ void main() {
2091
2315
  `;
2092
2316
  var orbProgram = {
2093
2317
  name: "orb",
2094
- fragmentSource: fragmentSource12
2318
+ fragmentSource: fragmentSource14
2095
2319
  };
2096
2320
 
2097
2321
  // src/runtime/viewer/shaders/builtins/pixelConstellation.ts
2098
- var fragmentSource13 = `
2322
+ var fragmentSource15 = `
2099
2323
  precision highp float;
2100
2324
 
2101
2325
  uniform float uTime;
@@ -2195,11 +2419,11 @@ void main() {
2195
2419
  `;
2196
2420
  var pixelConstellationProgram = {
2197
2421
  name: "pixelConstellation",
2198
- fragmentSource: fragmentSource13
2422
+ fragmentSource: fragmentSource15
2199
2423
  };
2200
2424
 
2201
2425
  // src/runtime/viewer/shaders/builtins/plasmaGauge.ts
2202
- var fragmentSource14 = `
2426
+ var fragmentSource16 = `
2203
2427
  precision highp float;
2204
2428
 
2205
2429
  uniform vec2 uResolution;
@@ -2301,12 +2525,12 @@ void main() {
2301
2525
  `;
2302
2526
  var plasmaGaugeProgram = {
2303
2527
  name: "plasmaGauge",
2304
- fragmentSource: fragmentSource14,
2528
+ fragmentSource: fragmentSource16,
2305
2529
  replacesBaseFill: true
2306
2530
  };
2307
2531
 
2308
2532
  // src/runtime/viewer/shaders/builtins/prismSlats.ts
2309
- var fragmentSource15 = `
2533
+ var fragmentSource17 = `
2310
2534
  precision highp float;
2311
2535
 
2312
2536
  uniform vec2 uResolution;
@@ -2381,11 +2605,136 @@ void main() {
2381
2605
  `;
2382
2606
  var prismSlatsProgram = {
2383
2607
  name: "prismSlats",
2384
- fragmentSource: fragmentSource15
2608
+ fragmentSource: fragmentSource17
2609
+ };
2610
+
2611
+ // src/runtime/viewer/shaders/builtins/reactivePanel.ts
2612
+ var fragmentSource18 = `
2613
+ precision highp float;
2614
+
2615
+ uniform float uTime;
2616
+ uniform float uSpeed;
2617
+ uniform float uIntensity;
2618
+ uniform float uEmission;
2619
+ uniform float uReception;
2620
+ uniform float uEmitterFill;
2621
+ uniform float uGrain;
2622
+ uniform float uGrainScale;
2623
+ uniform float uCornerRadius;
2624
+ uniform float uBorderWidth;
2625
+ uniform float uGlowRadius;
2626
+ uniform float uSurfacePadding;
2627
+ uniform float uLightX;
2628
+ uniform float uLightY;
2629
+ uniform float uLightStrength;
2630
+ uniform float uPixelScale;
2631
+ uniform vec2 uResolution;
2632
+ uniform vec3 uShapeColor;
2633
+ uniform vec3 uBaseColor;
2634
+ uniform vec3 uEdgeColor;
2635
+ uniform vec3 uLightColor;
2636
+ varying vec2 vUv;
2637
+
2638
+ float roundedBoxDistance(vec2 point, vec2 halfSize, float radius) {
2639
+ vec2 offset = abs(point) - halfSize + radius;
2640
+ return min(max(offset.x, offset.y), 0.0) + length(max(offset, 0.0)) - radius;
2641
+ }
2642
+
2643
+ float random(vec2 point) {
2644
+ vec3 value = fract(vec3(point.xyx) * 0.1031);
2645
+ value += dot(value, value.yzx + 33.33);
2646
+ return fract((value.x + value.y) * value.z);
2647
+ }
2648
+
2649
+ void main() {
2650
+ vec2 pixel = vUv * uResolution;
2651
+ float pixelScale = max(uPixelScale, 0.0001);
2652
+ float padding = clamp(uSurfacePadding * pixelScale, 0.0, min(uResolution.x, uResolution.y) * 0.45);
2653
+ vec2 panelHalfSize = max(vec2(1.0), uResolution * 0.5 - padding);
2654
+ vec2 panelPoint = pixel - uResolution * 0.5;
2655
+ float radius = min(max(uCornerRadius * pixelScale, 0.0), min(panelHalfSize.x, panelHalfSize.y));
2656
+ float distance = roundedBoxDistance(panelPoint, panelHalfSize, radius);
2657
+ float body = 1.0 - smoothstep(-1.25, 0.75, distance);
2658
+ float borderWidth = max(uBorderWidth * pixelScale, 0.5);
2659
+ float edge = exp(-pow(distance / borderWidth, 2.0));
2660
+ float innerEdge = exp(-pow((distance + borderWidth * 2.25) / (borderWidth * 2.2), 2.0)) * body;
2661
+
2662
+ vec2 lightPosition = vec2(uLightX, 1.0 - uLightY) * uResolution;
2663
+ float lightDistance = length(pixel - lightPosition);
2664
+ float lightRadius = max(uGlowRadius * pixelScale, 1.0);
2665
+ float receivedLight = exp(-pow(lightDistance / lightRadius, 2.0));
2666
+ receivedLight *= max(uReception, 0.0) * max(uLightStrength, 0.0);
2667
+
2668
+ float speed = max(uSpeed, 0.0);
2669
+ float breath = 0.88 + 0.12 * sin(uTime * speed * 6.2831853);
2670
+ float emittedLight = max(uEmission, 0.0) * breath;
2671
+ float outsideFalloff = exp(-max(distance, 0.0) / max(lightRadius * 0.22, 1.0));
2672
+ float outsideGlow = outsideFalloff * (emittedLight * 1.35 + receivedLight * 0.9);
2673
+ float frameDistance = min(min(pixel.x, uResolution.x - pixel.x), min(pixel.y, uResolution.y - pixel.y));
2674
+ float frameFade = smoothstep(0.0, max(padding * 0.65, 1.0), frameDistance);
2675
+ outsideGlow *= frameFade;
2676
+
2677
+ vec3 baseColor = dot(uBaseColor, uBaseColor) > 0.0 ? uBaseColor : uShapeColor;
2678
+ vec3 edgeColor = dot(uEdgeColor, uEdgeColor) > 0.0 ? uEdgeColor : vec3(0.22, 0.72, 1.0);
2679
+ vec3 lightColor = dot(uLightColor, uLightColor) > 0.0 ? uLightColor : edgeColor;
2680
+ vec3 color = baseColor * (0.82 + receivedLight * 0.42);
2681
+
2682
+ // Emission lights the material itself instead of leaving a dark cutout behind.
2683
+ // A soft centre bias keeps the fill dimensional while the edge remains crisp.
2684
+ vec2 normalizedPoint = panelPoint / max(panelHalfSize, vec2(1.0));
2685
+ float centreLight = 1.0 - smoothstep(0.05, 1.25, length(normalizedPoint));
2686
+ float fillLight = clamp(emittedLight * max(uEmitterFill, 0.0), 0.0, 1.0) * body;
2687
+ vec3 illuminatedFill = mix(edgeColor, lightColor, 0.62 + centreLight * 0.28);
2688
+ color = mix(color, illuminatedFill * (0.72 + centreLight * 0.62), fillLight);
2689
+
2690
+ // Fine object-space luminance grain. It is intentionally emission-gated so
2691
+ // receiver panels stay clean and the texture stays fixed on the active tile.
2692
+ float grainScale = max(uGrainScale * pixelScale, 0.75);
2693
+ vec2 grainCell = floor(pixel / grainScale);
2694
+ float grainValue = random(grainCell);
2695
+ float grainLight = (grainValue - 0.36) * max(uGrain, 0.0) * fillLight;
2696
+ color += lightColor * grainLight * (0.5 + centreLight * 0.75);
2697
+
2698
+ color += edgeColor * edge * (0.42 + emittedLight * 1.7);
2699
+ color += lightColor * edge * receivedLight * 2.5;
2700
+ color += lightColor * innerEdge * receivedLight * 1.25;
2701
+
2702
+ float intensity = max(uIntensity, 0.0);
2703
+ float halo = outsideGlow * (1.0 - body) * 0.9 * intensity;
2704
+ float alpha = body + halo;
2705
+ if (alpha < 0.002) discard;
2706
+
2707
+ vec3 haloColor = mix(edgeColor, lightColor, clamp(receivedLight * 1.5, 0.0, 1.0));
2708
+ vec3 premultiplied = color * body * intensity + haloColor * halo;
2709
+ gl_FragColor = vec4(clamp(premultiplied, 0.0, 1.0), clamp(alpha, 0.0, 1.0));
2710
+ }
2711
+ `;
2712
+ var reactivePanelProgram = {
2713
+ name: "reactivePanel",
2714
+ fragmentSource: fragmentSource18,
2715
+ defaultParameters: {
2716
+ intensity: 0.5,
2717
+ speed: 0.18,
2718
+ emission: 0,
2719
+ reception: 0.85,
2720
+ emitterFill: 0,
2721
+ grain: 0,
2722
+ grainScale: 1.5,
2723
+ cornerRadius: 18,
2724
+ borderWidth: 2,
2725
+ glowRadius: 90,
2726
+ lightX: 0.5,
2727
+ lightY: 0.5,
2728
+ lightStrength: 0,
2729
+ baseColor: "#09101c",
2730
+ edgeColor: "#33b8ff",
2731
+ lightColor: "#59d1ff"
2732
+ },
2733
+ replacesBaseFill: true
2385
2734
  };
2386
2735
 
2387
2736
  // src/runtime/viewer/shaders/builtins/ruler.ts
2388
- var fragmentSource16 = `
2737
+ var fragmentSource19 = `
2389
2738
  precision highp float;
2390
2739
 
2391
2740
  uniform vec2 uResolution;
@@ -2490,12 +2839,120 @@ void main() {
2490
2839
  `;
2491
2840
  var rulerProgram = {
2492
2841
  name: "ruler",
2493
- fragmentSource: fragmentSource16,
2842
+ fragmentSource: fragmentSource19,
2494
2843
  replacesBaseFill: true
2495
2844
  };
2496
2845
 
2846
+ // src/runtime/viewer/shaders/builtins/silkFolds.ts
2847
+ var fragmentSource20 = `
2848
+ precision highp float;
2849
+
2850
+ uniform vec2 uResolution;
2851
+ uniform float uTime;
2852
+ uniform float uSpeed;
2853
+ uniform float uIntensity;
2854
+ uniform float uScale;
2855
+ uniform float uSharpness;
2856
+ uniform float uDepth;
2857
+ uniform float uGlow;
2858
+ uniform float uGrain;
2859
+ uniform float uRotation;
2860
+ uniform float uRipple;
2861
+ uniform float uWave;
2862
+ uniform float uVariation;
2863
+ uniform float uFade;
2864
+ uniform float uReaction;
2865
+ uniform float uHover;
2866
+ uniform vec2 uPointer;
2867
+ uniform float uCornerRadius;
2868
+ uniform vec3 uBaseColor;
2869
+ uniform vec3 uColor;
2870
+ uniform vec3 uHighlightColor;
2871
+ varying vec2 vUv;
2872
+
2873
+ float boxMask(vec2 uv) {
2874
+ vec2 halfBox = uResolution * 0.5;
2875
+ float radius = uCornerRadius * min(uResolution.x, uResolution.y);
2876
+ vec2 q = abs(uv * uResolution - halfBox) - halfBox + radius;
2877
+ float d = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
2878
+ return 1.0 - smoothstep(-1.0, 1.0, d);
2879
+ }
2880
+
2881
+ float hash(vec2 p) {
2882
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
2883
+ }
2884
+
2885
+ vec2 turn(vec2 point, float angle) {
2886
+ float c = cos(angle);
2887
+ float s = sin(angle);
2888
+ return vec2(c * point.x - s * point.y, s * point.x + c * point.y);
2889
+ }
2890
+
2891
+ void main() {
2892
+ float shape = boxMask(vUv);
2893
+ if (shape <= 0.0) discard;
2894
+
2895
+ float t = uTime * max(uSpeed, 0.0);
2896
+ float aspect = uResolution.x / uResolution.y;
2897
+ float angle = radians(uRotation);
2898
+ float zoom = max(uScale, 0.2) * 2.0;
2899
+ vec2 p = turn((vUv - 0.5) * vec2(aspect, 1.0), angle) * zoom;
2900
+
2901
+ // An irregular, slow bend of the whole cloth, so no two folds are alike.
2902
+ p += uVariation * 1.3 * vec2(sin(p.y * 0.37 + 3.1), cos(p.x * 0.41 + 1.7));
2903
+
2904
+ // Bend the plane a few times, then lay a wave over it: the crests of the wave are the folds of the cloth.
2905
+ for (int i = 0; i < 3; i++) {
2906
+ float k = float(i);
2907
+ p += 0.22 * uWave * vec2(sin(p.y * 1.7 + t * 0.6 + k * 1.3), cos(p.x * 1.5 - t * 0.5 + k * 1.9));
2908
+ }
2909
+
2910
+ // The cloth lifts where the pointer is over it.
2911
+ vec2 touch = turn((uPointer - 0.5) * vec2(aspect, 1.0), angle) * zoom;
2912
+ float lift = exp(-pow(length(p - touch) * 0.55, 2.0)) * uHover * max(uReaction, 0.0);
2913
+
2914
+ float phase = p.x * 0.8 + p.y * 2.2 + 1.2 * sin(p.y * 0.9 - t * 0.3) + 0.8 * sin(p.x * 1.3 + t * 0.2) + lift * 2.4;
2915
+ phase += uRipple * 0.35 * sin(p.x * 7.0 + p.y * 5.0 + t * 1.1);
2916
+ float wave = 0.5 + 0.5 * sin(phase);
2917
+
2918
+ float crest = pow(wave, max(uSharpness, 0.5));
2919
+ float body = pow(wave, mix(1.0, 3.2, clamp(uDepth, 0.0, 1.0)));
2920
+ float bloom = pow(wave, 1.3) * max(uGlow, 0.0);
2921
+
2922
+ vec3 color = mix(uBaseColor, uColor, body * 0.9);
2923
+ color += uHighlightColor * (crest * (0.65 + 0.35 * lift) + bloom * 0.28);
2924
+ color *= max(uIntensity, 0.0);
2925
+ color *= 1.0 - clamp(uFade, 0.0, 1.0) * smoothstep(0.3, 0.78, length(vUv - 0.5) * 1.35);
2926
+ color += (hash(gl_FragCoord.xy) - 0.5) * max(uGrain, 0.0);
2927
+ gl_FragColor = vec4(clamp(color, 0.0, 1.0), shape);
2928
+ }
2929
+ `;
2930
+ var silkFoldsProgram = {
2931
+ name: "silkFolds",
2932
+ fragmentSource: fragmentSource20,
2933
+ defaultParameters: {
2934
+ speed: 0.2,
2935
+ intensity: 1,
2936
+ scale: 2.2,
2937
+ sharpness: 5,
2938
+ depth: 0.5,
2939
+ glow: 0.3,
2940
+ grain: 0.08,
2941
+ rotation: 0,
2942
+ ripple: 0.3,
2943
+ wave: 1,
2944
+ variation: 0,
2945
+ fade: 0.3,
2946
+ reaction: 1,
2947
+ cornerRadius: 0.02,
2948
+ baseColor: "#030303",
2949
+ color: "#4d4d4d",
2950
+ highlightColor: "#ffffff"
2951
+ }
2952
+ };
2953
+
2497
2954
  // src/runtime/viewer/shaders/builtins/smearOrb.ts
2498
- var fragmentSource17 = `
2955
+ var fragmentSource21 = `
2499
2956
  precision highp float;
2500
2957
 
2501
2958
  uniform vec2 uResolution;
@@ -2571,12 +3028,12 @@ void main() {
2571
3028
  `;
2572
3029
  var smearOrbProgram = {
2573
3030
  name: "smearOrb",
2574
- fragmentSource: fragmentSource17,
3031
+ fragmentSource: fragmentSource21,
2575
3032
  replacesBaseFill: true
2576
3033
  };
2577
3034
 
2578
3035
  // src/runtime/viewer/shaders/builtins/tickScale.ts
2579
- var fragmentSource18 = `
3036
+ var fragmentSource22 = `
2580
3037
  precision highp float;
2581
3038
 
2582
3039
  uniform vec2 uResolution;
@@ -2635,12 +3092,12 @@ void main() {
2635
3092
  `;
2636
3093
  var tickScaleProgram = {
2637
3094
  name: "tickScale",
2638
- fragmentSource: fragmentSource18,
3095
+ fragmentSource: fragmentSource22,
2639
3096
  replacesBaseFill: true
2640
3097
  };
2641
3098
 
2642
3099
  // src/runtime/viewer/shaders/builtins/violetGlass.ts
2643
- var fragmentSource19 = `
3100
+ var fragmentSource23 = `
2644
3101
  precision highp float;
2645
3102
 
2646
3103
  uniform float uTime;
@@ -2720,11 +3177,11 @@ void main() {
2720
3177
  `;
2721
3178
  var violetGlassProgram = {
2722
3179
  name: "violetGlass",
2723
- fragmentSource: fragmentSource19
3180
+ fragmentSource: fragmentSource23
2724
3181
  };
2725
3182
 
2726
3183
  // src/runtime/viewer/shaders/builtins/violetGlassLight.ts
2727
- var fragmentSource20 = `
3184
+ var fragmentSource24 = `
2728
3185
  precision highp float;
2729
3186
 
2730
3187
  uniform float uTime;
@@ -2794,7 +3251,7 @@ void main() {
2794
3251
  `;
2795
3252
  var violetGlassLightProgram = {
2796
3253
  name: "violetGlassLight",
2797
- fragmentSource: fragmentSource20
3254
+ fragmentSource: fragmentSource24
2798
3255
  };
2799
3256
 
2800
3257
  // src/runtime/viewer/shaders/programs.ts
@@ -2818,7 +3275,11 @@ var builtins = [
2818
3275
  violetGlassProgram,
2819
3276
  violetGlassLightProgram,
2820
3277
  lumenPortalProgram,
2821
- lumenPortalLightProgram
3278
+ lumenPortalLightProgram,
3279
+ reactivePanelProgram,
3280
+ ledMatrixProgram,
3281
+ lightBandProgram,
3282
+ silkFoldsProgram
2822
3283
  ];
2823
3284
  var programs = new Map(builtins.map((program) => [program.name, program]));
2824
3285
  function registerShaderProgram(program) {
@@ -2932,8 +3393,8 @@ function uniform2f(surface, name, value) {
2932
3393
  surface.gl.uniform2f(location, ...value);
2933
3394
  }
2934
3395
  }
2935
- function uniformName(parameter) {
2936
- return `u${parameter.charAt(0).toUpperCase()}${parameter.slice(1)}`;
3396
+ function uniformName(parameter2) {
3397
+ return `u${parameter2.charAt(0).toUpperCase()}${parameter2.slice(1)}`;
2937
3398
  }
2938
3399
  function enumParameter(name, value) {
2939
3400
  const values = {
@@ -2999,9 +3460,9 @@ function compile(gl, type, source) {
2999
3460
  }
3000
3461
  return shader;
3001
3462
  }
3002
- function linkProgram(gl, fragmentSource21) {
3463
+ function linkProgram(gl, fragmentSource25) {
3003
3464
  const vertex = compile(gl, gl.VERTEX_SHADER, VERTEX_SOURCE);
3004
- const fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource21);
3465
+ const fragment = compile(gl, gl.FRAGMENT_SHADER, fragmentSource25);
3005
3466
  if (!vertex || !fragment) {
3006
3467
  if (vertex) {
3007
3468
  gl.deleteShader(vertex);
@@ -3051,6 +3512,10 @@ function parametersOf(owner) {
3051
3512
  return {};
3052
3513
  }
3053
3514
  }
3515
+ function surfacePaddingOf(owner) {
3516
+ const padding = Number(owner.getAttribute("data-sf-shader-padding"));
3517
+ return Number.isFinite(padding) ? Math.max(0, padding) : 0;
3518
+ }
3054
3519
  function bindFullScreenQuad(gl, program) {
3055
3520
  const buffer = gl.createBuffer();
3056
3521
  if (!buffer) {
@@ -3103,8 +3568,13 @@ function createSurface(canvas) {
3103
3568
  gl,
3104
3569
  program,
3105
3570
  buffer,
3106
- parameters: parametersOf(owner),
3571
+ parameters: { ...definition.defaultParameters, ...parametersOf(owner) },
3572
+ surfacePadding: surfacePaddingOf(owner),
3107
3573
  smoothed: /* @__PURE__ */ new Map(),
3574
+ pointer: { x: 0.5, y: 0.5 },
3575
+ hovering: false,
3576
+ hover: 0,
3577
+ trail: [],
3108
3578
  backdropTexture: usesBackdrop ? transparentTexture(gl) : void 0,
3109
3579
  backdropOrigin: [0, 0],
3110
3580
  backdropScale: [1, 1],
@@ -3130,6 +3600,108 @@ function releaseSurface(surface) {
3130
3600
  }
3131
3601
  }
3132
3602
 
3603
+ // src/runtime/viewer/shaders/reactiveLightField.ts
3604
+ function geometryOf(surface) {
3605
+ const x = Number(surface.owner.getAttribute("x"));
3606
+ const y = Number(surface.owner.getAttribute("y"));
3607
+ const width = Number(surface.owner.getAttribute("width"));
3608
+ const height = Number(surface.owner.getAttribute("height"));
3609
+ if (![x, y, width, height].every(Number.isFinite) || width <= 0 || height <= 0) {
3610
+ return void 0;
3611
+ }
3612
+ const matrix = surface.owner.getCTM?.();
3613
+ const a = matrix?.a ?? 1;
3614
+ const b = matrix?.b ?? 0;
3615
+ const c = matrix?.c ?? 0;
3616
+ const d = matrix?.d ?? 1;
3617
+ const e = matrix?.e ?? 0;
3618
+ const f = matrix?.f ?? 0;
3619
+ const determinant = a * d - b * c;
3620
+ const centerX = a * (x + width / 2) + c * (y + height / 2) + e;
3621
+ const centerY = b * (x + width / 2) + d * (y + height / 2) + f;
3622
+ const localPoint = (worldX, worldY) => {
3623
+ if (Math.abs(determinant) < 1e-6) {
3624
+ return [worldX, worldY];
3625
+ }
3626
+ const translatedX = worldX - e;
3627
+ const translatedY = worldY - f;
3628
+ return [(d * translatedX - c * translatedY) / determinant, (-b * translatedX + a * translatedY) / determinant];
3629
+ };
3630
+ return { width, height, centerX, centerY, localPoint };
3631
+ }
3632
+ function parameter(parameters3, key, fallback) {
3633
+ return number(parameters3[key], fallback);
3634
+ }
3635
+ function normalizedLightPosition(sourceX, sourceY, receiverX, receiverY, receiverWidth, receiverHeight) {
3636
+ return [(sourceX - receiverX) / receiverWidth, (sourceY - receiverY) / receiverHeight];
3637
+ }
3638
+ function updateReactiveLightFields(surfaces) {
3639
+ const reactive = surfaces.filter((surface) => surface.owner.getAttribute("data-sf-shader") === "reactivePanel").flatMap((surface) => {
3640
+ const geometry = geometryOf(surface);
3641
+ return geometry ? [{ surface, geometry }] : [];
3642
+ });
3643
+ for (const receiver of reactive) {
3644
+ const sources = [];
3645
+ for (const candidate of reactive) {
3646
+ if (candidate.surface === receiver.surface) {
3647
+ continue;
3648
+ }
3649
+ const emission = Math.max(
3650
+ 0,
3651
+ candidate.surface.smoothed.get("emission") ?? parameter(candidate.surface.parameters, "emission", 0)
3652
+ );
3653
+ if (emission <= 1e-4) {
3654
+ continue;
3655
+ }
3656
+ const distance = Math.hypot(
3657
+ candidate.geometry.centerX - receiver.geometry.centerX,
3658
+ candidate.geometry.centerY - receiver.geometry.centerY
3659
+ );
3660
+ sources.push({ candidate, emission, weight: emission / Math.max(distance, 1) });
3661
+ }
3662
+ const totalWeight = sources.reduce((sum, source) => sum + source.weight, 0);
3663
+ if (totalWeight <= 0) {
3664
+ receiver.surface.reactiveLight = void 0;
3665
+ continue;
3666
+ }
3667
+ let worldX = 0;
3668
+ let worldY = 0;
3669
+ let sourceEmission = 0;
3670
+ let radius = 0;
3671
+ const lightColor = [0, 0, 0];
3672
+ for (const source of sources) {
3673
+ const influence = source.weight / totalWeight;
3674
+ worldX += source.candidate.geometry.centerX * influence;
3675
+ worldY += source.candidate.geometry.centerY * influence;
3676
+ sourceEmission += source.emission;
3677
+ radius += Math.max(1, parameter(source.candidate.surface.parameters, "glowRadius", 90)) * influence;
3678
+ const sourceColor = color(source.candidate.surface.parameters.lightColor, [0.35, 0.82, 1]);
3679
+ lightColor[0] += sourceColor[0] * influence;
3680
+ lightColor[1] += sourceColor[1] * influence;
3681
+ lightColor[2] += sourceColor[2] * influence;
3682
+ }
3683
+ const receiverStrength = Math.max(0, parameter(receiver.surface.parameters, "lightStrength", 1));
3684
+ const [sourceX, sourceY] = receiver.geometry.localPoint(worldX, worldY);
3685
+ const receiverX = Number(receiver.surface.owner.getAttribute("x"));
3686
+ const receiverY = Number(receiver.surface.owner.getAttribute("y"));
3687
+ const [lightX, lightY] = normalizedLightPosition(
3688
+ sourceX,
3689
+ sourceY,
3690
+ receiverX,
3691
+ receiverY,
3692
+ receiver.geometry.width,
3693
+ receiver.geometry.height
3694
+ );
3695
+ receiver.surface.reactiveLight = {
3696
+ x: lightX,
3697
+ y: lightY,
3698
+ strength: sourceEmission * receiverStrength * 1.8,
3699
+ radius,
3700
+ color: lightColor
3701
+ };
3702
+ }
3703
+ }
3704
+
3133
3705
  // src/runtime/viewer/shaders/renderSurface.ts
3134
3706
  function syncBackdropBounds(surface) {
3135
3707
  const svg = surface.canvas.closest("svg");
@@ -3158,6 +3730,7 @@ function applyBackdrop(surface, backdrop) {
3158
3730
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, backdrop.image);
3159
3731
  }
3160
3732
  var MAX_SURFACE_PIXELS = 2560;
3733
+ var TRAIL_LENGTH = 16;
3161
3734
  function renderSurface(surface, seconds) {
3162
3735
  const { canvas, gl, parameters: parameters3 } = surface;
3163
3736
  const shown = canvas.getBoundingClientRect();
@@ -3177,6 +3750,12 @@ function renderSurface(surface, seconds) {
3177
3750
  if (resolution) {
3178
3751
  gl.uniform2f(resolution, width, height);
3179
3752
  }
3753
+ const logicalWidth = Number(surface.owner.getAttribute("width"));
3754
+ uniform1f(
3755
+ surface,
3756
+ "uPixelScale",
3757
+ Number.isFinite(logicalWidth) && logicalWidth > 0 ? width / logicalWidth : density * fit
3758
+ );
3180
3759
  uniform1f(surface, "uTime", seconds);
3181
3760
  if (surface.backdropTexture) {
3182
3761
  syncBackdropBounds(surface);
@@ -3199,6 +3778,28 @@ function renderSurface(surface, seconds) {
3199
3778
  const elapsed = surface.lastSeconds === void 0 ? 0 : Math.max(0, Math.min(seconds - surface.lastSeconds, 0.1));
3200
3779
  surface.lastSeconds = seconds;
3201
3780
  applyParameters(surface, elapsed);
3781
+ surface.hover += ((surface.hovering ? 1 : 0) - surface.hover) * (1 - Math.exp(-elapsed / 0.18));
3782
+ uniform2f(surface, "uPointer", [surface.pointer.x, surface.pointer.y]);
3783
+ uniform1f(surface, "uHover", surface.hover);
3784
+ const fade = number(parameters3.trail, 0);
3785
+ const places = new Float32Array(TRAIL_LENGTH * 3);
3786
+ if (fade > 0) {
3787
+ surface.trail.slice(-TRAIL_LENGTH).forEach((place, index) => {
3788
+ places.set([place.x, place.y, Math.exp(-Math.max(seconds - place.at, 0) / fade)], index * 3);
3789
+ });
3790
+ }
3791
+ const trail = gl.getUniformLocation(surface.program, "uWake[0]");
3792
+ if (trail) {
3793
+ gl.uniform3fv(trail, places);
3794
+ }
3795
+ if (surface.reactiveLight) {
3796
+ uniform1f(surface, "uLightX", surface.reactiveLight.x);
3797
+ uniform1f(surface, "uLightY", surface.reactiveLight.y);
3798
+ uniform1f(surface, "uLightStrength", surface.reactiveLight.strength);
3799
+ uniform1f(surface, "uGlowRadius", surface.reactiveLight.radius);
3800
+ uniform3f(surface, "uLightColor", surface.reactiveLight.color);
3801
+ }
3802
+ uniform1f(surface, "uSurfacePadding", surface.surfacePadding);
3202
3803
  gl.drawArrays(gl.TRIANGLES, 0, 6);
3203
3804
  }
3204
3805
 
@@ -3224,6 +3825,8 @@ function createSurfaceClock(view) {
3224
3825
 
3225
3826
  // src/runtime/viewer/shaders/surface.ts
3226
3827
  var RECAPTURE_DELAY_MS = 120;
3828
+ var TRAIL_SPACING = 0.055;
3829
+ var TRAIL_LENGTH2 = 16;
3227
3830
  function capturePngs(svg, surfaces, seconds) {
3228
3831
  const surfaceByCanvas = new Map(surfaces.map((surface) => [surface.canvas, surface]));
3229
3832
  return [...svg.querySelectorAll("canvas[data-sf-shader-canvas]")].map((canvas) => {
@@ -3247,9 +3850,14 @@ function updateParameters(surfaces, ownerId, parameters3, seconds) {
3247
3850
  }
3248
3851
  Object.assign(surface.parameters, parameters3);
3249
3852
  surface.owner.setAttribute("data-sf-shader-params", JSON.stringify(surface.parameters));
3250
- renderSurface(surface, seconds);
3251
3853
  changed = true;
3252
3854
  }
3855
+ if (changed) {
3856
+ updateReactiveLightFields(surfaces);
3857
+ for (const surface of surfaces) {
3858
+ renderSurface(surface, seconds);
3859
+ }
3860
+ }
3253
3861
  return changed;
3254
3862
  }
3255
3863
  function watchSvgChanges(svg, view, onChange) {
@@ -3274,6 +3882,7 @@ function mountShaderSurfaces(svg) {
3274
3882
  const clock = createSurfaceClock(view);
3275
3883
  const draw = (milliseconds) => {
3276
3884
  if (!clock.paused()) {
3885
+ updateReactiveLightFields(surfaces);
3277
3886
  for (const surface of surfaces) {
3278
3887
  renderSurface(surface, milliseconds / 1e3 - clock.spent());
3279
3888
  }
@@ -3317,12 +3926,41 @@ function mountShaderSurfaces(svg) {
3317
3926
  frame = view.requestAnimationFrame(draw);
3318
3927
  };
3319
3928
  const refresh = () => {
3929
+ const previousState = new Map(
3930
+ surfaces.flatMap((surface) => {
3931
+ const ownerId = surface.owner.getAttribute("data-sf-id");
3932
+ return ownerId ? [
3933
+ [
3934
+ ownerId,
3935
+ {
3936
+ smoothed: new Map(surface.smoothed),
3937
+ reactiveLight: surface.reactiveLight,
3938
+ pointer: surface.pointer,
3939
+ hover: surface.hover,
3940
+ hovering: surface.hovering,
3941
+ trail: surface.trail
3942
+ }
3943
+ ]
3944
+ ] : [];
3945
+ })
3946
+ );
3320
3947
  stop();
3321
3948
  const generation = ++backdropGeneration;
3322
3949
  surfaces = [...svg.querySelectorAll("canvas[data-sf-shader-canvas]")].flatMap((canvas) => {
3323
3950
  const surface = createSurface(canvas);
3951
+ const ownerId = surface?.owner.getAttribute("data-sf-id");
3952
+ const previous = ownerId ? previousState.get(ownerId) : void 0;
3953
+ if (surface && previous) {
3954
+ surface.smoothed = previous.smoothed;
3955
+ surface.reactiveLight = previous.reactiveLight;
3956
+ surface.pointer = previous.pointer;
3957
+ surface.hover = previous.hover;
3958
+ surface.hovering = previous.hovering;
3959
+ surface.trail = previous.trail;
3960
+ }
3324
3961
  return surface ? [surface] : [];
3325
3962
  });
3963
+ updateReactiveLightFields(surfaces);
3326
3964
  captureBackdrops(generation);
3327
3965
  if (surfaces.length > 0) {
3328
3966
  startFrames();
@@ -3338,10 +3976,37 @@ function mountShaderSurfaces(svg) {
3338
3976
  }, RECAPTURE_DELAY_MS);
3339
3977
  };
3340
3978
  const unwatch = watchSvgChanges(svg, view, scheduleRecapture);
3979
+ const track = (event) => {
3980
+ for (const surface of surfaces) {
3981
+ const box = surface.canvas.getBoundingClientRect();
3982
+ const inside = box.width > 0 && box.height > 0 && event.clientX >= box.left && event.clientX <= box.right && event.clientY >= box.top && event.clientY <= box.bottom;
3983
+ surface.hovering = inside;
3984
+ if (inside) {
3985
+ surface.pointer = { x: (event.clientX - box.left) / box.width, y: 1 - (event.clientY - box.top) / box.height };
3986
+ const now = clock.now();
3987
+ const last = surface.trail[surface.trail.length - 1];
3988
+ if (!last || now - last.at >= TRAIL_SPACING) {
3989
+ surface.trail.push({ ...surface.pointer, at: now });
3990
+ if (surface.trail.length > TRAIL_LENGTH2) {
3991
+ surface.trail.shift();
3992
+ }
3993
+ }
3994
+ }
3995
+ }
3996
+ };
3997
+ const leave = () => {
3998
+ for (const surface of surfaces) {
3999
+ surface.hovering = false;
4000
+ }
4001
+ };
4002
+ svg.addEventListener("pointermove", track);
4003
+ svg.addEventListener("pointerleave", leave);
3341
4004
  refresh();
3342
4005
  const destroy = () => {
3343
4006
  backdropGeneration += 1;
3344
4007
  unwatch();
4008
+ svg.removeEventListener("pointermove", track);
4009
+ svg.removeEventListener("pointerleave", leave);
3345
4010
  if (recapture !== void 0) {
3346
4011
  view?.clearTimeout(recapture);
3347
4012
  }
@@ -3358,21 +4023,21 @@ function mountShaderSurfaces(svg) {
3358
4023
 
3359
4024
  // src/runtime/viewer/source.ts
3360
4025
  function renderViewerSource(next, defaultRenderOptions) {
3361
- const svg = next.svg ?? (next.source != null ? chunkZMLQIMJK_cjs.render(next.source, { ...next.renderOptions ?? defaultRenderOptions, linkHitAreas: true }).svg : null);
4026
+ const svg = next.svg ?? (next.source != null ? chunkA73UJ5AQ_cjs.render(next.source, { ...next.renderOptions ?? defaultRenderOptions, linkHitAreas: true }).svg : null);
3362
4027
  if (svg == null) {
3363
4028
  throw new Error("createViewer: provide either `source` (SFL) or `svg`.");
3364
4029
  }
3365
4030
  return svg;
3366
4031
  }
3367
4032
  function assertCreateViewerContract(svg) {
3368
- const version = chunkL3VJXZFD_cjs.parseContractVersion(svg);
3369
- if (!chunkL3VJXZFD_cjs.isContractCompatible(version)) {
4033
+ const version = chunkEKAWJFJQ_cjs.parseContractVersion(svg);
4034
+ if (!chunkEKAWJFJQ_cjs.isContractCompatible(version)) {
3370
4035
  throw new Error(`createViewer: incompatible DOM contract (svg=${version}). Renderer and viewer versions differ.`);
3371
4036
  }
3372
4037
  }
3373
4038
  function assertViewerUpdateContract(svg) {
3374
- const version = chunkL3VJXZFD_cjs.parseContractVersion(svg);
3375
- if (!chunkL3VJXZFD_cjs.isContractCompatible(version)) {
4039
+ const version = chunkEKAWJFJQ_cjs.parseContractVersion(svg);
4040
+ if (!chunkEKAWJFJQ_cjs.isContractCompatible(version)) {
3376
4041
  throw new Error(`viewer.update: incompatible DOM contract (svg=${version}). Renderer and viewer versions differ.`);
3377
4042
  }
3378
4043
  }
@@ -3604,6 +4269,22 @@ function trackScales(wiring, event) {
3604
4269
  }
3605
4270
  }
3606
4271
  }
4272
+ function driveValue(wiring, id, event) {
4273
+ const { runtime, svg } = wiring;
4274
+ const kind = chunkKXYSO6GC_cjs.getComponentDescriptor(runtime.graph.elements.get(id)?.componentType)?.interaction;
4275
+ if (kind !== "slide" && kind !== "pick" && kind !== "turn" && kind !== "range") {
4276
+ return;
4277
+ }
4278
+ const node = svg.querySelector(`[data-sf-primary][data-sf-id="${CSS.escape(id)}"]`);
4279
+ if (!node) {
4280
+ return;
4281
+ }
4282
+ const box = node.getBoundingClientRect();
4283
+ if (box.width > 0 && box.height > 0) {
4284
+ const within = (value) => Math.min(1, Math.max(0, value));
4285
+ runtime.slide(id, within((event.clientX - box.left) / box.width), within((event.clientY - box.top) / box.height));
4286
+ }
4287
+ }
3607
4288
  function updateHover(wiring, event) {
3608
4289
  const { runtime, svg, options, session } = wiring;
3609
4290
  const over = options.enabled?.() === false ? null : hit(svg, runtime.interactive.pressable, event.clientX, event.clientY);
@@ -3635,6 +4316,7 @@ function pressStart(wiring, event) {
3635
4316
  session.active = id;
3636
4317
  trackScales(wiring, event);
3637
4318
  runtime.press(id);
4319
+ driveValue(wiring, id, event);
3638
4320
  runtime.drag(id);
3639
4321
  }
3640
4322
  function pressMove(wiring, event) {
@@ -3644,6 +4326,7 @@ function pressMove(wiring, event) {
3644
4326
  return;
3645
4327
  }
3646
4328
  trackScales(wiring, event);
4329
+ driveValue(wiring, session.active, event);
3647
4330
  runtime.drag(session.active);
3648
4331
  }
3649
4332
  function pressEnd(wiring, event, tapOnElement) {
@@ -3727,5 +4410,5 @@ exports.connectInteraction = connectInteraction;
3727
4410
  exports.createViewer = createViewer;
3728
4411
  exports.registerShaderProgram = registerShaderProgram;
3729
4412
  exports.shaderProgram = shaderProgram;
3730
- //# sourceMappingURL=chunk-VK3T6O5Z.cjs.map
3731
- //# sourceMappingURL=chunk-VK3T6O5Z.cjs.map
4413
+ //# sourceMappingURL=chunk-BUOWM3LC.cjs.map
4414
+ //# sourceMappingURL=chunk-BUOWM3LC.cjs.map