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.
- package/LICENSE +21 -0
- package/README.md +57 -2
- package/dist/Accordion.d.ts +52 -0
- package/dist/Accordion.js +192 -0
- package/dist/AchievementToast.d.ts +36 -0
- package/dist/AchievementToast.js +162 -0
- package/dist/AgentCard.d.ts +41 -0
- package/dist/AgentCard.js +168 -0
- package/dist/ArcadeButtons.d.ts +23 -0
- package/dist/ArcadeButtons.js +169 -0
- package/dist/AuroraBands.d.ts +19 -0
- package/dist/AuroraBands.js +126 -0
- package/dist/AvatarTooltips.d.ts +32 -0
- package/dist/AvatarTooltips.js +121 -0
- package/dist/BarRace.d.ts +39 -0
- package/dist/BarRace.js +227 -0
- package/dist/BentoGrid.d.ts +50 -0
- package/dist/BentoGrid.js +145 -0
- package/dist/BootSequence.d.ts +48 -0
- package/dist/BootSequence.js +234 -0
- package/dist/BreadcrumbTrail.d.ts +31 -0
- package/dist/BreadcrumbTrail.js +181 -0
- package/dist/CRTPower.d.ts +30 -0
- package/dist/CRTPower.js +142 -0
- package/dist/CardDeck.d.ts +29 -0
- package/dist/CardDeck.js +154 -0
- package/dist/ChangelogTimeline.d.ts +35 -0
- package/dist/ChangelogTimeline.js +137 -0
- package/dist/ChapterProgress.d.ts +23 -0
- package/dist/ChapterProgress.js +211 -0
- package/dist/ChatBubbles.d.ts +42 -0
- package/dist/ChatBubbles.js +198 -0
- package/dist/ChiptuneKit.d.ts +158 -0
- package/dist/ChiptuneKit.js +207 -0
- package/dist/CipherCard.d.ts +22 -0
- package/dist/CipherCard.js +91 -0
- package/dist/CloudSky.d.ts +28 -0
- package/dist/CloudSky.js +222 -0
- package/dist/CodeRain.d.ts +24 -0
- package/dist/CodeRain.js +158 -0
- package/dist/CodeShowcase.d.ts +50 -0
- package/dist/CodeShowcase.js +307 -0
- package/dist/ColorDial.d.ts +42 -0
- package/dist/ColorDial.js +288 -0
- package/dist/CommandPalette.d.ts +59 -0
- package/dist/CommandPalette.js +349 -0
- package/dist/CompareSlider.d.ts +33 -0
- package/dist/CompareSlider.js +152 -0
- package/dist/Confetti.d.ts +61 -0
- package/dist/Confetti.js +176 -0
- package/dist/ConnectBeams.d.ts +39 -0
- package/dist/ConnectBeams.js +132 -0
- package/dist/ContextOrb.d.ts +34 -0
- package/dist/ContextOrb.js +269 -0
- package/dist/ContourLines.d.ts +20 -0
- package/dist/ContourLines.js +159 -0
- package/dist/Coverflow.d.ts +27 -0
- package/dist/Coverflow.js +167 -0
- package/dist/CursorAttractor.d.ts +21 -0
- package/dist/CursorAttractor.js +136 -0
- package/dist/CutReveal.d.ts +21 -0
- package/dist/CutReveal.js +116 -0
- package/dist/DateRange.d.ts +45 -0
- package/dist/DateRange.js +327 -0
- package/dist/DeviceFrame.d.ts +30 -0
- package/dist/DeviceFrame.js +145 -0
- package/dist/DiffReveal.d.ts +36 -0
- package/dist/DiffReveal.js +247 -0
- package/dist/DirectionHover.d.ts +15 -0
- package/dist/DirectionHover.js +90 -0
- package/dist/Discard.d.ts +18 -0
- package/dist/Discard.js +61 -0
- package/dist/DitherField.d.ts +15 -0
- package/dist/DitherField.js +157 -0
- package/dist/DotGlobe.d.ts +48 -0
- package/dist/DotGlobe.js +312 -0
- package/dist/DotMap.d.ts +47 -0
- package/dist/DotMap.js +172 -0
- package/dist/DropZone.d.ts +57 -0
- package/dist/DropZone.js +304 -0
- package/dist/DynamicIsland.d.ts +32 -0
- package/dist/DynamicIsland.js +92 -0
- package/dist/EdgeFX.d.ts +27 -0
- package/dist/EdgeFX.js +98 -0
- package/dist/ElasticString.d.ts +22 -0
- package/dist/ElasticString.js +127 -0
- package/dist/ExpandCard.d.ts +44 -0
- package/dist/ExpandCard.js +182 -0
- package/dist/FeatureTabs.d.ts +34 -0
- package/dist/FeatureTabs.js +169 -0
- package/dist/FeedList.d.ts +37 -0
- package/dist/FeedList.js +163 -0
- package/dist/FlickerGrid.d.ts +29 -0
- package/dist/FlickerGrid.js +156 -0
- package/dist/FocusGrid.d.ts +20 -0
- package/dist/FocusGrid.js +48 -0
- package/dist/FocusPull.d.ts +26 -0
- package/dist/FocusPull.js +106 -0
- package/dist/Footprints.d.ts +24 -0
- package/dist/Footprints.js +126 -0
- package/dist/FunnelFlow.d.ts +34 -0
- package/dist/FunnelFlow.js +267 -0
- package/dist/GameOver.d.ts +46 -0
- package/dist/GameOver.js +191 -0
- package/dist/GaugeMeter.d.ts +38 -0
- package/dist/GaugeMeter.js +195 -0
- package/dist/GlassPanel.d.ts +27 -0
- package/dist/GlassPanel.js +80 -0
- package/dist/GrainFX.d.ts +34 -0
- package/dist/GrainFX.js +122 -0
- package/dist/GravityBox.d.ts +30 -0
- package/dist/GravityBox.js +220 -0
- package/dist/HealthBar.d.ts +33 -0
- package/dist/HealthBar.js +140 -0
- package/dist/Heatmap.d.ts +42 -0
- package/dist/Heatmap.js +232 -0
- package/dist/HexField.d.ts +29 -0
- package/dist/HexField.js +188 -0
- package/dist/HoldToConfirm.d.ts +29 -0
- package/dist/HoldToConfirm.js +163 -0
- package/dist/HorizontalTrack.d.ts +28 -0
- package/dist/HorizontalTrack.js +195 -0
- package/dist/HotbarDock.d.ts +40 -0
- package/dist/HotbarDock.js +148 -0
- package/dist/InkText.d.ts +27 -0
- package/dist/InkText.js +65 -0
- package/dist/InlineEdit.d.ts +30 -0
- package/dist/InlineEdit.js +198 -0
- package/dist/InteractiveGrid.d.ts +25 -0
- package/dist/InteractiveGrid.js +194 -0
- package/dist/InventoryGrid.d.ts +45 -0
- package/dist/InventoryGrid.js +272 -0
- package/dist/JellyBlob.d.ts +30 -0
- package/dist/JellyBlob.js +209 -0
- package/dist/KineticHeadline.d.ts +30 -0
- package/dist/KineticHeadline.js +133 -0
- package/dist/LavaLamp.d.ts +21 -0
- package/dist/LavaLamp.js +133 -0
- package/dist/LetterSwap.d.ts +20 -0
- package/dist/LetterSwap.js +78 -0
- package/dist/LevelMap.d.ts +35 -0
- package/dist/LevelMap.js +189 -0
- package/dist/LightShafts.d.ts +22 -0
- package/dist/LightShafts.js +170 -0
- package/dist/LightboxGallery.d.ts +26 -0
- package/dist/LightboxGallery.js +327 -0
- package/dist/LinkPeek.d.ts +36 -0
- package/dist/LinkPeek.js +194 -0
- package/dist/LogoOrbit.d.ts +37 -0
- package/dist/LogoOrbit.js +117 -0
- package/dist/Marquee.d.ts +33 -0
- package/dist/Marquee.js +148 -0
- package/dist/MarqueeLine.d.ts +33 -0
- package/dist/MarqueeLine.js +167 -0
- package/dist/MasonryWall.d.ts +13 -0
- package/dist/MasonryWall.js +90 -0
- package/dist/MegaMenu.d.ts +32 -0
- package/dist/MegaMenu.js +280 -0
- package/dist/MeteorShower.d.ts +24 -0
- package/dist/MeteorShower.js +155 -0
- package/dist/Minimap.d.ts +21 -0
- package/dist/Minimap.js +236 -0
- package/dist/MobileTabBar.d.ts +38 -0
- package/dist/MobileTabBar.js +148 -0
- package/dist/MorphDialog.d.ts +34 -0
- package/dist/MorphDialog.js +199 -0
- package/dist/MorphPopover.d.ts +33 -0
- package/dist/MorphPopover.js +168 -0
- package/dist/MorphWords.d.ts +18 -0
- package/dist/MorphWords.js +136 -0
- package/dist/OTPInput.d.ts +43 -0
- package/dist/OTPInput.js +174 -0
- package/dist/OverlayKit.d.ts +97 -0
- package/dist/OverlayKit.js +466 -0
- package/dist/OverlayMenu.d.ts +32 -0
- package/dist/OverlayMenu.js +154 -0
- package/dist/ParallaxCollage.d.ts +41 -0
- package/dist/ParallaxCollage.js +143 -0
- package/dist/PasswordMeter.d.ts +44 -0
- package/dist/PasswordMeter.js +165 -0
- package/dist/PegBoard.d.ts +26 -0
- package/dist/PegBoard.js +184 -0
- package/dist/PinCard.d.ts +21 -0
- package/dist/PinCard.js +84 -0
- package/dist/PixelAvatar.d.ts +33 -0
- package/dist/PixelAvatar.js +144 -0
- package/dist/PixelButton.d.ts +20 -0
- package/dist/PixelButton.js +128 -0
- package/dist/PixelExplode.d.ts +31 -0
- package/dist/PixelExplode.js +164 -0
- package/dist/PixelLoader.d.ts +32 -0
- package/dist/PixelLoader.js +142 -0
- package/dist/PixelParallax.d.ts +41 -0
- package/dist/PixelParallax.js +151 -0
- package/dist/PixelSpinners.d.ts +21 -0
- package/dist/PixelSpinners.js +110 -0
- package/dist/PixelType.d.ts +26 -0
- package/dist/PixelType.js +220 -0
- package/dist/PointerKit.d.ts +23 -0
- package/dist/PointerKit.js +222 -0
- package/dist/Polaroids.d.ts +41 -0
- package/dist/Polaroids.js +293 -0
- package/dist/PressStart.d.ts +28 -0
- package/dist/PressStart.js +99 -0
- package/dist/PricingFlip.d.ts +52 -0
- package/dist/PricingFlip.js +190 -0
- package/dist/ProximityType.d.ts +26 -0
- package/dist/ProximityType.js +135 -0
- package/dist/QuestDialog.d.ts +50 -0
- package/dist/QuestDialog.js +204 -0
- package/dist/QuestLog.d.ts +39 -0
- package/dist/QuestLog.js +214 -0
- package/dist/RangeDual.d.ts +34 -0
- package/dist/RangeDual.js +238 -0
- package/dist/RatingPips.d.ts +25 -0
- package/dist/RatingPips.js +129 -0
- package/dist/RetroHorizon.d.ts +27 -0
- package/dist/RetroHorizon.js +169 -0
- package/dist/Reveal.d.ts +30 -0
- package/dist/Reveal.js +92 -0
- package/dist/RingProgress.d.ts +45 -0
- package/dist/RingProgress.js +180 -0
- package/dist/RollingNumber.d.ts +28 -0
- package/dist/RollingNumber.js +108 -0
- package/dist/ScanScope.d.ts +24 -0
- package/dist/ScanScope.js +164 -0
- package/dist/ScoreTicker.d.ts +32 -0
- package/dist/ScoreTicker.js +176 -0
- package/dist/ScreenScroller.d.ts +24 -0
- package/dist/ScreenScroller.js +138 -0
- package/dist/Screensaver.d.ts +31 -0
- package/dist/Screensaver.js +221 -0
- package/dist/ScrollTilt.d.ts +27 -0
- package/dist/ScrollTilt.js +100 -0
- package/dist/ScrollTypography.d.ts +26 -0
- package/dist/ScrollTypography.js +124 -0
- package/dist/ScrollZoom.d.ts +31 -0
- package/dist/ScrollZoom.js +123 -0
- package/dist/ScrubNumber.d.ts +29 -0
- package/dist/ScrubNumber.js +152 -0
- package/dist/ShadowStack.d.ts +28 -0
- package/dist/ShadowStack.js +116 -0
- package/dist/SideRail.d.ts +43 -0
- package/dist/SideRail.js +253 -0
- package/dist/SignalText.d.ts +25 -0
- package/dist/SignalText.js +178 -0
- package/dist/SkeletonShimmer.d.ts +18 -0
- package/dist/SkeletonShimmer.js +111 -0
- package/dist/SketchHighlight.d.ts +27 -0
- package/dist/SketchHighlight.js +180 -0
- package/dist/SlideTabs.d.ts +40 -0
- package/dist/SlideTabs.js +190 -0
- package/dist/SmartNavbar.d.ts +48 -0
- package/dist/SmartNavbar.js +188 -0
- package/dist/SparkChart.d.ts +41 -0
- package/dist/SparkChart.js +188 -0
- package/dist/Spoiler.d.ts +22 -0
- package/dist/Spoiler.js +97 -0
- package/dist/SpotlightTour.d.ts +38 -0
- package/dist/SpotlightTour.js +231 -0
- package/dist/SpringDrawer.d.ts +39 -0
- package/dist/SpringDrawer.js +360 -0
- package/dist/SpriteAnimator.d.ts +41 -0
- package/dist/SpriteAnimator.js +124 -0
- package/dist/StatCard.d.ts +43 -0
- package/dist/StatCard.js +168 -0
- package/dist/StepLoader.d.ts +41 -0
- package/dist/StepLoader.js +191 -0
- package/dist/StepperForm.d.ts +41 -0
- package/dist/StepperForm.js +206 -0
- package/dist/StickerBoard.d.ts +39 -0
- package/dist/StickerBoard.js +209 -0
- package/dist/StickyReveal.d.ts +42 -0
- package/dist/StickyReveal.js +181 -0
- package/dist/StoryViewer.d.ts +36 -0
- package/dist/StoryViewer.js +175 -0
- package/dist/StreamingText.d.ts +29 -0
- package/dist/StreamingText.js +271 -0
- package/dist/SuggestionChips.d.ts +32 -0
- package/dist/SuggestionChips.js +96 -0
- package/dist/SwipeActions.d.ts +30 -0
- package/dist/SwipeActions.js +141 -0
- package/dist/TagInput.d.ts +30 -0
- package/dist/TagInput.js +284 -0
- package/dist/TallyUp.d.ts +38 -0
- package/dist/TallyUp.js +157 -0
- package/dist/TerminalDemo.d.ts +63 -0
- package/dist/TerminalDemo.js +214 -0
- package/dist/TestimonialWall.d.ts +35 -0
- package/dist/TestimonialWall.js +131 -0
- package/dist/TextOnPath.d.ts +36 -0
- package/dist/TextOnPath.js +130 -0
- package/dist/ThinkingShimmer.d.ts +36 -0
- package/dist/ThinkingShimmer.js +132 -0
- package/dist/ToastStack.d.ts +62 -0
- package/dist/ToastStack.js +289 -0
- package/dist/ToggleGroup.d.ts +39 -0
- package/dist/ToggleGroup.js +190 -0
- package/dist/ToggleKit.d.ts +70 -0
- package/dist/ToggleKit.js +229 -0
- package/dist/TracingLine.d.ts +24 -0
- package/dist/TracingLine.js +139 -0
- package/dist/TradingCard.d.ts +30 -0
- package/dist/TradingCard.js +147 -0
- package/dist/VanishInput.d.ts +34 -0
- package/dist/VanishInput.js +190 -0
- package/dist/VideoHero.d.ts +32 -0
- package/dist/VideoHero.js +207 -0
- package/dist/VoiceOrb.d.ts +23 -0
- package/dist/VoiceOrb.js +182 -0
- package/dist/VoxelTiles.d.ts +38 -0
- package/dist/VoxelTiles.js +201 -0
- package/dist/WarpField.d.ts +18 -0
- package/dist/WarpField.js +160 -0
- package/dist/WebcamPixels.d.ts +38 -0
- package/dist/WebcamPixels.js +292 -0
- package/dist/WheelPicker.d.ts +29 -0
- package/dist/WheelPicker.js +199 -0
- package/dist/WobbleCard.d.ts +23 -0
- package/dist/WobbleCard.js +112 -0
- package/dist/index.d.ts +158 -0
- package/dist/index.js +159 -0
- package/package.json +58 -4
package/dist/TagInput.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useInsertionEffect, useRef, useState } from "react";
|
|
4
|
+
const STYLE_ID = "bl-tag-input";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.bl-tags { position: relative; width: 100%; max-width: var(--bl-w); font-family: var(--bl-font); color: var(--bl-ink); }
|
|
7
|
+
.bl-tags__label { display: block; margin-bottom: 6px; color: var(--bl-muted); font-size: 13px; font-weight: 600; }
|
|
8
|
+
.bl-tags__field { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 44px; padding: 6px 8px; box-sizing: border-box; border-radius: var(--bl-radius); background: var(--bl-bg); box-shadow: inset 0 0 0 1px var(--bl-line); cursor: text; transition: box-shadow 150ms; }
|
|
9
|
+
.bl-tags__field:focus-within { box-shadow: inset 0 0 0 2px var(--bl-accent); }
|
|
10
|
+
.bl-tags__field[data-invalid] { box-shadow: inset 0 0 0 2px var(--bl-error); }
|
|
11
|
+
.bl-tags__list { display: contents; margin: 0; padding: 0; list-style: none; }
|
|
12
|
+
.bl-tags__chip { display: inline-flex; align-items: center; gap: 4px; max-width: 100%; padding: 4px 4px 4px 10px; border-radius: 999px; background: var(--bl-chip); color: var(--bl-ink); font-size: 13px; font-weight: 600; animation: bl-tags-in 340ms cubic-bezier(.3,1.6,.5,1) both; }
|
|
13
|
+
.bl-tags__chip[data-selected] { box-shadow: 0 0 0 2px var(--bl-accent); }
|
|
14
|
+
.bl-tags__chip[data-leaving] { animation: bl-tags-out 180ms ease-in forwards; }
|
|
15
|
+
.bl-tags__chip[data-shake] { animation: bl-tags-shake 360ms ease; }
|
|
16
|
+
.bl-tags__text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
17
|
+
.bl-tags__x { display: grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--bl-muted); cursor: pointer; }
|
|
18
|
+
.bl-tags__x:hover { background: rgba(255,255,255,0.12); color: var(--bl-ink); }
|
|
19
|
+
.bl-tags__x:focus-visible { outline: 2px solid var(--bl-accent); }
|
|
20
|
+
.bl-tags__input { flex: 1 0 80px; min-width: 80px; height: 30px; padding: 0 4px; border: 0; background: transparent; color: inherit; font: inherit; font-size: 14px; outline: none; }
|
|
21
|
+
.bl-tags__input::placeholder { color: var(--bl-dim); }
|
|
22
|
+
.bl-tags__menu { position: absolute; left: 0; right: 0; top: calc(100% + 6px); z-index: 20; max-height: 220px; margin: 0; padding: 5px; overflow-y: auto; border-radius: var(--bl-radius); background: var(--bl-bg); box-shadow: 0 0 0 1px var(--bl-line), 0 18px 40px -18px rgba(0,0,0,0.85); list-style: none; animation: bl-tags-menu 160ms ease-out; }
|
|
23
|
+
.bl-tags__option { padding: 8px 10px; border-radius: calc(var(--bl-radius) * 0.6); font-size: 14px; cursor: pointer; }
|
|
24
|
+
.bl-tags__option[aria-selected="true"] { background: var(--bl-chip); }
|
|
25
|
+
.bl-tags__option mark { background: none; color: var(--bl-accent); font-weight: 700; }
|
|
26
|
+
.bl-tags__hint { min-height: 1.3em; margin: 6px 0 0; color: var(--bl-dim); font-size: 12px; }
|
|
27
|
+
.bl-tags__hint[data-error] { color: var(--bl-error); }
|
|
28
|
+
.bl-tags__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
29
|
+
@keyframes bl-tags-in { from { transform: scale(0.4); opacity: 0; } }
|
|
30
|
+
@keyframes bl-tags-out { to { transform: scale(0.4); opacity: 0; } }
|
|
31
|
+
@keyframes bl-tags-shake { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }
|
|
32
|
+
@keyframes bl-tags-menu { from { opacity: 0; transform: translateY(-4px); } }
|
|
33
|
+
@media (prefers-reduced-motion: reduce) { .bl-tags__chip, .bl-tags__chip[data-shake], .bl-tags__menu { animation: none; } .bl-tags__chip[data-leaving] { animation: bl-tags-fade 120ms forwards; } }
|
|
34
|
+
@keyframes bl-tags-fade { to { opacity: 0; } }
|
|
35
|
+
`;
|
|
36
|
+
function useStyles() {
|
|
37
|
+
useInsertionEffect(() => {
|
|
38
|
+
if (typeof document === "undefined") return;
|
|
39
|
+
const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
|
|
40
|
+
style.textContent = CSS;
|
|
41
|
+
if (!style.isConnected) document.head.appendChild(style);
|
|
42
|
+
}, []);
|
|
43
|
+
}
|
|
44
|
+
const SPLIT = /[,;\n\t]+/;
|
|
45
|
+
function TagInput({
|
|
46
|
+
value,
|
|
47
|
+
defaultValue = [],
|
|
48
|
+
onValueChange,
|
|
49
|
+
suggestions = [],
|
|
50
|
+
allowCustom = true,
|
|
51
|
+
max = Infinity,
|
|
52
|
+
validate,
|
|
53
|
+
label = "Tags",
|
|
54
|
+
placeholder = "Add a tag\u2026",
|
|
55
|
+
hint = "Enter or comma to add. Paste a list to add many.",
|
|
56
|
+
width = 520,
|
|
57
|
+
backgroundColor = "#1a1c2c",
|
|
58
|
+
chipColor = "#333c57",
|
|
59
|
+
textColor = "#f4f4f4",
|
|
60
|
+
mutedColor = "#94b0c2",
|
|
61
|
+
dimColor = "#566c86",
|
|
62
|
+
lineColor = "#333c57",
|
|
63
|
+
accentColor = "#73eff7",
|
|
64
|
+
errorColor = "#ef7d57",
|
|
65
|
+
radius = 12,
|
|
66
|
+
fontFamily = "ui-sans-serif, system-ui, sans-serif",
|
|
67
|
+
className = "",
|
|
68
|
+
style
|
|
69
|
+
}) {
|
|
70
|
+
useStyles();
|
|
71
|
+
const uid = useId().replace(/[^a-zA-Z0-9_-]/g, "");
|
|
72
|
+
const [inner, setInner] = useState(defaultValue);
|
|
73
|
+
const tags = value ?? inner;
|
|
74
|
+
const tagsRef = useRef(tags);
|
|
75
|
+
tagsRef.current = tags;
|
|
76
|
+
const [text, setText] = useState("");
|
|
77
|
+
const [open, setOpen] = useState(false);
|
|
78
|
+
const [highlight, setHighlight] = useState(0);
|
|
79
|
+
const [selected, setSelected] = useState(-1);
|
|
80
|
+
const [leaving, setLeaving] = useState([]);
|
|
81
|
+
const [shake, setShake] = useState(null);
|
|
82
|
+
const [error, setError] = useState("");
|
|
83
|
+
const [announce, setAnnounce] = useState("");
|
|
84
|
+
const inputRef = useRef(null);
|
|
85
|
+
const commit = (next) => {
|
|
86
|
+
if (value === void 0) setInner(next);
|
|
87
|
+
onValueChange?.(next);
|
|
88
|
+
};
|
|
89
|
+
const query = text.trim().toLowerCase();
|
|
90
|
+
const matches = suggestions.filter((s) => !tags.some((t) => t.toLowerCase() === s.toLowerCase()) && (!query || s.toLowerCase().includes(query))).slice(0, 8);
|
|
91
|
+
const showMenu = open && matches.length > 0 && (query.length > 0 || suggestions.length > 0);
|
|
92
|
+
const add = (raw) => {
|
|
93
|
+
const next = [...tags];
|
|
94
|
+
const added = [];
|
|
95
|
+
let problem = "";
|
|
96
|
+
for (const piece of raw) {
|
|
97
|
+
const tag = piece.trim();
|
|
98
|
+
if (!tag) continue;
|
|
99
|
+
const twin = next.findIndex((t) => t.toLowerCase() === tag.toLowerCase());
|
|
100
|
+
if (twin >= 0) {
|
|
101
|
+
setShake(next[twin]);
|
|
102
|
+
problem = `"${tag}" is already added.`;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!allowCustom && !suggestions.some((s) => s.toLowerCase() === tag.toLowerCase())) {
|
|
106
|
+
problem = `"${tag}" isn't one of the options.`;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const verdict = validate?.(tag);
|
|
110
|
+
if (verdict === false || typeof verdict === "string") {
|
|
111
|
+
problem = typeof verdict === "string" ? verdict : `"${tag}" isn't allowed.`;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (next.length >= max) {
|
|
115
|
+
problem = `You can add up to ${max}.`;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
const canonical = suggestions.find((s) => s.toLowerCase() === tag.toLowerCase()) ?? tag;
|
|
119
|
+
next.push(canonical);
|
|
120
|
+
added.push(canonical);
|
|
121
|
+
}
|
|
122
|
+
if (added.length) {
|
|
123
|
+
commit(next);
|
|
124
|
+
setAnnounce(`Added ${added.join(", ")}. ${next.length} tags.`);
|
|
125
|
+
}
|
|
126
|
+
setError(problem);
|
|
127
|
+
if (problem && !added.length) setAnnounce(problem);
|
|
128
|
+
return added.length > 0;
|
|
129
|
+
};
|
|
130
|
+
const remove = (index) => {
|
|
131
|
+
const tag = tags[index];
|
|
132
|
+
if (tag === void 0) return;
|
|
133
|
+
setSelected(-1);
|
|
134
|
+
setLeaving((list) => [...list, tag]);
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
setLeaving((list) => list.filter((t) => t !== tag));
|
|
137
|
+
const next = tagsRef.current.filter((t) => t !== tag);
|
|
138
|
+
tagsRef.current = next;
|
|
139
|
+
commit(next);
|
|
140
|
+
}, window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? 120 : 180);
|
|
141
|
+
setAnnounce(`Removed ${tag}.`);
|
|
142
|
+
setError("");
|
|
143
|
+
inputRef.current?.focus();
|
|
144
|
+
};
|
|
145
|
+
const onKeyDown = (event) => {
|
|
146
|
+
if (event.key === "ArrowDown" && matches.length) {
|
|
147
|
+
event.preventDefault();
|
|
148
|
+
setOpen(true);
|
|
149
|
+
setHighlight((h) => showMenu ? (h + 1) % matches.length : 0);
|
|
150
|
+
} else if (event.key === "ArrowUp" && showMenu) {
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
setHighlight((h) => (h - 1 + matches.length) % matches.length);
|
|
153
|
+
} else if (event.key === "Enter" || event.key === ",") {
|
|
154
|
+
if (event.key === "Enter" && showMenu && matches[highlight]) {
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
if (add([matches[highlight]])) setText("");
|
|
157
|
+
setHighlight(0);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (text.trim()) {
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
if (add([text])) setText("");
|
|
163
|
+
} else if (event.key === ",") event.preventDefault();
|
|
164
|
+
} else if (event.key === "Escape") {
|
|
165
|
+
setOpen(false);
|
|
166
|
+
setSelected(-1);
|
|
167
|
+
} else if (event.key === "Backspace" && !text) {
|
|
168
|
+
if (selected >= 0) remove(selected);
|
|
169
|
+
else if (tags.length) setSelected(tags.length - 1);
|
|
170
|
+
} else if (event.key === "ArrowLeft" && !text && tags.length) {
|
|
171
|
+
setSelected((s) => s < 0 ? tags.length - 1 : Math.max(0, s - 1));
|
|
172
|
+
} else if (event.key === "ArrowRight" && selected >= 0) {
|
|
173
|
+
setSelected((s) => s >= tags.length - 1 ? -1 : s + 1);
|
|
174
|
+
} else {
|
|
175
|
+
setSelected(-1);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const onPaste = (event) => {
|
|
179
|
+
const pasted = event.clipboardData.getData("text");
|
|
180
|
+
if (!SPLIT.test(pasted)) return;
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
add(pasted.split(SPLIT));
|
|
183
|
+
};
|
|
184
|
+
const mark = (option) => {
|
|
185
|
+
if (!query) return option;
|
|
186
|
+
const at = option.toLowerCase().indexOf(query);
|
|
187
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
188
|
+
option.slice(0, at),
|
|
189
|
+
/* @__PURE__ */ jsx("mark", { children: option.slice(at, at + query.length) }),
|
|
190
|
+
option.slice(at + query.length)
|
|
191
|
+
] });
|
|
192
|
+
};
|
|
193
|
+
return /* @__PURE__ */ jsxs(
|
|
194
|
+
"div",
|
|
195
|
+
{
|
|
196
|
+
className: `bl-tags ${className}`,
|
|
197
|
+
style: {
|
|
198
|
+
"--bl-w": `${width}px`,
|
|
199
|
+
"--bl-bg": backgroundColor,
|
|
200
|
+
"--bl-chip": chipColor,
|
|
201
|
+
"--bl-ink": textColor,
|
|
202
|
+
"--bl-muted": mutedColor,
|
|
203
|
+
"--bl-dim": dimColor,
|
|
204
|
+
"--bl-line": lineColor,
|
|
205
|
+
"--bl-accent": accentColor,
|
|
206
|
+
"--bl-error": errorColor,
|
|
207
|
+
"--bl-radius": `${radius}px`,
|
|
208
|
+
"--bl-font": fontFamily,
|
|
209
|
+
...style
|
|
210
|
+
},
|
|
211
|
+
children: [
|
|
212
|
+
/* @__PURE__ */ jsx("label", { className: "bl-tags__label", htmlFor: `${uid}-input`, children: label }),
|
|
213
|
+
/* @__PURE__ */ jsxs("div", { className: "bl-tags__field", "data-invalid": error ? "" : void 0, onClick: () => inputRef.current?.focus(), children: [
|
|
214
|
+
/* @__PURE__ */ jsx("ul", { className: "bl-tags__list", "aria-label": `${label}: ${tags.length} selected`, children: tags.map((tag, i) => /* @__PURE__ */ jsxs(
|
|
215
|
+
"li",
|
|
216
|
+
{
|
|
217
|
+
className: "bl-tags__chip",
|
|
218
|
+
"data-selected": i === selected || void 0,
|
|
219
|
+
"data-leaving": leaving.includes(tag) || void 0,
|
|
220
|
+
"data-shake": shake === tag || void 0,
|
|
221
|
+
onAnimationEnd: () => shake === tag && setShake(null),
|
|
222
|
+
children: [
|
|
223
|
+
/* @__PURE__ */ jsx("span", { className: "bl-tags__text", children: tag }),
|
|
224
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "bl-tags__x", "aria-label": `Remove ${tag}`, onClick: () => remove(i), children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M2 2l6 6M8 2 2 8" }) }) })
|
|
225
|
+
]
|
|
226
|
+
},
|
|
227
|
+
tag
|
|
228
|
+
)) }),
|
|
229
|
+
/* @__PURE__ */ jsx(
|
|
230
|
+
"input",
|
|
231
|
+
{
|
|
232
|
+
ref: inputRef,
|
|
233
|
+
id: `${uid}-input`,
|
|
234
|
+
className: "bl-tags__input",
|
|
235
|
+
role: "combobox",
|
|
236
|
+
"aria-expanded": showMenu,
|
|
237
|
+
"aria-controls": `${uid}-menu`,
|
|
238
|
+
"aria-autocomplete": "list",
|
|
239
|
+
"aria-activedescendant": showMenu ? `${uid}-opt-${highlight}` : void 0,
|
|
240
|
+
"aria-describedby": `${uid}-hint`,
|
|
241
|
+
"aria-invalid": error ? true : void 0,
|
|
242
|
+
value: text,
|
|
243
|
+
placeholder: tags.length >= max ? "" : placeholder,
|
|
244
|
+
onChange: (event) => {
|
|
245
|
+
setText(event.target.value);
|
|
246
|
+
setOpen(true);
|
|
247
|
+
setHighlight(0);
|
|
248
|
+
setError("");
|
|
249
|
+
},
|
|
250
|
+
onFocus: () => setOpen(true),
|
|
251
|
+
onBlur: () => {
|
|
252
|
+
setOpen(false);
|
|
253
|
+
setSelected(-1);
|
|
254
|
+
},
|
|
255
|
+
onKeyDown,
|
|
256
|
+
onPaste
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
] }),
|
|
260
|
+
showMenu && /* @__PURE__ */ jsx("ul", { id: `${uid}-menu`, className: "bl-tags__menu", role: "listbox", "aria-label": `${label} suggestions`, children: matches.map((option, i) => /* @__PURE__ */ jsx(
|
|
261
|
+
"li",
|
|
262
|
+
{
|
|
263
|
+
id: `${uid}-opt-${i}`,
|
|
264
|
+
role: "option",
|
|
265
|
+
"aria-selected": i === highlight,
|
|
266
|
+
className: "bl-tags__option",
|
|
267
|
+
onPointerEnter: () => setHighlight(i),
|
|
268
|
+
onPointerDown: (event) => {
|
|
269
|
+
event.preventDefault();
|
|
270
|
+
if (add([option])) setText("");
|
|
271
|
+
},
|
|
272
|
+
children: mark(option)
|
|
273
|
+
},
|
|
274
|
+
option
|
|
275
|
+
)) }),
|
|
276
|
+
/* @__PURE__ */ jsx("p", { id: `${uid}-hint`, className: "bl-tags__hint", "data-error": error ? "" : void 0, children: error || hint }),
|
|
277
|
+
/* @__PURE__ */ jsx("span", { className: "bl-tags__sr", "aria-live": "polite", children: announce })
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
TagInput as default
|
|
284
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
|
+
export interface TallyUpProps {
|
|
3
|
+
/** Where the count ends. */
|
|
4
|
+
value?: number;
|
|
5
|
+
/** The bar fills toward this; defaults to value. */
|
|
6
|
+
goal?: number;
|
|
7
|
+
start?: number;
|
|
8
|
+
/** In ms. */
|
|
9
|
+
duration?: number;
|
|
10
|
+
/** A smooth ease-out, or an arcade count in chunky steps. */
|
|
11
|
+
curve?: 'ease' | 'steps';
|
|
12
|
+
steps?: number;
|
|
13
|
+
/** Pixel blocks in the bar. */
|
|
14
|
+
blocks?: number;
|
|
15
|
+
/** Notches that flash as the count passes them. */
|
|
16
|
+
milestones?: number[];
|
|
17
|
+
trigger?: 'view' | 'mount';
|
|
18
|
+
locale?: string;
|
|
19
|
+
format?: Intl.NumberFormatOptions;
|
|
20
|
+
unit?: string;
|
|
21
|
+
caption?: string;
|
|
22
|
+
/** Show "of {goal}" under the bar (when goal is set). */
|
|
23
|
+
showGoal?: boolean;
|
|
24
|
+
onReach?: (value: number) => void;
|
|
25
|
+
width?: number;
|
|
26
|
+
fontSize?: number;
|
|
27
|
+
barHeight?: number;
|
|
28
|
+
gap?: number;
|
|
29
|
+
textColor?: string;
|
|
30
|
+
mutedColor?: string;
|
|
31
|
+
trackColor?: string;
|
|
32
|
+
fillColor?: string;
|
|
33
|
+
accentColor?: string;
|
|
34
|
+
fontFamily?: string;
|
|
35
|
+
className?: string;
|
|
36
|
+
style?: CSSProperties;
|
|
37
|
+
}
|
|
38
|
+
export default function TallyUp({ value, goal, start, duration, curve, steps, blocks, milestones, trigger, locale, format, unit, caption, showGoal, onReach, width, fontSize, barHeight, gap, textColor, mutedColor, trackColor, fillColor, accentColor, fontFamily, className, style }: TallyUpProps): import("react").JSX.Element;
|
package/dist/TallyUp.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useInsertionEffect, useRef, useState } from "react";
|
|
4
|
+
const STYLE_ID = "bl-tally-up";
|
|
5
|
+
const CSS = `
|
|
6
|
+
.bl-tally { display: grid; gap: 10px; width: 100%; max-width: var(--bl-w); font-family: var(--bl-font); color: var(--bl-ink); }
|
|
7
|
+
.bl-tally__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
|
|
8
|
+
.bl-tally__caption { color: var(--bl-muted); font-size: 14px; }
|
|
9
|
+
.bl-tally__figure { display: inline-flex; align-items: baseline; gap: 6px; font-size: var(--bl-size); font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
|
|
10
|
+
.bl-tally__figure[data-bump] { animation: bl-tally-bump 160ms steps(2); }
|
|
11
|
+
.bl-tally__unit { color: var(--bl-muted); font-size: 0.45em; font-weight: 600; }
|
|
12
|
+
.bl-tally__bar { position: relative; display: grid; grid-template-columns: repeat(var(--bl-blocks), minmax(0, 1fr)); gap: var(--bl-gap); height: var(--bl-bar-h); }
|
|
13
|
+
.bl-tally__block { background: var(--bl-track); transition: background-color 120ms steps(1); }
|
|
14
|
+
.bl-tally__block[data-on] { background: var(--bl-fill); box-shadow: inset 0 -3px 0 rgba(0,0,0,0.25); }
|
|
15
|
+
.bl-tally__bar[data-done] .bl-tally__block[data-on] { animation: bl-tally-flash 600ms steps(3); }
|
|
16
|
+
.bl-tally__notch { position: absolute; top: -5px; bottom: -5px; left: var(--x); width: 2px; margin-left: -1px; background: var(--bl-muted); opacity: 0.6; }
|
|
17
|
+
.bl-tally__notch[data-passed] { background: var(--bl-accent); opacity: 1; animation: bl-tally-notch 500ms steps(4); }
|
|
18
|
+
.bl-tally__goal { color: var(--bl-muted); font-size: 12px; text-align: right; font-variant-numeric: tabular-nums; }
|
|
19
|
+
.bl-tally__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
20
|
+
@keyframes bl-tally-bump { 50% { transform: translateY(-3px); } }
|
|
21
|
+
@keyframes bl-tally-flash { 33% { background: var(--bl-accent); } }
|
|
22
|
+
@keyframes bl-tally-notch { 50% { transform: scaleY(1.6); } }
|
|
23
|
+
@media (prefers-reduced-motion: reduce) { .bl-tally__figure[data-bump], .bl-tally__bar[data-done] .bl-tally__block[data-on], .bl-tally__notch[data-passed] { animation: none; } .bl-tally__block { transition: none; } }
|
|
24
|
+
`;
|
|
25
|
+
function useStyles() {
|
|
26
|
+
useInsertionEffect(() => {
|
|
27
|
+
if (typeof document === "undefined") return;
|
|
28
|
+
const style = document.getElementById(STYLE_ID) ?? Object.assign(document.createElement("style"), { id: STYLE_ID });
|
|
29
|
+
style.textContent = CSS;
|
|
30
|
+
if (!style.isConnected) document.head.appendChild(style);
|
|
31
|
+
}, []);
|
|
32
|
+
}
|
|
33
|
+
function TallyUp({
|
|
34
|
+
value = 0,
|
|
35
|
+
goal,
|
|
36
|
+
start = 0,
|
|
37
|
+
duration = 1600,
|
|
38
|
+
curve = "ease",
|
|
39
|
+
steps = 12,
|
|
40
|
+
blocks = 20,
|
|
41
|
+
milestones = [],
|
|
42
|
+
trigger = "view",
|
|
43
|
+
locale,
|
|
44
|
+
format,
|
|
45
|
+
unit = "",
|
|
46
|
+
caption = "",
|
|
47
|
+
showGoal = true,
|
|
48
|
+
onReach,
|
|
49
|
+
width = 420,
|
|
50
|
+
fontSize = 48,
|
|
51
|
+
barHeight = 14,
|
|
52
|
+
gap = 3,
|
|
53
|
+
textColor = "#f4f4f4",
|
|
54
|
+
mutedColor = "#94b0c2",
|
|
55
|
+
trackColor = "#262b44",
|
|
56
|
+
fillColor = "#38b764",
|
|
57
|
+
accentColor = "#ffcd75",
|
|
58
|
+
fontFamily = "inherit",
|
|
59
|
+
className = "",
|
|
60
|
+
style
|
|
61
|
+
}) {
|
|
62
|
+
useStyles();
|
|
63
|
+
const rootRef = useRef(null);
|
|
64
|
+
const figureRef = useRef(null);
|
|
65
|
+
const reachRef = useRef(onReach);
|
|
66
|
+
reachRef.current = onReach;
|
|
67
|
+
const [shown, setShown] = useState(start);
|
|
68
|
+
const [done, setDone] = useState(false);
|
|
69
|
+
const target = goal ?? value;
|
|
70
|
+
const fmt = new Intl.NumberFormat(locale, format);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const root = rootRef.current;
|
|
73
|
+
const reduced = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
74
|
+
let raf = 0;
|
|
75
|
+
let begun = 0;
|
|
76
|
+
let lastStep = -1;
|
|
77
|
+
setDone(false);
|
|
78
|
+
const finish = () => {
|
|
79
|
+
setShown(value);
|
|
80
|
+
setDone(true);
|
|
81
|
+
reachRef.current?.(value);
|
|
82
|
+
};
|
|
83
|
+
const tick = (now) => {
|
|
84
|
+
if (!begun) begun = now;
|
|
85
|
+
const t = Math.min(1, (now - begun) / duration);
|
|
86
|
+
let k;
|
|
87
|
+
if (curve === "steps") {
|
|
88
|
+
const step = Math.min(steps, Math.floor(t * steps + 1e-9));
|
|
89
|
+
k = step / steps;
|
|
90
|
+
if (step !== lastStep) {
|
|
91
|
+
lastStep = step;
|
|
92
|
+
const figure = figureRef.current;
|
|
93
|
+
if (figure && step > 0) {
|
|
94
|
+
delete figure.dataset.bump;
|
|
95
|
+
void figure.offsetWidth;
|
|
96
|
+
figure.dataset.bump = "";
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} else k = 1 - Math.pow(1 - t, 3);
|
|
100
|
+
setShown(start + (value - start) * k);
|
|
101
|
+
if (t < 1) raf = requestAnimationFrame(tick);
|
|
102
|
+
else finish();
|
|
103
|
+
};
|
|
104
|
+
const run = () => {
|
|
105
|
+
if (reduced) finish();
|
|
106
|
+
else raf = requestAnimationFrame(tick);
|
|
107
|
+
};
|
|
108
|
+
if (trigger === "mount") {
|
|
109
|
+
run();
|
|
110
|
+
return () => cancelAnimationFrame(raf);
|
|
111
|
+
}
|
|
112
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
113
|
+
if (!entry.isIntersecting) return;
|
|
114
|
+
observer.disconnect();
|
|
115
|
+
run();
|
|
116
|
+
}, { threshold: 0.4 });
|
|
117
|
+
observer.observe(root);
|
|
118
|
+
return () => {
|
|
119
|
+
observer.disconnect();
|
|
120
|
+
cancelAnimationFrame(raf);
|
|
121
|
+
};
|
|
122
|
+
}, [value, start, duration, curve, steps, trigger]);
|
|
123
|
+
const decimals = format?.maximumFractionDigits ?? format?.minimumFractionDigits ?? 0;
|
|
124
|
+
const display = fmt.format(Number(shown.toFixed(decimals)));
|
|
125
|
+
const share = target ? Math.max(0, Math.min(1, shown / target)) : 0;
|
|
126
|
+
const lit = Math.round(share * blocks);
|
|
127
|
+
return /* @__PURE__ */ jsxs(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
ref: rootRef,
|
|
131
|
+
className: `bl-tally ${className}`,
|
|
132
|
+
style: { "--bl-w": `${width}px`, "--bl-size": `${fontSize}px`, "--bl-bar-h": `${barHeight}px`, "--bl-gap": `${gap}px`, "--bl-blocks": blocks, "--bl-ink": textColor, "--bl-muted": mutedColor, "--bl-track": trackColor, "--bl-fill": fillColor, "--bl-accent": accentColor, "--bl-font": fontFamily, ...style },
|
|
133
|
+
children: [
|
|
134
|
+
/* @__PURE__ */ jsxs("div", { className: "bl-tally__head", "aria-hidden": "true", children: [
|
|
135
|
+
/* @__PURE__ */ jsxs("span", { ref: figureRef, className: "bl-tally__figure", children: [
|
|
136
|
+
display,
|
|
137
|
+
unit && /* @__PURE__ */ jsx("span", { className: "bl-tally__unit", children: unit })
|
|
138
|
+
] }),
|
|
139
|
+
caption && /* @__PURE__ */ jsx("span", { className: "bl-tally__caption", children: caption })
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsxs("div", { className: "bl-tally__bar", "data-done": done || void 0, "aria-hidden": "true", children: [
|
|
142
|
+
Array.from({ length: blocks }, (_, i) => /* @__PURE__ */ jsx("span", { className: "bl-tally__block", "data-on": i < lit || void 0 }, i)),
|
|
143
|
+
target > 0 && milestones.filter((m) => m > 0 && m < target).map((m) => /* @__PURE__ */ jsx("span", { className: "bl-tally__notch", "data-passed": shown >= m || void 0, style: { "--x": `${m / target * 100}%` } }, m))
|
|
144
|
+
] }),
|
|
145
|
+
showGoal && goal != null && /* @__PURE__ */ jsxs("span", { className: "bl-tally__goal", "aria-hidden": "true", children: [
|
|
146
|
+
"of ",
|
|
147
|
+
fmt.format(goal),
|
|
148
|
+
unit && ` ${unit}`
|
|
149
|
+
] }),
|
|
150
|
+
/* @__PURE__ */ jsx("span", { className: "bl-tally__sr", role: "status", children: done ? `${caption ? `${caption}: ` : ""}${fmt.format(value)}${unit ? ` ${unit}` : ""}${goal != null ? ` of ${fmt.format(goal)}` : ""}` : "" })
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
export {
|
|
156
|
+
TallyUp as default
|
|
157
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
|
+
/** One step of the scripted session. `after` is the pause after the step, in ms. */
|
|
3
|
+
export type TerminalStep = {
|
|
4
|
+
type: 'command';
|
|
5
|
+
text: string;
|
|
6
|
+
prompt?: string; /** Pause before typing starts, in ms. */
|
|
7
|
+
delay?: number;
|
|
8
|
+
after?: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'output' | 'success' | 'error' | 'info';
|
|
11
|
+
text: string;
|
|
12
|
+
after?: number;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'spinner';
|
|
15
|
+
text: string;
|
|
16
|
+
duration?: number; /** Text shown when the spinner resolves. */
|
|
17
|
+
done?: string; /** Resolve as an error instead of success. */
|
|
18
|
+
failed?: boolean;
|
|
19
|
+
after?: number;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'pause';
|
|
22
|
+
duration?: number;
|
|
23
|
+
after?: number;
|
|
24
|
+
};
|
|
25
|
+
export interface TerminalDemoProps {
|
|
26
|
+
/** The session, in order. */
|
|
27
|
+
script?: TerminalStep[];
|
|
28
|
+
/** Window title. */
|
|
29
|
+
title?: string;
|
|
30
|
+
/** Prompt symbol (each command can override it). */
|
|
31
|
+
prompt?: string;
|
|
32
|
+
/** Average ms per typed character (with jitter). */
|
|
33
|
+
typingSpeed?: number;
|
|
34
|
+
/** Default gap after each step, in ms. */
|
|
35
|
+
lineDelay?: number;
|
|
36
|
+
/** Replay forever. When not looping, a Replay button appears at the end. */
|
|
37
|
+
loop?: boolean;
|
|
38
|
+
/** Pause before looping, in ms. */
|
|
39
|
+
loopDelay?: number;
|
|
40
|
+
/** Wait until a third of the terminal is visible. */
|
|
41
|
+
startOnView?: boolean;
|
|
42
|
+
/** Show the Replay button. */
|
|
43
|
+
showControls?: boolean;
|
|
44
|
+
/** Max width, in px. */
|
|
45
|
+
width?: number;
|
|
46
|
+
/** Body height, in px. */
|
|
47
|
+
height?: number;
|
|
48
|
+
radius?: number;
|
|
49
|
+
fontSize?: number;
|
|
50
|
+
fontFamily?: string;
|
|
51
|
+
background?: string;
|
|
52
|
+
barColor?: string;
|
|
53
|
+
lineColor?: string;
|
|
54
|
+
textColor?: string;
|
|
55
|
+
mutedColor?: string;
|
|
56
|
+
promptColor?: string;
|
|
57
|
+
successColor?: string;
|
|
58
|
+
errorColor?: string;
|
|
59
|
+
infoColor?: string;
|
|
60
|
+
className?: string;
|
|
61
|
+
style?: CSSProperties;
|
|
62
|
+
}
|
|
63
|
+
export default function TerminalDemo({ script, title, prompt, typingSpeed, lineDelay, loop, loopDelay, startOnView, showControls, width, height, radius, fontSize, fontFamily, background, barColor, lineColor, textColor, mutedColor, promptColor, successColor, errorColor, infoColor, className, style }: TerminalDemoProps): import("react").JSX.Element;
|