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,59 @@
1
+ import { type ReactNode } from 'react';
2
+ export interface CommandItem {
3
+ id: string;
4
+ label: string;
5
+ icon?: ReactNode;
6
+ /** Muted text on the right. */
7
+ hint?: ReactNode;
8
+ /** Keys shown as kbd chips, e.g. ["⌘", "S"]. */
9
+ shortcut?: string[];
10
+ /** Extra words the search matches (not highlighted). */
11
+ keywords?: string[];
12
+ onSelect?: (item: CommandItem) => void;
13
+ /** Keep the palette open after running this item. */
14
+ keepOpen?: boolean;
15
+ /** Turns the item into a nested page. */
16
+ items?: CommandGroup[];
17
+ /** Search placeholder while this item's page is open. */
18
+ placeholder?: string;
19
+ }
20
+ export interface CommandGroup {
21
+ heading?: string;
22
+ items: CommandItem[];
23
+ }
24
+ export interface FuzzyResult {
25
+ score: number;
26
+ /** Indices of matched characters in the text. */
27
+ indices: number[];
28
+ }
29
+ export interface CommandPaletteProps {
30
+ groups?: CommandGroup[];
31
+ /** Controlled open state. */
32
+ open?: boolean;
33
+ onOpenChange?: (open: boolean) => void;
34
+ /** ⌘/Ctrl + this key toggles the palette; null disables it. */
35
+ hotkey?: string | null;
36
+ placeholder?: string;
37
+ emptyText?: ReactNode;
38
+ /** localStorage key for recently used items; null disables recents. */
39
+ recentKey?: string | null;
40
+ maxRecent?: number;
41
+ /** Width, in px. */
42
+ width?: number;
43
+ /** Max list height before it scrolls, in px. */
44
+ maxListHeight?: number;
45
+ radius?: number;
46
+ backgroundColor?: string;
47
+ textColor?: string;
48
+ mutedColor?: string;
49
+ lineColor?: string;
50
+ activeColor?: string;
51
+ accentColor?: string;
52
+ chipColor?: string;
53
+ backdropColor?: string;
54
+ fontFamily?: string;
55
+ /** Key hints footer. */
56
+ showFooter?: boolean;
57
+ }
58
+ export declare function fuzzyMatch(query: string, text: string): FuzzyResult | null;
59
+ export default function CommandPalette({ groups, open: controlledOpen, onOpenChange, hotkey, placeholder, emptyText, recentKey, maxRecent, width, maxListHeight, radius, backgroundColor, textColor, mutedColor, lineColor, activeColor, accentColor, chipColor, backdropColor, fontFamily, showFooter }: CommandPaletteProps): import("react").ReactPortal | null;
@@ -0,0 +1,349 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ const STYLE_ID = "bl-command-palette";
6
+ const CSS = `
7
+ .bl-cmdk__backdrop { position: fixed; inset: 0; z-index: 1300; background: var(--bl-backdrop); animation: bl-cmdk-fade 160ms ease; }
8
+ .bl-cmdk { position: fixed; z-index: 1301; top: 14vh; left: 50%; width: min(var(--bl-w), calc(100vw - 24px)); transform: translateX(-50%); overflow: hidden; border-radius: var(--bl-radius); background: var(--bl-bg); color: var(--bl-ink); font-family: var(--bl-font); box-shadow: 0 0 0 1px var(--bl-line), 0 30px 80px -20px rgba(0,0,0,0.7); animation: bl-cmdk-in 200ms cubic-bezier(.2,.9,.25,1.1); }
9
+ @keyframes bl-cmdk-in { from { opacity: 0; transform: translateX(-50%) scale(0.96); } }
10
+ @keyframes bl-cmdk-fade { from { opacity: 0; } }
11
+ .bl-cmdk__top { display: flex; align-items: center; gap: 8px; padding: 0 16px; border-bottom: 1px solid var(--bl-line); }
12
+ .bl-cmdk__crumb { flex: 0 0 auto; padding: 4px 8px; border-radius: 6px; background: var(--bl-chip); color: var(--bl-ink); font-size: 12px; font-weight: 600; white-space: nowrap; }
13
+ .bl-cmdk__input { flex: 1; min-width: 0; height: 54px; border: 0; background: transparent; color: inherit; font: inherit; font-size: 16px; outline: none; }
14
+ .bl-cmdk__input::placeholder { color: var(--bl-muted); }
15
+ .bl-cmdk__list { height: var(--bl-list-h); max-height: var(--bl-max-h); overflow-y: auto; overscroll-behavior: contain; transition: height 180ms cubic-bezier(.2,.8,.2,1); scroll-padding: 8px; }
16
+ .bl-cmdk__inner { padding: 6px; }
17
+ .bl-cmdk__heading { padding: 10px 10px 6px; color: var(--bl-muted); font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
18
+ .bl-cmdk__item { display: flex; align-items: center; gap: 12px; min-height: 42px; padding: 0 10px; border-radius: calc(var(--bl-radius) * 0.6); cursor: pointer; user-select: none; }
19
+ .bl-cmdk__item[aria-selected="true"] { background: var(--bl-active); }
20
+ .bl-cmdk__item[aria-selected="true"] .bl-cmdk__icon { color: var(--bl-accent); }
21
+ .bl-cmdk__icon { flex: 0 0 auto; display: grid; place-items: center; width: 24px; color: var(--bl-muted); }
22
+ .bl-cmdk__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
23
+ .bl-cmdk__label mark { background: none; color: var(--bl-accent); font-weight: 700; }
24
+ .bl-cmdk__hint { color: var(--bl-muted); font-size: 13px; white-space: nowrap; }
25
+ .bl-cmdk__keys { display: flex; gap: 4px; }
26
+ .bl-cmdk__keys kbd { min-width: 20px; padding: 2px 5px; border-radius: 5px; background: var(--bl-chip); color: var(--bl-muted); font: 600 11px/16px var(--bl-font); text-align: center; }
27
+ .bl-cmdk__empty { padding: 28px 16px; color: var(--bl-muted); text-align: center; }
28
+ .bl-cmdk__foot { display: flex; gap: 14px; justify-content: flex-end; padding: 8px 14px; border-top: 1px solid var(--bl-line); color: var(--bl-muted); font-size: 12px; }
29
+ .bl-cmdk__foot kbd { margin-right: 4px; padding: 1px 5px; border-radius: 4px; background: var(--bl-chip); font: inherit; }
30
+ @media (prefers-reduced-motion: reduce) { .bl-cmdk, .bl-cmdk__backdrop { animation: none; } .bl-cmdk__list { transition: none; } }
31
+ `;
32
+ function useStyles() {
33
+ useInsertionEffect(() => {
34
+ if (typeof document === "undefined") return;
35
+ const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
36
+ style.textContent = CSS;
37
+ if (!style.isConnected) document.head.appendChild(style);
38
+ }, []);
39
+ }
40
+ function fuzzyMatch(query, text) {
41
+ const q = query.toLowerCase();
42
+ const t = text.toLowerCase();
43
+ if (!q) return { score: 0, indices: [] };
44
+ let score = 0;
45
+ let from = 0;
46
+ let previous = -2;
47
+ const indices = [];
48
+ for (const char of q) {
49
+ if (char === " ") continue;
50
+ const at = t.indexOf(char, from);
51
+ if (at < 0) return null;
52
+ const wordStart = at === 0 || /[\s\-_/.]/.test(t[at - 1]);
53
+ score += 1 + (at === previous + 1 ? 3 : 0) + (wordStart ? 2 : 0) - at * 0.01;
54
+ indices.push(at);
55
+ previous = at;
56
+ from = at + 1;
57
+ }
58
+ if (t.startsWith(q)) score += 4;
59
+ return { score, indices };
60
+ }
61
+ function Highlight({ text, indices }) {
62
+ if (!indices?.length) return text;
63
+ const set = new Set(indices);
64
+ const parts = [];
65
+ let run = "";
66
+ let marked = false;
67
+ [...text].forEach((char, i) => {
68
+ const hit = set.has(i);
69
+ if (hit !== marked && run) {
70
+ parts.push(marked ? /* @__PURE__ */ jsx("mark", { children: run }, i) : run);
71
+ run = "";
72
+ }
73
+ marked = hit;
74
+ run += char;
75
+ });
76
+ if (run) parts.push(marked ? /* @__PURE__ */ jsx("mark", { children: run }, "end") : run);
77
+ return parts;
78
+ }
79
+ const readRecent = (key) => {
80
+ try {
81
+ return JSON.parse(localStorage.getItem(key)) ?? [];
82
+ } catch {
83
+ return [];
84
+ }
85
+ };
86
+ const writeRecent = (key, ids) => {
87
+ try {
88
+ localStorage.setItem(key, JSON.stringify(ids));
89
+ } catch {
90
+ }
91
+ };
92
+ function collect(groups, map = /* @__PURE__ */ new Map()) {
93
+ for (const group of groups) {
94
+ for (const item of group.items) {
95
+ map.set(item.id, item);
96
+ if (item.items) collect(item.items, map);
97
+ }
98
+ }
99
+ return map;
100
+ }
101
+ function CommandPalette({
102
+ groups = [],
103
+ open: controlledOpen,
104
+ onOpenChange,
105
+ hotkey = "k",
106
+ placeholder = "Type a command or search\u2026",
107
+ emptyText = "No results found.",
108
+ recentKey = "bl-command-palette-recent",
109
+ maxRecent = 4,
110
+ width = 620,
111
+ maxListHeight = 360,
112
+ radius = 14,
113
+ backgroundColor = "#1a1c2c",
114
+ textColor = "#f4f4f4",
115
+ mutedColor = "#94b0c2",
116
+ lineColor = "rgba(255,255,255,0.1)",
117
+ activeColor = "rgba(115,239,247,0.12)",
118
+ accentColor = "#73eff7",
119
+ chipColor = "rgba(255,255,255,0.08)",
120
+ backdropColor = "rgba(8,8,16,0.55)",
121
+ fontFamily = "ui-sans-serif, system-ui, sans-serif",
122
+ showFooter = true
123
+ }) {
124
+ useStyles();
125
+ const uid = useId().replace(/[^a-zA-Z0-9_-]/g, "");
126
+ const [innerOpen, setInnerOpen] = useState(false);
127
+ const open = controlledOpen ?? innerOpen;
128
+ const [query, setQuery] = useState("");
129
+ const [pages, setPages] = useState([]);
130
+ const [active, setActive] = useState(0);
131
+ const [recent, setRecent] = useState([]);
132
+ const [listHeight, setListHeight] = useState(0);
133
+ const inputRef = useRef(null);
134
+ const innerRef = useRef(null);
135
+ const listRef = useRef(null);
136
+ const restoreRef = useRef(null);
137
+ const setOpen = (next) => {
138
+ if (controlledOpen === void 0) setInnerOpen(next);
139
+ onOpenChange?.(next);
140
+ };
141
+ const openRef = useRef(open);
142
+ openRef.current = open;
143
+ useEffect(() => {
144
+ if (!hotkey) return;
145
+ const onKey = (event) => {
146
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === hotkey) {
147
+ event.preventDefault();
148
+ setOpen(!openRef.current);
149
+ }
150
+ };
151
+ window.addEventListener("keydown", onKey);
152
+ return () => window.removeEventListener("keydown", onKey);
153
+ }, [hotkey]);
154
+ useEffect(() => {
155
+ if (!open) return;
156
+ restoreRef.current = document.activeElement;
157
+ setQuery("");
158
+ setPages([]);
159
+ setActive(0);
160
+ if (recentKey) setRecent(readRecent(recentKey));
161
+ const previous = document.body.style.overflow;
162
+ document.body.style.overflow = "hidden";
163
+ inputRef.current?.focus({ preventScroll: true });
164
+ return () => {
165
+ document.body.style.overflow = previous;
166
+ restoreRef.current?.focus?.({ preventScroll: true });
167
+ };
168
+ }, [open, recentKey]);
169
+ const allItems = useMemo(() => collect(groups), [groups]);
170
+ const page = pages[pages.length - 1];
171
+ const pageGroups = page ? page.items : groups;
172
+ const results = useMemo(() => {
173
+ const q = query.trim();
174
+ const out = [];
175
+ if (!q) {
176
+ if (!page && recent.length) {
177
+ const items = recent.map((id) => allItems.get(id)).filter(Boolean);
178
+ if (items.length) out.push({ heading: "Recent", items: items.map((item) => ({ item, indices: [] })) });
179
+ }
180
+ pageGroups.forEach((group) => out.push({ heading: group.heading, items: group.items.map((item) => ({ item, indices: [] })) }));
181
+ return out;
182
+ }
183
+ pageGroups.forEach((group) => {
184
+ const matches = group.items.map((item) => {
185
+ const label = fuzzyMatch(q, item.label);
186
+ const keyword = (item.keywords ?? []).map((k) => fuzzyMatch(q, k)).filter(Boolean).sort((a, b) => b.score - a.score)[0];
187
+ if (!label && !keyword) return null;
188
+ return { item, indices: label?.indices ?? [], score: Math.max(label?.score ?? -Infinity, (keyword?.score ?? -Infinity) * 0.8) };
189
+ }).filter(Boolean).sort((a, b) => b.score - a.score);
190
+ if (matches.length) out.push({ heading: group.heading, items: matches, best: matches[0].score });
191
+ });
192
+ return out.sort((a, b) => b.best - a.best);
193
+ }, [query, pageGroups, page, recent, allItems]);
194
+ const flat = results.flatMap((group) => group.items);
195
+ const activeIndex = Math.min(active, Math.max(0, flat.length - 1));
196
+ useEffect(() => setActive(0), [query, pages.length]);
197
+ useLayoutEffect(() => {
198
+ if (!open || !innerRef.current) return;
199
+ const observer = new ResizeObserver(() => setListHeight(innerRef.current?.offsetHeight ?? 0));
200
+ observer.observe(innerRef.current);
201
+ setListHeight(innerRef.current.offsetHeight);
202
+ return () => observer.disconnect();
203
+ }, [open]);
204
+ useEffect(() => {
205
+ listRef.current?.querySelector(`#${uid}-opt-${activeIndex}`)?.scrollIntoView({ block: "nearest" });
206
+ }, [activeIndex, uid]);
207
+ const run = (entry) => {
208
+ if (!entry) return;
209
+ const { item } = entry;
210
+ if (item.items) {
211
+ setPages((prev) => [...prev, item]);
212
+ setQuery("");
213
+ return;
214
+ }
215
+ if (recentKey) {
216
+ const next = [item.id, ...recent.filter((id) => id !== item.id)].slice(0, maxRecent);
217
+ setRecent(next);
218
+ writeRecent(recentKey, next);
219
+ }
220
+ item.onSelect?.(item);
221
+ if (!item.keepOpen) setOpen(false);
222
+ };
223
+ const onKeyDown = (event) => {
224
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
225
+ event.preventDefault();
226
+ if (!flat.length) return;
227
+ const step = event.key === "ArrowDown" ? 1 : -1;
228
+ setActive((activeIndex + step + flat.length) % flat.length);
229
+ } else if (event.key === "Home" && !query) {
230
+ event.preventDefault();
231
+ setActive(0);
232
+ } else if (event.key === "End" && !query) {
233
+ event.preventDefault();
234
+ setActive(flat.length - 1);
235
+ } else if (event.key === "Enter") {
236
+ event.preventDefault();
237
+ run(flat[activeIndex]);
238
+ } else if (event.key === "Escape") {
239
+ event.preventDefault();
240
+ event.stopPropagation();
241
+ if (pages.length) setPages((prev) => prev.slice(0, -1));
242
+ else setOpen(false);
243
+ } else if (event.key === "Backspace" && !query && pages.length) {
244
+ event.preventDefault();
245
+ setPages((prev) => prev.slice(0, -1));
246
+ } else if (event.key === "Tab") {
247
+ event.preventDefault();
248
+ }
249
+ };
250
+ if (!open || typeof document === "undefined") return null;
251
+ let optionIndex = -1;
252
+ return createPortal(
253
+ /* @__PURE__ */ jsxs(
254
+ "div",
255
+ {
256
+ style: {
257
+ "--bl-w": `${width}px`,
258
+ "--bl-radius": `${radius}px`,
259
+ "--bl-bg": backgroundColor,
260
+ "--bl-ink": textColor,
261
+ "--bl-muted": mutedColor,
262
+ "--bl-line": lineColor,
263
+ "--bl-active": activeColor,
264
+ "--bl-accent": accentColor,
265
+ "--bl-chip": chipColor,
266
+ "--bl-backdrop": backdropColor,
267
+ "--bl-font": fontFamily,
268
+ "--bl-max-h": `${maxListHeight}px`,
269
+ "--bl-list-h": `${listHeight}px`
270
+ },
271
+ children: [
272
+ /* @__PURE__ */ jsx("div", { className: "bl-cmdk__backdrop", onClick: () => setOpen(false) }),
273
+ /* @__PURE__ */ jsxs("div", { className: "bl-cmdk", role: "dialog", "aria-modal": "true", "aria-label": "Command palette", children: [
274
+ /* @__PURE__ */ jsxs("div", { className: "bl-cmdk__top", children: [
275
+ pages.map((p) => /* @__PURE__ */ jsx("span", { className: "bl-cmdk__crumb", children: p.label }, p.id)),
276
+ /* @__PURE__ */ jsx(
277
+ "input",
278
+ {
279
+ ref: inputRef,
280
+ className: "bl-cmdk__input",
281
+ role: "combobox",
282
+ "aria-expanded": "true",
283
+ "aria-controls": `${uid}-list`,
284
+ "aria-activedescendant": flat.length ? `${uid}-opt-${activeIndex}` : void 0,
285
+ "aria-autocomplete": "list",
286
+ autoComplete: "off",
287
+ spellCheck: false,
288
+ placeholder: page?.placeholder ?? placeholder,
289
+ value: query,
290
+ onChange: (event) => setQuery(event.target.value),
291
+ onKeyDown
292
+ }
293
+ )
294
+ ] }),
295
+ /* @__PURE__ */ jsx("div", { ref: listRef, className: "bl-cmdk__list", id: `${uid}-list`, role: "listbox", "aria-label": "Results", children: /* @__PURE__ */ jsxs("div", { ref: innerRef, className: "bl-cmdk__inner", children: [
296
+ !flat.length && /* @__PURE__ */ jsx("div", { className: "bl-cmdk__empty", children: emptyText }),
297
+ results.map((group) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": group.heading, children: [
298
+ group.heading && /* @__PURE__ */ jsx("div", { className: "bl-cmdk__heading", "aria-hidden": "true", children: group.heading }),
299
+ group.items.map((entry) => {
300
+ optionIndex += 1;
301
+ const index = optionIndex;
302
+ const { item } = entry;
303
+ return /* @__PURE__ */ jsxs(
304
+ "div",
305
+ {
306
+ id: `${uid}-opt-${index}`,
307
+ className: "bl-cmdk__item",
308
+ role: "option",
309
+ "aria-selected": index === activeIndex,
310
+ onPointerMove: () => index !== activeIndex && setActive(index),
311
+ onClick: () => run(entry),
312
+ children: [
313
+ item.icon && /* @__PURE__ */ jsx("span", { className: "bl-cmdk__icon", children: item.icon }),
314
+ /* @__PURE__ */ jsx("span", { className: "bl-cmdk__label", children: /* @__PURE__ */ jsx(Highlight, { text: item.label, indices: entry.indices }) }),
315
+ item.hint && /* @__PURE__ */ jsx("span", { className: "bl-cmdk__hint", children: item.hint }),
316
+ item.items && /* @__PURE__ */ jsx("span", { className: "bl-cmdk__hint", "aria-hidden": "true", children: "\u203A" }),
317
+ item.shortcut && /* @__PURE__ */ jsx("span", { className: "bl-cmdk__keys", "aria-label": `Shortcut ${item.shortcut.join(" ")}`, children: item.shortcut.map((key) => /* @__PURE__ */ jsx("kbd", { children: key }, key)) })
318
+ ]
319
+ },
320
+ `${group.heading}-${item.id}`
321
+ );
322
+ })
323
+ ] }, group.heading ?? "group"))
324
+ ] }) }),
325
+ showFooter && /* @__PURE__ */ jsxs("div", { className: "bl-cmdk__foot", "aria-hidden": "true", children: [
326
+ /* @__PURE__ */ jsxs("span", { children: [
327
+ /* @__PURE__ */ jsx("kbd", { children: "\u2191\u2193" }),
328
+ "navigate"
329
+ ] }),
330
+ /* @__PURE__ */ jsxs("span", { children: [
331
+ /* @__PURE__ */ jsx("kbd", { children: "\u21B5" }),
332
+ "select"
333
+ ] }),
334
+ /* @__PURE__ */ jsxs("span", { children: [
335
+ /* @__PURE__ */ jsx("kbd", { children: "esc" }),
336
+ pages.length ? "back" : "close"
337
+ ] })
338
+ ] })
339
+ ] })
340
+ ]
341
+ }
342
+ ),
343
+ document.body
344
+ );
345
+ }
346
+ export {
347
+ CommandPalette as default,
348
+ fuzzyMatch
349
+ };
@@ -0,0 +1,33 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ export interface CompareSliderProps {
3
+ /** Layer shown on the "before" side: an image, video or live UI. */
4
+ before?: ReactNode;
5
+ /** Layer revealed on the "after" side. */
6
+ after?: ReactNode;
7
+ /** Corner labels; they hide when their side is almost covered. Empty to hide. */
8
+ beforeLabel?: string;
9
+ afterLabel?: string;
10
+ /** Uncontrolled starting position, in percent. */
11
+ defaultPosition?: number;
12
+ /** Controlled position, in percent. */
13
+ position?: number;
14
+ onPositionChange?: (position: number) => void;
15
+ /** Split top/bottom instead of left/right. */
16
+ vertical?: boolean;
17
+ /** Follow the mouse without dragging (touch still drags). */
18
+ hover?: boolean;
19
+ aspectRatio?: string;
20
+ radius?: number;
21
+ lineColor?: string;
22
+ lineWidth?: number;
23
+ handleInk?: string;
24
+ focusColor?: string;
25
+ /** Arrow-key step, in percent. */
26
+ step?: number;
27
+ fontFamily?: string;
28
+ /** Accessible name of the slider. */
29
+ label?: string;
30
+ className?: string;
31
+ style?: CSSProperties;
32
+ }
33
+ export default function CompareSlider({ before, after, beforeLabel, afterLabel, defaultPosition, position: controlled, onPositionChange, vertical, hover, aspectRatio, radius, lineColor, lineWidth, handleInk, focusColor, step, fontFamily, label, className, style }: CompareSliderProps): import("react").JSX.Element;
@@ -0,0 +1,152 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useInsertionEffect, useRef, useState } from "react";
4
+ const STYLE_ID = "bl-compare";
5
+ const CSS = `
6
+ .bl-cmp { position: relative; width: 100%; aspect-ratio: var(--bl-ratio); overflow: hidden; border-radius: var(--bl-radius); user-select: none; -webkit-user-select: none; touch-action: var(--bl-touch); cursor: var(--bl-cursor); background: #000; }
7
+ .bl-cmp__layer { position: absolute; inset: 0; }
8
+ .bl-cmp__layer > img, .bl-cmp__layer > video { width: 100%; height: 100%; object-fit: cover; display: block; pointer-events: none; }
9
+ .bl-cmp__after { clip-path: inset(0 0 0 var(--bl-pos)); }
10
+ .bl-cmp[data-vertical] .bl-cmp__after { clip-path: inset(var(--bl-pos) 0 0 0); }
11
+ .bl-cmp__label { position: absolute; top: 12px; padding: 5px 9px; border-radius: 6px; background: rgba(0,0,0,0.6); color: #fff; font: 600 11px/1 var(--bl-font); letter-spacing: 0.06em; text-transform: uppercase; pointer-events: none; transition: opacity 200ms; }
12
+ .bl-cmp__label[data-side="before"] { left: 12px; opacity: var(--bl-before-o); }
13
+ .bl-cmp__label[data-side="after"] { right: 12px; opacity: var(--bl-after-o); }
14
+ .bl-cmp[data-vertical] .bl-cmp__label[data-side="after"] { top: auto; bottom: 12px; right: auto; left: 12px; }
15
+ .bl-cmp__divider { position: absolute; top: 0; bottom: 0; left: var(--bl-pos); width: var(--bl-line-w); background: var(--bl-line); transform: translateX(-50%); pointer-events: none; box-shadow: 0 0 12px rgba(0,0,0,0.4); }
16
+ .bl-cmp[data-vertical] .bl-cmp__divider { top: var(--bl-pos); bottom: auto; left: 0; right: 0; width: auto; height: var(--bl-line-w); transform: translateY(-50%); }
17
+ .bl-cmp__handle { position: absolute; top: 50%; left: var(--bl-pos); display: grid; place-items: center; width: 42px; height: 42px; margin: -21px 0 0 -21px; border-radius: 50%; background: var(--bl-line); color: var(--bl-handle-ink); box-shadow: 0 4px 16px rgba(0,0,0,0.35); cursor: grab; outline: none; transition: transform 150ms; }
18
+ .bl-cmp[data-vertical] .bl-cmp__handle { top: var(--bl-pos); left: 50%; }
19
+ .bl-cmp[data-vertical] .bl-cmp__handle svg { transform: rotate(90deg); }
20
+ .bl-cmp__handle:focus-visible { box-shadow: 0 0 0 3px var(--bl-focus), 0 4px 16px rgba(0,0,0,0.35); }
21
+ .bl-cmp[data-dragging] .bl-cmp__handle { transform: scale(1.1); cursor: grabbing; }
22
+ @media (prefers-reduced-motion: reduce) { .bl-cmp__handle, .bl-cmp__label { transition: none; } }
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
+ const clamp = (value) => Math.min(100, Math.max(0, value));
33
+ function CompareSlider({
34
+ before,
35
+ after,
36
+ beforeLabel = "Before",
37
+ afterLabel = "After",
38
+ defaultPosition = 50,
39
+ position: controlled,
40
+ onPositionChange,
41
+ vertical = false,
42
+ hover = false,
43
+ aspectRatio = "16 / 10",
44
+ radius = 14,
45
+ lineColor = "#f4f4f4",
46
+ lineWidth = 3,
47
+ handleInk = "#1a1c2c",
48
+ focusColor = "#73eff7",
49
+ step = 2,
50
+ fontFamily = "ui-sans-serif, system-ui, sans-serif",
51
+ label = "Comparison slider",
52
+ className = "",
53
+ style
54
+ }) {
55
+ useStyles();
56
+ const ref = useRef(null);
57
+ const [inner, setInner] = useState(defaultPosition);
58
+ const [dragging, setDragging] = useState(false);
59
+ const position = controlled ?? inner;
60
+ const latest = useRef(position);
61
+ latest.current = position;
62
+ const set = (value) => {
63
+ const next = clamp(value);
64
+ latest.current = next;
65
+ if (controlled === void 0) setInner(next);
66
+ onPositionChange?.(next);
67
+ };
68
+ const fromPointer = (event) => {
69
+ const rect = ref.current.getBoundingClientRect();
70
+ return vertical ? (event.clientY - rect.top) / rect.height * 100 : (event.clientX - rect.left) / rect.width * 100;
71
+ };
72
+ const onPointerDown = (event) => {
73
+ if (hover || event.pointerType === "mouse" && event.button !== 0) return;
74
+ ref.current.setPointerCapture(event.pointerId);
75
+ setDragging(true);
76
+ set(fromPointer(event));
77
+ };
78
+ const onPointerMove = (event) => {
79
+ if (dragging || hover && event.pointerType === "mouse") set(fromPointer(event));
80
+ };
81
+ const onPointerUp = () => setDragging(false);
82
+ const onKeyDown = (event) => {
83
+ const position2 = latest.current;
84
+ const keys = {
85
+ ArrowLeft: position2 - step,
86
+ ArrowDown: vertical ? position2 + step : position2 - step,
87
+ ArrowRight: position2 + step,
88
+ ArrowUp: vertical ? position2 - step : position2 + step,
89
+ PageDown: position2 - 10,
90
+ PageUp: position2 + 10,
91
+ Home: 0,
92
+ End: 100
93
+ };
94
+ if (!(event.key in keys)) return;
95
+ event.preventDefault();
96
+ set(keys[event.key]);
97
+ };
98
+ return /* @__PURE__ */ jsxs(
99
+ "div",
100
+ {
101
+ ref,
102
+ className: `bl-cmp ${className}`,
103
+ "data-vertical": vertical || void 0,
104
+ "data-dragging": dragging || void 0,
105
+ onPointerDown,
106
+ onPointerMove,
107
+ onPointerUp,
108
+ onPointerCancel: onPointerUp,
109
+ style: {
110
+ "--bl-pos": `${position}%`,
111
+ "--bl-ratio": aspectRatio,
112
+ "--bl-radius": `${radius}px`,
113
+ "--bl-line": lineColor,
114
+ "--bl-line-w": `${lineWidth}px`,
115
+ "--bl-handle-ink": handleInk,
116
+ "--bl-focus": focusColor,
117
+ "--bl-font": fontFamily,
118
+ "--bl-touch": vertical ? "pan-x" : "pan-y",
119
+ "--bl-cursor": vertical ? "row-resize" : "col-resize",
120
+ "--bl-before-o": position > 12 ? 1 : 0,
121
+ "--bl-after-o": position < 88 ? 1 : 0,
122
+ ...style
123
+ },
124
+ children: [
125
+ /* @__PURE__ */ jsx("div", { className: "bl-cmp__layer", children: before }),
126
+ /* @__PURE__ */ jsx("div", { className: "bl-cmp__layer bl-cmp__after", children: after }),
127
+ beforeLabel && /* @__PURE__ */ jsx("span", { className: "bl-cmp__label", "data-side": "before", "aria-hidden": "true", children: beforeLabel }),
128
+ afterLabel && /* @__PURE__ */ jsx("span", { className: "bl-cmp__label", "data-side": "after", "aria-hidden": "true", children: afterLabel }),
129
+ /* @__PURE__ */ jsx("div", { className: "bl-cmp__divider", "aria-hidden": "true" }),
130
+ /* @__PURE__ */ jsx(
131
+ "div",
132
+ {
133
+ className: "bl-cmp__handle",
134
+ role: "slider",
135
+ tabIndex: 0,
136
+ "aria-label": label,
137
+ "aria-orientation": vertical ? "vertical" : "horizontal",
138
+ "aria-valuemin": 0,
139
+ "aria-valuemax": 100,
140
+ "aria-valuenow": Math.round(position),
141
+ "aria-valuetext": `${Math.round(position)}% ${beforeLabel || "before"}, ${100 - Math.round(position)}% ${afterLabel || "after"}`,
142
+ onKeyDown,
143
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "14", viewBox: "0 0 20 14", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 1 0 7l6 6zM14 1l6 6-6 6z" }) })
144
+ }
145
+ )
146
+ ]
147
+ }
148
+ );
149
+ }
150
+ export {
151
+ CompareSlider as default
152
+ };
@@ -0,0 +1,61 @@
1
+ import { type CSSProperties, type ReactNode } from 'react';
2
+ export type ConfettiPreset = 'burst' | 'cannon' | 'fireworks' | 'fountain' | 'rain';
3
+ interface PresetValues {
4
+ /** Number of particles. */
5
+ count: number;
6
+ /** Cone width, in degrees. */
7
+ spread: number;
8
+ /** Launch direction, in degrees from the right (90 = up). */
9
+ angle: number;
10
+ /** Launch speed. */
11
+ velocity: number;
12
+ /** Fall speed multiplier. */
13
+ gravity: number;
14
+ /** Air drag per frame (0–1; lower slows faster). */
15
+ decay: number;
16
+ /** Lifetime, in frames. */
17
+ ticks: number;
18
+ /** Spawn across the top of the window instead of at the origin. */
19
+ fromTop?: boolean;
20
+ }
21
+ /** "square", "circle" or "strip" for paper; any other string draws as text (emoji); an image URL or element draws a sprite. */
22
+ export type ConfettiShape = 'square' | 'circle' | 'strip' | (string & {}) | HTMLImageElement;
23
+ export interface ConfettiOptions extends Partial<PresetValues> {
24
+ /** Element to burst from, or a point (0–1 fractions of the window, or px). Defaults to center. */
25
+ origin?: Element | {
26
+ x: number;
27
+ y: number;
28
+ } | null;
29
+ /** Starting values for the physics options. */
30
+ preset?: ConfettiPreset;
31
+ /** Paper colors. */
32
+ colors?: string[];
33
+ shapes?: ConfettiShape[];
34
+ /** Base particle size, in px. */
35
+ size?: number;
36
+ /** Overall scale for size, speed and gravity. */
37
+ scalar?: number;
38
+ /** Sideways drift per frame. */
39
+ drift?: number;
40
+ /** Canvas z-index. */
41
+ zIndex?: number;
42
+ /** Draw image sprites without smoothing. */
43
+ pixelated?: boolean;
44
+ /** Fire even under reduced motion (skipped by default). */
45
+ force?: boolean;
46
+ }
47
+ export declare function confetti(options?: ConfettiOptions): void;
48
+ export declare namespace confetti {
49
+ var reset: () => void;
50
+ }
51
+ export interface ConfettiProps extends ConfettiOptions {
52
+ /** The element bursts come from. */
53
+ children?: ReactNode;
54
+ /** When to fire. */
55
+ trigger?: 'click' | 'hover' | 'mount';
56
+ disabled?: boolean;
57
+ className?: string;
58
+ style?: CSSProperties;
59
+ }
60
+ export default function Confetti({ children, trigger, disabled, className, style, ...options }: ConfettiProps): import("react").JSX.Element;
61
+ export {};