@kitn.ai/ui 0.20.1 → 0.22.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.
- package/README.md +44 -45
- package/dist/components/artifact-card.d.ts +51 -0
- package/dist/components/artifact.d.ts +1 -1
- package/dist/components/attachments.d.ts +2 -2
- package/dist/components/audio-visualizer/index.d.ts +3 -3
- package/dist/components/audio-visualizer/labs/lab-choreography.d.ts +59 -0
- package/dist/components/audio-visualizer/labs/lab-shaders.d.ts +22 -0
- package/dist/components/audio-visualizer/labs/lab-visualizer.d.ts +18 -0
- package/dist/components/audio-visualizer/variant-aurora.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-bar.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-custom.d.ts +2 -2
- package/dist/components/audio-visualizer/variant-grid.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-radial.d.ts +1 -1
- package/dist/components/audio-visualizer/variant-wave.d.ts +1 -1
- package/dist/components/card-fallback.d.ts +12 -2
- package/dist/components/card-renderer.d.ts +63 -2
- package/dist/components/chat-container.d.ts +3 -0
- package/dist/components/chat-scope-picker.d.ts +2 -2
- package/dist/components/chat-thread.d.ts +77 -18
- package/dist/components/choice-card.d.ts +3 -28
- package/dist/components/composer-dom.d.ts +1 -1
- package/dist/components/composer-highlight.d.ts +1 -1
- package/dist/components/composer-history.d.ts +1 -1
- package/dist/components/composer.d.ts +1 -1
- package/dist/components/confirm-card.d.ts +3 -18
- package/dist/components/context.d.ts +8 -4
- package/dist/components/conversation-item.d.ts +1 -1
- package/dist/components/conversation-list.d.ts +4 -3
- package/dist/components/embed.d.ts +3 -3
- package/dist/components/file-tree.d.ts +11 -22
- package/dist/components/form-widgets.d.ts +1 -1
- package/dist/components/form.d.ts +3 -44
- package/dist/components/link-preview.d.ts +3 -3
- package/dist/components/loader.d.ts +30 -48
- package/dist/components/message-skills.d.ts +4 -0
- package/dist/components/message.d.ts +84 -21
- package/dist/components/model-switcher.d.ts +2 -2
- package/dist/components/prompt-input.d.ts +2 -2
- package/dist/components/response-compare-types.d.ts +11 -2
- package/dist/components/response-compare.d.ts +3 -3
- package/dist/components/source.d.ts +12 -3
- package/dist/components/tasks-card.d.ts +3 -31
- package/dist/components/thread.d.ts +17 -5
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/tool-classify.d.ts +8 -0
- package/dist/components/tool-types.d.ts +29 -1
- package/dist/components/tool.d.ts +3 -3
- package/dist/components/use-card-resolution.d.ts +1 -1
- package/dist/create-tween-COnPwAQN.js +338 -0
- package/dist/create-tween-DmTUaXWE.js +341 -0
- package/dist/create-tween-qs-jjvNA.js +7 -0
- package/dist/custom-elements.json +1726 -463
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-types.d.ts +70 -10
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/chunks/{Icon-Tj58ES_d.js → Icon-CHG5z5L7.js} +1 -1
- package/dist/elements/chunks/{action-icons-ns1Fnedj.js → action-icons-BAtCEEgg.js} +1 -1
- package/dist/elements/chunks/arrow-left-CFPTeL1Y.js +1 -0
- package/dist/elements/chunks/artifact-fBZOE4SO.js +1 -0
- package/dist/elements/chunks/{attachments-mCB5F1Fq.js → attachments-DpYMe5VQ.js} +1 -1
- package/dist/elements/chunks/audio-visualizer-DFwzAcuL.js +1 -0
- package/dist/elements/chunks/{badge-B4Zuajl2.js → badge-D6zodm6E.js} +1 -1
- package/dist/elements/chunks/{button-ZWNif3--.js → button-C42vrGvO.js} +1 -1
- package/dist/elements/chunks/card-renderer-DMZsSuvU.js +1 -0
- package/dist/elements/chunks/card-tags-D8lZ-C_U.js +1 -0
- package/dist/elements/chunks/chat-thread-CNNEhol-.js +1 -0
- package/dist/elements/chunks/check-7Q3K-iXE.js +1 -0
- package/dist/elements/chunks/chevron-down-CpNYLn7E.js +1 -0
- package/dist/elements/chunks/chevron-right-DrH85Fha.js +1 -0
- package/dist/elements/chunks/choice-card-YoWjpsFV.js +1 -0
- package/dist/elements/chunks/circle-C9KRjKYv.js +1 -0
- package/dist/elements/chunks/circle-check-Dmi7Y4zw.js +1 -0
- package/dist/elements/chunks/{circle-x-B7faJFlY.js → circle-x-QIxXda6k.js} +1 -1
- package/dist/elements/chunks/code-block-CqeugReY.js +1 -0
- package/dist/elements/chunks/{collapsible-DM1Ckd4e.js → collapsible-sTv-_5lF.js} +1 -1
- package/dist/elements/chunks/{composer-BguS0QL_.js → composer-ldQyeVEB.js} +2 -2
- package/dist/elements/chunks/confirm-card-C0RNOwfn.js +1 -0
- package/dist/elements/chunks/context-5qgypNHC.js +1 -0
- package/dist/elements/chunks/conversation-list-DLzOacXz.js +1 -0
- package/dist/elements/chunks/create-tween-V4TXZ93X.js +7 -0
- package/dist/elements/chunks/default-input-DeeRSDHc.js +1 -0
- package/dist/elements/chunks/define-lE-QvQFn.js +1 -0
- package/dist/elements/chunks/{disclosure-CIZ5c8nO.js → disclosure-DZSa9jog.js} +1 -1
- package/dist/elements/chunks/{download-Dsbg3ste.js → download-B2ZmnGqW.js} +1 -1
- package/dist/elements/chunks/{dropdown-BDd1-Zgi.js → dropdown-R3B7cSRE.js} +1 -1
- package/dist/elements/chunks/{ellipsis-Dw6qrss-.js → ellipsis-BmxceY4l.js} +1 -1
- package/dist/elements/chunks/embed-BVrtTZPo.js +1 -0
- package/dist/elements/chunks/{external-link-Vt74zAoL.js → external-link-BbdR7YO7.js} +1 -1
- package/dist/elements/chunks/{file-text-CZrZF6_v.js → file-text-D7dijo1A.js} +1 -1
- package/dist/elements/chunks/{file-tree-DF4okKyo.js → file-tree-0upJ5jeb.js} +1 -1
- package/dist/elements/chunks/{folder-glP5rha4.js → folder-D8z58t7B.js} +1 -1
- package/dist/elements/chunks/form-p5BKJNw5.js +1 -0
- package/dist/elements/chunks/hover-card-CN9s2md5.js +1 -0
- package/dist/elements/chunks/{icon-BLb8beoi.js → icon-CNiKP37E.js} +1 -1
- package/dist/elements/chunks/{info-CIsv92JK.js → info-BSnuJiHI.js} +1 -1
- package/dist/elements/chunks/{input-Dds1kFyt.js → input-BauDmzxX.js} +1 -1
- package/dist/elements/chunks/{kbd-De_xbgi9.js → kbd-BlHJaP9b.js} +1 -1
- package/dist/elements/chunks/{link-i4r_k7z4.js → link-DEi5iUWC.js} +1 -1
- package/dist/elements/chunks/link-preview-BaHyM6W4.js +1 -0
- package/dist/elements/chunks/{loader-BmQH4s3V.js → loader-CmJG_Fkq.js} +1 -1
- package/dist/elements/chunks/{markdown-Zi21WhUz.js → markdown-D2jaMpCN.js} +1 -1
- package/dist/elements/chunks/message-C5UfXZ2Z.js +1 -0
- package/dist/elements/chunks/message-CXWLmmLn.js +1 -0
- package/dist/elements/chunks/message-square-hXylwsy0.js +1 -0
- package/dist/elements/chunks/{minimize-2--ifeCGrl.js → minimize-2-C9ytZFMU.js} +1 -1
- package/dist/elements/chunks/model-switcher-CivGfD7-.js +1 -0
- package/dist/elements/chunks/{overlay-kD8dwRv_.js → overlay-DJL_sbOm.js} +1 -1
- package/dist/elements/chunks/{paperclip-q21dYOSK.js → paperclip-CFaB8naM.js} +1 -1
- package/dist/elements/chunks/{progress-bar-BrAIIaaJ.js → progress-bar-Br5SksfR.js} +1 -1
- package/dist/elements/chunks/{prompt-suggestion-Bjn2K-fR.js → prompt-suggestion-CMIvtAhU.js} +1 -1
- package/dist/elements/chunks/reasoning-DpZcNzLq.js +1 -0
- package/dist/elements/chunks/{resizable-Dp4JExql.js → resizable-Q8i3T9a_.js} +1 -1
- package/dist/elements/chunks/{rotate-cw-CFWWkpj2.js → rotate-cw-B5IHCBFV.js} +1 -1
- package/dist/elements/chunks/{scroll-area-Bb0kHH1j.js → scroll-area-eLeydBje.js} +1 -1
- package/dist/elements/chunks/scroll-button-DWbz0yA1.js +1 -0
- package/dist/elements/chunks/{separator-9kRgr1X9.js → separator-Xic78AD_.js} +1 -1
- package/dist/elements/chunks/{settings-B8lmec4D.js → settings-B8H51pAx.js} +1 -1
- package/dist/elements/chunks/{settings-group-I0hEuXiN.js → settings-group-CsG9eYLe.js} +1 -1
- package/dist/elements/chunks/{share-C3lTiYGt.js → share-CNTx0z__.js} +1 -1
- package/dist/elements/chunks/skeleton-CLlHTcMI.js +1 -0
- package/dist/elements/chunks/slots-CIw9RlAe.js +1 -0
- package/dist/elements/chunks/source-BoVcU5ok.js +1 -0
- package/dist/elements/chunks/{star-CSJtGxgv.js → star-CxQVTVhI.js} +1 -1
- package/dist/elements/chunks/{store-CHyW95TP.js → store-CLtS5CUG.js} +1 -1
- package/dist/elements/chunks/tasks-card-CzlkLmUt.js +1 -0
- package/dist/elements/chunks/{text-shimmer-Cn9TmNpI.js → text-shimmer-D5NhpIQ1.js} +1 -1
- package/dist/elements/chunks/textarea-x5Uxsmtm.js +1 -0
- package/dist/elements/chunks/{thumbs-up-PNVVThEF.js → thumbs-up-UobcJnx9.js} +1 -1
- package/dist/elements/chunks/{toast-store-DKbQn3Wn.js → toast-store-BOfs9eXq.js} +1 -1
- package/dist/elements/chunks/{tool-DjTRpIpl.js → tool-Be6Dh_dt.js} +1 -1
- package/dist/elements/chunks/tooltip-RxMxyCLF.js +1 -0
- package/dist/elements/chunks/{triangle-alert-DsHTHCPm.js → triangle-alert-C4yxH2XN.js} +1 -1
- package/dist/elements/chunks/use-card-resolution-jva9ehH6.js +1 -0
- package/dist/elements/chunks/{variant-aurora-Dc4nQUia.js → variant-aurora-Dx4VRcjS.js} +2 -2
- package/dist/elements/chunks/{variant-custom-y_3kVQhS.js → variant-custom-Y1ZTWgEa.js} +1 -1
- package/dist/elements/chunks/{variant-wave-D5OR1-9Z.js → variant-wave-B9gml9Cg.js} +2 -2
- package/dist/elements/chunks/{video-B7vmenoC.js → video-CrPHsytT.js} +1 -1
- package/dist/elements/chunks/x-_-OPHept.js +1 -0
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +34 -7
- package/dist/elements/define.d.ts +1 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/disclosure.d.ts +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/element-data-types.d.ts +107 -0
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/register.d.ts +8 -6
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +1 -1
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slot-text.d.ts +51 -0
- package/dist/elements/slots.d.ts +21 -0
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/validate-messages.d.ts +25 -0
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +2734 -217
- package/dist/index.d.ts +163 -125
- package/dist/index.js +6572 -5990
- package/dist/index.server.d.ts +5 -0
- package/dist/index.server.js +5403 -4860
- package/dist/kai-provider.es.d.ts +5 -0
- package/dist/kai-provider.es.js +79 -77
- package/dist/kai.es.d.ts +5 -0
- package/dist/kai.es.js +1 -1
- package/dist/llms/llms-full.txt +774 -151
- package/dist/llms/llms.txt +57 -5
- package/dist/mcp.es.js +4756 -782
- package/dist/primitives/card-component-types.d.ts +11 -0
- package/dist/primitives/card-data-types.d.ts +196 -0
- package/dist/primitives/card-host.d.ts +1 -1
- package/dist/primitives/card-recovery.d.ts +3 -3
- package/dist/primitives/card-registry.d.ts +4 -14
- package/dist/primitives/card-resolution.d.ts +1 -1
- package/dist/primitives/card-routing.d.ts +1 -1
- package/dist/primitives/card-tags.d.ts +11 -0
- package/dist/primitives/card-validate-cards.d.ts +57 -0
- package/dist/primitives/card-validate-generator.testlib.d.ts +20 -0
- package/dist/primitives/card-validate-schemas.d.ts +17 -0
- package/dist/primitives/card-validate.d.ts +24 -0
- package/dist/primitives/create-kai-chat.d.ts +3 -3
- package/dist/primitives/embed-providers.d.ts +1 -1
- package/dist/primitives/link-preview.d.ts +1 -1
- package/dist/primitives/message-feedback.d.ts +2 -2
- package/dist/primitives/toast-store.d.ts +1 -1
- package/dist/react/index.d.ts +730 -302
- package/dist/react/use-kai-chat.d.ts +8 -4
- package/dist/react.d.ts +5 -0
- package/dist/react.js +418 -317
- package/dist/register-impl-AxIlqjo7.js +145 -0
- package/dist/remote/host-embed.d.ts +1 -1
- package/dist/remote/index.d.ts +2 -2
- package/dist/remote/provider-runtime.d.ts +2 -2
- package/dist/remote/provider.d.ts +2 -2
- package/dist/remote/validate.d.ts +1 -1
- package/dist/remote/wire.d.ts +1 -1
- package/dist/schemas/artifact.schema.json +92 -0
- package/dist/schemas/embed.schema.json +0 -2
- package/dist/schemas/from-tool-call.d.ts +48 -0
- package/dist/schemas/index.d.ts +48 -0
- package/dist/schemas/link.schema.json +0 -2
- package/dist/schemas/provider-subsets.d.ts +136 -0
- package/dist/schemas/registry.d.ts +140 -0
- package/dist/schemas/tool-defs.d.ts +121 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.js +717 -0
- package/dist/solid-BGYSJyHG.js +22960 -0
- package/dist/solid-Dt2nEwfl.js +20194 -0
- package/dist/solid.d.ts +66 -0
- package/dist/solid.js +261 -0
- package/dist/solid.server.d.ts +5 -0
- package/dist/solid.server.js +261 -0
- package/dist/state/index.d.ts +14 -4
- package/dist/state/messages.d.ts +8 -3
- package/dist/state/mock.d.ts +46 -0
- package/dist/state/parts.d.ts +85 -0
- package/dist/state/stream.d.ts +15 -9
- package/dist/state.d.ts +5 -0
- package/dist/state.js +253 -84
- package/dist/ui/action-icons.d.ts +1 -1
- package/dist/ui/collapsible.d.ts +11 -6
- package/dist/ui/dropdown.d.ts +47 -42
- package/dist/ui/pane-group.d.ts +1 -1
- package/dist/{variant-aurora-DVtGqVH6.js → variant-aurora-B44X69AG.js} +1 -1
- package/dist/variant-aurora-BRhV8Flk.js +391 -0
- package/dist/variant-aurora-Ds5ou9BH.js +381 -0
- package/dist/variant-custom-B20FhtYj.js +170 -0
- package/dist/{variant-custom-Dif-IV4u.js → variant-custom-BvA1Schl.js} +1 -1
- package/dist/variant-custom-D6Rtvneb.js +200 -0
- package/dist/{variant-wave-DbfNdvSi.js → variant-wave-BUQtkryq.js} +1 -1
- package/dist/variant-wave-BVYnqy9L.js +218 -0
- package/dist/variant-wave-DXC6_LcH.js +208 -0
- package/dist/wire/chunk.d.ts +171 -0
- package/dist/wire/consume.d.ts +26 -0
- package/dist/wire/encode.d.ts +221 -0
- package/dist/wire/files.d.ts +116 -0
- package/dist/wire/formats/anthropic.d.ts +2 -0
- package/dist/wire/formats/openai.d.ts +5 -0
- package/dist/wire/index.d.ts +16 -0
- package/dist/wire/media-types.d.ts +106 -0
- package/dist/wire/read.d.ts +26 -0
- package/dist/wire/sink-helpers.d.ts +21 -0
- package/dist/wire/sse.d.ts +33 -0
- package/dist/wire.d.ts +5 -53
- package/dist/wire.js +1126 -0
- package/frameworks/react/index.tsx +191 -158
- package/frameworks/react/runtime.tsx +21 -1
- package/frameworks/react/use-kai-chat.tsx +11 -1
- package/llms-full.txt +774 -151
- package/llms.txt +57 -5
- package/package.json +62 -8
- package/src/agent-tooling/archetypes.ts +127 -0
- package/src/agent-tooling/integrations/anthropic.ts +436 -0
- package/src/agent-tooling/integrations/cloudflare.ts +141 -52
- package/src/agent-tooling/integrations/langgraph.ts +80 -13
- package/src/agent-tooling/integrations/mastra.ts +161 -12
- package/src/agent-tooling/integrations/mock.ts +47 -8
- package/src/agent-tooling/integrations/ollama.ts +68 -24
- package/src/agent-tooling/integrations/openai.ts +89 -0
- package/src/agent-tooling/integrations/openrouter.ts +58 -8
- package/src/agent-tooling/integrations/pi.ts +104 -23
- package/src/agent-tooling/integrations/pydantic-ai.ts +61 -5
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +120 -13
- package/src/agent-tooling/mcp/manifest.ts +206 -25
- package/src/agent-tooling/mcp/tools/debug.ts +13 -7
- package/src/agent-tooling/mcp/tools/reference.ts +285 -6
- package/src/agent-tooling/mcp/tools/scaffold.ts +4152 -661
- package/src/agent-tooling/registry.ts +74 -0
- package/src/agent-tooling/types.ts +361 -1
- package/src/components/artifact-card.tsx +120 -0
- package/src/components/audio-visualizer/index.tsx +9 -0
- package/src/components/audio-visualizer/labs/lab-choreography.ts +187 -0
- package/src/components/audio-visualizer/labs/lab-shaders.ts +363 -0
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +102 -0
- package/src/components/audio-visualizer/shader-canvas.tsx +31 -1
- package/src/components/card-fallback.tsx +42 -10
- package/src/components/card-renderer.tsx +146 -9
- package/src/components/chat-container.tsx +4 -0
- package/src/components/chat-thread.tsx +128 -52
- package/src/components/choice-card.tsx +17 -29
- package/src/components/composer.tsx +12 -2
- package/src/components/confirm-card.tsx +24 -20
- package/src/components/context.tsx +30 -16
- package/src/components/conversation-item.tsx +6 -0
- package/src/components/conversation-list.tsx +18 -2
- package/src/components/file-tree.tsx +11 -22
- package/src/components/file-upload.tsx +14 -8
- package/src/components/form.tsx +14 -47
- package/src/components/loader.tsx +39 -12
- package/src/components/message-skills.tsx +4 -0
- package/src/components/message.tsx +294 -46
- package/src/components/model-switcher.tsx +38 -8
- package/src/components/reasoning.tsx +92 -5
- package/src/components/response-compare-types.ts +25 -0
- package/src/components/response-compare.tsx +4 -9
- package/src/components/source.tsx +50 -24
- package/src/components/tasks-card.tsx +10 -33
- package/src/components/thread.tsx +84 -42
- package/src/components/toast.tsx +17 -6
- package/src/components/tool-classify.ts +26 -0
- package/src/components/tool-types.ts +31 -1
- package/src/elements/agent-card.tsx +11 -11
- package/src/elements/artifact.tsx +15 -7
- package/src/elements/attachments.tsx +6 -4
- package/src/elements/avatar.tsx +1 -1
- package/src/elements/button.tsx +29 -6
- package/src/elements/card.tsx +2 -2
- package/src/elements/cards.tsx +109 -14
- package/src/elements/chain-of-thought.tsx +14 -10
- package/src/elements/chat-scope-picker.tsx +9 -7
- package/src/elements/chat-types.ts +59 -6
- package/src/elements/chat-workspace.tsx +50 -9
- package/src/elements/chat.tsx +90 -3
- package/src/elements/choice.tsx +8 -8
- package/src/elements/coachmark.tsx +1 -1
- package/src/elements/command.tsx +8 -23
- package/src/elements/compare.tsx +7 -6
- package/src/elements/compiled.css +1 -1
- package/src/elements/composer.tsx +8 -8
- package/src/elements/confirm-card.tsx +9 -9
- package/src/elements/context-meter.tsx +4 -18
- package/src/elements/conversation-list.tsx +14 -9
- package/src/elements/default-input.tsx +131 -8
- package/src/elements/define.tsx +178 -43
- package/src/elements/editable-label.tsx +17 -2
- package/src/elements/element-data-types.ts +112 -0
- package/src/elements/element-meta.json +1624 -306
- package/src/elements/element-types.d.ts +2645 -214
- package/src/elements/feedback-bar.tsx +1 -1
- package/src/elements/file-tree.tsx +1 -1
- package/src/elements/file-upload.tsx +1 -1
- package/src/elements/form.tsx +14 -6
- package/src/elements/input.tsx +1 -1
- package/src/elements/kbd.tsx +1 -1
- package/src/elements/menu.tsx +40 -32
- package/src/elements/message-skills.tsx +7 -9
- package/src/elements/message.tsx +200 -32
- package/src/elements/model-switcher.tsx +5 -3
- package/src/elements/pane.tsx +1 -1
- package/src/elements/prompt-dock.tsx +8 -8
- package/src/elements/prompt-input.tsx +10 -10
- package/src/elements/prompt-suggestions.tsx +7 -4
- package/src/elements/reasoning.tsx +1 -1
- package/src/elements/register.ts +9 -0
- package/src/elements/resizable.globals.d.ts +36 -0
- package/src/elements/resizable.tsx +24 -13
- package/src/elements/response-stream.tsx +1 -1
- package/src/elements/scroll-button.tsx +1 -1
- package/src/elements/search.tsx +6 -1
- package/src/elements/segmented.tsx +5 -11
- package/src/elements/separator.tsx +1 -1
- package/src/elements/slot-text.ts +73 -0
- package/src/elements/slots.ts +67 -24
- package/src/elements/source.tsx +21 -22
- package/src/elements/switch.tsx +3 -3
- package/src/elements/tasks.tsx +5 -4
- package/src/elements/thread.tsx +36 -4
- package/src/elements/toast.tsx +3 -2
- package/src/elements/tool.tsx +1 -1
- package/src/elements/validate-messages.ts +76 -0
- package/src/elements/voice-input.tsx +7 -7
- package/src/elements/voice-output.tsx +4 -4
- package/src/index.ts +145 -6
- package/src/primitives/card-component-types.ts +63 -0
- package/src/primitives/card-data-types.ts +312 -0
- package/src/primitives/card-recovery.ts +13 -2
- package/src/primitives/card-registry.tsx +34 -23
- package/src/primitives/card-schemas/artifact.schema.json +92 -0
- package/src/primitives/card-schemas/embed.schema.json +0 -2
- package/src/primitives/card-schemas/link.schema.json +0 -2
- package/src/primitives/card-tags.ts +61 -0
- package/src/primitives/card-validate-cards.ts +255 -0
- package/src/primitives/card-validate-generator.testlib.ts +38 -0
- package/src/primitives/card-validate-schemas.ts +58 -0
- package/src/primitives/card-validate.ts +48 -20
- package/src/primitives/create-tween.ts +54 -2
- package/src/primitives/message-feedback.ts +3 -2
- package/src/primitives/use-audio-analysis.ts +20 -1
- package/src/primitives/use-sequencer.ts +20 -1
- package/src/schemas/from-tool-call.ts +151 -0
- package/src/schemas/index.ts +340 -0
- package/src/schemas/provider-subsets.ts +538 -0
- package/src/schemas/registry.ts +355 -0
- package/src/schemas/tool-defs.ts +492 -0
- package/src/solid.ts +150 -0
- package/src/state/index.ts +27 -1
- package/src/state/messages.ts +21 -4
- package/src/state/mock.ts +211 -0
- package/src/state/parts.ts +295 -0
- package/src/state/stream.ts +56 -58
- package/src/ui/collapsible.tsx +17 -5
- package/src/ui/dropdown.tsx +46 -12
- package/src/ui/overlay.tsx +10 -4
- package/src/wire/chunk.ts +201 -0
- package/src/wire/consume.ts +440 -0
- package/src/wire/encode.ts +689 -0
- package/src/wire/files.ts +342 -0
- package/src/wire/formats/anthropic.ts +267 -0
- package/src/wire/formats/openai.ts +187 -0
- package/src/wire/index.ts +73 -0
- package/src/wire/media-types.ts +344 -0
- package/src/wire/read.ts +152 -0
- package/src/wire/sink-helpers.ts +50 -0
- package/src/wire/sse.ts +140 -0
- package/dist/create-tween-hvpmSuwW.js +0 -7
- package/dist/elements/chunks/arrow-left-DQocUFvy.js +0 -1
- package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +0 -1
- package/dist/elements/chunks/card-BkHbp4BA.js +0 -1
- package/dist/elements/chunks/chat-thread-CkRN6pZ7.js +0 -1
- package/dist/elements/chunks/check-B9-gn6SS.js +0 -1
- package/dist/elements/chunks/chevron-down-BNsxc2hk.js +0 -1
- package/dist/elements/chunks/chevron-right-Hv00StBO.js +0 -1
- package/dist/elements/chunks/circle-0e3KJTDr.js +0 -1
- package/dist/elements/chunks/circle-check-BNAS0JEy.js +0 -1
- package/dist/elements/chunks/code-block-BFUHn6Va.js +0 -1
- package/dist/elements/chunks/context-Cb7k4F-v.js +0 -1
- package/dist/elements/chunks/conversation-list-CvoAkWhN.js +0 -1
- package/dist/elements/chunks/create-tween-oVvAIG8r.js +0 -7
- package/dist/elements/chunks/default-input-Cqqilg9t.js +0 -1
- package/dist/elements/chunks/define-D1din7Ld.js +0 -1
- package/dist/elements/chunks/hover-card-Cmm6Q53m.js +0 -1
- package/dist/elements/chunks/message-BqyXDN3-.js +0 -1
- package/dist/elements/chunks/message-feedback-Djr3z6Yb.js +0 -1
- package/dist/elements/chunks/message-square-vFAgbDaX.js +0 -1
- package/dist/elements/chunks/model-switcher-B94YAKsM.js +0 -1
- package/dist/elements/chunks/reasoning-DTpCGtnY.js +0 -1
- package/dist/elements/chunks/scroll-button-B0cH5fXf.js +0 -1
- package/dist/elements/chunks/skeleton-DSXW5Yya.js +0 -1
- package/dist/elements/chunks/slots--V19HwUb.js +0 -1
- package/dist/elements/chunks/textarea-CUwqAX0G.js +0 -1
- package/dist/elements/chunks/tooltip-CgBZCVKp.js +0 -1
- package/dist/elements/chunks/use-card-resolution-BSu_XHjH.js +0 -1
- package/dist/elements/chunks/x-GRUeeQFT.js +0 -1
- package/dist/host-embed.d.ts +0 -33
- package/dist/kai-provider.d.ts +0 -2
- package/dist/origin.d.ts +0 -5
- package/dist/provider-runtime.d.ts +0 -27
- package/dist/register-impl-DQyejdfb.js +0 -145
- package/dist/validate.d.ts +0 -4
- package/dist/version.d.ts +0 -4
- package/src/components/component-meta.json +0 -4550
- package/src/elements/card-media.jpg +0 -0
- package/src/elements/resizable.d.ts +0 -27
- package/src/elements/video-poster.jpg +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,363 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
}
|