@kitn.ai/ui 0.28.0 → 0.29.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 (376) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-tooling/construct/public.d.ts +15 -0
  3. package/dist/agent-tooling/construct/schema.d.ts +111 -0
  4. package/dist/construct-cli.es.js +3 -3
  5. package/dist/construct.d.ts +5 -0
  6. package/dist/construct.js +327 -0
  7. package/dist/core-C8fzo39E.js +1 -12
  8. package/dist/engine-javascript-C1x7zo1_.js +1 -141
  9. package/dist/mcp.es.js +1 -1
  10. package/package.json +16 -16
  11. package/bin/route.test.js +0 -58
  12. package/src/agent-tooling/README.md +0 -192
  13. package/src/agent-tooling/archetypes.ts +0 -205
  14. package/src/agent-tooling/catalog/README.md +0 -676
  15. package/src/agent-tooling/catalog/catalog-types.ts +0 -231
  16. package/src/agent-tooling/catalog/fabrications.ts +0 -96
  17. package/src/agent-tooling/catalog/invariants.ts +0 -284
  18. package/src/agent-tooling/catalog/labs-titles.ts +0 -114
  19. package/src/agent-tooling/catalog/scenarios.ts +0 -87
  20. package/src/agent-tooling/catalog/surfaces.ts +0 -347
  21. package/src/agent-tooling/construct/cli-entry.ts +0 -8
  22. package/src/agent-tooling/construct/cli.ts +0 -147
  23. package/src/agent-tooling/construct/codegen.ts +0 -1635
  24. package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
  25. package/src/agent-tooling/construct/dev.ts +0 -148
  26. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
  27. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
  28. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
  29. package/src/agent-tooling/construct/schema.ts +0 -452
  30. package/src/agent-tooling/integrations/anthropic.ts +0 -442
  31. package/src/agent-tooling/integrations/cloudflare.ts +0 -218
  32. package/src/agent-tooling/integrations/langgraph.ts +0 -133
  33. package/src/agent-tooling/integrations/mastra.ts +0 -182
  34. package/src/agent-tooling/integrations/mock.ts +0 -148
  35. package/src/agent-tooling/integrations/ollama.ts +0 -97
  36. package/src/agent-tooling/integrations/openai.ts +0 -95
  37. package/src/agent-tooling/integrations/openrouter.ts +0 -82
  38. package/src/agent-tooling/integrations/pi.ts +0 -176
  39. package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
  40. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
  41. package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
  42. package/src/agent-tooling/mcp/manifest.ts +0 -422
  43. package/src/agent-tooling/mcp/server.ts +0 -116
  44. package/src/agent-tooling/mcp/stdio.ts +0 -18
  45. package/src/agent-tooling/mcp/tools/construct.ts +0 -130
  46. package/src/agent-tooling/mcp/tools/debug.ts +0 -621
  47. package/src/agent-tooling/mcp/tools/reference.ts +0 -980
  48. package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
  49. package/src/agent-tooling/mcp/tools/theme.ts +0 -456
  50. package/src/agent-tooling/mcp/tools/types.ts +0 -14
  51. package/src/agent-tooling/mcp/validate-args.ts +0 -141
  52. package/src/agent-tooling/recipes/composed-thread.ts +0 -714
  53. package/src/agent-tooling/recipes/index.ts +0 -22
  54. package/src/agent-tooling/recipes/types.ts +0 -32
  55. package/src/agent-tooling/registry.ts +0 -132
  56. package/src/agent-tooling/route-emit.ts +0 -305
  57. package/src/agent-tooling/types.ts +0 -390
  58. package/src/components/artifact-card.tsx +0 -120
  59. package/src/components/artifact.tsx +0 -914
  60. package/src/components/attachment-types.ts +0 -66
  61. package/src/components/attachments.tsx +0 -536
  62. package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
  63. package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
  64. package/src/components/audio-visualizer/fit-scale.ts +0 -112
  65. package/src/components/audio-visualizer/index.tsx +0 -528
  66. package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
  67. package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
  68. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
  69. package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
  70. package/src/components/audio-visualizer/sizes.ts +0 -54
  71. package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
  72. package/src/components/audio-visualizer/variant-bar.tsx +0 -175
  73. package/src/components/audio-visualizer/variant-custom.tsx +0 -344
  74. package/src/components/audio-visualizer/variant-grid.tsx +0 -175
  75. package/src/components/audio-visualizer/variant-radial.tsx +0 -163
  76. package/src/components/audio-visualizer/variant-wave.tsx +0 -130
  77. package/src/components/audio-visualizer/wave.glsl.ts +0 -130
  78. package/src/components/card-fallback.tsx +0 -60
  79. package/src/components/card-renderer.tsx +0 -220
  80. package/src/components/card.tsx +0 -212
  81. package/src/components/chain-of-thought.tsx +0 -348
  82. package/src/components/chat-container.tsx +0 -89
  83. package/src/components/chat-scope-picker.tsx +0 -57
  84. package/src/components/chat-thread.tsx +0 -1014
  85. package/src/components/checkpoint.tsx +0 -88
  86. package/src/components/choice-card.tsx +0 -743
  87. package/src/components/coachmark.tsx +0 -249
  88. package/src/components/code-block.tsx +0 -181
  89. package/src/components/composer-dom.ts +0 -159
  90. package/src/components/composer-highlight.ts +0 -242
  91. package/src/components/composer-history.ts +0 -82
  92. package/src/components/composer.tsx +0 -1075
  93. package/src/components/confirm-card.tsx +0 -402
  94. package/src/components/context.tsx +0 -377
  95. package/src/components/conversation-item.tsx +0 -241
  96. package/src/components/conversation-list.tsx +0 -429
  97. package/src/components/conversation-panel.tsx +0 -118
  98. package/src/components/dismissed-stub.tsx +0 -80
  99. package/src/components/embed.tsx +0 -200
  100. package/src/components/empty.tsx +0 -177
  101. package/src/components/feedback-bar.tsx +0 -166
  102. package/src/components/file-tree.tsx +0 -530
  103. package/src/components/file-upload.tsx +0 -167
  104. package/src/components/form-widgets.tsx +0 -525
  105. package/src/components/form.tsx +0 -1296
  106. package/src/components/home-panel.tsx +0 -159
  107. package/src/components/image.tsx +0 -65
  108. package/src/components/link-preview.tsx +0 -195
  109. package/src/components/loader.tsx +0 -367
  110. package/src/components/markdown.tsx +0 -162
  111. package/src/components/message-skills.tsx +0 -40
  112. package/src/components/message.tsx +0 -765
  113. package/src/components/model-switcher.tsx +0 -132
  114. package/src/components/prompt-input.tsx +0 -188
  115. package/src/components/prompt-suggestion.tsx +0 -150
  116. package/src/components/reasoning.tsx +0 -293
  117. package/src/components/response-compare-types.ts +0 -152
  118. package/src/components/response-compare.tsx +0 -455
  119. package/src/components/response-stream.tsx +0 -109
  120. package/src/components/screen.tsx +0 -181
  121. package/src/components/scroll-button.tsx +0 -93
  122. package/src/components/source.tsx +0 -192
  123. package/src/components/tasks-card.tsx +0 -801
  124. package/src/components/text-shimmer.tsx +0 -37
  125. package/src/components/thinking-bar.tsx +0 -50
  126. package/src/components/thread.tsx +0 -228
  127. package/src/components/toast.tsx +0 -503
  128. package/src/components/tool-classify.ts +0 -26
  129. package/src/components/tool-types.ts +0 -49
  130. package/src/components/tool.tsx +0 -190
  131. package/src/components/use-card-resolution.ts +0 -44
  132. package/src/components/voice-input.tsx +0 -222
  133. package/src/components/voice-output.tsx +0 -242
  134. package/src/components/widget-tab-bar.tsx +0 -73
  135. package/src/components/workspace-shell.tsx +0 -285
  136. package/src/diagnostics/hook.ts +0 -352
  137. package/src/diagnostics/index.ts +0 -82
  138. package/src/diagnostics/report-request.ts +0 -296
  139. package/src/elements/agent-card.tsx +0 -67
  140. package/src/elements/artifact.tsx +0 -194
  141. package/src/elements/attachments.tsx +0 -140
  142. package/src/elements/audio-visualizer.tsx +0 -227
  143. package/src/elements/autoloader.ts +0 -89
  144. package/src/elements/avatar.tsx +0 -33
  145. package/src/elements/badge.tsx +0 -32
  146. package/src/elements/button.tsx +0 -149
  147. package/src/elements/card.tsx +0 -133
  148. package/src/elements/cards.tsx +0 -266
  149. package/src/elements/chain-of-thought.tsx +0 -141
  150. package/src/elements/chat-scope-picker.tsx +0 -65
  151. package/src/elements/chat-types.ts +0 -102
  152. package/src/elements/chat-workspace.tsx +0 -188
  153. package/src/elements/chat.tsx +0 -304
  154. package/src/elements/checkbox-group.tsx +0 -164
  155. package/src/elements/checkbox.tsx +0 -134
  156. package/src/elements/checkpoint.tsx +0 -47
  157. package/src/elements/choice.tsx +0 -100
  158. package/src/elements/coachmark.tsx +0 -90
  159. package/src/elements/code-block.tsx +0 -60
  160. package/src/elements/command.tsx +0 -197
  161. package/src/elements/compare.tsx +0 -111
  162. package/src/elements/compiled.css +0 -2
  163. package/src/elements/composer.tsx +0 -162
  164. package/src/elements/confirm-card.tsx +0 -76
  165. package/src/elements/context-meter.tsx +0 -107
  166. package/src/elements/conversation-item.tsx +0 -120
  167. package/src/elements/conversation-list.tsx +0 -203
  168. package/src/elements/css.ts +0 -5
  169. package/src/elements/default-input.tsx +0 -392
  170. package/src/elements/define-entry.ts +0 -12
  171. package/src/elements/define.tsx +0 -563
  172. package/src/elements/diagnostic-events.ts +0 -114
  173. package/src/elements/dialog.tsx +0 -145
  174. package/src/elements/disclosure.ts +0 -95
  175. package/src/elements/dock.tsx +0 -215
  176. package/src/elements/dropdown.tsx +0 -123
  177. package/src/elements/editable-label.tsx +0 -140
  178. package/src/elements/element-data-types.ts +0 -152
  179. package/src/elements/element-diagnostics.ts +0 -392
  180. package/src/elements/element-manifest.json +0 -354
  181. package/src/elements/element-nonscalar.json +0 -187
  182. package/src/elements/element-types.d.ts +0 -4353
  183. package/src/elements/embed.tsx +0 -35
  184. package/src/elements/empty.tsx +0 -29
  185. package/src/elements/feedback-bar.tsx +0 -66
  186. package/src/elements/file-tree.tsx +0 -62
  187. package/src/elements/file-upload.tsx +0 -44
  188. package/src/elements/form.tsx +0 -94
  189. package/src/elements/hover-card.tsx +0 -80
  190. package/src/elements/icon.tsx +0 -41
  191. package/src/elements/image.tsx +0 -32
  192. package/src/elements/input.tsx +0 -492
  193. package/src/elements/kbd.tsx +0 -45
  194. package/src/elements/link-preview.tsx +0 -34
  195. package/src/elements/loader.tsx +0 -25
  196. package/src/elements/markdown.tsx +0 -38
  197. package/src/elements/menu.tsx +0 -241
  198. package/src/elements/message-skills.tsx +0 -83
  199. package/src/elements/message.tsx +0 -361
  200. package/src/elements/model-switcher.tsx +0 -121
  201. package/src/elements/nav.tsx +0 -87
  202. package/src/elements/notice.tsx +0 -53
  203. package/src/elements/pane-grid.tsx +0 -111
  204. package/src/elements/pane-group.tsx +0 -119
  205. package/src/elements/pane.tsx +0 -129
  206. package/src/elements/popover.tsx +0 -81
  207. package/src/elements/progress-bar.tsx +0 -39
  208. package/src/elements/prompt-dock.tsx +0 -82
  209. package/src/elements/prompt-input.tsx +0 -240
  210. package/src/elements/prompt-suggestions.tsx +0 -113
  211. package/src/elements/radio-group.tsx +0 -129
  212. package/src/elements/reasoning.tsx +0 -71
  213. package/src/elements/register-impl.ts +0 -148
  214. package/src/elements/register.ts +0 -76
  215. package/src/elements/remote.tsx +0 -225
  216. package/src/elements/resizable.globals.d.ts +0 -36
  217. package/src/elements/resizable.tsx +0 -704
  218. package/src/elements/response-stream.tsx +0 -40
  219. package/src/elements/screen.tsx +0 -90
  220. package/src/elements/scroll-area.tsx +0 -33
  221. package/src/elements/scroll-button.tsx +0 -179
  222. package/src/elements/search.tsx +0 -185
  223. package/src/elements/segmented.tsx +0 -129
  224. package/src/elements/select.tsx +0 -165
  225. package/src/elements/separator.tsx +0 -36
  226. package/src/elements/setting-item.tsx +0 -50
  227. package/src/elements/settings-group.tsx +0 -37
  228. package/src/elements/skeleton.tsx +0 -45
  229. package/src/elements/slider.tsx +0 -171
  230. package/src/elements/slot-text.ts +0 -73
  231. package/src/elements/slots.ts +0 -787
  232. package/src/elements/source.tsx +0 -126
  233. package/src/elements/status.tsx +0 -42
  234. package/src/elements/styles.css +0 -328
  235. package/src/elements/switch.tsx +0 -118
  236. package/src/elements/tabs.tsx +0 -95
  237. package/src/elements/tasks.tsx +0 -103
  238. package/src/elements/text-shimmer.tsx +0 -28
  239. package/src/elements/thinking-bar.tsx +0 -43
  240. package/src/elements/thread.tsx +0 -139
  241. package/src/elements/toast.tsx +0 -106
  242. package/src/elements/tool.tsx +0 -78
  243. package/src/elements/tooltip.tsx +0 -85
  244. package/src/elements/validate-messages.ts +0 -76
  245. package/src/elements/voice-input.tsx +0 -100
  246. package/src/elements/voice-output.tsx +0 -82
  247. package/src/index.ts +0 -430
  248. package/src/primitives/audio-bands.ts +0 -174
  249. package/src/primitives/card-component-types.ts +0 -63
  250. package/src/primitives/card-contract.ts +0 -80
  251. package/src/primitives/card-data-types.ts +0 -361
  252. package/src/primitives/card-host.tsx +0 -37
  253. package/src/primitives/card-recovery.ts +0 -160
  254. package/src/primitives/card-registry.tsx +0 -78
  255. package/src/primitives/card-resolution.ts +0 -36
  256. package/src/primitives/card-routing.ts +0 -85
  257. package/src/primitives/card-schemas/artifact.schema.json +0 -92
  258. package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
  259. package/src/primitives/card-schemas/card-event.schema.json +0 -12
  260. package/src/primitives/card-schemas/choice.schema.json +0 -75
  261. package/src/primitives/card-schemas/confirm.schema.json +0 -65
  262. package/src/primitives/card-schemas/embed.schema.json +0 -63
  263. package/src/primitives/card-schemas/form.result.schema.json +0 -7
  264. package/src/primitives/card-schemas/form.schema.json +0 -53
  265. package/src/primitives/card-schemas/link.schema.json +0 -54
  266. package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
  267. package/src/primitives/card-schemas/tasks.schema.json +0 -83
  268. package/src/primitives/card-tags.ts +0 -61
  269. package/src/primitives/card-validate-cards.ts +0 -255
  270. package/src/primitives/card-validate-schemas.ts +0 -58
  271. package/src/primitives/card-validate.ts +0 -131
  272. package/src/primitives/chat-config.tsx +0 -103
  273. package/src/primitives/composer-model.ts +0 -49
  274. package/src/primitives/composer-triggers.ts +0 -35
  275. package/src/primitives/controllable.ts +0 -21
  276. package/src/primitives/conversation-store.ts +0 -248
  277. package/src/primitives/create-kai-chat.ts +0 -66
  278. package/src/primitives/create-tween.ts +0 -266
  279. package/src/primitives/embed-providers.ts +0 -254
  280. package/src/primitives/field-mask.ts +0 -256
  281. package/src/primitives/field-semantics.ts +0 -115
  282. package/src/primitives/highlighter.ts +0 -157
  283. package/src/primitives/input-mask.ts +0 -853
  284. package/src/primitives/link-preview.ts +0 -87
  285. package/src/primitives/message-feedback.ts +0 -124
  286. package/src/primitives/pdf-preview.ts +0 -121
  287. package/src/primitives/toast-store.ts +0 -338
  288. package/src/primitives/url-scheme-policy.ts +0 -70
  289. package/src/primitives/use-audio-analysis.ts +0 -340
  290. package/src/primitives/use-auto-resize.ts +0 -31
  291. package/src/primitives/use-resize-observer.ts +0 -45
  292. package/src/primitives/use-sequencer.ts +0 -72
  293. package/src/primitives/use-speech-recognition.ts +0 -146
  294. package/src/primitives/use-stick-to-bottom.ts +0 -75
  295. package/src/primitives/use-text-stream.ts +0 -143
  296. package/src/primitives/use-voice-recorder.ts +0 -62
  297. package/src/primitives/visualizer-sequences.ts +0 -350
  298. package/src/remote/host-embed.ts +0 -345
  299. package/src/remote/index.ts +0 -2
  300. package/src/remote/origin.ts +0 -30
  301. package/src/remote/provider-runtime.ts +0 -262
  302. package/src/remote/provider.ts +0 -2
  303. package/src/remote/validate.ts +0 -22
  304. package/src/remote/version.ts +0 -12
  305. package/src/remote/wire.ts +0 -48
  306. package/src/schemas/from-tool-call.ts +0 -151
  307. package/src/schemas/index.ts +0 -341
  308. package/src/schemas/provider-subsets.ts +0 -538
  309. package/src/schemas/registry.ts +0 -355
  310. package/src/schemas/tool-defs.ts +0 -793
  311. package/src/solid.ts +0 -173
  312. package/src/state/index.ts +0 -44
  313. package/src/state/messages.ts +0 -53
  314. package/src/state/mock.ts +0 -297
  315. package/src/state/parts.ts +0 -295
  316. package/src/state/persistence.ts +0 -180
  317. package/src/state/stream.ts +0 -246
  318. package/src/state/suggestions.ts +0 -9
  319. package/src/state/threads.ts +0 -142
  320. package/src/test-utils/fake-clock.ts +0 -88
  321. package/src/types.ts +0 -95
  322. package/src/ui/action-icons.ts +0 -53
  323. package/src/ui/agent-card.tsx +0 -218
  324. package/src/ui/avatar.tsx +0 -23
  325. package/src/ui/badge.tsx +0 -21
  326. package/src/ui/button.tsx +0 -49
  327. package/src/ui/card.tsx +0 -245
  328. package/src/ui/checkbox-group.tsx +0 -153
  329. package/src/ui/checkbox.tsx +0 -63
  330. package/src/ui/collapsible.tsx +0 -163
  331. package/src/ui/command.tsx +0 -103
  332. package/src/ui/dialog.tsx +0 -223
  333. package/src/ui/dock.tsx +0 -630
  334. package/src/ui/dropdown.tsx +0 -636
  335. package/src/ui/editable-label.tsx +0 -112
  336. package/src/ui/hover-card.tsx +0 -345
  337. package/src/ui/icon.tsx +0 -167
  338. package/src/ui/input.tsx +0 -391
  339. package/src/ui/kbd.tsx +0 -118
  340. package/src/ui/nav.tsx +0 -282
  341. package/src/ui/notice.tsx +0 -84
  342. package/src/ui/overlay.tsx +0 -277
  343. package/src/ui/pane-grid.tsx +0 -117
  344. package/src/ui/pane-group.tsx +0 -291
  345. package/src/ui/pane.tsx +0 -193
  346. package/src/ui/popover.tsx +0 -106
  347. package/src/ui/progress-bar.tsx +0 -83
  348. package/src/ui/prompt-dock.tsx +0 -145
  349. package/src/ui/radio.tsx +0 -150
  350. package/src/ui/resizable.tsx +0 -693
  351. package/src/ui/scroll-area.tsx +0 -26
  352. package/src/ui/segmented.tsx +0 -109
  353. package/src/ui/select.tsx +0 -168
  354. package/src/ui/separator.tsx +0 -10
  355. package/src/ui/settings-group.tsx +0 -67
  356. package/src/ui/skeleton.tsx +0 -73
  357. package/src/ui/slider.tsx +0 -178
  358. package/src/ui/status.tsx +0 -48
  359. package/src/ui/switch.tsx +0 -119
  360. package/src/ui/tabs.tsx +0 -168
  361. package/src/ui/textarea.tsx +0 -21
  362. package/src/ui/tooltip.tsx +0 -118
  363. package/src/utils/cn.ts +0 -30
  364. package/src/wire/chunk.ts +0 -248
  365. package/src/wire/consume.ts +0 -599
  366. package/src/wire/diagnostics.ts +0 -727
  367. package/src/wire/encode-probe.ts +0 -214
  368. package/src/wire/encode.ts +0 -947
  369. package/src/wire/files.ts +0 -342
  370. package/src/wire/formats/anthropic.ts +0 -274
  371. package/src/wire/formats/openai.ts +0 -228
  372. package/src/wire/index.ts +0 -95
  373. package/src/wire/media-types.ts +0 -344
  374. package/src/wire/read.ts +0 -396
  375. package/src/wire/sink-helpers.ts +0 -50
  376. package/src/wire/sse.ts +0 -153
