bits-lab 0.0.0-stage → 0.1.2

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 (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -2
  3. package/dist/Accordion.d.ts +52 -0
  4. package/dist/Accordion.js +192 -0
  5. package/dist/AchievementToast.d.ts +36 -0
  6. package/dist/AchievementToast.js +162 -0
  7. package/dist/AgentCard.d.ts +41 -0
  8. package/dist/AgentCard.js +168 -0
  9. package/dist/ArcadeButtons.d.ts +23 -0
  10. package/dist/ArcadeButtons.js +169 -0
  11. package/dist/AuroraBands.d.ts +19 -0
  12. package/dist/AuroraBands.js +126 -0
  13. package/dist/AvatarTooltips.d.ts +32 -0
  14. package/dist/AvatarTooltips.js +121 -0
  15. package/dist/BarRace.d.ts +39 -0
  16. package/dist/BarRace.js +227 -0
  17. package/dist/BentoGrid.d.ts +50 -0
  18. package/dist/BentoGrid.js +145 -0
  19. package/dist/BootSequence.d.ts +48 -0
  20. package/dist/BootSequence.js +234 -0
  21. package/dist/BreadcrumbTrail.d.ts +31 -0
  22. package/dist/BreadcrumbTrail.js +181 -0
  23. package/dist/CRTPower.d.ts +30 -0
  24. package/dist/CRTPower.js +142 -0
  25. package/dist/CardDeck.d.ts +29 -0
  26. package/dist/CardDeck.js +154 -0
  27. package/dist/ChangelogTimeline.d.ts +35 -0
  28. package/dist/ChangelogTimeline.js +137 -0
  29. package/dist/ChapterProgress.d.ts +23 -0
  30. package/dist/ChapterProgress.js +211 -0
  31. package/dist/ChatBubbles.d.ts +42 -0
  32. package/dist/ChatBubbles.js +198 -0
  33. package/dist/ChiptuneKit.d.ts +158 -0
  34. package/dist/ChiptuneKit.js +207 -0
  35. package/dist/CipherCard.d.ts +22 -0
  36. package/dist/CipherCard.js +91 -0
  37. package/dist/CloudSky.d.ts +28 -0
  38. package/dist/CloudSky.js +222 -0
  39. package/dist/CodeRain.d.ts +24 -0
  40. package/dist/CodeRain.js +158 -0
  41. package/dist/CodeShowcase.d.ts +50 -0
  42. package/dist/CodeShowcase.js +307 -0
  43. package/dist/ColorDial.d.ts +42 -0
  44. package/dist/ColorDial.js +288 -0
  45. package/dist/CommandPalette.d.ts +59 -0
  46. package/dist/CommandPalette.js +349 -0
  47. package/dist/CompareSlider.d.ts +33 -0
  48. package/dist/CompareSlider.js +152 -0
  49. package/dist/Confetti.d.ts +61 -0
  50. package/dist/Confetti.js +176 -0
  51. package/dist/ConnectBeams.d.ts +39 -0
  52. package/dist/ConnectBeams.js +132 -0
  53. package/dist/ContextOrb.d.ts +34 -0
  54. package/dist/ContextOrb.js +269 -0
  55. package/dist/ContourLines.d.ts +20 -0
  56. package/dist/ContourLines.js +159 -0
  57. package/dist/Coverflow.d.ts +27 -0
  58. package/dist/Coverflow.js +167 -0
  59. package/dist/CursorAttractor.d.ts +21 -0
  60. package/dist/CursorAttractor.js +136 -0
  61. package/dist/CutReveal.d.ts +21 -0
  62. package/dist/CutReveal.js +116 -0
  63. package/dist/DateRange.d.ts +45 -0
  64. package/dist/DateRange.js +327 -0
  65. package/dist/DeviceFrame.d.ts +30 -0
  66. package/dist/DeviceFrame.js +145 -0
  67. package/dist/DiffReveal.d.ts +36 -0
  68. package/dist/DiffReveal.js +247 -0
  69. package/dist/DirectionHover.d.ts +15 -0
  70. package/dist/DirectionHover.js +90 -0
  71. package/dist/Discard.d.ts +18 -0
  72. package/dist/Discard.js +61 -0
  73. package/dist/DitherField.d.ts +15 -0
  74. package/dist/DitherField.js +157 -0
  75. package/dist/DotGlobe.d.ts +48 -0
  76. package/dist/DotGlobe.js +312 -0
  77. package/dist/DotMap.d.ts +47 -0
  78. package/dist/DotMap.js +172 -0
  79. package/dist/DropZone.d.ts +57 -0
  80. package/dist/DropZone.js +304 -0
  81. package/dist/DynamicIsland.d.ts +32 -0
  82. package/dist/DynamicIsland.js +92 -0
  83. package/dist/EdgeFX.d.ts +27 -0
  84. package/dist/EdgeFX.js +98 -0
  85. package/dist/ElasticString.d.ts +22 -0
  86. package/dist/ElasticString.js +127 -0
  87. package/dist/ExpandCard.d.ts +44 -0
  88. package/dist/ExpandCard.js +182 -0
  89. package/dist/FeatureTabs.d.ts +34 -0
  90. package/dist/FeatureTabs.js +169 -0
  91. package/dist/FeedList.d.ts +37 -0
  92. package/dist/FeedList.js +163 -0
  93. package/dist/FlickerGrid.d.ts +29 -0
  94. package/dist/FlickerGrid.js +156 -0
  95. package/dist/FocusGrid.d.ts +20 -0
  96. package/dist/FocusGrid.js +48 -0
  97. package/dist/FocusPull.d.ts +26 -0
  98. package/dist/FocusPull.js +106 -0
  99. package/dist/Footprints.d.ts +24 -0
  100. package/dist/Footprints.js +126 -0
  101. package/dist/FunnelFlow.d.ts +34 -0
  102. package/dist/FunnelFlow.js +267 -0
  103. package/dist/GameOver.d.ts +46 -0
  104. package/dist/GameOver.js +191 -0
  105. package/dist/GaugeMeter.d.ts +38 -0
  106. package/dist/GaugeMeter.js +195 -0
  107. package/dist/GlassPanel.d.ts +27 -0
  108. package/dist/GlassPanel.js +80 -0
  109. package/dist/GrainFX.d.ts +34 -0
  110. package/dist/GrainFX.js +122 -0
  111. package/dist/GravityBox.d.ts +30 -0
  112. package/dist/GravityBox.js +220 -0
  113. package/dist/HealthBar.d.ts +33 -0
  114. package/dist/HealthBar.js +140 -0
  115. package/dist/Heatmap.d.ts +42 -0
  116. package/dist/Heatmap.js +232 -0
  117. package/dist/HexField.d.ts +29 -0
  118. package/dist/HexField.js +188 -0
  119. package/dist/HoldToConfirm.d.ts +29 -0
  120. package/dist/HoldToConfirm.js +163 -0
  121. package/dist/HorizontalTrack.d.ts +28 -0
  122. package/dist/HorizontalTrack.js +195 -0
  123. package/dist/HotbarDock.d.ts +40 -0
  124. package/dist/HotbarDock.js +148 -0
  125. package/dist/InkText.d.ts +27 -0
  126. package/dist/InkText.js +65 -0
  127. package/dist/InlineEdit.d.ts +30 -0
  128. package/dist/InlineEdit.js +198 -0
  129. package/dist/InteractiveGrid.d.ts +25 -0
  130. package/dist/InteractiveGrid.js +194 -0
  131. package/dist/InventoryGrid.d.ts +45 -0
  132. package/dist/InventoryGrid.js +272 -0
  133. package/dist/JellyBlob.d.ts +30 -0
  134. package/dist/JellyBlob.js +209 -0
  135. package/dist/KineticHeadline.d.ts +30 -0
  136. package/dist/KineticHeadline.js +133 -0
  137. package/dist/LavaLamp.d.ts +21 -0
  138. package/dist/LavaLamp.js +133 -0
  139. package/dist/LetterSwap.d.ts +20 -0
  140. package/dist/LetterSwap.js +78 -0
  141. package/dist/LevelMap.d.ts +35 -0
  142. package/dist/LevelMap.js +189 -0
  143. package/dist/LightShafts.d.ts +22 -0
  144. package/dist/LightShafts.js +170 -0
  145. package/dist/LightboxGallery.d.ts +26 -0
  146. package/dist/LightboxGallery.js +327 -0
  147. package/dist/LinkPeek.d.ts +36 -0
  148. package/dist/LinkPeek.js +194 -0
  149. package/dist/LogoOrbit.d.ts +37 -0
  150. package/dist/LogoOrbit.js +117 -0
  151. package/dist/Marquee.d.ts +33 -0
  152. package/dist/Marquee.js +148 -0
  153. package/dist/MarqueeLine.d.ts +33 -0
  154. package/dist/MarqueeLine.js +167 -0
  155. package/dist/MasonryWall.d.ts +13 -0
  156. package/dist/MasonryWall.js +90 -0
  157. package/dist/MegaMenu.d.ts +32 -0
  158. package/dist/MegaMenu.js +280 -0
  159. package/dist/MeteorShower.d.ts +24 -0
  160. package/dist/MeteorShower.js +155 -0
  161. package/dist/Minimap.d.ts +21 -0
  162. package/dist/Minimap.js +236 -0
  163. package/dist/MobileTabBar.d.ts +38 -0
  164. package/dist/MobileTabBar.js +148 -0
  165. package/dist/MorphDialog.d.ts +34 -0
  166. package/dist/MorphDialog.js +199 -0
  167. package/dist/MorphPopover.d.ts +33 -0
  168. package/dist/MorphPopover.js +168 -0
  169. package/dist/MorphWords.d.ts +18 -0
  170. package/dist/MorphWords.js +136 -0
  171. package/dist/OTPInput.d.ts +43 -0
  172. package/dist/OTPInput.js +174 -0
  173. package/dist/OverlayKit.d.ts +97 -0
  174. package/dist/OverlayKit.js +466 -0
  175. package/dist/OverlayMenu.d.ts +32 -0
  176. package/dist/OverlayMenu.js +154 -0
  177. package/dist/ParallaxCollage.d.ts +41 -0
  178. package/dist/ParallaxCollage.js +143 -0
  179. package/dist/PasswordMeter.d.ts +44 -0
  180. package/dist/PasswordMeter.js +165 -0
  181. package/dist/PegBoard.d.ts +26 -0
  182. package/dist/PegBoard.js +184 -0
  183. package/dist/PinCard.d.ts +21 -0
  184. package/dist/PinCard.js +84 -0
  185. package/dist/PixelAvatar.d.ts +33 -0
  186. package/dist/PixelAvatar.js +144 -0
  187. package/dist/PixelButton.d.ts +20 -0
  188. package/dist/PixelButton.js +128 -0
  189. package/dist/PixelExplode.d.ts +31 -0
  190. package/dist/PixelExplode.js +164 -0
  191. package/dist/PixelLoader.d.ts +32 -0
  192. package/dist/PixelLoader.js +142 -0
  193. package/dist/PixelParallax.d.ts +41 -0
  194. package/dist/PixelParallax.js +151 -0
  195. package/dist/PixelSpinners.d.ts +21 -0
  196. package/dist/PixelSpinners.js +110 -0
  197. package/dist/PixelType.d.ts +26 -0
  198. package/dist/PixelType.js +220 -0
  199. package/dist/PointerKit.d.ts +23 -0
  200. package/dist/PointerKit.js +222 -0
  201. package/dist/Polaroids.d.ts +41 -0
  202. package/dist/Polaroids.js +293 -0
  203. package/dist/PressStart.d.ts +28 -0
  204. package/dist/PressStart.js +99 -0
  205. package/dist/PricingFlip.d.ts +52 -0
  206. package/dist/PricingFlip.js +190 -0
  207. package/dist/ProximityType.d.ts +26 -0
  208. package/dist/ProximityType.js +135 -0
  209. package/dist/QuestDialog.d.ts +50 -0
  210. package/dist/QuestDialog.js +204 -0
  211. package/dist/QuestLog.d.ts +39 -0
  212. package/dist/QuestLog.js +214 -0
  213. package/dist/RangeDual.d.ts +34 -0
  214. package/dist/RangeDual.js +238 -0
  215. package/dist/RatingPips.d.ts +25 -0
  216. package/dist/RatingPips.js +129 -0
  217. package/dist/RetroHorizon.d.ts +27 -0
  218. package/dist/RetroHorizon.js +169 -0
  219. package/dist/Reveal.d.ts +30 -0
  220. package/dist/Reveal.js +92 -0
  221. package/dist/RingProgress.d.ts +45 -0
  222. package/dist/RingProgress.js +180 -0
  223. package/dist/RollingNumber.d.ts +28 -0
  224. package/dist/RollingNumber.js +108 -0
  225. package/dist/ScanScope.d.ts +24 -0
  226. package/dist/ScanScope.js +164 -0
  227. package/dist/ScoreTicker.d.ts +32 -0
  228. package/dist/ScoreTicker.js +176 -0
  229. package/dist/ScreenScroller.d.ts +24 -0
  230. package/dist/ScreenScroller.js +138 -0
  231. package/dist/Screensaver.d.ts +31 -0
  232. package/dist/Screensaver.js +221 -0
  233. package/dist/ScrollTilt.d.ts +27 -0
  234. package/dist/ScrollTilt.js +100 -0
  235. package/dist/ScrollTypography.d.ts +26 -0
  236. package/dist/ScrollTypography.js +124 -0
  237. package/dist/ScrollZoom.d.ts +31 -0
  238. package/dist/ScrollZoom.js +123 -0
  239. package/dist/ScrubNumber.d.ts +29 -0
  240. package/dist/ScrubNumber.js +152 -0
  241. package/dist/ShadowStack.d.ts +28 -0
  242. package/dist/ShadowStack.js +116 -0
  243. package/dist/SideRail.d.ts +43 -0
  244. package/dist/SideRail.js +253 -0
  245. package/dist/SignalText.d.ts +25 -0
  246. package/dist/SignalText.js +178 -0
  247. package/dist/SkeletonShimmer.d.ts +18 -0
  248. package/dist/SkeletonShimmer.js +111 -0
  249. package/dist/SketchHighlight.d.ts +27 -0
  250. package/dist/SketchHighlight.js +180 -0
  251. package/dist/SlideTabs.d.ts +40 -0
  252. package/dist/SlideTabs.js +190 -0
  253. package/dist/SmartNavbar.d.ts +48 -0
  254. package/dist/SmartNavbar.js +188 -0
  255. package/dist/SparkChart.d.ts +41 -0
  256. package/dist/SparkChart.js +188 -0
  257. package/dist/Spoiler.d.ts +22 -0
  258. package/dist/Spoiler.js +97 -0
  259. package/dist/SpotlightTour.d.ts +38 -0
  260. package/dist/SpotlightTour.js +231 -0
  261. package/dist/SpringDrawer.d.ts +39 -0
  262. package/dist/SpringDrawer.js +360 -0
  263. package/dist/SpriteAnimator.d.ts +41 -0
  264. package/dist/SpriteAnimator.js +124 -0
  265. package/dist/StatCard.d.ts +43 -0
  266. package/dist/StatCard.js +168 -0
  267. package/dist/StepLoader.d.ts +41 -0
  268. package/dist/StepLoader.js +191 -0
  269. package/dist/StepperForm.d.ts +41 -0
  270. package/dist/StepperForm.js +206 -0
  271. package/dist/StickerBoard.d.ts +39 -0
  272. package/dist/StickerBoard.js +209 -0
  273. package/dist/StickyReveal.d.ts +42 -0
  274. package/dist/StickyReveal.js +181 -0
  275. package/dist/StoryViewer.d.ts +36 -0
  276. package/dist/StoryViewer.js +175 -0
  277. package/dist/StreamingText.d.ts +29 -0
  278. package/dist/StreamingText.js +271 -0
  279. package/dist/SuggestionChips.d.ts +32 -0
  280. package/dist/SuggestionChips.js +96 -0
  281. package/dist/SwipeActions.d.ts +30 -0
  282. package/dist/SwipeActions.js +141 -0
  283. package/dist/TagInput.d.ts +30 -0
  284. package/dist/TagInput.js +284 -0
  285. package/dist/TallyUp.d.ts +38 -0
  286. package/dist/TallyUp.js +157 -0
  287. package/dist/TerminalDemo.d.ts +63 -0
  288. package/dist/TerminalDemo.js +214 -0
  289. package/dist/TestimonialWall.d.ts +35 -0
  290. package/dist/TestimonialWall.js +131 -0
  291. package/dist/TextOnPath.d.ts +36 -0
  292. package/dist/TextOnPath.js +130 -0
  293. package/dist/ThinkingShimmer.d.ts +36 -0
  294. package/dist/ThinkingShimmer.js +132 -0
  295. package/dist/ToastStack.d.ts +62 -0
  296. package/dist/ToastStack.js +289 -0
  297. package/dist/ToggleGroup.d.ts +39 -0
  298. package/dist/ToggleGroup.js +190 -0
  299. package/dist/ToggleKit.d.ts +70 -0
  300. package/dist/ToggleKit.js +229 -0
  301. package/dist/TracingLine.d.ts +24 -0
  302. package/dist/TracingLine.js +139 -0
  303. package/dist/TradingCard.d.ts +30 -0
  304. package/dist/TradingCard.js +147 -0
  305. package/dist/VanishInput.d.ts +34 -0
  306. package/dist/VanishInput.js +190 -0
  307. package/dist/VideoHero.d.ts +32 -0
  308. package/dist/VideoHero.js +207 -0
  309. package/dist/VoiceOrb.d.ts +23 -0
  310. package/dist/VoiceOrb.js +182 -0
  311. package/dist/VoxelTiles.d.ts +38 -0
  312. package/dist/VoxelTiles.js +201 -0
  313. package/dist/WarpField.d.ts +18 -0
  314. package/dist/WarpField.js +160 -0
  315. package/dist/WebcamPixels.d.ts +38 -0
  316. package/dist/WebcamPixels.js +292 -0
  317. package/dist/WheelPicker.d.ts +29 -0
  318. package/dist/WheelPicker.js +199 -0
  319. package/dist/WobbleCard.d.ts +23 -0
  320. package/dist/WobbleCard.js +112 -0
  321. package/dist/index.d.ts +158 -0
  322. package/dist/index.js +159 -0
  323. package/package.json +58 -4
@@ -0,0 +1,176 @@
1
+ 'use client';
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ const PRESETS = {
5
+ burst: { count: 90, spread: 70, angle: 90, velocity: 42, gravity: 1, decay: 0.92, ticks: 220 },
6
+ cannon: { count: 120, spread: 30, angle: 70, velocity: 58, gravity: 1, decay: 0.93, ticks: 260 },
7
+ fireworks: { count: 140, spread: 360, angle: 90, velocity: 34, gravity: 0.6, decay: 0.91, ticks: 200 },
8
+ fountain: { count: 70, spread: 24, angle: 90, velocity: 52, gravity: 1.1, decay: 0.94, ticks: 260 },
9
+ rain: { count: 160, spread: 0, angle: 270, velocity: 4, gravity: 0.35, decay: 0.99, ticks: 400, fromTop: true }
10
+ };
11
+ const DEFAULT_COLORS = ["#ef7d57", "#ffcd75", "#a7f070", "#38b764", "#41a6f6", "#73eff7", "#b13e53", "#f4f4f4"];
12
+ let canvas = null;
13
+ let ctx = null;
14
+ let particles = [];
15
+ const pool = [];
16
+ let frame = 0;
17
+ let dpr = 1;
18
+ const imageCache = /* @__PURE__ */ new Map();
19
+ function ensureCanvas(zIndex) {
20
+ if (canvas?.isConnected) return;
21
+ canvas = document.createElement("canvas");
22
+ canvas.setAttribute("aria-hidden", "true");
23
+ Object.assign(canvas.style, { position: "fixed", inset: "0", width: "100vw", height: "100vh", pointerEvents: "none", zIndex: String(zIndex) });
24
+ document.body.appendChild(canvas);
25
+ ctx = canvas.getContext("2d");
26
+ resize();
27
+ window.addEventListener("resize", resize);
28
+ }
29
+ function resize() {
30
+ if (!canvas) return;
31
+ dpr = Math.min(2, window.devicePixelRatio || 1);
32
+ canvas.width = Math.round(window.innerWidth * dpr);
33
+ canvas.height = Math.round(window.innerHeight * dpr);
34
+ }
35
+ function loadImage(src) {
36
+ if (typeof src !== "string") return src;
37
+ if (!imageCache.has(src)) {
38
+ const image = new Image();
39
+ image.src = src;
40
+ imageCache.set(src, image);
41
+ }
42
+ return imageCache.get(src);
43
+ }
44
+ const isImageSource = (value) => typeof value === "object" || /^(\/|\.|https?:|data:image)/.test(value);
45
+ function step() {
46
+ frame = 0;
47
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
48
+ ctx.clearRect(0, 0, canvas.width / dpr, canvas.height / dpr);
49
+ let alive = 0;
50
+ for (let i = 0; i < particles.length; i++) {
51
+ const p = particles[i];
52
+ p.tick++;
53
+ p.vx *= p.decay;
54
+ p.vy *= p.decay;
55
+ p.vy += p.gravity;
56
+ p.x += p.vx + Math.cos(p.wobble) * p.drift;
57
+ p.y += p.vy;
58
+ p.wobble += p.wobbleSpeed;
59
+ p.tilt += p.tiltSpeed;
60
+ const life = 1 - p.tick / p.ticks;
61
+ if (life <= 0 || p.y > window.innerHeight + 60) {
62
+ pool.push(p);
63
+ continue;
64
+ }
65
+ particles[alive++] = p;
66
+ ctx.save();
67
+ ctx.globalAlpha = Math.min(1, life * 2.2);
68
+ ctx.translate(p.x, p.y);
69
+ ctx.rotate(p.rotation + p.tilt);
70
+ ctx.scale(1, Math.abs(Math.cos(p.wobble)) * 0.8 + 0.2);
71
+ const s = p.size;
72
+ if (p.kind === "image") {
73
+ if (p.image.complete && p.image.naturalWidth) {
74
+ ctx.imageSmoothingEnabled = !p.pixelated;
75
+ ctx.drawImage(p.image, -s, -s, s * 2, s * 2);
76
+ }
77
+ } else if (p.kind === "text") {
78
+ ctx.font = `${s * 2}px system-ui, "Apple Color Emoji", "Segoe UI Emoji", sans-serif`;
79
+ ctx.textAlign = "center";
80
+ ctx.textBaseline = "middle";
81
+ ctx.fillText(p.text, 0, 0);
82
+ } else {
83
+ ctx.fillStyle = p.color;
84
+ if (p.kind === "circle") {
85
+ ctx.beginPath();
86
+ ctx.arc(0, 0, s * 0.6, 0, Math.PI * 2);
87
+ ctx.fill();
88
+ } else if (p.kind === "strip") ctx.fillRect(-s * 0.3, -s, s * 0.6, s * 2);
89
+ else ctx.fillRect(-s * 0.6, -s * 0.6, s * 1.2, s * 1.2);
90
+ }
91
+ ctx.restore();
92
+ }
93
+ particles.length = alive;
94
+ if (alive) frame = requestAnimationFrame(step);
95
+ else ctx.clearRect(0, 0, canvas.width, canvas.height);
96
+ }
97
+ function originPoint(origin) {
98
+ if (!origin) return { x: window.innerWidth / 2, y: window.innerHeight * 0.6 };
99
+ if (typeof Element !== "undefined" && origin instanceof Element) {
100
+ const r = origin.getBoundingClientRect();
101
+ return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
102
+ }
103
+ const x = origin.x <= 1 ? origin.x * window.innerWidth : origin.x;
104
+ const y = origin.y <= 1 ? origin.y * window.innerHeight : origin.y;
105
+ return { x, y };
106
+ }
107
+ function confetti(options = {}) {
108
+ if (typeof window === "undefined") return;
109
+ if (!options.force && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
110
+ const o = { ...PRESETS[options.preset ?? "burst"], ...options };
111
+ const { count, spread, angle, velocity, gravity, decay, ticks, colors = DEFAULT_COLORS, shapes = ["square", "strip", "circle"], size = 7, scalar = 1, zIndex = 2e3, pixelated = true } = o;
112
+ ensureCanvas(zIndex);
113
+ const from = originPoint(o.origin);
114
+ const kinds = shapes.map((shape) => shape === "square" || shape === "circle" || shape === "strip" ? { kind: shape } : isImageSource(shape) ? { kind: "image", image: loadImage(shape) } : { kind: "text", text: shape });
115
+ for (let i = 0; i < count; i++) {
116
+ const p = pool.pop() ?? {};
117
+ const kind = kinds[Math.floor(Math.random() * kinds.length)];
118
+ const a = (angle + (Math.random() - 0.5) * spread) * Math.PI / 180;
119
+ const speed = velocity * (0.5 + Math.random() * 0.5) * scalar * 0.35;
120
+ Object.assign(p, {
121
+ ...kind,
122
+ x: o.fromTop ? Math.random() * window.innerWidth : from.x,
123
+ y: o.fromTop ? -20 - Math.random() * window.innerHeight * 0.4 : from.y,
124
+ vx: Math.cos(a) * speed,
125
+ vy: -Math.sin(a) * speed,
126
+ gravity: gravity * 0.32 * scalar,
127
+ decay,
128
+ drift: (o.drift ?? 0) + (Math.random() - 0.5) * 0.6,
129
+ wobble: Math.random() * Math.PI * 2,
130
+ wobbleSpeed: 0.05 + Math.random() * 0.1,
131
+ rotation: Math.random() * Math.PI * 2,
132
+ tilt: 0,
133
+ tiltSpeed: (Math.random() - 0.5) * 0.2,
134
+ size: size * scalar * (0.7 + Math.random() * 0.6) * (kind.kind === "image" || kind.kind === "text" ? 1.6 : 1),
135
+ color: colors[Math.floor(Math.random() * colors.length)],
136
+ tick: 0,
137
+ ticks: ticks * (0.8 + Math.random() * 0.4),
138
+ pixelated
139
+ });
140
+ particles.push(p);
141
+ }
142
+ if (!frame) frame = requestAnimationFrame(step);
143
+ }
144
+ confetti.reset = () => {
145
+ cancelAnimationFrame(frame);
146
+ frame = 0;
147
+ pool.push(...particles);
148
+ particles = [];
149
+ if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height);
150
+ };
151
+ function Confetti({ children, trigger = "click", disabled = false, className = "", style, ...options }) {
152
+ const ref = useRef(null);
153
+ const optionsRef = useRef(options);
154
+ optionsRef.current = options;
155
+ useEffect(() => {
156
+ if (trigger === "mount" && !disabled) confetti({ origin: ref.current, ...optionsRef.current });
157
+ }, [trigger, disabled]);
158
+ const fire = () => {
159
+ if (!disabled) confetti({ origin: ref.current, ...optionsRef.current });
160
+ };
161
+ return /* @__PURE__ */ jsx(
162
+ "span",
163
+ {
164
+ ref,
165
+ className,
166
+ style: { display: "inline-block", ...style },
167
+ onClick: trigger === "click" ? fire : void 0,
168
+ onPointerEnter: trigger === "hover" ? fire : void 0,
169
+ children
170
+ }
171
+ );
172
+ }
173
+ export {
174
+ confetti,
175
+ Confetti as default
176
+ };
@@ -0,0 +1,39 @@
1
+ import { type CSSProperties, type RefObject } from 'react';
2
+ export interface Beam {
3
+ from: RefObject<Element | null>;
4
+ to: RefObject<Element | null>;
5
+ /** Run the pulse from `to` back to `from`. */
6
+ reverse?: boolean;
7
+ /** Overrides the shared curvature for this beam. */
8
+ curvature?: number;
9
+ /** Pulse loop length for this beam, in seconds. */
10
+ duration?: number;
11
+ /** Animation delay, in seconds (negative starts mid-loop). */
12
+ delay?: number;
13
+ /** Track color for this beam. */
14
+ color?: string;
15
+ pulseColor?: string;
16
+ pulseColorEnd?: string;
17
+ }
18
+ export interface ConnectBeamsProps {
19
+ /** Positioned parent that holds the nodes; the SVG overlay fills it. */
20
+ containerRef: RefObject<Element | null>;
21
+ beams?: Beam[];
22
+ /** Static track color. */
23
+ color?: string;
24
+ pulseColor?: string;
25
+ pulseColorEnd?: string;
26
+ /** Stroke width, in px. */
27
+ width?: number;
28
+ /** Bend perpendicular to the beam; negative bends the other way. */
29
+ curvature?: number;
30
+ /** Pulse loop length, in seconds. */
31
+ duration?: number;
32
+ /** Pulse length as a share of the beam (0–1). */
33
+ pulseLength?: number;
34
+ /** How far inside the node edge beams attach, in px. */
35
+ edgeInset?: number;
36
+ className?: string;
37
+ style?: CSSProperties;
38
+ }
39
+ export default function ConnectBeams({ containerRef, beams, color, pulseColor, pulseColorEnd, width, curvature, duration, pulseLength, edgeInset, className, style }: ConnectBeamsProps): import("react").JSX.Element;
@@ -0,0 +1,132 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useInsertionEffect, useState } from "react";
4
+ const STYLE_ID = "bl-connect-beams";
5
+ const CSS = `
6
+ .bl-beams { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 0; }
7
+ .bl-beams__pulse { animation: bl-beam-pulse var(--bl-dur) linear infinite; }
8
+ @keyframes bl-beam-pulse { from { stroke-dashoffset: var(--bl-from); } to { stroke-dashoffset: var(--bl-to); } }
9
+ @media (prefers-reduced-motion: reduce) { .bl-beams__pulse { animation: none; stroke-dasharray: none; opacity: 0.6; } }
10
+ `;
11
+ function useStyles() {
12
+ useInsertionEffect(() => {
13
+ if (typeof document === "undefined") return;
14
+ const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
15
+ style.textContent = CSS;
16
+ if (!style.isConnected) document.head.appendChild(style);
17
+ }, []);
18
+ }
19
+ function edgePoint(rect, toward, inset) {
20
+ const cx = rect.x + rect.width / 2;
21
+ const cy = rect.y + rect.height / 2;
22
+ const dx = toward[0] - cx;
23
+ const dy = toward[1] - cy;
24
+ if (!dx && !dy) return [cx, cy];
25
+ const sx = Math.abs(dx) ? (rect.width / 2 - inset) / Math.abs(dx) : Infinity;
26
+ const sy = Math.abs(dy) ? (rect.height / 2 - inset) / Math.abs(dy) : Infinity;
27
+ const s = Math.min(sx, sy);
28
+ return [cx + dx * s, cy + dy * s];
29
+ }
30
+ function ConnectBeams({
31
+ containerRef,
32
+ beams = [],
33
+ color = "#3b5dc9",
34
+ pulseColor = "#73eff7",
35
+ pulseColorEnd = "#a7f070",
36
+ width = 2,
37
+ curvature = 0.25,
38
+ duration = 3,
39
+ pulseLength = 0.22,
40
+ edgeInset = 4,
41
+ className = "",
42
+ style
43
+ }) {
44
+ useStyles();
45
+ const uid = useId().replace(/[^a-zA-Z0-9_-]/g, "");
46
+ const [paths, setPaths] = useState([]);
47
+ const [box, setBox] = useState({ width: 0, height: 0 });
48
+ useEffect(() => {
49
+ const container = containerRef?.current;
50
+ if (!container) return;
51
+ let frame = 0;
52
+ const measure = () => {
53
+ frame = 0;
54
+ const base = container.getBoundingClientRect();
55
+ setBox((prev) => prev.width === base.width && prev.height === base.height ? prev : { width: base.width, height: base.height });
56
+ const next = beams.map((beam) => {
57
+ const a = beam.from?.current;
58
+ const b = beam.to?.current;
59
+ if (!a || !b) return null;
60
+ const ra = a.getBoundingClientRect();
61
+ const rb = b.getBoundingClientRect();
62
+ const local = (r) => ({ x: r.left - base.left, y: r.top - base.top, width: r.width, height: r.height });
63
+ const la = local(ra);
64
+ const lb = local(rb);
65
+ const ca = [la.x + la.width / 2, la.y + la.height / 2];
66
+ const cb = [lb.x + lb.width / 2, lb.y + lb.height / 2];
67
+ const [x1, y1] = edgePoint(la, cb, edgeInset);
68
+ const [x2, y2] = edgePoint(lb, ca, edgeInset);
69
+ const bend = beam.curvature ?? curvature;
70
+ const mx = (x1 + x2) / 2 - (y2 - y1) * bend;
71
+ const my = (y1 + y2) / 2 + (x2 - x1) * bend;
72
+ return { d: `M${x1.toFixed(1)} ${y1.toFixed(1)}Q${mx.toFixed(1)} ${my.toFixed(1)} ${x2.toFixed(1)} ${y2.toFixed(1)}`, x1, y1, x2, y2 };
73
+ });
74
+ setPaths((prev) => JSON.stringify(prev) === JSON.stringify(next) ? prev : next);
75
+ };
76
+ const schedule = () => {
77
+ if (!frame) frame = requestAnimationFrame(measure);
78
+ };
79
+ const observer = new ResizeObserver(schedule);
80
+ observer.observe(container);
81
+ beams.forEach((beam) => {
82
+ if (beam.from?.current) observer.observe(beam.from.current);
83
+ if (beam.to?.current) observer.observe(beam.to.current);
84
+ });
85
+ window.addEventListener("resize", schedule);
86
+ measure();
87
+ return () => {
88
+ cancelAnimationFrame(frame);
89
+ observer.disconnect();
90
+ window.removeEventListener("resize", schedule);
91
+ };
92
+ }, [containerRef, beams, curvature, edgeInset]);
93
+ return /* @__PURE__ */ jsxs("svg", { className: `bl-beams ${className}`, width: box.width, height: box.height, viewBox: `0 0 ${box.width || 1} ${box.height || 1}`, "aria-hidden": "true", style, children: [
94
+ /* @__PURE__ */ jsx("defs", { children: paths.map(
95
+ (path, index) => path ? /* @__PURE__ */ jsxs("linearGradient", { id: `${uid}-g${index}`, gradientUnits: "userSpaceOnUse", x1: path.x1, y1: path.y1, x2: path.x2, y2: path.y2, children: [
96
+ /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: beams[index].pulseColor ?? pulseColor }),
97
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: beams[index].pulseColorEnd ?? pulseColorEnd })
98
+ ] }, index) : null
99
+ ) }),
100
+ paths.map((path, index) => {
101
+ if (!path) return null;
102
+ const beam = beams[index];
103
+ const reverse = beam.reverse;
104
+ const dur = beam.duration ?? duration;
105
+ return /* @__PURE__ */ jsxs("g", { children: [
106
+ /* @__PURE__ */ jsx("path", { d: path.d, fill: "none", stroke: beam.color ?? color, strokeWidth: width, strokeOpacity: "0.35", strokeLinecap: "round" }),
107
+ /* @__PURE__ */ jsx(
108
+ "path",
109
+ {
110
+ className: "bl-beams__pulse",
111
+ d: path.d,
112
+ fill: "none",
113
+ pathLength: "1",
114
+ stroke: `url(#${uid}-g${index})`,
115
+ strokeWidth: width + 0.5,
116
+ strokeLinecap: "round",
117
+ strokeDasharray: `${pulseLength} ${1 + pulseLength}`,
118
+ style: {
119
+ "--bl-dur": `${dur}s`,
120
+ "--bl-from": reverse ? -1 : pulseLength,
121
+ "--bl-to": reverse ? pulseLength : -1,
122
+ animationDelay: `${beam.delay ?? -index * 0.6}s`
123
+ }
124
+ }
125
+ )
126
+ ] }, index);
127
+ })
128
+ ] });
129
+ }
130
+ export {
131
+ ConnectBeams as default
132
+ };
@@ -0,0 +1,34 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ export interface OrbItem {
3
+ label: string;
4
+ icon?: ReactNode;
5
+ onSelect?: () => void;
6
+ disabled?: boolean;
7
+ danger?: boolean;
8
+ }
9
+ export interface ContextOrbProps {
10
+ /** Actions, clockwise from the top. */
11
+ items?: OrbItem[];
12
+ /** The area that opens the menu. */
13
+ children?: ReactNode;
14
+ onSelect?: (item: OrbItem, index: number) => void;
15
+ radius?: number;
16
+ itemSize?: number;
17
+ hubSize?: number;
18
+ /** Pointer distance before aiming starts, in px. */
19
+ deadZone?: number;
20
+ /** Touch hold time in ms. */
21
+ longPress?: number;
22
+ label?: string;
23
+ /** Hub text before an action is aimed at. */
24
+ hint?: string;
25
+ backgroundColor?: string;
26
+ textColor?: string;
27
+ lineColor?: string;
28
+ accentColor?: string;
29
+ dangerColor?: string;
30
+ fontFamily?: string;
31
+ className?: string;
32
+ style?: CSSProperties;
33
+ }
34
+ export default function ContextOrb({ items, children, onSelect, radius, itemSize, hubSize, deadZone, longPress, label, hint, backgroundColor, textColor, lineColor, accentColor, dangerColor, fontFamily, className, style }: ContextOrbProps): import("react").JSX.Element;
@@ -0,0 +1,269 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useInsertionEffect, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ const STYLE_ID = "bl-context-orb";
6
+ const CSS = `
7
+ .bl-corb-area { position: relative; outline: none; -webkit-touch-callout: none; }
8
+ .bl-corb-area:focus-visible { outline: 2px dashed var(--bl-accent); outline-offset: 4px; }
9
+ .bl-corb { position: fixed; z-index: 1800; width: 0; height: 0; font-family: var(--bl-font); }
10
+ .bl-corb__hub { position: absolute; left: 0; top: 0; display: grid; place-items: center; width: var(--bl-hub); height: var(--bl-hub); margin: calc(var(--bl-hub) / -2) 0 0 calc(var(--bl-hub) / -2); border-radius: 50%; background: var(--bl-bg); color: var(--bl-ink); box-shadow: 0 0 0 1px var(--bl-line), 0 0 0 calc(var(--bl-radius) + var(--bl-item) / 2 + 10px) color-mix(in srgb, var(--bl-bg) 55%, transparent); font-size: 11px; font-weight: 600; text-align: center; line-height: 1.2; padding: 6px; box-sizing: border-box; animation: bl-corb-hub 260ms cubic-bezier(.3,1.4,.5,1) both; }
11
+ .bl-corb__item { position: absolute; left: 0; top: 0; display: grid; place-items: center; width: var(--bl-item); height: var(--bl-item); margin: calc(var(--bl-item) / -2) 0 0 calc(var(--bl-item) / -2); padding: 0; border: 0; border-radius: 50%; background: var(--bl-bg); color: var(--bl-ink); box-shadow: 0 0 0 1px var(--bl-line), 0 10px 24px -10px rgba(0,0,0,0.8); cursor: pointer; transform: translate(var(--x), var(--y)); animation: bl-corb-item 380ms cubic-bezier(.3,1.5,.5,1) both; animation-delay: calc(var(--i) * 25ms); transition: box-shadow 120ms, scale 160ms cubic-bezier(.3,1.6,.5,1); }
12
+ .bl-corb__item > * { pointer-events: none; }
13
+ .bl-corb__item[data-active] { scale: 1.18; box-shadow: 0 0 0 2px var(--bl-accent), 0 10px 24px -10px rgba(0,0,0,0.8); }
14
+ .bl-corb__item[data-danger][data-active] { box-shadow: 0 0 0 2px var(--bl-danger), 0 10px 24px -10px rgba(0,0,0,0.8); }
15
+ .bl-corb__item:disabled { opacity: 0.35; cursor: not-allowed; }
16
+ .bl-corb__item:focus-visible { outline: none; }
17
+ .bl-corb[data-closing] .bl-corb__item, .bl-corb[data-closing] .bl-corb__hub { animation: bl-corb-out 140ms ease-in both; }
18
+ @keyframes bl-corb-hub { from { transform: scale(0.3); opacity: 0; } }
19
+ @keyframes bl-corb-item { from { transform: translate(0, 0) scale(0.2); opacity: 0; } }
20
+ @keyframes bl-corb-out { to { opacity: 0; scale: 0.6; } }
21
+ @media (prefers-reduced-motion: reduce) { .bl-corb__item, .bl-corb__hub { animation: bl-corb-fade 120ms both; transition: none; } }
22
+ @keyframes bl-corb-fade { from { opacity: 0; } }
23
+ `;
24
+ function useStyles() {
25
+ useInsertionEffect(() => {
26
+ if (typeof document === "undefined") return;
27
+ const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
28
+ style.textContent = CSS;
29
+ if (!style.isConnected) document.head.appendChild(style);
30
+ }, []);
31
+ }
32
+ function ContextOrb({
33
+ items = [],
34
+ children,
35
+ onSelect,
36
+ radius = 78,
37
+ itemSize = 48,
38
+ hubSize = 64,
39
+ deadZone = 26,
40
+ longPress = 450,
41
+ label = "Actions",
42
+ hint = "Pick an action",
43
+ backgroundColor = "#1a1c2c",
44
+ textColor = "#f4f4f4",
45
+ lineColor = "#333c57",
46
+ accentColor = "#73eff7",
47
+ dangerColor = "#ef7d57",
48
+ fontFamily = "ui-sans-serif, system-ui, sans-serif",
49
+ className = "",
50
+ style
51
+ }) {
52
+ useStyles();
53
+ const uid = useId().replace(/[^a-zA-Z0-9_-]/g, "");
54
+ const areaRef = useRef(null);
55
+ const [menu, setMenu] = useState(null);
56
+ const [active, setActive] = useState(-1);
57
+ const gesture = useRef({ held: false, moved: false, x: 0, y: 0, keyboard: false });
58
+ const pressTimer = useRef(0);
59
+ const closeTimer = useRef(0);
60
+ const itemRefs = useRef([]);
61
+ const activeRef = useRef(active);
62
+ activeRef.current = active;
63
+ const angleOf = (i) => -Math.PI / 2 + i / items.length * Math.PI * 2;
64
+ const open = (x, y, { held = false, keyboard = false } = {}) => {
65
+ const reach = radius + itemSize / 2 + 8;
66
+ const cx = Math.max(reach, Math.min(window.innerWidth - reach, x));
67
+ const cy = Math.max(reach, Math.min(window.innerHeight - reach, y));
68
+ clearTimeout(closeTimer.current);
69
+ gesture.current = { held, moved: false, x: cx, y: cy, keyboard };
70
+ setActive(keyboard ? items.findIndex((item) => !item.disabled) : -1);
71
+ setMenu({ x: cx, y: cy, closing: false });
72
+ };
73
+ const close = (refocus = false) => {
74
+ setMenu((current2) => current2 ? { ...current2, closing: true } : null);
75
+ clearTimeout(closeTimer.current);
76
+ closeTimer.current = setTimeout(() => setMenu(null), 160);
77
+ if (refocus) areaRef.current?.focus({ preventScroll: true });
78
+ };
79
+ const choose = (index) => {
80
+ const item = items[index];
81
+ if (!item || item.disabled) return;
82
+ item.onSelect?.();
83
+ onSelect?.(item, index);
84
+ close(gesture.current.keyboard);
85
+ };
86
+ const aim = (clientX, clientY) => {
87
+ const { x, y } = gesture.current;
88
+ const dx = clientX - x;
89
+ const dy = clientY - y;
90
+ if (Math.hypot(dx, dy) < deadZone) return -1;
91
+ const angle = Math.atan2(dy, dx);
92
+ let best = -1;
93
+ let bestGap = Infinity;
94
+ items.forEach((item, i) => {
95
+ if (item.disabled) return;
96
+ const gap = Math.abs(Math.atan2(Math.sin(angle - angleOf(i)), Math.cos(angle - angleOf(i))));
97
+ if (gap < bestGap) {
98
+ bestGap = gap;
99
+ best = i;
100
+ }
101
+ });
102
+ return best;
103
+ };
104
+ useEffect(() => {
105
+ if (!menu || menu.closing) return void 0;
106
+ const onMove = (event) => {
107
+ const index = aim(event.clientX, event.clientY);
108
+ if (index >= 0) gesture.current.moved = true;
109
+ setActive(index);
110
+ };
111
+ const onUp = (event) => {
112
+ if (gesture.current.held && gesture.current.moved) {
113
+ const index = aim(event.clientX, event.clientY);
114
+ if (index >= 0) choose(index);
115
+ else close();
116
+ }
117
+ gesture.current.held = false;
118
+ };
119
+ const onDown = (event) => {
120
+ if (event.target.closest?.(".bl-corb")) gesture.current.held = false;
121
+ else close();
122
+ };
123
+ const onKey = (event) => {
124
+ const step = event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : event.key === "ArrowLeft" || event.key === "ArrowUp" ? -1 : 0;
125
+ if (step) {
126
+ event.preventDefault();
127
+ gesture.current.keyboard = true;
128
+ setActive((current2) => {
129
+ let next = current2;
130
+ for (let n = 0; n < items.length; n++) {
131
+ next = (next + step + items.length) % items.length;
132
+ if (!items[next].disabled) return next;
133
+ }
134
+ return current2;
135
+ });
136
+ } else if (event.key === "Enter" || event.key === " ") {
137
+ event.preventDefault();
138
+ if (activeRef.current >= 0) choose(activeRef.current);
139
+ } else if (event.key === "Escape" || event.key === "Tab") {
140
+ event.preventDefault();
141
+ close(true);
142
+ }
143
+ };
144
+ window.addEventListener("pointermove", onMove);
145
+ window.addEventListener("pointerup", onUp);
146
+ window.addEventListener("pointerdown", onDown, true);
147
+ window.addEventListener("keydown", onKey);
148
+ const dismiss = () => close();
149
+ window.addEventListener("scroll", dismiss, { passive: true, capture: true });
150
+ window.addEventListener("blur", dismiss);
151
+ return () => {
152
+ window.removeEventListener("pointermove", onMove);
153
+ window.removeEventListener("pointerup", onUp);
154
+ window.removeEventListener("pointerdown", onDown, true);
155
+ window.removeEventListener("keydown", onKey);
156
+ window.removeEventListener("scroll", dismiss, { capture: true });
157
+ window.removeEventListener("blur", dismiss);
158
+ };
159
+ }, [menu, items]);
160
+ useEffect(() => {
161
+ if (menu && !menu.closing && gesture.current.keyboard && active >= 0) itemRefs.current[active]?.focus({ preventScroll: true });
162
+ }, [menu, active]);
163
+ const onContextMenu = (event) => {
164
+ event.preventDefault();
165
+ clearTimeout(pressTimer.current);
166
+ open(event.clientX, event.clientY, { held: event.button === 2 || event.nativeEvent.pointerType === "touch" });
167
+ };
168
+ const onPointerDown = (event) => {
169
+ if (event.pointerType !== "touch") return;
170
+ const { clientX, clientY } = event;
171
+ clearTimeout(pressTimer.current);
172
+ pressTimer.current = setTimeout(() => open(clientX, clientY, { held: true }), longPress);
173
+ const cancel = (move) => {
174
+ if (!move || Math.hypot(move.clientX - clientX, move.clientY - clientY) > 10) {
175
+ clearTimeout(pressTimer.current);
176
+ window.removeEventListener("pointermove", cancel);
177
+ window.removeEventListener("pointerup", cancel);
178
+ }
179
+ };
180
+ window.addEventListener("pointermove", cancel);
181
+ window.addEventListener("pointerup", () => cancel(null), { once: true });
182
+ };
183
+ const onKeyDown = (event) => {
184
+ if (event.key === "ContextMenu" || event.key === "F10" && event.shiftKey) {
185
+ event.preventDefault();
186
+ const rect = areaRef.current.getBoundingClientRect();
187
+ open(rect.left + rect.width / 2, rect.top + rect.height / 2, { keyboard: true });
188
+ }
189
+ };
190
+ useEffect(
191
+ () => () => {
192
+ clearTimeout(pressTimer.current);
193
+ clearTimeout(closeTimer.current);
194
+ },
195
+ []
196
+ );
197
+ const current = items[active];
198
+ return /* @__PURE__ */ jsxs(
199
+ "div",
200
+ {
201
+ ref: areaRef,
202
+ className: `bl-corb-area ${className}`,
203
+ tabIndex: 0,
204
+ "aria-haspopup": "menu",
205
+ "aria-expanded": !!menu && !menu.closing,
206
+ "aria-keyshortcuts": "Shift+F10",
207
+ onContextMenu,
208
+ onPointerDown,
209
+ onKeyDown,
210
+ style: { "--bl-accent": accentColor, ...style },
211
+ children: [
212
+ children,
213
+ menu && createPortal(
214
+ /* @__PURE__ */ jsxs(
215
+ "div",
216
+ {
217
+ className: "bl-corb",
218
+ "data-closing": menu.closing || void 0,
219
+ style: {
220
+ left: menu.x,
221
+ top: menu.y,
222
+ "--bl-item": `${itemSize}px`,
223
+ "--bl-hub": `${hubSize}px`,
224
+ "--bl-radius": `${radius}px`,
225
+ "--bl-bg": backgroundColor,
226
+ "--bl-ink": textColor,
227
+ "--bl-line": lineColor,
228
+ "--bl-accent": accentColor,
229
+ "--bl-danger": dangerColor,
230
+ "--bl-font": fontFamily
231
+ },
232
+ children: [
233
+ /* @__PURE__ */ jsx("div", { className: "bl-corb__hub", "aria-hidden": "true", children: current ? current.label : hint }),
234
+ /* @__PURE__ */ jsx("div", { role: "menu", "aria-label": label, id: `${uid}-menu`, children: items.map((item, i) => {
235
+ const a = angleOf(i);
236
+ return /* @__PURE__ */ jsx(
237
+ "button",
238
+ {
239
+ ref: (node) => {
240
+ itemRefs.current[i] = node;
241
+ },
242
+ type: "button",
243
+ role: "menuitem",
244
+ className: "bl-corb__item",
245
+ tabIndex: i === active ? 0 : -1,
246
+ "aria-label": item.label,
247
+ disabled: item.disabled,
248
+ "data-active": i === active || void 0,
249
+ "data-danger": item.danger || void 0,
250
+ style: { "--x": `${(Math.cos(a) * radius).toFixed(1)}px`, "--y": `${(Math.sin(a) * radius).toFixed(1)}px`, "--i": i },
251
+ onPointerEnter: () => setActive(i),
252
+ onClick: () => choose(i),
253
+ children: item.icon ?? item.label.slice(0, 1)
254
+ },
255
+ item.label
256
+ );
257
+ }) })
258
+ ]
259
+ }
260
+ ),
261
+ document.body
262
+ )
263
+ ]
264
+ }
265
+ );
266
+ }
267
+ export {
268
+ ContextOrb as default
269
+ };
@@ -0,0 +1,20 @@
1
+ import { type CSSProperties } from 'react';
2
+ export interface ContourLinesProps {
3
+ /** How many contours. */
4
+ levels?: number;
5
+ /** A brighter index line every this many contours. */
6
+ major?: number;
7
+ scale?: number;
8
+ speed?: number;
9
+ pixelSize?: number;
10
+ /** Alternate the colour between contours, like an atlas. */
11
+ tint?: boolean;
12
+ /** The pointer raises a hill. */
13
+ pointer?: boolean;
14
+ lineColor?: string;
15
+ majorColor?: string;
16
+ bandColors?: string[];
17
+ className?: string;
18
+ style?: CSSProperties;
19
+ }
20
+ export default function ContourLines({ levels, major, scale, speed, pixelSize, tint, pointer, lineColor, majorColor, bandColors, className, style }: ContourLinesProps): import("react").JSX.Element;