astro-component-kit 0.0.1 → 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 (353) hide show
  1. package/README.md +218 -119
  2. package/package.json +25 -52
  3. package/src/components/index.ts +207 -0
  4. package/src/components/lib/AnimatedGalaxy.astro +185 -0
  5. package/src/components/lib/Galaxy3D.astro +308 -0
  6. package/src/components/lib/GlassNavbar.astro +13 -11
  7. package/src/components/lib/LogoWithGalaxy.astro +63 -0
  8. package/src/components/lib/buttons/3dPushButton.astro +9 -0
  9. package/src/components/lib/buttons/AnimatedIconButton.astro +10 -0
  10. package/src/components/lib/buttons/BorderDrawButton.astro +9 -0
  11. package/src/components/lib/buttons/CyberpunkButton.astro +10 -0
  12. package/src/components/lib/buttons/DoubleBorderButton.astro +9 -0
  13. package/src/components/lib/buttons/GhostOutlineButton.astro +10 -0
  14. package/src/components/lib/buttons/GlassButton.astro +13 -32
  15. package/src/components/lib/buttons/GlowButton.astro +9 -0
  16. package/src/components/lib/buttons/LiquidButton.astro +9 -0
  17. package/src/components/lib/buttons/LoadingButton.astro +10 -0
  18. package/src/components/lib/buttons/MagneticButton.astro +10 -0
  19. package/src/components/lib/buttons/MinimalPillButton.astro +9 -0
  20. package/src/components/lib/buttons/NeumorphicButton.astro +10 -0
  21. package/src/components/lib/buttons/PulseButton.astro +10 -0
  22. package/src/components/lib/buttons/RetroArcadeButton.astro +9 -0
  23. package/src/components/lib/buttons/RetroShadowButton.astro +9 -0
  24. package/src/components/lib/buttons/ShimmerButton.astro +9 -0
  25. package/src/components/lib/buttons/ShinyButton.astro +9 -0
  26. package/src/components/lib/buttons/TiltGlowButton.astro +10 -0
  27. package/src/components/lib/cards/BlogHorizontalCard.astro +46 -13
  28. package/src/components/lib/cards/CyberFeatureCard.astro +50 -6
  29. package/src/components/lib/cards/EcommerceProductCard.astro +69 -16
  30. package/src/components/lib/cards/GlassCard.astro +8 -0
  31. package/src/components/lib/cards/GlassEventCard.astro +53 -12
  32. package/src/components/lib/cards/GlowPortfolioCard.astro +46 -9
  33. package/src/components/lib/cards/InteractiveTiltCard.astro +47 -7
  34. package/src/components/lib/cards/KanbanItemCard.astro +40 -9
  35. package/src/components/lib/cards/MinimalLinkCard.astro +37 -7
  36. package/src/components/lib/cards/MusicPlayerMini.astro +54 -14
  37. package/src/components/lib/cards/NeumorphicCard.astro +32 -2
  38. package/src/components/lib/cards/NotificationCard.astro +44 -9
  39. package/src/components/lib/cards/PricingCard.astro +47 -9
  40. package/src/components/lib/cards/ProfileCard.astro +50 -11
  41. package/src/components/lib/cards/RetroGameCard.astro +37 -9
  42. package/src/components/lib/cards/StatCard.astro +43 -8
  43. package/src/components/lib/cards/TaskKanbanCard.astro +50 -11
  44. package/src/components/lib/cards/TestimonialCardClean.astro +43 -12
  45. package/src/components/lib/cards/WeatherWidgetCard.astro +36 -10
  46. package/src/components/lib/feedback/AnimatedCheckmark.astro +58 -9
  47. package/src/components/lib/feedback/Badge.astro +47 -12
  48. package/src/components/lib/feedback/CircleProgress.astro +56 -13
  49. package/src/components/lib/feedback/ConfettiFeedback.astro +74 -11
  50. package/src/components/lib/feedback/CyberGlitchAlert.astro +69 -6
  51. package/src/components/lib/feedback/EmptyStateCard.astro +55 -7
  52. package/src/components/lib/feedback/GlassAlert.astro +59 -13
  53. package/src/components/lib/feedback/GlassModal.astro +99 -14
  54. package/src/components/lib/feedback/GlassProgress.astro +39 -5
  55. package/src/components/lib/feedback/IndicatorBadgeMinimal.astro +56 -3
  56. package/src/components/lib/feedback/NeonSpinner.astro +40 -3
  57. package/src/components/lib/feedback/PulseDot.astro +51 -7
  58. package/src/components/lib/feedback/RatingPill.astro +38 -8
  59. package/src/components/lib/feedback/ShakeErrorGroup.astro +44 -3
  60. package/src/components/lib/feedback/SimpleTooltip.astro +53 -4
  61. package/src/components/lib/feedback/SkeletonList.astro +59 -13
  62. package/src/components/lib/feedback/Spotlight.astro +49 -4
  63. package/src/components/lib/feedback/StepProgress.astro +96 -9
  64. package/src/components/lib/feedback/ToastNotif.astro +60 -6
  65. package/src/components/lib/feedback/TypingIndicator.astro +52 -7
  66. package/src/components/lib/forms/AnimatedInput.astro +47 -5
  67. package/src/components/lib/forms/ChipInput.astro +116 -8
  68. package/src/components/lib/forms/ColorPickerInput.astro +53 -6
  69. package/src/components/lib/forms/CurrencyInput.astro +59 -6
  70. package/src/components/lib/forms/CustomRadioGroup.astro +61 -9
  71. package/src/components/lib/forms/CyberpunkCheckbox.astro +64 -8
  72. package/src/components/lib/forms/DragDropUpload.astro +87 -7
  73. package/src/components/lib/forms/ErrorInput.astro +31 -4
  74. package/src/components/lib/forms/FloatingPassword.astro +48 -10
  75. package/src/components/lib/forms/FormGroupVertical.astro +63 -9
  76. package/src/components/lib/forms/GlassSlider.astro +84 -3
  77. package/src/components/lib/forms/GlassTextarea.astro +39 -6
  78. package/src/components/lib/forms/ModernSelect.astro +66 -10
  79. package/src/components/lib/forms/NeumorphicSwitch.astro +54 -26
  80. package/src/components/lib/forms/OTPInput.astro +84 -12
  81. package/src/components/lib/forms/RatingStars.astro +66 -10
  82. package/src/components/lib/forms/SearchReveal.astro +44 -6
  83. package/src/components/lib/forms/SegmentedControl.astro +61 -7
  84. package/src/components/lib/forms/SimpleFileInput.astro +57 -6
  85. package/src/components/lib/forms/StepperInput.astro +101 -9
  86. package/src/components/lib/layout/FeatureHero.astro +70 -6
  87. package/src/components/lib/layout/FooterCenteredMinimal.astro +5 -2
  88. package/src/components/lib/navigation/GlassNavbar.astro +10 -5
  89. package/src/components/lib/navigation/MinimalSidebar.astro +6 -3
  90. package/src/components/lib/navigation/SimpleFooterGlass.astro +6 -2
  91. package/src/components/lib/overlays/SplashIntroOverlay.astro +6 -3
  92. package/src/components/lib/sections/ButtonsShowcase.astro +182 -0
  93. package/src/components/lib/sections/CardsShowcase.astro +376 -0
  94. package/src/components/lib/sections/DataShowcase.astro +329 -0
  95. package/src/components/lib/sections/FeedbackShowcase.astro +320 -0
  96. package/src/components/lib/sections/FormsShowcase.astro +347 -0
  97. package/src/components/lib/sections/HeroGlass.astro +202 -0
  98. package/src/components/lib/sections/HeroGradient.astro +143 -0
  99. package/src/components/lib/sections/HeroSplit.astro +210 -0
  100. package/src/components/lib/sections/LayoutShowcase.astro +317 -0
  101. package/src/components/lib/sections/NavigationShowcase.astro +285 -0
  102. package/src/components/lib/sections/OverlaysShowcase.astro +373 -0
  103. package/src/components/lib/sections/TypographyShowcase.astro +239 -0
  104. package/src/components/lib/sections/index.ts +9 -0
  105. package/src/components/types.d.ts +6 -0
  106. package/{dist → src}/styles/global.css +5 -5
  107. package/dist/AnimatedInput.astro +0 -82
  108. package/dist/Badge.astro +0 -52
  109. package/dist/GlassButton.astro +0 -87
  110. package/dist/GlassCard.astro +0 -72
  111. package/dist/GlassNavbar.astro +0 -65
  112. package/dist/GlowButton.astro +0 -60
  113. package/dist/buttons/3dPushButton.astro +0 -136
  114. package/dist/buttons/AnimatedIconButton.astro +0 -146
  115. package/dist/buttons/BorderDrawButton.astro +0 -112
  116. package/dist/buttons/CyberpunkButton.astro +0 -148
  117. package/dist/buttons/DoubleBorderButton.astro +0 -131
  118. package/dist/buttons/GhostOutlineButton.astro +0 -109
  119. package/dist/buttons/GlassButton.astro +0 -165
  120. package/dist/buttons/GlowButton.astro +0 -119
  121. package/dist/buttons/LiquidButton.astro +0 -167
  122. package/dist/buttons/LoadingButton.astro +0 -148
  123. package/dist/buttons/MagneticButton.astro +0 -134
  124. package/dist/buttons/MinimalPillButton.astro +0 -102
  125. package/dist/buttons/NeumorphicButton.astro +0 -158
  126. package/dist/buttons/PulseButton.astro +0 -111
  127. package/dist/buttons/RetroArcadeButton.astro +0 -105
  128. package/dist/buttons/RetroShadowButton.astro +0 -82
  129. package/dist/buttons/ShimmerButton.astro +0 -113
  130. package/dist/buttons/ShinyButton.astro +0 -121
  131. package/dist/buttons/TiltGlowButton.astro +0 -145
  132. package/dist/buttons/index.mjs +0 -19
  133. package/dist/buttons/index.ts +0 -19
  134. package/dist/cards/BlogHorizontalCard.astro +0 -18
  135. package/dist/cards/CyberFeatureCard.astro +0 -12
  136. package/dist/cards/EcommerceProductCard.astro +0 -24
  137. package/dist/cards/GlassCard.astro +0 -17
  138. package/dist/cards/GlassEventCard.astro +0 -19
  139. package/dist/cards/GlowPortfolioCard.astro +0 -16
  140. package/dist/cards/InteractiveTiltCard.astro +0 -25
  141. package/dist/cards/KanbanItemCard.astro +0 -15
  142. package/dist/cards/MinimalLinkCard.astro +0 -12
  143. package/dist/cards/MusicPlayerMini.astro +0 -21
  144. package/dist/cards/NeumorphicCard.astro +0 -6
  145. package/dist/cards/NotificationCard.astro +0 -15
  146. package/dist/cards/PricingCard.astro +0 -17
  147. package/dist/cards/ProfileCard.astro +0 -17
  148. package/dist/cards/RetroGameCard.astro +0 -15
  149. package/dist/cards/StatCard.astro +0 -15
  150. package/dist/cards/TaskKanbanCard.astro +0 -18
  151. package/dist/cards/TestimonialCardClean.astro +0 -20
  152. package/dist/cards/WeatherWidgetCard.astro +0 -17
  153. package/dist/cards/index.mjs +0 -19
  154. package/dist/cards/index.ts +0 -19
  155. package/dist/data/AccordionGroupGlass.astro +0 -21
  156. package/dist/data/AvatarGroupStack.astro +0 -15
  157. package/dist/data/CalendarGridView.astro +0 -18
  158. package/dist/data/DataChipsGroup.astro +0 -16
  159. package/dist/data/DescriptionListHoriz.astro +0 -14
  160. package/dist/data/FileTreeView.astro +0 -22
  161. package/dist/data/GanttChartMinimal.astro +0 -12
  162. package/dist/data/GlassTable.astro +0 -23
  163. package/dist/data/KeyValuePillGroup.astro +0 -12
  164. package/dist/data/PriceCompareTable.astro +0 -22
  165. package/dist/data/ProgressListSmall.astro +0 -17
  166. package/dist/data/RatingBreakdownBar.astro +0 -13
  167. package/dist/data/SparklineStatCard.astro +0 -16
  168. package/dist/data/StatsGridDashboard.astro +0 -16
  169. package/dist/data/StepperDataVertical.astro +0 -15
  170. package/dist/data/TagCloudData.astro +0 -14
  171. package/dist/data/TimelineHorizSteps.astro +0 -18
  172. package/dist/data/TreeItemInteractive.astro +0 -18
  173. package/dist/data/UserDirectoryItem.astro +0 -15
  174. package/dist/data/VerticalTimeline.astro +0 -21
  175. package/dist/data/index.mjs +0 -20
  176. package/dist/data/index.ts +0 -20
  177. package/dist/feedback/AnimatedCheckmark.astro +0 -13
  178. package/dist/feedback/Badge.astro +0 -19
  179. package/dist/feedback/CircleProgress.astro +0 -22
  180. package/dist/feedback/ConfettiFeedback.astro +0 -18
  181. package/dist/feedback/CyberGlitchAlert.astro +0 -11
  182. package/dist/feedback/EmptyStateCard.astro +0 -13
  183. package/dist/feedback/GlassAlert.astro +0 -20
  184. package/dist/feedback/GlassModal.astro +0 -19
  185. package/dist/feedback/GlassProgress.astro +0 -10
  186. package/dist/feedback/IndicatorBadgeMinimal.astro +0 -10
  187. package/dist/feedback/NeonSpinner.astro +0 -7
  188. package/dist/feedback/PulseDot.astro +0 -12
  189. package/dist/feedback/RatingPill.astro +0 -13
  190. package/dist/feedback/ShakeErrorGroup.astro +0 -7
  191. package/dist/feedback/SimpleTooltip.astro +0 -10
  192. package/dist/feedback/SkeletonList.astro +0 -20
  193. package/dist/feedback/Spotlight.astro +0 -9
  194. package/dist/feedback/StepProgress.astro +0 -14
  195. package/dist/feedback/ToastNotif.astro +0 -11
  196. package/dist/feedback/TypingIndicator.astro +0 -12
  197. package/dist/feedback/index.mjs +0 -20
  198. package/dist/feedback/index.ts +0 -20
  199. package/dist/forms/AnimatedInput.astro +0 -16
  200. package/dist/forms/ChipInput.astro +0 -13
  201. package/dist/forms/ColorPickerInput.astro +0 -13
  202. package/dist/forms/CurrencyInput.astro +0 -11
  203. package/dist/forms/CustomRadioGroup.astro +0 -13
  204. package/dist/forms/CyberpunkCheckbox.astro +0 -15
  205. package/dist/forms/DragDropUpload.astro +0 -12
  206. package/dist/forms/ErrorInput.astro +0 -11
  207. package/dist/forms/FloatingPassword.astro +0 -20
  208. package/dist/forms/FormGroupVertical.astro +0 -14
  209. package/dist/forms/GlassSlider.astro +0 -7
  210. package/dist/forms/GlassTextarea.astro +0 -14
  211. package/dist/forms/ModernSelect.astro +0 -16
  212. package/dist/forms/NeumorphicSwitch.astro +0 -55
  213. package/dist/forms/OTPInput.astro +0 -22
  214. package/dist/forms/RatingStars.astro +0 -15
  215. package/dist/forms/SearchReveal.astro +0 -13
  216. package/dist/forms/SegmentedControl.astro +0 -13
  217. package/dist/forms/SimpleFileInput.astro +0 -11
  218. package/dist/forms/StepperInput.astro +0 -14
  219. package/dist/forms/index.mjs +0 -20
  220. package/dist/forms/index.ts +0 -20
  221. package/dist/index.js +0 -1
  222. package/dist/index.mjs +0 -1
  223. package/dist/layout/BentoGrid3.astro +0 -14
  224. package/dist/layout/CenterFixedBox.astro +0 -6
  225. package/dist/layout/CenteredContainer.astro +0 -8
  226. package/dist/layout/ClusterHorizontal.astro +0 -6
  227. package/dist/layout/FeatureHero.astro +0 -17
  228. package/dist/layout/FooterCenteredMinimal.astro +0 -11
  229. package/dist/layout/FullBleedSection.astro +0 -6
  230. package/dist/layout/GalleryGrid4.astro +0 -7
  231. package/dist/layout/GlassCardGrid.astro +0 -6
  232. package/dist/layout/GlassSectionHeader.astro +0 -15
  233. package/dist/layout/LandingSectionSplit.astro +0 -13
  234. package/dist/layout/MasonryGrid.astro +0 -7
  235. package/dist/layout/MinimalFooterGrid.astro +0 -20
  236. package/dist/layout/ScrollSnapSection.astro +0 -7
  237. package/dist/layout/SectionDividerText.astro +0 -7
  238. package/dist/layout/SidebarLayoutWrapper.astro +0 -11
  239. package/dist/layout/SplitScreenLayout.astro +0 -11
  240. package/dist/layout/StepLayoutVertical.astro +0 -21
  241. package/dist/layout/StickySidebarWrapper.astro +0 -10
  242. package/dist/layout/VerticalStack.astro +0 -8
  243. package/dist/layout/index.mjs +0 -20
  244. package/dist/layout/index.ts +0 -20
  245. package/dist/navigation/AnchorSideNav.astro +0 -13
  246. package/dist/navigation/BottomNavMobile.astro +0 -13
  247. package/dist/navigation/BreadcrumbsMinimal.astro +0 -16
  248. package/dist/navigation/BurgerMorphIcon.astro +0 -12
  249. package/dist/navigation/CommandPaletteUI.astro +0 -17
  250. package/dist/navigation/DotNavigationSlider.astro +0 -13
  251. package/dist/navigation/FloatingTabBar.astro +0 -12
  252. package/dist/navigation/GlassNavbar.astro +0 -19
  253. package/dist/navigation/LangSwitcherPill.astro +0 -17
  254. package/dist/navigation/MegaMenuGlass.astro +0 -25
  255. package/dist/navigation/MinimalSidebar.astro +0 -18
  256. package/dist/navigation/PaginationGlass.astro +0 -20
  257. package/dist/navigation/PaginationInfiniteUI.astro +0 -11
  258. package/dist/navigation/RadialIconMenu.astro +0 -15
  259. package/dist/navigation/RetroArcadeMenu.astro +0 -12
  260. package/dist/navigation/ScrollProgressTop.astro +0 -15
  261. package/dist/navigation/SimpleFooterGlass.astro +0 -21
  262. package/dist/navigation/TabUnderline.astro +0 -14
  263. package/dist/navigation/UserProfileNav.astro +0 -21
  264. package/dist/navigation/VerticalTabs.astro +0 -14
  265. package/dist/navigation/index.mjs +0 -20
  266. package/dist/navigation/index.ts +0 -20
  267. package/dist/overlays/AgeVerificationOverlay.astro +0 -20
  268. package/dist/overlays/BackdropBlurMask.astro +0 -6
  269. package/dist/overlays/BottomSheetMobile.astro +0 -16
  270. package/dist/overlays/CommandDialog.astro +0 -19
  271. package/dist/overlays/ContextMenuOverlay.astro +0 -17
  272. package/dist/overlays/CookieBannerGlass.astro +0 -14
  273. package/dist/overlays/ExitIntentOverlay.astro +0 -19
  274. package/dist/overlays/FloatingTrayActions.astro +0 -13
  275. package/dist/overlays/HelpBubbleOverlay.astro +0 -11
  276. package/dist/overlays/LightboxOverlay.astro +0 -13
  277. package/dist/overlays/LoadingOverlayFull.astro +0 -10
  278. package/dist/overlays/MobileNavOverlay.astro +0 -18
  279. package/dist/overlays/OverlayModal.astro +0 -24
  280. package/dist/overlays/PopoverMenuGlass.astro +0 -17
  281. package/dist/overlays/SearchOverlayFullscreen.astro +0 -15
  282. package/dist/overlays/SideDrawerRight.astro +0 -16
  283. package/dist/overlays/SplashIntroOverlay.astro +0 -11
  284. package/dist/overlays/SpotlightIndicator.astro +0 -6
  285. package/dist/overlays/ToastStackOverlay.astro +0 -12
  286. package/dist/overlays/TooltipActionTray.astro +0 -14
  287. package/dist/overlays/index.mjs +0 -20
  288. package/dist/overlays/index.ts +0 -20
  289. package/dist/typography/AnimatedUnderlineLink.astro +0 -10
  290. package/dist/typography/BackgroundClipMask.astro +0 -7
  291. package/dist/typography/CodeInlineGlass.astro +0 -6
  292. package/dist/typography/CyberpunkGlitchText.astro +0 -20
  293. package/dist/typography/DropCapParagraph.astro +0 -7
  294. package/dist/typography/FadedVerticalText.astro +0 -6
  295. package/dist/typography/FloatingTextLabel.astro +0 -10
  296. package/dist/typography/GlassBlockQuote.astro +0 -13
  297. package/dist/typography/GlassTextReveal.astro +0 -7
  298. package/dist/typography/GradientHeading.astro +0 -9
  299. package/dist/typography/GradientUnderlineLink.astro +0 -7
  300. package/dist/typography/KbdIndicator.astro +0 -6
  301. package/dist/typography/LetterSpacingWide.astro +0 -6
  302. package/dist/typography/MinimalListMarkers.astro +0 -10
  303. package/dist/typography/MonospaceStatLine.astro +0 -6
  304. package/dist/typography/NeonTextHighlight.astro +0 -6
  305. package/dist/typography/ShadowRevealText.astro +0 -7
  306. package/dist/typography/StrokeHeadingOutline.astro +0 -8
  307. package/dist/typography/Text3DLayer.astro +0 -7
  308. package/dist/typography/TypewriterText.astro +0 -15
  309. package/dist/typography/index.mjs +0 -20
  310. package/dist/typography/index.ts +0 -20
  311. package/dist/utilities/AspectRatioBox.astro +0 -11
  312. package/dist/utilities/BackgroundDotPattern.astro +0 -6
  313. package/dist/utilities/CircularMask.astro +0 -7
  314. package/dist/utilities/ClickRippleWrapper.astro +0 -7
  315. package/dist/utilities/FadeInWrapper.astro +0 -11
  316. package/dist/utilities/FixedRatioImage.astro +0 -7
  317. package/dist/utilities/GlassBlurLayer.astro +0 -6
  318. package/dist/utilities/GradientBorderMask.astro +0 -7
  319. package/dist/utilities/HoverLift.astro +0 -7
  320. package/dist/utilities/ResponsiveSpacer.astro +0 -15
  321. package/dist/utilities/ResponsiveVisToggle.astro +0 -11
  322. package/dist/utilities/ScrollLockParent.astro +0 -11
  323. package/dist/utilities/ScrollMarginTarget.astro +0 -10
  324. package/dist/utilities/SlideUpReveal.astro +0 -7
  325. package/dist/utilities/SmoothAnchorLink.astro +0 -22
  326. package/dist/utilities/StackLayering.astro +0 -12
  327. package/dist/utilities/StickyObserver.astro +0 -8
  328. package/dist/utilities/TextTruncate.astro +0 -10
  329. package/dist/utilities/TruncateSingleLine.astro +0 -6
  330. package/dist/utilities/VisuallyHidden.astro +0 -6
  331. package/dist/utilities/index.mjs +0 -20
  332. package/dist/utilities/index.ts +0 -20
  333. package/src/components/lib/utilities/AspectRatioBox.astro +0 -11
  334. package/src/components/lib/utilities/BackgroundDotPattern.astro +0 -6
  335. package/src/components/lib/utilities/CircularMask.astro +0 -7
  336. package/src/components/lib/utilities/ClickRippleWrapper.astro +0 -7
  337. package/src/components/lib/utilities/FadeInWrapper.astro +0 -11
  338. package/src/components/lib/utilities/FixedRatioImage.astro +0 -7
  339. package/src/components/lib/utilities/GlassBlurLayer.astro +0 -6
  340. package/src/components/lib/utilities/GradientBorderMask.astro +0 -7
  341. package/src/components/lib/utilities/HoverLift.astro +0 -7
  342. package/src/components/lib/utilities/ResponsiveSpacer.astro +0 -15
  343. package/src/components/lib/utilities/ResponsiveVisToggle.astro +0 -11
  344. package/src/components/lib/utilities/ScrollLockParent.astro +0 -11
  345. package/src/components/lib/utilities/ScrollMarginTarget.astro +0 -10
  346. package/src/components/lib/utilities/SlideUpReveal.astro +0 -7
  347. package/src/components/lib/utilities/SmoothAnchorLink.astro +0 -22
  348. package/src/components/lib/utilities/StackLayering.astro +0 -12
  349. package/src/components/lib/utilities/StickyObserver.astro +0 -8
  350. package/src/components/lib/utilities/TextTruncate.astro +0 -10
  351. package/src/components/lib/utilities/TruncateSingleLine.astro +0 -6
  352. package/src/components/lib/utilities/VisuallyHidden.astro +0 -6
  353. package/src/components/lib/utilities/index.ts +0 -20
