@mkbabb/glass-ui 4.0.1 → 4.1.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 (459) hide show
  1. package/dist/{CardAction-CW7a0m8M.js → CardAction-8whJrLWt.js} +23 -8
  2. package/dist/{CommandShortcut-DvZNQ_HF.js → CommandShortcut-D3yxgHNn.js} +23 -12
  3. package/dist/{ConfiguratorRow-BR4l-ixA.js → ConfiguratorRow-CaP7U3ZA.js} +11 -11
  4. package/dist/ContextMenuContent-B3ZsheLV.js +90 -0
  5. package/dist/{ContextMenuSubContent-xol4sD2q.js → ContextMenuSubContent-DDRID3qC.js} +15 -15
  6. package/dist/{DataTable-CuKwF7wr.js → DataTable-Bc9kUtu_.js} +2 -2
  7. package/dist/{DialogContent-DcKK8k9i.js → DialogContent-6JtTB5x2.js} +8 -5
  8. package/dist/DialogFooter-9phqcRIS.js +80 -0
  9. package/dist/DialogScrollContent-TTuovQst.js +93 -0
  10. package/dist/HoverCardContent-Bel1gdLZ.js +88 -0
  11. package/dist/{IconChip-BTD-nay5.js → IconChip-DhbdGdFQ.js} +1 -1
  12. package/dist/{IconTooltip-Bl8gFZ8d.js → IconTooltip-B0zimd2H.js} +1 -1
  13. package/dist/Input-Cg9DF62r.js +57 -0
  14. package/dist/{Notification-VUwexFUf.js → Notification-CphK7AAm.js} +3 -3
  15. package/dist/NumberFieldContent-D8cXeyO4.js +140 -0
  16. package/dist/PagerDots-Cjx96la-.js +98 -0
  17. package/dist/{SelectScrollDownButton-CrA8F0iV.js → SelectScrollDownButton-DAKCBEdW.js} +62 -57
  18. package/dist/{SelectSeparator-DXswVdRz.js → SelectSeparator-C2UGOkXF.js} +1 -1
  19. package/dist/Separator-DQcwC2TR.js +44 -0
  20. package/dist/Switch-B8RscmRu.js +49 -0
  21. package/dist/{Toaster-Bw4xR8xV.js → Toaster-D9qIHjBI.js} +1 -1
  22. package/dist/{ToggleGroupItem-pEM9vIhs.js → ToggleGroupItem-BLtr3TJq.js} +2 -2
  23. package/dist/TooltipProvider-BJ_Y5EGX.js +109 -0
  24. package/dist/animated-digit.js +1 -1
  25. package/dist/api/index.d.ts +15 -32
  26. package/dist/api/types-extra.d.ts +31 -0
  27. package/dist/api.js +1 -1
  28. package/dist/aurora.js +579 -251
  29. package/dist/border-progress.js +49 -57
  30. package/dist/{button-DYCUa-tH.js → button-5dY1Dvhd.js} +13 -14
  31. package/dist/button.js +1 -1
  32. package/dist/canvas.js +2 -3
  33. package/dist/card.js +1 -1
  34. package/dist/carousel.js +20 -20
  35. package/dist/color-Cs0-oxYL.js +116 -0
  36. package/dist/color.js +2 -2
  37. package/dist/command.js +1 -1
  38. package/dist/completion-seal.d.ts +1 -0
  39. package/dist/completion-seal.js +89 -0
  40. package/dist/components/custom/aurora/Aurora.vue.d.ts +10 -5
  41. package/dist/components/custom/aurora/composables/color.d.ts +13 -0
  42. package/dist/components/custom/aurora/composables/frameLoop.d.ts +9 -0
  43. package/dist/components/custom/aurora/composables/runtime.d.ts +12 -0
  44. package/dist/components/custom/aurora/composables/uniformBridgeWGPU.d.ts +11 -2
  45. package/dist/components/custom/aurora/composables/wgpuSetup.d.ts +8 -0
  46. package/dist/components/custom/aurora/constants/presets.d.ts +18 -0
  47. package/dist/components/custom/aurora/constants/renderMode.d.ts +16 -8
  48. package/dist/components/custom/aurora/constants/shaders/aurora-mediums.wgsl.d.ts +1 -0
  49. package/dist/components/custom/aurora/constants/shaders/aurora.wgsl.d.ts +1 -1
  50. package/dist/components/custom/border-progress/composables/spectrum-walk.d.ts +25 -0
  51. package/dist/components/custom/border-progress/composables/useBorderSpectrum.d.ts +14 -18
  52. package/dist/components/custom/border-progress/index.d.ts +1 -1
  53. package/dist/components/custom/completion-seal/CompletionSeal.vue.d.ts +21 -0
  54. package/dist/components/custom/completion-seal/composables/useCompletionSeal.d.ts +37 -0
  55. package/dist/components/custom/completion-seal/constants.d.ts +46 -0
  56. package/dist/components/custom/completion-seal/index.d.ts +4 -0
  57. package/dist/components/custom/concentric/composables/concentricGLSetup.d.ts +7 -0
  58. package/dist/components/custom/concentric/composables/concentricWGPUSetup.d.ts +9 -0
  59. package/dist/components/custom/concentric/composables/ringField.d.ts +57 -16
  60. package/dist/components/custom/concentric/composables/uniformBridgeWGPU.d.ts +2 -1
  61. package/dist/components/custom/concentric/composables/useConcentric.d.ts +4 -4
  62. package/dist/components/custom/concentric/constants.d.ts +30 -6
  63. package/dist/components/custom/concentric/index.d.ts +2 -2
  64. package/dist/components/custom/concentric/shaders/concentric.glsl.d.ts +2 -2
  65. package/dist/components/custom/concentric/shaders/concentric.wgsl.d.ts +1 -1
  66. package/dist/components/custom/confirm-dialog/ConfirmDialog.vue.d.ts +3 -3
  67. package/dist/components/custom/constellation/Constellation.vue.d.ts +5 -4
  68. package/dist/components/custom/constellation/composables/constellationGLSetup.d.ts +10 -0
  69. package/dist/components/custom/constellation/composables/constellationWGPUSetup.d.ts +19 -0
  70. package/dist/components/custom/constellation/composables/uniformBridgeWGPU.d.ts +66 -0
  71. package/dist/components/custom/constellation/composables/useConstellation.d.ts +3 -10
  72. package/dist/components/custom/constellation/constants.d.ts +33 -0
  73. package/dist/components/custom/constellation/constellationField.d.ts +31 -1
  74. package/dist/components/custom/constellation/constellationInteraction.d.ts +23 -14
  75. package/dist/components/custom/constellation/constellationRender.d.ts +25 -0
  76. package/dist/components/custom/constellation/constellationTypes.d.ts +38 -0
  77. package/dist/components/custom/constellation/constellationWell.d.ts +15 -0
  78. package/dist/components/custom/constellation/index.d.ts +5 -5
  79. package/dist/components/custom/constellation/shaders/constellation-lines.glsl.d.ts +2 -0
  80. package/dist/components/custom/constellation/shaders/constellation-lines.wgsl.d.ts +1 -0
  81. package/dist/components/custom/constellation/shaders/constellation-points.glsl.d.ts +2 -0
  82. package/dist/components/custom/constellation/shaders/constellation-points.wgsl.d.ts +1 -0
  83. package/dist/components/custom/deck/DeckPager.vue.d.ts +29 -0
  84. package/dist/components/custom/deck/composables/useDeck.d.ts +27 -0
  85. package/dist/components/custom/deck/composables/useDeckKeyboard.d.ts +25 -0
  86. package/dist/components/custom/deck/composables/useDeckSpring.d.ts +22 -0
  87. package/dist/components/custom/deck/constants.d.ts +14 -0
  88. package/dist/components/custom/deck/index.d.ts +8 -0
  89. package/dist/components/custom/dock/DockIconButton.vue.d.ts +12 -0
  90. package/dist/components/custom/dock/DockStack.vue.d.ts +65 -0
  91. package/dist/components/custom/dock/GlassDock.vue.d.ts +4 -2
  92. package/dist/components/custom/dock/composables/dockMorphMeasure.d.ts +80 -0
  93. package/dist/components/custom/dock/composables/index.d.ts +2 -0
  94. package/dist/components/custom/dock/composables/useDockSearch.d.ts +85 -0
  95. package/dist/components/custom/dock/composables/useDockShellProps.d.ts +11 -0
  96. package/dist/components/custom/dock/constants.d.ts +18 -14
  97. package/dist/components/custom/dock/index.d.ts +5 -2
  98. package/dist/components/custom/dot-flow-field/DotFlowField.vue.d.ts +15 -11
  99. package/dist/components/custom/dot-flow-field/composables/flowField.d.ts +48 -6
  100. package/dist/components/custom/dot-flow-field/composables/uniformBridgeWGPU.d.ts +23 -8
  101. package/dist/components/custom/dot-flow-field/composables/useDotFlowField.d.ts +6 -5
  102. package/dist/components/custom/dot-flow-field/composables/useFlowParticles.d.ts +18 -5
  103. package/dist/components/custom/dot-flow-field/constants.d.ts +42 -21
  104. package/dist/components/custom/dot-flow-field/index.d.ts +2 -2
  105. package/dist/components/custom/dot-flow-field/shaders/flow-field.compute.wgsl.d.ts +1 -1
  106. package/dist/components/custom/dot-flow-field/shaders/flow-field.glsl.d.ts +4 -20
  107. package/dist/components/custom/dot-flow-field/shaders/flow-field.render.wgsl.d.ts +1 -1
  108. package/dist/components/custom/dot-matrix/DotMatrix.vue.d.ts +43 -0
  109. package/dist/components/custom/dot-matrix/composables/dotMatrixField.d.ts +89 -0
  110. package/dist/components/custom/dot-matrix/composables/uniformBridgeWGPU.d.ts +52 -0
  111. package/dist/components/custom/dot-matrix/composables/useDotMatrix.d.ts +34 -0
  112. package/dist/components/custom/dot-matrix/composables/useDotSphere.d.ts +27 -0
  113. package/dist/components/custom/dot-matrix/constants.d.ts +58 -0
  114. package/dist/components/custom/dot-matrix/index.d.ts +5 -0
  115. package/dist/components/custom/dot-matrix/shaders/dot-matrix.glsl.d.ts +4 -0
  116. package/dist/components/custom/dot-matrix/shaders/dot-matrix.wgsl.d.ts +1 -0
  117. package/dist/components/custom/easing/EasingPicker.vue.d.ts +2 -2
  118. package/dist/components/custom/easing/composables/useEasingPicker.d.ts +5 -0
  119. package/dist/components/custom/expandable-container/ExpandableContainer.vue.d.ts +11 -0
  120. package/dist/components/custom/fourier-field/FourierField.vue.d.ts +40 -47
  121. package/dist/components/custom/fourier-field/composables/fourierFieldGLSetup.d.ts +15 -0
  122. package/dist/components/custom/fourier-field/composables/fourierFieldWGPUSetup.d.ts +20 -0
  123. package/dist/components/custom/fourier-field/composables/uniformBridgeWGPU.d.ts +41 -0
  124. package/dist/components/custom/fourier-field/composables/useFourierField.d.ts +40 -37
  125. package/dist/components/custom/fourier-field/constants.d.ts +61 -4
  126. package/dist/components/custom/fourier-field/index.d.ts +23 -18
  127. package/dist/components/custom/fourier-field/shaders/fourier-field.compute.wgsl.d.ts +1 -0
  128. package/dist/components/custom/fourier-field/shaders/fourier-field.glsl.d.ts +4 -0
  129. package/dist/components/custom/fourier-field/shaders/fourier-field.render.wgsl.d.ts +1 -0
  130. package/dist/components/custom/goo-blob/GooBlob.vue.d.ts +9 -1
  131. package/dist/components/custom/goo-blob/constants.d.ts +1 -1
  132. package/dist/components/custom/goo-blob/index.d.ts +1 -1
  133. package/dist/components/custom/goo-blob/shaders/metaball-noise.wgsl.d.ts +1 -0
  134. package/dist/components/custom/goo-blob/shaders/metaball-palette.wgsl.d.ts +1 -0
  135. package/dist/components/custom/goo-blob/shaders/metaball-uniforms.glsl.d.ts +1 -1
  136. package/dist/components/custom/goo-blob/shaders/metaball.wgsl.d.ts +1 -1
  137. package/dist/components/custom/goo-blob/types.d.ts +36 -0
  138. package/dist/components/custom/goo-dot-matrix/GooDotMatrix.vue.d.ts +49 -0
  139. package/dist/components/custom/goo-dot-matrix/composables/gooDotLattice.d.ts +24 -0
  140. package/dist/components/custom/goo-dot-matrix/composables/gooDotSetup.d.ts +50 -0
  141. package/dist/components/custom/goo-dot-matrix/composables/uniformBridgeWGPU.d.ts +35 -0
  142. package/dist/components/custom/goo-dot-matrix/composables/useGooDotMatrix.d.ts +31 -0
  143. package/dist/components/custom/goo-dot-matrix/constants.d.ts +76 -0
  144. package/dist/components/custom/goo-dot-matrix/index.d.ts +5 -0
  145. package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.frag.d.ts +11 -0
  146. package/dist/components/custom/goo-dot-matrix/shaders/goo-dot.wgsl.d.ts +3 -0
  147. package/dist/components/custom/labeled-field/LabeledField.vue.d.ts +21 -2
  148. package/dist/components/custom/metric-stack/MetricRow.vue.d.ts +15 -0
  149. package/dist/components/custom/pager-dots/PagerDots.vue.d.ts +9 -0
  150. package/dist/components/custom/pager-dots/index.d.ts +2 -0
  151. package/dist/components/custom/pager-dots/pagerWindow.d.ts +9 -0
  152. package/dist/components/custom/paper-grid/PaperGrid.vue.d.ts +42 -0
  153. package/dist/components/custom/paper-grid/composables/paperGrid.d.ts +90 -0
  154. package/dist/components/custom/paper-grid/composables/paperGridGLSetup.d.ts +16 -0
  155. package/dist/components/custom/paper-grid/composables/paperGridWGPUSetup.d.ts +19 -0
  156. package/dist/components/custom/paper-grid/composables/uniformBridgeWGPU.d.ts +16 -0
  157. package/dist/components/custom/paper-grid/composables/usePaperGrid.d.ts +31 -0
  158. package/dist/components/custom/paper-grid/constants.d.ts +57 -0
  159. package/dist/components/custom/paper-grid/index.d.ts +5 -0
  160. package/dist/components/custom/paper-grid/shaders/paper-grid.glsl.d.ts +4 -0
  161. package/dist/components/custom/paper-grid/shaders/paper-grid.wgsl.d.ts +1 -0
  162. package/dist/components/custom/search/FuzzySearch.vue.d.ts +8 -2
  163. package/dist/components/custom/search/SearchBar.vue.d.ts +8 -0
  164. package/dist/components/custom/search/index.d.ts +2 -0
  165. package/dist/components/custom/search/searchVariants.d.ts +19 -0
  166. package/dist/components/custom/selectable-chip/SelectableChip.vue.d.ts +50 -0
  167. package/dist/components/custom/selectable-chip/index.d.ts +2 -0
  168. package/dist/components/custom/selectable-chip/selectableChipVariants.d.ts +23 -0
  169. package/dist/components/custom/split-chars/SplitChars.vue.d.ts +39 -0
  170. package/dist/components/custom/split-chars/index.d.ts +1 -0
  171. package/dist/components/custom/tabs/SegmentedTabs.vue.d.ts +8 -6
  172. package/dist/components/custom/tabs/constants.d.ts +20 -2
  173. package/dist/components/custom/watercolor-dot/WatercolorDot.vue.d.ts +29 -16
  174. package/dist/components/custom/watercolor-dot/useWatercolorBlob.d.ts +10 -5
  175. package/dist/components/ui/_shared/index.d.ts +2 -0
  176. package/dist/components/ui/_shared/useControlSize.d.ts +46 -0
  177. package/dist/components/ui/button/index.d.ts +1 -1
  178. package/dist/components/ui/card/Card.vue.d.ts +45 -0
  179. package/dist/components/ui/card/index.d.ts +1 -1
  180. package/dist/components/ui/carousel/CarouselNext.vue.d.ts +1 -1
  181. package/dist/components/ui/carousel/CarouselPrevious.vue.d.ts +1 -1
  182. package/dist/components/ui/command/CommandDialog.vue.d.ts +9 -3
  183. package/dist/components/ui/command/CommandList.vue.d.ts +3 -0
  184. package/dist/components/ui/context-menu/ContextMenuContent.vue.d.ts +5 -1
  185. package/dist/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +4 -0
  186. package/dist/components/ui/hover-card/HoverCardContent.vue.d.ts +3 -0
  187. package/dist/components/ui/input/Input.vue.d.ts +3 -0
  188. package/dist/components/ui/number-field/NumberFieldInput.vue.d.ts +6 -1
  189. package/dist/components/ui/select/SelectContent.vue.d.ts +3 -0
  190. package/dist/components/ui/switch/Switch.vue.d.ts +2 -0
  191. package/dist/components/ui/textarea/Textarea.vue.d.ts +3 -0
  192. package/dist/components/ui/tooltip/TooltipContent.vue.d.ts +3 -0
  193. package/dist/composables/color/index.d.ts +2 -0
  194. package/dist/composables/color/useAccentTone.d.ts +34 -0
  195. package/dist/composables/glass/useVizChoreography.d.ts +123 -0
  196. package/dist/composables/glass/webgl/createCanvasLifecycle.d.ts +10 -0
  197. package/dist/composables/glass/webgl/shaders/flow.wgsl.d.ts +1 -0
  198. package/dist/composables/glass/webgpu/index.d.ts +1 -1
  199. package/dist/composables/glass/webgpu/useGpuSubstrate.d.ts +28 -7
  200. package/dist/composables/glass/webgpu/useWebGPUCanvas.d.ts +1 -0
  201. package/dist/composables/glass/webgpu/webgpuDevice.d.ts +42 -0
  202. package/dist/composables/motion/core/index.d.ts +3 -0
  203. package/dist/composables/motion/scrollReader.d.ts +25 -0
  204. package/dist/composables/motion/springPresets.d.ts +20 -1
  205. package/dist/composables/motion/useCharStagger.d.ts +44 -0
  206. package/dist/composables/motion/useDockCtaReceive.d.ts +31 -6
  207. package/dist/composables/motion/useScrollChrome.d.ts +58 -0
  208. package/dist/composables/motion/useScrollTrigger.d.ts +67 -0
  209. package/dist/composables/motion/useSpringPress.d.ts +5 -5
  210. package/dist/composables/motion/useStaggerReveal.d.ts +24 -0
  211. package/dist/composables/sidebar/index.d.ts +4 -1
  212. package/dist/composables/sidebar/types.d.ts +68 -3
  213. package/dist/composables/sidebar/useClickDelegate.d.ts +4 -0
  214. package/dist/composables/sidebar/useLazyLoader.d.ts +5 -0
  215. package/dist/composables/sidebar/useScrollTo.d.ts +5 -0
  216. package/dist/composables/virtual/index.d.ts +4 -0
  217. package/dist/composables/virtual/useVirtualSectionWindow.d.ts +72 -0
  218. package/dist/composables/virtual/useWindowedStore.d.ts +43 -0
  219. package/dist/composables/virtual/virtualSectionLayout.d.ts +103 -0
  220. package/dist/concentric.js +495 -221
  221. package/dist/configurator.js +2 -2
  222. package/dist/confirm-dialog.js +62 -47
  223. package/dist/constellation.js +635 -235
  224. package/dist/context-menu.js +2 -2
  225. package/dist/controls.js +1 -1
  226. package/dist/createCanvasLifecycle-Gh45Ce-p.js +93 -0
  227. package/dist/dark.js +1 -1
  228. package/dist/data-table.js +1 -1
  229. package/dist/deck.d.ts +1 -0
  230. package/dist/deck.js +105 -0
  231. package/dist/dialog.js +4 -3
  232. package/dist/dock.js +602 -458
  233. package/dist/dot-flow-field.js +580 -290
  234. package/dist/dot-matrix.d.ts +1 -0
  235. package/dist/dot-matrix.js +630 -0
  236. package/dist/dotMatrixField-D_x9_1qq.js +48 -0
  237. package/dist/{dropdown-menu-CofSZuk8.js → dropdown-menu-aJmV5SqE.js} +83 -79
  238. package/dist/dropdown-menu.js +1 -1
  239. package/dist/easing.js +188 -176
  240. package/dist/expandable-container.js +42 -20
  241. package/dist/fading-scroll.js +1 -1
  242. package/dist/flow.glsl-B2P7e0MT.js +4 -0
  243. package/dist/forms.js +62 -60
  244. package/dist/fourier-field.js +825 -178
  245. package/dist/fourier-math.js +1 -1
  246. package/dist/glass-ui.css +1 -1
  247. package/dist/glass-ui.js +145 -104
  248. package/dist/goo-blob.js +171 -1228
  249. package/dist/goo-dot-matrix.d.ts +1 -0
  250. package/dist/goo-dot-matrix.js +591 -0
  251. package/dist/handmark.js +1 -1
  252. package/dist/hover-card.js +1 -1
  253. package/dist/hover-popover.js +1 -1
  254. package/dist/icon-chip.js +1 -1
  255. package/dist/icon-tooltip.js +1 -1
  256. package/dist/index.d.ts +2 -0
  257. package/dist/instrument-chassis.js +1 -1
  258. package/dist/keyboard.js +1 -1
  259. package/dist/labeled-field.js +70 -60
  260. package/dist/metric-cell.js +1 -1
  261. package/dist/metric-stack.js +11 -2
  262. package/dist/motion-core.js +54 -32
  263. package/dist/motion-curves.js +11 -1
  264. package/dist/motion.js +46 -111
  265. package/dist/notification.js +1 -1
  266. package/dist/number-field.js +1 -1
  267. package/dist/pager-dots.js +2 -91
  268. package/dist/paper-backdrop.js +1 -1
  269. package/dist/paper-grid.d.ts +1 -0
  270. package/dist/paper-grid.js +788 -0
  271. package/dist/{presets-BW2b-fr1.js → presets-CvOUqtdY.js} +3 -3
  272. package/dist/{procedural-color.glsl-CIFsJhwI.js → procedural-color.wgsl-m7Zgv35j.js} +2 -2
  273. package/dist/progress.js +1 -1
  274. package/dist/pulse.js +1 -1
  275. package/dist/reactive.js +1 -1
  276. package/dist/{useCanvas2D-B8w_E3Rr.js → resolveCanvasColor-yPyIpJt9.js} +12 -2
  277. package/dist/scrollReader-DI1NWxUw.js +42 -0
  278. package/dist/scrolling-text.js +1 -1
  279. package/dist/search.js +160 -304
  280. package/dist/select.js +3 -3
  281. package/dist/selectable-chip.d.ts +1 -0
  282. package/dist/selectable-chip.js +65 -0
  283. package/dist/separator.js +1 -1
  284. package/dist/{sheet-tZMg0E0w.js → sheet-B2flBfLH.js} +2 -2
  285. package/dist/sheet.js +1 -1
  286. package/dist/sidebar.js +216 -114
  287. package/dist/slider.js +1 -1
  288. package/dist/sortable-list.js +1 -1
  289. package/dist/spectrum-walk-BVzA7Biz.js +33 -0
  290. package/dist/{springPresets-CFQGQfdl.js → springPresets-Ce7OYCm9.js} +12 -6
  291. package/dist/styles/animations.css +13 -3
  292. package/dist/styles/cards.css +69 -0
  293. package/dist/styles/completion-seal.css +131 -0
  294. package/dist/styles/components.css +2 -3
  295. package/dist/styles/configurator.css +55 -0
  296. package/dist/styles/critical-partition.mjs +33 -11
  297. package/dist/styles/deferred.css +2 -0
  298. package/dist/styles/dock/cta-seat.css +87 -0
  299. package/dist/styles/dock/density.css +153 -0
  300. package/dist/styles/dock/layers.css +55 -7
  301. package/dist/styles/dock/morph-bridge.css +54 -18
  302. package/dist/styles/dock/morph.css +41 -33
  303. package/dist/styles/dock/overflow.css +12 -0
  304. package/dist/styles/dock/search.css +68 -0
  305. package/dist/styles/dock/shape.css +124 -0
  306. package/dist/styles/dock/shell.css +23 -5
  307. package/dist/styles/dock/stack-rail.css +264 -0
  308. package/dist/styles/dock-controls/dark-mode-toggle.css +17 -4
  309. package/dist/styles/dock-controls/icon-button.css +14 -0
  310. package/dist/styles/dock.css +11 -1
  311. package/dist/styles/glass/accent-tone.css +66 -0
  312. package/dist/styles/glass/control-surfaces.css +167 -0
  313. package/dist/styles/glass/ladder.css +67 -17
  314. package/dist/styles/glass/rim.css +19 -9
  315. package/dist/styles/glass/surfaces.css +69 -148
  316. package/dist/styles/glass.css +10 -0
  317. package/dist/styles/index.css +15 -0
  318. package/dist/styles/scroll-chrome.css +123 -0
  319. package/dist/styles/scroll-driven.css +38 -0
  320. package/dist/styles/segmented-tabs.css +50 -14
  321. package/dist/styles/theme/bridges.css +22 -0
  322. package/dist/styles/theme/radius.css +18 -1
  323. package/dist/styles/tokens/color-radius.css +13 -3
  324. package/dist/styles/tokens/dark-arm.css +39 -6
  325. package/dist/styles/tokens/glass-deep.css +28 -3
  326. package/dist/styles/tokens/glass-fx.css +44 -1
  327. package/dist/styles/tokens/glass.css +91 -31
  328. package/dist/styles/tokens/light-dark.css +1 -1
  329. package/dist/styles/tokens/offsets.css +27 -0
  330. package/dist/styles/tokens/property-regs.css +133 -0
  331. package/dist/styles/tokens/scale-paper.css +73 -29
  332. package/dist/styles/tokens/scheme-motion.css +44 -6
  333. package/dist/styles/tokens/sizing-config.css +110 -0
  334. package/dist/styles/tokens/sizing.css +55 -104
  335. package/dist/styles/tokens.css +5 -0
  336. package/dist/styles/typography/semantic.css +18 -5
  337. package/dist/styles/utilities/a11y-overrides.css +20 -5
  338. package/dist/styles/utilities/base-misc.css +52 -0
  339. package/dist/styles/utilities/btn.css +14 -3
  340. package/dist/styles/utilities/components.css +31 -6
  341. package/dist/styles/utilities/metal.css +26 -0
  342. package/dist/switch.js +1 -1
  343. package/dist/tabs.js +8 -8
  344. package/dist/timeline.js +1 -1
  345. package/dist/toast.js +1 -1
  346. package/dist/toggle-chip.js +10 -10
  347. package/dist/toggle-group.js +1 -1
  348. package/dist/tooltip.js +1 -1
  349. package/dist/typewriter.js +1 -1
  350. package/dist/uniformBridgeWGPU-CtAKl45L.js +1204 -0
  351. package/dist/{useAnimatedNumber-BfUq2bUM.js → useAnimatedNumber-CLrxicG9.js} +1 -1
  352. package/dist/{useConfiguratorState-DNlOh6c8.js → useConfiguratorState-4xblKfwd.js} +25 -24
  353. package/dist/useControlSize-SH1UmJCi.js +9 -0
  354. package/dist/useDockCtaReceive-DfFkmgL1.js +82 -0
  355. package/dist/{useDragMorph-DgxnsVJz.js → useDragMorph-BUgAC-zK.js} +4 -4
  356. package/dist/useFuzzySearch-DIhcYtcw.js +177 -0
  357. package/dist/useGpuSubstrate-4pTcp6mX.js +294 -0
  358. package/dist/{useLiquidPress-kfb4KX79.js → useLiquidPress-BooG97RY.js} +2 -2
  359. package/dist/usePointerVelocityField-QLsy3_kv.js +91 -0
  360. package/dist/useScrollChrome-D66AVP7C.js +258 -0
  361. package/dist/{useSpringMount-q1amq1SJ.js → useSpringMount-BWDnKIwh.js} +1 -1
  362. package/dist/useSpringPress-B1-Czp-V.js +36 -0
  363. package/dist/useViewTransition-CUI1nAgn.js +95 -0
  364. package/dist/{vendor-CKmzio-i.js → vendor-B2qOlYY3.js} +24 -11
  365. package/dist/virtual.d.ts +1 -0
  366. package/dist/virtual.js +225 -0
  367. package/dist/watercolor-dot.js +116 -73
  368. package/package.json +127 -7
  369. package/src/styles/animations.css +13 -3
  370. package/src/styles/cards.css +69 -0
  371. package/src/styles/completion-seal.css +131 -0
  372. package/src/styles/configurator.css +55 -0
  373. package/src/styles/critical-partition.mjs +33 -11
  374. package/src/styles/dock/cta-seat.css +87 -0
  375. package/src/styles/dock/density.css +153 -0
  376. package/src/styles/dock/layers.css +55 -7
  377. package/src/styles/dock/morph-bridge.css +54 -18
  378. package/src/styles/dock/morph.css +41 -33
  379. package/src/styles/dock/overflow.css +12 -0
  380. package/src/styles/dock/search.css +68 -0
  381. package/src/styles/dock/shape.css +124 -0
  382. package/src/styles/dock/shell.css +23 -5
  383. package/src/styles/dock/stack-rail.css +264 -0
  384. package/src/styles/dock-controls/dark-mode-toggle.css +17 -4
  385. package/src/styles/dock-controls/icon-button.css +14 -0
  386. package/src/styles/dock.css +11 -1
  387. package/src/styles/glass/accent-tone.css +66 -0
  388. package/src/styles/glass/control-surfaces.css +167 -0
  389. package/src/styles/glass/ladder.css +67 -17
  390. package/src/styles/glass/rim.css +19 -9
  391. package/src/styles/glass/surfaces.css +69 -148
  392. package/src/styles/glass.css +10 -0
  393. package/src/styles/index.css +15 -0
  394. package/src/styles/scroll-chrome.css +123 -0
  395. package/src/styles/scroll-driven.css +38 -0
  396. package/src/styles/segmented-tabs.css +50 -14
  397. package/src/styles/theme/bridges.css +22 -0
  398. package/src/styles/theme/radius.css +18 -1
  399. package/src/styles/tokens/color-radius.css +13 -3
  400. package/src/styles/tokens/dark-arm.css +39 -6
  401. package/src/styles/tokens/glass-deep.css +28 -3
  402. package/src/styles/tokens/glass-fx.css +44 -1
  403. package/src/styles/tokens/glass.css +91 -31
  404. package/src/styles/tokens/light-dark.css +1 -1
  405. package/src/styles/tokens/offsets.css +27 -0
  406. package/src/styles/tokens/property-regs.css +133 -0
  407. package/src/styles/tokens/scale-paper.css +73 -29
  408. package/src/styles/tokens/scheme-motion.css +44 -6
  409. package/src/styles/tokens/sizing-config.css +110 -0
  410. package/src/styles/tokens/sizing.css +55 -104
  411. package/src/styles/tokens.css +5 -0
  412. package/src/styles/typography/semantic.css +18 -5
  413. package/src/styles/utilities/a11y-overrides.css +20 -5
  414. package/src/styles/utilities/base-misc.css +52 -0
  415. package/src/styles/utilities/btn.css +14 -3
  416. package/src/styles/utilities/components.css +31 -6
  417. package/src/styles/utilities/metal.css +26 -0
  418. package/dist/ContextMenuContent-uWnVxDab.js +0 -85
  419. package/dist/DialogFooter-BZNX5aVr.js +0 -165
  420. package/dist/HoverCardContent-b2uaAMRR.js +0 -83
  421. package/dist/Input-h9v5LeXf.js +0 -55
  422. package/dist/NumberFieldContent-Cq7EzX-U.js +0 -138
  423. package/dist/Separator-pKF0oA4M.js +0 -37
  424. package/dist/Switch-CwYNf8bo.js +0 -47
  425. package/dist/TooltipProvider-rzvnXz60.js +0 -104
  426. package/dist/color-DweYl7pE.js +0 -86
  427. package/dist/components/custom/constellation/composables/useConstellationPointer.d.ts +0 -35
  428. package/dist/components/custom/constellation/constellationDraw.d.ts +0 -30
  429. package/dist/components/custom/dock/DockRail.vue.d.ts +0 -89
  430. package/dist/createCanvasLifecycle-CHD5XrDW.js +0 -82
  431. package/dist/procedural-color.wgsl-CToRHugY.js +0 -224
  432. package/dist/resolveCanvasColor-CUyHr5Uu.js +0 -11
  433. package/dist/styles/dock/rail-extend.css +0 -397
  434. package/dist/usePointerVelocityField-JbRd5CrM.js +0 -137
  435. package/dist/useRAFLoop-UYa4zoiN.js +0 -109
  436. package/dist/useSpringPress-BsqPr7FJ.js +0 -34
  437. package/src/styles/dock/rail-extend.css +0 -397
  438. /package/dist/{FadingScroll-DI6hQhT9.js → FadingScroll-DLRbH5Xr.js} +0 -0
  439. /package/dist/{HoverPopover-CbqbNwgU.js → HoverPopover-BcIxvyqZ.js} +0 -0
  440. /package/dist/{InstrumentChassis-Bx0F_q5g.js → InstrumentChassis-CxsHSyMj.js} +0 -0
  441. /package/dist/{PaperBackdrop-Vf3tlpvd.js → PaperBackdrop-CqwjnfLv.js} +0 -0
  442. /package/dist/{Progress-DctG61iZ.js → Progress-CnqB7gLm.js} +0 -0
  443. /package/dist/{ScrollingText-yOpBzFYq.js → ScrollingText-CTZbA_cG.js} +0 -0
  444. /package/dist/{SelectGroup-DwwjicPY.js → SelectGroup-BFiod7X2.js} +0 -0
  445. /package/dist/{compile-CQEFRTmx.js → compile-nZ1xVYTp.js} +0 -0
  446. /package/dist/{constants-BPOqYJAm.js → constants--C2DkLW8.js} +0 -0
  447. /package/dist/{math-BINYmg5z.js → math-Eb0w3LqU.js} +0 -0
  448. /package/dist/{prng-Za0Rmgag.js → prng-B-d9eYX8.js} +0 -0
  449. /package/dist/{slider-DVb4HXU-.js → slider-2A0rPn79.js} +0 -0
  450. /package/dist/{useGlobalDark-C28t0VWJ.js → useGlobalDark-CmjB9E32.js} +0 -0
  451. /package/dist/{useIntersectionPause-Bj4sPkMh.js → useIntersectionPause-Dbozzjgm.js} +0 -0
  452. /package/dist/{useInterval-CvK1mL92.js → useInterval-CNdua40W.js} +0 -0
  453. /package/dist/{useKeyboardShortcuts-BXWXOZ-9.js → useKeyboardShortcuts-BPRp33Im.js} +0 -0
  454. /package/dist/{useLiquidFlex-mZPMiNXh.js → useLiquidFlex-UmA6LMZu.js} +0 -0
  455. /package/dist/{useScrollProgress-D7bYU2RK.js → useScrollProgress-c3yxmH6a.js} +0 -0
  456. /package/dist/{useSortable-DHjtZSEd.js → useSortable-BVqlJRBR.js} +0 -0
  457. /package/dist/{useTextHighlight-CWEi25hf.js → useTextHighlight-NmBM5V_4.js} +0 -0
  458. /package/dist/{vReveal-Czsb7zQC.js → vReveal-D9k0jADx.js} +0 -0
  459. /package/dist/{vSpecular-CQFmLNzA.js → vSpecular-EX7loENl.js} +0 -0
