@kitn.ai/ui 0.19.0 → 0.20.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 (235) hide show
  1. package/LICENSE +6 -0
  2. package/NOTICE +54 -0
  3. package/dist/components/audio-visualizer/audio-visualizer.voice-fixture.d.ts +59 -0
  4. package/dist/components/audio-visualizer/aurora.glsl.d.ts +114 -0
  5. package/dist/components/audio-visualizer/index.d.ts +155 -0
  6. package/dist/components/audio-visualizer/shader-canvas.d.ts +130 -0
  7. package/dist/components/audio-visualizer/sizes.d.ts +25 -0
  8. package/dist/components/audio-visualizer/variant-aurora.d.ts +89 -0
  9. package/dist/components/audio-visualizer/variant-bar.d.ts +46 -0
  10. package/dist/components/audio-visualizer/variant-custom.d.ts +73 -0
  11. package/dist/components/audio-visualizer/variant-grid.d.ts +22 -0
  12. package/dist/components/audio-visualizer/variant-radial.d.ts +13 -0
  13. package/dist/components/audio-visualizer/variant-wave.d.ts +11 -0
  14. package/dist/components/audio-visualizer/wave.glsl.d.ts +16 -0
  15. package/dist/create-tween-hvpmSuwW.js +7 -0
  16. package/dist/custom-elements.json +282 -0
  17. package/dist/elements/agent-card.js +1 -1
  18. package/dist/elements/artifact.js +1 -1
  19. package/dist/elements/attachments.js +1 -1
  20. package/dist/elements/audio-visualizer.d.ts +1 -0
  21. package/dist/elements/audio-visualizer.js +1 -0
  22. package/dist/elements/autoloader.js +1 -1
  23. package/dist/elements/avatar.js +1 -1
  24. package/dist/elements/badge.js +1 -1
  25. package/dist/elements/button.js +1 -1
  26. package/dist/elements/card.js +1 -1
  27. package/dist/elements/cards.js +1 -1
  28. package/dist/elements/chain-of-thought.js +1 -1
  29. package/dist/elements/chat-scope-picker.js +1 -1
  30. package/dist/elements/chat-workspace.js +1 -1
  31. package/dist/elements/chat.js +1 -1
  32. package/dist/elements/checkpoint.js +1 -1
  33. package/dist/elements/choice.js +1 -1
  34. package/dist/elements/chunks/{Icon-11SRdjJ4.js → Icon-Tj58ES_d.js} +1 -1
  35. package/dist/elements/chunks/{action-icons-CtRg17uX.js → action-icons-ns1Fnedj.js} +1 -1
  36. package/dist/elements/chunks/arrow-left-DQocUFvy.js +1 -0
  37. package/dist/elements/chunks/{attachments-CBqQRh60.js → attachments-mCB5F1Fq.js} +1 -1
  38. package/dist/elements/chunks/audio-visualizer-BqNy7dfm.js +1 -0
  39. package/dist/elements/chunks/{badge-CxklEXQm.js → badge-B4Zuajl2.js} +1 -1
  40. package/dist/elements/chunks/{button-BD7lUvVB.js → button-ZWNif3--.js} +1 -1
  41. package/dist/elements/chunks/{card-B-PRGXdj.js → card-BkHbp4BA.js} +1 -1
  42. package/dist/elements/chunks/{chat-thread-DIZbRIKG.js → chat-thread-CkRN6pZ7.js} +1 -1
  43. package/dist/elements/chunks/check-B9-gn6SS.js +1 -0
  44. package/dist/elements/chunks/chevron-down-BNsxc2hk.js +1 -0
  45. package/dist/elements/chunks/chevron-right-Hv00StBO.js +1 -0
  46. package/dist/elements/chunks/circle-0e3KJTDr.js +1 -0
  47. package/dist/elements/chunks/circle-check-BNAS0JEy.js +1 -0
  48. package/dist/elements/chunks/{circle-x-mtjCO_Ok.js → circle-x-B7faJFlY.js} +1 -1
  49. package/dist/elements/chunks/{code-block-BeWVttmU.js → code-block-BFUHn6Va.js} +1 -1
  50. package/dist/elements/chunks/collapsible-DM1Ckd4e.js +1 -0
  51. package/dist/elements/chunks/{composer-CavJww3d.js → composer-BguS0QL_.js} +2 -2
  52. package/dist/elements/chunks/{context-CnlsNJSJ.js → context-Cb7k4F-v.js} +1 -1
  53. package/dist/elements/chunks/{conversation-list-5O_KdI_I.js → conversation-list-CvoAkWhN.js} +1 -1
  54. package/dist/elements/chunks/create-tween-oVvAIG8r.js +7 -0
  55. package/dist/elements/chunks/{default-input-CB46cJJ1.js → default-input-Cqqilg9t.js} +1 -1
  56. package/dist/elements/chunks/define-D1din7Ld.js +1 -0
  57. package/dist/elements/chunks/{disclosure-BtFK3a-M.js → disclosure-CIZ5c8nO.js} +1 -1
  58. package/dist/elements/chunks/{download-qJv1dS3M.js → download-Dsbg3ste.js} +1 -1
  59. package/dist/elements/chunks/{dropdown-UhtAueYR.js → dropdown-BDd1-Zgi.js} +1 -1
  60. package/dist/elements/chunks/{ellipsis-B1sOOqiJ.js → ellipsis-Dw6qrss-.js} +1 -1
  61. package/dist/elements/chunks/{external-link-DToP_VKE.js → external-link-Vt74zAoL.js} +1 -1
  62. package/dist/elements/chunks/{file-text-BwUs_Pj4.js → file-text-CZrZF6_v.js} +1 -1
  63. package/dist/elements/chunks/{file-tree-C6RhmSnX.js → file-tree-DF4okKyo.js} +1 -1
  64. package/dist/elements/chunks/{folder-H_Xp0GYP.js → folder-glP5rha4.js} +1 -1
  65. package/dist/elements/chunks/{hover-card-Dn3yrk1l.js → hover-card-Cmm6Q53m.js} +1 -1
  66. package/dist/elements/chunks/{icon-BrxJQXzC.js → icon-BLb8beoi.js} +1 -1
  67. package/dist/elements/chunks/{info-11eT2q5H.js → info-CIsv92JK.js} +1 -1
  68. package/dist/elements/chunks/{input-B9oZKDfb.js → input-Dds1kFyt.js} +1 -1
  69. package/dist/elements/chunks/{kbd-D2fx3rWh.js → kbd-De_xbgi9.js} +1 -1
  70. package/dist/elements/chunks/{link-B-RNYWNw.js → link-i4r_k7z4.js} +1 -1
  71. package/dist/elements/chunks/{loader-BJh_aRlp.js → loader-BmQH4s3V.js} +1 -1
  72. package/dist/elements/chunks/{markdown-BIpjrDFv.js → markdown-Zi21WhUz.js} +7 -7
  73. package/dist/elements/chunks/{message-CPfqj8Gi.js → message-BqyXDN3-.js} +1 -1
  74. package/dist/elements/chunks/{message-feedback-8uj0aVYh.js → message-feedback-Djr3z6Yb.js} +1 -1
  75. package/dist/elements/chunks/message-square-vFAgbDaX.js +1 -0
  76. package/dist/elements/chunks/{minimize-2-C9qkiTJg.js → minimize-2--ifeCGrl.js} +1 -1
  77. package/dist/elements/chunks/{model-switcher-DRrMcRXH.js → model-switcher-B94YAKsM.js} +1 -1
  78. package/dist/elements/chunks/{overlay-C8_FUL8q.js → overlay-kD8dwRv_.js} +1 -1
  79. package/dist/elements/chunks/{paperclip-MA9hxLhW.js → paperclip-q21dYOSK.js} +1 -1
  80. package/dist/elements/chunks/{progress-bar-y5G6HDjg.js → progress-bar-BrAIIaaJ.js} +1 -1
  81. package/dist/elements/chunks/{prompt-suggestion-LalWvCJy.js → prompt-suggestion-Bjn2K-fR.js} +1 -1
  82. package/dist/elements/chunks/reasoning-DTpCGtnY.js +1 -0
  83. package/dist/elements/chunks/{resizable-xhYF5lCQ.js → resizable-Dp4JExql.js} +1 -1
  84. package/dist/elements/chunks/{rotate-cw-2ndEXjgS.js → rotate-cw-CFWWkpj2.js} +1 -1
  85. package/dist/elements/chunks/{scroll-area-BzOPDXrZ.js → scroll-area-Bb0kHH1j.js} +1 -1
  86. package/dist/elements/chunks/scroll-button-B0cH5fXf.js +1 -0
  87. package/dist/elements/chunks/{separator-CPvL5Xdl.js → separator-9kRgr1X9.js} +1 -1
  88. package/dist/elements/chunks/{settings-hmzIuNXD.js → settings-B8lmec4D.js} +1 -1
  89. package/dist/elements/chunks/{settings-group-BiIym17O.js → settings-group-I0hEuXiN.js} +1 -1
  90. package/dist/elements/chunks/{share-BbziTAzn.js → share-C3lTiYGt.js} +1 -1
  91. package/dist/elements/chunks/{skeleton-Bxhs1thL.js → skeleton-DSXW5Yya.js} +1 -1
  92. package/dist/elements/chunks/{star-BHL3Va5p.js → star-CSJtGxgv.js} +1 -1
  93. package/dist/elements/chunks/{store-tpnnWlxY.js → store-CHyW95TP.js} +1 -1
  94. package/dist/elements/chunks/{text-shimmer-1DCKivKx.js → text-shimmer-Cn9TmNpI.js} +1 -1
  95. package/dist/elements/chunks/{textarea-Czaowo9F.js → textarea-CUwqAX0G.js} +1 -1
  96. package/dist/elements/chunks/{thumbs-up-CdLqA13R.js → thumbs-up-PNVVThEF.js} +1 -1
  97. package/dist/elements/chunks/{toast-store-BvBquUFA.js → toast-store-DKbQn3Wn.js} +1 -1
  98. package/dist/elements/chunks/{tool-4P_ne8Go.js → tool-DjTRpIpl.js} +1 -1
  99. package/dist/elements/chunks/tooltip-CgBZCVKp.js +1 -0
  100. package/dist/elements/chunks/{triangle-alert-BllqxXq8.js → triangle-alert-DsHTHCPm.js} +1 -1
  101. package/dist/elements/chunks/{use-card-resolution-73xiddIW.js → use-card-resolution-BSu_XHjH.js} +1 -1
  102. package/dist/elements/chunks/variant-aurora-Dc4nQUia.js +218 -0
  103. package/dist/elements/chunks/variant-custom-y_3kVQhS.js +1 -0
  104. package/dist/elements/chunks/variant-wave-D5OR1-9Z.js +116 -0
  105. package/dist/elements/chunks/{video-O9rA6k7S.js → video-B7vmenoC.js} +1 -1
  106. package/dist/elements/chunks/x-GRUeeQFT.js +1 -0
  107. package/dist/elements/coachmark.js +1 -1
  108. package/dist/elements/code-block.js +1 -1
  109. package/dist/elements/command.js +1 -1
  110. package/dist/elements/compare.js +1 -1
  111. package/dist/elements/composer.js +1 -1
  112. package/dist/elements/confirm-card.js +1 -1
  113. package/dist/elements/context-meter.js +1 -1
  114. package/dist/elements/conversation-list.js +1 -1
  115. package/dist/elements/define.d.ts +11 -0
  116. package/dist/elements/dialog.js +1 -1
  117. package/dist/elements/editable-label.js +1 -1
  118. package/dist/elements/embed.js +1 -1
  119. package/dist/elements/empty.js +1 -1
  120. package/dist/elements/feedback-bar.js +1 -1
  121. package/dist/elements/file-tree.js +1 -1
  122. package/dist/elements/file-upload.js +1 -1
  123. package/dist/elements/form.js +1 -1
  124. package/dist/elements/hover-card.js +1 -1
  125. package/dist/elements/icon.js +1 -1
  126. package/dist/elements/image.js +1 -1
  127. package/dist/elements/input.js +1 -1
  128. package/dist/elements/kbd.js +1 -1
  129. package/dist/elements/link-preview.js +1 -1
  130. package/dist/elements/loader.js +1 -1
  131. package/dist/elements/markdown.js +1 -1
  132. package/dist/elements/menu.js +1 -1
  133. package/dist/elements/message-skills.js +1 -1
  134. package/dist/elements/message.js +1 -1
  135. package/dist/elements/model-switcher.js +1 -1
  136. package/dist/elements/nav.js +1 -1
  137. package/dist/elements/notice.js +1 -1
  138. package/dist/elements/pane-group.js +1 -1
  139. package/dist/elements/pane.js +1 -1
  140. package/dist/elements/popover.js +1 -1
  141. package/dist/elements/progress-bar.js +1 -1
  142. package/dist/elements/prompt-dock.js +1 -1
  143. package/dist/elements/prompt-input.js +1 -1
  144. package/dist/elements/prompt-suggestions.js +1 -1
  145. package/dist/elements/reasoning.js +1 -1
  146. package/dist/elements/remote.js +1 -1
  147. package/dist/elements/resizable.js +1 -1
  148. package/dist/elements/response-stream.js +1 -1
  149. package/dist/elements/screen.js +1 -1
  150. package/dist/elements/scroll-area.js +1 -1
  151. package/dist/elements/scroll-button.js +1 -1
  152. package/dist/elements/search.js +1 -1
  153. package/dist/elements/segmented.js +1 -1
  154. package/dist/elements/separator.js +1 -1
  155. package/dist/elements/setting-item.js +1 -1
  156. package/dist/elements/settings-group.js +1 -1
  157. package/dist/elements/skeleton.js +1 -1
  158. package/dist/elements/slots.d.ts +12 -0
  159. package/dist/elements/source.js +1 -1
  160. package/dist/elements/status.js +1 -1
  161. package/dist/elements/switch.js +1 -1
  162. package/dist/elements/tabs.js +1 -1
  163. package/dist/elements/tasks.js +1 -1
  164. package/dist/elements/text-shimmer.js +1 -1
  165. package/dist/elements/thinking-bar.js +1 -1
  166. package/dist/elements/thread.js +1 -1
  167. package/dist/elements/toast.js +1 -1
  168. package/dist/elements/tool.js +1 -1
  169. package/dist/elements/tooltip.js +1 -1
  170. package/dist/elements/voice-input.js +1 -1
  171. package/dist/elements/voice-output.js +1 -1
  172. package/dist/elements.d.ts +38 -0
  173. package/dist/index.js +18 -17
  174. package/dist/kai.es.js +1 -1
  175. package/dist/llms/llms-full.txt +40 -4
  176. package/dist/llms/llms.txt +3 -3
  177. package/dist/primitives/audio-bands.d.ts +106 -0
  178. package/dist/primitives/create-tween.d.ts +33 -0
  179. package/dist/primitives/use-audio-analysis.d.ts +149 -0
  180. package/dist/primitives/use-sequencer.d.ts +13 -0
  181. package/dist/primitives/use-voice-recorder.d.ts +1 -0
  182. package/dist/primitives/visualizer-sequences.d.ts +39 -0
  183. package/dist/react/index.d.ts +41 -0
  184. package/dist/react.js +159 -153
  185. package/dist/register-impl-DQyejdfb.js +145 -0
  186. package/dist/test-utils/fake-clock.d.ts +45 -0
  187. package/dist/variant-aurora-DVtGqVH6.js +218 -0
  188. package/dist/variant-custom-Dif-IV4u.js +1 -0
  189. package/dist/variant-wave-DbfNdvSi.js +116 -0
  190. package/frameworks/react/index.tsx +42 -0
  191. package/llms-full.txt +40 -4
  192. package/llms.txt +3 -3
  193. package/package.json +6 -3
  194. package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +257 -0
  195. package/src/components/audio-visualizer/aurora.glsl.ts +330 -0
  196. package/src/components/audio-visualizer/index.tsx +442 -0
  197. package/src/components/audio-visualizer/shader-canvas.tsx +846 -0
  198. package/src/components/audio-visualizer/sizes.ts +54 -0
  199. package/src/components/audio-visualizer/variant-aurora.tsx +299 -0
  200. package/src/components/audio-visualizer/variant-bar.tsx +143 -0
  201. package/src/components/audio-visualizer/variant-custom.tsx +338 -0
  202. package/src/components/audio-visualizer/variant-grid.tsx +170 -0
  203. package/src/components/audio-visualizer/variant-radial.tsx +158 -0
  204. package/src/components/audio-visualizer/variant-wave.tsx +125 -0
  205. package/src/components/audio-visualizer/wave.glsl.ts +130 -0
  206. package/src/components/component-meta.json +24 -24
  207. package/src/elements/audio-visualizer.tsx +183 -0
  208. package/src/elements/compiled.css +1 -1
  209. package/src/elements/define.tsx +12 -1
  210. package/src/elements/element-manifest.json +4 -0
  211. package/src/elements/element-meta.json +170 -0
  212. package/src/elements/element-types.d.ts +38 -0
  213. package/src/elements/register-impl.ts +1 -0
  214. package/src/elements/slots.ts +35 -0
  215. package/src/primitives/audio-bands.ts +174 -0
  216. package/src/primitives/create-tween.ts +214 -0
  217. package/src/primitives/use-audio-analysis.ts +321 -0
  218. package/src/primitives/use-sequencer.ts +53 -0
  219. package/src/primitives/use-voice-recorder.ts +16 -4
  220. package/src/primitives/visualizer-sequences.ts +350 -0
  221. package/src/test-utils/fake-clock.ts +88 -0
  222. package/dist/elements/chunks/arrow-left-CifsGq8x.js +0 -1
  223. package/dist/elements/chunks/check-CUKS495w.js +0 -1
  224. package/dist/elements/chunks/chevron-down-AELmYT1j.js +0 -1
  225. package/dist/elements/chunks/chevron-right-C8g26oKh.js +0 -1
  226. package/dist/elements/chunks/circle-DGcI8Cft.js +0 -1
  227. package/dist/elements/chunks/circle-check-DuU0IcBQ.js +0 -1
  228. package/dist/elements/chunks/collapsible-DGjADCN6.js +0 -1
  229. package/dist/elements/chunks/define-DfTe4zwZ.js +0 -1
  230. package/dist/elements/chunks/message-square-CCSQ4M9g.js +0 -1
  231. package/dist/elements/chunks/reasoning-CW3SDdb4.js +0 -1
  232. package/dist/elements/chunks/scroll-button-B1x4cYqM.js +0 -1
  233. package/dist/elements/chunks/tooltip-CBeFqJKk.js +0 -1
  234. package/dist/elements/chunks/x-DeS3rQhx.js +0 -1
  235. package/dist/register-impl-CaaHJcea.js +0 -145
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Shared fake `requestAnimationFrame` + `performance.now()` clock for tests
3
+ * that need to drive time deterministically instead of racing real timers.
4
+ *
5
+ * requestAnimationFrame's timestamp and performance.now() share a time origin
6
+ * per spec, so production code can read either. Stubbing them off the same
7
+ * fake `now` keeps the two from silently disagreeing.
8
+ *
9
+ * The stub holds a REAL per-registration queue, matching a real browser: a
10
+ * single frame fires every callback that was pending BEFORE that frame, all
11
+ * with the SAME advanced `now`, in registration order -- so two
12
+ * independently-animating things under test (e.g. a `createTween`'s own step
13
+ * loop and `ShaderCanvas`'s separate `draw` loop, both requestAnimationFrame
14
+ * consumers, both mounted at once) tick together on one `advance()` call
15
+ * instead of the second silently stealing the first's slot.
16
+ *
17
+ * This used to be a single PENDING-callback slot, not a queue: a second
18
+ * consumer scheduling a new frame before `advance()` ran overwrote the
19
+ * first rather than queueing behind it. That was fine for anything that only
20
+ * ever has ONE thing pending at a time (the common case, e.g. bar/grid/radial's
21
+ * single sequencer tick, or a lone `createTween`), which is why switching to a
22
+ * queue does not change any of those. It was NOT fine for a mounted shader
23
+ * variant, where a tween and ShaderCanvas's `draw` are both independently
24
+ * pending at once: `draw` always registers last and re-arms itself every
25
+ * `advance()`, so it permanently "won" the single slot and the tween's step
26
+ * never fired -- silently defeating any test trying to prove something holds
27
+ * while UNIFORM VALUES genuinely change every frame (see
28
+ * `variant-custom.test.tsx`'s recompile-guard test for the concrete case this
29
+ * was fixed for).
30
+ *
31
+ * `cancelAnimationFrame` cancels by id now (each `requestAnimationFrame` call
32
+ * gets its own), not by clearing whatever happens to be in the single slot --
33
+ * required once more than one callback can be pending at a time, so a
34
+ * `cancelAnimationFrame(idA)` cannot accidentally drop a DIFFERENT pending
35
+ * callback `idB`.
36
+ *
37
+ * Call once per `describe` block (or at file scope for the whole file); it
38
+ * registers `beforeEach`/`afterEach` hooks scoped to wherever it is called,
39
+ * exactly like inlining the hooks would, and returns the driver bound to
40
+ * that scope's fake clock.
41
+ */
42
+ export declare function installFakeClock(): {
43
+ advance: (ms: number) => void;
44
+ isFramePending: () => boolean;
45
+ };
@@ -0,0 +1,218 @@
1
+ import{i as x,s as y,c as b,a as w,C as R,t as A}from"./register-impl-DQyejdfb.js";import{d as u,j as S,b as _,f as k,o as M}from"./kai.es.js";import{c as n,h as T,S as W,D as C}from"./create-tween-hvpmSuwW.js";const q=`
2
+ const float PI = 3.14159265359;
3
+ // Strand phase span: 0.5 + pi (fact sheet section 2's "sigma", the
4
+ // midpoint of the interval [1, 2*pi] with the interpolation knob fixed
5
+ // at 0.5).
6
+ const float STRAND_SIGMA = 0.5 + PI;
7
+ const int STRAND_COUNT = 36;
8
+
9
+ // 4-octave directional-sine warp cascade. M0 and the per-octave rotation B
10
+ // (cos 0.6, sin 0.8, an exact ~53.13 degree rotation) are fact sheet
11
+ // section 2's stated matrices; M1/M2/M3 = B composed with the previous
12
+ // octave's matrix, and each v_k is the first row of M_k. Hand-derived and
13
+ // checked against the fact sheet's own listed v_0..v_3 below, not copied
14
+ // from any source.
15
+ const mat2 WARP_M0 = mat2(0.6, 0.25, -0.25, 0.9);
16
+ const mat2 WARP_M1 = mat2(0.16, 0.63, -0.87, 0.34);
17
+ const mat2 WARP_M2 = mat2(-0.408, 0.506, -0.794, -0.492);
18
+ const mat2 WARP_M3 = mat2(-0.6496, -0.0228, -0.0828, -0.9304);
19
+ const vec2 WARP_V0 = vec2(0.600, -0.250);
20
+ const vec2 WARP_V1 = vec2(0.160, -0.870);
21
+ const vec2 WARP_V2 = vec2(-0.408, -0.794);
22
+ const vec2 WARP_V3 = vec2(-0.650, -0.083);
23
+
24
+ // Displaces p through all 4 octaves. Octave k's phase carries k*tau, so
25
+ // octave 0 is static in time and octave 3 moves fastest -- fine
26
+ // corrugation slides across coarse folds, which reads as flowing wind
27
+ // (fact sheet section 2, "Mechanism of the fold / wind").
28
+ vec2 auroraWarp(vec2 p, float phi, float tau, float freq, float amp) {
29
+ vec2 x = p;
30
+ float f = freq;
31
+ float a = amp;
32
+
33
+ vec2 q = WARP_M0 * x;
34
+ vec2 w = sin(f * q + vec2(phi));
35
+ x += (a / f) * WARP_V0 * w;
36
+ f *= 1.4;
37
+ a *= 1.0 + 0.1 * (max(w.x, w.y) - 1.0);
38
+
39
+ q = WARP_M1 * x;
40
+ w = sin(f * q + vec2(tau + phi));
41
+ x += (a / f) * WARP_V1 * w;
42
+ f *= 1.4;
43
+ a *= 1.0 + 0.1 * (max(w.x, w.y) - 1.0);
44
+
45
+ q = WARP_M2 * x;
46
+ w = sin(f * q + vec2(2.0 * tau + phi));
47
+ x += (a / f) * WARP_V2 * w;
48
+ f *= 1.4;
49
+ a *= 1.0 + 0.1 * (max(w.x, w.y) - 1.0);
50
+
51
+ q = WARP_M3 * x;
52
+ w = sin(f * q + vec2(3.0 * tau + phi));
53
+ x += (a / f) * WARP_V3 * w;
54
+
55
+ return x;
56
+ }
57
+
58
+ vec3 auroraRgb2Hsv(vec3 c) {
59
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
60
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
61
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
62
+ float d = q.x - min(q.w, q.y);
63
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + 1.0e-10)), d / (q.x + 1.0e-10), q.x);
64
+ }
65
+
66
+ vec3 auroraHsv2Rgb(vec3 c) {
67
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
68
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
69
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
70
+ }
71
+
72
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
73
+ // Fact sheet section 2: u in [0,1]^2, centered point p = u - 0.5, no
74
+ // aspect correction -- the element is forced square by CSS, so this is
75
+ // only correct on a square canvas (true for every audio-visualizer size).
76
+ vec2 uv = fragCoord / iResolution.xy;
77
+ vec2 p = uv - 0.5;
78
+
79
+ // Solid-body rotation of the sampling frame (module doc, departure 1).
80
+ // gl_FragCoord's y-up frame is mirrored against the screen's y-down one,
81
+ // so the sign here is what makes positive uRotation read CLOCKWISE on
82
+ // screen -- verified empirically against the audit's estimator (which
83
+ // measures +10 for uRotation = +10 deg/s with the wind frozen).
84
+ float rotA = -uRotation * iTime;
85
+ float rc = cos(rotA);
86
+ float rs = sin(rotA);
87
+ p = mat2(rc, -rs, rs, rc) * p;
88
+
89
+ // Negative tau: time-reversing the octave phases flips the wind's
90
+ // emergent angular drift from counter-clockwise (measured on the original)
91
+ // to the reference's clockwise, without touching any static property --
92
+ // lobes, radii, spectra are distribution-identical (module doc,
93
+ // departure 1).
94
+ float tau = -iTime * uSpeed;
95
+ float freq = max(2.0 + 13.0 * uComplexity, 1.0);
96
+ float amp = uAmplitude;
97
+ float ringRadius = uScale;
98
+
99
+ vec3 hsv = auroraRgb2Hsv(uColor);
100
+ // Chain-seed strand, phase -1/36 NOT scaled by STRAND_SIGMA (fact sheet
101
+ // section 2), so inter-strand spacing is defined for strand 1 too.
102
+ vec2 prevStrand = auroraWarp(p, -1.0 / float(STRAND_COUNT), tau, freq, amp);
103
+
104
+ vec3 accum = vec3(0.0);
105
+ for (int j = 1; j <= STRAND_COUNT; j++) {
106
+ float frac = float(j) / float(STRAND_COUNT);
107
+ float phi = frac * STRAND_SIGMA;
108
+ vec2 strand = auroraWarp(p, phi, tau, freq, amp);
109
+
110
+ // Signed distance to the (warped) ring, per strand: negative inside,
111
+ // positive outside -- the sign feeds the asymmetric edge width below.
112
+ float sd = length(strand) - ringRadius;
113
+ float dist = abs(sd);
114
+ // Inter-strand spacing through the chain: an analytic blur exactly
115
+ // proportional to how far this strand's warp has drifted from its
116
+ // neighbour's. Fanned regions (large spacing) fuse into soft veils;
117
+ // bunched regions (small spacing) stay crisp -- this is what turns 36
118
+ // discrete rings into an aurora (fact sheet section 2). The 2.3 growth
119
+ // rate (fact sheet's own is 2.0) and the 0.66x outer-side factor are
120
+ // the parity edge calibration: the reference holds a 10-90% rise of
121
+ // ~6-10px(2x) with the OUTER edge always the sharper of the two
122
+ // (module doc, departure 4).
123
+ float spacing = length(strand - prevStrand);
124
+ float edgeWidth = 0.01 + max(exp(2.3 * spacing) - 1.0, 0.001);
125
+ edgeWidth *= mix(1.0, 0.66, step(0.0, sd));
126
+ float coverage = 1.0 - smoothstep(0.0, 1.0, dist / edgeWidth);
127
+
128
+ // Fixed hue drift across the strand fan, matching the fact sheet's
129
+ // documented colorShift default (0.05 turns at weight 0.3, i.e. 0.015
130
+ // turns end to end); earliest strand shifts most.
131
+ vec3 strandColor = auroraHsv2Rgb(vec3(fract(hsv.x + (1.0 - frac) * 0.015), hsv.y, hsv.z));
132
+ accum += coverage * strandColor;
133
+ prevStrand = strand;
134
+ }
135
+
136
+ // Mean soft coverage across all 36 strands (fact sheet section 2's image
137
+ // accumulator I). The inverse-distance glow accumulator G is omitted: the
138
+ // fact sheet states its gain ships as 0, so it contributes nothing.
139
+ vec3 image = accum / float(STRAND_COUNT);
140
+
141
+ // Deterministic per-pixel dither, +/- 1/510, identical on all channels
142
+ // (fact sheet section 3). Kept as a plain vec3 offset, not pre-mixed into
143
+ // the image accumulator, so each branch can add it at the point the fact
144
+ // sheet actually specifies (see the dark branch below).
145
+ float n = fract(sin(dot(fragCoord, vec2(12.9898, 78.233))) * 43758.5453);
146
+ vec3 dither = vec3((n - 0.5) / 255.0);
147
+
148
+ float brightness = uIntensity;
149
+ vec3 rgb;
150
+ float alpha;
151
+
152
+ if (uTheme < 0.5) {
153
+ // Dark pipeline, parity-calibrated (module doc, departures 2 + 3).
154
+ // RGB1 = 1.2 * I, THEN add dither (fact sheet order: pre-gain first so
155
+ // the dither's written amplitude stays +/- 1/510), then floor at 0 --
156
+ // a negative dither on a near-black pixel would otherwise be blown up
157
+ // by the chroma-preserving rescale's division right below.
158
+ vec3 x1 = max(1.2 * image + dither, 0.0);
159
+
160
+ // Chroma-preserving tonemap: knee the MAX channel (11x/(1+11x) -- a
161
+ // steeper knee than the fact sheet's per-channel 4x/(1+4x)) and rescale
162
+ // the vector, so ribbon cores land on a stable brightness level largely
163
+ // independent of how thin the veils have fanned (the audit measured the
164
+ // per-channel map crushing spread-out states to ~half the reference's
165
+ // rendered brightness) while hue and saturation pass through untouched
166
+ // for the HSV shape-up to own.
167
+ float mxc = max(x1.r, max(x1.g, x1.b));
168
+ float tmMax = 11.0 * mxc / (1.0 + 11.0 * mxc);
169
+ vec3 tm = x1 * (tmMax / max(mxc, 1.0e-5));
170
+
171
+ // Rendered-colour calibration: hue +0.013 turns (audit target
172
+ // ~197.5deg for the default accent), saturation proportional to the
173
+ // caller's own (a desaturated accent stays desaturated) but rising
174
+ // with the pixel's value and capped at 0.98 -- Rob's reference:
175
+ // saturation RISES with brightness, and nothing is ever white.
176
+ vec3 hv = auroraRgb2Hsv(tm);
177
+ hv.x = fract(hv.x + 0.013);
178
+ hv.y = min(hv.y * (1.02 + 0.35 * hv.z), 0.98);
179
+ tm = auroraHsv2Rgb(hv);
180
+
181
+ // Brightness compression (departure 3): uIntensity DRIVES 0.5..2.5 at
182
+ // the thinking/connecting pulse but must RENDER inside roughly
183
+ // 0.5..0.65 mean brightness, never dropping the ring below visibility.
184
+ // Two compressive powers (colour flatter than alpha) plus a smoothstep
185
+ // alpha knee that lifts ribbon cores to full opacity while cutting the
186
+ // dim tails -- which is also what keeps the centre transparent and the
187
+ // edges crisp. max(brightness, 0.05) only guards pow() against a
188
+ // (contractually impossible) zero or negative uniform.
189
+ float bVal = pow(max(brightness, 0.05) / 1.5, 0.07);
190
+ float bAlpha = 0.97 * pow(max(brightness, 0.05) / 1.5, 0.09);
191
+ float luma = dot(tm, vec3(0.299, 0.587, 0.114));
192
+ // Clamped to [0,1] before the premultiply below, mirroring the light
193
+ // branch, so rgb * alpha <= alpha stays enforced for every input.
194
+ rgb = clamp(tm * bVal, 0.0, 1.0);
195
+ alpha = clamp(smoothstep(0.0, 0.50, luma) * bAlpha, 0.0, 1.0);
196
+ } else {
197
+ // Light pipeline (fact sheet section 4): RGB1 = I, then add dither;
198
+ // brightness curve on vector length, hue direction kept, saturation
199
+ // extrapolated 3x about gray.
200
+ vec3 x1 = image + dither;
201
+ float mag = length(x1);
202
+ vec3 dir = x1 / max(mag, 1.0e-5);
203
+ float mag2 = 2.0 * mag / (1.0 + 2.0 * mag);
204
+ vec3 x2 = dir * mag2;
205
+ float gray = dot(x2, vec3(0.2, 0.5, 0.1));
206
+ rgb = clamp(vec3(gray) + 3.0 * (x2 - vec3(gray)), 0.0, 1.0);
207
+ alpha = clamp(mag2 * clamp(brightness, 1.0, 2.0), 0.0, 1.0);
208
+ }
209
+
210
+ // PREMULTIPLIED output. Both branches above clamp their natural rgb to
211
+ // [0,1] before this line, which is what makes rgb * alpha <= alpha
212
+ // (componentwise) a property the code enforces unconditionally, not one
213
+ // that happens to hold for the inputs this was tested against. See the
214
+ // module doc above for why this departs from the fact sheet's own
215
+ // (deliberately non-premultiplied) pipeline.
216
+ fragColor = vec4(rgb * alpha, alpha);
217
+ }
218
+ `;var z=A("<div style=aspect-ratio:1>");function d(e){switch(e){case"listening":return{intensity:[1.5,2],speed:1,complexity:.7,amplitude:1,scale:.3,rotation:5.3};case"thinking":return{intensity:[.5,2.5],speed:1.5,complexity:1,amplitude:.5,scale:.3,rotation:9.4};case"connecting":return{intensity:[.5,2.5],speed:1.5,complexity:1,amplitude:.5,scale:.3,rotation:5.5};case"speaking":return{intensity:1.5,speed:3.5,complexity:1.25,amplitude:.75,scale:.3,rotation:-3.5};case"disconnected":return{intensity:1,speed:.5,complexity:.4,amplitude:1.2,scale:.2,rotation:0};default:return{intensity:1,speed:.5,complexity:.4,amplitude:1.2,scale:.2,rotation:0}}}function P(){var e;const[c,s]=k(!1);if(typeof matchMedia=="function"){const i=matchMedia("(prefers-color-scheme: dark)");s(i.matches);const o=r=>s(r.matches);(e=i.addEventListener)==null||e.call(i,"change",o),M(()=>{var r;return(r=i.removeEventListener)==null?void 0:r.call(i,"change",o)})}return c}function N(e){const c=n(1),s=n(.5),i=n(.4),o=n(1.2),r=n(.2),f=P(),m=()=>e.dark??f();u(()=>{const t=d(e.state),a=e.frozen?{duration:0}:{duration:.5,ease:"easeOut"},l=e.frozen?{duration:0}:{duration:.35,ease:"easeOut"},h=Array.isArray(t.intensity)&&e.frozen?t.intensity[0]:t.intensity;c.to(h,Array.isArray(t.intensity)?l:a),i.to(t.complexity,a),o.to(t.amplitude,a),r.to(t.scale,e.state==="listening"&&!e.frozen?{type:"spring",duration:1,bounce:.35}:a),s.to(e.frozen?0:t.speed,{duration:0})}),u(()=>{if(e.state!=="speaking")return;const t=e.volume;t>0&&(r.animating()||r.to(.2+.2*t))});const v=()=>e.frozen?0:d(e.state).rotation*Math.PI/180,g=()=>m()?0:1;return(()=>{var t=z();return x(t,S(W,{fragment:q,get precision(){return e.size==="icon"||e.size==="sm"?"mediump":"highp"},get uniforms(){return{uColor:{type:"3fv",value:T(e.color??C)},uIntensity:{type:"1f",value:c.value()},uSpeed:{type:"1f",value:s.value()},uComplexity:{type:"1f",value:i.value()},uAmplitude:{type:"1f",value:o.value()},uScale:{type:"1f",value:r.value()},uTheme:{type:"1f",value:g()},uRotation:{type:"1f",value:v()}}},get animateWhenNotVisible(){return e.animateWhenNotVisible},onError:a=>{/not available/i.test(a)?console.warn('<kai-audio-visualizer variant="aurora">: shader unavailable',a):console.error('<kai-audio-visualizer variant="aurora">: shader error',a),e.onUnavailable()}})),_(a=>{var l=e.state,h=e.class,p=`${R[e.size]}px`;return l!==a.e&&y(t,"data-kai-state",a.e=l),h!==a.t&&b(t,a.t=h),p!==a.a&&w(t,"height",a.a=p),a},{e:void 0,t:void 0,a:void 0}),t})()}export{d as auroraTargets,N as default};
@@ -0,0 +1 @@
1
+ import{b as k,i as w,s as d,c,d as m,t as S,C as M}from"./register-impl-DQyejdfb.js";import{d as h,c as A,j as y,S as g,b as p}from"./kai.es.js";import{c as x,S as N,h as j,D as C}from"./create-tween-hvpmSuwW.js";var b=S("<div>");const E={"1f":!0,"1i":!0,"1fv":!0,"2f":!0,"3f":!0,"3fv":!0,"4f":!0,"4fv":!0,Matrix2fv:!0,Matrix3fv:!0,Matrix4fv:!0},V=new Set(["1f","1i"]),F={"2f":2,"3f":3,"4f":4,Matrix2fv:4,Matrix3fv:9,Matrix4fv:16};function O(r,e){if(e==null||typeof e!="object")return`uniform "${r}" is not a valid declaration (expected an object with "type" and "value").`;if(E[e.type]!==!0)return`uniform "${r}" has an unrecognized type "${String(e.type)}".`;if(V.has(e.type))return typeof e.value!="number"||!Number.isFinite(e.value)?`uniform "${r}" is declared "${e.type}" (a number) but its value is not a finite number.`:void 0;if(!Array.isArray(e.value)||e.value.some(s=>typeof s!="number"||!Number.isFinite(s)))return`uniform "${r}" is declared "${e.type}" (an array) but its value is not an array of finite numbers.`;const o=F[e.type];if(o!==void 0&&e.value.length!==o)return`uniform "${r}" is declared "${e.type}", which takes exactly ${o} numbers, but its value has ${e.value.length}.`}function $(r,e){const o=r.bands.length?r.bands:[0],s={uColor:{type:"3fv",value:j(r.color)},uIntensity:{type:"1f",value:r.intensity},uSpeed:{type:"1f",value:r.speed},uComplexity:{type:"1f",value:r.complexity},uVolume:{type:"1f",value:r.volume},uBands:{type:"1fv",value:o,arraySize:o.length}};if(!e)return s;for(const[l,v]of Object.entries(e)){const t=O(l,v);if(t)throw new Error(t)}return{...s,...e}}function U(r){const e=x(.3),o=x(1);h(()=>{const t=k(r.state);if(r.state==="speaking")e.to(.3+.7*r.volume,{duration:0});else{const a=r.frozen?{duration:0}:{duration:.5,ease:"easeOut"};e.to(Array.isArray(t.intensity)&&r.frozen?t.intensity[0]:t.intensity,a)}o.to(r.frozen?0:t.speed,{duration:0})});const s=A(()=>{var t;try{return{uniforms:$({color:r.color??C,intensity:e.value(),speed:o.value(),complexity:r.complexity??.5,volume:r.volume,bands:r.bands},(t=r.shader)==null?void 0:t.uniforms)}}catch(a){return{error:a instanceof Error?a.message:String(a)}}});let l=!1;h(()=>{const{error:t}=s();if(!t){l=!1;return}l||(l=!0,console.error(`<kai-audio-visualizer variant="custom">: ${t}`),r.onUnavailable())});const v=()=>({height:`${M[r.size]}px`,"aspect-ratio":"1"});return y(g,{get when(){var t;return(t=r.shader)==null?void 0:t.fragment},get fallback(){return(()=>{var t=b();return p(a=>{var n=r.state,i=r.class,u=v();return n!==a.e&&d(t,"data-kai-state",a.e=n),i!==a.t&&c(t,a.t=i),a.a=m(t,u,a.a),a},{e:void 0,t:void 0,a:void 0}),t})()},children:t=>y(g,{get when(){return s().uniforms},get fallback(){return(()=>{var a=b();return p(n=>{var i=r.state,u=r.class,f=v();return i!==n.e&&d(a,"data-kai-state",n.e=i),u!==n.t&&c(a,n.t=u),n.a=m(a,f,n.a),n},{e:void 0,t:void 0,a:void 0}),a})()},children:a=>(()=>{var n=b();return w(n,y(N,{get fragment(){return t()},get precision(){return r.size==="icon"||r.size==="sm"?"mediump":"highp"},get uniforms(){return a()},get animateWhenNotVisible(){return r.animateWhenNotVisible},onError:i=>{/not available/i.test(i)?console.warn('<kai-audio-visualizer variant="custom">: shader unavailable',i):console.error('<kai-audio-visualizer variant="custom">: shader error',i),r.onUnavailable()}})),p(i=>{var u=r.state,f=r.class,z=v();return u!==i.e&&d(n,"data-kai-state",i.e=u),f!==i.t&&c(n,i.t=f),i.a=m(n,z,i.a),i},{e:void 0,t:void 0,a:void 0}),n})()})})}export{$ as customUniforms,U as default};
@@ -0,0 +1,116 @@
1
+ import{i as p,s as m,c as h,a as x,C as g,t as y,w as b}from"./register-impl-DQyejdfb.js";import{d as v,j as w,b as C}from"./kai.es.js";import{c as r,h as z,S,D as U}from"./create-tween-hvpmSuwW.js";const F=`
2
+ const float TAU = 6.28318530718;
3
+
4
+ // Noise for dithering
5
+ vec2 randFibo(vec2 p) {
6
+ p = fract(p * vec2(443.897, 441.423));
7
+ p += dot(p, p.yx + 19.19);
8
+ return fract((p.xx + p.yx) * p.xy);
9
+ }
10
+
11
+ // Luma for alpha
12
+ float luma(vec3 color) {
13
+ return dot(color, vec3(0.299, 0.587, 0.114));
14
+ }
15
+
16
+ // RGB to HSV
17
+ vec3 rgb2hsv(vec3 c) {
18
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
19
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
20
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
21
+ float d = q.x - min(q.w, q.y);
22
+ float e = 1.0e-10;
23
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
24
+ }
25
+
26
+ // HSV to RGB
27
+ vec3 hsv2rgb(vec3 c) {
28
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
29
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
30
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
31
+ }
32
+
33
+ // Bell curve function for attenuation from center with rounded top
34
+ float bellCurve(float distanceFromCenter, float maxDistance) {
35
+ float normalizedDistance = distanceFromCenter / maxDistance;
36
+ // Use cosine with high power for smooth rounded top
37
+ return pow(cos(normalizedDistance * (3.14159265359 / 4.0)), 16.0);
38
+ }
39
+
40
+ // Calculate the sine wave
41
+ float oscilloscopeWave(float x, float centerX, float time) {
42
+ float relativeX = x - centerX;
43
+ float maxDistance = centerX;
44
+ float distanceFromCenter = abs(relativeX);
45
+
46
+ // Apply bell curve for amplitude attenuation
47
+ float bell = bellCurve(distanceFromCenter, maxDistance);
48
+
49
+ // Calculate wave with uniforms and bell curve attenuation
50
+ float wave = sin(relativeX * uFrequency + time * uSpeed) * uAmplitude * bell;
51
+
52
+ return wave;
53
+ }
54
+
55
+ void mainImage(out vec4 fragColor, in vec2 fragCoord) {
56
+ vec2 uv = fragCoord / iResolution.xy;
57
+ vec2 pos = uv - 0.5;
58
+
59
+ // Calculate center and positions
60
+ float centerX = 0.5;
61
+ float centerY = 0.5;
62
+ float x = uv.x;
63
+ float y = uv.y;
64
+
65
+ // Convert line width from pixels to UV space
66
+ // Use the average of width and height to handle aspect ratio
67
+ float pixelSize = 2.0 / (iResolution.x + iResolution.y);
68
+ float lineWidthUV = uLineWidth * pixelSize;
69
+ float smoothingUV = uSmoothing * pixelSize;
70
+
71
+ // Find minimum distance to the wave by sampling nearby points
72
+ // This gives us consistent line width without high-frequency artifacts
73
+ const int NUM_SAMPLES = 50; // Must be const for GLSL loop
74
+ float minDist = 1000.0;
75
+ float sampleRange = 0.02; // Range to search for closest point
76
+
77
+ for(int i = 0; i < NUM_SAMPLES; i++) {
78
+ float offset = (float(i) / float(NUM_SAMPLES - 1) - 0.5) * sampleRange;
79
+ float sampleX = x + offset;
80
+ float waveY = centerY + oscilloscopeWave(sampleX, centerX, iTime);
81
+
82
+ // Calculate distance from current pixel to this point on the wave
83
+ vec2 wavePoint = vec2(sampleX, waveY);
84
+ vec2 currentPoint = vec2(x, y);
85
+ float dist = distance(currentPoint, wavePoint);
86
+
87
+ minDist = min(minDist, dist);
88
+ }
89
+
90
+ // Solid line with smooth edges using minimum distance
91
+ float line = smoothstep(lineWidthUV + smoothingUV, lineWidthUV - smoothingUV, minDist);
92
+
93
+ vec3 color = uColor;
94
+ if(abs(uColorShift) > 0.01) {
95
+ // Keep the center 50% at base color, then ramp shift across outer 25% on each side.
96
+ float centerBandHalfWidth = 0.2;
97
+ float edgeBandWidth = 0.5;
98
+ float distanceFromCenter = abs(x - centerX);
99
+ float edgeFactor = clamp((distanceFromCenter - centerBandHalfWidth) / edgeBandWidth, 0.0, 1.0);
100
+ vec3 hsv = rgb2hsv(color);
101
+ // Hue shift is zero in the center band and strongest at far edges.
102
+ hsv.x = fract(hsv.x + edgeFactor * uColorShift * 0.3);
103
+ color = hsv2rgb(hsv);
104
+ }
105
+
106
+ // Apply line intensity
107
+ color *= line;
108
+
109
+ // Add dithering for smoother gradients
110
+ // color += (randFibo(fragCoord).x - 0.5) / 255.0;
111
+
112
+ // Calculate alpha based on line intensity
113
+ float alpha = line * uMix;
114
+
115
+ fragColor = vec4(color * uMix, alpha);
116
+ }`;var W=y('<div style="aspect-ratio:1;mask-image:linear-gradient(90deg, transparent 0%, black 20%, black 80%, transparent 100%)">');const q=.5,A=.05;function D(e){const o=r(0),i=r(0),s=r(1),n=()=>b(e.state),l=()=>e.frozen?{duration:0}:{duration:.2,ease:"easeOut"};v(()=>{const a=n(),t=Array.isArray(a.opacity)&&e.frozen?a.opacity[0]:a.opacity;s.to(t,e.frozen?{duration:0}:{duration:a.pulseDuration||.2})}),v(()=>{if(e.state==="speaking"){const t=e.volume;o.to(.015+.4*t,{duration:0}),i.to(20+60*t,{duration:0});return}const a=n();o.to(a.amplitude,l()),i.to(a.frequency,l())});const d=()=>e.size==="icon"||e.size==="sm"?2:1;return(()=>{var a=W();return p(a,w(S,{fragment:F,get precision(){return e.size==="icon"||e.size==="sm"?"mediump":"highp"},get uniforms(){return{uSpeed:{type:"1f",value:e.frozen?0:n().speed},uAmplitude:{type:"1f",value:o.value()},uFrequency:{type:"1f",value:i.value()},uMix:{type:"1f",value:s.value()},uLineWidth:{type:"1f",value:d()},uSmoothing:{type:"1f",value:q},uColor:{type:"3fv",value:z(e.color??U)},uColorShift:{type:"1f",value:A}}},get animateWhenNotVisible(){return e.animateWhenNotVisible},onError:t=>{console.warn('<kai-audio-visualizer variant="wave">: shader error',t),e.onUnavailable()}})),C(t=>{var c=e.state,u=e.class,f=`${g[e.size]}px`;return c!==t.e&&m(a,"data-kai-state",t.e=c),u!==t.t&&h(a,t.t=u),f!==t.a&&x(a,"height",t.a=f),t},{e:void 0,t:void 0,a:void 0}),a})()}export{D as default};
@@ -114,6 +114,48 @@ export const Attachments = /*#__PURE__*/ createWebComponent<AttachmentsProps>(
114
114
  () => import('@kitn.ai/ui/elements/attachments'),
115
115
  );
