@vllnt/ui 0.1.11 → 0.2.0-canary.4abf494
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 +104 -0
- package/README.md +106 -1
- package/dist/components/activity-heatmap/activity-heatmap.js +168 -0
- package/dist/components/activity-heatmap/index.js +6 -0
- package/dist/components/activity-log/activity-log.js +256 -0
- package/dist/components/activity-log/index.js +6 -0
- package/dist/components/ai-chat-input/ai-chat-input.js +107 -0
- package/dist/components/ai-chat-input/index.js +4 -0
- package/dist/components/ai-message-bubble/ai-message-bubble.js +119 -0
- package/dist/components/ai-message-bubble/index.js +6 -0
- package/dist/components/ai-source-citation/ai-source-citation.js +39 -0
- package/dist/components/ai-source-citation/index.js +6 -0
- package/dist/components/ai-streaming-text/ai-streaming-text.js +41 -0
- package/dist/components/ai-streaming-text/index.js +6 -0
- package/dist/components/ai-tool-call-display/ai-tool-call-display.js +93 -0
- package/dist/components/ai-tool-call-display/index.js +6 -0
- package/dist/components/animated-text/animated-text.js +328 -0
- package/dist/components/animated-text/index.js +4 -0
- package/dist/components/annotation/annotation.js +49 -0
- package/dist/components/annotation/index.js +8 -0
- package/dist/components/avatar-group/avatar-group.js +82 -0
- package/dist/components/avatar-group/index.js +10 -0
- package/dist/components/border-beam/border-beam.js +51 -0
- package/dist/components/border-beam/index.js +4 -0
- package/dist/components/candlestick-chart/candlestick-chart.js +215 -0
- package/dist/components/candlestick-chart/index.js +6 -0
- package/dist/components/combobox/combobox.js +130 -0
- package/dist/components/combobox/index.js +4 -0
- package/dist/components/countdown-timer/countdown-timer.js +184 -0
- package/dist/components/countdown-timer/index.js +4 -0
- package/dist/components/credit-badge/credit-badge.js +59 -0
- package/dist/components/credit-badge/index.js +6 -0
- package/dist/components/data-list/data-list.js +99 -0
- package/dist/components/data-list/index.js +16 -0
- package/dist/components/data-table/data-table.js +242 -0
- package/dist/components/data-table/index.js +6 -0
- package/dist/components/date-picker/date-picker.js +74 -0
- package/dist/components/date-picker/index.js +4 -0
- package/dist/components/file-upload/file-upload.js +227 -0
- package/dist/components/file-upload/index.js +4 -0
- package/dist/components/flashcard/flashcard.js +66 -0
- package/dist/components/flashcard/index.js +4 -0
- package/dist/components/index.js +172 -1
- package/dist/components/live-feed/index.js +4 -0
- package/dist/components/live-feed/live-feed.js +168 -0
- package/dist/components/market-treemap/index.js +6 -0
- package/dist/components/market-treemap/market-treemap.js +100 -0
- package/dist/components/marquee/index.js +4 -0
- package/dist/components/marquee/marquee.js +98 -0
- package/dist/components/metric-gauge/index.js +6 -0
- package/dist/components/metric-gauge/metric-gauge.js +213 -0
- package/dist/components/model-selector/model-selector.js +11 -2
- package/dist/components/number-input/index.js +4 -0
- package/dist/components/number-input/number-input.js +167 -0
- package/dist/components/number-ticker/index.js +4 -0
- package/dist/components/number-ticker/number-ticker.js +63 -0
- package/dist/components/order-book/index.js +6 -0
- package/dist/components/order-book/order-book.js +128 -0
- package/dist/components/password-input/index.js +4 -0
- package/dist/components/password-input/password-input.js +45 -0
- package/dist/components/plan-badge/index.js +6 -0
- package/dist/components/plan-badge/plan-badge.js +67 -0
- package/dist/components/rating/index.js +4 -0
- package/dist/components/rating/rating.js +121 -0
- package/dist/components/role-badge/index.js +6 -0
- package/dist/components/role-badge/role-badge.js +50 -0
- package/dist/components/scope-selector/index.js +6 -0
- package/dist/components/scope-selector/scope-selector.js +336 -0
- package/dist/components/severity-badge/index.js +8 -0
- package/dist/components/severity-badge/severity-badge.js +163 -0
- package/dist/components/sparkline-grid/index.js +6 -0
- package/dist/components/sparkline-grid/sparkline-grid.js +92 -0
- package/dist/components/spinner/index.js +5 -1
- package/dist/components/spinner/unicode-spinner.js +708 -0
- package/dist/components/stat-card/index.js +5 -0
- package/dist/components/stat-card/stat-card.js +102 -0
- package/dist/components/status-board/index.js +6 -0
- package/dist/components/status-board/status-board.js +138 -0
- package/dist/components/status-indicator/index.js +10 -0
- package/dist/components/status-indicator/status-indicator.js +175 -0
- package/dist/components/stepper/index.js +4 -0
- package/dist/components/stepper/stepper.js +117 -0
- package/dist/components/subscription-card/index.js +6 -0
- package/dist/components/subscription-card/subscription-card.js +161 -0
- package/dist/components/ticker-tape/index.js +6 -0
- package/dist/components/ticker-tape/ticker-tape.js +106 -0
- package/dist/components/tour/index.js +4 -0
- package/dist/components/tour/tour.js +157 -0
- package/dist/components/usage-breakdown/index.js +6 -0
- package/dist/components/usage-breakdown/usage-breakdown.js +140 -0
- package/dist/components/wallet-card/index.js +4 -0
- package/dist/components/wallet-card/wallet-card.js +115 -0
- package/dist/components/watchlist/index.js +6 -0
- package/dist/components/watchlist/watchlist.js +110 -0
- package/dist/components/world-clock-bar/index.js +6 -0
- package/dist/components/world-clock-bar/world-clock-bar.js +101 -0
- package/dist/index.d.ts +1173 -7
- package/dist/test-setup.js +19 -0
- package/package.json +27 -6
- package/styles.css +55 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
import { Button } from "../button/button";
|
|
5
|
+
import {
|
|
6
|
+
Card,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardDescription,
|
|
9
|
+
CardFooter,
|
|
10
|
+
CardHeader,
|
|
11
|
+
CardTitle
|
|
12
|
+
} from "../card/card";
|
|
13
|
+
import {
|
|
14
|
+
CreditBadge
|
|
15
|
+
} from "../credit-badge/credit-badge";
|
|
16
|
+
function DetailRow({ label, value }) {
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4 text-sm", children: [
|
|
18
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
|
|
19
|
+
/* @__PURE__ */ jsx("span", { className: "text-right font-medium", children: value })
|
|
20
|
+
] });
|
|
21
|
+
}
|
|
22
|
+
function WalletDetails({
|
|
23
|
+
availableLabel,
|
|
24
|
+
balanceLabel,
|
|
25
|
+
note,
|
|
26
|
+
pendingLabel,
|
|
27
|
+
renewsLabel
|
|
28
|
+
}) {
|
|
29
|
+
return /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
30
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border/70 bg-background px-4 py-3", children: [
|
|
31
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-[0.18em] text-muted-foreground", children: "Current balance" }),
|
|
32
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-3xl font-semibold tracking-tight", children: balanceLabel })
|
|
33
|
+
] }),
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3 rounded-lg border border-border/70 bg-muted/20 px-4 py-4", children: [
|
|
35
|
+
availableLabel ? /* @__PURE__ */ jsx(DetailRow, { label: "Available now", value: availableLabel }) : null,
|
|
36
|
+
pendingLabel ? /* @__PURE__ */ jsx(DetailRow, { label: "Pending", value: pendingLabel }) : null,
|
|
37
|
+
renewsLabel ? /* @__PURE__ */ jsx(DetailRow, { label: "Refresh", value: renewsLabel }) : null
|
|
38
|
+
] }),
|
|
39
|
+
note ? /* @__PURE__ */ jsx("p", { className: "rounded-lg bg-muted px-4 py-3 text-sm text-muted-foreground", children: note }) : null
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
function WalletActions({
|
|
43
|
+
primaryActionLabel,
|
|
44
|
+
secondaryActionLabel
|
|
45
|
+
}) {
|
|
46
|
+
if (!primaryActionLabel && !secondaryActionLabel) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ jsxs(CardFooter, { className: "flex flex-col gap-2 sm:flex-row sm:justify-end", children: [
|
|
50
|
+
secondaryActionLabel ? /* @__PURE__ */ jsx(Button, { className: "w-full sm:w-auto", variant: "outline", children: secondaryActionLabel }) : null,
|
|
51
|
+
primaryActionLabel ? /* @__PURE__ */ jsx(Button, { className: "w-full sm:w-auto", children: primaryActionLabel }) : null
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
const WalletCard = React.forwardRef(
|
|
55
|
+
({
|
|
56
|
+
availableLabel,
|
|
57
|
+
balanceLabel,
|
|
58
|
+
className,
|
|
59
|
+
note,
|
|
60
|
+
pendingLabel,
|
|
61
|
+
primaryActionLabel,
|
|
62
|
+
renewsLabel,
|
|
63
|
+
secondaryActionLabel,
|
|
64
|
+
status,
|
|
65
|
+
...props
|
|
66
|
+
}, reference) => {
|
|
67
|
+
return /* @__PURE__ */ jsxs(
|
|
68
|
+
Card,
|
|
69
|
+
{
|
|
70
|
+
className: cn(
|
|
71
|
+
"w-full max-w-md border-border/70 bg-card shadow-sm",
|
|
72
|
+
className
|
|
73
|
+
),
|
|
74
|
+
ref: reference,
|
|
75
|
+
...props,
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "space-y-4 pb-4", children: [
|
|
78
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
79
|
+
/* @__PURE__ */ jsx(CardTitle, { className: "text-lg", children: "Wallet" }),
|
|
80
|
+
/* @__PURE__ */ jsx(CardDescription, { children: "Track credits, pending top-ups, and replenishment timing." })
|
|
81
|
+
] }),
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 rounded-lg border border-border/70 bg-muted/30 px-4 py-3", children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
84
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Available balance" }),
|
|
85
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: renewsLabel ?? "Credits refresh automatically when enabled." })
|
|
86
|
+
] }),
|
|
87
|
+
/* @__PURE__ */ jsx(CreditBadge, { amount: balanceLabel, status })
|
|
88
|
+
] })
|
|
89
|
+
] }),
|
|
90
|
+
/* @__PURE__ */ jsx(
|
|
91
|
+
WalletDetails,
|
|
92
|
+
{
|
|
93
|
+
availableLabel,
|
|
94
|
+
balanceLabel,
|
|
95
|
+
note,
|
|
96
|
+
pendingLabel,
|
|
97
|
+
renewsLabel
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
/* @__PURE__ */ jsx(
|
|
101
|
+
WalletActions,
|
|
102
|
+
{
|
|
103
|
+
primaryActionLabel,
|
|
104
|
+
secondaryActionLabel
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
WalletCard.displayName = "WalletCard";
|
|
113
|
+
export {
|
|
114
|
+
WalletCard
|
|
115
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ArrowDownRight, ArrowUpRight, Star } from "lucide-react";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
function formatPrice(price) {
|
|
6
|
+
return typeof price === "number" ? price.toLocaleString(void 0, {
|
|
7
|
+
maximumFractionDigits: 2,
|
|
8
|
+
minimumFractionDigits: 2
|
|
9
|
+
}) : price;
|
|
10
|
+
}
|
|
11
|
+
function formatChange(change) {
|
|
12
|
+
const sign = change > 0 ? "+" : "";
|
|
13
|
+
return `${sign}${change.toFixed(2)}%`;
|
|
14
|
+
}
|
|
15
|
+
function WatchlistRow({ item }) {
|
|
16
|
+
const isPositive = item.change >= 0;
|
|
17
|
+
const TrendIcon = isPositive ? ArrowUpRight : ArrowDownRight;
|
|
18
|
+
return /* @__PURE__ */ jsxs("li", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto_auto] items-center gap-3 rounded-xl px-3 py-2.5 transition-colors hover:bg-muted/40", children: [
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
"span",
|
|
21
|
+
{
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
className: cn(
|
|
24
|
+
"flex h-7 w-7 items-center justify-center rounded-full border",
|
|
25
|
+
item.starred ? "border-amber-400/40 bg-amber-400/10 text-amber-500" : "border-border bg-background text-muted-foreground"
|
|
26
|
+
),
|
|
27
|
+
children: /* @__PURE__ */ jsx(
|
|
28
|
+
Star,
|
|
29
|
+
{
|
|
30
|
+
className: cn("h-3.5 w-3.5", item.starred && "fill-current"),
|
|
31
|
+
strokeWidth: 1.75
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
37
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-foreground", children: item.symbol }),
|
|
38
|
+
item.name ? /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: item.name }) : null
|
|
39
|
+
] }),
|
|
40
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
41
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold tabular-nums text-foreground", children: formatPrice(item.price) }),
|
|
42
|
+
item.volume ? /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground tabular-nums", children: item.volume }) : null
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsxs(
|
|
45
|
+
"span",
|
|
46
|
+
{
|
|
47
|
+
className: cn(
|
|
48
|
+
"inline-flex items-center gap-1 rounded-full border px-2 py-1 text-xs font-medium tabular-nums",
|
|
49
|
+
isPositive ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" : "border-rose-500/30 bg-rose-500/10 text-rose-600 dark:text-rose-400"
|
|
50
|
+
),
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsx(TrendIcon, { className: "h-3 w-3" }),
|
|
53
|
+
formatChange(item.change)
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
] });
|
|
58
|
+
}
|
|
59
|
+
const Watchlist = React.forwardRef(
|
|
60
|
+
({
|
|
61
|
+
className,
|
|
62
|
+
eyebrow = "Tracked symbols",
|
|
63
|
+
items,
|
|
64
|
+
title = "Watchlist",
|
|
65
|
+
...props
|
|
66
|
+
}, reference) => {
|
|
67
|
+
if (items.length === 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const advancing = items.filter((item) => item.change >= 0).length;
|
|
71
|
+
const declining = items.length - advancing;
|
|
72
|
+
return /* @__PURE__ */ jsxs(
|
|
73
|
+
"section",
|
|
74
|
+
{
|
|
75
|
+
"aria-label": title,
|
|
76
|
+
className: cn(
|
|
77
|
+
"rounded-2xl border border-border bg-card/80 p-4 shadow-sm",
|
|
78
|
+
className
|
|
79
|
+
),
|
|
80
|
+
ref: reference,
|
|
81
|
+
...props,
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("header", { className: "mb-3 flex flex-wrap items-start justify-between gap-3", children: [
|
|
84
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
85
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-[0.28em] text-muted-foreground", children: eyebrow }),
|
|
86
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: title })
|
|
87
|
+
] }),
|
|
88
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
89
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full border border-emerald-500/30 bg-emerald-500/10 px-2 py-1 text-emerald-600 dark:text-emerald-400", children: [
|
|
90
|
+
/* @__PURE__ */ jsx(ArrowUpRight, { className: "h-3 w-3" }),
|
|
91
|
+
advancing,
|
|
92
|
+
" up"
|
|
93
|
+
] }),
|
|
94
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full border border-rose-500/30 bg-rose-500/10 px-2 py-1 text-rose-600 dark:text-rose-400", children: [
|
|
95
|
+
/* @__PURE__ */ jsx(ArrowDownRight, { className: "h-3 w-3" }),
|
|
96
|
+
declining,
|
|
97
|
+
" down"
|
|
98
|
+
] })
|
|
99
|
+
] })
|
|
100
|
+
] }),
|
|
101
|
+
/* @__PURE__ */ jsx("ul", { className: "divide-y divide-border/60", children: items.map((item) => /* @__PURE__ */ jsx(WatchlistRow, { item }, item.symbol)) })
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
Watchlist.displayName = "Watchlist";
|
|
108
|
+
export {
|
|
109
|
+
Watchlist
|
|
110
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { Badge } from "../badge";
|
|
6
|
+
function normalizeDate(input) {
|
|
7
|
+
if (input instanceof Date) {
|
|
8
|
+
return new Date(input.getTime());
|
|
9
|
+
}
|
|
10
|
+
return new Date(input);
|
|
11
|
+
}
|
|
12
|
+
function useLiveDate(now, updateIntervalMs) {
|
|
13
|
+
const fixedNow = React.useMemo(
|
|
14
|
+
() => now ? normalizeDate(now) : void 0,
|
|
15
|
+
[now]
|
|
16
|
+
);
|
|
17
|
+
const [liveNow, setLiveNow] = React.useState(fixedNow ?? /* @__PURE__ */ new Date());
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (fixedNow) {
|
|
20
|
+
setLiveNow(fixedNow);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const interval = window.setInterval(() => {
|
|
24
|
+
setLiveNow(/* @__PURE__ */ new Date());
|
|
25
|
+
}, updateIntervalMs);
|
|
26
|
+
return () => {
|
|
27
|
+
window.clearInterval(interval);
|
|
28
|
+
};
|
|
29
|
+
}, [fixedNow, updateIntervalMs]);
|
|
30
|
+
return liveNow;
|
|
31
|
+
}
|
|
32
|
+
function formatZoneDateTime(zone, date, showDate) {
|
|
33
|
+
const locale = zone.locale ?? "en-US";
|
|
34
|
+
const timeFormatter = new Intl.DateTimeFormat(locale, {
|
|
35
|
+
hour: "numeric",
|
|
36
|
+
minute: "2-digit",
|
|
37
|
+
timeZone: zone.timeZone,
|
|
38
|
+
timeZoneName: "short"
|
|
39
|
+
});
|
|
40
|
+
const dateFormatter = new Intl.DateTimeFormat(locale, {
|
|
41
|
+
day: "numeric",
|
|
42
|
+
month: "short",
|
|
43
|
+
timeZone: zone.timeZone,
|
|
44
|
+
weekday: "short"
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
date: showDate ? dateFormatter.format(date) : "",
|
|
48
|
+
time: timeFormatter.format(date)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function WorldClockCard({
|
|
52
|
+
date,
|
|
53
|
+
showDate,
|
|
54
|
+
zone
|
|
55
|
+
}) {
|
|
56
|
+
const formatted = formatZoneDateTime(zone, date, showDate);
|
|
57
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-w-[190px] rounded-lg border bg-card px-4 py-3 shadow-sm", children: [
|
|
58
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium", children: zone.city }),
|
|
59
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-2xl font-semibold tracking-tight", children: formatted.time }),
|
|
60
|
+
showDate ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-muted-foreground", children: formatted.date }) : null,
|
|
61
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3 text-[11px] uppercase tracking-[0.16em] text-muted-foreground", children: zone.timeZone })
|
|
62
|
+
] });
|
|
63
|
+
}
|
|
64
|
+
const WorldClockBar = React.forwardRef(
|
|
65
|
+
({
|
|
66
|
+
className,
|
|
67
|
+
now,
|
|
68
|
+
showDate = true,
|
|
69
|
+
title = "World clock",
|
|
70
|
+
updateIntervalMs = 6e4,
|
|
71
|
+
zones,
|
|
72
|
+
...props
|
|
73
|
+
}, ref) => {
|
|
74
|
+
const liveNow = useLiveDate(now, updateIntervalMs);
|
|
75
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), ref, ...props, children: [
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
77
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
78
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold tracking-tight", children: title }),
|
|
79
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Synchronized time across distributed teams and regions." })
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsxs(Badge, { variant: "outline", children: [
|
|
82
|
+
zones.length,
|
|
83
|
+
" zones"
|
|
84
|
+
] })
|
|
85
|
+
] }),
|
|
86
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-3 overflow-x-auto pb-1", children: zones.map((zone) => /* @__PURE__ */ jsx(
|
|
87
|
+
WorldClockCard,
|
|
88
|
+
{
|
|
89
|
+
date: liveNow,
|
|
90
|
+
showDate,
|
|
91
|
+
zone
|
|
92
|
+
},
|
|
93
|
+
`${zone.city}-${zone.timeZone}`
|
|
94
|
+
)) })
|
|
95
|
+
] });
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
WorldClockBar.displayName = "WorldClockBar";
|
|
99
|
+
export {
|
|
100
|
+
WorldClockBar
|
|
101
|
+
};
|