@@ -27,9 +27,9 @@ export interface ConcentricHandle {
27
27
  dispose: () => void;
28
28
  }
29
29
  /**
30
- * Mount the concentric renderer on `canvasRef`. The WebGPU primary + the WebGL2 fallback
31
- * are BOTH pure fullscreen fragment passes evaluating the SAME radial-Fourier field (the
32
- * ONE math source `ringField.ts`), so the picker is the only seam. Returns the uniform
33
- * lifecycle handle.
30
+ * Mount the concentric renderer on `canvasRef`. The WebGPU primary + the WebGL2 fallback are
31
+ * BOTH pure fullscreen fragment passes evaluating the SAME radial-Fourier field (the ONE
32
+ * math source `ringField.ts`), so the picker is the only seam. Returns the uniform lifecycle
33
+ * handle.
34
34
  */
35
35
  export declare function useConcentric(canvasRef: Ref<HTMLCanvasElement | null>, options: UseConcentricOptions): ConcentricHandle;
@@ -6,6 +6,10 @@ export declare const MAX_RINGS = 8;
6
6
  export declare const MAX_CENTERS = 4;
7
7
  /** Compile-time palette cap — mirrors the WGSL `MAX_RING_STOPS` #define. */
8
8
  export declare const MAX_RING_STOPS = 4;
