@vllnt/ui 0.2.1-canary.0aaaad2 → 0.2.1-canary.0cc4e50
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/CHANGELOG.md +3 -0
- package/dist/components/activity-heatmap/activity-heatmap.js +2 -1
- package/dist/components/activity-log/activity-log.js +1 -1
- package/dist/components/ai-artifact/ai-artifact.js +8 -8
- package/dist/components/ai-chat-input/ai-chat-input.js +1 -1
- package/dist/components/ai-message-bubble/ai-message-bubble.js +1 -1
- package/dist/components/ai-sidebar/ai-sidebar.js +4 -4
- package/dist/components/ai-tool-call-display/ai-tool-call-display.js +1 -1
- package/dist/components/animated-text/animated-text.js +6 -3
- package/dist/components/annotation/annotation.js +1 -1
- package/dist/components/auto-reload/auto-reload.js +1 -1
- package/dist/components/avatar-group/avatar-group.js +1 -1
- package/dist/components/blog-card/blog-card.js +4 -2
- package/dist/components/bottom-activity-strip/bottom-activity-strip.js +2 -2
- package/dist/components/candlestick-chart/candlestick-chart.js +2 -1
- package/dist/components/canvas-shell/canvas-foundation-demo.js +1 -1
- package/dist/components/carousel/carousel.js +14 -6
- package/dist/components/category-filter/category-filter.js +1 -1
- package/dist/components/chat-dock-section/chat-dock-section.js +1 -1
- package/dist/components/checklist/checklist.js +35 -7
- package/dist/components/checklist/index.js +8 -2
- package/dist/components/chronological-timeline/chronological-timeline.js +2 -2
- package/dist/components/code-playground/code-playground.js +3 -2
- package/dist/components/combobox/combobox.js +1 -6
- package/dist/components/comment-pin/comment-pin.js +2 -2
- package/dist/components/comparison/comparison.js +2 -1
- package/dist/components/completion-dialog/completion-dialog.js +19 -11
- package/dist/components/connector-edge/connector-edge.js +1 -1
- package/dist/components/content-intro/content-intro.js +18 -15
- package/dist/components/conversation-thread/conversation-thread.js +4 -4
- package/dist/components/countdown-timer/countdown-timer.js +1 -1
- package/dist/components/data-table/data-table.js +1 -1
- package/dist/components/date-picker/date-picker.js +1 -6
- package/dist/components/exercise/exercise.js +11 -3
- package/dist/components/faq/faq.js +6 -2
- package/dist/components/file-upload/file-upload.js +1 -6
- package/dist/components/filter-bar/filter-bar.js +7 -7
- package/dist/components/flashcard/flashcard.js +1 -1
- package/dist/components/floating-toolbar/floating-toolbar.js +2 -2
- package/dist/components/form/form.js +1 -1
- package/dist/components/gantt-chart/gantt-chart.js +8 -7
- package/dist/components/globe-3d/globe-3d.js +16 -4
- package/dist/components/horizontal-scroll-row/horizontal-scroll-row.js +2 -1
- package/dist/components/inline-input/inline-input.js +1 -1
- package/dist/components/interactive-timeline/interactive-timeline.js +8 -5
- package/dist/components/jarvis-dock/jarvis-dock.js +2 -2
- package/dist/components/key-concept/key-concept.js +2 -1
- package/dist/components/keyboard-shortcuts-help/keyboard-shortcuts-help.js +2 -1
- package/dist/components/knowledge-check/knowledge-check.js +2 -2
- package/dist/components/lang-provider/lang-provider.js +3 -3
- package/dist/components/learning-objectives/learning-objectives.js +2 -1
- package/dist/components/live-feed/live-feed.js +2 -2
- package/dist/components/map-2d/map-2d.js +1 -1
- package/dist/components/map-timeline/map-timeline.js +5 -5
- package/dist/components/market-treemap/market-treemap.js +2 -2
- package/dist/components/mdx-content/mdx-content.js +17 -8
- package/dist/components/metric-gauge/metric-gauge.js +1 -1
- package/dist/components/model-selector/model-selector.js +1 -1
- package/dist/components/multi-select/multi-select.js +1 -1
- package/dist/components/navbar-saas/navbar-saas.js +5 -5
- package/dist/components/number-input/number-input.js +1 -1
- package/dist/components/number-ticker/number-ticker.js +1 -1
- package/dist/components/object-card/object-card.js +1 -1
- package/dist/components/order-book/order-book.js +2 -2
- package/dist/components/overview-board/overview-board.js +1 -1
- package/dist/components/policy-delivery-panel/policy-delivery-panel.js +2 -2
- package/dist/components/profile-section/profile-section.js +2 -1
- package/dist/components/progress-card/progress-card.js +1 -1
- package/dist/components/progress-tracker/progress-tracker.js +17 -9
- package/dist/components/prompt-templates/prompt-templates.js +2 -2
- package/dist/components/quiz/quiz.js +3 -2
- package/dist/components/relationship-inspector/relationship-inspector.js +2 -2
- package/dist/components/routing-assignment-panel/routing-assignment-panel.js +2 -2
- package/dist/components/run-timeline/run-timeline.js +2 -2
- package/dist/components/scope-selector/scope-selector.js +1 -1
- package/dist/components/search-dialog/search-dialog.js +484 -51
- package/dist/components/share-dialog/share-dialog.js +2 -2
- package/dist/components/share-section/share-section.js +2 -1
- package/dist/components/sidebar/sidebar.js +30 -25
- package/dist/components/sidebar-toggle/sidebar-toggle.js +1 -1
- package/dist/components/slideshow/slideshow.js +3 -2
- package/dist/components/social-fab/social-fab.js +10 -10
- package/dist/components/spinner/spinner.js +1 -1
- package/dist/components/spinner/unicode-spinner.js +4 -2
- package/dist/components/stat-card/stat-card.js +2 -2
- package/dist/components/status-board/status-board.js +13 -6
- package/dist/components/step-by-step/step-by-step.js +2 -1
- package/dist/components/table-of-contents/table-of-contents.js +5 -2
- package/dist/components/table-of-contents-panel/table-of-contents-panel.js +3 -1
- package/dist/components/tabs/tabs.js +26 -8
- package/dist/components/tags-input/tags-input.js +11 -3
- package/dist/components/terminal/terminal.js +11 -3
- package/dist/components/theme-toggle/theme-toggle.js +2 -2
- package/dist/components/thinking-block/thinking-block.js +2 -2
- package/dist/components/ticker-tape/ticker-tape.js +1 -1
- package/dist/components/timeline-scrubber/timeline-scrubber.js +2 -2
- package/dist/components/tldr-section/tldr-section.js +9 -7
- package/dist/components/tour/tour.js +1 -1
- package/dist/components/transaction-list/transaction-list.js +2 -2
- package/dist/components/tutorial-card/tutorial-card.js +1 -1
- package/dist/components/tutorial-complete/tutorial-complete.js +8 -6
- package/dist/components/tutorial-filters/tutorial-filters.js +2 -2
- package/dist/components/tutorial-intro-content/tutorial-intro-content.js +5 -5
- package/dist/components/tutorial-mdx/tutorial-mdx.js +6 -6
- package/dist/components/usage-breakdown/usage-breakdown.js +1 -1
- package/dist/components/viewport-bookmarks/viewport-bookmarks.js +2 -2
- package/dist/components/watchlist/watchlist.js +2 -1
- package/dist/components/world-breadcrumbs/world-breadcrumbs.js +2 -2
- package/dist/components/world-clock-bar/world-clock-bar.js +5 -4
- package/dist/components/zoom-hud/zoom-hud.js +1 -1
- package/dist/index.d.ts +113 -29
- package/package.json +3 -3
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { ChevronDown } from "lucide-react";
|
|
5
5
|
import Link from "next/link";
|
|
6
6
|
import { usePathname } from "next/navigation";
|
|
7
|
+
import { useMounted } from "../../lib/use-mounted";
|
|
7
8
|
import { cn } from "../../lib/utils";
|
|
8
|
-
import { useSidebar } from "../sidebar-provider";
|
|
9
|
+
import { useSidebar } from "../sidebar-provider/sidebar-provider";
|
|
10
|
+
const getMobileSnapshot = () => typeof window === "undefined" ? false : window.innerWidth < 1024;
|
|
11
|
+
const getServerMobileSnapshot = () => false;
|
|
12
|
+
const subscribeToViewportResize = (onStoreChange) => {
|
|
13
|
+
window.addEventListener("resize", onStoreChange);
|
|
14
|
+
return () => {
|
|
15
|
+
window.removeEventListener("resize", onStoreChange);
|
|
16
|
+
};
|
|
17
|
+
};
|
|
9
18
|
function useMobile(setOpen) {
|
|
10
|
-
const
|
|
19
|
+
const isMobile = useSyncExternalStore(
|
|
20
|
+
subscribeToViewportResize,
|
|
21
|
+
getMobileSnapshot,
|
|
22
|
+
getServerMobileSnapshot
|
|
23
|
+
);
|
|
11
24
|
useEffect(() => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
setIsMobile(mobile);
|
|
15
|
-
if (mobile) {
|
|
16
|
-
setOpen(false);
|
|
17
|
-
} else {
|
|
18
|
-
setOpen(true);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
checkMobile();
|
|
22
|
-
window.addEventListener("resize", checkMobile);
|
|
23
|
-
return () => {
|
|
24
|
-
window.removeEventListener("resize", checkMobile);
|
|
25
|
-
};
|
|
26
|
-
}, [setOpen]);
|
|
25
|
+
setOpen(!isMobile);
|
|
26
|
+
}, [isMobile, setOpen]);
|
|
27
27
|
return isMobile;
|
|
28
28
|
}
|
|
29
29
|
function useScrollFade(containerReference) {
|
|
@@ -38,7 +38,7 @@ function useScrollFade(containerReference) {
|
|
|
38
38
|
setShowBottomFade(scrollTop < scrollHeight - clientHeight - 1);
|
|
39
39
|
};
|
|
40
40
|
checkScroll();
|
|
41
|
-
container.addEventListener("scroll", checkScroll);
|
|
41
|
+
container.addEventListener("scroll", checkScroll, { passive: true });
|
|
42
42
|
return () => {
|
|
43
43
|
container.removeEventListener("scroll", checkScroll);
|
|
44
44
|
};
|
|
@@ -88,6 +88,7 @@ function CollapsibleSection({
|
|
|
88
88
|
"grid transition-all duration-200 ease-in-out",
|
|
89
89
|
isOpen ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"
|
|
90
90
|
),
|
|
91
|
+
hidden: !isOpen,
|
|
91
92
|
children: /* @__PURE__ */ jsx("div", { className: "overflow-hidden", children })
|
|
92
93
|
}
|
|
93
94
|
)
|
|
@@ -97,15 +98,18 @@ function Sidebar({ sections }) {
|
|
|
97
98
|
const pathname = usePathname();
|
|
98
99
|
const { open, setOpen } = useSidebar();
|
|
99
100
|
const isMobile = useMobile(setOpen);
|
|
101
|
+
const mounted = useMounted();
|
|
100
102
|
const scrollContainerReference = useRef(null);
|
|
101
103
|
const { showBottomFade, showTopFade } = useScrollFade(
|
|
102
104
|
scrollContainerReference
|
|
103
105
|
);
|
|
106
|
+
const collapsed = mounted && !isMobile && !open;
|
|
104
107
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
105
108
|
isMobile && open ? /* @__PURE__ */ jsx(
|
|
106
109
|
"div",
|
|
107
110
|
{
|
|
108
111
|
className: "fixed inset-0 bg-black/50 z-40 lg:hidden",
|
|
112
|
+
"data-testid": "sidebar-overlay",
|
|
109
113
|
onClick: () => {
|
|
110
114
|
setOpen(false);
|
|
111
115
|
},
|
|
@@ -122,15 +126,16 @@ function Sidebar({ sections }) {
|
|
|
122
126
|
"aside",
|
|
123
127
|
{
|
|
124
128
|
className: cn(
|
|
125
|
-
"fixed lg:relative top-16 lg:top-0 bottom-0 lg:bottom-auto left-0 z-40 lg:h-full
|
|
129
|
+
"fixed lg:relative top-16 lg:top-0 bottom-0 lg:bottom-auto left-0 z-40 lg:h-full bg-background transition-[transform,width] duration-300 ease-in-out",
|
|
126
130
|
"flex flex-col",
|
|
127
131
|
"overflow-hidden",
|
|
128
132
|
"shrink-0",
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
collapsed ? "border-r-0" : "border-r",
|
|
134
|
+
collapsed ? "w-0" : isMobile ? "w-full" : "w-64",
|
|
131
135
|
isMobile && open && "translate-x-0",
|
|
132
|
-
|
|
133
|
-
!isMobile && "lg:translate-x-0"
|
|
136
|
+
isMobile && !open && "-translate-x-full",
|
|
137
|
+
!isMobile && !collapsed && "-translate-x-full lg:translate-x-0",
|
|
138
|
+
!isMobile && collapsed && "-translate-x-full"
|
|
134
139
|
),
|
|
135
140
|
children: /* @__PURE__ */ jsxs("div", { className: "relative flex-1 overflow-hidden", children: [
|
|
136
141
|
showTopFade ? /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 h-8 bg-gradient-to-b from-background to-transparent pointer-events-none z-20" }) : null,
|
|
@@ -138,7 +143,7 @@ function Sidebar({ sections }) {
|
|
|
138
143
|
/* @__PURE__ */ jsx(
|
|
139
144
|
"nav",
|
|
140
145
|
{
|
|
141
|
-
className: "flex-1 p-4 overflow-y-auto h-full",
|
|
146
|
+
className: "flex-1 p-4 overflow-y-auto overscroll-contain h-full [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
142
147
|
ref: scrollContainerReference,
|
|
143
148
|
children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: sections.map((section, sectionIndex) => {
|
|
144
149
|
const sectionItems = /* @__PURE__ */ jsx("div", { className: section.title ? "space-y-0.5" : "space-y-1", children: section.items.map((item) => /* @__PURE__ */ jsx(
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Menu, X } from "lucide-react";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
|
-
import { Button } from "../button";
|
|
5
|
+
import { Button } from "../button/button";
|
|
6
6
|
function SidebarToggle({
|
|
7
7
|
className,
|
|
8
8
|
onToggle,
|
|
@@ -4,7 +4,7 @@ import { memo, useCallback, useEffect, useState } from "react";
|
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
5
|
import { useMounted } from "../../lib/use-mounted";
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
|
-
import { CompletionDialog } from "../completion-dialog";
|
|
7
|
+
import { CompletionDialog } from "../completion-dialog/completion-dialog";
|
|
8
8
|
const DEFAULT_LABELS = {
|
|
9
9
|
closeLabel: "Close",
|
|
10
10
|
closeTocLabel: "Close table of contents",
|
|
@@ -17,6 +17,7 @@ const DEFAULT_LABELS = {
|
|
|
17
17
|
};
|
|
18
18
|
const EMPTY_SLIDESHOW_LABELS = {};
|
|
19
19
|
function SlideshowImpl({
|
|
20
|
+
as: SectionsHeading = "h3",
|
|
20
21
|
completedSections,
|
|
21
22
|
completionDialogTitle = "Mark section as complete?",
|
|
22
23
|
currentIndex,
|
|
@@ -249,7 +250,7 @@ function SlideshowImpl({
|
|
|
249
250
|
role: "dialog",
|
|
250
251
|
children: [
|
|
251
252
|
/* @__PURE__ */ jsxs("div", { className: "sticky top-0 flex items-center justify-between px-4 py-3 border-b border-border bg-background", children: [
|
|
252
|
-
/* @__PURE__ */ jsx(
|
|
253
|
+
/* @__PURE__ */ jsx(SectionsHeading, { className: "font-semibold", children: mergedLabels.sectionsLabel }),
|
|
253
254
|
/* @__PURE__ */ jsx(
|
|
254
255
|
"button",
|
|
255
256
|
{
|
|
@@ -7,15 +7,15 @@ function ShareMenu({
|
|
|
7
7
|
onPlatformSelect,
|
|
8
8
|
platforms
|
|
9
9
|
}) {
|
|
10
|
-
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5 rounded-md border border-
|
|
11
|
-
const
|
|
10
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5 rounded-md border border-zinc-300 bg-background p-1.5 shadow-md dark:border-zinc-600", children: platforms.map((p) => {
|
|
11
|
+
const handleSelectSharePlatform = () => {
|
|
12
12
|
onPlatformSelect(p.key);
|
|
13
13
|
};
|
|
14
14
|
return /* @__PURE__ */ jsx(
|
|
15
15
|
"button",
|
|
16
16
|
{
|
|
17
17
|
className: "rounded px-3 py-1.5 text-left text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
|
|
18
|
-
onClick:
|
|
18
|
+
onClick: handleSelectSharePlatform,
|
|
19
19
|
type: "button",
|
|
20
20
|
children: p.label
|
|
21
21
|
},
|
|
@@ -24,12 +24,12 @@ function ShareMenu({
|
|
|
24
24
|
}) });
|
|
25
25
|
}
|
|
26
26
|
function ActionButton({ action }) {
|
|
27
|
-
const
|
|
27
|
+
const handleRunAction = action.onClick;
|
|
28
28
|
return /* @__PURE__ */ jsx(
|
|
29
29
|
"button",
|
|
30
30
|
{
|
|
31
31
|
className: "rounded px-3 py-1.5 text-left text-sm transition-colors hover:bg-accent",
|
|
32
|
-
onClick:
|
|
32
|
+
onClick: handleRunAction,
|
|
33
33
|
type: "button",
|
|
34
34
|
children: action.label
|
|
35
35
|
}
|
|
@@ -47,7 +47,7 @@ function ActionPanel({
|
|
|
47
47
|
const handleShareClick = shareAction?.onClick;
|
|
48
48
|
const handleShareMouseEnter = isMobile ? void 0 : onShareHover;
|
|
49
49
|
const handleShareMouseLeave = isMobile ? void 0 : onShareLeave;
|
|
50
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 rounded-md border border-
|
|
50
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 rounded-md border border-zinc-300 bg-background p-1.5 shadow-md dark:border-zinc-600", children: [
|
|
51
51
|
shareAction ? /* @__PURE__ */ jsx(
|
|
52
52
|
"button",
|
|
53
53
|
{
|
|
@@ -69,7 +69,7 @@ function MainFabButton({
|
|
|
69
69
|
mainText,
|
|
70
70
|
onToggle
|
|
71
71
|
}) {
|
|
72
|
-
const
|
|
72
|
+
const handleToggleSharePanel = onToggle;
|
|
73
73
|
return /* @__PURE__ */ jsx(
|
|
74
74
|
"button",
|
|
75
75
|
{
|
|
@@ -77,11 +77,11 @@ function MainFabButton({
|
|
|
77
77
|
"aria-label": isExpanded ? labels.close : labels.share,
|
|
78
78
|
className: cn(
|
|
79
79
|
"flex size-10 items-center justify-center rounded-md",
|
|
80
|
-
"border border-
|
|
80
|
+
"border border-zinc-300 bg-background dark:border-zinc-600",
|
|
81
81
|
"transition-all duration-200 ease-out",
|
|
82
|
-
"hover:-translate-y-0.5 hover:border-
|
|
82
|
+
"hover:-translate-y-0.5 hover:border-zinc-400 hover:shadow-md dark:hover:border-zinc-500"
|
|
83
83
|
),
|
|
84
|
-
onClick:
|
|
84
|
+
onClick: handleToggleSharePanel,
|
|
85
85
|
type: "button",
|
|
86
86
|
children: /* @__PURE__ */ jsx("span", { className: "text-sm font-mono", children: isMobile && isExpanded ? "\u2715" : mainText })
|
|
87
87
|
}
|
|
@@ -14,7 +14,7 @@ function Spinner({ className, size = "md", ...props }) {
|
|
|
14
14
|
className
|
|
15
15
|
),
|
|
16
16
|
...props,
|
|
17
|
-
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading
|
|
17
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading\u2026" })
|
|
18
18
|
}
|
|
19
19
|
);
|
|
20
20
|
}
|
|
@@ -658,9 +658,11 @@ const UnicodeSpinner = React.forwardRef(
|
|
|
658
658
|
const preset = UNICODE_SPINNER_PRESETS[animation];
|
|
659
659
|
const resolvedInterval = interval ?? preset.interval;
|
|
660
660
|
const [frameIndex, setFrameIndex] = React.useState(0);
|
|
661
|
-
React.
|
|
661
|
+
const [previousAnimation, setPreviousAnimation] = React.useState(animation);
|
|
662
|
+
if (previousAnimation !== animation) {
|
|
663
|
+
setPreviousAnimation(animation);
|
|
662
664
|
setFrameIndex(0);
|
|
663
|
-
}
|
|
665
|
+
}
|
|
664
666
|
React.useEffect(() => {
|
|
665
667
|
if (paused) {
|
|
666
668
|
return;
|
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
import { cva } from "class-variance-authority";
|
|
4
4
|
import { ArrowDownRight, ArrowRight, ArrowUpRight } from "lucide-react";
|
|
5
5
|
import { cn } from "../../lib/utils";
|
|
6
|
-
import { Card, CardContent, CardDescription, CardHeader } from "../card";
|
|
6
|
+
import { Card, CardContent, CardDescription, CardHeader } from "../card/card";
|
|
7
7
|
const statCardVariants = cva("overflow-hidden border shadow-sm", {
|
|
8
8
|
defaultVariants: {
|
|
9
9
|
tone: "neutral"
|
|
@@ -74,7 +74,7 @@ const StatCard = React.forwardRef(
|
|
|
74
74
|
...props,
|
|
75
75
|
children: [
|
|
76
76
|
/* @__PURE__ */ jsx("div", { className: accentVariants({ tone }) }),
|
|
77
|
-
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-4
|
|
77
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-4 gap-y-0 pb-3", children: [
|
|
78
78
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
79
79
|
/* @__PURE__ */ jsx(CardDescription, { className: "text-xs font-medium uppercase tracking-[0.14em]", children: label }),
|
|
80
80
|
/* @__PURE__ */ jsx("div", { className: "text-3xl font-semibold tracking-tight", children: value })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { cn } from "../../lib/utils";
|
|
4
|
-
import { Badge } from "../badge";
|
|
4
|
+
import { Badge } from "../badge/badge";
|
|
5
5
|
import {
|
|
6
6
|
Card,
|
|
7
7
|
CardContent,
|
|
@@ -71,10 +71,16 @@ function getSummary(items) {
|
|
|
71
71
|
warning: 0
|
|
72
72
|
}
|
|
73
73
|
);
|
|
74
|
-
return STATUS_ORDER.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
return STATUS_ORDER.reduce(
|
|
75
|
+
(summary, status) => {
|
|
76
|
+
const count = counts[status];
|
|
77
|
+
if (count > 0) {
|
|
78
|
+
summary.push({ count, status });
|
|
79
|
+
}
|
|
80
|
+
return summary;
|
|
81
|
+
},
|
|
82
|
+
[]
|
|
83
|
+
);
|
|
78
84
|
}
|
|
79
85
|
function StatusBoardSummary({ items }) {
|
|
80
86
|
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: getSummary(items).map(({ count, status }) => {
|
|
@@ -113,6 +119,7 @@ function StatusBoardCard({ item }) {
|
|
|
113
119
|
}
|
|
114
120
|
const StatusBoard = React.forwardRef(
|
|
115
121
|
({
|
|
122
|
+
as: Heading = "h2",
|
|
116
123
|
className,
|
|
117
124
|
columns = 3,
|
|
118
125
|
description,
|
|
@@ -123,7 +130,7 @@ const StatusBoard = React.forwardRef(
|
|
|
123
130
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), ref, ...props, children: [
|
|
124
131
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
125
132
|
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
126
|
-
/* @__PURE__ */ jsx(
|
|
133
|
+
/* @__PURE__ */ jsx(Heading, { className: "text-lg font-semibold tracking-tight", children: title }),
|
|
127
134
|
description ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description }) : null
|
|
128
135
|
] }),
|
|
129
136
|
/* @__PURE__ */ jsx(StatusBoardSummary, { items })
|
|
@@ -93,6 +93,7 @@ function InteractiveStep({
|
|
|
93
93
|
] });
|
|
94
94
|
}
|
|
95
95
|
function StepByStep({
|
|
96
|
+
as: Heading = "h3",
|
|
96
97
|
children,
|
|
97
98
|
className,
|
|
98
99
|
interactive = false,
|
|
@@ -127,7 +128,7 @@ function StepByStep({
|
|
|
127
128
|
)
|
|
128
129
|
}
|
|
129
130
|
),
|
|
130
|
-
/* @__PURE__ */ jsx(
|
|
131
|
+
/* @__PURE__ */ jsx(Heading, { className: "font-semibold text-lg", children: title })
|
|
131
132
|
] }) : null,
|
|
132
133
|
/* @__PURE__ */ jsx("div", { className: "space-y-0", children: steps.map((step, index) => {
|
|
133
134
|
const stepElement = step;
|
|
@@ -41,13 +41,16 @@ function useActiveSection(sections) {
|
|
|
41
41
|
}, [sections]);
|
|
42
42
|
return activeSection;
|
|
43
43
|
}
|
|
44
|
-
function TableOfContents({
|
|
44
|
+
function TableOfContents({
|
|
45
|
+
as: Heading = "h3",
|
|
46
|
+
sections
|
|
47
|
+
}) {
|
|
45
48
|
const activeSection = useActiveSection(sections);
|
|
46
49
|
if (sections.length === 0) {
|
|
47
50
|
return null;
|
|
48
51
|
}
|
|
49
52
|
return /* @__PURE__ */ jsx("aside", { className: "hidden xl:block", children: /* @__PURE__ */ jsx("div", { className: "sticky top-8", children: /* @__PURE__ */ jsxs("div", { className: "border-l-2 border-border pl-4", children: [
|
|
50
|
-
/* @__PURE__ */ jsx(
|
|
53
|
+
/* @__PURE__ */ jsx(Heading, { className: "text-sm font-semibold mb-4 text-muted-foreground uppercase tracking-wider", children: "On This Page" }),
|
|
51
54
|
/* @__PURE__ */ jsx("nav", { className: "space-y-2", children: sections.map((section) => /* @__PURE__ */ jsx(
|
|
52
55
|
"button",
|
|
53
56
|
{
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { memo, useEffect, useRef } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
5
|
function TableOfContentsPanelImpl({
|
|
6
|
+
as: Heading = "h2",
|
|
6
7
|
className,
|
|
7
8
|
closeIcon,
|
|
8
9
|
completedSections,
|
|
@@ -55,6 +56,7 @@ function TableOfContentsPanelImpl({
|
|
|
55
56
|
{
|
|
56
57
|
"aria-hidden": "true",
|
|
57
58
|
className: "absolute inset-0 bg-black/50 backdrop-blur-sm",
|
|
59
|
+
"data-testid": "toc-backdrop",
|
|
58
60
|
onClick: onClose
|
|
59
61
|
}
|
|
60
62
|
),
|
|
@@ -68,7 +70,7 @@ function TableOfContentsPanelImpl({
|
|
|
68
70
|
ref: panelRef,
|
|
69
71
|
children: /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col", children: [
|
|
70
72
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
|
|
71
|
-
/* @__PURE__ */ jsx(
|
|
73
|
+
/* @__PURE__ */ jsx(Heading, { className: "text-lg font-semibold", id: "toc-title", children: title }),
|
|
72
74
|
/* @__PURE__ */ jsx(
|
|
73
75
|
"button",
|
|
74
76
|
{
|
|
@@ -13,18 +13,23 @@ function useTabsContext() {
|
|
|
13
13
|
function Tabs({
|
|
14
14
|
children,
|
|
15
15
|
className,
|
|
16
|
-
defaultValue,
|
|
17
|
-
onValueChange
|
|
16
|
+
defaultValue = "",
|
|
17
|
+
onValueChange,
|
|
18
|
+
value
|
|
18
19
|
}) {
|
|
19
|
-
const [
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const [internalTab, setInternalTab] = useState(defaultValue);
|
|
21
|
+
const isControlled = value !== void 0;
|
|
22
|
+
const activeTab = isControlled ? value : internalTab;
|
|
23
|
+
const handleSetActiveTab = (next) => {
|
|
24
|
+
if (!isControlled) {
|
|
25
|
+
setInternalTab(next);
|
|
26
|
+
}
|
|
27
|
+
onValueChange?.(next);
|
|
23
28
|
};
|
|
24
29
|
const contextValue = useMemo(
|
|
25
30
|
() => ({ activeTab, setActiveTab: handleSetActiveTab }),
|
|
26
31
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
-
[activeTab]
|
|
32
|
+
[activeTab, isControlled]
|
|
28
33
|
);
|
|
29
34
|
return /* @__PURE__ */ jsx(TabsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { className: cn("my-6", className), children }) });
|
|
30
35
|
}
|
|
@@ -39,8 +44,10 @@ function TabsList({ children, className }) {
|
|
|
39
44
|
);
|
|
40
45
|
}
|
|
41
46
|
function TabsTrigger({
|
|
47
|
+
"aria-hidden": ariaHidden,
|
|
42
48
|
children,
|
|
43
49
|
className,
|
|
50
|
+
tabIndex,
|
|
44
51
|
value
|
|
45
52
|
}) {
|
|
46
53
|
const { activeTab, setActiveTab } = useTabsContext();
|
|
@@ -48,6 +55,7 @@ function TabsTrigger({
|
|
|
48
55
|
return /* @__PURE__ */ jsx(
|
|
49
56
|
"button",
|
|
50
57
|
{
|
|
58
|
+
"aria-hidden": ariaHidden,
|
|
51
59
|
"aria-selected": isActive,
|
|
52
60
|
className: cn(
|
|
53
61
|
"px-4 py-2 text-sm font-medium whitespace-nowrap transition-colors",
|
|
@@ -59,19 +67,29 @@ function TabsTrigger({
|
|
|
59
67
|
setActiveTab(value);
|
|
60
68
|
},
|
|
61
69
|
role: "tab",
|
|
70
|
+
tabIndex,
|
|
62
71
|
type: "button",
|
|
63
72
|
children
|
|
64
73
|
}
|
|
65
74
|
);
|
|
66
75
|
}
|
|
67
76
|
function TabsContent({
|
|
77
|
+
"aria-hidden": ariaHidden,
|
|
68
78
|
children,
|
|
69
79
|
className,
|
|
70
80
|
value
|
|
71
81
|
}) {
|
|
72
82
|
const { activeTab } = useTabsContext();
|
|
73
83
|
if (activeTab !== value) return null;
|
|
74
|
-
return /* @__PURE__ */ jsx(
|
|
84
|
+
return /* @__PURE__ */ jsx(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
"aria-hidden": ariaHidden,
|
|
88
|
+
className: cn("pt-4", className),
|
|
89
|
+
role: "tabpanel",
|
|
90
|
+
children
|
|
91
|
+
}
|
|
92
|
+
);
|
|
75
93
|
}
|
|
76
94
|
Tabs.List = TabsList;
|
|
77
95
|
Tabs.Trigger = TabsTrigger;
|
|
@@ -7,9 +7,17 @@ function normalizeTag(tag) {
|
|
|
7
7
|
return tag.trim();
|
|
8
8
|
}
|
|
9
9
|
function getNormalizedTags(tags) {
|
|
10
|
-
return tags.
|
|
11
|
-
(
|
|
12
|
-
|
|
10
|
+
return tags.reduce(
|
|
11
|
+
(state, tag) => {
|
|
12
|
+
const normalizedTag = normalizeTag(tag);
|
|
13
|
+
if (normalizedTag.length > 0 && !state.seen.has(normalizedTag)) {
|
|
14
|
+
state.seen.add(normalizedTag);
|
|
15
|
+
state.tags.push(normalizedTag);
|
|
16
|
+
}
|
|
17
|
+
return state;
|
|
18
|
+
},
|
|
19
|
+
{ seen: /* @__PURE__ */ new Set(), tags: [] }
|
|
20
|
+
).tags;
|
|
13
21
|
}
|
|
14
22
|
function shouldAddTagFromKey(key) {
|
|
15
23
|
return key === "Enter" || key === ",";
|
|
@@ -2,14 +2,22 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { Check, Copy, Terminal as TerminalIcon } from "lucide-react";
|
|
5
|
-
import { Button } from "../button";
|
|
5
|
+
import { Button } from "../button/button";
|
|
6
|
+
function getCommandContents(lines) {
|
|
7
|
+
return lines.reduce((commands, line) => {
|
|
8
|
+
if (line.type === "command") {
|
|
9
|
+
commands.push(line.content);
|
|
10
|
+
}
|
|
11
|
+
return commands;
|
|
12
|
+
}, []);
|
|
13
|
+
}
|
|
6
14
|
function Terminal({
|
|
7
15
|
copyable = true,
|
|
8
16
|
lines,
|
|
9
17
|
title = "Terminal"
|
|
10
18
|
}) {
|
|
11
19
|
const [copied, setCopied] = useState(false);
|
|
12
|
-
const commands = lines
|
|
20
|
+
const commands = getCommandContents(lines);
|
|
13
21
|
const handleCopy = async () => {
|
|
14
22
|
await navigator.clipboard.writeText(commands.join("\n"));
|
|
15
23
|
setCopied(true);
|
|
@@ -75,7 +83,7 @@ function SimpleTerminal({
|
|
|
75
83
|
}
|
|
76
84
|
return { content: line, type: "output" };
|
|
77
85
|
});
|
|
78
|
-
const commands = lines
|
|
86
|
+
const commands = getCommandContents(lines);
|
|
79
87
|
const handleCopy = async () => {
|
|
80
88
|
await navigator.clipboard.writeText(commands.join("\n"));
|
|
81
89
|
setCopied(true);
|
|
@@ -20,7 +20,7 @@ function ThemeButton({
|
|
|
20
20
|
Button,
|
|
21
21
|
{
|
|
22
22
|
"aria-label": ariaLabel,
|
|
23
|
-
className: "bg-background text-foreground border border-
|
|
23
|
+
className: "bg-background text-foreground border border-zinc-300 dark:border-zinc-600 hover:border-zinc-400 dark:hover:border-zinc-500 transition-colors",
|
|
24
24
|
size: "icon",
|
|
25
25
|
variant: "outline",
|
|
26
26
|
...props,
|
|
@@ -120,7 +120,7 @@ function ThemeToggle({ dict }) {
|
|
|
120
120
|
DropdownMenuContent,
|
|
121
121
|
{
|
|
122
122
|
align: "end",
|
|
123
|
-
className: "bg-background border border-
|
|
123
|
+
className: "bg-background border border-zinc-300 dark:border-zinc-600",
|
|
124
124
|
onMouseEnter: () => {
|
|
125
125
|
isHoveringOverMenuAreaReference.current = true;
|
|
126
126
|
clearCloseTimer();
|
|
@@ -33,7 +33,7 @@ function ThinkingBlock({
|
|
|
33
33
|
isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-3" }),
|
|
34
34
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
35
35
|
"Thinking",
|
|
36
|
-
isStreaming ? /* @__PURE__ */ jsx("span", { className: "ml-1 animate-pulse", children: "
|
|
36
|
+
isStreaming ? /* @__PURE__ */ jsx("span", { className: "ml-1 animate-pulse", children: "\u2026" }) : null
|
|
37
37
|
] })
|
|
38
38
|
]
|
|
39
39
|
}
|
|
@@ -41,7 +41,7 @@ function ThinkingBlock({
|
|
|
41
41
|
isExpanded ? /* @__PURE__ */ jsxs(
|
|
42
42
|
"div",
|
|
43
43
|
{
|
|
44
|
-
className: "mt-2 p-3 bg-muted/50 rounded text-xs text-muted-foreground whitespace-pre-wrap border-l
|
|
44
|
+
className: "mt-2 p-3 bg-muted/50 rounded text-xs text-muted-foreground whitespace-pre-wrap border-l border-muted-foreground/30 max-h-48 overflow-y-auto",
|
|
45
45
|
id: contentId,
|
|
46
46
|
children: [
|
|
47
47
|
thinking,
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { ArrowDownRight, ArrowUpRight, Dot } from "lucide-react";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
|
-
import { Badge } from "../badge";
|
|
5
|
+
import { Badge } from "../badge/badge";
|
|
6
6
|
const tickerTapeKeyframes = `
|
|
7
7
|
@keyframes ticker-tape-scroll {
|
|
8
8
|
from {
|
|
@@ -125,7 +125,7 @@ const TimelineScrubber = forwardRef((props, ref) => {
|
|
|
125
125
|
const span = safeEnd - start;
|
|
126
126
|
const clamped = clamp(value, start, safeEnd);
|
|
127
127
|
const ratio = clamp((clamped - start) / span, 0, 1);
|
|
128
|
-
const
|
|
128
|
+
const handleScrubberValueChange = (event) => {
|
|
129
129
|
onValueChange(clamp(Number(event.target.value), start, safeEnd));
|
|
130
130
|
};
|
|
131
131
|
return /* @__PURE__ */ jsxs(
|
|
@@ -158,7 +158,7 @@ const TimelineScrubber = forwardRef((props, ref) => {
|
|
|
158
158
|
inputId,
|
|
159
159
|
max: safeEnd,
|
|
160
160
|
min: start,
|
|
161
|
-
onChange:
|
|
161
|
+
onChange: handleScrubberValueChange,
|
|
162
162
|
ratio,
|
|
163
163
|
scrubberId: inputId,
|
|
164
164
|
span,
|
|
@@ -3,20 +3,20 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
function TLDRSection({ children, label }) {
|
|
5
5
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
6
|
-
const [
|
|
7
|
-
const
|
|
6
|
+
const [showSkeleton, setShowSkeleton] = useState(false);
|
|
7
|
+
const hasBeenOpenedRef = useRef(false);
|
|
8
8
|
const timerReference = useRef(null);
|
|
9
9
|
useEffect(() => {
|
|
10
|
-
if (isExpanded && !
|
|
10
|
+
if (isExpanded && !hasBeenOpenedRef.current) {
|
|
11
11
|
if (timerReference.current) {
|
|
12
12
|
clearTimeout(timerReference.current);
|
|
13
13
|
}
|
|
14
14
|
const rafId = requestAnimationFrame(() => {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
setShowSkeleton(true);
|
|
16
|
+
hasBeenOpenedRef.current = true;
|
|
17
17
|
});
|
|
18
18
|
timerReference.current = setTimeout(() => {
|
|
19
|
-
|
|
19
|
+
setShowSkeleton(false);
|
|
20
20
|
timerReference.current = null;
|
|
21
21
|
}, 800);
|
|
22
22
|
return () => {
|
|
@@ -25,6 +25,7 @@ function TLDRSection({ children, label }) {
|
|
|
25
25
|
clearTimeout(timerReference.current);
|
|
26
26
|
timerReference.current = null;
|
|
27
27
|
}
|
|
28
|
+
setShowSkeleton(false);
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
return () => {
|
|
@@ -32,6 +33,7 @@ function TLDRSection({ children, label }) {
|
|
|
32
33
|
clearTimeout(timerReference.current);
|
|
33
34
|
timerReference.current = null;
|
|
34
35
|
}
|
|
36
|
+
setShowSkeleton(false);
|
|
35
37
|
};
|
|
36
38
|
}, [isExpanded]);
|
|
37
39
|
return /* @__PURE__ */ jsxs("div", { className: "my-8 rounded-lg border border-border bg-muted/30 overflow-hidden", children: [
|
|
@@ -88,7 +90,7 @@ function TLDRSection({ children, label }) {
|
|
|
88
90
|
]
|
|
89
91
|
}
|
|
90
92
|
),
|
|
91
|
-
isExpanded ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-4 pt-2 border-t border-border", children:
|
|
93
|
+
isExpanded ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-4 pt-2 border-t border-border", children: showSkeleton ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
92
94
|
/* @__PURE__ */ jsx("div", { className: "relative h-4 bg-muted/50 rounded overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent animate-shimmer" }) }),
|
|
93
95
|
/* @__PURE__ */ jsx("div", { className: "relative h-4 bg-muted/50 rounded overflow-hidden w-5/6", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent animate-shimmer" }) }),
|
|
94
96
|
/* @__PURE__ */ jsx("div", { className: "relative h-4 bg-muted/50 rounded overflow-hidden w-4/5", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent animate-shimmer" }) }),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { cn } from "../../lib/utils";
|
|
5
|
-
import { Badge } from "../badge";
|
|
5
|
+
import { Badge } from "../badge/badge";
|
|
6
6
|
import { Button } from "../button";
|
|
7
7
|
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "../card";
|
|
8
8
|
function TourHeader({
|
|
@@ -12,7 +12,7 @@ function getCurrencyFormatter(locale, currency) {
|
|
|
12
12
|
const key = `${locale}|${currency}`;
|
|
13
13
|
let formatter = CURRENCY_FORMATTER_CACHE.get(key);
|
|
14
14
|
if (!formatter) {
|
|
15
|
-
formatter =
|
|
15
|
+
formatter = Intl.NumberFormat(locale, {
|
|
16
16
|
currency,
|
|
17
17
|
style: "currency"
|
|
18
18
|
});
|
|
@@ -24,7 +24,7 @@ const DATE_FORMATTER_CACHE = /* @__PURE__ */ new Map();
|
|
|
24
24
|
function getTransactionDateFormatter(locale) {
|
|
25
25
|
let formatter = DATE_FORMATTER_CACHE.get(locale);
|
|
26
26
|
if (!formatter) {
|
|
27
|
-
formatter =
|
|
27
|
+
formatter = Intl.DateTimeFormat(locale, {
|
|
28
28
|
day: "numeric",
|
|
29
29
|
month: "short",
|
|
30
30
|
year: "numeric"
|