xiod-ui 1.0.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 (224) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +167 -0
  3. package/dist/components/accordion.d.ts +9 -0
  4. package/dist/components/accordion.js +46 -0
  5. package/dist/components/agent-steps.d.ts +47 -0
  6. package/dist/components/agent-steps.js +223 -0
  7. package/dist/components/alert-dialog.d.ts +21 -0
  8. package/dist/components/alert-dialog.js +74 -0
  9. package/dist/components/alert.d.ts +12 -0
  10. package/dist/components/alert.js +45 -0
  11. package/dist/components/aspect-ratio.d.ts +9 -0
  12. package/dist/components/aspect-ratio.js +22 -0
  13. package/dist/components/autocomplete.d.ts +35 -0
  14. package/dist/components/autocomplete.js +160 -0
  15. package/dist/components/avatar.d.ts +17 -0
  16. package/dist/components/avatar.js +65 -0
  17. package/dist/components/badge.d.ts +15 -0
  18. package/dist/components/badge.js +46 -0
  19. package/dist/components/breadcrumb.d.ts +12 -0
  20. package/dist/components/breadcrumb.js +75 -0
  21. package/dist/components/button-group.d.ts +14 -0
  22. package/dist/components/button-group.js +45 -0
  23. package/dist/components/button-split.d.ts +19 -0
  24. package/dist/components/button-split.js +73 -0
  25. package/dist/components/button.d.ts +15 -0
  26. package/dist/components/button.js +54 -0
  27. package/dist/components/calendar.d.ts +63 -0
  28. package/dist/components/calendar.js +425 -0
  29. package/dist/components/card.d.ts +17 -0
  30. package/dist/components/card.js +139 -0
  31. package/dist/components/carousel.d.ts +59 -0
  32. package/dist/components/carousel.js +503 -0
  33. package/dist/components/checkbox.d.ts +16 -0
  34. package/dist/components/checkbox.js +86 -0
  35. package/dist/components/circular-progress.d.ts +28 -0
  36. package/dist/components/circular-progress.js +127 -0
  37. package/dist/components/collapsible.d.ts +8 -0
  38. package/dist/components/collapsible.js +27 -0
  39. package/dist/components/color-picker.d.ts +159 -0
  40. package/dist/components/color-picker.js +1589 -0
  41. package/dist/components/combobox.d.ts +46 -0
  42. package/dist/components/combobox.js +237 -0
  43. package/dist/components/command.d.ts +22 -0
  44. package/dist/components/command.js +129 -0
  45. package/dist/components/context-menu.d.ts +38 -0
  46. package/dist/components/context-menu.js +164 -0
  47. package/dist/components/copy-to-clipboard.d.ts +32 -0
  48. package/dist/components/copy-to-clipboard.js +83 -0
  49. package/dist/components/corner-badge.d.ts +22 -0
  50. package/dist/components/corner-badge.js +84 -0
  51. package/dist/components/dashboard-grid.d.ts +83 -0
  52. package/dist/components/dashboard-grid.js +486 -0
  53. package/dist/components/date-picker.d.ts +29 -0
  54. package/dist/components/date-picker.js +261 -0
  55. package/dist/components/dialog.d.ts +26 -0
  56. package/dist/components/dialog.js +97 -0
  57. package/dist/components/dot-matrix.d.ts +32 -0
  58. package/dist/components/dot-matrix.js +707 -0
  59. package/dist/components/draggable.d.ts +42 -0
  60. package/dist/components/draggable.js +346 -0
  61. package/dist/components/drawer.d.ts +66 -0
  62. package/dist/components/drawer.js +304 -0
  63. package/dist/components/empty.d.ts +14 -0
  64. package/dist/components/empty.js +75 -0
  65. package/dist/components/field.d.ts +12 -0
  66. package/dist/components/field.js +44 -0
  67. package/dist/components/fieldset.d.ts +7 -0
  68. package/dist/components/fieldset.js +21 -0
  69. package/dist/components/file-upload.d.ts +61 -0
  70. package/dist/components/file-upload.js +482 -0
  71. package/dist/components/form.d.ts +6 -0
  72. package/dist/components/form.js +14 -0
  73. package/dist/components/frame.d.ts +10 -0
  74. package/dist/components/frame.js +47 -0
  75. package/dist/components/gauge.d.ts +27 -0
  76. package/dist/components/gauge.js +74 -0
  77. package/dist/components/grid.d.ts +26 -0
  78. package/dist/components/grid.js +204 -0
  79. package/dist/components/group.d.ts +19 -0
  80. package/dist/components/group.js +45 -0
  81. package/dist/components/input-group.d.ts +15 -0
  82. package/dist/components/input-group.js +61 -0
  83. package/dist/components/input-otp.d.ts +24 -0
  84. package/dist/components/input-otp.js +50 -0
  85. package/dist/components/input-payment.d.ts +131 -0
  86. package/dist/components/input-payment.js +1140 -0
  87. package/dist/components/input-phone.d.ts +70 -0
  88. package/dist/components/input-phone.js +657 -0
  89. package/dist/components/input-sensitive.d.ts +12 -0
  90. package/dist/components/input-sensitive.js +169 -0
  91. package/dist/components/input.d.ts +13 -0
  92. package/dist/components/input.js +26 -0
  93. package/dist/components/kbd.d.ts +6 -0
  94. package/dist/components/kbd.js +19 -0
  95. package/dist/components/kinetic-click.d.ts +48 -0
  96. package/dist/components/kinetic-click.js +1184 -0
  97. package/dist/components/label.d.ts +6 -0
  98. package/dist/components/label.js +18 -0
  99. package/dist/components/list-box.d.ts +20 -0
  100. package/dist/components/list-box.js +148 -0
  101. package/dist/components/loader.d.ts +13 -0
  102. package/dist/components/loader.js +430 -0
  103. package/dist/components/marker.d.ts +15 -0
  104. package/dist/components/marker.js +59 -0
  105. package/dist/components/menu.d.ts +42 -0
  106. package/dist/components/menu.js +186 -0
  107. package/dist/components/menubar.d.ts +40 -0
  108. package/dist/components/menubar.js +107 -0
  109. package/dist/components/message.d.ts +33 -0
  110. package/dist/components/message.js +112 -0
  111. package/dist/components/meter.d.ts +10 -0
  112. package/dist/components/meter.js +42 -0
  113. package/dist/components/morphic-toast.d.ts +61 -0
  114. package/dist/components/morphic-toast.js +916 -0
  115. package/dist/components/navigation-menu.d.ts +26 -0
  116. package/dist/components/navigation-menu.js +116 -0
  117. package/dist/components/number-field.d.ts +15 -0
  118. package/dist/components/number-field.js +86 -0
  119. package/dist/components/option-picker.d.ts +18 -0
  120. package/dist/components/option-picker.js +89 -0
  121. package/dist/components/orb.d.ts +38 -0
  122. package/dist/components/orb.js +1413 -0
  123. package/dist/components/pagination.d.ts +25 -0
  124. package/dist/components/pagination.js +147 -0
  125. package/dist/components/popover.d.ts +22 -0
  126. package/dist/components/popover.js +79 -0
  127. package/dist/components/preview-card.d.ts +16 -0
  128. package/dist/components/preview-card.js +60 -0
  129. package/dist/components/progress.d.ts +21 -0
  130. package/dist/components/progress.js +139 -0
  131. package/dist/components/radio.d.ts +16 -0
  132. package/dist/components/radio.js +68 -0
  133. package/dist/components/resizable.d.ts +58 -0
  134. package/dist/components/resizable.js +964 -0
  135. package/dist/components/ruler-picker.d.ts +27 -0
  136. package/dist/components/ruler-picker.js +253 -0
  137. package/dist/components/scroll-area.d.ts +13 -0
  138. package/dist/components/scroll-area.js +34 -0
  139. package/dist/components/scroll-bar.d.ts +13 -0
  140. package/dist/components/scroll-bar.js +47 -0
  141. package/dist/components/select.d.ts +29 -0
  142. package/dist/components/select.js +140 -0
  143. package/dist/components/separator.d.ts +6 -0
  144. package/dist/components/separator.js +15 -0
  145. package/dist/components/sidebar.d.ts +65 -0
  146. package/dist/components/sidebar.js +408 -0
  147. package/dist/components/skeleton.d.ts +5 -0
  148. package/dist/components/skeleton.js +12 -0
  149. package/dist/components/slider.d.ts +12 -0
  150. package/dist/components/slider.js +96 -0
  151. package/dist/components/sortable.d.ts +44 -0
  152. package/dist/components/sortable.js +327 -0
  153. package/dist/components/switch.d.ts +15 -0
  154. package/dist/components/switch.js +63 -0
  155. package/dist/components/table.d.ts +12 -0
  156. package/dist/components/table.js +65 -0
  157. package/dist/components/tabs.d.ts +12 -0
  158. package/dist/components/tabs.js +39 -0
  159. package/dist/components/text.d.ts +14 -0
  160. package/dist/components/text.js +69 -0
  161. package/dist/components/textarea.d.ts +9 -0
  162. package/dist/components/textarea.js +20 -0
  163. package/dist/components/theme-provider.d.ts +52 -0
  164. package/dist/components/theme-provider.js +148 -0
  165. package/dist/components/timeline.d.ts +34 -0
  166. package/dist/components/timeline.js +147 -0
  167. package/dist/components/toast.d.ts +17 -0
  168. package/dist/components/toast.js +161 -0
  169. package/dist/components/toggle-group.d.ts +14 -0
  170. package/dist/components/toggle-group.js +53 -0
  171. package/dist/components/toggle.d.ts +11 -0
  172. package/dist/components/toggle.js +36 -0
  173. package/dist/components/toolbar.d.ts +11 -0
  174. package/dist/components/toolbar.js +49 -0
  175. package/dist/components/tooltip.d.ts +17 -0
  176. package/dist/components/tooltip.js +56 -0
  177. package/dist/components/waveform.d.ts +61 -0
  178. package/dist/components/waveform.js +500 -0
  179. package/dist/components/wheel-picker.d.ts +44 -0
  180. package/dist/components/wheel-picker.js +771 -0
  181. package/dist/hooks/use-copy-to-clipboard.d.ts +9 -0
  182. package/dist/hooks/use-copy-to-clipboard.js +36 -0
  183. package/dist/hooks/use-media-query.d.ts +21 -0
  184. package/dist/hooks/use-media-query.js +58 -0
  185. package/dist/styles.css +202 -0
  186. package/dist/themes/afterglow.css +89 -0
  187. package/dist/themes/afterglow.scoped.css +90 -0
  188. package/dist/themes/blacklight.css +89 -0
  189. package/dist/themes/blacklight.scoped.css +90 -0
  190. package/dist/themes/cathode.css +89 -0
  191. package/dist/themes/cathode.scoped.css +90 -0
  192. package/dist/themes/cel.css +89 -0
  193. package/dist/themes/cel.scoped.css +90 -0
  194. package/dist/themes/cinder.css +89 -0
  195. package/dist/themes/cinder.scoped.css +90 -0
  196. package/dist/themes/clay.css +89 -0
  197. package/dist/themes/clay.scoped.css +90 -0
  198. package/dist/themes/cobalt.css +89 -0
  199. package/dist/themes/cobalt.scoped.css +90 -0
  200. package/dist/themes/crimson.css +89 -0
  201. package/dist/themes/crimson.scoped.css +90 -0
  202. package/dist/themes/ion.css +89 -0
  203. package/dist/themes/ion.scoped.css +90 -0
  204. package/dist/themes/iris.css +89 -0
  205. package/dist/themes/iris.scoped.css +90 -0
  206. package/dist/themes/lagoon.css +89 -0
  207. package/dist/themes/lagoon.scoped.css +90 -0
  208. package/dist/themes/mochi.css +89 -0
  209. package/dist/themes/mochi.scoped.css +90 -0
  210. package/dist/themes/riso.css +89 -0
  211. package/dist/themes/riso.scoped.css +90 -0
  212. package/dist/themes/roast.css +89 -0
  213. package/dist/themes/roast.scoped.css +90 -0
  214. package/dist/themes/sage.css +89 -0
  215. package/dist/themes/sage.scoped.css +90 -0
  216. package/dist/themes/sepia.css +89 -0
  217. package/dist/themes/sepia.scoped.css +90 -0
  218. package/dist/themes/sorbet.css +89 -0
  219. package/dist/themes/sorbet.scoped.css +90 -0
  220. package/dist/themes/taffy.css +89 -0
  221. package/dist/themes/taffy.scoped.css +90 -0
  222. package/dist/themes/toxin.css +89 -0
  223. package/dist/themes/toxin.scoped.css +90 -0
  224. package/package.json +140 -0
