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,1184 @@
1
+ "use client";
2
+ import { cn } from "cn";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { memo, useCallback, useEffect, useRef, useState } from "react";
5
+ //#region src/components/kinetic-click.tsx
6
+ const KATA = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン0123456789";
7
+ var GlobalCanvasManager = class GlobalCanvasManager {
8
+ static instance = null;
9
+ canvas = null;
10
+ ctx = null;
11
+ particles = [];
12
+ animId = null;
13
+ consumers = 0;
14
+ constructor() {
15
+ if (typeof window === "undefined") return;
16
+ this.createCanvas();
17
+ window.addEventListener("resize", this.handleResize);
18
+ }
19
+ static getInstance() {
20
+ if (!GlobalCanvasManager.instance) GlobalCanvasManager.instance = new GlobalCanvasManager();
21
+ return GlobalCanvasManager.instance;
22
+ }
23
+ createCanvas() {
24
+ this.canvas = document.createElement("canvas");
25
+ this.canvas.dataset.slot = "kinetic-click-canvas";
26
+ this.canvas.setAttribute("aria-hidden", "true");
27
+ Object.assign(this.canvas.style, {
28
+ position: "fixed",
29
+ top: "0",
30
+ left: "0",
31
+ width: "100vw",
32
+ height: "100vh",
33
+ pointerEvents: "none",
34
+ zIndex: "999999"
35
+ });
36
+ this.canvas.width = window.innerWidth;
37
+ this.canvas.height = window.innerHeight;
38
+ document.body.appendChild(this.canvas);
39
+ this.ctx = this.canvas.getContext("2d");
40
+ }
41
+ handleResize = () => {
42
+ if (this.canvas) {
43
+ this.canvas.width = window.innerWidth;
44
+ this.canvas.height = window.innerHeight;
45
+ }
46
+ };
47
+ addParticles(newParticles) {
48
+ this.particles.push(...newParticles);
49
+ this.startLoop();
50
+ }
51
+ retain() {
52
+ this.consumers += 1;
53
+ }
54
+ release() {
55
+ this.consumers = Math.max(0, this.consumers - 1);
56
+ if (this.consumers === 0) this.cleanup();
57
+ }
58
+ startLoop() {
59
+ if (this.animId !== null) return;
60
+ const loop = (timestamp) => {
61
+ this.updateAndDraw(timestamp);
62
+ if (this.particles.length > 0) this.animId = requestAnimationFrame(loop);
63
+ else {
64
+ this.animId = null;
65
+ if (this.ctx && this.canvas) this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
66
+ }
67
+ };
68
+ this.animId = requestAnimationFrame(loop);
69
+ }
70
+ updateAndDraw(_timestamp) {
71
+ const ctx = this.ctx;
72
+ const canvas = this.canvas;
73
+ if (!ctx || !canvas) return;
74
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
75
+ const TESSERACT_NODES = [
76
+ [
77
+ -1,
78
+ -1,
79
+ -1
80
+ ],
81
+ [
82
+ 1,
83
+ -1,
84
+ -1
85
+ ],
86
+ [
87
+ 1,
88
+ 1,
89
+ -1
90
+ ],
91
+ [
92
+ -1,
93
+ 1,
94
+ -1
95
+ ],
96
+ [
97
+ -1,
98
+ -1,
99
+ 1
100
+ ],
101
+ [
102
+ 1,
103
+ -1,
104
+ 1
105
+ ],
106
+ [
107
+ 1,
108
+ 1,
109
+ 1
110
+ ],
111
+ [
112
+ -1,
113
+ 1,
114
+ 1
115
+ ]
116
+ ];
117
+ const TESSERACT_EDGES = [
118
+ [0, 1],
119
+ [1, 2],
120
+ [2, 3],
121
+ [3, 0],
122
+ [4, 5],
123
+ [5, 6],
124
+ [6, 7],
125
+ [7, 4],
126
+ [0, 4],
127
+ [1, 5],
128
+ [2, 6],
129
+ [3, 7]
130
+ ];
131
+ const coreKeys = /* @__PURE__ */ new Set();
132
+ this.particles = this.particles.filter((p) => {
133
+ p.life -= p.decay;
134
+ if (p.life <= 0) return false;
135
+ ctx.save();
136
+ ctx.globalAlpha = Math.max(0, p.life);
137
+ switch (p.type) {
138
+ case "spark": {
139
+ p.x += p.vx;
140
+ p.y += p.vy;
141
+ p.vy += .05;
142
+ const tailX = p.x - p.vx * 1.5;
143
+ const tailY = p.y - p.vy * 1.5;
144
+ ctx.beginPath();
145
+ ctx.moveTo(tailX, tailY);
146
+ ctx.lineTo(p.x, p.y);
147
+ ctx.lineWidth = p.size;
148
+ ctx.strokeStyle = p.color;
149
+ ctx.lineCap = "round";
150
+ ctx.stroke();
151
+ break;
152
+ }
153
+ case "ripple":
154
+ p.size += p.vx;
155
+ ctx.beginPath();
156
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
157
+ ctx.lineWidth = p.vy;
158
+ ctx.strokeStyle = p.color;
159
+ ctx.stroke();
160
+ break;
161
+ case "embers": {
162
+ p.vy -= .02;
163
+ p.x += p.vx + Math.sin(p.wobble ?? 0) * .4;
164
+ p.y += p.vy;
165
+ if (p.wobble !== void 0 && p.wobbleSpeed !== void 0) p.wobble += p.wobbleSpeed;
166
+ const currentRadius = Math.max(.2, p.size * p.life);
167
+ ctx.beginPath();
168
+ ctx.arc(p.x, p.y, currentRadius, 0, Math.PI * 2);
169
+ ctx.fillStyle = p.color;
170
+ ctx.fill();
171
+ break;
172
+ }
173
+ case "quantum": {
174
+ if (p.timer !== void 0 && p.teleportTimer !== void 0) {
175
+ p.timer--;
176
+ if (p.timer <= 0) {
177
+ const spread = p.vx;
178
+ p.x = p.originX + (Math.random() - .5) * spread;
179
+ p.y = p.originY + (Math.random() - .5) * spread;
180
+ p.timer = Math.random() * p.teleportTimer;
181
+ }
182
+ }
183
+ const cs = p.size;
184
+ ctx.beginPath();
185
+ ctx.moveTo(p.x - cs, p.y);
186
+ ctx.lineTo(p.x + cs, p.y);
187
+ ctx.moveTo(p.x, p.y - cs);
188
+ ctx.lineTo(p.x, p.y + cs);
189
+ ctx.lineWidth = 1;
190
+ ctx.strokeStyle = p.color;
191
+ ctx.stroke();
192
+ break;
193
+ }
194
+ case "tesseract":
195
+ if (p.rotX !== void 0 && p.rotY !== void 0 && p.rotSpeedX !== void 0 && p.rotSpeedY !== void 0) {
196
+ p.rotX += p.rotSpeedX;
197
+ p.rotY += p.rotSpeedY;
198
+ const limitSize = p.vx;
199
+ const speed = p.vy;
200
+ if (p.size < limitSize) p.size += speed;
201
+ const rx = p.rotX;
202
+ const ry = p.rotY;
203
+ const size = p.size;
204
+ const projected = TESSERACT_NODES.map(([nx, ny, nz]) => {
205
+ const x1 = nx * Math.cos(ry) - nz * Math.sin(ry);
206
+ const z1 = nx * Math.sin(ry) + nz * Math.cos(ry);
207
+ const y2 = ny * Math.cos(rx) - z1 * Math.sin(rx);
208
+ const x2 = x1;
209
+ return [p.x + x2 * size, p.y + y2 * size];
210
+ });
211
+ ctx.beginPath();
212
+ for (const [a, b] of TESSERACT_EDGES) {
213
+ ctx.moveTo(projected[a][0], projected[a][1]);
214
+ ctx.lineTo(projected[b][0], projected[b][1]);
215
+ }
216
+ ctx.lineWidth = 1;
217
+ ctx.strokeStyle = p.color;
218
+ ctx.stroke();
219
+ }
220
+ break;
221
+ case "blackhole":
222
+ if (p.angle !== void 0 && p.dist !== void 0) {
223
+ p.dist *= p.accretion ?? .93;
224
+ p.angle += 3 / Math.max(5, p.dist);
225
+ const px = p.originX + Math.cos(p.angle) * p.dist;
226
+ const py = p.originY + Math.sin(p.angle) * p.dist;
227
+ ctx.beginPath();
228
+ ctx.arc(px, py, p.size, 0, Math.PI * 2);
229
+ ctx.fillStyle = p.color;
230
+ ctx.fill();
231
+ const key = `${p.originX},${p.originY}`;
232
+ if (!coreKeys.has(key)) {
233
+ coreKeys.add(key);
234
+ ctx.save();
235
+ ctx.globalAlpha = Math.max(0, p.life * .5);
236
+ ctx.beginPath();
237
+ ctx.arc(p.originX, p.originY, p.size * 4, 0, Math.PI * 2);
238
+ ctx.strokeStyle = p.color;
239
+ ctx.lineWidth = 1;
240
+ ctx.stroke();
241
+ ctx.restore();
242
+ }
243
+ }
244
+ break;
245
+ case "firework":
246
+ p.vx *= p.friction ?? .96;
247
+ p.vy *= p.friction ?? .96;
248
+ p.vy += p.gravity ?? .08;
249
+ p.x += p.vx;
250
+ p.y += p.vy;
251
+ ctx.beginPath();
252
+ ctx.arc(p.x, p.y, p.size * (.6 + Math.random() * .8), 0, Math.PI * 2);
253
+ ctx.fillStyle = p.color;
254
+ ctx.fill();
255
+ break;
256
+ case "shatter":
257
+ if (p.angle !== void 0 && p.dist !== void 0 && p.initialRotation !== void 0 && p.rotationSpeed !== void 0) {
258
+ const easedProgress = 1 - p.life;
259
+ const x = p.originX + Math.cos(p.angle) * easedProgress * p.dist;
260
+ const y = p.originY + Math.sin(p.angle) * easedProgress * p.dist + (p.gravity ?? .6) * easedProgress * easedProgress * p.dist;
261
+ const rotation = p.initialRotation + p.rotationSpeed * easedProgress * Math.PI * 4;
262
+ const shardAlpha = p.life < .4 ? p.life / .4 : 1;
263
+ ctx.save();
264
+ ctx.globalAlpha = Math.max(0, shardAlpha * p.life);
265
+ ctx.translate(x, y);
266
+ ctx.rotate(rotation);
267
+ ctx.fillStyle = p.color;
268
+ const s = p.size;
269
+ ctx.beginPath();
270
+ ctx.moveTo(0, -s);
271
+ ctx.lineTo(s, s);
272
+ ctx.lineTo(-s, s);
273
+ ctx.closePath();
274
+ ctx.fill();
275
+ ctx.restore();
276
+ }
277
+ break;
278
+ case "warp":
279
+ if (p.angle !== void 0 && p.dist !== void 0) {
280
+ p.vx *= p.accel ?? 1.1;
281
+ const oldX = p.originX + Math.cos(p.angle) * p.dist;
282
+ const oldY = p.originY + Math.sin(p.angle) * p.dist;
283
+ p.dist += p.vx;
284
+ const newX = p.originX + Math.cos(p.angle) * p.dist;
285
+ const newY = p.originY + Math.sin(p.angle) * p.dist;
286
+ const lineW = Math.min(p.size, p.vx * .15);
287
+ ctx.beginPath();
288
+ ctx.moveTo(oldX, oldY);
289
+ ctx.lineTo(newX, newY);
290
+ ctx.lineWidth = lineW;
291
+ ctx.strokeStyle = p.color;
292
+ ctx.stroke();
293
+ }
294
+ break;
295
+ case "matrix": {
296
+ const easedProgress = 1 - p.life;
297
+ const traveled = p.vy * easedProgress * 60;
298
+ const headY = p.y + traveled;
299
+ ctx.font = `${p.size}px monospace`;
300
+ ctx.textAlign = "center";
301
+ const trail = p.trailLength ?? 8;
302
+ for (let j = 0; j < trail; j++) {
303
+ const charY = headY - j * (p.size + 2);
304
+ const trailAlpha = Math.max(0, (1 - j / trail) * p.life);
305
+ ctx.save();
306
+ ctx.fillStyle = p.color;
307
+ ctx.globalAlpha = Math.max(0, (j === 0 ? trailAlpha : trailAlpha * .6) * p.life);
308
+ const char = KATA[Math.floor(Math.random() * 55)];
309
+ ctx.fillText(char, p.x, charY);
310
+ ctx.restore();
311
+ }
312
+ break;
313
+ }
314
+ case "smoke":
315
+ p.x += p.vx;
316
+ p.y += p.vy;
317
+ p.size += p.speed ?? .3;
318
+ ctx.save();
319
+ ctx.beginPath();
320
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
321
+ ctx.fillStyle = p.color;
322
+ ctx.globalAlpha = Math.max(0, p.life * (p.opacity ?? .15));
323
+ ctx.fill();
324
+ ctx.restore();
325
+ break;
326
+ case "supernova":
327
+ if (p.subType === "ring") {
328
+ p.size += p.vx;
329
+ ctx.beginPath();
330
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
331
+ ctx.lineWidth = 4 * p.life;
332
+ ctx.strokeStyle = p.color;
333
+ ctx.stroke();
334
+ } else {
335
+ p.x += p.vx;
336
+ p.y += p.vy;
337
+ p.vx *= p.friction ?? .95;
338
+ p.vy *= p.friction ?? .95;
339
+ ctx.beginPath();
340
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
341
+ ctx.fillStyle = p.color;
342
+ ctx.fill();
343
+ }
344
+ break;
345
+ case "holosphere": {
346
+ p.rotX = (p.rotX ?? 0) + (p.rotSpeedX ?? .02);
347
+ p.rotY = (p.rotY ?? 0) + (p.rotSpeedY ?? .03);
348
+ const maxS = p.vx;
349
+ const growS = p.vy;
350
+ if (p.size < maxS) p.size += growS;
351
+ if (p.pts) for (const [sx, sy, sz] of p.pts) {
352
+ const py = sy * Math.cos(p.rotX) - sz * Math.sin(p.rotX);
353
+ const pz1 = sy * Math.sin(p.rotX) + sz * Math.cos(p.rotX);
354
+ const px = sx * Math.cos(p.rotY) - pz1 * Math.sin(p.rotY);
355
+ const depth = (sx * Math.sin(p.rotY) + pz1 * Math.cos(p.rotY) + 1) / 2;
356
+ ctx.save();
357
+ ctx.fillStyle = p.color;
358
+ ctx.globalAlpha = Math.max(0, p.life * depth);
359
+ ctx.fillRect(p.x + px * p.size, p.y + py * p.size, 1.5, 1.5);
360
+ ctx.restore();
361
+ }
362
+ break;
363
+ }
364
+ case "flowfield":
365
+ p.vx += Math.sin(p.y * (p.fieldScale ?? .05)) * (p.fieldStrength ?? .2);
366
+ p.vy += Math.cos(p.x * (p.fieldScale ?? .05)) * (p.fieldStrength ?? .2);
367
+ p.x += p.vx;
368
+ p.y += p.vy;
369
+ ctx.beginPath();
370
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
371
+ ctx.fillStyle = p.color;
372
+ ctx.fill();
373
+ break;
374
+ case "synapse": {
375
+ p.vx *= p.friction ?? .88;
376
+ p.vy *= p.friction ?? .88;
377
+ p.x += p.vx;
378
+ p.y += p.vy;
379
+ const connectionDist = p.dist ?? 70;
380
+ ctx.save();
381
+ ctx.beginPath();
382
+ const groupNodes = this.particles.filter((other) => other.type === "synapse" && other.groupId === p.groupId && other.id > p.id);
383
+ for (const other of groupNodes) {
384
+ const dx = p.x - other.x;
385
+ const dy = p.y - other.y;
386
+ if (Math.sqrt(dx * dx + dy * dy) < connectionDist) {
387
+ ctx.moveTo(p.x, p.y);
388
+ ctx.lineTo(other.x, other.y);
389
+ }
390
+ }
391
+ ctx.lineWidth = 1;
392
+ ctx.strokeStyle = p.color;
393
+ ctx.globalAlpha = Math.max(0, p.life * .4);
394
+ ctx.stroke();
395
+ ctx.restore();
396
+ ctx.beginPath();
397
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
398
+ ctx.fillStyle = p.color;
399
+ ctx.fill();
400
+ break;
401
+ }
402
+ case "diffusion": {
403
+ const easeSpeed = .1;
404
+ p.x += (p.vx - p.x) * easeSpeed;
405
+ p.y += (p.vy - p.y) * easeSpeed;
406
+ ctx.beginPath();
407
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
408
+ ctx.fillStyle = p.color;
409
+ ctx.fill();
410
+ break;
411
+ }
412
+ case "rain":
413
+ if (!p.hit) {
414
+ p.y += p.vy;
415
+ const streakHeight = 15;
416
+ ctx.save();
417
+ ctx.beginPath();
418
+ ctx.moveTo(p.x, p.y - streakHeight);
419
+ ctx.lineTo(p.x, p.y);
420
+ ctx.lineWidth = 1;
421
+ ctx.strokeStyle = p.color;
422
+ ctx.stroke();
423
+ ctx.restore();
424
+ if (p.y >= (p.targetY ?? p.y)) {
425
+ p.hit = true;
426
+ p.y = p.targetY ?? p.y;
427
+ p.size = 0;
428
+ }
429
+ } else {
430
+ const rippleSpeed = 1.5;
431
+ const rippleSquish = .4;
432
+ p.size += rippleSpeed;
433
+ const rippleAlpha = Math.max(0, p.life - (1 - p.life) * .5);
434
+ ctx.save();
435
+ ctx.beginPath();
436
+ ctx.ellipse(p.x, p.targetY ?? p.y, p.size, p.size * rippleSquish, 0, 0, Math.PI * 2);
437
+ ctx.lineWidth = 1;
438
+ ctx.strokeStyle = p.color;
439
+ ctx.globalAlpha = Math.max(0, rippleAlpha);
440
+ ctx.stroke();
441
+ ctx.restore();
442
+ }
443
+ break;
444
+ case "binary": {
445
+ const progress = 1 - p.life;
446
+ const eased = progress * (2 - progress);
447
+ p.x = p.originX + Math.cos(p.angle ?? 0) * eased * (p.dist ?? 60);
448
+ p.y = p.originY + Math.sin(p.angle ?? 0) * eased * (p.dist ?? 60) - eased * 18;
449
+ const alpha = progress < .5 ? 1 : 1 - (progress - .5) * 2;
450
+ ctx.save();
451
+ ctx.font = `${p.size}px monospace`;
452
+ ctx.textAlign = "center";
453
+ ctx.textBaseline = "middle";
454
+ ctx.globalAlpha = Math.max(0, alpha);
455
+ ctx.fillStyle = p.color;
456
+ ctx.fillText(p.char ?? "1", p.x, p.y);
457
+ ctx.restore();
458
+ break;
459
+ }
460
+ case "fission": {
461
+ const alpha = p.life;
462
+ let splits = 1;
463
+ let radius = p.size;
464
+ let spread = 0;
465
+ const maxSpread = 40;
466
+ if (p.life > .6) {
467
+ splits = 1;
468
+ radius = p.size * 2;
469
+ spread = 0;
470
+ } else if (p.life > .3) {
471
+ splits = 3;
472
+ radius = p.size;
473
+ spread = (1 - p.life) * maxSpread;
474
+ } else {
475
+ splits = 9;
476
+ radius = p.size * .5;
477
+ spread = (1 - p.life) * maxSpread;
478
+ }
479
+ const spinAngle = p.life * 5;
480
+ for (let i = 0; i < splits; i++) {
481
+ const angle = i * (Math.PI * 2 / splits) + spinAngle;
482
+ const sx = p.x + (splits > 1 ? Math.cos(angle) * spread : 0);
483
+ const sy = p.y + (splits > 1 ? Math.sin(angle) * spread : 0);
484
+ ctx.beginPath();
485
+ ctx.arc(sx, sy, radius, 0, Math.PI * 2);
486
+ ctx.fillStyle = p.color;
487
+ ctx.globalAlpha = alpha;
488
+ ctx.fill();
489
+ }
490
+ break;
491
+ }
492
+ case "bullettime": {
493
+ p.vx *= p.friction ?? .92;
494
+ p.vy *= p.friction ?? .92;
495
+ p.x += p.vx;
496
+ p.y += p.vy;
497
+ const dx = p.x - p.originX;
498
+ const dy = p.y - p.originY;
499
+ if (Math.sqrt(dx * dx + dy * dy) <= (p.dist ?? 80)) {
500
+ const alpha = p.life;
501
+ const speed = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
502
+ ctx.save();
503
+ ctx.strokeStyle = p.color;
504
+ ctx.lineWidth = p.size * p.life;
505
+ ctx.lineCap = "round";
506
+ ctx.globalAlpha = alpha;
507
+ ctx.beginPath();
508
+ ctx.moveTo(p.x, p.y);
509
+ ctx.lineTo(p.x - p.vx / (speed || 1) * speed * 2.5, p.y - p.vy / (speed || 1) * speed * 2.5);
510
+ ctx.stroke();
511
+ ctx.restore();
512
+ if (p.life > .5) {
513
+ ctx.save();
514
+ ctx.strokeStyle = p.color;
515
+ ctx.lineWidth = .5;
516
+ ctx.globalAlpha = p.life * .3;
517
+ ctx.beginPath();
518
+ ctx.arc(p.x, p.y, (1 - p.life) * 30, 0, Math.PI * 2);
519
+ ctx.stroke();
520
+ ctx.restore();
521
+ }
522
+ ctx.beginPath();
523
+ ctx.arc(p.x, p.y, p.size * .8, 0, Math.PI * 2);
524
+ ctx.fillStyle = p.color;
525
+ ctx.fill();
526
+ }
527
+ break;
528
+ }
529
+ }
530
+ ctx.restore();
531
+ return true;
532
+ });
533
+ }
534
+ cleanup() {
535
+ if (this.canvas) {
536
+ window.removeEventListener("resize", this.handleResize);
537
+ if (this.canvas.parentNode) this.canvas.parentNode.removeChild(this.canvas);
538
+ this.canvas = null;
539
+ this.ctx = null;
540
+ this.particles = [];
541
+ if (this.animId !== null) {
542
+ cancelAnimationFrame(this.animId);
543
+ this.animId = null;
544
+ }
545
+ GlobalCanvasManager.instance = null;
546
+ }
547
+ }
548
+ };
549
+ function isNeutralColor(color) {
550
+ if (!color || color === "transparent" || color.includes("rgba(0, 0, 0, 0)")) return true;
551
+ const normalized = color.trim().toLowerCase();
552
+ const rgbMatch = normalized.match(/rgba?\((\d+)[\s,]+(\d+)[\s,]+(\d+)/);
553
+ if (rgbMatch) {
554
+ const red = parseInt(rgbMatch[1], 10);
555
+ const green = parseInt(rgbMatch[2], 10);
556
+ const blue = parseInt(rgbMatch[3], 10);
557
+ return Math.max(red, green, blue) - Math.min(red, green, blue) < 20;
558
+ }
559
+ const oklchMatch = normalized.match(/oklch\(([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/);
560
+ if (oklchMatch) return parseFloat(oklchMatch[2]) < .04;
561
+ const hslMatch = normalized.match(/hsla?\(([\d.]+)deg?[,\s]+([\d.]+)%?[,\s]+([\d.]+)%?/) || normalized.match(/hsla?\(([\d.]+)[,\s]+([\d.]+)%?[,\s]+([\d.]+)%?/);
562
+ if (hslMatch) {
563
+ const saturationText = hslMatch[2];
564
+ const saturation = parseFloat(saturationText);
565
+ return saturationText.includes("%") || saturation > 1 ? saturation < 4 : saturation < .04;
566
+ }
567
+ if (normalized.startsWith("#")) {
568
+ const hex = normalized.slice(1);
569
+ if (hex.length === 3 || hex.length === 4) {
570
+ const red = parseInt(hex[0], 16);
571
+ const green = parseInt(hex[1], 16);
572
+ const blue = parseInt(hex[2], 16);
573
+ return Math.max(red, green, blue) - Math.min(red, green, blue) < 2;
574
+ }
575
+ if (hex.length === 6 || hex.length === 8) {
576
+ const red = parseInt(hex.slice(0, 2), 16);
577
+ const green = parseInt(hex.slice(2, 4), 16);
578
+ const blue = parseInt(hex.slice(4, 6), 16);
579
+ return Math.max(red, green, blue) - Math.min(red, green, blue) < 20;
580
+ }
581
+ }
582
+ return false;
583
+ }
584
+ const KineticClick = memo(function KineticClick({ variant = "spark", color = "currentColor", colorFrom = "auto", count, size, duration, trigger = "mousedown", className, style, children, ...props }) {
585
+ const containerRef = useRef(null);
586
+ const [manager, setManager] = useState(null);
587
+ useEffect(() => {
588
+ const m = GlobalCanvasManager.getInstance();
589
+ m.retain();
590
+ setManager(m);
591
+ return () => m.release();
592
+ }, []);
593
+ const handleTrigger = useCallback((e) => {
594
+ if (!manager) return;
595
+ const resolveTargetColor = (el) => {
596
+ if (color && color !== "currentColor") return color;
597
+ try {
598
+ const clone = el.cloneNode(false);
599
+ clone.style.position = "absolute";
600
+ clone.style.visibility = "hidden";
601
+ clone.style.pointerEvents = "none";
602
+ const parent = el.parentNode || document.body;
603
+ parent.appendChild(clone);
604
+ const cs = window.getComputedStyle(clone);
605
+ const textColor = cs.color;
606
+ const bgColor = cs.backgroundColor;
607
+ const borderColor = cs.borderColor;
608
+ parent.removeChild(clone);
609
+ if (colorFrom === "text") return textColor || "#ffffff";
610
+ if (colorFrom === "background") return bgColor && bgColor !== "transparent" && !bgColor.includes("rgba(0, 0, 0, 0)") ? bgColor : "#ffffff";
611
+ if (colorFrom === "border") return borderColor && borderColor !== "transparent" && !borderColor.includes("rgba(0, 0, 0, 0)") ? borderColor : "#ffffff";
612
+ if (!isNeutralColor(textColor)) return textColor;
613
+ if (!isNeutralColor(bgColor)) return bgColor;
614
+ if (!isNeutralColor(borderColor)) return borderColor;
615
+ return textColor || "#ffffff";
616
+ } catch {
617
+ return "#ffffff";
618
+ }
619
+ };
620
+ const computedColor = resolveTargetColor(e.target?.closest?.("button, a, [role='button']") || e.currentTarget);
621
+ const x = e.clientX;
622
+ const y = e.clientY;
623
+ const list = [];
624
+ const pid = Math.random().toString(36).slice(2, 9);
625
+ switch (variant) {
626
+ case "spark": {
627
+ const pCount = count ?? 20;
628
+ const pDur = duration ?? 750;
629
+ const pSize = size ?? 1.5;
630
+ const decay = 1 / (pDur / 16);
631
+ for (let i = 0; i < pCount; i++) {
632
+ const angle = Math.random() * Math.PI * 2;
633
+ const speed = 2 + Math.random() * 5;
634
+ list.push({
635
+ id: `${pid}-${i}`,
636
+ type: "spark",
637
+ x,
638
+ y,
639
+ originX: x,
640
+ originY: y,
641
+ vx: Math.cos(angle) * speed,
642
+ vy: Math.sin(angle) * speed,
643
+ size: pSize,
644
+ life: 1,
645
+ decay,
646
+ color: computedColor
647
+ });
648
+ }
649
+ break;
650
+ }
651
+ case "ripple": {
652
+ const rCount = count ?? 3;
653
+ const rDur = duration ?? 800;
654
+ const maxRadius = size ?? 40;
655
+ const decay = 1 / (rDur / 16);
656
+ for (let i = 0; i < rCount; i++) {
657
+ const delayOffset = i * 6;
658
+ list.push({
659
+ id: `${pid}-${i}`,
660
+ type: "ripple",
661
+ x,
662
+ y,
663
+ originX: x,
664
+ originY: y,
665
+ vx: maxRadius / (rDur / 16),
666
+ vy: Math.max(.5, 2 - i * .5),
667
+ size: 0,
668
+ life: 1,
669
+ decay,
670
+ color: computedColor,
671
+ timer: delayOffset
672
+ });
673
+ }
674
+ break;
675
+ }
676
+ case "embers": {
677
+ const eCount = count ?? 25;
678
+ const eDur = duration ?? 1200;
679
+ const pSize = size ?? 2;
680
+ const decay = 1 / (eDur / 16);
681
+ for (let i = 0; i < eCount; i++) {
682
+ const vx = (Math.random() - .5) * 1.5;
683
+ const vy = -1 - Math.random() * 2;
684
+ list.push({
685
+ id: `${pid}-${i}`,
686
+ type: "embers",
687
+ x,
688
+ y,
689
+ originX: x,
690
+ originY: y,
691
+ vx,
692
+ vy,
693
+ size: pSize + Math.random() * 1.5,
694
+ life: 1,
695
+ decay,
696
+ color: computedColor,
697
+ wobble: Math.random() * Math.PI,
698
+ wobbleSpeed: .05 + Math.random() * .05
699
+ });
700
+ }
701
+ break;
702
+ }
703
+ case "quantum": {
704
+ const qCount = count ?? 10;
705
+ const qDur = duration ?? 1200;
706
+ const qSize = size ?? 4;
707
+ const decay = 1 / (qDur / 16);
708
+ for (let i = 0; i < qCount; i++) {
709
+ const spread = 60;
710
+ const initialX = x + (Math.random() - .5) * spread;
711
+ const initialY = y + (Math.random() - .5) * spread;
712
+ list.push({
713
+ id: `${pid}-${i}`,
714
+ type: "quantum",
715
+ x: initialX,
716
+ y: initialY,
717
+ originX: x,
718
+ originY: y,
719
+ vx: spread,
720
+ vy: 0,
721
+ size: qSize,
722
+ life: 1,
723
+ decay,
724
+ color: computedColor,
725
+ timer: Math.random() * 8,
726
+ teleportTimer: 10
727
+ });
728
+ }
729
+ break;
730
+ }
731
+ case "tesseract": {
732
+ const tDur = duration ?? 1500;
733
+ const limitSize = size ?? 30;
734
+ const decay = 1 / (tDur / 16);
735
+ list.push({
736
+ id: `${pid}-0`,
737
+ type: "tesseract",
738
+ x,
739
+ y,
740
+ originX: x,
741
+ originY: y,
742
+ vx: limitSize,
743
+ vy: limitSize / (tDur / 32),
744
+ size: 5,
745
+ life: 1,
746
+ decay,
747
+ color: computedColor,
748
+ rotX: Math.random() * Math.PI,
749
+ rotY: Math.random() * Math.PI,
750
+ rotSpeedX: .015,
751
+ rotSpeedY: .02
752
+ });
753
+ break;
754
+ }
755
+ case "blackhole": {
756
+ const bhCount = count ?? 40;
757
+ const bhDur = duration ?? 1e3;
758
+ const bhSize = size ?? 2;
759
+ const decay = 1 / (bhDur / 16);
760
+ const baseDist = size ? size * 25 : 50;
761
+ for (let i = 0; i < bhCount; i++) list.push({
762
+ id: `${pid}-${i}`,
763
+ type: "blackhole",
764
+ x,
765
+ y,
766
+ originX: x,
767
+ originY: y,
768
+ vx: 0,
769
+ vy: 0,
770
+ size: bhSize,
771
+ life: 1,
772
+ decay,
773
+ color: computedColor,
774
+ angle: Math.random() * Math.PI * 2,
775
+ dist: baseDist * (.6 + Math.random() * .8),
776
+ accretion: .93
777
+ });
778
+ break;
779
+ }
780
+ case "firework": {
781
+ const fwCount = count ?? 35;
782
+ const fwDur = duration ?? 1e3;
783
+ const fwSpeed = size ? size / 2 : 6;
784
+ const decay = 1 / (fwDur / 16);
785
+ for (let i = 0; i < fwCount; i++) {
786
+ const angle = Math.random() * Math.PI * 2;
787
+ const s = 2 + Math.random() * fwSpeed;
788
+ list.push({
789
+ id: `${pid}-${i}`,
790
+ type: "firework",
791
+ x,
792
+ y,
793
+ originX: x,
794
+ originY: y,
795
+ vx: Math.cos(angle) * s,
796
+ vy: Math.sin(angle) * s,
797
+ size: 1.5,
798
+ life: 1,
799
+ decay,
800
+ color: computedColor,
801
+ gravity: .08,
802
+ friction: .96
803
+ });
804
+ }
805
+ break;
806
+ }
807
+ case "shatter": {
808
+ const shCount = count ?? 12;
809
+ const shDur = duration ?? 700;
810
+ const spreadRadius = size ? size * 8 : 80;
811
+ const decay = 1 / (shDur / 16);
812
+ for (let i = 0; i < shCount; i++) list.push({
813
+ id: `${pid}-${i}`,
814
+ type: "shatter",
815
+ x,
816
+ y,
817
+ originX: x,
818
+ originY: y,
819
+ vx: 0,
820
+ vy: 0,
821
+ size: 6 * (.5 + Math.random() * .8),
822
+ life: 1,
823
+ decay,
824
+ color: computedColor,
825
+ angle: Math.random() * Math.PI * 2,
826
+ dist: spreadRadius * (.4 + Math.random() * .6),
827
+ initialRotation: Math.random() * Math.PI * 2,
828
+ rotationSpeed: (Math.random() - .5) * 2,
829
+ gravity: .6
830
+ });
831
+ break;
832
+ }
833
+ case "warp": {
834
+ const wpCount = count ?? 30;
835
+ const decay = 1 / ((duration ?? 1e3) / 16);
836
+ const baseSpeed = 1;
837
+ for (let i = 0; i < wpCount; i++) list.push({
838
+ id: `${pid}-${i}`,
839
+ type: "warp",
840
+ x,
841
+ y,
842
+ originX: x,
843
+ originY: y,
844
+ vx: baseSpeed + Math.random() * baseSpeed,
845
+ vy: 0,
846
+ size: size ?? 4,
847
+ life: 1,
848
+ decay,
849
+ color: computedColor,
850
+ angle: Math.random() * Math.PI * 2,
851
+ dist: 5,
852
+ accel: 1.1 + Math.random() * .1
853
+ });
854
+ break;
855
+ }
856
+ case "matrix": {
857
+ const mxCount = count ?? 10;
858
+ const mxDur = duration ?? 1200;
859
+ const spreadRadius = size ? size * 10 : 120;
860
+ const decay = 1 / (mxDur / 16);
861
+ const fallSpeed = 3;
862
+ for (let i = 0; i < mxCount; i++) list.push({
863
+ id: `${pid}-${i}`,
864
+ type: "matrix",
865
+ x: x + (Math.random() - .5) * spreadRadius,
866
+ y: y - Math.random() * 50,
867
+ originX: x,
868
+ originY: y,
869
+ vx: 0,
870
+ vy: fallSpeed + Math.random() * (fallSpeed * .7),
871
+ size: 14,
872
+ life: 1,
873
+ decay,
874
+ color: computedColor,
875
+ trailLength: 8
876
+ });
877
+ break;
878
+ }
879
+ case "smoke": {
880
+ const smCount = count ?? 8;
881
+ const smDur = duration ?? 2500;
882
+ const spreadX = size ? size : 10;
883
+ const decay = 1 / (smDur / 16);
884
+ const driftSpeed = 1;
885
+ const minRiseSpeed = .5;
886
+ for (let i = 0; i < smCount; i++) list.push({
887
+ id: `${pid}-${i}`,
888
+ type: "smoke",
889
+ x: x + (Math.random() - .5) * spreadX,
890
+ y,
891
+ originX: x,
892
+ originY: y,
893
+ vx: (Math.random() - .5) * driftSpeed,
894
+ vy: -(minRiseSpeed + Math.random() * 1),
895
+ size: 5 + Math.random() * 10,
896
+ life: 1,
897
+ decay,
898
+ color: computedColor,
899
+ speed: .3,
900
+ opacity: .15
901
+ });
902
+ break;
903
+ }
904
+ case "supernova": {
905
+ const snDur = duration ?? 1e3;
906
+ const snDotCount = count ?? 30;
907
+ const dotSize = size ?? 1.5;
908
+ const ringSpeed = size ? size / 10 : 4;
909
+ const decay = 1 / (snDur / 16);
910
+ list.push({
911
+ id: `${pid}-ring`,
912
+ type: "supernova",
913
+ x,
914
+ y,
915
+ originX: x,
916
+ originY: y,
917
+ vx: ringSpeed,
918
+ vy: 0,
919
+ size: 0,
920
+ life: 1,
921
+ decay,
922
+ color: computedColor,
923
+ subType: "ring"
924
+ });
925
+ for (let i = 0; i < snDotCount; i++) {
926
+ const angle = Math.random() * Math.PI * 2;
927
+ const s = 2 + Math.random() * 6;
928
+ list.push({
929
+ id: `${pid}-dot-${i}`,
930
+ type: "supernova",
931
+ x,
932
+ y,
933
+ originX: x,
934
+ originY: y,
935
+ vx: Math.cos(angle) * s,
936
+ vy: Math.sin(angle) * s,
937
+ size: dotSize,
938
+ life: 1,
939
+ decay,
940
+ color: computedColor,
941
+ subType: "dot",
942
+ friction: .95
943
+ });
944
+ }
945
+ break;
946
+ }
947
+ case "holosphere": {
948
+ const hsDur = duration ?? 2e3;
949
+ const hsCount = count ?? 40;
950
+ const maxSize = size ? size * 4 : 40;
951
+ const growSpeed = 2;
952
+ const decay = 1 / (hsDur / 16);
953
+ const pts = Array.from({ length: hsCount }, () => {
954
+ const theta = Math.random() * Math.PI * 2;
955
+ const phi = Math.acos(2 * Math.random() - 1);
956
+ return [
957
+ Math.cos(theta) * Math.sin(phi),
958
+ Math.cos(phi),
959
+ Math.sin(theta) * Math.sin(phi)
960
+ ];
961
+ });
962
+ list.push({
963
+ id: `${pid}-0`,
964
+ type: "holosphere",
965
+ x,
966
+ y,
967
+ originX: x,
968
+ originY: y,
969
+ vx: maxSize,
970
+ vy: growSpeed,
971
+ size: 0,
972
+ life: 1,
973
+ decay,
974
+ color: computedColor,
975
+ pts,
976
+ rotX: 0,
977
+ rotY: 0,
978
+ rotSpeedX: .02,
979
+ rotSpeedY: .03
980
+ });
981
+ break;
982
+ }
983
+ case "flowfield": {
984
+ const ffDur = duration ?? 2e3;
985
+ const ffCount = count ?? 40;
986
+ const decay = 1 / (ffDur / 16);
987
+ const initialSpeed = 4;
988
+ const fieldStrength = .2;
989
+ const fieldScale = .05;
990
+ const dotRadius = size ?? 1.5;
991
+ for (let i = 0; i < ffCount; i++) list.push({
992
+ id: `${pid}-${i}`,
993
+ type: "flowfield",
994
+ x,
995
+ y,
996
+ originX: x,
997
+ originY: y,
998
+ vx: (Math.random() - .5) * initialSpeed,
999
+ vy: (Math.random() - .5) * initialSpeed,
1000
+ size: dotRadius,
1001
+ life: 1,
1002
+ decay,
1003
+ color: computedColor,
1004
+ fieldScale,
1005
+ fieldStrength
1006
+ });
1007
+ break;
1008
+ }
1009
+ case "synapse": {
1010
+ const syDur = duration ?? 1500;
1011
+ const syCount = count ?? 10;
1012
+ const decay = 1 / (syDur / 16);
1013
+ const burstSpeed = 8;
1014
+ const friction = .88;
1015
+ const connectionDist = size ? size * 7 : 70;
1016
+ for (let i = 0; i < syCount; i++) list.push({
1017
+ id: `${pid}-${i}`,
1018
+ type: "synapse",
1019
+ x,
1020
+ y,
1021
+ originX: x,
1022
+ originY: y,
1023
+ vx: (Math.random() - .5) * burstSpeed,
1024
+ vy: (Math.random() - .5) * burstSpeed,
1025
+ size: 2,
1026
+ life: 1,
1027
+ decay,
1028
+ color: computedColor,
1029
+ friction,
1030
+ dist: connectionDist,
1031
+ groupId: pid
1032
+ });
1033
+ break;
1034
+ }
1035
+ case "diffusion": {
1036
+ const dfDur = duration ?? 1e3;
1037
+ const dfCount = count ?? 30;
1038
+ const radius = size ? size * 2.5 : 25;
1039
+ const decay = 1 / (dfDur / 16);
1040
+ for (let i = 0; i < dfCount; i++) {
1041
+ const angle = i / dfCount * Math.PI * 2;
1042
+ list.push({
1043
+ id: `${pid}-${i}`,
1044
+ type: "diffusion",
1045
+ x: x + (Math.random() - .5) * 100,
1046
+ y: y + (Math.random() - .5) * 100,
1047
+ originX: x,
1048
+ originY: y,
1049
+ vx: x + Math.cos(angle) * radius,
1050
+ vy: y + Math.sin(angle) * radius,
1051
+ size: 1.5,
1052
+ life: 1,
1053
+ decay,
1054
+ color: computedColor
1055
+ });
1056
+ }
1057
+ break;
1058
+ }
1059
+ case "rain": {
1060
+ const rnDur = duration ?? 2e3;
1061
+ const rnCount = count ?? 15;
1062
+ const decay = 1 / (rnDur / 16);
1063
+ const fallSpeed = 5;
1064
+ const maxExtraSpeed = 3;
1065
+ const spreadX = size ? size * 12 : 120;
1066
+ for (let i = 0; i < rnCount; i++) list.push({
1067
+ id: `${pid}-${i}`,
1068
+ type: "rain",
1069
+ x: x + (Math.random() - .5) * spreadX,
1070
+ y: y - 80 - Math.random() * 50,
1071
+ originX: x,
1072
+ originY: y,
1073
+ vx: 0,
1074
+ vy: fallSpeed + Math.random() * maxExtraSpeed,
1075
+ size: 0,
1076
+ life: 1,
1077
+ decay,
1078
+ color: computedColor,
1079
+ targetY: y + (Math.random() - .5) * 40,
1080
+ hit: false
1081
+ });
1082
+ break;
1083
+ }
1084
+ case "binary": {
1085
+ const biDur = duration ?? 1e3;
1086
+ const biCount = count ?? 10;
1087
+ const spreadRadius = size ? size * 6 : 60;
1088
+ const decay = 1 / (biDur / 16);
1089
+ const chars = ["0", "1"];
1090
+ for (let i = 0; i < biCount; i++) list.push({
1091
+ id: `${pid}-${i}`,
1092
+ type: "binary",
1093
+ x,
1094
+ y,
1095
+ originX: x,
1096
+ originY: y,
1097
+ vx: 0,
1098
+ vy: 0,
1099
+ size: size ?? 12,
1100
+ life: 1,
1101
+ decay,
1102
+ color: computedColor,
1103
+ char: chars[Math.floor(Math.random() * chars.length)],
1104
+ angle: Math.random() * Math.PI * 2,
1105
+ dist: spreadRadius * (.4 + Math.random() * .6)
1106
+ });
1107
+ break;
1108
+ }
1109
+ case "fission": {
1110
+ const decay = 1 / ((duration ?? 1500) / 16);
1111
+ const radius = size ?? 4;
1112
+ list.push({
1113
+ id: `${pid}-0`,
1114
+ type: "fission",
1115
+ x,
1116
+ y,
1117
+ originX: x,
1118
+ originY: y,
1119
+ vx: 0,
1120
+ vy: 0,
1121
+ size: radius,
1122
+ life: 1,
1123
+ decay,
1124
+ color: computedColor
1125
+ });
1126
+ break;
1127
+ }
1128
+ case "bullettime": {
1129
+ const btDur = duration ?? 1e3;
1130
+ const btCount = count ?? 15;
1131
+ const decay = 1 / (btDur / 16);
1132
+ const speedMin = 8;
1133
+ const friction = .92;
1134
+ const maxRadius = size ? size * 8 : 80;
1135
+ for (let i = 0; i < btCount; i++) {
1136
+ const angle = Math.random() * Math.PI * 2;
1137
+ const speed = speedMin + Math.random() * 6;
1138
+ list.push({
1139
+ id: `${pid}-${i}`,
1140
+ type: "bullettime",
1141
+ x,
1142
+ y,
1143
+ originX: x,
1144
+ originY: y,
1145
+ vx: Math.cos(angle) * speed,
1146
+ vy: Math.sin(angle) * speed,
1147
+ size: 1.5 + Math.random() * 1.5,
1148
+ life: 1,
1149
+ decay,
1150
+ color: computedColor,
1151
+ friction,
1152
+ dist: maxRadius,
1153
+ angle
1154
+ });
1155
+ }
1156
+ break;
1157
+ }
1158
+ }
1159
+ if (list.length > 0) manager.addParticles(list);
1160
+ }, [
1161
+ manager,
1162
+ variant,
1163
+ count,
1164
+ size,
1165
+ duration,
1166
+ color,
1167
+ colorFrom
1168
+ ]);
1169
+ const triggerHandlers = { [trigger === "mousedown" ? "onMouseDown" : "onClick"]: handleTrigger };
1170
+ return /* @__PURE__ */ jsx("div", {
1171
+ ref: containerRef,
1172
+ style: {
1173
+ display: "contents",
1174
+ ...style
1175
+ },
1176
+ className: cn(className),
1177
+ "data-slot": "kinetic-click",
1178
+ ...triggerHandlers,
1179
+ ...props,
1180
+ children
1181
+ });
1182
+ });
1183
+ //#endregion
1184
+ export { KineticClick };