116
116
 
117
+ export interface AudioVisualizerProps extends WebComponentProps {
118
+ /** Look to render: `bar` (default), `grid`, `radial`, `wave`, `aurora`, `custom`. `aura` is accepted as a LiveKit-markup alias for `aurora`. Attribute: `variant`. */
119
+ variant?: string;
120
+ /** `idle` (default), `connecting`, `listening`, `thinking`, `speaking`, `disconnected` (connection down: the dead, flat look). LiveKit's room-lifecycle state names are accepted as aliases. Attribute: `state`. */
121
+ state?: string;
122
+ /** `icon` | `sm` | `md` (default) | `lg` | `xl`. Attribute: `size`. */
123
+ size?: string;
124
+ /** Bars to draw. Bar and radial only. Attribute: `bar-count`. */
125
+ barCount?: number;
126
+ /** Grid only: rows and columns of the (always square) grid. Attribute: `count`. */
127
+ count?: number;
128
+ /** Radial only: ring distance from center, in px. Attribute: `radius`. */
129
+ radius?: number;
130
+ /** Grid only: ring distance for the connecting animation, in cells. Attribute: `spread`. */
131
+ spread?: number;
132
+ /** Grid only: ms between scripted frames. Attribute: `interval`. */
133
+ interval?: number;
134
+ /** CSS color for the geometry, overriding the inherited `currentColor`. Attribute: `color`. */
135
+ color?: string;
136
+ /** Shader variants only: pattern density, 0..1. Attribute: `complexity`. */
137
+ complexity?: number;
138
+ /** Setting this makes the element an announced image (`role="img"`) instead of decorative (`aria-hidden`). Attribute: `label`. */
139
+ label?: string;
140
+ /** Live microphone or WebRTC audio to analyze. JS property only. */
141
+ stream?: MediaStream;
142
+ /** An `<audio>` or `<video>` element to tap for its audio. JS property only. */
143
+ audioElement?: HTMLMediaElement;
144
+ /** Pre-computed levels, 0..1. Set this and no AudioContext is ever built, which is what keeps headless/SSR rendering and browser-speech-synthesis playback (which exposes no audio node) free of Web Audio entirely. JS property only. A new array reference is required for each update; mutating the existing array in place will not re-render. */
145
+ bands?: number[];
146
+ /** Custom fragment shader for `variant="custom"`. JS property only. */
147
+ shader?: { fragment: string; uniforms?: Record<string, { type: "1f" | "1i" | "1fv" | "2f" | "3f" | "3fv" | "4f" | "4fv" | "Matrix2fv" | "Matrix3fv" | "Matrix4fv"; value: number | number[] }> };
148
+ /** Shader variants only: keep animating while scrolled off screen. Off by default, which stops drawing and releases the WebGL context until the element comes back (browsers ration contexts to roughly 16 a page). Does not override `prefers-reduced-motion`. Attribute: `animate-when-not-visible`. */
149
+ animateWhenNotVisible?: boolean;
150
+ }
151
+
152
+ export const AudioVisualizer = /*#__PURE__*/ createWebComponent<AudioVisualizerProps>(
153
+ 'kai-audio-visualizer',
154
+ ["theme","variant","state","size","barCount","count","radius","spread","interval","color","complexity","label","stream","audioElement","bands","shader","animateWhenNotVisible"],
155
+ { },
156
+ () => import('@kitn.ai/ui/elements/audio-visualizer'),
157
+ );
158
+
117
159
  export interface AvatarProps extends WebComponentProps {
118
160
  /** Image URL/data-URI. When absent, the `fallback` initials show instead. */
119
161
  src?: string;
package/llms-full.txt CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @kitn.ai/ui
5
5
 
6
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 79 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
6
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 80 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
7
7
 
8
8
  ## Install
9
9
 
@@ -37,7 +37,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
37
37
  - `<kai-prompt-input>` — standalone composer with send button.
38
38
 
39
39
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
40
- All 79 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
40
+ All 80 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
41
41
 
42
42
  ## Key rules for the web components
43
43
 
@@ -99,7 +99,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
99
99
 
100
100
  ## Docs
101
101
 
102
- - Full element reference (all 79 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
102
+ - Full element reference (all 80 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
103
103
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
104
104
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
105
105
  - Storybook: https://storybook.kitn.dev
@@ -173,7 +173,7 @@ The same rule applies to every array/object property (`models`, `context`, `sugg
173
173
 
174
174
  ---
175
175
 
176
- ## Element reference (79 elements, generated from custom-elements.json)
176
+ ## Element reference (80 elements, generated from custom-elements.json)
177
177
 
178
178
  Every element also accepts the `theme` attribute. Array/object properties are marked with a `—` attribute: they must be set as JS properties.
179
179
 
@@ -267,6 +267,42 @@ Every element also accepts the `theme` attribute. Array/object properties are ma
267
267
 
268
268
  ---
269
269
 
270
+ ### `kai-audio-visualizer` / `AudioVisualizer`
271
+
272
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
273
+
274
+ | Property | Attribute | Type | Description |
275
+ |---|---|---|---|
276
+ | `variant` | `variant` | `undefined \| string` | Look to render: `bar` (default), `grid`, `radial`, `wave`, `aurora`, `custom`. `aura` is accepted as a LiveKit-markup alias for `aurora`. Attribute: `variant`. |
277
+ | `state` | `state` | `undefined \| string` | `idle` (default), `connecting`, `listening`, `thinking`, `speaking`, `disconnected` (connection down: the dead, flat look). LiveKit's room-lifecycle state names are accepted as aliases. Attribute: `state`. |
278
+ | `size` | `size` | `undefined \| string` | `icon` \| `sm` \| `md` (default) \| `lg` \| `xl`. Attribute: `size`. |
279
+ | `barCount` | `bar-count` | `undefined \| number` | Bars to draw. Bar and radial only. Attribute: `bar-count`. |
280
+ | `count` | `count` | `undefined \| number` | Grid only: rows and columns of the (always square) grid. Attribute: `count`. |
281
+ | `radius` | `radius` | `undefined \| number` | Radial only: ring distance from center, in px. Attribute: `radius`. |
282
+ | `spread` | `spread` | `undefined \| number` | Grid only: ring distance for the connecting animation, in cells. Attribute: `spread`. |
283
+ | `interval` | `interval` | `undefined \| number` | Grid only: ms between scripted frames. Attribute: `interval`. |
284
+ | `color` | `color` | `undefined \| string` | CSS color for the geometry, overriding the inherited `currentColor`. Attribute: `color`. |
285
+ | `complexity` | `complexity` | `undefined \| number` | Shader variants only: pattern density, 0..1. Attribute: `complexity`. |
286
+ | `label` | `label` | `undefined \| string` | Setting this makes the element an announced image (`role="img"`) instead of decorative (`aria-hidden`). Attribute: `label`. |
287
+ | `stream` | — | `undefined \| MediaStream` | Live microphone or WebRTC audio to analyze. JS property only. |
288
+ | `audioElement` | — | `undefined \| HTMLMediaElement` | An `<audio>` or `<video>` element to tap for its audio. JS property only. |
289
+ | `bands` | — | `undefined \| number[]` | Pre-computed levels, 0..1. Set this and no AudioContext is ever built, which is what keeps headless/SSR rendering and browser-speech-synthesis playback (which exposes no audio node) free of Web Audio entirely. JS property only. A new array reference is required for each update; mutating the existing array in place will not re-render. |
290
+ | `shader` | — | `undefined \| { fragment: string; uniforms?: undefined \| Record<string, { type: "1f" \| "1i" \| "1fv" \| "2f" \| "3f" \| "3fv" \| "4f" \| "4fv" \| "Matrix2fv" \| "Matrix3fv" \| "Matrix4fv"; value: number \| number[] }> }` | Custom fragment shader for `variant="custom"`. JS property only. |
291
+ | `animateWhenNotVisible` | `animate-when-not-visible` | `undefined \| false \| true` | Shader variants only: keep animating while scrolled off screen. Off by default, which stops drawing and releases the WebGL context until the element comes back (browsers ration contexts to roughly 16 a page). Does not override `prefers-reduced-motion`. Attribute: `animate-when-not-visible`. |
292
+
293
+ _No events._
294
+
295
+ **Styleable parts** (restyle from outside via `kai-audio-visualizer::part(name)`):
296
+
297
+ | Part | Description |
298
+ |---|---|
299
+ | `::part(bar)` | A single bar in the `bar` variant, or a single spoke in the `radial` variant. Also carries `data-kai-index` and `data-kai-highlighted` ("true"/"false") for use inside the shadow root; to style the lit state from OUTSIDE, combine with the `highlighted` part below rather than an attribute selector. — `kai-audio-visualizer::part(bar) { border-radius: 2px } kai-audio-visualizer::part(bar highlighted) { background: var(--brand) }` |
300
+ | `::part(cell)` | A single dot in the `grid` variant. Also carries `data-kai-index` and `data-kai-highlighted` ("true"/"false") for use inside the shadow root; to style the lit state from OUTSIDE, combine with the `highlighted` part below rather than an attribute selector. — `kai-audio-visualizer::part(cell) { border-radius: 9999px } kai-audio-visualizer::part(cell highlighted) { background: var(--brand) }` |
301
+ | `::part(highlighted)` | A second part TOKEN present on a `bar` or `cell` exactly when the sequencer or live audio has it lit, not a standalone styleable element. Combine it in the same `::part()` argument: `::part(bar highlighted)` or `::part(cell highlighted)`. This is the external equivalent of the internal `data-kai-highlighted="true"` attribute, which a `::part()` selector cannot reach (an attribute selector cannot follow a pseudo-element). — `kai-audio-visualizer::part(bar highlighted) { background: var(--brand) } kai-audio-visualizer::part(cell highlighted) { background: var(--brand) }` |
302
+ | `::part(canvas)` | The WebGL canvas backing the `wave` and `aurora` variants. Restyle its size or radius, or layer a mask/filter, from outside. — `kai-audio-visualizer::part(canvas) { border-radius: 0.75rem }` |
303
+
304
+ ---
305
+
270
306
  ### `kai-avatar` / `Avatar`
271
307
 
272
308
  **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
2
2
  # @kitn.ai/ui
3
3
 
4
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 79 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
4
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 80 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
5
5
 
6
6
  ## Install
7
7
 
@@ -35,7 +35,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
35
35
  - `<kai-prompt-input>` — standalone composer with send button.
36
36
 
37
37
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
38
- All 79 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
38
+ All 80 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
39
39
 
40
40
  ## Key rules for the web components
41
41
 
@@ -97,7 +97,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
97
97
 
98
98
  ## Docs
99
99
 
100
- - Full element reference (all 79 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
100
+ - Full element reference (all 80 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
101
101
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
102
102
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
103
103
  - Storybook: https://storybook.kitn.dev
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitn.ai/ui",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "nx": {
5
5
  "name": "ui",
6
6
  "targets": {
@@ -30,6 +30,7 @@
30
30
  "sideEffects": [
31
31
  "**/*.css",
32
32
  "./dist/kai.es.js",
33
+ "./dist/register-impl-*.js",
33
34
  "./dist/elements/*.js"
34
35
  ],
35
36
  "description": "Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.",
@@ -117,17 +118,19 @@
117
118
  "frameworks",
118
119
  "theme.css",
119
120
  "llms.txt",
120
- "llms-full.txt"
121
+ "llms-full.txt",
122
+ "NOTICE"
121
123
  ],
122
124
  "scripts": {
123
125
  "prepublishOnly": "npm run build",
124
126
  "prebuild": "npm run build:css",
125
- "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts && vite build --config vite.config.react.ts && vite build --config vite.config.barrel.ts && vite build --config vite.config.state.ts && vite build --config vite.config.mcp.ts && npm run build:elements && node scripts/verify-elements-bundle.mjs && node scripts/verify-react-wrappers.mjs",
127
+ "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts && vite build --config vite.config.react.ts && vite build --config vite.config.barrel.ts && vite build --config vite.config.state.ts && vite build --config vite.config.mcp.ts && npm run build:elements && node scripts/verify-elements-bundle.mjs && node scripts/verify-react-wrappers.mjs && node scripts/verify-shader-lazy.mjs",
126
128
  "build:elements": "node scripts/gen-elements-manifest.mjs && vite build --config vite.config.elements.ts && node scripts/gen-element-dts.mjs",
127
129
  "postbuild": "npm run build:theme && npm run build:api && npm run build:schemas",
128
130
  "build:theme": "node scripts/build-theme-tokens.mjs",
129
131
  "build:api": "node scripts/gen-element-api.mjs",
130
132
  "build:schemas": "node scripts/copy-card-schemas.mjs",
133
+ "verify:consumer": "node scripts/verify-consumer-sideeffects.mjs",
131
134
  "test": "vitest run",
132
135
  "test:react": "vitest run --config vitest.react.config.ts",
133
136
  "test:storybook": "vitest run --project=storybook",