@@ -0,0 +1,1413 @@
1
+ "use client";
2
+ import { cn } from "cn";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { cva } from "class-variance-authority";
5
+ import * as React$1 from "react";
6
+ import { mergeProps } from "@base-ui/react/merge-props";
7
+ import { useRender } from "@base-ui/react/use-render";
8
+ //#region src/components/orb.tsx
9
+ const orbVariants = cva("relative inline-flex items-center justify-center select-none shrink-0 transition-colors", {
10
+ variants: {
11
+ variant: {
12
+ default: "",
13
+ expressive: "filter drop-shadow-[0_0_6px_currentColor]",
14
+ classic: "",
15
+ sharp: "",
16
+ diamond: "",
17
+ ring: "",
18
+ cross: ""
19
+ },
20
+ intent: {
21
+ default: "text-foreground",
22
+ primary: "text-primary",
23
+ secondary: "text-muted-foreground",
24
+ success: "text-success",
25
+ warning: "text-warning",
26
+ destructive: "text-destructive",
27
+ info: "text-info"
28
+ },
29
+ size: {
30
+ xs: "size-4",
31
+ sm: "size-6",
32
+ md: "size-10",
33
+ lg: "size-16",
34
+ xl: "size-24",
35
+ "2xl": "size-32"
36
+ },
37
+ glow: {
38
+ none: "",
39
+ subtle: "filter drop-shadow-[0_0_8px_currentColor]",
40
+ intense: "filter drop-shadow-[0_0_16px_currentColor]"
41
+ }
42
+ },
43
+ defaultVariants: {
44
+ variant: "default",
45
+ intent: "default",
46
+ size: "lg",
47
+ glow: "none"
48
+ }
49
+ });
50
+ const SIZE_MAP = {
51
+ xs: 16,
52
+ sm: 24,
53
+ md: 40,
54
+ lg: 64,
55
+ xl: 96,
56
+ "2xl": 128
57
+ };
58
+ const STATE_ALIAS_MAP = {
59
+ working: "orbits",
60
+ thinking: "orbits",
61
+ searching: "globe",
62
+ analyzing: "globe",
63
+ solving: "rubik",
64
+ processing: "rubik",
65
+ listening: "wave",
66
+ composing: "ribbon",
67
+ shaping: "morph",
68
+ pulsing: "pulse",
69
+ pulse: "pulse",
70
+ beacon: "pulse",
71
+ vortex: "vortex",
72
+ swarm: "vortex",
73
+ atom: "atom",
74
+ nucleus: "atom",
75
+ helix: "helix",
76
+ dna: "helix",
77
+ radar: "radar",
78
+ sonar: "radar",
79
+ galaxy: "galaxy",
80
+ nebula: "galaxy",
81
+ spiral: "galaxy",
82
+ torus: "torus",
83
+ donut: "torus",
84
+ ring_torus: "torus",
85
+ quantum: "quantum",
86
+ matrix: "quantum",
87
+ cube: "quantum",
88
+ network: "network",
89
+ constellation: "network",
90
+ nodes: "network",
91
+ supernova: "supernova",
92
+ burst: "supernova",
93
+ spark: "supernova"
94
+ };
95
+ const STATE_LABELS = {
96
+ working: "Working…",
97
+ thinking: "Thinking…",
98
+ searching: "Searching…",
99
+ analyzing: "Analyzing…",
100
+ solving: "Solving…",
101
+ processing: "Processing…",
102
+ listening: "Listening…",
103
+ composing: "Composing…",
104
+ shaping: "Shaping…",
105
+ pulsing: "Pulsing…",
106
+ pulse: "Pulsing…",
107
+ beacon: "Beacon…",
108
+ vortex: "Swirling…",
109
+ swarm: "Swarming…",
110
+ atom: "Atom Core…",
111
+ nucleus: "Nucleus…",
112
+ helix: "DNA Helix…",
113
+ dna: "DNA Helix…",
114
+ radar: "Scanning Radar…",
115
+ sonar: "Sonar Sweep…",
116
+ galaxy: "Spiral Galaxy…",
117
+ nebula: "Cosmic Nebula…",
118
+ spiral: "Spiral Core…",
119
+ torus: "Quantum Torus…",
120
+ donut: "Donut Lattice…",
121
+ ring_torus: "Ring Torus…",
122
+ quantum: "Tesseract Matrix…",
123
+ matrix: "Matrix Grid…",
124
+ cube: "Quantum Cube…",
125
+ network: "Node Network…",
126
+ constellation: "Constellation…",
127
+ nodes: "Active Nodes…",
128
+ supernova: "Supernova Burst…",
129
+ burst: "Star Burst…",
130
+ spark: "Starlight Spark…"
131
+ };
132
+ const MODE_BASE_SPEED = {
133
+ orbits: 1.885,
134
+ globe: 2.015,
135
+ rubik: 1.82,
136
+ wave: 4.388,
137
+ ribbon: 2.34,
138
+ morph: 2.405,
139
+ pulse: 1.5,
140
+ vortex: 1.5,
141
+ atom: 1.2,
142
+ helix: 1.4,
143
+ radar: 1.2,
144
+ galaxy: 1.6,
145
+ torus: 1.8,
146
+ quantum: 1.4,
147
+ network: 1.5,
148
+ supernova: 2
149
+ };
150
+ const MAX_DOTS = 1200;
151
+ const DOT_BUFFER = Array.from({ length: MAX_DOTS }, () => ({
152
+ x: 0,
153
+ y: 0,
154
+ z: 0,
155
+ r: 0,
156
+ white: 0,
157
+ a: 1
158
+ }));
159
+ let dotCount = 0;
160
+ function resetDotBuffer() {
161
+ dotCount = 0;
162
+ }
163
+ function pushDot(x, y, z, r, white, a = 1) {
164
+ if (dotCount >= MAX_DOTS) return;
165
+ const d = DOT_BUFFER[dotCount++];
166
+ d.x = x;
167
+ d.y = y;
168
+ d.z = z;
169
+ d.r = r;
170
+ d.white = white;
171
+ d.a = a;
172
+ }
173
+ function hashD(a, b) {
174
+ const h = Math.sin(a * 12.9898 + b * 78.233) * 43758.5453;
175
+ return h - Math.floor(h);
176
+ }
177
+ function fibDir(i, n) {
178
+ const golden = Math.PI * (3 - Math.sqrt(5));
179
+ const y = 1 - 2 * (i + .5) / n;
180
+ const rad = Math.sqrt(Math.max(0, 1 - y * y));
181
+ const a = i * golden;
182
+ return [
183
+ rad * Math.cos(a),
184
+ y,
185
+ rad * Math.sin(a)
186
+ ];
187
+ }
188
+ function angleDelta(a, b) {
189
+ return Math.atan2(Math.sin(a - b), Math.cos(a - b));
190
+ }
191
+ function radiusScale(size, pow = .6) {
192
+ return (size / 300) ** pow;
193
+ }
194
+ function makeProj(yaw, tilt, cx, cy, scale) {
195
+ const st = Math.sin(tilt);
196
+ const ct = Math.cos(tilt);
197
+ const sy = Math.sin(yaw);
198
+ const cyw = Math.cos(yaw);
199
+ return (x, y, z) => {
200
+ const x1 = x * cyw + z * sy;
201
+ const z1 = -x * sy + z * cyw;
202
+ const y1 = y * ct - z1 * st;
203
+ const z2 = y * st + z1 * ct;
204
+ return [
205
+ cx + x1 * scale,
206
+ cy - y1 * scale,
207
+ z2
208
+ ];
209
+ };
210
+ }
211
+ function paintDots(ctx, dark, rMin = .3, customRgb, styleVariant = "default") {
212
+ if (dotCount === 0) return;
213
+ for (let i = 1; i < dotCount; i++) {
214
+ const key = DOT_BUFFER[i];
215
+ let j = i - 1;
216
+ while (j >= 0 && DOT_BUFFER[j].z > key.z) {
217
+ DOT_BUFFER[j + 1] = DOT_BUFFER[j];
218
+ j--;
219
+ }
220
+ DOT_BUFFER[j + 1] = key;
221
+ }
222
+ for (let i = 0; i < dotCount; i++) {
223
+ const d = DOT_BUFFER[i];
224
+ if (d.a < .02) continue;
225
+ const w = Math.min(1, Math.max(0, d.white));
226
+ const radius = Math.max(rMin, styleVariant === "classic" ? d.r * .8 : d.r);
227
+ if (customRgb) {
228
+ const depthFactor = dark ? 1 - w : w;
229
+ const alphaBoost = styleVariant === "expressive" ? 1.25 : 1;
230
+ const alpha = Math.min(1, Math.max(0, d.a * (.3 + .7 * depthFactor) * alphaBoost));
231
+ ctx.fillStyle = `rgba(${customRgb[0]},${customRgb[1]},${customRgb[2]},${alpha})`;
232
+ } else {
233
+ const depthFactor = dark ? 1 - w : w;
234
+ const alphaBoost = styleVariant === "expressive" ? 1.2 : 1;
235
+ const g = Math.round(depthFactor * 255);
236
+ ctx.fillStyle = `rgba(${g},${g},${g},${Math.min(1, Math.max(0, d.a * alphaBoost))})`;
237
+ }
238
+ if (styleVariant === "sharp") {
239
+ const sz = radius * 1.8;
240
+ ctx.fillRect(d.x - sz / 2, d.y - sz / 2, sz, sz);
241
+ } else if (styleVariant === "diamond") {
242
+ const sz = radius * 1.8;
243
+ ctx.beginPath();
244
+ ctx.moveTo(d.x, d.y - sz / 2);
245
+ ctx.lineTo(d.x + sz / 2, d.y);
246
+ ctx.lineTo(d.x, d.y + sz / 2);
247
+ ctx.lineTo(d.x - sz / 2, d.y);
248
+ ctx.closePath();
249
+ ctx.fill();
250
+ } else if (styleVariant === "ring") {
251
+ ctx.beginPath();
252
+ ctx.arc(d.x, d.y, Math.max(1, radius), 0, Math.PI * 2);
253
+ ctx.lineWidth = Math.max(.8, radius * .4);
254
+ ctx.strokeStyle = ctx.fillStyle;
255
+ ctx.stroke();
256
+ } else if (styleVariant === "cross") {
257
+ const sz = radius * 1.6;
258
+ ctx.beginPath();
259
+ ctx.moveTo(d.x - sz, d.y);
260
+ ctx.lineTo(d.x + sz, d.y);
261
+ ctx.moveTo(d.x, d.y - sz);
262
+ ctx.lineTo(d.x, d.y + sz);
263
+ ctx.lineWidth = Math.max(.8, radius * .35);
264
+ ctx.strokeStyle = ctx.fillStyle;
265
+ ctx.stroke();
266
+ } else {
267
+ ctx.beginPath();
268
+ ctx.arc(d.x, d.y, radius, 0, Math.PI * 2);
269
+ ctx.fill();
270
+ }
271
+ }
272
+ }
273
+ const BASE_PROFILES = {
274
+ globe: {
275
+ latRings: 17,
276
+ lonDensity: 44,
277
+ rBase: .6,
278
+ rDepth: 1.7,
279
+ rBoost: 1,
280
+ inkFar: .62,
281
+ inkSpan: .54,
282
+ rsPow: .6,
283
+ rMin: .3,
284
+ scanMul: 4.08,
285
+ dimBase: .45
286
+ },
287
+ orbits: {
288
+ orbitN: 12,
289
+ ghostN: 40,
290
+ ghostR: .9,
291
+ ghostA: .5,
292
+ particles: 3,
293
+ partR: 1.2,
294
+ partRDepth: 1.6,
295
+ rsPow: .6,
296
+ rMin: .3
297
+ },
298
+ rubik: {
299
+ latRings: 15,
300
+ lonDensity: 40,
301
+ moveCount: 14,
302
+ rBase: .6,
303
+ rDepth: 1.7,
304
+ rActive: .3,
305
+ inkFar: .62,
306
+ inkSpan: .54,
307
+ rsPow: .6,
308
+ rMin: .3
309
+ },
310
+ wave: {
311
+ rings: 15,
312
+ lonDensity: 40,
313
+ rBase: .6,
314
+ rDepth: 1.7,
315
+ rsPow: .6,
316
+ rMin: .3
317
+ },
318
+ ribbon: {
319
+ lanes: 5,
320
+ segs: 88,
321
+ ghostN: 150,
322
+ rBase: 1.1,
323
+ rDepth: 1.7,
324
+ rsPow: .6,
325
+ rMin: .3,
326
+ spin: 0,
327
+ bandMul: 3.9,
328
+ wobMul: 1
329
+ },
330
+ morph: {
331
+ rDot: .021,
332
+ iconD: 1,
333
+ rMin: .25,
334
+ spread: 1.45
335
+ },
336
+ pulse: {
337
+ rings: 16,
338
+ lonDensity: 40,
339
+ rBase: .7,
340
+ rDepth: 1.6,
341
+ rsPow: .6,
342
+ rMin: .3
343
+ },
344
+ vortex: {
345
+ particles: 180,
346
+ rBase: .8,
347
+ rDepth: 1.8,
348
+ rsPow: .6,
349
+ rMin: .3
350
+ },
351
+ atom: {
352
+ orbits: 4,
353
+ ghostN: 32,
354
+ partR: 1.4,
355
+ nucleusN: 30,
356
+ rsPow: .6,
357
+ rMin: .3
358
+ },
359
+ helix: {
360
+ strands: 2,
361
+ turns: 3,
362
+ segs: 70,
363
+ rBase: .8,
364
+ rDepth: 1.6,
365
+ rsPow: .6,
366
+ rMin: .3
367
+ },
368
+ radar: {
369
+ rings: 5,
370
+ segs: 48,
371
+ scanSpeed: 2.2,
372
+ rBase: .7,
373
+ rDepth: 1.5,
374
+ rsPow: .6,
375
+ rMin: .3
376
+ },
377
+ galaxy: {
378
+ stars: 220,
379
+ arms: 2,
380
+ rBase: .75,
381
+ rDepth: 1.7,
382
+ rsPow: .6,
383
+ rMin: .3
384
+ },
385
+ torus: {
386
+ rings: 16,
387
+ segs: 36,
388
+ rBase: .7,
389
+ rDepth: 1.6,
390
+ rsPow: .6,
391
+ rMin: .3
392
+ },
393
+ quantum: {
394
+ nodes: 16,
395
+ segsPerEdge: 8,
396
+ rBase: .8,
397
+ rDepth: 1.6,
398
+ rsPow: .6,
399
+ rMin: .3
400
+ },
401
+ network: {
402
+ hubs: 30,
403
+ segsPerLink: 7,
404
+ rBase: .75,
405
+ rDepth: 1.6,
406
+ rsPow: .6,
407
+ rMin: .3
408
+ },
409
+ supernova: {
410
+ rays: 140,
411
+ rBase: .85,
412
+ rDepth: 1.8,
413
+ rsPow: .6,
414
+ rMin: .3
415
+ }
416
+ };
417
+ function resolveOptsForSize(mode, size) {
418
+ const base = BASE_PROFILES[mode] || BASE_PROFILES.orbits;
419
+ const countScale = size <= 20 ? .25 : size >= 64 ? 1 : .25 + .75 * ((size - 20) / 44);
420
+ const sizeScale = size <= 20 ? 1.8 : size >= 64 ? 1 : 1.8 - .8 * ((size - 20) / 44);
421
+ const opts = { ...base };
422
+ if (opts.latRings != null && opts.lonDensity != null) {
423
+ const rt = Math.sqrt(countScale);
424
+ opts.latRings = Math.max(3, Math.round(opts.latRings * rt));
425
+ opts.lonDensity = Math.max(6, Math.round(opts.lonDensity * rt));
426
+ }
427
+ if (opts.orbitN != null) opts.orbitN = Math.max(2, Math.round(opts.orbitN * countScale));
428
+ if (opts.ghostN != null) opts.ghostN = Math.max(10, Math.round(opts.ghostN * countScale));
429
+ if (opts.particles != null) opts.particles = Math.max(20, Math.round(opts.particles * countScale));
430
+ if (opts.stars != null) opts.stars = Math.max(30, Math.round(opts.stars * countScale));
431
+ if (opts.rays != null) opts.rays = Math.max(24, Math.round(opts.rays * countScale));
432
+ if (opts.rBase != null) opts.rBase *= sizeScale;
433
+ if (opts.rDepth != null) opts.rDepth *= sizeScale;
434
+ if (opts.ghostR != null) opts.ghostR *= sizeScale;
435
+ if (opts.partR != null) opts.partR *= sizeScale;
436
+ return opts;
437
+ }
438
+ const STATIC_RUBIK_MOVES = Array.from({ length: 20 }, (_, i) => {
439
+ const axis = Math.min(2, Math.floor(hashD(i, 2.3) * 3));
440
+ const lo = -1 + .5 * Math.min(3, Math.floor(hashD(i, 5.9) * 4));
441
+ const dir = hashD(i, 7.7) < .5 ? 1 : -1;
442
+ return {
443
+ axis,
444
+ lo,
445
+ hi: lo + .5,
446
+ ang: dir * Math.PI / 2
447
+ };
448
+ });
449
+ const STATIC_AMOUNT_BUFFER = /* @__PURE__ */ new Float32Array(20);
450
+ function solveCycle(time, count, slotDur, rest) {
451
+ const tc = time % (2 * count * slotDur + rest);
452
+ STATIC_AMOUNT_BUFFER.fill(0);
453
+ let active = -1;
454
+ if (tc < 2 * count * slotDur) {
455
+ const slot = Math.floor(tc / slotDur);
456
+ const p = (tc - slot * slotDur) / slotDur;
457
+ const ep = 1 - (1 - Math.min(1, p / .7)) ** 3;
458
+ if (slot < count) {
459
+ for (let i = 0; i < slot; i++) STATIC_AMOUNT_BUFFER[i] = 1;
460
+ STATIC_AMOUNT_BUFFER[slot] = ep;
461
+ active = slot;
462
+ } else {
463
+ const u = 2 * count - 1 - slot;
464
+ for (let i = 0; i < u; i++) STATIC_AMOUNT_BUFFER[i] = 1;
465
+ STATIC_AMOUNT_BUFFER[u] = 1 - ep;
466
+ active = u;
467
+ }
468
+ }
469
+ return active;
470
+ }
471
+ function applyRubikMoves(pt3, moveCount, activeIdx) {
472
+ let [x, y, z] = pt3;
473
+ let inActive = false;
474
+ for (let i = 0; i < moveCount; i++) {
475
+ const amt = STATIC_AMOUNT_BUFFER[i];
476
+ if (amt <= 0) continue;
477
+ const mv = STATIC_RUBIK_MOVES[i];
478
+ const coord = mv.axis === 0 ? x : mv.axis === 1 ? y : z;
479
+ if (coord < mv.lo || coord >= mv.hi) continue;
480
+ if (i === activeIdx) inActive = true;
481
+ const a = mv.ang * amt;
482
+ const ca = Math.cos(a);
483
+ const sa = Math.sin(a);
484
+ if (mv.axis === 0) {
485
+ const y2 = y * ca - z * sa;
486
+ z = y * sa + z * ca;
487
+ y = y2;
488
+ } else if (mv.axis === 1) {
489
+ const x2 = x * ca + z * sa;
490
+ z = -x * sa + z * ca;
491
+ x = x2;
492
+ } else {
493
+ const x2 = x * ca - y * sa;
494
+ y = x * sa + y * ca;
495
+ x = x2;
496
+ }
497
+ }
498
+ return [
499
+ x,
500
+ y,
501
+ z,
502
+ inActive
503
+ ];
504
+ }
505
+ const MORPH_CIRCLE = (f) => {
506
+ const a = -Math.PI / 2 + f * 2 * Math.PI;
507
+ return [Math.cos(a) * .24, Math.sin(a) * .24];
508
+ };
509
+ function createPolyPath(verts) {
510
+ const V = verts.length;
511
+ const L = [];
512
+ let total = 0;
513
+ for (let i = 0; i < V; i++) {
514
+ const a = verts[i];
515
+ const b = verts[(i + 1) % V];
516
+ const l = Math.hypot(b[0] - a[0], b[1] - a[1]);
517
+ L.push(l);
518
+ total += l;
519
+ }
520
+ return (f) => {
521
+ let target = f * total;
522
+ let i = 0;
523
+ while (target > L[i] && i < V - 1) {
524
+ target -= L[i];
525
+ i++;
526
+ }
527
+ const a = verts[i];
528
+ const b = verts[(i + 1) % V];
529
+ const ff = L[i] ? Math.min(1, target / L[i]) : 0;
530
+ return [a[0] + (b[0] - a[0]) * ff, a[1] + (b[1] - a[1]) * ff];
531
+ };
532
+ }
533
+ const MORPH_CYCLE = [
534
+ MORPH_CIRCLE,
535
+ createPolyPath([
536
+ [0, -.26],
537
+ [.24, .16],
538
+ [-.24, .16]
539
+ ]),
540
+ createPolyPath([
541
+ [0, -.2],
542
+ [.2, -.2],
543
+ [.2, .2],
544
+ [-.2, .2],
545
+ [-.2, -.2]
546
+ ])
547
+ ];
548
+ const MORPH_SAMPLES = 160;
549
+ const STATIC_MORPH_PTS = Array.from({ length: MORPH_SAMPLES }, () => [0, 0]);
550
+ const STATIC_MORPH_L = new Float32Array(MORPH_SAMPLES);
551
+ function drawOrbitsMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
552
+ const cx = size / 2;
553
+ const cy = size / 2;
554
+ const R = size / 2 * .82;
555
+ const pt = makeProj(t * .12, .3, cx, cy, 1);
556
+ const rs = radiusScale(size, o.rsPow ?? .6);
557
+ resetDotBuffer();
558
+ const orbitN = o.orbitN ?? 8;
559
+ const ghostN = o.ghostN ?? 24;
560
+ const particles = o.particles ?? 3;
561
+ for (let orb = 0; orb < orbitN; orb++) {
562
+ const h1 = hashD(orb, 1.7);
563
+ const h2 = hashD(orb, 5.2);
564
+ const h3 = hashD(orb, 8.9);
565
+ const ro = R * (.45 + .52 * h1);
566
+ const th = h1 * 2 * Math.PI;
567
+ const phi = Math.acos(2 * h2 - 1);
568
+ const nx = Math.sin(phi) * Math.cos(th);
569
+ const ny = Math.cos(phi);
570
+ const nz = Math.sin(phi) * Math.sin(th);
571
+ let ux = -ny;
572
+ let uy = nx;
573
+ const uz = 0;
574
+ const ul = Math.max(1e-6, Math.sqrt(ux * ux + uy * uy));
575
+ ux /= ul;
576
+ uy /= ul;
577
+ const vx = ny * uz - nz * uy;
578
+ const vy = nz * ux - nx * uz;
579
+ const vz = nx * uy - ny * ux;
580
+ const speed = (.25 + .55 * h3) * (h3 > .5 ? 1 : -1);
581
+ for (let k = 0; k < ghostN; k++) {
582
+ const a = k / ghostN * 2 * Math.PI;
583
+ const [px, py, z] = pt((ux * Math.cos(a) + vx * Math.sin(a)) * ro, (uy * Math.cos(a) + vy * Math.sin(a)) * ro, (uz * Math.cos(a) + vz * Math.sin(a)) * ro);
584
+ const depth = (z / ro + 1) / 2;
585
+ pushDot(px, py, z, (o.ghostR ?? .9) * rs, .72, (o.ghostA ?? .5) * (.4 + .6 * depth));
586
+ }
587
+ for (let m = 0; m < particles; m++) {
588
+ const a = t * speed + m / particles * 2 * Math.PI + h2 * 6;
589
+ const [px, py, z] = pt((ux * Math.cos(a) + vx * Math.sin(a)) * ro, (uy * Math.cos(a) + vy * Math.sin(a)) * ro, (uz * Math.cos(a) + vz * Math.sin(a)) * ro);
590
+ const depth = (z / ro + 1) / 2;
591
+ pushDot(px, py, z, ((o.partR ?? 1.2) + (o.partRDepth ?? 1.6) * depth) * rs, .3 - .22 * depth, 1);
592
+ }
593
+ }
594
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
595
+ }
596
+ function drawGlobeMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
597
+ const spin = .5;
598
+ const cx = size / 2;
599
+ const cy = size / 2;
600
+ const radius = size / 2 * .82;
601
+ const tilt = .4 + .06 * Math.sin(t * .35);
602
+ const pt = makeProj(t * spin, tilt, cx, cy, radius);
603
+ const scan = t * (spin + 1.2 * (o.scanMul ?? 4.08));
604
+ const rs = radiusScale(size, o.rsPow ?? .6);
605
+ const dimBase = o.dimBase ?? .45;
606
+ resetDotBuffer();
607
+ const latRings = o.latRings ?? 12;
608
+ const lonDensity = o.lonDensity ?? 28;
609
+ for (let li = 0; li <= latRings; li++) {
610
+ const lat = -Math.PI / 2 + li / latRings * Math.PI;
611
+ const cosLat = Math.cos(lat);
612
+ const sinLat = Math.sin(lat);
613
+ const lonCount = Math.max(1, Math.round(Math.abs(cosLat) * lonDensity));
614
+ for (let lj = 0; lj < lonCount; lj++) {
615
+ const lon = lj / lonCount * 2 * Math.PI;
616
+ const [px, py, z] = pt(cosLat * Math.cos(lon), sinLat, cosLat * Math.sin(lon));
617
+ const depth = (z + 1) / 2;
618
+ const d = angleDelta(lon + t * spin, scan);
619
+ const boost = Math.exp(-(d * d) / .18) * Math.max(0, z);
620
+ pushDot(px, py, z, ((o.rBase ?? .6) + (o.rDepth ?? 1.7) * depth + (o.rBoost ?? 1) * boost) * rs, (o.inkFar ?? .62) - (o.inkSpan ?? .54) * depth, dimBase + (1 - dimBase) * Math.min(1, boost));
621
+ }
622
+ }
623
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
624
+ }
625
+ function drawRubikMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
626
+ const cx = size / 2;
627
+ const cy = size / 2;
628
+ const R = size / 2 * .82;
629
+ const pt = makeProj(t * .55, .35 + .1 * Math.sin(t * .9), cx, cy, R);
630
+ const rs = radiusScale(size, o.rsPow ?? .6);
631
+ const moveCount = Math.min(20, o.moveCount ?? 14);
632
+ const activeIdx = solveCycle(t, moveCount, .42, 1.2);
633
+ resetDotBuffer();
634
+ const latRings = o.latRings ?? 12;
635
+ const lonDensity = o.lonDensity ?? 28;
636
+ for (let li = 0; li <= latRings; li++) {
637
+ const lat = -Math.PI / 2 + li / latRings * Math.PI;
638
+ const cosLat = Math.cos(lat);
639
+ const sinLat = Math.sin(lat);
640
+ const lonCount = Math.max(1, Math.round(Math.abs(cosLat) * lonDensity));
641
+ for (let lj = 0; lj < lonCount; lj++) {
642
+ const lon = lj / lonCount * 2 * Math.PI;
643
+ const [x, y, z, inActive] = applyRubikMoves([
644
+ cosLat * Math.cos(lon),
645
+ sinLat,
646
+ cosLat * Math.sin(lon)
647
+ ], moveCount, activeIdx);
648
+ const [px, py, zr] = pt(x, y, z);
649
+ const depth = (zr + 1) / 2;
650
+ pushDot(px, py, zr, ((o.rBase ?? .6) + (o.rDepth ?? 1.7) * depth + (inActive ? o.rActive ?? .3 : 0)) * rs, (o.inkFar ?? .62) - (o.inkSpan ?? .54) * depth - (inActive ? .14 : 0), 1);
651
+ }
652
+ }
653
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
654
+ }
655
+ function drawWaveMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
656
+ const cx = size / 2;
657
+ const cy = size / 2;
658
+ const R = size / 2 * .874;
659
+ const pt = makeProj(t * .18, .38, cx, cy, 1);
660
+ const rs = radiusScale(size, o.rsPow ?? .6);
661
+ resetDotBuffer();
662
+ const rings = o.rings ?? 12;
663
+ const lonDensity = o.lonDensity ?? 28;
664
+ for (let ri = 0; ri <= rings; ri++) {
665
+ const lat = -Math.PI / 2 + ri / rings * Math.PI;
666
+ const cosLat = Math.cos(lat);
667
+ const sinLat = Math.sin(lat);
668
+ const w = .62 * Math.sin(t * 2.1 - ri * .52) + .38 * Math.sin(t * 1.27 + ri * .83);
669
+ const rr = R * (.88 + .105 * w);
670
+ const lonCount = Math.max(1, Math.round(Math.abs(cosLat) * lonDensity));
671
+ for (let lj = 0; lj < lonCount; lj++) {
672
+ const lon = lj / lonCount * 2 * Math.PI;
673
+ const [px, py, z] = pt(cosLat * Math.cos(lon) * rr, sinLat * rr, cosLat * Math.sin(lon) * rr);
674
+ const depth = (z / R + 1) / 2;
675
+ const crest = Math.max(0, w);
676
+ pushDot(px, py, z, ((o.rBase ?? .6) + (o.rDepth ?? 1.7) * depth) * (1 + .4 * crest) * rs, .66 - .56 * depth - .1 * crest, 1);
677
+ }
678
+ }
679
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
680
+ }
681
+ function drawRibbonMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
682
+ const cx = size / 2;
683
+ const cy = size / 2;
684
+ const R = size / 2 * .78;
685
+ const spin = o.spin ?? 0;
686
+ const pt = makeProj(t * .1 * spin, .3, cx, cy, 1);
687
+ const rs = radiusScale(size, o.rsPow ?? .6);
688
+ resetDotBuffer();
689
+ const ghostN = o.ghostN ?? 100;
690
+ for (let i = 0; i < ghostN; i++) {
691
+ const d = fibDir(i, ghostN);
692
+ const [px, py, z] = pt(d[0] * R, d[1] * R, d[2] * R);
693
+ const depth = (z / R + 1) / 2;
694
+ pushDot(px, py, z, .8 * rs, .78, .1 + .22 * depth);
695
+ }
696
+ const ya = t * .24;
697
+ const ta = .55 + .3 * Math.sin(t * .18);
698
+ const ux = Math.cos(ya);
699
+ const uy = 0;
700
+ const uz = Math.sin(ya);
701
+ const vx = -uz * Math.sin(ta);
702
+ const vy = Math.cos(ta);
703
+ const vz = ux * Math.sin(ta);
704
+ const nx = uy * vz - uz * vy;
705
+ const ny = uz * vx - ux * vz;
706
+ const nz = ux * vy - uy * vx;
707
+ const baseLanes = o.lanes ?? 4;
708
+ const segs = o.segs ?? 60;
709
+ const lanes = Math.max(1, Math.round(baseLanes * (o.bandMul ?? 3.9)));
710
+ for (let w = 0; w < lanes; w++) {
711
+ const laneOff = (w - (lanes - 1) / 2) * .075;
712
+ const edge = Math.abs(w - (lanes - 1) / 2) / Math.max(1, (lanes - 1) / 2);
713
+ for (let k = 0; k < segs; k++) {
714
+ const a = k / segs * 2 * Math.PI;
715
+ const off = laneOff + (.16 * Math.sin(a * 3 - t * 1.7 + w * .22) + .07 * Math.sin(a * 5 + t * 1.1)) * (o.wobMul ?? 1);
716
+ const x = ux * Math.cos(a) + vx * Math.sin(a) + nx * off;
717
+ const y = uy * Math.cos(a) + vy * Math.sin(a) + ny * off;
718
+ const z = uz * Math.cos(a) + vz * Math.sin(a) + nz * off;
719
+ const l = Math.sqrt(x * x + y * y + z * z);
720
+ const [px, py, zr] = pt(x / l * R, y / l * R, z / l * R);
721
+ const depth = (zr / R + 1) / 2;
722
+ pushDot(px, py, zr, ((o.rBase ?? 1.1) + (o.rDepth ?? 1.7) * depth) * (1 - .25 * edge) * rs, .52 - .44 * depth + .18 * edge, .4 + .6 * depth);
723
+ }
724
+ }
725
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
726
+ }
727
+ function drawMorphMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
728
+ const K = MORPH_CYCLE.length;
729
+ const HOLD = 1.4;
730
+ const MORPH = .9;
731
+ const SEG = 2.3;
732
+ const tc = t % (SEG * K);
733
+ const k = Math.floor(tc / SEG);
734
+ const local = tc - k * SEG;
735
+ const m = local > HOLD ? (local - HOLD) / MORPH : 0;
736
+ const smoothM = m * m * (3 - 2 * m);
737
+ const sprd = o.spread ?? 1.45;
738
+ const pA = MORPH_CYCLE[k];
739
+ const pB = MORPH_CYCLE[(k + 1) % K];
740
+ let totalL = 0;
741
+ for (let i = 0; i < MORPH_SAMPLES; i++) {
742
+ const f = i / MORPH_SAMPLES;
743
+ const a = pA(f);
744
+ const b = pB(f);
745
+ STATIC_MORPH_PTS[i][0] = (a[0] + (b[0] - a[0]) * smoothM) * sprd;
746
+ STATIC_MORPH_PTS[i][1] = (a[1] + (b[1] - a[1]) * smoothM) * sprd;
747
+ }
748
+ for (let i = 0; i < MORPH_SAMPLES; i++) {
749
+ const a = STATIC_MORPH_PTS[i];
750
+ const b = STATIC_MORPH_PTS[(i + 1) % MORPH_SAMPLES];
751
+ const l = Math.hypot(b[0] - a[0], b[1] - a[1]);
752
+ STATIC_MORPH_L[i] = l;
753
+ totalL += l;
754
+ }
755
+ const n = Math.max(8, Math.round(28 * (o.iconD ?? 1)));
756
+ const re = (o.rDot ?? .021) * 1.35 * sprd;
757
+ const pulse = 1 + .02 * Math.sin(local * 3.1);
758
+ resetDotBuffer();
759
+ const c2 = size / 2;
760
+ let seg = 0;
761
+ let acc = 0;
762
+ for (let k2 = 0; k2 < n; k2++) {
763
+ const target = k2 / n * totalL;
764
+ while (acc + STATIC_MORPH_L[seg] < target && seg < 159) {
765
+ acc += STATIC_MORPH_L[seg];
766
+ seg++;
767
+ }
768
+ const a = STATIC_MORPH_PTS[seg];
769
+ const b = STATIC_MORPH_PTS[(seg + 1) % MORPH_SAMPLES];
770
+ const f = STATIC_MORPH_L[seg] ? Math.min(1, (target - acc) / STATIC_MORPH_L[seg]) : 0;
771
+ const x = (a[0] + (b[0] - a[0]) * f) * pulse;
772
+ const y = (a[1] + (b[1] - a[1]) * f) * pulse;
773
+ pushDot(c2 + x * size, c2 + y * size, 0, Math.max(.35, re * size), .1, 1);
774
+ }
775
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
776
+ }
777
+ function drawPulseMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
778
+ const cx = size / 2;
779
+ const cy = size / 2;
780
+ const R = size / 2 * .82;
781
+ const pt = makeProj(t * .25, .35, cx, cy, R);
782
+ const rs = radiusScale(size, o.rsPow ?? .6);
783
+ resetDotBuffer();
784
+ const latRings = o.latRings ?? 14;
785
+ const lonDensity = o.lonDensity ?? 32;
786
+ const breathe = .88 + .14 * Math.sin(t * 2.5);
787
+ for (let li = 0; li <= latRings; li++) {
788
+ const lat = -Math.PI / 2 + li / latRings * Math.PI;
789
+ const cosLat = Math.cos(lat);
790
+ const sinLat = Math.sin(lat);
791
+ const lonCount = Math.max(1, Math.round(Math.abs(cosLat) * lonDensity));
792
+ const shockwave = Math.max(0, Math.sin(t * 3 - li * .4));
793
+ for (let lj = 0; lj < lonCount; lj++) {
794
+ const lon = lj / lonCount * 2 * Math.PI;
795
+ const [px, py, z] = pt(cosLat * Math.cos(lon) * breathe, sinLat * breathe, cosLat * Math.sin(lon) * breathe);
796
+ const depth = (z + 1) / 2;
797
+ pushDot(px, py, z, ((o.rBase ?? .7) + (o.rDepth ?? 1.6) * depth + shockwave * .6) * rs, .65 - .5 * depth - shockwave * .15, .4 + .6 * depth);
798
+ }
799
+ }
800
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
801
+ }
802
+ function drawVortexMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
803
+ const cx = size / 2;
804
+ const cy = size / 2;
805
+ const R = size / 2 * .82;
806
+ const pt = makeProj(t * .3, .45, cx, cy, 1);
807
+ const rs = radiusScale(size, o.rsPow ?? .6);
808
+ resetDotBuffer();
809
+ const particles = o.particles ?? 120;
810
+ for (let i = 0; i < particles; i++) {
811
+ const frac = i / particles;
812
+ const angle = t * 1.5 + frac * Math.PI * 8;
813
+ const r = R * frac ** .7;
814
+ const h = (1 - frac) * R * .6 * Math.sin(t * .8 + frac * 4);
815
+ const [px, py, pz] = pt(Math.cos(angle) * r, h, Math.sin(angle) * r);
816
+ const depth = (pz / R + 1) / 2;
817
+ pushDot(px, py, pz, ((o.rBase ?? .8) + (o.rDepth ?? 1.8) * depth * (1 - frac * .4)) * rs, .6 - .5 * depth, .3 + .7 * frac);
818
+ }
819
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
820
+ }
821
+ function drawAtomMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
822
+ const cx = size / 2;
823
+ const cy = size / 2;
824
+ const R = size / 2 * .82;
825
+ const pt = makeProj(t * .15, .3, cx, cy, 1);
826
+ const rs = radiusScale(size, o.rsPow ?? .6);
827
+ resetDotBuffer();
828
+ const nPoints = o.nucleusN ?? 24;
829
+ for (let i = 0; i < nPoints; i++) {
830
+ const d = fibDir(i, nPoints);
831
+ const pulse = .22 * R * (1 + .08 * Math.sin(t * 4 + i));
832
+ const [px, py, z] = pt(d[0] * pulse, d[1] * pulse, d[2] * pulse);
833
+ const depth = (z / R + 1) / 2;
834
+ pushDot(px, py, z, 1.6 * rs, .25 - .15 * depth, 1);
835
+ }
836
+ const orbitCount = o.orbits ?? 4;
837
+ const ghostN = o.ghostN ?? 28;
838
+ for (let orb = 0; orb < orbitCount; orb++) {
839
+ const angleOffset = orb / orbitCount * Math.PI;
840
+ const tilt = .6 * Math.sin(angleOffset);
841
+ const speed = 2.4 * (orb % 2 === 0 ? 1 : -1);
842
+ const ux = Math.cos(angleOffset);
843
+ const uy = Math.sin(angleOffset) * Math.cos(tilt);
844
+ const uz = Math.sin(angleOffset) * Math.sin(tilt);
845
+ const vx = -Math.sin(angleOffset);
846
+ const vy = Math.cos(angleOffset) * Math.cos(tilt);
847
+ const vz = Math.cos(angleOffset) * Math.sin(tilt);
848
+ for (let k = 0; k < ghostN; k++) {
849
+ const a = k / ghostN * 2 * Math.PI;
850
+ const [px, py, zr] = pt((ux * Math.cos(a) + vx * Math.sin(a)) * R, (uy * Math.cos(a) + vy * Math.sin(a)) * R, (uz * Math.cos(a) + vz * Math.sin(a)) * R);
851
+ const depth = (zr / R + 1) / 2;
852
+ pushDot(px, py, zr, .8 * rs, .7, .25 + .35 * depth);
853
+ }
854
+ const ea = t * speed + orb * 1.5;
855
+ const [epx, epy, ezr] = pt((ux * Math.cos(ea) + vx * Math.sin(ea)) * R, (uy * Math.cos(ea) + vy * Math.sin(ea)) * R, (uz * Math.cos(ea) + vz * Math.sin(ea)) * R);
856
+ (ezr / R + 1) / 2;
857
+ pushDot(epx, epy, ezr, (o.partR ?? 1.8) * rs, .15, 1);
858
+ }
859
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
860
+ }
861
+ function drawHelixMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
862
+ const cx = size / 2;
863
+ const cy = size / 2;
864
+ const R = size / 2 * .82;
865
+ const pt = makeProj(.2, .25, cx, cy, 1);
866
+ const rs = radiusScale(size, o.rsPow ?? .6);
867
+ resetDotBuffer();
868
+ const segs = o.segs ?? 54;
869
+ const strands = o.strands ?? 2;
870
+ for (let s = 0; s < strands; s++) {
871
+ const strandPhase = s / strands * Math.PI * 2;
872
+ for (let i = 0; i < segs; i++) {
873
+ const frac = i / segs;
874
+ const y = (frac - .5) * R * 1.6;
875
+ const angle = t * 2 + frac * Math.PI * 5 + strandPhase;
876
+ const radius = R * .45;
877
+ const x = Math.cos(angle) * radius;
878
+ const z = Math.sin(angle) * radius;
879
+ const [px, py, zr] = pt(x, y, z);
880
+ const depth = (zr / R + 1) / 2;
881
+ pushDot(px, py, zr, ((o.rBase ?? .8) + (o.rDepth ?? 1.6) * depth) * rs, .6 - .5 * depth, .3 + .7 * depth);
882
+ if (s === 0 && i % 4 === 0) {
883
+ const x2 = Math.cos(angle + Math.PI) * radius;
884
+ const z2 = Math.sin(angle + Math.PI) * radius;
885
+ for (let r = 1; r <= 3; r++) {
886
+ const rf = r / 4;
887
+ const [rpx, rpy, rzr] = pt(x + (x2 - x) * rf, y, z + (z2 - z) * rf);
888
+ const rdepth = (rzr / R + 1) / 2;
889
+ pushDot(rpx, rpy, rzr, .6 * rs, .75, .15 + .25 * rdepth);
890
+ }
891
+ }
892
+ }
893
+ }
894
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
895
+ }
896
+ function drawRadarMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
897
+ const cx = size / 2;
898
+ const cy = size / 2;
899
+ const R = size / 2 * .82;
900
+ const pt = makeProj(.1, .5, cx, cy, 1);
901
+ const rs = radiusScale(size, o.rsPow ?? .6);
902
+ resetDotBuffer();
903
+ const rings = o.rings ?? 4;
904
+ const segs = o.segs ?? 36;
905
+ const sweepAngle = t * (o.scanSpeed ?? 2.2) % (Math.PI * 2);
906
+ for (let r = 1; r <= rings; r++) {
907
+ const ringRadius = R * (r / rings);
908
+ for (let k = 0; k < segs; k++) {
909
+ const a = k / segs * 2 * Math.PI;
910
+ const d = angleDelta(a, sweepAngle);
911
+ const intensity = Math.max(.1, Math.exp(-(d * d) / .25));
912
+ const [px, py, zr] = pt(Math.cos(a) * ringRadius, 0, Math.sin(a) * ringRadius);
913
+ const depth = (zr / R + 1) / 2;
914
+ pushDot(px, py, zr, ((o.rBase ?? .7) + (o.rDepth ?? 1.5) * depth + intensity * .8) * rs, .65 - .5 * depth - intensity * .2, .2 + .8 * intensity);
915
+ }
916
+ }
917
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
918
+ }
919
+ function drawGalaxyMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
920
+ const cx = size / 2;
921
+ const cy = size / 2;
922
+ const R = size / 2 * .82;
923
+ const pt = makeProj(t * .2, .45 + .08 * Math.sin(t * .3), cx, cy, 1);
924
+ const rs = radiusScale(size, o.rsPow ?? .6);
925
+ resetDotBuffer();
926
+ const totalStars = o.stars ?? 180;
927
+ const arms = o.arms ?? 2;
928
+ for (let i = 0; i < 28; i++) {
929
+ const d = fibDir(i, 28);
930
+ const cr = R * .2 * (.4 + .6 * hashD(i, 1.1));
931
+ const [px, py, z] = pt(d[0] * cr, d[1] * cr, d[2] * cr);
932
+ const depth = (z / R + 1) / 2;
933
+ pushDot(px, py, z, 1.7 * rs, .15 - .1 * depth, 1);
934
+ }
935
+ for (let i = 0; i < totalStars; i++) {
936
+ const arm = i % arms;
937
+ const frac = (i / totalStars) ** .85;
938
+ const r = R * (.22 + .78 * frac);
939
+ const armOffset = arm / arms * Math.PI * 2;
940
+ const theta = Math.log(r / R + .1) * 2.8 + armOffset + t * .8;
941
+ const spread = (hashD(i, 4.3) - .5) * .2 * (1 - frac * .5);
942
+ const x = Math.cos(theta + spread) * r;
943
+ const z = Math.sin(theta + spread) * r;
944
+ const [px, py, pz] = pt(x, (hashD(i, 8.7) - .5) * R * .15 * (1 - frac), z);
945
+ const depth = (pz / R + 1) / 2;
946
+ pushDot(px, py, pz, ((o.rBase ?? .75) + (o.rDepth ?? 1.7) * depth * (1 - frac * .3)) * rs, .65 - .55 * depth, .35 + .65 * (1 - frac * .5));
947
+ }
948
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
949
+ }
950
+ function drawTorusMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
951
+ const cx = size / 2;
952
+ const cy = size / 2;
953
+ const R_major = size / 2 * .55;
954
+ const R_minor = size / 2 * .25;
955
+ const pt = makeProj(t * .25, .5 + .15 * Math.sin(t * .4), cx, cy, 1);
956
+ const rs = radiusScale(size, o.rsPow ?? .6);
957
+ resetDotBuffer();
958
+ const majorRings = o.rings ?? 16;
959
+ const segs = o.segs ?? 32;
960
+ for (let i = 0; i < majorRings; i++) {
961
+ const u = i / majorRings * Math.PI * 2;
962
+ for (let j = 0; j < segs; j++) {
963
+ const v = j / segs * Math.PI * 2;
964
+ const ripple = .12 * Math.sin(4 * u + 3 * v - t * 3);
965
+ const x = (R_major + (R_minor + ripple * R_minor) * Math.cos(v)) * Math.cos(u);
966
+ const z = (R_major + (R_minor + ripple * R_minor) * Math.cos(v)) * Math.sin(u);
967
+ const [px, py, pz] = pt(x, (R_minor + ripple * R_minor) * Math.sin(v), z);
968
+ const depth = (pz / (R_major + R_minor) + 1) / 2;
969
+ pushDot(px, py, pz, ((o.rBase ?? .7) + (o.rDepth ?? 1.6) * depth + ripple * .4) * rs, .65 - .5 * depth - ripple * .1, .3 + .7 * depth);
970
+ }
971
+ }
972
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
973
+ }
974
+ function drawQuantumMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
975
+ const cx = size / 2;
976
+ const cy = size / 2;
977
+ const S = size / 2 * .65;
978
+ const pt = makeProj(t * .3, .35 + .12 * Math.sin(t * .5), cx, cy, 1);
979
+ const rs = radiusScale(size, o.rsPow ?? .6);
980
+ resetDotBuffer();
981
+ const corners3D = [
982
+ [
983
+ -1,
984
+ -1,
985
+ -1
986
+ ],
987
+ [
988
+ 1,
989
+ -1,
990
+ -1
991
+ ],
992
+ [
993
+ 1,
994
+ 1,
995
+ -1
996
+ ],
997
+ [
998
+ -1,
999
+ 1,
1000
+ -1
1001
+ ],
1002
+ [
1003
+ -1,
1004
+ -1,
1005
+ 1
1006
+ ],
1007
+ [
1008
+ 1,
1009
+ -1,
1010
+ 1
1011
+ ],
1012
+ [
1013
+ 1,
1014
+ 1,
1015
+ 1
1016
+ ],
1017
+ [
1018
+ -1,
1019
+ 1,
1020
+ 1
1021
+ ]
1022
+ ];
1023
+ const edges = [
1024
+ [0, 1],
1025
+ [1, 2],
1026
+ [2, 3],
1027
+ [3, 0],
1028
+ [4, 5],
1029
+ [5, 6],
1030
+ [6, 7],
1031
+ [7, 4],
1032
+ [0, 4],
1033
+ [1, 5],
1034
+ [2, 6],
1035
+ [3, 7]
1036
+ ];
1037
+ const pulseInner = .55 + .15 * Math.sin(t * 2);
1038
+ const innerCorners = corners3D.map(([x, y, z]) => [
1039
+ x * pulseInner,
1040
+ y * pulseInner,
1041
+ z * pulseInner
1042
+ ]);
1043
+ const segs = o.segsPerEdge ?? 7;
1044
+ edges.forEach(([a, b]) => {
1045
+ const c1 = corners3D[a];
1046
+ const c2 = corners3D[b];
1047
+ for (let k = 0; k <= segs; k++) {
1048
+ const f = k / segs;
1049
+ const x = (c1[0] + (c2[0] - c1[0]) * f) * S * .8;
1050
+ const y = (c1[1] + (c2[1] - c1[1]) * f) * S * .8;
1051
+ const z = (c1[2] + (c2[2] - c1[2]) * f) * S * .8;
1052
+ const [px, py, pz] = pt(x, y, z);
1053
+ const depth = (pz / S + 1) / 2;
1054
+ const isVertex = k === 0 || k === segs;
1055
+ pushDot(px, py, pz, (isVertex ? 1.6 : .85) * rs, isVertex ? .1 : .6 - .4 * depth, isVertex ? 1 : .4 + .6 * depth);
1056
+ }
1057
+ });
1058
+ edges.forEach(([a, b]) => {
1059
+ const c1 = innerCorners[a];
1060
+ const c2 = innerCorners[b];
1061
+ for (let k = 0; k <= segs; k++) {
1062
+ const f = k / segs;
1063
+ const x = (c1[0] + (c2[0] - c1[0]) * f) * S * .8;
1064
+ const y = (c1[1] + (c2[1] - c1[1]) * f) * S * .8;
1065
+ const z = (c1[2] + (c2[2] - c1[2]) * f) * S * .8;
1066
+ const [px, py, pz] = pt(x, y, z);
1067
+ const depth = (pz / S + 1) / 2;
1068
+ const isVertex = k === 0 || k === segs;
1069
+ pushDot(px, py, pz, (isVertex ? 1.3 : .7) * rs, isVertex ? .15 : .65 - .45 * depth, isVertex ? .9 : .3 + .5 * depth);
1070
+ }
1071
+ });
1072
+ for (let i = 0; i < 8; i++) {
1073
+ const c1 = corners3D[i];
1074
+ const c2 = innerCorners[i];
1075
+ for (let k = 1; k < segs; k++) {
1076
+ const f = k / segs;
1077
+ const [px, py, pz] = pt((c1[0] + (c2[0] - c1[0]) * f) * S * .8, (c1[1] + (c2[1] - c1[1]) * f) * S * .8, (c1[2] + (c2[2] - c1[2]) * f) * S * .8);
1078
+ const depth = (pz / S + 1) / 2;
1079
+ pushDot(px, py, pz, .65 * rs, .7, .25 + .35 * depth);
1080
+ }
1081
+ }
1082
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
1083
+ }
1084
+ function drawNetworkMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
1085
+ const cx = size / 2;
1086
+ const cy = size / 2;
1087
+ const R = size / 2 * .78;
1088
+ const pt = makeProj(t * .18, .32, cx, cy, 1);
1089
+ const rs = radiusScale(size, o.rsPow ?? .6);
1090
+ resetDotBuffer();
1091
+ const numHubs = o.hubs ?? 28;
1092
+ const hubs = [];
1093
+ for (let i = 0; i < numHubs; i++) {
1094
+ const d = fibDir(i, numHubs);
1095
+ hubs.push([
1096
+ d[0] * R,
1097
+ d[1] * R,
1098
+ d[2] * R
1099
+ ]);
1100
+ }
1101
+ hubs.forEach(([hx, hy, hz], idx) => {
1102
+ const [px, py, pz] = pt(hx, hy, hz);
1103
+ const depth = (pz / R + 1) / 2;
1104
+ const pulse = Math.sin(t * 3 + idx * .7) > .6;
1105
+ pushDot(px, py, pz, (pulse ? 1.8 : 1.3) * rs, pulse ? .1 : .3 - .2 * depth, 1);
1106
+ });
1107
+ const segs = o.segsPerLink ?? 6;
1108
+ for (let i = 0; i < numHubs; i++) for (let j = i + 1; j < numHubs; j++) {
1109
+ const h1 = hubs[i];
1110
+ const h2 = hubs[j];
1111
+ if (Math.hypot(h1[0] - h2[0], h1[1] - h2[1], h1[2] - h2[2]) < R * .85) {
1112
+ const signalPos = (t * 1.8 + i * .5 + j * .3) % 1;
1113
+ for (let k = 1; k < segs; k++) {
1114
+ const f = k / segs;
1115
+ const [px, py, pz] = pt(h1[0] + (h2[0] - h1[0]) * f, h1[1] + (h2[1] - h1[1]) * f, h1[2] + (h2[2] - h1[2]) * f);
1116
+ const depth = (pz / R + 1) / 2;
1117
+ const isSignal = Math.abs(f - signalPos) < .15;
1118
+ pushDot(px, py, pz, (isSignal ? 1.2 : .65) * rs, isSignal ? .1 : .7, isSignal ? 1 : .2 + .4 * depth);
1119
+ }
1120
+ }
1121
+ }
1122
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
1123
+ }
1124
+ function drawSupernovaMode(ctx, size, t, dark, o, customRgb, styleVariant = "default") {
1125
+ const cx = size / 2;
1126
+ const cy = size / 2;
1127
+ const R_max = size / 2 * .85;
1128
+ const pt = makeProj(t * .22, .4, cx, cy, 1);
1129
+ const rs = radiusScale(size, o.rsPow ?? .6);
1130
+ resetDotBuffer();
1131
+ const cycle = t * 1.2 % (Math.PI * 2);
1132
+ const expansion = .2 + .8 * Math.abs(Math.sin(cycle)) ** 2;
1133
+ const R_curr = R_max * expansion;
1134
+ for (let i = 0; i < 20; i++) {
1135
+ const d = fibDir(i, 20);
1136
+ const cr = R_max * .15 * (1 - expansion * .5);
1137
+ const [px, py, pz] = pt(d[0] * cr, d[1] * cr, d[2] * cr);
1138
+ (pz / R_max + 1) / 2;
1139
+ pushDot(px, py, pz, 2 * rs, .05, 1);
1140
+ }
1141
+ const numRays = o.rays ?? 110;
1142
+ for (let i = 0; i < numRays; i++) {
1143
+ const d = fibDir(i, numRays);
1144
+ const rayLength = R_curr * (.6 + .4 * hashD(i, 3.2));
1145
+ const [px, py, pz] = pt(d[0] * rayLength, d[1] * rayLength, d[2] * rayLength);
1146
+ const depth = (pz / R_max + 1) / 2;
1147
+ pushDot(px, py, pz, ((o.rBase ?? .85) + (o.rDepth ?? 1.8) * depth * (1.2 - expansion * .4)) * rs, .6 - .5 * depth, .3 + .7 * depth);
1148
+ }
1149
+ paintDots(ctx, dark, o.rMin, customRgb, styleVariant);
1150
+ }
1151
+ function parseColorToRgb(colorStr) {
1152
+ if (!colorStr) return null;
1153
+ if (colorStr.startsWith("#")) {
1154
+ let hex = colorStr.slice(1);
1155
+ if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
1156
+ if (hex.length === 6) {
1157
+ const num = parseInt(hex, 16);
1158
+ return [
1159
+ num >> 16 & 255,
1160
+ num >> 8 & 255,
1161
+ num & 255
1162
+ ];
1163
+ }
1164
+ }
1165
+ const match = colorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
1166
+ if (match) return [
1167
+ parseInt(match[1], 10),
1168
+ parseInt(match[2], 10),
1169
+ parseInt(match[3], 10)
1170
+ ];
1171
+ return null;
1172
+ }
1173
+ function useResolvedDark(theme, hostRef) {
1174
+ const [dark, setDark] = React$1.useState(true);
1175
+ React$1.useEffect(() => {
1176
+ if (theme === "dark") {
1177
+ setDark(true);
1178
+ return;
1179
+ }
1180
+ if (theme === "light") {
1181
+ setDark(false);
1182
+ return;
1183
+ }
1184
+ const resolve = () => {
1185
+ let node = hostRef.current;
1186
+ while (node) {
1187
+ if (node.classList.contains("dark") || node.getAttribute("data-theme") === "dark") {
1188
+ setDark(true);
1189
+ return;
1190
+ }
1191
+ if (node.classList.contains("light") || node.getAttribute("data-theme") === "light") {
1192
+ setDark(false);
1193
+ return;
1194
+ }
1195
+ node = node.parentElement;
1196
+ }
1197
+ const systemDark = typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)").matches;
1198
+ setDark(systemDark);
1199
+ };
1200
+ resolve();
1201
+ const mq = typeof matchMedia !== "undefined" ? matchMedia("(prefers-color-scheme: dark)") : null;
1202
+ const onMq = () => resolve();
1203
+ mq?.addEventListener("change", onMq);
1204
+ let mo = null;
1205
+ if (typeof MutationObserver !== "undefined" && hostRef.current) {
1206
+ mo = new MutationObserver(resolve);
1207
+ mo.observe(document.documentElement, {
1208
+ attributes: true,
1209
+ attributeFilter: ["class", "data-theme"],
1210
+ subtree: true
1211
+ });
1212
+ }
1213
+ return () => {
1214
+ mq?.removeEventListener("change", onMq);
1215
+ mo?.disconnect();
1216
+ };
1217
+ }, [theme, hostRef]);
1218
+ return dark;
1219
+ }
1220
+ function useReducedMotion() {
1221
+ const [reduced, setReduced] = React$1.useState(false);
1222
+ React$1.useEffect(() => {
1223
+ if (typeof matchMedia === "undefined") return;
1224
+ const mq = matchMedia("(prefers-reduced-motion: reduce)");
1225
+ setReduced(mq.matches);
1226
+ const on = (e) => setReduced(e.matches);
1227
+ mq.addEventListener("change", on);
1228
+ return () => mq.removeEventListener("change", on);
1229
+ }, []);
1230
+ return reduced;
1231
+ }
1232
+ function Orb({ className, variant = "default", intent, size = "lg", glow, state = "working", pixelSize, theme = "auto", speed = 1, paused = false, color, interactive = false, render, "aria-label": ariaLabel, ...props }) {
1233
+ const wrapperRef = React$1.useRef(null);
1234
+ const canvasRef = React$1.useRef(null);
1235
+ const hoverSpeedRef = React$1.useRef(1);
1236
+ const dark = useResolvedDark(theme, wrapperRef);
1237
+ const reduced = useReducedMotion();
1238
+ const computedSize = pixelSize ?? (size ? SIZE_MAP[size] : 64);
1239
+ const modeKey = STATE_ALIAS_MAP[state] ?? "orbits";
1240
+ const styleVariant = variant || "default";
1241
+ React$1.useEffect(() => {
1242
+ const canvas = canvasRef.current;
1243
+ if (!canvas) return;
1244
+ const dpr = Math.min(2, typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1);
1245
+ canvas.width = Math.round(computedSize * dpr);
1246
+ canvas.height = Math.round(computedSize * dpr);
1247
+ const ctx = canvas.getContext("2d");
1248
+ if (!ctx) return;
1249
+ const opts = resolveOptsForSize(modeKey, computedSize);
1250
+ const customRgb = parseColorToRgb(color ?? "");
1251
+ const baseSpeed = MODE_BASE_SPEED[modeKey] ?? 1.885;
1252
+ const renderFrame = (tSec) => {
1253
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
1254
+ ctx.clearRect(0, 0, computedSize, computedSize);
1255
+ switch (modeKey) {
1256
+ case "orbits":
1257
+ drawOrbitsMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1258
+ break;
1259
+ case "globe":
1260
+ drawGlobeMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1261
+ break;
1262
+ case "rubik":
1263
+ drawRubikMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1264
+ break;
1265
+ case "wave":
1266
+ drawWaveMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1267
+ break;
1268
+ case "ribbon":
1269
+ drawRibbonMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1270
+ break;
1271
+ case "morph":
1272
+ drawMorphMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1273
+ break;
1274
+ case "pulse":
1275
+ drawPulseMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1276
+ break;
1277
+ case "vortex":
1278
+ drawVortexMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1279
+ break;
1280
+ case "atom":
1281
+ drawAtomMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1282
+ break;
1283
+ case "helix":
1284
+ drawHelixMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1285
+ break;
1286
+ case "radar":
1287
+ drawRadarMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1288
+ break;
1289
+ case "galaxy":
1290
+ drawGalaxyMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1291
+ break;
1292
+ case "torus":
1293
+ drawTorusMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1294
+ break;
1295
+ case "quantum":
1296
+ drawQuantumMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1297
+ break;
1298
+ case "network":
1299
+ drawNetworkMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1300
+ break;
1301
+ case "supernova": drawSupernovaMode(ctx, computedSize, tSec, dark, opts, customRgb, styleVariant);
1302
+ }
1303
+ };
1304
+ if (reduced) {
1305
+ renderFrame(.6);
1306
+ return;
1307
+ }
1308
+ let raf = 0;
1309
+ let running = false;
1310
+ const startTime = performance.now();
1311
+ const loop = () => {
1312
+ const elapsedSec = (performance.now() - startTime) / 1e3 * baseSpeed * speed * hoverSpeedRef.current;
1313
+ renderFrame(elapsedSec);
1314
+ if (running) raf = requestAnimationFrame(loop);
1315
+ };
1316
+ const start = () => {
1317
+ if (running || paused) return;
1318
+ running = true;
1319
+ raf = requestAnimationFrame(loop);
1320
+ };
1321
+ const stop = () => {
1322
+ running = false;
1323
+ cancelAnimationFrame(raf);
1324
+ };
1325
+ renderFrame(0);
1326
+ let isIntersecting = true;
1327
+ const observer = typeof IntersectionObserver !== "undefined" ? new IntersectionObserver(([entry]) => {
1328
+ isIntersecting = entry.isIntersecting;
1329
+ if (isIntersecting && document.visibilityState !== "hidden") start();
1330
+ else stop();
1331
+ }) : null;
1332
+ if (canvas) observer?.observe(canvas);
1333
+ const onVisibilityChange = () => {
1334
+ if (document.visibilityState === "hidden") stop();
1335
+ else if (isIntersecting) start();
1336
+ };
1337
+ document.addEventListener("visibilitychange", onVisibilityChange);
1338
+ if (!observer) start();
1339
+ return () => {
1340
+ stop();
1341
+ observer?.disconnect();
1342
+ document.removeEventListener("visibilitychange", onVisibilityChange);
1343
+ };
1344
+ }, [
1345
+ modeKey,
1346
+ computedSize,
1347
+ dark,
1348
+ speed,
1349
+ paused,
1350
+ reduced,
1351
+ color,
1352
+ styleVariant
1353
+ ]);
1354
+ const handleMouseEnter = () => {
1355
+ if (interactive) hoverSpeedRef.current = 1.75;
1356
+ };
1357
+ const handleMouseLeave = () => {
1358
+ if (interactive) hoverSpeedRef.current = 1;
1359
+ };
1360
+ const defaultProps = {
1361
+ ref: wrapperRef,
1362
+ className: cn(orbVariants({
1363
+ variant,
1364
+ intent,
1365
+ size,
1366
+ glow,
1367
+ className
1368
+ })),
1369
+ role: "status",
1370
+ "aria-label": ariaLabel ?? STATE_LABELS[state] ?? "AI Orb",
1371
+ "data-slot": "orb",
1372
+ onMouseEnter: handleMouseEnter,
1373
+ onMouseLeave: handleMouseLeave,
1374
+ children: /* @__PURE__ */ jsx("canvas", {
1375
+ "aria-hidden": "true",
1376
+ ref: canvasRef,
1377
+ style: {
1378
+ width: computedSize,
1379
+ height: computedSize,
1380
+ display: "block"
1381
+ }
1382
+ })
1383
+ };
1384
+ return useRender({
1385
+ defaultTagName: "div",
1386
+ props: mergeProps(defaultProps, props),
1387
+ render
1388
+ });
1389
+ }
1390
+ function OrbLabel({ className, render, ...props }) {
1391
+ const defaultProps = {
1392
+ className: cn("font-mono text-xs text-muted-foreground select-none", className),
1393
+ "data-slot": "orb-label"
1394
+ };
1395
+ return useRender({
1396
+ defaultTagName: "span",
1397
+ props: mergeProps(defaultProps, props),
1398
+ render
1399
+ });
1400
+ }
1401
+ function OrbBadge({ className, render, ...props }) {
1402
+ const defaultProps = {
1403
+ className: cn("inline-flex items-center gap-2 rounded-full border border-border/80 bg-background/80 px-2.5 py-1 text-xs backdrop-blur-sm shadow-xs/5", className),
1404
+ "data-slot": "orb-badge"
1405
+ };
1406
+ return useRender({
1407
+ defaultTagName: "div",
1408
+ props: mergeProps(defaultProps, props),
1409
+ render
1410
+ });
1411
+ }
1412
+ //#endregion
1413
+ export { Orb, OrbBadge, OrbLabel, orbVariants };