9
+ /** The render mode — traveling crest-lines, static elevation-contour, or both. */
10
+ export type ConcentricRenderMode = "traveling-rings" | "static-contour" | "both";
11
+ /** Map a render mode to the shader int (the uniform `ints.w` lane). */
12
+ export declare function renderModeToInt(mode: ConcentricRenderMode): number;
9
13
  /**
10
14
  * The full author schema — the studio's `useConfiguratorState` model. Every field is a
11
15
  * tunable the demo configurator drives; the SFC resolves it into the uniform table.
@@ -13,12 +17,22 @@ export declare const MAX_RING_STOPS = 4;
13
17
  export interface ConcentricConfig {
14
18
  /** The ring origins (1..MAX_CENTERS) — a multi-center sum produces ring interference. */
15
19
  centers: RingCenter[];
16
- /** The radial sum-of-sines table (1..MAX_RINGS). */
20
+ /** The clean radial sum-of-sines table (1..2 frequencies — NOT a turbulence ladder). */
17
21
  ringComponents: RingComponent[];
18
- /** The ellipsoidal-norm axis ratio (a, b) — the 3D-tilt depth implication. */
22
+ /** The ellipsoidal-norm axis ratio (a, b) — the tilted-disc depth implication. */
19
23
  axisRatio: [number, number];
20
24
  /** The ring-travel speed (scales ω). */
21
25
  speed: number;
26
+ /** The stroke half-width (field-distance units; the IQ line thickness). */
27
+ lineWidth: number;
28
+ /** The stroke AA softness (field-distance units; the edge feather). */
29
+ lineSoftness: number;
30
+ /** The render mode — traveling crest-lines · static elevation-contour · both. */
31
+ renderMode: ConcentricRenderMode;
32
+ /** The contour-level count for the static-contour mode (4..24). */
33
+ contourLevels: number;
34
+ /** The beat detune — the second ring's wavelength offset that makes the families BEAT. */
35
+ beatDetune: number;
22
36
  /** The field-value color ramp (the demo themes it); resolved via the ColorResolver. */
23
37
  palette: OklchStop[];
24
38
  /** The ground color (default transparent so it reads over the page; demo sets it). */
