bits-lab 0.0.0-stage → 0.1.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 (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +51 -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 +34 -4
@@ -0,0 +1,189 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useInsertionEffect, useMemo, useRef, useState } from "react";
4
+ const STYLE_ID = "bl-level-map";
5
+ const CSS = `
6
+ .bl-lvl { position: relative; width: 100%; font-family: var(--bl-font, "Press Start 2P", ui-monospace, monospace); }
7
+ .bl-lvl__svg { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
8
+ .bl-lvl__reveal { stroke-dasharray: 1; stroke-dashoffset: 1; animation: bl-lvl-draw var(--bl-draw) steps(24) 200ms forwards; }
9
+ .bl-lvl__node { position: absolute; display: grid; place-items: center; width: var(--bl-node); height: var(--bl-node); margin: calc(var(--bl-node) / -2) 0 0 calc(var(--bl-node) / -2); padding: 0; border: 0; cursor: pointer;
10
+ background: var(--bl-face); color: #0b0b14; font-size: calc(var(--bl-node) / 4);
11
+ box-shadow: 0 -4px 0 0 #0b0b14, 0 4px 0 0 #0b0b14, -4px 0 0 0 #0b0b14, 4px 0 0 0 #0b0b14, inset -4px -4px 0 0 rgba(0,0,0,0.25), inset 4px 4px 0 0 rgba(255,255,255,0.3); }
12
+ .bl-lvl__node:hover:not([aria-disabled="true"]) { filter: brightness(1.12); transform: translateY(-2px); }
13
+ .bl-lvl__node:focus-visible { outline: 4px solid #f4f4f4; outline-offset: 6px; }
14
+ .bl-lvl__node[aria-disabled="true"] { cursor: not-allowed; filter: grayscale(1) brightness(0.6); }
15
+ .bl-lvl__node[data-status="current"] { animation: bl-lvl-pulse 1s steps(2) infinite; }
16
+ .bl-lvl__marker { position: absolute; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%); animation: bl-lvl-bounce 0.7s steps(3) infinite alternate; pointer-events: none; }
17
+ .bl-lvl__name { position: absolute; top: calc(100% + 12px); left: 50%; transform: translateX(-50%); width: max-content; max-width: 140px; color: var(--bl-text); font-size: 8px; line-height: 1.5; text-align: center; text-transform: uppercase; pointer-events: none; }
18
+ .bl-lvl__stars { display: block; margin-top: 4px; color: #ffcd75; letter-spacing: 2px; }
19
+ @keyframes bl-lvl-draw { to { stroke-dashoffset: 0; } }
20
+ @keyframes bl-lvl-pulse { 50% { box-shadow: 0 -4px 0 0 #f4f4f4, 0 4px 0 0 #f4f4f4, -4px 0 0 0 #f4f4f4, 4px 0 0 0 #f4f4f4, inset -4px -4px 0 0 rgba(0,0,0,0.25), inset 4px 4px 0 0 rgba(255,255,255,0.3); } }
21
+ @keyframes bl-lvl-bounce { to { transform: translate(-50%, -8px); } }
22
+ @media (prefers-reduced-motion: reduce) {
23
+ .bl-lvl__reveal { animation: none; stroke-dashoffset: 0; }
24
+ .bl-lvl__node[data-status="current"], .bl-lvl__marker { animation: none; }
25
+ }
26
+ `;
27
+ function useStyles() {
28
+ useInsertionEffect(() => {
29
+ if (typeof document === "undefined") return;
30
+ const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
31
+ style.textContent = CSS;
32
+ if (!style.isConnected) document.head.appendChild(style);
33
+ }, []);
34
+ }
35
+ const Lock = () => /* @__PURE__ */ jsxs("svg", { width: "45%", height: "45%", viewBox: "0 0 8 8", shapeRendering: "crispEdges", fill: "#0b0b14", "aria-hidden": "true", children: [
36
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "0", width: "4", height: "1" }),
37
+ /* @__PURE__ */ jsx("rect", { x: "1", y: "1", width: "1", height: "3" }),
38
+ /* @__PURE__ */ jsx("rect", { x: "6", y: "1", width: "1", height: "3" }),
39
+ /* @__PURE__ */ jsx("rect", { x: "0", y: "4", width: "8", height: "4" })
40
+ ] });
41
+ const STATUS_COLORS = { cleared: "#38b764", current: "#ffcd75", available: "#41a6f6", locked: "#566c86" };
42
+ function layout(count, width, { nodeSize, minSpacing, rowGap, padding }) {
43
+ const inner = Math.max(nodeSize, width - padding * 2 - nodeSize);
44
+ const perRow = Math.max(2, Math.floor(inner / minSpacing) + 1);
45
+ const spacing = inner / (perRow - 1);
46
+ const points = Array.from({ length: count }, (_, i) => {
47
+ const row = Math.floor(i / perRow);
48
+ const col = i % perRow;
49
+ const x = padding + nodeSize / 2 + (row % 2 ? perRow - 1 - col : col) * spacing;
50
+ const y = padding + nodeSize / 2 + 40 + row * rowGap + Math.sin(col * 1.3 + row) * rowGap * 0.12;
51
+ return { x, y, row };
52
+ });
53
+ const rows = Math.ceil(count / perRow);
54
+ return { points, height: padding * 2 + nodeSize + 40 + (rows - 1) * rowGap + 70 };
55
+ }
56
+ function pathThrough(points) {
57
+ if (!points.length) return "";
58
+ let d = `M${points[0].x} ${points[0].y}`;
59
+ for (let i = 1; i < points.length; i++) {
60
+ const a = points[i - 1];
61
+ const b = points[i];
62
+ if (a.row === b.row) {
63
+ d += ` Q${(a.x + b.x) / 2} ${(a.y + b.y) / 2 - 18} ${b.x} ${b.y}`;
64
+ } else {
65
+ const bulge = a.x > b.x || a.row % 2 === 0 ? 80 : -80;
66
+ d += ` C${a.x + bulge} ${a.y} ${b.x + bulge} ${b.y} ${b.x} ${b.y}`;
67
+ }
68
+ }
69
+ return d;
70
+ }
71
+ const DEFAULT_LEVELS = [
72
+ { id: 1, name: "Spawn point", status: "cleared", stars: 3 },
73
+ { id: 2, name: "Oak woods", status: "cleared", stars: 2 },
74
+ { id: 3, name: "Copper cave", status: "cleared", stars: 3 },
75
+ { id: 4, name: "Sunken temple", status: "current" },
76
+ { id: 5, name: "Lava bridge", status: "available" },
77
+ { id: 6, name: "Sky isles", status: "locked" },
78
+ { id: 7, name: "Crystal depths", status: "locked" },
79
+ { id: 8, name: "The dragon", status: "locked" }
80
+ ];
81
+ function LevelMap({
82
+ levels = DEFAULT_LEVELS,
83
+ nodeSize = 56,
84
+ minSpacing = 130,
85
+ rowGap = 150,
86
+ padding = 24,
87
+ pathColor = "#566c86",
88
+ clearedColor = "#a7f070",
89
+ textColor = "#f4f4f4",
90
+ marker,
91
+ drawDuration = 1200,
92
+ fontFamily,
93
+ onSelect,
94
+ className = "",
95
+ style
96
+ }) {
97
+ useStyles();
98
+ const maskId = `bl-lvl-mask-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
99
+ const rootRef = useRef(null);
100
+ const nodeRefs = useRef([]);
101
+ const [width, setWidth] = useState(640);
102
+ useEffect(() => {
103
+ const root = rootRef.current;
104
+ if (!root) return void 0;
105
+ const observer = new ResizeObserver(([entry]) => setWidth(entry.contentRect.width));
106
+ observer.observe(root);
107
+ return () => observer.disconnect();
108
+ }, []);
109
+ const { points, height } = useMemo(
110
+ () => layout(levels.length, width, { nodeSize, minSpacing, rowGap, padding }),
111
+ [levels.length, width, nodeSize, minSpacing, rowGap, padding]
112
+ );
113
+ const fullPath = useMemo(() => pathThrough(points), [points]);
114
+ const progressIndex = Math.max(0, levels.findIndex((level) => level.status === "current"), levels.filter((level) => level.status === "cleared").length - 1);
115
+ const clearedPath = useMemo(() => pathThrough(points.slice(0, progressIndex + 1)), [points, progressIndex]);
116
+ const focusNode = (index) => nodeRefs.current[Math.max(0, Math.min(levels.length - 1, index))]?.focus();
117
+ return /* @__PURE__ */ jsxs(
118
+ "div",
119
+ {
120
+ ref: rootRef,
121
+ className: `bl-lvl ${className}`,
122
+ role: "list",
123
+ "aria-label": "Level map",
124
+ style: { height, "--bl-node": `${nodeSize}px`, "--bl-text": textColor, "--bl-draw": `${drawDuration}ms`, ...fontFamily ? { "--bl-font": fontFamily } : null, ...style },
125
+ children: [
126
+ /* @__PURE__ */ jsxs("svg", { className: "bl-lvl__svg", width: "100%", height, "aria-hidden": "true", shapeRendering: "crispEdges", children: [
127
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("mask", { id: maskId, maskUnits: "userSpaceOnUse", children: /* @__PURE__ */ jsx("path", { className: "bl-lvl__reveal", d: clearedPath, pathLength: "1", fill: "none", stroke: "#fff", strokeWidth: "24" }, progressIndex) }) }),
128
+ /* @__PURE__ */ jsx("path", { d: fullPath, fill: "none", stroke: pathColor, strokeWidth: "6", strokeDasharray: "6 12", strokeLinecap: "square" }),
129
+ /* @__PURE__ */ jsx(
130
+ "path",
131
+ {
132
+ d: clearedPath,
133
+ fill: "none",
134
+ stroke: clearedColor,
135
+ strokeWidth: "8",
136
+ strokeDasharray: "8 10",
137
+ strokeLinecap: "square",
138
+ mask: `url(#${maskId})`
139
+ }
140
+ )
141
+ ] }),
142
+ levels.map((level, index) => {
143
+ const point = points[index];
144
+ const locked = level.status === "locked";
145
+ return /* @__PURE__ */ jsx("div", { role: "listitem", children: /* @__PURE__ */ jsxs(
146
+ "button",
147
+ {
148
+ ref: (el) => {
149
+ nodeRefs.current[index] = el;
150
+ },
151
+ type: "button",
152
+ className: "bl-lvl__node",
153
+ "data-status": level.status,
154
+ "aria-disabled": locked || void 0,
155
+ "aria-current": level.status === "current" ? "step" : void 0,
156
+ "aria-label": `Level ${index + 1}${level.name ? `: ${level.name}` : ""}, ${level.status}${level.stars ? `, ${level.stars} of 3 stars` : ""}`,
157
+ style: { left: point.x, top: point.y, "--bl-face": STATUS_COLORS[level.status] ?? STATUS_COLORS.available },
158
+ onClick: () => !locked && onSelect?.(level, index),
159
+ onKeyDown: (event) => {
160
+ if (event.key === "ArrowRight" || event.key === "ArrowDown") {
161
+ event.preventDefault();
162
+ focusNode(index + 1);
163
+ }
164
+ if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
165
+ event.preventDefault();
166
+ focusNode(index - 1);
167
+ }
168
+ },
169
+ children: [
170
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: locked ? /* @__PURE__ */ jsx(Lock, {}) : level.status === "cleared" ? "\u2713" : level.label ?? index + 1 }),
171
+ level.status === "current" && /* @__PURE__ */ jsx("span", { className: "bl-lvl__marker", "aria-hidden": "true", children: marker ?? /* @__PURE__ */ jsx("span", { style: { fontSize: 22, color: "#ffcd75" }, children: "\u25BC" }) }),
172
+ level.name && /* @__PURE__ */ jsxs("span", { className: "bl-lvl__name", "aria-hidden": "true", children: [
173
+ level.name,
174
+ level.stars ? /* @__PURE__ */ jsxs("span", { className: "bl-lvl__stars", children: [
175
+ "\u2605".repeat(level.stars),
176
+ "\u2606".repeat(3 - level.stars)
177
+ ] }) : null
178
+ ] })
179
+ ]
180
+ }
181
+ ) }, level.id ?? index);
182
+ })
183
+ ]
184
+ }
185
+ );
186
+ }
187
+ export {
188
+ LevelMap as default
189
+ };
@@ -0,0 +1,22 @@
1
+ import { type CSSProperties } from 'react';
2
+ export interface LightShaftsProps {
3
+ /** Swaying rays from a source, flickering floor pillars, or forked lightning with a flash. */
4
+ mode?: 'rays' | 'beams' | 'lightning';
5
+ /** Rays or pillars. */
6
+ count?: number;
7
+ speed?: number;
8
+ /** Light source position as a share of the area. */
9
+ originX?: number;
10
+ originY?: number;
11
+ /** Fan angle of the rays in degrees. */
12
+ spread?: number;
13
+ /** Roughly how often lightning strikes, in ms. */
14
+ interval?: number;
15
+ pixelSize?: number;
16
+ /** [main, second]. */
17
+ colors?: string[];
18
+ backgroundColor?: string;
19
+ className?: string;
20
+ style?: CSSProperties;
21
+ }
22
+ export default function LightShafts({ mode, count, speed, originX, originY, spread, interval, pixelSize, colors, backgroundColor, className, style }: LightShaftsProps): import("react").JSX.Element;
@@ -0,0 +1,170 @@
1
+ 'use client';
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ const hexToRgb = (hex) => {
5
+ const n = parseInt(hex.replace("#", "").replace(/^(.)(.)(.)$/, "$1$1$2$2$3$3"), 16);
6
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
7
+ };
8
+ const rgba = ([r, g, b], a) => `rgba(${r},${g},${b},${a})`;
9
+ function bolt(x, y, length, angle, depth, out) {
10
+ const segs = 10;
11
+ let px = x;
12
+ let py = y;
13
+ for (let i = 0; i < segs; i++) {
14
+ const a = angle + (Math.random() - 0.5) * 0.9;
15
+ const nx = px + Math.cos(a) * (length / segs);
16
+ const ny = py + Math.sin(a) * (length / segs);
17
+ out.push([px, py, nx, ny, depth]);
18
+ if (depth < 2 && Math.random() < 0.18) bolt(nx, ny, length * 0.45, a + (Math.random() < 0.5 ? -0.6 : 0.6), depth + 1, out);
19
+ px = nx;
20
+ py = ny;
21
+ }
22
+ return out;
23
+ }
24
+ function LightShafts({
25
+ mode = "rays",
26
+ count = 7,
27
+ speed = 1,
28
+ originX = 0.5,
29
+ originY = -0.05,
30
+ spread = 70,
31
+ interval = 3500,
32
+ pixelSize = 3,
33
+ colors = ["#ffcd75", "#f4f4f4"],
34
+ backgroundColor = "#1a1c2c",
35
+ className = "",
36
+ style
37
+ }) {
38
+ const canvasRef = useRef(null);
39
+ useEffect(() => {
40
+ const canvas = canvasRef.current;
41
+ const ctx = canvas.getContext("2d");
42
+ const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
43
+ const main = hexToRgb(colors[0]);
44
+ const second = hexToRgb(colors[1] ?? colors[0]);
45
+ const bg = hexToRgb(backgroundColor);
46
+ let w = 0;
47
+ let h = 0;
48
+ let t = 2;
49
+ let raf = 0;
50
+ let last = 0;
51
+ let visible = true;
52
+ let strike = null;
53
+ let nextStrike = 600;
54
+ const pillars = Array.from({ length: count }, (_, i) => ({ x: (i + 0.5) / count + Math.sin(i * 7.1) * 0.3 / count, width: 0.4 + i * 37 % 10 / 20, phase: i * 1.7 }));
55
+ const fit = () => {
56
+ w = Math.max(1, Math.ceil(canvas.clientWidth / pixelSize));
57
+ h = Math.max(1, Math.ceil(canvas.clientHeight / pixelSize));
58
+ canvas.width = w;
59
+ canvas.height = h;
60
+ ctx.imageSmoothingEnabled = false;
61
+ };
62
+ const rays = () => {
63
+ const ox = originX * w;
64
+ const oy = originY * h;
65
+ const reach = Math.hypot(w, h) * 1.1;
66
+ for (let i = 0; i < count; i++) {
67
+ const base = (i / Math.max(1, count - 1) - 0.5) * (spread * Math.PI / 180);
68
+ const a = Math.PI / 2 + base + Math.sin(t * 0.4 + i * 1.3) * 0.08;
69
+ const half = 0.03 + 0.025 * (0.5 + 0.5 * Math.sin(t * 0.7 + i * 2.1));
70
+ const glow = ctx.createLinearGradient(ox, oy, ox + Math.cos(a) * reach, oy + Math.sin(a) * reach);
71
+ const tint = i % 2 ? second : main;
72
+ const strength = 0.16 + 0.1 * Math.sin(t * 1.1 + i);
73
+ glow.addColorStop(0, rgba(tint, strength * 1.8));
74
+ glow.addColorStop(0.6, rgba(tint, strength * 0.5));
75
+ glow.addColorStop(1, rgba(tint, 0));
76
+ ctx.fillStyle = glow;
77
+ ctx.beginPath();
78
+ ctx.moveTo(ox, oy);
79
+ ctx.lineTo(ox + Math.cos(a - half) * reach, oy + Math.sin(a - half) * reach);
80
+ ctx.lineTo(ox + Math.cos(a + half) * reach, oy + Math.sin(a + half) * reach);
81
+ ctx.closePath();
82
+ ctx.fill();
83
+ }
84
+ };
85
+ const beams = () => {
86
+ pillars.forEach((p, i) => {
87
+ const flicker = 0.55 + 0.25 * Math.sin(t * 3 + p.phase) + 0.2 * Math.sin(t * 7.3 + p.phase * 2);
88
+ const x = (p.x + Math.sin(t * 0.3 + p.phase) * 0.01) * w;
89
+ const bw = Math.max(1, w / count * p.width * 0.5);
90
+ const tint = i % 2 ? second : main;
91
+ const glow = ctx.createLinearGradient(0, h, 0, 0);
92
+ glow.addColorStop(0, rgba(tint, 0.55 * flicker));
93
+ glow.addColorStop(0.5, rgba(tint, 0.18 * flicker));
94
+ glow.addColorStop(1, rgba(tint, 0));
95
+ ctx.fillStyle = glow;
96
+ ctx.fillRect(Math.round(x - bw / 2), 0, Math.round(bw), h);
97
+ ctx.fillStyle = rgba(tint, 0.35 * flicker);
98
+ ctx.fillRect(Math.round(x), Math.round(h * 0.35), 1, h);
99
+ });
100
+ };
101
+ const lightning = (now) => {
102
+ if (!strike || now - strike.at > 700) return;
103
+ const age = (now - strike.at) / 700;
104
+ const flash = age < 0.08 || age > 0.16 && age < 0.22 ? 0.35 : 0;
105
+ if (flash) {
106
+ ctx.fillStyle = rgba(second, flash);
107
+ ctx.fillRect(0, 0, w, h);
108
+ }
109
+ ctx.fillStyle = rgba(main, 1 - age);
110
+ strike.segs.forEach(([x0, y0, x1, y1, depth]) => {
111
+ const steps = Math.max(1, Math.ceil(Math.hypot(x1 - x0, y1 - y0)));
112
+ for (let k = 0; k <= steps; k++) ctx.fillRect(Math.round(x0 + (x1 - x0) * k / steps), Math.round(y0 + (y1 - y0) * k / steps), depth ? 1 : 2, depth ? 1 : 2);
113
+ });
114
+ };
115
+ const draw = (now) => {
116
+ ctx.globalCompositeOperation = "source-over";
117
+ const [r, g, b] = bg;
118
+ ctx.fillStyle = `rgb(${r},${g},${b})`;
119
+ ctx.fillRect(0, 0, w, h);
120
+ ctx.globalCompositeOperation = "lighter";
121
+ if (mode === "beams") beams();
122
+ else if (mode === "lightning") lightning(now);
123
+ else rays();
124
+ ctx.globalCompositeOperation = "source-over";
125
+ };
126
+ const tick = (now) => {
127
+ const dt = Math.max(0, Math.min(0.05, (now - last) / 1e3));
128
+ last = now;
129
+ t += dt * speed;
130
+ if (mode === "lightning") {
131
+ nextStrike -= dt * 1e3;
132
+ if (nextStrike <= 0) {
133
+ strike = { at: now, segs: bolt(w * (0.2 + Math.random() * 0.6), 0, h * 0.95, Math.PI / 2, 0, []) };
134
+ nextStrike = interval * (0.6 + Math.random() * 0.8);
135
+ }
136
+ }
137
+ draw(now);
138
+ raf = visible && !document.hidden ? requestAnimationFrame(tick) : 0;
139
+ };
140
+ const start = () => {
141
+ if (raf || reduced || !visible || document.hidden) return;
142
+ last = performance.now();
143
+ raf = requestAnimationFrame(tick);
144
+ };
145
+ const resize = new ResizeObserver(() => {
146
+ fit();
147
+ draw(performance.now());
148
+ });
149
+ resize.observe(canvas);
150
+ const observer = new IntersectionObserver(([entry]) => {
151
+ visible = entry.isIntersecting;
152
+ start();
153
+ });
154
+ observer.observe(canvas);
155
+ document.addEventListener("visibilitychange", start);
156
+ fit();
157
+ draw(performance.now());
158
+ start();
159
+ return () => {
160
+ cancelAnimationFrame(raf);
161
+ resize.disconnect();
162
+ observer.disconnect();
163
+ document.removeEventListener("visibilitychange", start);
164
+ };
165
+ }, [mode, count, speed, originX, originY, spread, interval, pixelSize, colors.join(), backgroundColor]);
166
+ return /* @__PURE__ */ jsx("canvas", { ref: canvasRef, "aria-hidden": "true", className, style: { display: "block", width: "100%", height: "100%", background: backgroundColor, imageRendering: "pixelated", ...style } });
167
+ }
168
+ export {
169
+ LightShafts as default
170
+ };
@@ -0,0 +1,26 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ export interface GalleryImage {
3
+ src: string;
4
+ alt?: string;
5
+ caption?: ReactNode;
6
+ /** A smaller image for the grid. */
7
+ thumb?: string;
8
+ }
9
+ export interface LightboxGalleryProps {
10
+ images?: GalleryImage[];
11
+ /** Grid column width in px. */
12
+ thumbSize?: number;
13
+ gap?: number;
14
+ aspectRatio?: string;
15
+ radius?: number;
16
+ /** Applied to thumbs and the full image. */
17
+ imageStyle?: CSSProperties;
18
+ label?: string;
19
+ backdropColor?: string;
20
+ surfaceColor?: string;
21
+ accentColor?: string;
22
+ fontFamily?: string;
23
+ className?: string;
24
+ style?: CSSProperties;
25
+ }
26
+ export default function LightboxGallery({ images, thumbSize, gap, aspectRatio, radius, imageStyle, label, backdropColor, surfaceColor, accentColor, fontFamily, className, style }: LightboxGalleryProps): import("react").JSX.Element;