@@ -1,55 +1,83 @@
1
1
  ---
2
+ /**
3
+ * NeumorphicSwitch — A soft-UI checkbox toggle with realistic inset and outset shadow states.
4
+ *
5
+ * @param {string} label - Optional descriptive text suffix.
6
+ * @param {string} id - HTML ID for input linkage.
7
+ * @param {string} name - HTML name binding.
8
+ * @param {boolean} checked - Initial toggle state. Default is false.
9
+ */
10
+ interface Props {
11
+ label?: string;
12
+ id: string;
13
+ name?: string;
14
+ checked?: boolean;
15
+ }
16
+
17
+ const { label, id, name, checked = false } = Astro.props;
2
18
  ---
3
- <label class="neu-switch">
4
- <input type="checkbox" />
5
- <span class="slider"></span>
6
- </label>
19
+
20
+ <div class="neu-switch-wrapper">
21
+ <label class="neu-switch">
22
+ <input type="checkbox" {id} {name} {checked} />
23
+ <span class="slider"></span>
24
+ </label>
25
+ {label && <label for={id} class="neu-label">{label}</label>}
26
+ </div>
27
+
7
28
  <style>
29
+ .neu-switch-wrapper { display: flex; align-items: center; gap: var(--sp-3, 0.75rem); }
30
+
8
31
  .neu-switch {
9
32
  position: relative;
10
33
  display: inline-block;
11
- width: 56px;
12
- height: 30px;
34
+ width: 60px;
35
+ height: 32px;
36
+ flex-shrink: 0;
13
37
  }