@@ -31,13 +45,23 @@ export interface ConcentricConfig {
31
45
  /**
32
46
  * The warm-cream identity palette (the library default — NOT a themed hue). A three-stop
33
47
  * warm ramp over the warm-cream foreground family, resolved via the ColorResolver: a soft
34
- * cream trough, a warm amber mid, a deeper ember crest — so the ring field reads as warm
48
+ * cream trough, a warm amber mid, a deeper ember crest — so the ring LINES read as warm
35
49
  * light interference. A consumer (the demo) themes it through a PRESET, never a token edit.
36
50
  */
37
51
  export declare const WARM_IDENTITY_PALETTE: OklchStop[];
38
- /** The default 5-octave Phillips radial ring ladder. */
52
+ /**
53
+ * Build the default clean beating ring table — one base ring + a slightly-detuned twin so
54
+ * the field BEATS into a low-frequency moiré envelope (the "distinct waves"). NOT the
55
+ * retired 5-octave Phillips turbulence ladder.
56
+ */
57
+ export declare function buildDefaultRingComponents(baseWavelength?: number, beatDetune?: number): RingComponent[];
58
+ /** The default clean beating ring table (2 detuned low-frequency rings). */
39
59
  export declare const DEFAULT_RING_COMPONENTS: RingComponent[];
40
- /** Two ring families offset on the diagonal — the default interference (a moiré beat). */
60
+ /**
61
+ * Two ring FAMILIES offset on the diagonal at different tilts — the default interference: a
62
+ * moiré BEAT where the two tilted-ellipsoid families cross (the literal "ellipsoid lines
63
+ * forming distinct waves").
64
+ */
41
65
  export declare const DEFAULT_CENTERS: RingCenter[];
42
- /** The shipped warm-identity default config. */
66
+ /** The shipped warm-identity default config — thin bright LINES that beat into waves. */
43
67
  export declare const DEFAULT_CONCENTRIC_CONFIG: ConcentricConfig;
@@ -1,5 +1,5 @@
1
1
  export { default as Concentric } from "./Concentric.vue";
2
2
  export { useConcentric, type ConcentricHandle, type UseConcentricOptions, } from "./composables/useConcentric";
3
- export { type ConcentricConfig, DEFAULT_CONCENTRIC_CONFIG, DEFAULT_RING_COMPONENTS, DEFAULT_CENTERS, WARM_IDENTITY_PALETTE, MAX_RINGS, MAX_CENTERS, MAX_RING_STOPS, } from "./constants";
4
- export { type RingComponent, type RingCenter, type Vec2, sampleRingField, ellipsoidalRadius, buildRingLadder, RING_GRAVITY, } from "./composables/ringField";
3
+ export { type ConcentricConfig, type ConcentricRenderMode, renderModeToInt, DEFAULT_CONCENTRIC_CONFIG, DEFAULT_RING_COMPONENTS, DEFAULT_CENTERS, WARM_IDENTITY_PALETTE, buildDefaultRingComponents, MAX_RINGS, MAX_CENTERS, MAX_RING_STOPS, } from "./constants";
4
+ export { type RingComponent, type RingCenter, type Vec2, sampleRingField, ringIsolineInk, ellipsoidalRadius, ellipsoidalRadiusRot, ellipsoidalGradMag, buildRingFamily, RING_GRAVITY, } from "./composables/ringField";
5
5
  export type { OklchStop } from "../../../composables/color";
@@ -1,4 +1,4 @@
1
1
  /** The full-screen-triangle vertex shader (the substrate's standard fullscreen pass). */
2
2
  export declare const CONCENTRIC_VERT_GLSL = "#version 300 es\nprecision highp float;\nin vec2 aPosition;\nout vec2 vUv;\nvoid main() {\n vUv = aPosition; // [-1,1]\u00B2 domain\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}";
3
- /** The concentric fragment source — the aurora-class radial-Fourier field. */
4
- export declare const CONCENTRIC_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\n#define PI 3.141592653589793\n#define TAU 6.283185307179586\n#define RING_GRAVITY 9.81\n#define MAX_RINGS 8\n#define MAX_CENTERS 4\n#define MAX_RING_STOPS 4\n\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform float uTime;\nuniform float uSpeed;\nuniform vec2 uAxis; // (a, b) ellipsoidal-norm axis ratio\nuniform float uFieldNorm; // field \u2192 [0,1] amplitude scale\nuniform float uAspect;\nuniform int uCenterCount;\nuniform int uRingCount;\nuniform int uStopCount;\nuniform float uHasBackground;\nuniform vec3 uRings[MAX_RINGS]; // (amplitude, wavelength, phase)\nuniform vec3 uCenters[MAX_CENTERS]; // (x, y, weight)\nuniform vec3 uPalette[MAX_RING_STOPS]; // linear-sRGB stops\n\n\nfloat srgbToLinearCh(float c) {\n return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n}\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfloat linearToSrgbCh(float c) {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nvec3 linearToSrgb(vec3 c) {\n return vec3(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS (constants.ts), row-major; written here as GLSL\n// columns (= the transpose) so mat3 * vec3 evaluates the row-major M\u00B7v.\nconst mat3 LINEAR_SRGB_TO_LMS = mat3(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients (gamut.ts lines 295-297 \u2014\n// these differ at the ~1e-9 digit from LMS_TO_OKLAB_MATRIX; use the inline ones to\n// mirror the exact value.js path), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_OKLAB = mat3(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF (constants.ts), row-major \u2192 GLSL columns. Rows:\n// l = [1, 0.3963377774, 0.2158037573], m = [1, -0.1055613458, -0.0638541728],\n// s = [1, -0.0894841775, -1.2914855480].\nconst mat3 OKLAB_TO_LMS = mat3(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB (constants.ts), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_LINEAR_SRGB = mat3(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nvec3 srgbToOklab(vec3 c) {\n vec3 lin = srgbToLinear(c);\n vec3 lms = LINEAR_SRGB_TO_LMS * lin;\n vec3 lmsCbrt = sign(lms) * pow(abs(lms), vec3(1.0 / 3.0));\n return LMS_TO_OKLAB * lmsCbrt;\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nvec3 oklabToLinearSrgb(vec3 lab) {\n vec3 lms_ = OKLAB_TO_LMS * lab;\n vec3 lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS. Mirrors value.js rawOklabToOklch (which returns\n// degrees; we stay in radians and only fold to [0, 2pi)).\nvec3 oklabToOklch(vec3 lab) {\n float C = length(lab.yz);\n float H = atan(lab.z, lab.y);\n if (H < 0.0) H += 2.0 * PI;\n return vec3(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nvec3 oklchToOklab(vec3 lch) {\n return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// \u2016p \u2212 c\u2016_e = sqrt((dx/a)\u00B2 + (dy/b)\u00B2) \u2014 transcribes ringField.ts ellipsoidalRadius.\nfloat ellipsoidalRadius(vec2 p, vec2 center, float axisA, float axisB) {\n float dx = (p.x - center.x) / max(axisA, 1e-4);\n float dy = (p.y - center.y) / max(axisB, 1e-4);\n return sqrt(dx * dx + dy * dy);\n}\n\n// f(p,t) \u2014 the multi-center weighted radial sum (transcribes ringField.ts sampleRingField).\nfloat sampleRingField(vec2 p, float t) {\n float acc = 0.0;\n for (int j = 0; j < MAX_CENTERS; j++) {\n if (j >= uCenterCount) break;\n vec3 cj = uCenters[j];\n float radius = ellipsoidalRadius(p, cj.xy, uAxis.x, uAxis.y);\n float centerSum = 0.0;\n for (int i = 0; i < MAX_RINGS; i++) {\n if (i >= uRingCount) break;\n vec3 r = uRings[i];\n float k = TAU / max(r.y, 1e-4);\n float omega = sqrt(RING_GRAVITY * k) * uSpeed;\n float theta = k * radius - omega * t + r.z;\n centerSum += r.x * sin(theta);\n }\n acc += centerSum * cj.z;\n }\n return acc;\n}\n\n// Sample the multi-stop palette (linear-sRGB stops, OKLab mix). t in [0,1].\nvec3 samplePaletteLin(float t) {\n if (uStopCount <= 1) return uPalette[0];\n float n = float(uStopCount);\n float ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n int i0 = int(floor(ft));\n int i1 = min(i0 + 1, uStopCount - 1);\n float f = ft - float(i0);\n // cube-root LMS (the GLSL chunk inlines cbrt as sign(x)\u00B7pow(|x|,1/3) \u2014 no cbrt3 fn).\n vec3 lmsA = LINEAR_SRGB_TO_LMS * uPalette[i0];\n vec3 lmsB = LINEAR_SRGB_TO_LMS * uPalette[i1];\n vec3 labA = LMS_TO_OKLAB * (sign(lmsA) * pow(abs(lmsA), vec3(1.0 / 3.0)));\n vec3 labB = LMS_TO_OKLAB * (sign(lmsB) * pow(abs(lmsB), vec3(1.0 / 3.0)));\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\nvoid main() {\n float aspect = max(uAspect, 1e-4);\n vec2 p = vec2(vUv.x * aspect, vUv.y);\n float raw = sampleRingField(p, uTime);\n float v = clamp(0.5 + raw * uFieldNorm, 0.0, 1.0);\n vec3 lin = samplePaletteLin(v);\n vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));\n if (uHasBackground > 0.5) {\n fragColor = vec4(rgb, 1.0);\n return;\n }\n float alpha = clamp(v * 0.92 + 0.08, 0.0, 1.0);\n fragColor = vec4(rgb * alpha, alpha);\n}";
3
+ /** The concentric fragment source — the aurora-class radial-Fourier isoline render. */
4
+ export declare const CONCENTRIC_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\n#define PI 3.141592653589793\n#define TAU 6.283185307179586\n#define RING_GRAVITY 9.81\n#define MAX_RINGS 8\n#define MAX_CENTERS 4\n#define MAX_RING_STOPS 4\n\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform float uTime;\nuniform float uSpeed;\nuniform vec2 uAxis; // (a, b) ellipsoidal-norm axis ratio\nuniform float uFieldNorm; // field \u2192 [0,1] amplitude scale\nuniform float uAspect;\nuniform int uCenterCount;\nuniform int uRingCount;\nuniform int uStopCount;\nuniform int uRenderMode; // 0 traveling-rings \u00B7 1 static-contour \u00B7 2 both\nuniform float uHasBackground;\nuniform vec3 uLine; // (lineHalfWidth, aaSoftness, contourLevels) \u2014 stroke geometry\nuniform vec3 uBg; // themed background (linear-sRGB)\nuniform vec3 uRings[MAX_RINGS]; // (amplitude, wavelength, phase)\nuniform vec4 uCenters[MAX_CENTERS]; // (x, y, weight, rotAlpha)\nuniform vec3 uPalette[MAX_RING_STOPS]; // linear-sRGB stops\n\n\nfloat srgbToLinearCh(float c) {\n return c <= 0.04045 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);\n}\nvec3 srgbToLinear(vec3 c) {\n return vec3(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfloat linearToSrgbCh(float c) {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nvec3 linearToSrgb(vec3 c) {\n return vec3(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS (constants.ts), row-major; written here as GLSL\n// columns (= the transpose) so mat3 * vec3 evaluates the row-major M\u00B7v.\nconst mat3 LINEAR_SRGB_TO_LMS = mat3(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients (gamut.ts lines 295-297 \u2014\n// these differ at the ~1e-9 digit from LMS_TO_OKLAB_MATRIX; use the inline ones to\n// mirror the exact value.js path), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_OKLAB = mat3(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF (constants.ts), row-major \u2192 GLSL columns. Rows:\n// l = [1, 0.3963377774, 0.2158037573], m = [1, -0.1055613458, -0.0638541728],\n// s = [1, -0.0894841775, -1.2914855480].\nconst mat3 OKLAB_TO_LMS = mat3(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB (constants.ts), row-major \u2192 GLSL columns.\nconst mat3 LMS_TO_LINEAR_SRGB = mat3(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nvec3 srgbToOklab(vec3 c) {\n vec3 lin = srgbToLinear(c);\n vec3 lms = LINEAR_SRGB_TO_LMS * lin;\n vec3 lmsCbrt = sign(lms) * pow(abs(lms), vec3(1.0 / 3.0));\n return LMS_TO_OKLAB * lmsCbrt;\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nvec3 oklabToLinearSrgb(vec3 lab) {\n vec3 lms_ = OKLAB_TO_LMS * lab;\n vec3 lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS. Mirrors value.js rawOklabToOklch (which returns\n// degrees; we stay in radians and only fold to [0, 2pi)).\nvec3 oklabToOklch(vec3 lab) {\n float C = length(lab.yz);\n float H = atan(lab.z, lab.y);\n if (H < 0.0) H += 2.0 * PI;\n return vec3(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nvec3 oklchToOklab(vec3 lch) {\n return vec3(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// rotated ellipsoidal radius \u2014 transcribes ringField.ts ellipsoidalRadiusRot.\nfloat ellipsoidalRadiusRot(vec2 p, vec2 center, float rotAlpha, float axisA, float axisB) {\n float ca = cos(rotAlpha);\n float sa = sin(rotAlpha);\n float px = p.x - center.x;\n float py = p.y - center.y;\n float rx = ca * px + sa * py;\n float ry = -sa * px + ca * py;\n float dx = rx / max(axisA, 1e-4);\n float dy = ry / max(axisB, 1e-4);\n return sqrt(dx * dx + dy * dy);\n}\n\n// |\u2207r| of the rotated ellipsoidal radius \u2014 transcribes ringField.ts ellipsoidalGradMag.\nfloat ellipsoidalGradMag(vec2 p, vec2 center, float rotAlpha, float axisA, float axisB) {\n float ca = cos(rotAlpha);\n float sa = sin(rotAlpha);\n float px = p.x - center.x;\n float py = p.y - center.y;\n float rx = ca * px + sa * py;\n float ry = -sa * px + ca * py;\n float a = max(axisA, 1e-4);\n float b = max(axisB, 1e-4);\n float sx = rx / a;\n float sy = ry / b;\n float r = sqrt(sx * sx + sy * sy);\n float gx = sx / a;\n float gy = sy / b;\n return sqrt(gx * gx + gy * gy) / max(r, 1e-4);\n}\n\n// f(p,t) \u2014 the multi-center weighted radial sum (transcribes ringField.ts sampleRingField).\nfloat sampleRingField(vec2 p, float t) {\n float acc = 0.0;\n for (int j = 0; j < MAX_CENTERS; j++) {\n if (j >= uCenterCount) break;\n vec4 cj = uCenters[j];\n float radius = ellipsoidalRadiusRot(p, cj.xy, cj.w, uAxis.x, uAxis.y);\n float centerSum = 0.0;\n for (int i = 0; i < MAX_RINGS; i++) {\n if (i >= uRingCount) break;\n vec3 r = uRings[i];\n float k = TAU / max(r.y, 1e-4);\n float omega = sqrt(RING_GRAVITY * k) * uSpeed;\n float theta = k * radius - omega * t + r.z;\n centerSum += r.x * sin(theta);\n }\n acc += centerSum * cj.z;\n }\n return acc;\n}\n\n// The IQ gradient-normalized isoline ink + the beat envelope (transcribes ringIsolineInk).\n// Returns vec2(ink, env).\nvec2 ringIsolineInk(vec2 p, float t) {\n float ink = 0.0;\n float env = 0.0;\n float lineHalfW = uLine.x;\n float aa = uLine.y;\n for (int j = 0; j < MAX_CENTERS; j++) {\n if (j >= uCenterCount) break;\n vec4 cj = uCenters[j];\n float radius = ellipsoidalRadiusRot(p, cj.xy, cj.w, uAxis.x, uAxis.y);\n float gradR = ellipsoidalGradMag(p, cj.xy, cj.w, uAxis.x, uAxis.y);\n for (int i = 0; i < MAX_RINGS; i++) {\n if (i >= uRingCount) break;\n vec3 r = uRings[i];\n float k = TAU / max(r.y, 1e-4);\n float omega = sqrt(RING_GRAVITY * k) * uSpeed;\n float phase = k * radius - omega * t + r.z;\n float s = sin(phase);\n float cphase = abs(cos(phase));\n float gradPhase = max(k * gradR, 1e-4);\n // The IQ gradient-normalized distance-to-isoline (domain units; round-trips JS).\n float de = abs(s) / max(cphase * gradPhase, 1e-4);\n // Convert to PIXELS via fwidth(phase) so the stroke is a constant pixel width.\n float dPx = max(fwidth(phase), 1e-4);\n float dePx = de * gradPhase / dPx;\n float lineV = 1.0 - smoothstep(lineHalfW, lineHalfW + aa, dePx);\n // Analytic anti-aliasing: fade lines where the rings pack tighter than a pixel can\n // resolve (fwidth(phase) \u2273 \u03C0, near a center / under DPR) so the field stays thin LINES\n // instead of flooding to a bright slab (IQ filterwidth).\n float aliasFade = 1.0 - smoothstep(PI * 0.6, PI * 1.2, dPx);\n lineV *= aliasFade;\n float w = r.x * cj.z;\n ink = max(ink, lineV * w);\n env += s * w;\n }\n }\n return vec2(clamp(ink, 0.0, 1.0), env);\n}\n\n// The topographic-contour operator (transcribes contourInk).\nfloat contourInk(float envValue, float levels) {\n float fN = envValue * levels;\n float band = abs(fract(fN + 0.5) - 0.5);\n float aaW = max(fwidth(fN), 1e-4);\n return 1.0 - smoothstep(uLine.x, uLine.x + uLine.y, band / aaW);\n}\n\nvec3 samplePaletteLin(float t) {\n if (uStopCount <= 1) return uPalette[0];\n float n = float(uStopCount);\n float ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n int i0 = int(floor(ft));\n int i1 = min(i0 + 1, uStopCount - 1);\n float f = ft - float(i0);\n vec3 lmsA = LINEAR_SRGB_TO_LMS * uPalette[i0];\n vec3 lmsB = LINEAR_SRGB_TO_LMS * uPalette[i1];\n vec3 labA = LMS_TO_OKLAB * (sign(lmsA) * pow(abs(lmsA), vec3(1.0 / 3.0)));\n vec3 labB = LMS_TO_OKLAB * (sign(lmsB) * pow(abs(lmsB), vec3(1.0 / 3.0)));\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\nvoid main() {\n float aspect = max(uAspect, 1e-4);\n vec2 p = vec2(vUv.x * aspect, vUv.y);\n\n vec2 ie = ringIsolineInk(p, uTime);\n float ink = ie.x;\n float env = ie.y;\n\n if (uRenderMode == 1) {\n ink = contourInk(env * uFieldNorm, max(uLine.z, 1.0));\n } else if (uRenderMode == 2) {\n ink = max(ink, contourInk(env * uFieldNorm, max(uLine.z, 1.0)));\n }\n ink = clamp(ink, 0.0, 1.0);\n\n // The beat-envelope drives the warm-family tone across the ramp (cream\u2194amber\u2194ember) so the\n // crossing families read as warm-light interference (the warm-cream identity).\n float v = clamp(0.5 + env * uFieldNorm, 0.0, 1.0);\n vec3 lin = samplePaletteLin(v);\n vec3 rgb = clamp(linearToSrgb(lin), vec3(0.0), vec3(1.0));\n\n if (uHasBackground > 0.5) {\n vec3 bg = clamp(linearToSrgb(uBg), vec3(0.0), vec3(1.0));\n fragColor = vec4(mix(bg, rgb, ink), 1.0);\n return;\n }\n float alpha = ink;\n fragColor = vec4(rgb * alpha, alpha);\n}";
@@ -1 +1 @@
1
- export declare const CONCENTRIC_WGSL = "\nconst PI: f32 = 3.141592653589793;\nconst TAU: f32 = 6.283185307179586;\nconst RING_GRAVITY: f32 = 9.81;\nconst MAX_RINGS: i32 = 8;\nconst MAX_CENTERS: i32 = 4;\nconst MAX_RING_STOPS: i32 = 4;\n\n// \u2500\u2500 Concentric uniforms (the typed-struct source-of-truth \u2014 see uniformBridgeWGPU.ts) \u2500\u2500\nstruct ConcentricUniforms {\n // u0: (uTime, uSpeed, uAxisA, uAxisB)\n u0: vec4<f32>,\n // ints: (uCenterCount, uRingCount, uStopCount, _pad)\n ints: vec4<i32>,\n // bg: (background.rgb (linear), hasBackground)\n bg: vec4<f32>,\n // norm: (uFieldNorm, uAspect, _pad, _pad) \u2014 field \u2192 [0,1] scale\n norm: vec4<f32>,\n // each ring row: (amplitude, wavelength, phase, _pad)\n rings: array<vec4<f32>, 8>,\n // each center row: (x, y, weight, _pad)\n centers: array<vec4<f32>, 4>,\n // each palette stop: linear-sRGB rgb + _pad\n palette: array<vec4<f32>, 4>,\n};\n\n@group(0) @binding(0) var<uniform> u: ConcentricUniforms;\n\n\nfn srgbToLinearCh(c: f32) -> f32 {\n if (c <= 0.04045) { return c / 12.92; }\n return pow((c + 0.055) / 1.055, 2.4);\n}\nfn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfn linearToSrgbCh(c: f32) -> f32 {\n if (c <= 0.0031308) { return c * 12.92; }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nfn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS, row-major \u2192 WGSL columns (= the transpose).\nconst LINEAR_SRGB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients, row-major \u2192 WGSL columns.\nconst LMS_TO_OKLAB: mat3x3<f32> = mat3x3<f32>(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF, row-major \u2192 WGSL columns.\nconst OKLAB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB, row-major \u2192 WGSL columns.\nconst LMS_TO_LINEAR_SRGB: mat3x3<f32> = mat3x3<f32>(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\nfn cbrt3(v: vec3<f32>) -> vec3<f32> {\n return sign(v) * pow(abs(v), vec3<f32>(1.0 / 3.0));\n}\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nfn srgbToOklab(c: vec3<f32>) -> vec3<f32> {\n let lin = srgbToLinear(c);\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nfn oklabToLinearSrgb(lab: vec3<f32>) -> vec3<f32> {\n let lms_ = OKLAB_TO_LMS * lab;\n let lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS, folded to [0, 2pi). Mirrors value.js rawOklabToOklch.\nfn oklabToOklch(lab: vec3<f32>) -> vec3<f32> {\n let C = length(lab.yz);\n var H = atan2(lab.z, lab.y);\n if (H < 0.0) { H = H + 2.0 * PI; }\n return vec3<f32>(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nfn oklchToOklab(lch: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// Full-screen-triangle (the pilot idiom): NDC corners (-1,-1),(3,-1),(-1,3) cover the\n// viewport from a single 3-vertex draw \u2014 no vertex buffer.\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>, // domain [-1,1]\u00B2, aspect-corrected x\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n var corners = array<vec2<f32>, 3>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(3.0, -1.0), vec2<f32>(-1.0, 3.0),\n );\n let c = corners[vi];\n var out: VSOut;\n out.pos = vec4<f32>(c, 0.0, 1.0);\n // aspect-correct so the rings stay circular under the ellipsoidal norm (NOT squashed\n // by the canvas aspect): widen the domain x by the aspect ratio.\n out.uv = vec2<f32>(c.x, c.y);\n return out;\n}\n\n// The ellipsoidal radial distance \u2016p \u2212 c\u2016_e = sqrt((dx/a)\u00B2 + (dy/b)\u00B2). The single radial\n// metric (transcribes ringField.ts ellipsoidalRadius).\nfn ellipsoidalRadius(p: vec2<f32>, center: vec2<f32>, axisA: f32, axisB: f32) -> f32 {\n let dx = (p.x - center.x) / max(axisA, 1e-4);\n let dy = (p.y - center.y) / max(axisB, 1e-4);\n return sqrt(dx * dx + dy * dy);\n}\n\n// The radial-Fourier ring-interference value f(p,t) \u2014 the multi-center weighted sum of\n// radial sinusoids (transcribes ringField.ts sampleRingField line-for-line).\nfn sampleRingField(p: vec2<f32>, t: f32) -> f32 {\n var acc = 0.0;\n let speed = u.u0.y;\n let axisA = u.u0.z;\n let axisB = u.u0.w;\n let centerCount = u.ints.x;\n let ringCount = u.ints.y;\n for (var j = 0; j < MAX_CENTERS; j = j + 1) {\n if (j >= centerCount) { break; }\n let cj = u.centers[j];\n let radius = ellipsoidalRadius(p, cj.xy, axisA, axisB);\n var centerSum = 0.0;\n for (var i = 0; i < MAX_RINGS; i = i + 1) {\n if (i >= ringCount) { break; }\n let r = u.rings[i];\n let k = TAU / max(r.y, 1e-4);\n // \u03C9 = \u221A(g\u00B7k); speed scales the travel (the shared dispersion law).\n let omega = sqrt(RING_GRAVITY * k) * speed;\n let theta = k * radius - omega * t + r.z;\n centerSum = centerSum + r.x * sin(theta);\n }\n acc = acc + centerSum * cj.z;\n }\n return acc;\n}\n\n// Sample the multi-stop palette (linear-sRGB stops, OKLab mix). t in [0,1].\nfn samplePaletteLin(t: f32) -> vec3<f32> {\n let stopCount = u.ints.z;\n if (stopCount <= 1) { return u.palette[0].rgb; }\n let n = f32(stopCount);\n let ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n let i0 = i32(floor(ft));\n let i1 = min(i0 + 1, stopCount - 1);\n let f = ft - f32(i0);\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i0].rgb);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i1].rgb);\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n // aspect-correct the domain x so the rings read circular under the ellipsoidal norm.\n let aspect = max(u.norm.y, 1e-4);\n let p = vec2<f32>(in.uv.x * aspect, in.uv.y);\n let t = u.u0.x;\n\n let raw = sampleRingField(p, t);\n // Normalize the field \u2192 [0,1] for the palette ramp (uFieldNorm is the amplitude scale).\n let v = clamp(0.5 + raw * u.norm.x, 0.0, 1.0);\n\n let lin = samplePaletteLin(v);\n let rgb = clamp(linearToSrgb(lin), vec3<f32>(0.0), vec3<f32>(1.0));\n\n // Premultiplied-alpha output over the (transparent / themed) ground.\n let hasBg = u.bg.w;\n if (hasBg > 0.5) {\n // opaque themed ground: the field paints fully opaque.\n return vec4<f32>(rgb, 1.0);\n }\n // transparent ground: the field's alpha rides its own brightness so the page reads\n // through the troughs (the ring crests carry the ink; the calm field is faint).\n let alpha = clamp(v * 0.92 + 0.08, 0.0, 1.0);\n return vec4<f32>(rgb * alpha, alpha);\n}\n";
1
+ export declare const CONCENTRIC_WGSL = "\nconst PI: f32 = 3.141592653589793;\nconst TAU: f32 = 6.283185307179586;\nconst RING_GRAVITY: f32 = 9.81;\nconst MAX_RINGS: i32 = 8;\nconst MAX_CENTERS: i32 = 4;\nconst MAX_RING_STOPS: i32 = 4;\n\n// \u2500\u2500 Concentric uniforms (the typed-struct source-of-truth \u2014 see uniformBridgeWGPU.ts) \u2500\u2500\nstruct ConcentricUniforms {\n // u0: (uTime, uSpeed, uAxisA, uAxisB)\n u0: vec4<f32>,\n // ints: (uCenterCount, uRingCount, uStopCount, uRenderMode) // 0 rings \u00B7 1 contour \u00B7 2 both\n ints: vec4<i32>,\n // bg: (background.rgb (linear), hasBackground)\n bg: vec4<f32>,\n // norm: (uFieldNorm, uAspect, _pad, _pad) \u2014 field \u2192 [0,1] scale\n norm: vec4<f32>,\n // line: (lineHalfWidth, aaSoftness, contourLevels, _pad) \u2014 stroke geometry (field units)\n line: vec4<f32>,\n // each ring row: (amplitude, wavelength, phase, _pad)\n rings: array<vec4<f32>, 8>,\n // each center row: (x, y, weight, rotAlpha)\n centers: array<vec4<f32>, 4>,\n // each palette stop: linear-sRGB rgb + _pad\n palette: array<vec4<f32>, 4>,\n};\n\n@group(0) @binding(0) var<uniform> u: ConcentricUniforms;\n\n\nfn srgbToLinearCh(c: f32) -> f32 {\n if (c <= 0.04045) { return c / 12.92; }\n return pow((c + 0.055) / 1.055, 2.4);\n}\nfn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(srgbToLinearCh(c.r), srgbToLinearCh(c.g), srgbToLinearCh(c.b));\n}\n\nfn linearToSrgbCh(c: f32) -> f32 {\n if (c <= 0.0031308) { return c * 12.92; }\n return 1.055 * pow(c, 1.0 / 2.4) - 0.055;\n}\nfn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(linearToSrgbCh(c.r), linearToSrgbCh(c.g), linearToSrgbCh(c.b));\n}\n\n// value.js LINEAR_SRGB_TO_LMS, row-major \u2192 WGSL columns (= the transpose).\nconst LINEAR_SRGB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 0.4122214708, 0.2119034982, 0.0883024619,\n 0.5363325363, 0.6806995451, 0.2817188376,\n 0.0514459929, 0.1073969566, 0.6299787005\n);\n\n// value.js srgbToOKLab's INLINE LMS\u2192OKLab coefficients, row-major \u2192 WGSL columns.\nconst LMS_TO_OKLAB: mat3x3<f32> = mat3x3<f32>(\n 0.2104542553, 1.9779984951, 0.0259040371,\n 0.7936177850, -2.4285922050, 0.7827717662,\n -0.0040720468, 0.4505937099, -0.8086757660\n);\n\n// value.js OKLAB_TO_LMS_COEFF, row-major \u2192 WGSL columns.\nconst OKLAB_TO_LMS: mat3x3<f32> = mat3x3<f32>(\n 1.0, 1.0, 1.0,\n 0.3963377774, -0.1055613458, -0.0894841775,\n 0.2158037573, -0.0638541728, -1.2914855480\n);\n\n// value.js LMS_TO_LINEAR_SRGB, row-major \u2192 WGSL columns.\nconst LMS_TO_LINEAR_SRGB: mat3x3<f32> = mat3x3<f32>(\n 4.0767416621, -1.2684380046, -0.0041960863,\n -3.3077115913, 2.6097574011, -0.7034186147,\n 0.2309699292, -0.3413193965, 1.7076147010\n);\n\nfn cbrt3(v: vec3<f32>) -> vec3<f32> {\n return sign(v) * pow(abs(v), vec3<f32>(1.0 / 3.0));\n}\n\n// Gamma sRGB \u2192 raw OKLab (L, a, b). Mirrors value.js srgbToOKLab.\nfn srgbToOklab(c: vec3<f32>) -> vec3<f32> {\n let lin = srgbToLinear(c);\n let lms = LINEAR_SRGB_TO_LMS * lin;\n return LMS_TO_OKLAB * cbrt3(lms);\n}\n\n// Raw OKLab (L, a, b) \u2192 linear sRGB. Mirrors value.js oklabToLinearSRGB.\nfn oklabToLinearSrgb(lab: vec3<f32>) -> vec3<f32> {\n let lms_ = OKLAB_TO_LMS * lab;\n let lms = lms_ * lms_ * lms_;\n return LMS_TO_LINEAR_SRGB * lms;\n}\n\n// OKLab \u2192 OKLCh: H in RADIANS, folded to [0, 2pi). Mirrors value.js rawOklabToOklch.\nfn oklabToOklch(lab: vec3<f32>) -> vec3<f32> {\n let C = length(lab.yz);\n var H = atan2(lab.z, lab.y);\n if (H < 0.0) { H = H + 2.0 * PI; }\n return vec3<f32>(lab.x, C, H);\n}\n\n// OKLCh (H radians) \u2192 OKLab. Mirrors value.js rawOklchToOklab.\nfn oklchToOklab(lch: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(lch.x, lch.y * cos(lch.z), lch.y * sin(lch.z));\n}\n\n// Full-screen-triangle (the pilot idiom): NDC corners (-1,-1),(3,-1),(-1,3) cover the\n// viewport from a single 3-vertex draw \u2014 no vertex buffer.\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) uv: vec2<f32>, // domain [-1,1]\u00B2, aspect-corrected x\n};\n\n@vertex\nfn vs_main(@builtin(vertex_index) vi: u32) -> VSOut {\n var corners = array<vec2<f32>, 3>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(3.0, -1.0), vec2<f32>(-1.0, 3.0),\n );\n let c = corners[vi];\n var out: VSOut;\n out.pos = vec4<f32>(c, 0.0, 1.0);\n out.uv = vec2<f32>(c.x, c.y);\n return out;\n}\n\n// The ellipsoidal radial distance in the family's ROTATED frame R(\u2212\u03B1): rotate (p \u2212 c) by\n// \u2212\u03B1, then scale by (a,b). Transcribes ringField.ts ellipsoidalRadiusRot.\nfn ellipsoidalRadiusRot(p: vec2<f32>, center: vec2<f32>, rotAlpha: f32, axisA: f32, axisB: f32) -> f32 {\n let ca = cos(rotAlpha);\n let sa = sin(rotAlpha);\n let px = p.x - center.x;\n let py = p.y - center.y;\n let rx = ca * px + sa * py;\n let ry = -sa * px + ca * py;\n let dx = rx / max(axisA, 1e-4);\n let dy = ry / max(axisB, 1e-4);\n return sqrt(dx * dx + dy * dy);\n}\n\n// |\u2207r| of the rotated ellipsoidal radius \u2014 closed-form (the IQ distance-estimation\n// denominator). Transcribes ringField.ts ellipsoidalGradMag.\nfn ellipsoidalGradMag(p: vec2<f32>, center: vec2<f32>, rotAlpha: f32, axisA: f32, axisB: f32) -> f32 {\n let ca = cos(rotAlpha);\n let sa = sin(rotAlpha);\n let px = p.x - center.x;\n let py = p.y - center.y;\n let rx = ca * px + sa * py;\n let ry = -sa * px + ca * py;\n let a = max(axisA, 1e-4);\n let b = max(axisB, 1e-4);\n let sx = rx / a;\n let sy = ry / b;\n let r = sqrt(sx * sx + sy * sy);\n let gx = sx / a;\n let gy = sy / b;\n return sqrt(gx * gx + gy * gy) / max(r, 1e-4);\n}\n\n// The radial-Fourier ring-interference value f(p,t) \u2014 the multi-center weighted sum of\n// CLEAN radial sinusoids (the BEAT ENVELOPE; transcribes ringField.ts sampleRingField).\nfn sampleRingField(p: vec2<f32>, t: f32) -> f32 {\n var acc = 0.0;\n let speed = u.u0.y;\n let axisA = u.u0.z;\n let axisB = u.u0.w;\n let centerCount = u.ints.x;\n let ringCount = u.ints.y;\n for (var j = 0; j < MAX_CENTERS; j = j + 1) {\n if (j >= centerCount) { break; }\n let cj = u.centers[j];\n let radius = ellipsoidalRadiusRot(p, cj.xy, cj.w, axisA, axisB);\n var centerSum = 0.0;\n for (var i = 0; i < MAX_RINGS; i = i + 1) {\n if (i >= ringCount) { break; }\n let r = u.rings[i];\n let k = TAU / max(r.y, 1e-4);\n let omega = sqrt(RING_GRAVITY * k) * speed;\n let theta = k * radius - omega * t + r.z;\n centerSum = centerSum + r.x * sin(theta);\n }\n acc = acc + centerSum * cj.z;\n }\n return acc;\n}\n\n// The IQ gradient-normalized isoline INK + the beat ENVELOPE \u2014 the per-pixel line strength\n// (brightest-wins union over every family \u00D7 ring crest) and the raw envelope (the hue\n// driver). Transcribes ringField.ts ringIsolineInk.\nstruct InkEnv { ink: f32, env: f32, };\nfn ringIsolineInk(p: vec2<f32>, t: f32) -> InkEnv {\n var ink = 0.0;\n var env = 0.0;\n let speed = u.u0.y;\n let axisA = u.u0.z;\n let axisB = u.u0.w;\n let centerCount = u.ints.x;\n let ringCount = u.ints.y;\n let lineHalfW = u.line.x;\n let aa = u.line.y;\n for (var j = 0; j < MAX_CENTERS; j = j + 1) {\n if (j >= centerCount) { break; }\n let cj = u.centers[j];\n let radius = ellipsoidalRadiusRot(p, cj.xy, cj.w, axisA, axisB);\n let gradR = ellipsoidalGradMag(p, cj.xy, cj.w, axisA, axisB);\n for (var i = 0; i < MAX_RINGS; i = i + 1) {\n if (i >= ringCount) { break; }\n let r = u.rings[i];\n let k = TAU / max(r.y, 1e-4);\n let omega = sqrt(RING_GRAVITY * k) * speed;\n let phase = k * radius - omega * t + r.z;\n let s = sin(phase);\n let cphase = abs(cos(phase));\n let gradPhase = max(k * gradR, 1e-4);\n // The IQ gradient-normalized distance-to-isoline (domain units; round-trips JS).\n let de = abs(s) / max(cphase * gradPhase, 1e-4);\n // Convert the domain-units distance to PIXELS via fwidth(phase) (the device\n // per-pixel phase change) so the stroke is a constant pixel width everywhere \u2014\n // lineHalfW/aa are in pixels (NOT fwidthFine, Compatibility-Mode safe).\n let dPx = max(fwidth(phase), 1e-4);\n let dePx = de * gradPhase / dPx;\n var lineV = 1.0 - smoothstep(lineHalfW, lineHalfW + aa, dePx);\n // Analytic anti-aliasing: where the rings pack tighter than the pixel can resolve\n // (fwidth(phase) \u2273 \u03C0, near a center / under DPR), FADE the line out instead of\n // flooding to a solid mass (IQ filterwidth \u2014 the aliasing-fade that keeps the field\n // thin LINES, not a bright slab where the rings converge).\n let aliasFade = 1.0 - smoothstep(PI * 0.6, PI * 1.2, dPx);\n lineV = lineV * aliasFade;\n let w = r.x * cj.z;\n ink = max(ink, lineV * w);\n env = env + s * w;\n }\n }\n var oe: InkEnv;\n oe.ink = clamp(ink, 0.0, 1.0);\n oe.env = env;\n return oe;\n}\n\n// The topographic-contour operator: the isolines of the STATIC interference envelope at N\n// evenly-spaced heights. de_contour = |fract(f\u00B7N + 0.5) \u2212 0.5| / |fwidth(f\u00B7N)| \u2014 the IQ\n// contour-line form. fwidth is the device pixel-derivative safety clamp on the composite\n// ONLY (NOT fwidthFine \u2014 Compatibility-Mode safe on Metal/WebKit).\nfn contourInk(envValue: f32, levels: f32) -> f32 {\n let fN = envValue * levels;\n let band = abs(fract(fN + 0.5) - 0.5);\n // fwidth is the device pixel-derivative safety clamp (NOT fwidthFine \u2014 Compatibility-Mode\n // safe on Metal/WebKit).\n let aaW = max(fwidth(fN), 1e-4);\n return 1.0 - smoothstep(u.line.x, u.line.x + u.line.y, band / aaW);\n}\n\n// Sample the multi-stop palette (linear-sRGB stops, OKLab mix). t in [0,1].\nfn samplePaletteLin(t: f32) -> vec3<f32> {\n let stopCount = u.ints.z;\n if (stopCount <= 1) { return u.palette[0].rgb; }\n let n = f32(stopCount);\n let ft = clamp(t, 0.0, 1.0) * (n - 1.0);\n let i0 = i32(floor(ft));\n let i1 = min(i0 + 1, stopCount - 1);\n let f = ft - f32(i0);\n let labA = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i0].rgb);\n let labB = LMS_TO_OKLAB * cbrt3(LINEAR_SRGB_TO_LMS * u.palette[i1].rgb);\n return oklabToLinearSrgb(mix(labA, labB, f));\n}\n\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n // aspect-correct the domain x so the rings read circular under the ellipsoidal norm.\n let aspect = max(u.norm.y, 1e-4);\n let p = vec2<f32>(in.uv.x * aspect, in.uv.y);\n let t = u.u0.x;\n let mode = u.ints.w; // 0 traveling-rings \u00B7 1 static-contour \u00B7 2 both\n let levels = u.line.z;\n\n // The isoline strokes (the LINES) + the beat envelope (the HUE).\n let oe = ringIsolineInk(p, t);\n var ink = oe.ink;\n let env = oe.env;\n\n // The static-contour mode draws elevation lines of the (static) envelope.\n if (mode == 1) {\n ink = contourInk(env * u.norm.x, max(levels, 1.0));\n } else if (mode == 2) {\n ink = max(ink, contourInk(env * u.norm.x, max(levels, 1.0)));\n }\n // fwidth safety clamp on the final line composite (Compatibility-Mode safe).\n ink = clamp(ink, 0.0, 1.0);\n\n // The beat-envelope drives the warm-family tone across the ramp (cream\u2194amber\u2194ember) so the\n // crossing ring families read as warm-light interference; the saturated mid-amber reads on\n // BOTH the cream page and the dark page (the warm-cream identity, NOT a themed hue).\n let v = clamp(0.5 + env * u.norm.x, 0.0, 1.0);\n let lin = samplePaletteLin(v);\n let rgb = clamp(linearToSrgb(lin), vec3<f32>(0.0), vec3<f32>(1.0));\n\n let hasBg = u.bg.w;\n if (hasBg > 0.5) {\n // opaque themed ground: composite the lit line over the themed bg.\n let bg = clamp(linearToSrgb(u.bg.rgb), vec3<f32>(0.0), vec3<f32>(1.0));\n let outRgb = mix(bg, rgb, ink);\n return vec4<f32>(outRgb, 1.0);\n }\n // transparent ground: the LINE carries the alpha \u2014 the page reads through the troughs.\n let alpha = ink;\n return vec4<f32>(rgb * alpha, alpha);\n}\n";
@@ -9,11 +9,11 @@ type __VLS_ModelProps = {
9
9
  "open"?: boolean;
10
10
  };
11
11
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
12
- declare var __VLS_13: {}, __VLS_36: {};
12
+ declare var __VLS_35: {}, __VLS_64: {};
13
13
  type __VLS_Slots = {} & {
14
- default?: (props: typeof __VLS_13) => any;
14
+ default?: (props: typeof __VLS_35) => any;
15
15
  } & {
16
- action?: (props: typeof __VLS_36) => any;
16
+ action?: (props: typeof __VLS_64) => any;
17
17
  };
18
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
19
  "update:open": (value: boolean) => any;
@@ -4,8 +4,13 @@ declare const __VLS_export: import("vue").DefineComponent<ConstellationProps, im
4
4
  speed: number;
5
5
  count: number;
6
6
  opacityCeiling: number;
7
+ parallax: number;
7
8
  pointerReactive: boolean;
8
9
  warpOnClick: boolean;
10
+ wander: boolean | {
11
+ minIdle?: number;
12
+ jitter?: number;
13
+ };
9
14
  gravityWell: boolean | {
10
15
  holdMs?: number;
11
16
  gain?: number;
@@ -14,10 +19,6 @@ declare const __VLS_export: import("vue").DefineComponent<ConstellationProps, im
14
19
  maxSpeed?: number;
15
20
  soften?: number;
16
21
  };
17
- wander: boolean | {
18
- minIdle?: number;
19
- jitter?: number;
20
- };
21
22
  pinned: boolean | number;
22
23
  accentEdges: boolean;
23
24
  pinnedDrift: boolean | {
@@ -0,0 +1,10 @@
1
+ import type { WebGLCanvasFrame } from "../../../../composables/glass/webgl/useWebGLCanvas";
2
+ import type { ConstellationRenderState } from "./constellationWGPUSetup";
3
+ export interface ConstellationGLSetupDeps {
4
+ canvas: HTMLCanvasElement;
5
+ resolveFrame: (timeSec: number) => ConstellationRenderState | null;
6
+ onResize?: (w: number, h: number) => void;
7
+ shouldContinue: () => boolean;
8
+ }
9
+ /** Build the `setupGL(gl)` callback the `createGpuSubstrate` WebGL2 path invokes. */
10
+ export declare function createConstellationGLSetup(deps: ConstellationGLSetupDeps): (gl: WebGL2RenderingContext) => WebGLCanvasFrame;
@@ -0,0 +1,19 @@
1
+ import type { WebGPUCanvasFrame } from "../../../../composables/glass/webgpu/useWebGPUCanvas";
2
+ import { type ConstellationUniformValues, type PackedNode, type PackedEdge } from "./uniformBridgeWGPU";
3
+ /** The per-frame render state the renderer resolves (the stepped field → packed rows). */
4
+ export interface ConstellationRenderState {
5
+ nodes: PackedNode[];
6
+ edges: PackedEdge[];
7
+ uniforms: ConstellationUniformValues;
8
+ }
9
+ export interface ConstellationWGPUSetupDeps {
10
+ canvas: HTMLCanvasElement;
11
+ /** Advance the field + the shared pointer field one renderer frame, return the packed render state. */
12
+ resolveFrame: (timeSec: number) => ConstellationRenderState | null;
13
+ /** Size the canvas backing store (returns the resolved backing-store [w,h] in device px). */
14
+ onResize?: (w: number, h: number) => void;
15
+ /** Demand-gate (the renderer's quiescence layer — substrate-agnostic). */
16
+ shouldContinue: () => boolean;
17
+ }
18
+ /** Build the constellation `setupWGPU(device, context, format)` callback. */
19
+ export declare function createConstellationWGPUSetup(deps: ConstellationWGPUSetupDeps): (device: GPUDevice, context: GPUCanvasContext, format: GPUTextureFormat) => WebGPUCanvasFrame;
@@ -0,0 +1,66 @@
1
+ /** Floats per node row (one vec4). */
2
+ export declare const NODE_FLOATS = 4;
3
+ /** Bytes per node row. */
4
+ export declare const NODE_BYTES: number;
5
+ /** The pre-sized node storage buffer byte length. */
6
+ export declare const NODES_BUFFER_BYTES: number;
7
+ /** Floats per edge row (2 vec4s). */
8
+ export declare const EDGE_FLOATS = 8;
9
+ /** Bytes per edge row. */
10
+ export declare const EDGE_BYTES: number;
11
+ /** The pre-sized edge storage buffer byte length. */
12
+ export declare const EDGES_BUFFER_BYTES: number;
13
+ export declare const CONSTELLATION_UNIFORM_BYTES = 112;
14
+ export interface ConstellationUniformScratch {
15
+ buffer: ArrayBuffer;
16
+ f32: Float32Array;
17
+ }
18
+ export declare function createConstellationScratch(): ConstellationUniformScratch;
19
+ /** The per-frame uniform values the render reads (resolved JS-side). */
20
+ export interface ConstellationUniformValues {
21
+ resolutionX: number;
22
+ resolutionY: number;
23
+ dpr: number;
24
+ kVis: number;
25
+ time: number;
26
+ lineWidth: number;
27
+ opacityCeiling: number;
28
+ /** The field-yields-to-type `--constellation-alpha` global dimmer. */
29
+ alpha: number;
30
+ edgeAlpha: number;
31
+ edgeFocusAlpha: number;
32
+ edgeAccentAlpha: number;
33
+ edgeFloor: number;
34
+ /** Premultiplied-ready RGBA (`[0,1]`) — `node`/`nodeDim`/`line`/`accent`. */
35
+ node: [number, number, number, number];
36
+ nodeDim: [number, number, number, number];
37
+ line: [number, number, number, number];
38
+ accent: [number, number, number, number];
39
+ }
40
+ /** Pack the constellation uniforms in place. */
41
+ export declare function packConstellationUniforms(scratch: ConstellationUniformScratch, v: ConstellationUniformValues): ConstellationUniformScratch;
42
+ /** A pre-sized node scratch (`MAX_NODES` rows × NODE_FLOATS). */
43
+ export declare function createNodeScratch(): Float32Array;
44
+ /** A pre-sized edge scratch (`E_MAX` rows × EDGE_FLOATS). */
45
+ export declare function createEdgeScratch(): Float32Array;
46
+ /** A packed node row in screen-px: `(x, y, radius, dim)`. */
47
+ export interface PackedNode {
48
+ x: number;
49
+ y: number;
50
+ r: number;
51
+ dim: number;
52
+ }
53
+ /** Pack `count` node rows into the scratch (clamped to MAX_NODES). Returns the count packed. */
54
+ export declare function packNodes(scratch: Float32Array, nodes: readonly PackedNode[]): number;
55
+ /** A packed edge row: `(ax, ay, bx, by, alpha, accent, focus)`. */
56
+ export interface PackedEdge {
57
+ ax: number;
58
+ ay: number;
59
+ bx: number;
60
+ by: number;
61
+ alpha: number;
62
+ accent: number;
63
+ focus: number;
64
+ }
65
+ /** Pack `count` edge rows into the scratch (clamped to E_MAX). Returns the count packed. */
66
+ export declare function packEdges(scratch: Float32Array, edges: readonly PackedEdge[]): number;
@@ -1,9 +1,12 @@
1
1
  import { type Ref } from "vue";
2
+ import { type GpuBackend } from "../../../../composables/glass/webgpu/useGpuSubstrate";
2
3
  import { type ConstellationField, type ConstellationProps } from "../constellationField";
3
4
  /** The imperative seam the SFC re-exposes via `defineExpose`. */
4
5
  export interface ConstellationExpose {
5
6
  field: ConstellationField;
6
7
  isFrozen: Ref<boolean>;
8
+ /** The resolved backend (`"webgpu"` where supported, else the WebGL2 instanced twin). */
9
+ backend: () => GpuBackend;
7
10
  warpTo(a: {
8
11
  x: number;
9
12
  y: number;
@@ -13,14 +16,4 @@ export interface ConstellationExpose {
13
16
  warpSettled(): boolean;
14
17
  pinNode(idx: number): void;
15
18
  }
16
- /**
17
- * Drive a `<Constellation>` instance. `props` is the REACTIVE (defaulted) prop
18
- * surface — the per-frame live-read props (`pointerReactive`/`opacityCeiling`/
19
- * `accentEdges`/`drawOverlay`) are read off `props.x` INSIDE the render loop so a
20
- * bound `:opacity-ceiling` updates without a remount (the Vue 3.5 reactive-prop
21
- * read; the SFC `defineProps` destructure transform does not reach a composable
22
- * argument, so the live reads stay on `props`). `hostRef`/`canvasRef` are the SFC
23
- * template refs. Returns the imperative expose object the SFC spreads into
24
- * `defineExpose`.
25
- */
26
19
  export declare function useConstellation(props: ConstellationProps, hostRef: Ref<HTMLElement | null>, canvasRef: Ref<HTMLCanvasElement | null>): ConstellationExpose;
@@ -59,3 +59,36 @@ export declare const DEFAULT_PINNED_DRIFT_JITTER = 8000;
59
59
  * ≥ ~0.72·BASE_WIDTH ≈ 922px (incl. the 1280 export frame — byte-identical
60
60
  * there by construction); below it the marks stop crushing sub-pixel. */
61
61
  export declare const DEFAULT_K_FLOOR = 0.72;
62
+ /**
63
+ * The maximum node count the points/edges buffers pre-size for (the slider cap — a count
64
+ * above this is clamped at upload). ≫ this BOOKS the compute neighbor-bin path.
65
+ */
66
+ export declare const MAX_NODES = 256;
67
+ /**
68
+ * The per-node max degree budget — the edge buffer is pre-sized at `MAX_NODES · MAX_DEGREE`
69
+ * so the CPU all-pairs scan never overflows it (a denser-than-degree neighborhood drops the
70
+ * weakest edges, never re-allocates). 12 is a generous incident-edge ceiling for a
71
+ * distance-threshold ε-proximity graph at the default link/count.
72
+ */
73
+ export declare const MAX_DEGREE = 12;
74
+ /** The pre-sized edge instance budget (`MAX_NODES · MAX_DEGREE`). */
75
+ export declare const E_MAX: number;
76
+ /**
77
+ * The pointer-parallax depth default (§6). Each node carries a seeded depth `z ∈ [0,1]`;
78
+ * the pointer offsets node screen positions by `parallax · z · (pointer − center)` — a
79
+ * cheap pointer-parallax giving the flat lattice apparent depth (the Awwwards "living
80
+ * network" register). Additive default-on at a SUB-PERCEPTUAL 0.08 (a hair of depth, not a
81
+ * behavior break). 0 = the flat lattice (no parallax).
82
+ */
83
+ export declare const DEFAULT_PARALLAX = 0.08;
84
+ /**
85
+ * The base node radius band (CSS px) the DPR-aware SDF circle sizes within (the §1 "Node
86
+ * size" config axis). `seedField` rolls each node's radius in `[NODE_R_MIN, NODE_R_MIN +
87
+ * NODE_R_SPREAD)` (the prior `1.6 + rng()*1.6` band, named); the WGSL/GLSL fragment SDF
88
+ * sizes `half = radius · uKVis · uDpr / uResolution` so the disc samples at full device
89
+ * resolution and is AA'd by the pixel-footprint derivative — crisp at ANY DPR.
90
+ */
91
+ export declare const NODE_R_MIN = 1.6;
92
+ export declare const NODE_R_SPREAD = 1.6;
93
+ /** The hairline edge half-width (CSS px) the instanced segment-quad fragment AAs. */
94
+ export declare const DEFAULT_LINE_WIDTH = 1;
@@ -39,4 +39,34 @@ export declare function refitField(field: ConstellationField, prevW: number, pre
39
39
  * `setWarpTarget` to a random node when it elapses AND the spring has settled
40
40
  * (a click-warp in flight pre-empts the cadence — `warpSettled` reports false).
41
41
  */
42
- export declare function stepField(field: ConstellationField, k: number, speed: number, pointer: ConstellationPointer | null, dt?: number, now?: number, rng?: () => number): void;
42
+ export declare function stepField(field: ConstellationField, k: number, speed: number, pointer: ConstellationPointer | null, dt?: number, now?: number, rng?: () => number, pointerVel?: ConstellationPointer | null): void;
43
+ import type { ConstellationEdge } from "./constellationTypes";
44
+ /**
45
+ * Scan the proximity graph and return its edge SET (the `1 − d²/reach²` distance-falloff
46
+ * weight per pair within `reach = link·k`). `accentIndex ≥ 0` marks the edges incident on
47
+ * that node (the flagged-node tether). Pure + node-testable; the render loop calls it each
48
+ * frame and uploads the result to the instanced-lines storage buffer.
49
+ *
50
+ * `eMax` caps the result (the pre-sized buffer budget). When the scan would exceed it, the
51
+ * WEAKEST overflow edges are dropped (a denser-than-budget neighborhood keeps its strongest
52
+ * links — never re-allocates the GPU buffer mid-frame).
53
+ */
54
+ export declare function buildEdges(field: ConstellationField, link: number, accentIndex?: number, eMax?: number): ConstellationEdge[];
55
+ /**
56
+ * Append the POINTER-WEB tether edges to an existing edge set (the `drawPointerWeb` math
57
+ * relocated): the cursor is a "virtual node" whose incident edges (to every node within
58
+ * `reach`) carry `focus = 1` (the render strokes them at the focus alpha). No-op when the
59
+ * pointer is inactive (`x < 0`). The `eMax` budget is shared with the ambient set.
60
+ */
61
+ export declare function appendPointerWeb(edges: ConstellationEdge[], field: ConstellationField, link: number, pointer: ConstellationPointer | null, eMax?: number): void;
62
+ /**
63
+ * The parallax-offset SCREEN position for a node (§6). Offsets the node by
64
+ * `parallax · z · (pointer − center)` — a cheap pointer-parallax giving the flat lattice
65
+ * apparent depth (deeper nodes — higher `z` — shift more, the Awwwards "living network"
66
+ * register). When the pointer is inactive the offset is 0 (the flat lattice). Pure; the
67
+ * render loop maps each node's `(x,y)` through this before writing the GPU position buffer.
68
+ */
69
+ export declare function parallaxNodePos(node: ConstellationNode, pointer: ConstellationPointer | null, w: number, h: number, parallax: number): {
70
+ x: number;
71
+ y: number;
72
+ };
@@ -19,20 +19,7 @@ export declare function readInteractionConfig(canvas: HTMLCanvasElement): {
19
19
  jitter: number;
20
20
  };
21
21
  };
22
- /**
23
- * Advance the gravity-well one `dt` (AY.W-CON2). A transient held-pointer force
24
- * composed inside `stepField` (NO new rAF): ease `well.strength` toward
25
- * `well.target` (1 held / 0 released) at `cfg.ramp`/s; while active, add an
26
- * inverse-square pull toward the held point onto each node within `cfg.reach`
27
- * (the `max(d, soften)` no-singularity floor + the `cfg.maxSpeed` no-slingshot
28
- * clamp); ALWAYS ease every node's |v| back toward `speed` (the field-cools
29
- * invariant — so a released well re-settles). No-ops (entirely skipped) when
30
- * `field.well` is undefined → the default render is byte-identical to HEAD.
31
- *
32
- * `dt` is clamped to {@link WARP_DT_CLAMP} (the same park-resume guard the warp
33
- * uses) so a tab-throttle gap cannot slingshot the field in one giant step.
34
- */
35
- export declare function stepWell(field: ConstellationField, k: number, speed: number, dt: number): void;
22
+ export { stepWell } from "./constellationWell";
36
23
  /**
37
24
  * The nearest DRIFTING node to `(px, py)` in canvas-local px — a linear O(count)
38
25
  * min-d² scan (count 64 default — negligible; matches the O(count²) edge pass).
@@ -130,3 +117,25 @@ export declare function makePinnedDrift(override?: {
130
117
  * rests at the leg's end, the next leg arming after `minIdle + rng()*jitter`.
131
118
  */
132
119
  export declare function stepPinnedDrift(field: ConstellationField, now: number, rng: () => number): void;
120
+ /** The flick-burst threshold (the shared usePointerVelocityField `burst` 0..1) above which
121
+ * a fast flick fires the focal warp + a transient ripple (a slow drag never fires). */
122
+ export declare const BURST_FIRE_THRESHOLD = 0.45;
123
+ /**
124
+ * Fire a focal BURST off a flick (the §E "reads velocity AND acceleration" mandate). A high
125
+ * `burst` (from the shared `usePointerVelocityField`, the eased flick impulse) warps the
126
+ * focal node toward the cursor (the warp spring snaps it) AND drops an expanding ripple at
127
+ * the focal — the lattice "snaps the focal toward the cursor and drops an expanding ring"
128
+ * (the WGSL ripple instance / the accent-ring overlay). A slow drag (`burst` below the
129
+ * threshold) never fires (a steady hover is the gentle gather, not a snap). Returns true
130
+ * when a burst fired. Composes the EXISTING `warpTo` + the ripple list — no new mechanic,
131
+ * no second rAF (the warp rides the substrate's ONE clock); PRM is enforced by the CALLER
132
+ * (the shared field's `tick(0)` zeroes `burst` under reduce, so this never fires).
133
+ */
134
+ export declare function fireBurst(field: ConstellationField, pointer: {
135
+ x: number;
136
+ y: number;
137
+ }, burst: number, ripples: {
138
+ x: number;
139
+ y: number;
140
+ start: number;
141
+ }[]): boolean;
@@ -0,0 +1,25 @@
1
+ import type { ConstellationField, ConstellationPalette } from "./constellationField";
2
+ import { DEFAULT_PALETTE } from "./constants";
3
+ /** R5-8 — the visual-SIZE draw scale: `max(k, kFloor)`. The instanced disc/segment
4
+ * geometry sizes on this; positions/reach stay on TRUE `field.k`. Exported so a
5
+ * consumer skin floors its own marks on the same axis. */
6
+ export declare function kVisOf(field: ConstellationField): number;
7
+ export { DEFAULT_PALETTE };
8
+ /**
9
+ * Resolve the FULL neutral palette + legibility weights off a canvas's resolved custom
10
+ * properties (the `--constellation-*` set). The colors AND the alpha multipliers route
11
+ * through the same `getComputedStyle` probe, so a dark-mode flip re-resolves BOTH the
12
+ * `:root`/`.dark` color arms AND the per-mode alpha defaults in one read. SSR-safe
13
+ * (returns the warm-cream defaults with no `window`).
14
+ */
15
+ export declare function readPalette(canvas: HTMLCanvasElement): ConstellationPalette;
16
+ /**
17
+ * Parse a CSS color string (the `--constellation-*` hsl/hex literals the palette carries)
18
+ * into a linear-ish premultiplied-ready RGBA in `[0,1]` for the GPU uniform write. A small
19
+ * sRGB parser: it reads `#rgb`/`#rrggbb`/`#rrggbbaa`, `rgb()/rgba()`, and `hsl()/hsla()` —
20
+ * the forms the `--constellation-*` token authoring uses (PLAIN-hsl per arm). The shader
21
+ * outputs premultiplied alpha over the transparent clear, so the render loop multiplies the
22
+ * `a` into the uniform color at upload (kept here so there is ONE color parse seam). Falls
23
+ * back to opaque warm-ink on an unparseable value (never a NaN garbage write).
24
+ */
25
+ export declare function parseColorRGBA(input: string): [number, number, number, number];
@@ -5,6 +5,35 @@ export interface ConstellationNode {
5
5
  vy: number;
6
6
  r: number;
7
7
  dim: boolean;
8
+ /**
9
+ * BC.W-VIZ-CONSTELLATION — the seeded parallax DEPTH (`z ∈ [0,1]`, §6). The pointer
10
+ * offsets the node's SCREEN position by `parallax · z · (pointer − center)` so the flat
11
+ * lattice reads as having depth (the Awwwards "living network" register). Seeded in
12
+ * `seedField`; perturbs the GPU node-position write only (never a layout property). A
13
+ * field literal that omits it is treated as `z = 0.5` (the mid-plane, no parallax bias).
14
+ */
15
+ z?: number;
16
+ }
17
+ /**
18
+ * BC.W-VIZ-CONSTELLATION — ONE edge of the proximity graph, the row the CPU all-pairs scan
19
+ * (`buildEdges`) writes each frame into the instanced-lines storage buffer. `a`/`b` are the
20
+ * two endpoint positions in canvas-local CSS px; `alpha` is the distance-falloff weight
21
+ * (`1 − d²/reach²`, the `drawEdges` math) the segment-quad fragment multiplies; `accent`
22
+ * (0/1) flags the accented-node tether (the flagged-node edge tint); `focus` (0/1) flags
23
+ * the pointer-web tether (the cursor's incident edges). The WGSL/GLSL render transcribes
24
+ * the SHAPE, never re-derives the scan (the ONE math source stays JS).
25
+ */
26
+ export interface ConstellationEdge {
27
+ ax: number;
28
+ ay: number;
29
+ bx: number;
30
+ by: number;
31
+ /** The distance-falloff weight `1 − d²/reach²` (the drawEdges math). */
32
+ alpha: number;
33
+ /** 1 when the edge is incident on the accented node (the tether tint), else 0. */
34
+ accent: number;
35
+ /** 1 when the edge is a pointer-web tether (the cursor's incident edge), else 0. */
36
+ focus: number;
8
37
  }
9
38
  export interface ConstellationRipple {
10
39
  x: number;
@@ -274,6 +303,15 @@ export interface ConstellationProps {
274
303
  link?: number;
275
304
  /** Drift speed. Default 0.16. */
276
305
  speed?: number;
306
+ /**
307
+ * BC.W-VIZ-CONSTELLATION (§6) — the pointer-PARALLAX depth. Each node carries a seeded
308
+ * depth `z ∈ [0,1]`; the pointer offsets node screen positions by `parallax · z ·
309
+ * (pointer − center)` so the flat lattice reads as having depth (the Awwwards "living
310
+ * network" register). Additive default-on at a SUB-PERCEPTUAL 0.08 (a hair of depth, not
311
+ * a behavior break); 0 = the flat lattice. GPU-only (perturbs the node-position write,
312
+ * never a layout property). Frozen under reduced-motion / `freeze`.
313
+ */
314
+ parallax?: number;
277
315
  /**
278
316
  * AY.W-COHERE E3 — the per-instance outer-envelope RECESSION knob (the aurora
279
317
  * `opacityCeiling` / fourier `intensity` sibling — ONE recession vocabulary
@@ -0,0 +1,15 @@
1
+ import type { ConstellationField } from "./constellationField";
2
+ /**
3
+ * Advance the gravity-well one `dt` (AY.W-CON2). A transient held-pointer force
4
+ * composed inside `stepField` (NO new rAF): ease `well.strength` toward
5
+ * `well.target` (1 held / 0 released) at `cfg.ramp`/s; while active, add an
6
+ * inverse-square pull toward the held point onto each node within `cfg.reach`
7
+ * (the `max(d, soften)` no-singularity floor + the `cfg.maxSpeed` no-slingshot
8
+ * clamp); ALWAYS ease every node's |v| back toward `speed` (the field-cools
9
+ * invariant — so a released well re-settles). No-ops (entirely skipped) when
10
+ * `field.well` is undefined → the default render is byte-identical to HEAD.
11
+ *
12
+ * `dt` is clamped to {@link WELL_DT_CLAMP} (the same park-resume guard the warp
13
+ * uses) so a tab-throttle gap cannot slingshot the field in one giant step.
14
+ */
15
+ export declare function stepWell(field: ConstellationField, k: number, speed: number, dt: number): void;
@@ -1,6 +1,6 @@
1
1
  export { default as Constellation } from "./Constellation.vue";
2
- export { seedField, stepField, refitField, BASE_WIDTH, } from "./constellationField";
3
- export { DEFAULT_K_FLOOR } from "./constants";
4
- export { stepWell, nearestNode, readInteractionConfig, warpStep, warpTo, setWarpTarget, warpSettled, pickWanderTarget, stepPinnedDrift, makePinnedDrift, DEFAULT_WELL_CONFIG, DEFAULT_WANDER_IDLE, DEFAULT_WANDER_JITTER, DEFAULT_PINNED_DRIFT_FRAC, DEFAULT_PINNED_DRIFT_DUR, DEFAULT_PINNED_DRIFT_IDLE, DEFAULT_PINNED_DRIFT_JITTER, WARP_RESPONSE, WARP_ZETA, } from "./constellationInteraction";
5
- export { kVisOf, readPalette, drawEdges, drawNodes, drawPointerWeb, drawRipples, DEFAULT_PALETTE, } from "./constellationDraw";
6
- export type { ConstellationNode, ConstellationRipple, ConstellationPointer, ConstellationPalette, ConstellationField, ConstellationWarp, ConstellationWarpConfig, ConstellationWander, ConstellationWell, ConstellationWellConfig, ConstellationPinnedDrift, ConstellationProps, } from "./constellationTypes";
2
+ export { seedField, stepField, refitField, buildEdges, appendPointerWeb, parallaxNodePos, BASE_WIDTH, } from "./constellationField";
3
+ export { DEFAULT_K_FLOOR, DEFAULT_PARALLAX, MAX_NODES, MAX_DEGREE, E_MAX, } from "./constants";
4
+ export { stepWell, nearestNode, readInteractionConfig, warpStep, warpTo, setWarpTarget, warpSettled, pickWanderTarget, stepPinnedDrift, makePinnedDrift, DEFAULT_WELL_CONFIG, DEFAULT_WANDER_IDLE, DEFAULT_WANDER_JITTER, DEFAULT_PINNED_DRIFT_FRAC, DEFAULT_PINNED_DRIFT_DUR, DEFAULT_PINNED_DRIFT_IDLE, DEFAULT_PINNED_DRIFT_JITTER, WARP_RESPONSE, WARP_ZETA, fireBurst, BURST_FIRE_THRESHOLD, } from "./constellationInteraction";
5
+ export { kVisOf, readPalette, parseColorRGBA, DEFAULT_PALETTE, } from "./constellationRender";
6
+ export type { ConstellationNode, ConstellationEdge, ConstellationRipple, ConstellationPointer, ConstellationPalette, ConstellationField, ConstellationWarp, ConstellationWarpConfig, ConstellationWander, ConstellationWell, ConstellationWellConfig, ConstellationPinnedDrift, ConstellationProps, } from "./constellationTypes";
@@ -0,0 +1,2 @@
1
+ export declare const CONSTELLATION_LINES_VERT_GLSL = "#version 300 es\nprecision highp float;\n\n// per-instance edge rows \u2014 vertexAttribDivisor(1).\nlayout(location = 0) in vec4 aAB; // (a.x, a.y, b.x, b.y)\nlayout(location = 1) in vec4 aW; // (alpha, accent, focus, _pad)\n\nuniform vec2 uResolution;\nuniform float uDpr;\nuniform float uKVis;\nuniform float uLineWidth;\n\nout float vLineCoord;\nout float vAlpha;\nout float vAccent;\nout float vFocus;\n\nvoid main() {\n vec2 quad[6] = vec2[6](\n vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0),\n vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0)\n );\n vec2 alongQuad = quad[gl_VertexID];\n\n vec2 a = aAB.xy;\n vec2 b = aAB.zw;\n vec2 dir = normalize(b - a + vec2(1e-6, 0.0));\n vec2 ortho = vec2(-dir.y, dir.x);\n // accent tether reads a touch heavier (1.1\u00D7).\n float halfWPx = uLineWidth * uKVis * uDpr * 0.5 * mix(1.0, 1.1, aW.y);\n vec2 p = mix(a, b, alongQuad.x * 0.5 + 0.5) + ortho * alongQuad.y * halfWPx;\n\n vec2 ndc = vec2(\n p.x / max(uResolution.x, 1.0) * 2.0 - 1.0,\n 1.0 - p.y / max(uResolution.y, 1.0) * 2.0\n );\n\n gl_Position = vec4(ndc, 0.0, 1.0);\n vLineCoord = alongQuad.y;\n vAlpha = aW.x;\n vAccent = aW.y;\n vFocus = aW.z;\n}\n";
2
+ export declare const CONSTELLATION_LINES_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\nuniform vec4 uLine; // premultiplied-ready rgba\nuniform vec4 uAccent;\nuniform float uAlphaGlobal; // --constellation-alpha\nuniform float uOpacityCeiling;\nuniform float uEdgeAlpha;\nuniform float uEdgeFocusAlpha;\nuniform float uEdgeAccentAlpha;\nuniform float uEdgeFloor;\n\nin float vLineCoord;\nin float vAlpha;\nin float vAccent;\nin float vFocus;\nout vec4 fragColor;\n\nvoid main() {\n float aaBand = 0.6;\n float cross = 1.0 - smoothstep(1.0 - aaBand, 1.0, abs(vLineCoord));\n if (cross <= 0.0) { discard; }\n\n float dim = uAlphaGlobal * uOpacityCeiling;\n vec4 col = uLine;\n float weight = (uEdgeAlpha * vAlpha + uEdgeFloor) * dim;\n if (vAccent > 0.5) {\n col = uAccent;\n weight = uEdgeAccentAlpha * vAlpha * dim;\n } else if (vFocus > 0.5) {\n col = uLine;\n weight = uEdgeFocusAlpha * uAlphaGlobal * uOpacityCeiling * vAlpha;\n }\n\n float a = col.a * weight * cross;\n if (a <= 0.0) { discard; }\n fragColor = vec4(col.rgb * a, a);\n}\n";
@@ -0,0 +1 @@
1
+ export declare const CONSTELLATION_LINES_WGSL = "\nstruct Edge {\n // vec4 0: (a.x, a.y, b.x, b.y)\n ab: vec4<f32>,\n // vec4 1: (alpha, accent, focus, _pad)\n w: vec4<f32>,\n};\n\nstruct ConstellationUniforms {\n // u0: (resolution.x, resolution.y, dpr, kVis)\n u0: vec4<f32>,\n // u1: (time, lineWidth, opacityCeiling, alpha)\n u1: vec4<f32>,\n // uEdge: (edgeAlpha, edgeFocusAlpha, edgeAccentAlpha, edgeFloor)\n uEdge: vec4<f32>,\n uNode: vec4<f32>,\n uNodeDim: vec4<f32>,\n uLine: vec4<f32>,\n uAccent: vec4<f32>,\n};\n\n@group(0) @binding(0) var<uniform> u: ConstellationUniforms;\n@group(0) @binding(1) var<storage, read> edges: array<Edge>;\n\nstruct VSOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) lineCoord: f32, // [-1,1] cross-line \u2192 fragment AA\n @location(1) alpha: f32, // distance-falloff weight\n @location(2) accent: f32, // accent flag (the flagged-node tether tint)\n @location(3) focus: f32, // focus flag (the pointer-web tether)\n};\n\n@vertex\nfn vs_main(\n @builtin(vertex_index) vIdx: u32,\n @builtin(instance_index) iIdx: u32,\n) -> VSOut {\n var QUAD = array<vec2<f32>, 6>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(1.0, -1.0), vec2<f32>(-1.0, 1.0),\n vec2<f32>(-1.0, 1.0), vec2<f32>(1.0, -1.0), vec2<f32>(1.0, 1.0),\n );\n let alongQuad = QUAD[vIdx];\n\n let e = edges[iIdx];\n let a = e.ab.xy;\n let b = e.ab.zw;\n let res = u.u0.xy;\n let dpr = u.u0.z;\n let kVis = u.u0.w;\n let lineW = u.u1.y;\n\n // Screen-space segment direction + orthogonal (the half-width offset axis).\n let dir = normalize(b - a + vec2<f32>(1e-6, 0.0));\n let ortho = vec2<f32>(-dir.y, dir.x);\n // Lerp along the segment (alongQuad.x \u2208 [-1,1] \u2192 [0,1]); offset by ortho \u00D7 half-width.\n // The accent tether reads a touch heavier (1.1\u00D7 the neutral width).\n let halfWPx = lineW * kVis * dpr * 0.5 * mix(1.0, 1.1, e.w.y);\n let p = mix(a, b, alongQuad.x * 0.5 + 0.5) + ortho * (alongQuad.y) * halfWPx;\n\n // px (y-down) \u2192 clip (y-up).\n let ndc = vec2<f32>(\n p.x / max(res.x, 1.0) * 2.0 - 1.0,\n 1.0 - p.y / max(res.y, 1.0) * 2.0,\n );\n\n var out: VSOut;\n out.pos = vec4<f32>(ndc, 0.0, 1.0);\n out.lineCoord = alongQuad.y;\n out.alpha = e.w.x;\n out.accent = e.w.y;\n out.focus = e.w.z;\n return out;\n}\n\n@fragment\nfn fs_main(in: VSOut) -> @location(0) vec4<f32> {\n // Cross-line AA \u2014 a smoothstep on |lineCoord| so the hairline edge is crisp.\n let aaBand = 0.6;\n let cross = 1.0 - smoothstep(1.0 - aaBand, 1.0, abs(in.lineCoord));\n if (cross <= 0.0) { discard; }\n\n let dim = u.u1.w * u.u1.z; // alpha \u00B7 opacityCeiling\n // Resolve the edge class: accent tether \u00B7 focus pointer-web \u00B7 neutral ambient.\n var col = u.uLine;\n var weight = (u.uEdge.x * in.alpha + u.uEdge.w) * dim; // edgeAlpha\u00B7falloff + edgeFloor\n if (in.accent > 0.5) {\n col = u.uAccent;\n weight = u.uEdge.z * in.alpha * dim; // edgeAccentAlpha\n } else if (in.focus > 0.5) {\n col = u.uLine;\n weight = u.uEdge.y * u.u1.w * u.u1.z * in.alpha; // edgeFocusAlpha \u00B7 alpha \u00B7 ceiling\n }\n\n let a = col.a * weight * cross;\n if (a <= 0.0) { discard; }\n return vec4<f32>(col.rgb * a, a);\n}\n";
@@ -0,0 +1,2 @@
1
+ export declare const CONSTELLATION_POINTS_VERT_GLSL = "#version 300 es\nprecision highp float;\n\n// per-instance node row (x, y, radius, dim) \u2014 vertexAttribDivisor(1).\nlayout(location = 0) in vec4 aNode;\n\nuniform vec2 uResolution;\nuniform float uDpr;\nuniform float uKVis;\n\nout vec2 vUv; // [-1,1] billboard-local \u2192 fragment SDF coord\nout float vDim;\n\nvoid main() {\n // Two-triangle quad corners (the SAME order as the WGSL QUAD).\n vec2 quad[6] = vec2[6](\n vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0),\n vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0)\n );\n vec2 corner = quad[gl_VertexID];\n\n vec2 centerPx = aNode.xy;\n // px (y-down) \u2192 clip (y-up).\n vec2 centerNdc = vec2(\n centerPx.x / max(uResolution.x, 1.0) * 2.0 - 1.0,\n 1.0 - centerPx.y / max(uResolution.y, 1.0) * 2.0\n );\n // half-extent: radius\u00B7kVis CSS px \u2192 backing-store px (\u00B7dpr) \u2192 NDC half (\u00B72/res).\n // (half is a GLSL reserved word \u2014 name it halfExt.)\n float radPx = aNode.z * uKVis * uDpr;\n vec2 halfExt = vec2(\n radPx / max(uResolution.x, 1.0) * 2.0,\n radPx / max(uResolution.y, 1.0) * 2.0\n );\n\n gl_Position = vec4(centerNdc + corner * halfExt, 0.0, 1.0);\n vUv = corner;\n vDim = aNode.w;\n}\n";
2
+ export declare const CONSTELLATION_POINTS_FRAG_GLSL = "#version 300 es\nprecision highp float;\n\nuniform vec4 uNode; // premultiplied-ready rgba\nuniform vec4 uNodeDim;\nuniform float uOpacityCeiling;\n\nin vec2 vUv;\nin float vDim;\nout vec4 fragColor;\n\nvoid main() {\n // SDF: distance to the unit-circle edge (0 at the rim, neg inside).\n float d = length(vUv) - 1.0;\n // fwidth(d) \u2014 the pixel footprint, the resolution-independent AA width.\n float aa = max(fwidth(d), 1e-4);\n float coverage = 1.0 - smoothstep(-aa, aa, d);\n if (coverage <= 0.0) { discard; }\n vec4 col = mix(uNode, uNodeDim, vDim);\n float a = col.a * coverage * uOpacityCeiling;\n fragColor = vec4(col.rgb * a, a); // premultiplied\n}\n";