@@ -1,187 +0,0 @@
1
- import type { LabLook } from './lab-shaders';
2
-
3
- /** The agent states the kit's visualizers respond to, plus manual free play. */
4
- export type LabState = 'manual' | 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking';
5
-
6
- export const LAB_STATES: LabState[] = ['manual', 'idle', 'connecting', 'listening', 'thinking', 'speaking'];
7
-
8
- /** Every tunable the lab shaders read. Flat on purpose: story args map 1:1. */
9
- export interface LabParams {
10
- baseR: number; ampIdle: number; ampVoice: number; radVoice: number;
11
- sigma: number; gain: number; f1: number; f2: number; s1: number; s2: number;
12
- envSpd: number; sepSpd: number; whiteLo: number; whiteHi: number;
13
- bloomMul: number; bloomGain: number; delta: number; off: number;
14
- wWidth: number; wMin: number; fillGain: number; edgeGain: number;
15
- flut: number; twistSpd: number; warpAmp: number; lens: number; spec: number;
16
- tint: number; vSpeed: number; presence: number; gather: number;
17
- core: number; neural: number; boltJag: number; boltWidth: number; boltRate: number;
18
- }
19
-
20
- const SHARED: LabParams = {
21
- baseR: 0.33, ampIdle: 0.017, ampVoice: 0.043, radVoice: 0.24,
22
- sigma: 0.022, gain: 0.42, f1: 6, f2: 10, s1: 0.55, s2: 0.85,
23
- envSpd: 0.21, sepSpd: 0.38, whiteLo: 1.35, whiteHi: 2.3,
24
- bloomMul: 2.6, bloomGain: 0.18, delta: 0.35, off: 0.024,
25
- wWidth: 0.045, wMin: 0.006, fillGain: 0.38, edgeGain: 0.7,
26
- flut: 0.01, twistSpd: 0.55, warpAmp: 0.75, lens: 0.85, spec: 0.35,
27
- tint: 0.25, vSpeed: 2.2, presence: 1, gather: 0,
28
- core: 0, neural: 0, boltJag: 0.5, boltWidth: 3, boltRate: 0.25,
29
- };
30
-
31
- /** Hand-tuned in the aurora playground; per-look starting points. */
32
- export const LOOK_DEFAULTS: Record<LabLook, LabParams> = {
33
- braid: { ...SHARED },
34
- ribbon: {
35
- ...SHARED,
36
- baseR: 0.315, ampIdle: 0.012, ampVoice: 0.032, radVoice: 0.09,
37
- sigma: 0.014, gain: 0.6, f1: 3, f2: 9, s1: 1.1, s2: 2.2,
38
- envSpd: 0.5, whiteLo: 1.0, whiteHi: 2.4, bloomMul: 2.5, bloomGain: 0.15,
39
- wWidth: 0.085, wMin: 0.009, fillGain: 0.85, edgeGain: 0.35, twistSpd: 1.9,
40
- },
41
- planet: {
42
- ...SHARED,
43
- radVoice: 0, gain: 1.0, fillGain: 0.75, edgeGain: 0.5,
44
- f2: 12, s1: 1, s2: 1, twistSpd: 1.0, warpAmp: 0.9,
45
- whiteLo: 1.2, whiteHi: 2.6,
46
- },
47
- orb: {
48
- ...SHARED,
49
- radVoice: 0, gain: 1.1, fillGain: 0.65, edgeGain: 0.45,
50
- f2: 10, s1: 1, s2: 1, twistSpd: 1.2, warpAmp: 1.0,
51
- lens: 0.8, spec: 0.3, vSpeed: 3.0,
52
- },
53
- };
54
-
55
- const ORB_LOOKS: LabLook[] = ['planet', 'orb'];
56
-
57
- /** Loudness loop standing in for a live voice while `speaking` (dB per third-second). */
58
- const ENV_DB = [-60.9, -49.0, -46.7, -54.1, -50.0, -47.8, -49.3, -53.3, -53.5, -50.4,
59
- -46.9, -53.0, -50.2, -52.5, -53.9, -50.6, -50.8, -49.2, -55.1, -48.7,
60
- -48.4, -47.4, -49.6, -50.7, -49.0, -46.9, -50.8, -52.9, -52.2, -46.6,
61
- -46.6, -46.2];
62
-
63
- function envelopeAt(sec: number): number {
64
- const x = (sec % 10.6) * 3;
65
- const i = Math.max(0, Math.min(ENV_DB.length - 1, Math.floor(x)));
66
- const j = Math.min(ENV_DB.length - 1, i + 1);
67
- const f = x - i;
68
- const db = ENV_DB[i] * (1 - f) + ENV_DB[j] * f;
69
- return Math.max(0, Math.min(1, (db + 58) / 14));
70
- }
71
-
72
- interface Slow {
73
- presence: number; gather: number; tintAdd: number; warpMul: number;
74
- deltaAdd: number; f2Add: number; gainMul: number; neural: number;
75
- }
76
-
77
- export interface LabFrame {
78
- t: number;
79
- level: number;
80
- values: LabParams;
81
- }
82
-
83
- /**
84
- * The state choreography from the playground, per frame. Slow targets glide
85
- * over seconds (presence slowest, so smoke visibly forms and dissipates);
86
- * tempo runs on an accumulated warped clock, so state changes never jump the
87
- * animation phase; the ember beats and the bolts fire in real time.
88
- */
89
- export function createChoreography(getLook: () => LabLook, getState: () => LabState, getParams: () => LabParams) {
90
- let tAnim = 0;
91
- let rateSm = 1;
92
- let smooth = 0;
93
- let elapsed = 0;
94
- const slow: Slow = { presence: 1, gather: 0, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
95
-
96
- const step = (dt: number): LabFrame => {
97
- elapsed += dt;
98
- const P = getParams();
99
- const state = getState();
100
- const orb = ORB_LOOKS.includes(getLook());
101
- const base = orb ? 0.35 : 1.0;
102
-
103
- const drive = envelopeAt(elapsed);
104
- const k = drive > smooth ? 0.25 : 0.06;
105
- smooth += (drive - smooth) * k;
106
-
107
- const beat = Math.pow(0.5 + 0.5 * Math.sin((elapsed / 1.2) * Math.PI * 2), 3.0);
108
- const flick = 0.5 + 0.5 * Math.sin((elapsed / 0.35) * Math.PI * 2);
109
-
110
- let target: Slow;
111
- let rate: number;
112
- let level: number;
113
- let core: number;
114
- let gpulse = 0;
115
- switch (state) {
116
- case 'idle':
117
- target = orb
118
- ? { presence: 0.12, gather: -0.8, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 }
119
- : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.8, neural: 0 };
120
- rate = base; level = 0; core = orb ? 0.06 : 0;
121
- break;
122
- case 'connecting':
123
- target = orb
124
- ? { presence: 0.22, gather: -0.25, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.9, neural: 0 }
125
- : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 0.85, neural: 0 };
126
- rate = base * 1.4; level = 0.04; core = orb ? 0.18 + 0.55 * beat : 0;
127
- if (!orb) gpulse = 0.2 * beat;
128
- break;
129
- case 'listening':
130
- target = orb
131
- ? { presence: 0.8, gather: 0.5, tintAdd: 0.05, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 }
132
- : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
133
- rate = base * 1.7; level = 0.2; core = orb ? 0.12 : 0;
134
- break;
135
- case 'thinking':
136
- target = orb
137
- ? { presence: 1, gather: 0.6, tintAdd: 0.5, warpMul: 1.3, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 1 }
138
- : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0.5, f2Add: 3, gainMul: 1, neural: 0 };
139
- rate = orb ? 2.2 : 2.5; level = 0.12 + 0.2 * flick; core = orb ? 0.05 : 0;
140
- if (!orb) gpulse = 0.1 * flick;
141
- break;
142
- case 'speaking':
143
- target = orb
144
- ? { presence: 1, gather: 0, tintAdd: 0, warpMul: 1.25, deltaAdd: 0, f2Add: 0, gainMul: 1.05, neural: 0 }
145
- : { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: 0 };
146
- rate = base * 1.5 + 5.5 * smooth; level = Math.min(1, smooth * 1.35);
147
- core = orb ? 0.08 + 0.6 * smooth : 0;
148
- break;
149
- default:
150
- target = { presence: P.presence, gather: P.gather, tintAdd: 0, warpMul: 1, deltaAdd: 0, f2Add: 0, gainMul: 1, neural: P.neural };
151
- rate = base + P.vSpeed * smooth; level = smooth; core = P.core;
152
- }
153
-
154
- const mixTo = (cur: number, tgt: number, tc: number): number =>
155
- cur + (tgt - cur) * (1 - Math.exp(-dt / tc));
156
- slow.presence = mixTo(slow.presence, target.presence, 1.4);
157
- slow.gather = mixTo(slow.gather, target.gather, 1.0);
158
- slow.tintAdd = mixTo(slow.tintAdd, target.tintAdd, 0.6);
159
- slow.warpMul = mixTo(slow.warpMul, target.warpMul, 0.6);
160
- slow.deltaAdd = mixTo(slow.deltaAdd, target.deltaAdd, 0.6);
161
- slow.f2Add = mixTo(slow.f2Add, target.f2Add, 0.6);
162
- slow.gainMul = mixTo(slow.gainMul, target.gainMul, 0.6);
163
- slow.neural = mixTo(slow.neural, target.neural, 0.6);
164
-
165
- rateSm += (rate - rateSm) * (1 - Math.exp(-dt / 0.4));
166
- tAnim += dt * rateSm;
167
-
168
- return {
169
- t: tAnim,
170
- level,
171
- values: {
172
- ...P,
173
- presence: slow.presence,
174
- gather: slow.gather,
175
- core,
176
- neural: slow.neural,
177
- tint: Math.min(1, P.tint + slow.tintAdd),
178
- warpAmp: P.warpAmp * slow.warpMul,
179
- delta: P.delta + slow.deltaAdd,
180
- f2: P.f2 + slow.f2Add,
181
- gain: P.gain * slow.gainMul * (1 + gpulse),
182
- },
183
- };
184
- };
185
-
186
- return { step };
187
- }
@@ -1,363 +0,0 @@
1
- /**
2
- * The four lab looks, written for `ShaderCanvas` in the same `mainImage`
3
- * convention the `custom` variant documents. Every uniform is declared by
4
- * the canvas from the uniform map (`lab-visualizer.tsx`), never in the body.
5
- *
6
- * All four are original clean-room work from the aurora prototyping sessions
7
- * (see `examples/internal/aurora-playground`, the tuning playground these were
8
- * born in). Braid and ribbon read the accent through the shared ring pipeline;
9
- * planet and orb are stationary vessels whose CONTENTS react to state and
10
- * voice: presence materializes the smoke, gather settles or centers it, the
11
- * ember pulses while connecting, and thinking fires fractal lightning.
12
- */
13
-
14
- /** Value-noise fbm. Non-integer lacunarity so octaves do not align into grids. */
15
- const NOISE = `
16
- float labHash(vec2 q) {
17
- return fract(sin(dot(q, vec2(127.1, 311.7))) * 43758.5453);
18
- }
19
- float labNoise(vec2 q) {
20
- vec2 i = floor(q);
21
- vec2 f = fract(q);
22
- vec2 u = f * f * (3.0 - 2.0 * f);
23
- float a = labHash(i);
24
- float b = labHash(i + vec2(1.0, 0.0));
25
- float c = labHash(i + vec2(0.0, 1.0));
26
- float d = labHash(i + vec2(1.0, 1.0));
27
- return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
28
- }
29
- float labFbm(vec2 q) {
30
- float sum = 0.0;
31
- float amp = 0.5;
32
- for (int i = 0; i < 4; i++) {
33
- sum += amp * labNoise(q);
34
- q *= 2.03;
35
- amp *= 0.5;
36
- }
37
- return sum;
38
- }
39
- `;
40
-
41
- /**
42
- * Fractal lightning: five sites firing on independent rhythms; each firing
43
- * strikes a noise-displaced arc (re-seeded per strike, so no two bolts share
44
- * a shape) plus a fainter fork, from its previous site to its new one.
45
- */
46
- const LIGHTNING = `
47
- float labSegDist(vec2 q, vec2 a, vec2 b) {
48
- vec2 ab = b - a;
49
- float h = clamp(dot(q - a, ab) / max(dot(ab, ab), 1.0e-6), 0.0, 1.0);
50
- return length(q - a - ab * h);
51
- }
52
- vec2 labSparkPos(float k, float i, float R) {
53
- float h1 = labHash(vec2(k * 7.31 + 1.13, i * 3.71 + 0.17));
54
- float h2 = labHash(vec2(i * 9.13 + 2.29, k * 5.77 + 0.53));
55
- float av = 6.2831853 * h1;
56
- float rad = R * 0.85 * sqrt(h2);
57
- return vec2(cos(av), sin(av)) * rad;
58
- }
59
- float labBolt(vec2 q, vec2 A, vec2 B, float seed, float R, float life) {
60
- vec2 ab = B - A;
61
- float len = max(length(ab), 1.0e-4);
62
- vec2 dir = ab / len;
63
- vec2 nrm = vec2(-dir.y, dir.x);
64
- vec2 w = q - A;
65
- float u = dot(w, dir) / len;
66
- float v = dot(w, nrm);
67
- if (u < -0.05 || u > 1.05 || abs(v) > R * 0.30) return 0.0;
68
- float uu = clamp(u, 0.0, 1.0);
69
- float taper = sin(uu * 3.14159265);
70
- float off1 = (labFbm(vec2(uu * 9.0 + seed * 13.1, seed * 7.7)) - 0.5) * 0.55 * uBoltJag;
71
- float off2 = (labFbm(vec2(uu * 23.0 + seed * 5.3, seed * 3.9 + 4.2)) - 0.5) * 0.22 * uBoltJag;
72
- float mainArc = abs(v - (off1 + off2) * len * taper);
73
- float forkArc = abs(v - (off1 * 0.6 - off2 * 1.8) * len * taper);
74
- float wdt = R * (0.006 + 0.010 * life) * uBoltWidth;
75
- float bolt = exp(-pow(mainArc / wdt, 2.0))
76
- + 0.45 * exp(-pow(mainArc / (wdt * 3.0), 2.0))
77
- + 0.5 * exp(-pow(forkArc / (wdt * 0.8), 2.0))
78
- + 0.25 * exp(-pow(forkArc / (wdt * 2.5), 2.0));
79
- return bolt * taper;
80
- }
81
- float labNeural(vec2 q, float t, float R) {
82
- if (uNeural < 0.01) return 0.0;
83
- float acc = 0.0;
84
- for (int k = 0; k < 5; k++) {
85
- float fk = float(k);
86
- float period = (1.1 + 1.3 * labHash(vec2(fk, 3.3))) / max(uBoltRate, 0.05);
87
- float cyc = t / period + labHash(vec2(fk, 7.7)) * 7.0;
88
- float i = floor(cyc);
89
- float life = fract(cyc);
90
- float env = smoothstep(0.0, 0.04, life) * exp(-5.0 * life);
91
- if (env >= 0.004) {
92
- vec2 pos = labSparkPos(fk, i, R);
93
- vec2 prev = labSparkPos(fk, i - 1.0, R);
94
- float seed = labHash(vec2(fk * 3.1, i * 1.7));
95
- float bolt = labBolt(q, prev, pos, seed, R, life) * env;
96
- vec2 dp = q - pos;
97
- vec2 dq = q - prev;
98
- float tips = (exp(-dot(dp, dp) / (2.0 * R * R * 0.0016))
99
- + 0.6 * exp(-dot(dq, dq) / (2.0 * R * R * 0.0012))) * env;
100
- acc += bolt * 1.2 + tips * 0.8;
101
- }
102
- }
103
- return acc * uNeural;
104
- }
105
- `;
106
-
107
- /** Super-gaussian stroke: flat solid core, fast but feathered falloff. */
108
- const STROKE = `
109
- float labStroke(float d, float sigma) {
110
- float q = d / sigma;
111
- float q2 = q * q;
112
- float core = exp(-q2 * q2);
113
- float bq = d / (sigma * uBloomMul);
114
- float bloom = exp(-bq * bq) * uBloomGain;
115
- return core + bloom;
116
- }
117
- `;
118
-
119
- /** Shared ring color pipeline: accent brightness ramp with a capped white lift. */
120
- const RING_COLOR = `
121
- vec4 labRingColor(float glow, float bfloor, float bscale, float wcap, vec2 fragCoord) {
122
- float bright = bfloor + bscale * min(glow, 1.2);
123
- float white = smoothstep(uWhiteLo, uWhiteHi, glow) * wcap;
124
- vec3 col = mix(uColor * bright, vec3(1.0), white);
125
- float alpha = clamp(glow, 0.0, 1.0);
126
- float n = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);
127
- alpha = clamp(alpha + (n - 0.5) / 255.0, 0.0, 1.0);
128
- return vec4(col * alpha, alpha);
129
- }
130
- `;
131
-
132
- /** Three woven strands sharing one wave family; pileups soft-compressed. */
133
- export const BRAID_FRAGMENT = `${STROKE}${RING_COLOR}
134
- void mainImage(out vec4 fragColor, in vec2 fragCoord) {
135
- vec2 hres = iResolution.xy * 0.5;
136
- vec2 p = (fragCoord - hres) / hres.y;
137
- float r = length(p);
138
- float th = atan(p.y, p.x);
139
- float t = uT;
140
-
141
- float amp = uAmpIdle + uAmpVoice * uLvl;
142
- float baseR = uBaseR + uRadVoice * uLvl;
143
- float env = 0.62 + 0.38 * sin(th * 2.0 + t * uEnvSpd + 2.0);
144
-
145
- float glow = 0.0;
146
- for (int i = 0; i < 3; i++) {
147
- float fi = float(i);
148
- float a = th + fi * uDelta;
149
- float tt = t + fi * 1.3;
150
- float wob = sin(a * uF1 + tt * uS1) * 0.55 + sin(a * uF2 - tt * uS2) * 0.45;
151
- float ampi = amp * (0.65 + 0.35 * fi);
152
- float sepMod = 0.5 + 0.5 * sin(th + t * uSepSpd + fi * 1.9);
153
- float ringR = baseR + (fi - 1.0) * uOff * (0.35 + 1.5 * sepMod) + wob * ampi * env;
154
- glow += uGain * (0.8 + 0.35 * env) * labStroke(abs(r - ringR), uSigma);
155
- }
156
- // three overlapping strands can sum past every threshold; compress so
157
- // crossings brighten without blowing out to a solid white tube
158
- glow = glow / (1.0 + 0.35 * glow);
159
- fragColor = labRingColor(glow, 0.55, 0.65, 0.45, fragCoord);
160
- }
161
- `;
162
-
163
- /** One ribbon whose width pinches to zero at traveling twist points. */
164
- export const RIBBON_FRAGMENT = `${STROKE}${RING_COLOR}
165
- void mainImage(out vec4 fragColor, in vec2 fragCoord) {
166
- vec2 hres = iResolution.xy * 0.5;
167
- vec2 p = (fragCoord - hres) / hres.y;
168
- float r = length(p);
169
- float th = atan(p.y, p.x);
170
- float t = uT;
171
-
172
- float amp = uAmpIdle + uAmpVoice * uLvl;
173
- float baseR = uBaseR + uRadVoice * uLvl;
174
- float env = 0.62 + 0.38 * sin(th * 2.0 + t * uEnvSpd + 2.0);
175
-
176
- float wRaw = sin(th * 2.0 + t * uTwistSpd) * 0.6
177
- + sin(th * 3.0 - t * uTwistSpd * 0.7 + 1.7) * 0.4;
178
- float w = (abs(wRaw) * uWWidth + uWMin) * (0.55 + 0.45 * env);
179
-
180
- float c = baseR
181
- + (sin(th * uF1 + t * uS1) * 0.6
182
- + sin(th * (uF1 + 2.0) - t * uS1 * 0.63 + 2.3) * 0.4) * amp;
183
-
184
- float fl = uFlut * (0.5 + 0.9 * uLvl);
185
- float e1 = c - w + sin(th * uF2 + t * uS2) * fl;
186
- float e2 = c + w + sin(th * uF2 * 1.3 - t * uS2 * 0.8 + 2.0) * fl;
187
-
188
- float lo = min(e1, e2), hi = max(e1, e2);
189
- float ww = max(hi - lo, 0.004);
190
- float dens = clamp(uWWidth * 1.2 / ww, 0.4, 2.0);
191
-
192
- float box = smoothstep(-uSigma, uSigma, r - lo)
193
- * (1.0 - smoothstep(-uSigma, uSigma, r - hi));
194
- float u = clamp((r - lo) / ww, 0.0, 1.0);
195
- float rim = smoothstep(0.5, 1.0, abs(u - 0.5) * 2.0);
196
-
197
- float outside = max(max(lo - r, r - hi), 0.0);
198
- float bs = uSigma * uBloomMul;
199
- float halo = exp(-(outside * outside) / (2.0 * bs * bs)) * uBloomGain * dens;
200
-
201
- float glow = uGain * uFillGain
202
- * (box * dens * (1.0 + uEdgeGain * rim) + halo * (1.0 - box));
203
- fragColor = labRingColor(glow, 0.75, 0.45, 0.55, fragCoord);
204
- }
205
- `;
206
-
207
- /** Dense churning cloud cover on a stationary glass sphere. */
208
- export const PLANET_FRAGMENT = `${NOISE}${LIGHTNING}${RING_COLOR}
209
- void mainImage(out vec4 fragColor, in vec2 fragCoord) {
210
- vec2 hres = iResolution.xy * 0.5;
211
- vec2 p = (fragCoord - hres) / hres.y;
212
- float t = uT;
213
- float R = uBaseR * 2.0;
214
- float d = length(p);
215
- float mask = 1.0 - smoothstep(R - 0.012, R + 0.004, d);
216
- float zn = sqrt(max(R * R - d * d, 0.0)) / max(R, 1.0e-4);
217
- vec2 ps = p / (R * mix(1.0, 0.35 + 0.65 * zn, uLens));
218
-
219
- float tt = t * uTwistSpd;
220
- float sc = uF2 * 0.35;
221
- float turb = uWarpAmp * (0.5 + 0.8 * uLvl);
222
-
223
- float dens = 0.0;
224
- for (int k = 0; k < 3; k++) {
225
- float fk = float(k);
226
- vec2 o = vec2(fk * 7.31, fk * 3.77);
227
- vec2 pk = ps * (1.0 + fk * 0.18 * (1.0 - zn));
228
- vec2 q = vec2(
229
- labFbm(pk * sc * 0.6 + o + vec2(tt * uS1 * 0.55, 0.0)),
230
- labFbm(pk * sc * 0.6 + o + vec2(5.2, 1.3) - vec2(0.0, tt * uS2 * 0.45)));
231
- float n = labFbm(pk * sc + turb * 2.0 * (q - 0.5) + o + vec2(tt * 0.28, tt * 0.18));
232
- dens += (0.45 - fk * 0.1) * n;
233
- }
234
- dens = smoothstep(0.30 + (1.0 - uPresence) * 0.40, 0.78, dens);
235
- dens *= 0.12 + 0.88 * uPresence;
236
-
237
- vec2 lp = vec2(cos(tt * 0.23), sin(tt * 0.31)) * R * 0.35;
238
- vec2 dl = p - lp;
239
- float smoke = dens * (0.5 + 0.9 * exp(-dot(dl, dl) / (2.0 * R * R * 0.16))) * (0.55 + 0.65 * zn)
240
- + 0.05 * zn;
241
-
242
- float rim = pow(smoothstep(R * 0.62, R, d), 3.0);
243
- vec2 hp = p - vec2(-0.38, 0.42) * R;
244
- float spec = exp(-dot(hp, hp) / (2.0 * R * R * 0.004)) * uSpec;
245
- float core = uCore * exp(-(d * d) / (2.0 * R * R * 0.026));
246
- float nrl = labNeural(p, tt * 0.6, R);
247
-
248
- float glow = uGain * mask
249
- * (uFillGain * 1.6 * smoke + uEdgeGain * 0.8 * rim + spec + core * 1.3 + nrl * 1.2);
250
- fragColor = labRingColor(glow, 0.75, 0.45, 0.55, fragCoord);
251
- }
252
- `;
253
-
254
- /** Luminous smoke sealed in a stationary glass sphere, lit from within. */
255
- export const ORB_FRAGMENT = `${NOISE}${LIGHTNING}
256
- void mainImage(out vec4 fragColor, in vec2 fragCoord) {
257
- vec2 hres = iResolution.xy * 0.5;
258
- vec2 p = (fragCoord - hres) / hres.y;
259
- float t = uT;
260
- float R = uBaseR * 2.0;
261
- float d = length(p);
262
- float mask = 1.0 - smoothstep(R - 0.010, R + 0.004, d);
263
- float zn = sqrt(max(R * R - d * d, 0.0)) / max(R, 1.0e-4);
264
- float inner = 1.0 - clamp(d / max(R, 1.0e-4), 0.0, 1.0);
265
- vec2 ps = p / (R * mix(1.0, 0.35 + 0.65 * zn, uLens));
266
-
267
- float tt = t * uTwistSpd;
268
- // rigid drift plus a BOUNDED oscillating stir: shear that accumulates
269
- // forever winds any pattern into a spiral
270
- float ang = tt * 0.04
271
- + (sin(tt * 0.11) * 0.55 + sin(tt * 0.047 + 1.7) * 0.35) * inner;
272
- float ca = cos(ang), sa = sin(ang);
273
- ps = mat2(ca, -sa, sa, ca) * ps;
274
-
275
- float sc = uF2 * 0.18;
276
- float tau0 = 0.50 + 0.06 * uLvl;
277
- float bw = mix(0.16, 0.12, uLvl);
278
-
279
- vec2 lp = vec2(cos(tt * 0.21), sin(tt * 0.27)) * R * 0.42;
280
- vec2 L = normalize(lp - p + vec2(1.0e-4, 0.0));
281
-
282
- float dens = 0.0;
283
- float lit = 0.0;
284
- for (int k = 0; k < 2; k++) {
285
- float fk = float(k);
286
- vec2 o = vec2(fk * 9.17, fk * 5.13);
287
- float scale = sc * (1.0 + 0.7 * fk);
288
- vec2 pk = ps * (1.0 + fk * 0.24 * (1.0 - zn)) + o;
289
-
290
- // bounded orbit, never a straight scroll: the coverage pattern wanders
291
- // around home instead of migrating off one side of the vessel
292
- float cn = labFbm(pk * 0.9 + vec2(sin(tt * 0.041), -cos(tt * 0.033)) * 0.8);
293
- float covLo = 0.62 - 0.30 * uFillGain + 0.03 * uLvl
294
- + (1.0 - uPresence) * 0.45;
295
- float bottomness = clamp(-p.y / max(R, 1.0e-4) * 1.3 - 0.1, 0.0, 1.0);
296
- float gBias = 0.16 * inner * uPresence
297
- + max(uGather, 0.0) * 0.30 * inner
298
- + max(-uGather, 0.0) * 0.38 * bottomness;
299
- float cov = smoothstep(covLo, covLo + 0.28, cn + gBias);
300
-
301
- vec2 flow = vec2(-pk.y, pk.x) * 0.5 + vec2(0.0, 0.4);
302
- float cyc = tt * 0.10 * uS1 * (1.0 + 0.6 * fk);
303
- float ph0 = fract(cyc + 0.35 * cn);
304
- float ph1 = fract(cyc + 0.35 * cn + 0.5);
305
- float w0 = 1.0 - abs(1.0 - 2.0 * ph0);
306
-
307
- vec2 w2 = vec2(labFbm(pk * scale * 0.5 + vec2(sin(tt * 0.09 * uS2), cos(tt * 0.075 * uS2)) * 0.9),
308
- labFbm(pk * scale * 0.5 + vec2(3.7, 8.1) + vec2(cos(tt * 0.065 * uS2), sin(tt * 0.083 * uS2)) * 0.9));
309
- vec2 qw = pk * scale + uWarpAmp * 3.0 * (w2 - 0.5);
310
-
311
- float n = mix(labFbm(qw - flow * 1.2 * ph1), labFbm(qw - flow * 1.2 * ph0), w0);
312
- float sgn = 2.0 * n - 1.0;
313
- float ridge = 1.0 - abs(sgn);
314
- ridge *= ridge;
315
- float band = smoothstep(tau0 - bw, tau0, n) * (1.0 - smoothstep(tau0, tau0 + bw, n));
316
- float dk = cov * (band * (0.6 + 0.5 * ridge) + 0.12 * n * cov);
317
- dens += (0.60 - 0.22 * fk) * dk;
318
-
319
- float nL = labFbm(qw + L * 0.5);
320
- lit += clamp((nL - n) * 3.0, 0.0, 1.0) * dk;
321
- }
322
- dens *= 1.0 - smoothstep(0.72, 0.97, d / max(R, 1.0e-4));
323
- dens *= (0.45 + 1.25 * uFillGain) * (1.0 + 0.25 * uLvl);
324
- dens *= 0.08 + 0.92 * uPresence;
325
- float dEff = clamp(dens, 0.0, 1.5) * (0.5 + 0.5 * zn);
326
- float aSmoke = 1.0 - exp(-2.6 * dEff);
327
-
328
- float rL = length(p - lp) / R;
329
- float G = 1.0 / (1.0 + 2.0 * rL + 8.0 * rL * rL);
330
- float act = 0.7 + 0.8 * uLvl;
331
-
332
- vec3 albedo = mix(vec3(0.84, 0.87, 0.92), uColor, uTint);
333
- vec3 body = albedo * (0.30 + 0.55 * exp(-1.4 * dEff))
334
- + uColor * (lit * 0.5 + dEff * G * 1.1) * act;
335
- vec3 bgIn = uColor * 0.05 * zn;
336
- vec3 col = mix(bgIn, body, aSmoke)
337
- + uColor * G * act * 0.18 * zn;
338
-
339
- float rim = pow(smoothstep(R * 0.66, R, d), 3.0);
340
- vec2 hp = p - vec2(-0.38, 0.42) * R;
341
- float spec = exp(-dot(hp, hp) / (2.0 * R * R * 0.004)) * uSpec;
342
- float core = uCore * exp(-(d * d) / (2.0 * R * R * 0.022));
343
- float nrl = labNeural(p, tt * 0.6, R);
344
- col += uColor * rim * uEdgeGain * 0.7 + vec3(spec) + uColor * core * 1.5
345
- + uColor * nrl * (0.7 + 0.6 * aSmoke);
346
-
347
- col *= uGain * mask;
348
- float alpha = clamp((aSmoke * 0.9 + G * act * 0.15 * zn + core + nrl * 0.55
349
- + rim * uEdgeGain * 0.5 + spec + 0.03 * zn) * uGain, 0.0, 1.0) * mask;
350
- float nz = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);
351
- alpha = clamp(alpha + (nz - 0.5) / 255.0, 0.0, 1.0);
352
- fragColor = vec4(col, alpha);
353
- }
354
- `;
355
-
356
- export type LabLook = 'braid' | 'ribbon' | 'planet' | 'orb';
357
-
358
- export const LAB_FRAGMENTS: Record<LabLook, string> = {
359
- braid: BRAID_FRAGMENT,
360
- ribbon: RIBBON_FRAGMENT,
361
- planet: PLANET_FRAGMENT,
362
- orb: ORB_FRAGMENT,
363
- };
@@ -1,102 +0,0 @@
1
- import { createSignal, onCleanup, onMount, type JSX } from 'solid-js';
2
- import { ShaderCanvas, hexToRgb, type UniformSpec } from '../shader-canvas';
3
- import { LAB_FRAGMENTS, type LabLook } from './lab-shaders';
4
- import { createChoreography, LOOK_DEFAULTS, type LabParams, type LabState } from './lab-choreography';
5
-
6
- export interface LabVisualizerProps {
7
- look: LabLook;
8
- state?: LabState;
9
- color?: string;
10
- /** Square canvas edge in px. */
11
- size?: number;
12
- /** Overrides on the look's tuned defaults. */
13
- params?: Partial<LabParams>;
14
- }
15
-
16
- /**
17
- * Runs one lab look through the same `ShaderCanvas` the shipped variants use,
18
- * with the playground's state choreography driving the uniforms per frame.
19
- * While `speaking`, a baked loudness loop stands in for a live voice.
20
- */
21
- export function LabVisualizer(props: LabVisualizerProps): JSX.Element {
22
- const merged = (): LabParams => {
23
- const out: LabParams = { ...LOOK_DEFAULTS[props.look] };
24
- for (const [key, value] of Object.entries(props.params ?? {})) {
25
- if (typeof value === 'number' && Number.isFinite(value)) {
26
- (out as unknown as Record<string, number>)[key] = value;
27
- }
28
- }
29
- return out;
30
- };
31
- const chor = createChoreography(() => props.look, () => props.state ?? 'manual', merged);
32
- const [frame, setFrame] = createSignal(chor.step(0));
33
-
34
- onMount(() => {
35
- // Captured at SETUP and closed over, never re-resolved as a global inside
36
- // `onCleanup`: cleanup can run after the host removed the DOM globals (a
37
- // `kai-*` release is deferred one microtask past detachment, so an
38
- // environment teardown gets in between), and a bare `cancelAnimationFrame`
39
- // there throws -- from a promise nobody holds, so it lands as an unhandled
40
- // rejection that fails the run while every test passes.
41
- // See tests/components/teardown-without-dom-globals.test.tsx.
42
- //
43
- // The FUNCTION, not the view. The `const win = window` capture that fixes a
44
- // bare `document` does nothing here: `window === globalThis` -- measured, in
45
- // jsdom and in real Chromium/WebKit alike -- and the teardown deletes these
46
- // keys off that very object, so `win.cancelAnimationFrame` is undefined by
47
- // the time cleanup runs. It only trades the ReferenceError for a TypeError.
48
- // `.bind` pins the receiver the WebIDL operation is specified on; Chromium
49
- // and WebKit both accept a detached call (measured), so the bind is belt and
50
- // braces against an engine that does not, at zero cost.
51
- const cancelFrame = cancelAnimationFrame.bind(globalThis);
52
-
53
- let raf = 0;
54
- let last = performance.now();
55
- const loop = (): void => {
56
- const now = performance.now();
57
- const dt = Math.min((now - last) / 1000, 0.1);
58
- last = now;
59
- setFrame(chor.step(dt));
60
- raf = requestAnimationFrame(loop);
61
- };
62
- raf = requestAnimationFrame(loop);
63
- onCleanup(() => cancelFrame(raf));
64
- });
65
-
66
- const uniforms = (): Record<string, UniformSpec> => {
67
- const f = frame();
68
- const v = f.values;
69
- const one = (value: number): UniformSpec => ({ type: '1f', value });
70
- return {
71
- uColor: { type: '3fv', value: hexToRgb(props.color ?? '#1fd5f9') },
72
- uT: one(f.t),
73
- uLvl: one(f.level),
74
- uBaseR: one(v.baseR), uAmpIdle: one(v.ampIdle), uAmpVoice: one(v.ampVoice),
75
- uRadVoice: one(v.radVoice), uSigma: one(v.sigma), uGain: one(v.gain),
76
- uF1: one(v.f1), uF2: one(v.f2), uS1: one(v.s1), uS2: one(v.s2),
77
- uEnvSpd: one(v.envSpd), uSepSpd: one(v.sepSpd),
78
- uWhiteLo: one(v.whiteLo), uWhiteHi: one(v.whiteHi),
79
- uBloomMul: one(v.bloomMul), uBloomGain: one(v.bloomGain),
80
- uDelta: one(v.delta), uOff: one(v.off),
81
- uWWidth: one(v.wWidth), uWMin: one(v.wMin),
82
- uFillGain: one(v.fillGain), uEdgeGain: one(v.edgeGain), uFlut: one(v.flut),
83
- uTwistSpd: one(v.twistSpd), uWarpAmp: one(v.warpAmp),
84
- uLens: one(v.lens), uSpec: one(v.spec), uTint: one(v.tint),
85
- uPresence: one(v.presence), uGather: one(v.gather), uCore: one(v.core),
86
- uNeural: one(v.neural), uBoltJag: one(v.boltJag),
87
- uBoltWidth: one(v.boltWidth), uBoltRate: one(v.boltRate),
88
- };
89
- };
90
-
91
- const edge = (): string => `${props.size ?? 320}px`;
92
-
93
- return (
94
- <div style={{ width: edge(), height: edge() }}>
95
- <ShaderCanvas
96
- fragment={LAB_FRAGMENTS[props.look]}
97
- uniforms={uniforms()}
98
- onError={(message) => console.warn(`lab visualizer (${props.look}):`, message)}
99
- />
100
- </div>
101
- );
102
- }