38
+
39
+ .neu-label { font-size: 0.9rem; color: var(--c-text-2, #94a3b8); cursor: pointer; }
40
+
14
41
  .neu-switch input {
15
42
  opacity: 0;
16
43
  width: 0;
17
44
  height: 0;
18
45
  }
46
+
19
47
  .slider {
20
48
  position: absolute;
21
49
  cursor: pointer;
22
50
  inset: 0;
23
- background: #1a1f2e;
24
- transition: 0.4s;
51
+ background: var(--c-bg, #1a1f2e);
52
+ transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
25
53
  border-radius: 34px;
26
- border: 1px solid rgba(255, 255, 255, 0.05);
54
+ border: 1px solid var(--c-border, rgba(255, 255, 255, 0.05));
27
55
  box-shadow:
28
- inset 2px 2px 4px rgba(0, 0, 0, 0.4),
29
- inset -2px -2px 4px rgba(255, 255, 255, 0.03);
56
+ inset 2px 2px 5px rgba(0, 0, 0, 0.5),
57
+ inset -2px -2px 5px rgba(255, 255, 255, 0.04);
30
58
  }
59
+
31
60
  .slider:before {
32
61
  position: absolute;
33
62
  content: "";
34
- height: 22px;
35
- width: 22px;
36
- left: 3px;
37
- top: 3px;
38
- background: #4b5563;
39
- transition: 0.4s;
63
+ height: 24px;
64
+ width: 24px;
65
+ left: 4px;
66
+ bottom: 3px;
67
+ background: #374151;
68
+ transition: 0.4s cubic-bezier(0.18, 0.89, 0.32, 1.28);
40
69
  border-radius: 50%;
41
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
70
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
42
71
  }
72
+
43
73
  input:checked + .slider {
44
- background: #1e2433;
45
- box-shadow:
46
- inset 2px 2px 4px rgba(0, 0, 0, 0.5),
47
- inset -2px -2px 4px rgba(255, 255, 255, 0.02);
74
+ background: rgba(99, 102, 241, 0.1);
75
+ border-color: rgba(99, 102, 241, 0.2);
48
76
  }
77
+
49
78
  input:checked + .slider:before {
50
- transform: translateX(26px);
51
- background: #818cf8;
52
- box-shadow: 0 0 10px rgba(129, 140, 248, 0.4);
79
+ transform: translateX(28px);
80
+ background: var(--c-primary, #818cf8);
81
+ box-shadow: 0 0 15px rgba(129, 140, 248, 0.5);
53
82
  }
54
83
  </style>
55
-
@@ -1,22 +1,94 @@
1
1
  ---
2
+ /**
3
+ * OTPInput — A specialized input group for One-Time Password verification codes.
4
+ *
5
+ * @param {string} label - Optional grouping label title.
6
+ * @param {string} id - Base HTML ID for the inputs.
7
+ * @param {number} length - Number of OTP digits. Default is 4.
8
+ * @param {string} name - Base name for form submission (will be indexed).
9
+ */
10
+ interface Props {
11
+ label?: string;
12
+ id: string;
13
+ length?: number;
14
+ name?: string;
15
+ }
16
+
17
+ const { label, id, length = 4, name = "otp" } = Astro.props;
2
18
  ---
3
- <div class="otp-wrap">
4
- <input type="text" maxlength="1" />
5
- <input type="text" maxlength="1" />
6
- <input type="text" maxlength="1" />
7
- <input type="text" maxlength="1" />
19
+
20
+ <div class="otp-container">
21
+ {label && <label class="otp-label">{label}</label>}
22
+ <div class="otp-wrap" data-otp-group>
23
+ {Array.from({ length }).map((_, i) => (
24
+ <input
25
+ type="text"
26
+ inputmode="numeric"
27
+ maxlength="1"
28
+ pattern="[0-9]*"
29
+ autocomplete="one-time-code"
30
+ id={`${id}-${i}`}
31
+ name={`${name}[]`}
32
+ class="otp-field"
33
+ data-otp-index={i}
34
+ />
35
+ ))}
36
+ </div>
8
37
  </div>
38
+
9
39
  <style>
40
+ .otp-container { display: flex; flex-direction: column; align-items: center; gap: var(--sp-4, 1rem); }
41
+ .otp-label { font-size: 0.9rem; font-weight: 600; color: var(--c-text-2, #94a3b8); }
42
+
10
43
  .otp-wrap { display: flex; gap: 0.75rem; justify-content: center; }
11
- .otp-wrap input { width: 45px; height: 55px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); border-radius: 10px; text-align: center; color: #fff; font-size: 1.5rem; font-weight: 700; outline: none; transition: 0.2s; }
12
- .otp-wrap input:focus { border-color: #6366f1; background: rgba(99, 102, 241, 0.1); box-shadow: 0 0 15px rgba(99, 102, 241, 0.3); }
44
+
45
+ .otp-field {
46
+ width: 50px; height: 60px;
47
+ background: var(--c-bg-elev, rgba(255,255,255,0.05));
48
+ border: 1px solid var(--c-border, rgba(255,255,255,0.1));
49
+ border-radius: var(--r-md, 12px);
50
+ text-align: center; color: var(--c-text-1, #fff);
51
+ font-size: 1.75rem; font-weight: 800;
52
+ outline: none; transition: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
53
+ }
54
+
55
+ .otp-field:focus {
56
+ border-color: var(--c-primary, #6366f1);
57
+ background: rgba(99, 102, 241, 0.1);
58
+ box-shadow: 0 0 15px rgba(99, 102, 241, 0.3), 0 0 0 3px rgba(99, 102, 241, 0.15);
59
+ transform: translateY(-2px);
60
+ }
13
61
  </style>
62
+
14
63
  <script>
15
- document.querySelectorAll('.otp-wrap input').forEach((input, idx, inputs) => {
16
- input.addEventListener('input', () => {
17
- if ((input as HTMLInputElement).value && idx < inputs.length - 1) {
18
- (inputs[idx+1] as HTMLInputElement).focus();
19
- }
64
+ document.querySelectorAll('[data-otp-group]').forEach(group => {
65
+ const inputs = group.querySelectorAll('input') as NodeListOf<HTMLInputElement>;
66
+
67
+ inputs.forEach((input, idx) => {
68
+ // Auto-advance
69
+ input.addEventListener('input', (e) => {
70
+ const val = (e.target as HTMLInputElement).value;
71
+ if (val && idx < inputs.length - 1) {
72
+ inputs[idx + 1].focus();
73
+ }
74
+ });
75
+
76
+ // Backspace logic
77
+ input.addEventListener('keydown', (e) => {
78
+ if (e.key === 'Backspace' && !input.value && idx > 0) {
79
+ inputs[idx - 1].focus();
80
+ }
81
+ });
82
+
83
+ // Paste logic
84
+ input.addEventListener('paste', (e) => {
85
+ e.preventDefault();
86
+ const data = e.clipboardData?.getData('text').slice(0, inputs.length).split('') || [];
87
+ data.forEach((val, i) => {
88
+ if (inputs[i]) inputs[i].value = val;
89
+ });
90
+ if (inputs[data.length - 1]) inputs[data.length - 1].focus();
91
+ });
20
92
  });
21
93
  });
22
94
  </script>
@@ -1,15 +1,71 @@
1
1
  ---
2
+ /**
3
+ * RatingStars — A classic star-rating input for user reviews and feedback.
4
+ *
5
+ * @param {string} name - HTML name for form submission. Default is "rating".
6
+ * @param {number} maxRating - Maximum number of stars. Default is 5.
7
+ * @param {string} idPrefix - Prefix used to generate unique IDs for radio buttons.
8
+ * @param {number} initialValue - Currently selected rating.
9
+ */
10
+ interface Props {
11
+ name?: string;
12
+ maxRating?: number;
13
+ idPrefix?: string;
14
+ initialValue?: number;
15
+ }
16
+
17
+ const { name = "rating", maxRating = 5, idPrefix = "star", initialValue = 0 } = Astro.props;
2
18
  ---
3
- <div class="rating">
4
- <input type="radio" name="star" id="star5" /><label for="star5"></label>
5
- <input type="radio" name="star" id="star4" /><label for="star4"></label>
6
- <input type="radio" name="star" id="star3" /><label for="star3"></label>
7
- <input type="radio" name="star" id="star2" /><label for="star2"></label>
8
- <input type="radio" name="star" id="star1" /><label for="star1"></label>
19
+
20
+ <div class="rating-stars" data-rating-group>
21
+ {Array.from({ length: maxRating }).map((_, i) => {
22
+ const val = maxRating - i;
23
+ return (
24
+ <>
25
+ <input
26
+ type="radio"
27
+ name={name}
28
+ id={`${idPrefix}-${val}`}
29
+ value={val}
30
+ checked={initialValue === val}
31
+ class="rating-stars__input"
32
+ />
33
+ <label for={`${idPrefix}-${val}`} class="rating-stars__star" aria-label={`${val} stars`}>
34
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
35
+ <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
36
+ </svg>
37
+ </label>
38
+ </>
39
+ );
40
+ })}
9
41
  </div>
42
+
10
43
  <style>
11
- .rating { display: flex; flex-direction: row-reverse; gap: 5px; }
12
- .rating input { display: none; }
13
- .rating label { width: 24px; height: 24px; background: #334155; clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%); cursor: pointer; transition: 0.2s; }
14
- .rating label:hover, .rating label:hover ~ label, .rating input:checked ~ label { background: #fbbf24; box-shadow: 0 0 10px #fbbf24; }
44
+ .rating-stars { display: flex; flex-direction: row-reverse; gap: 4px; width: fit-content; }
45
+
46
+ .rating-stars__input { display: none; }
47
+
48
+ .rating-stars__star {
49
+ width: 32px; height: 32px;
50
+ cursor: pointer; transition: all 0.2s ease;
51
+ color: var(--c-border, #334155);
52
+ }
53
+
54
+ .rating-stars__star svg { width: 100%; height: 100%; fill: transparent; transition: all 0.2s; }
55
+
56
+ /* Hover and check logic using sibling selectors (requires row-reverse) */
57
+ .rating-stars__star:hover,
58
+ .rating-stars__star:hover ~ .rating-stars__star,
59
+ .rating-stars__input:checked ~ .rating-stars__star {
60
+ color: #fbbf24;
61
+ }
62
+
63
+ .rating-stars__star:hover svg,
64
+ .rating-stars__star:hover ~ .rating-stars__star svg,
65
+ .rating-stars__input:checked ~ .rating-stars__star svg {
66
+ fill: #fbbf24;
67
+ filter: drop-shadow(0 0 5px rgba(251, 191, 36, 0.4));
68
+ }
69
+
70
+ .rating-stars__star:active { transform: scale(0.9); }
15
71
  </style>
@@ -1,13 +1,51 @@
1
1
  ---
2
+ /**
3
+ * SearchReveal — A dynamic minimal search pod that expands smoothly into a full input field on hover or focus.
4
+ *
5
+ * @param {string} id - Standard HTML ID property.
6
+ * @param {string} placeholder - Default placeholder ("Search...").
7
+ * @param {string} name - Standard HTML name grouping.
8
+ */
9
+ interface Props {
10
+ id: string;
11
+ placeholder?: string;
12
+ name?: string;
13
+ }
14
+
15
+ const { id, placeholder = "Search...", name } = Astro.props;
2
16
  ---
17
+
3
18
  <div class="search-box">
4
- <input type="text" placeholder="Search..." />
5
- <button>🔍</button>
19
+ <input type="search" {id} {name} {placeholder} class="search-input" aria-label="Search content" />
20
+ <button type="button" aria-label="Submit search" class="search-btn">
21
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
22
+ <circle cx="11" cy="11" r="8"></circle>
23
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
24
+ </svg>
25
+ </button>
6
26
  </div>
27
+
7
28
  <style>
8
- .search-box { position: relative; width: 40px; height: 40px; transition: 0.4s; }
29
+ .search-box { position: relative; width: 44px; height: 44px; transition: 0.4s cubic-bezier(0.4, 0, 0.2, 1); }
9
30
  .search-box:hover, .search-box:focus-within { width: 250px; }
10
- .search-box input { width: 100%; height: 100%; background: #1e293b; border: 1px solid rgba(255,255,255,0.1); border-radius: 100px; padding: 0 45px 0 20px; color: #fff; outline: none; opacity: 0; transition: 0.3s; }
11
- .search-box:hover input, .search-box:focus-within input { opacity: 1; }
12
- .search-box button { position: absolute; right: 0; width: 40px; height: 40px; background: #6366f1; border: none; border-radius: 50%; color: #fff; cursor: pointer; }
31
+ .search-input {
32
+ width: 100%; height: 100%; box-sizing: border-box;
33
+ background: var(--c-bg-elev, #1e293b);
34
+ border: 1px solid var(--c-border, rgba(255,255,255,0.1));
35
+ border-radius: var(--r-full, 100px);
36
+ padding: 0 45px 0 20px;
37
+ color: var(--c-text-1, #fff); outline: none; opacity: 0; transition: 0.3s;
38
+ }
39
+ .search-box:hover .search-input, .search-box:focus-within .search-input { opacity: 1; }
40
+ .search-input::placeholder { color: var(--c-text-muted, #64748b); }
41
+
42
+ .search-btn {
43
+ position: absolute; right: 0; top: 0;
44
+ width: 44px; height: 44px;
45
+ background: var(--c-primary, #6366f1); border: none;
46
+ border-radius: 50%; color: #fff; cursor: pointer;
47
+ display: flex; align-items: center; justify-content: center;
48
+ transition: background 0.2s;
49
+ }
50
+ .search-btn:hover { background: var(--c-primary-light, #818cf8); }
13
51
  </style>
@@ -1,13 +1,67 @@
1
1
  ---
2
+ /**
3
+ * SegmentedControl — A horizontal group of button-like radio choices for switching views or modes.
4
+ *
5
+ * @param {string} name - Shared HTML name for the internal radio inputs.
6
+ * @param {Array<{label: string, value: string, checked?: boolean}>} options - Selectable segments.
7
+ * @param {string} idPrefix - Prefix for auto-generating input IDs.
8
+ */
9
+ interface Props {
10
+ name: string;
11
+ options: Array<{ label: string; value: string; checked?: boolean }>;
12
+ idPrefix?: string;
13
+ }
14
+
15
+ const { name, options = [], idPrefix = "seg" } = Astro.props;
2
16
  ---
17
+
3
18
  <div class="segmented">
4
- <input type="radio" name="seg" id="seg1" checked /><label for="seg1">Daily</label>
5
- <input type="radio" name="seg" id="seg2" /><label for="seg2">Weekly</label>
6
- <input type="radio" name="seg" id="seg3" /><label for="seg3">Monthly</label>
19
+ {options.map((opt, i) => (
20
+ <div class="segmented-item">
21
+ <input
22
+ type="radio"
23
+ name={name}
24
+ id={`${idPrefix}-${i}`}
25
+ value={opt.value}
26
+ checked={opt.checked}
27
+ class="segmented-input"
28
+ />
29
+ <label for={`${idPrefix}-${i}`} class="segmented-label">{opt.label}</label>
30
+ </div>
31
+ ))}
7
32
  </div>
33
+
8
34
  <style>
9
- .segmented { display: flex; position: relative; background: rgba(255,255,255,0.05); padding: 4px; border-radius: 10px; width: fit-content; }
10
- .segmented label { padding: 0.4rem 1.2rem; cursor: pointer; z-index: 1; font-size: 0.85rem; transition: 0.3s; color: #94a3b8; }
11
- .segmented input { display: none; }
12
- .segmented input:checked + label { color: #fff; font-weight: 600; background: rgba(99, 102, 241, 0.2); border-radius: 6px; }
35
+ .segmented {
36
+ display: flex; position: relative;
37
+ background: var(--c-bg-elev, rgba(255,255,255,0.05));
38
+ padding: 4px; border-radius: var(--r-md, 12px);
39
+ width: fit-content; border: 1px solid var(--c-border, rgba(255,255,255,0.05));
40
+ box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
41
+ }
42
+
43
+ .segmented-item { display: flex; }
44
+
45
+ .segmented-label {
46
+ padding: 0.5rem 1.4rem; cursor: pointer; z-index: 1;
47
+ font-size: 0.85rem; transition: all 0.25s ease;
48
+ color: var(--c-text-2, #94a3b8);
49
+ border-radius: var(--r-sm, 8px);
50
+ font-weight: 500;
51
+ user-select: none;
52
+ }
53
+
54
+ .segmented-input { display: none; }
55
+
56
+ .segmented-input:checked + .segmented-label {
57
+ color: var(--c-text-1, #fff);
58
+ font-weight: 700;
59
+ background: var(--c-primary, #6366f1);
60
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
61
+ }
62
+
63
+ .segmented-label:hover:not(.segmented-input:checked + .segmented-label) {
64
+ color: var(--c-text-1);
65
+ background: rgba(255,255,255,0.03);
66
+ }
13
67
  </style>
@@ -1,11 +1,62 @@
1
1
  ---
2
+ /**
3
+ * SimpleFileInput — A minimalist file upload button that masks the native browser input.
4
+ *
5
+ * @param {string} label - The text displayed on the button. Default is "Choose File".
6
+ * @param {string} id - HTML ID for the file input.
7
+ * @param {string} name - HTML name binding.
8
+ * @param {string} accept - Allowed file formats.
9
+ */
10
+ interface Props {
11
+ label?: string;
12
+ id: string;
13
+ name?: string;
14
+ accept?: string;
15
+ }
16
+
17
+ const { label = "Choose File", id, name, accept } = Astro.props;
2
18
  ---
3
- <label class="file-btn">
4
- <input type="file" />
5
- <span>Upload Logo</span>
19
+
20
+ <label class="file-btn" for={id}>
21
+ <input type="file" {id} {name} {accept} class="file-btn__input" />
22
+ <span class="file-btn__label">{label}</span>
6
23
  </label>
24
+
7
25
  <style>
8
- .file-btn { position: relative; overflow: hidden; display: inline-block; cursor: pointer; }
9
- .file-btn input { position: absolute; font-size: 100px; right: 0; top: 0; opacity: 0; cursor: pointer; }
10
- .file-btn span { background: #6366f1; color: #fff; padding: 0.7rem 1.5rem; border-radius: 8px; font-weight: 600; display: inline-block; }
26
+ .file-btn {
27
+ position: relative;
28
+ overflow: hidden;
29
+ display: inline-block;
30
+ cursor: pointer;
31
+ }
32
+
33
+ .file-btn__input {
34
+ position: absolute;
35
+ left: 0; top: 0;
36
+ width: 100%; height: 100%;
37
+ opacity: 0; cursor: pointer;
38
+ font-size: 0;
39
+ }
40
+
41
+ .file-btn__label {
42
+ background: var(--c-primary, #6366f1);
43
+ color: #fff;
44
+ padding: 0.8rem 1.6rem;
45
+ border-radius: var(--r-md, 10px);
46
+ font-weight: 700;
47
+ display: inline-block;
48
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
49
+ box-shadow: 0 4px 15px rgba(99, 102, 241, 0.2);
50
+ font-size: 0.95rem;
51
+ }
52
+
53
+ .file-btn:hover .file-btn__label {
54
+ filter: brightness(1.1);
55
+ transform: translateY(-2px);
56
+ box-shadow: 0 6px 20px rgba(99, 102, 241, 0.3);
57
+ }
58
+
59
+ .file-btn:active .file-btn__label {
60
+ transform: translateY(0);
61
+ }
11
62
  </style>
@@ -1,14 +1,106 @@
1
1
  ---
2
+ /**
3
+ * StepperInput — A numeric input with increment and decrement buttons for precise control.
4
+ *
5
+ * @param {string} label - Optional input label.
6
+ * @param {string} id - HTML ID for the number input.
7
+ * @param {string} name - HTML name binding.
8
+ * @param {number} value - Initial default value. Default is 1.
9
+ * @param {number} min - Minimum allowed value.
10
+ * @param {number} max - Maximum allowed value.
11
+ * @param {number} step - Numeric increment step. Default is 1.
12
+ */
13
+ interface Props {
14
+ label?: string;
15
+ id: string;
16
+ name?: string;
17
+ value?: number;
18
+ min?: number;
19
+ max?: number;
20
+ step?: number;
21
+ }
22
+
23
+ const { label, id, name, value = 1, min, max, step = 1 } = Astro.props;
2
24
  ---
3
- <div class="stepper">
4
- <button>-</button>
5
- <input type="number" value="1" />
6
- <button>+</button>
25
+
26
+ <div class="stepper-container">
27
+ {label && <label class="stepper-label" for={id}>{label}</label>}
28
+ <div class="stepper" data-stepper>
29
+ <button type="button" class="stepper-btn stepper-btn--minus" data-step-minus aria-label="Decrease value">−</button>
30
+ <input
31
+ type="number"
32
+ {id}
33
+ {name}
34
+ {min}
35
+ {max}
36
+ {step}
37
+ value={value}
38
+ class="stepper-input"
39
+ data-step-input
40
+ />
41
+ <button type="button" class="stepper-btn stepper-btn--plus" data-step-plus aria-label="Increase value">+</button>
42
+ </div>
7
43
  </div>
44
+
8
45
  <style>
9
- .stepper { display: flex; align-items: center; gap: 2px; }
10
- .stepper button { width: 35px; height: 35px; background: #6366f1; border: none; color: #fff; font-size: 1.2rem; cursor: pointer; transition: 0.2s; }
11
- .stepper button:hover { background: #4f46e5; }
12
- .stepper input { width: 50px; height: 35px; background: rgba(255,255,255,0.05); border: none; text-align: center; color: #fff; outline: none; -moz-appearance: textfield; }
13
- .stepper input::-webkit-inner-spin-button { display: none; }
46
+ .stepper-container { display: flex; flex-direction: column; gap: var(--sp-2, 0.5rem); }
47
+ .stepper-label { font-size: 0.85rem; font-weight: 600; color: var(--c-text-2, #94a3b8); margin-left: 0.5rem; }
48
+
49
+ .stepper {
50
+ display: flex; align-items: center;
51
+ background: var(--c-bg-elev, rgba(255,255,255,0.05));
52
+ border-radius: var(--r-md, 12px);
53
+ border: 1px solid var(--c-border, rgba(255,255,255,0.1));
54
+ overflow: hidden;
55
+ width: fit-content;
56
+ }
57
+
58
+ .stepper-btn {
59
+ width: 40px; height: 40px;
60
+ background: var(--c-primary, #6366f1);
61
+ border: none; color: #fff;
62
+ font-size: 1.25rem; font-weight: 600;
63
+ cursor: pointer; transition: all 0.2s;
64
+ display: grid; place-items: center;
65
+ }
66
+
67
+ .stepper-btn:hover { background: var(--c-primary-light, #818cf8); }
68
+ .stepper-btn:active { transform: scale(0.95); }
69
+
70
+ .stepper-input {
71
+ width: 60px; height: 40px;
72
+ background: transparent;
73
+ border: none; text-align: center;
74
+ color: var(--c-text-1, #fff);
75
+ font-size: 1rem; font-weight: 700;
76
+ outline: none; -moz-appearance: textfield;
77
+ font-family: inherit;
78
+ }
79
+
80
+ .stepper-input::-webkit-inner-spin-button,
81
+ .stepper-input::-webkit-outer-spin-button { display: none; }
14
82
  </style>
83
+
84
+ <script>
85
+ document.querySelectorAll('[data-stepper]').forEach(wrapper => {
86
+ const input = wrapper.querySelector('[data-step-input]') as HTMLInputElement;
87
+ const minus = wrapper.querySelector('[data-step-minus]');
88
+ const plus = wrapper.querySelector('[data-step-plus]');
89
+
90
+ if (!input || !minus || !plus) return;
91
+
92
+ const step = parseFloat(input.step) || 1;
93
+ const min = input.min !== "" ? parseFloat(input.min) : -Infinity;
94
+ const max = input.max !== "" ? parseFloat(input.max) : Infinity;
95
+
96
+ minus.addEventListener('click', () => {
97
+ const current = parseFloat(input.value) || 0;
98
+ if (current - step >= min) input.value = (current - step).toString();
99
+ });
100
+
101
+ plus.addEventListener('click', () => {
102
+ const current = parseFloat(input.value) || 0;
103
+ if (current + step <= max) input.value = (current + step).toString();
104
+ });
105
+ });
106
+ </script>