@vllnt/ui 0.1.11 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +106 -1
  3. package/dist/components/activity-heatmap/activity-heatmap.js +168 -0
  4. package/dist/components/activity-heatmap/index.js +6 -0
  5. package/dist/components/activity-log/activity-log.js +256 -0
  6. package/dist/components/activity-log/index.js +6 -0
  7. package/dist/components/ai-chat-input/ai-chat-input.js +107 -0
  8. package/dist/components/ai-chat-input/index.js +4 -0
  9. package/dist/components/ai-message-bubble/ai-message-bubble.js +119 -0
  10. package/dist/components/ai-message-bubble/index.js +6 -0
  11. package/dist/components/ai-source-citation/ai-source-citation.js +39 -0
  12. package/dist/components/ai-source-citation/index.js +6 -0
  13. package/dist/components/ai-streaming-text/ai-streaming-text.js +41 -0
  14. package/dist/components/ai-streaming-text/index.js +6 -0
  15. package/dist/components/ai-tool-call-display/ai-tool-call-display.js +93 -0
  16. package/dist/components/ai-tool-call-display/index.js +6 -0
  17. package/dist/components/animated-text/animated-text.js +328 -0
  18. package/dist/components/animated-text/index.js +4 -0
  19. package/dist/components/annotation/annotation.js +49 -0
  20. package/dist/components/annotation/index.js +8 -0
  21. package/dist/components/avatar-group/avatar-group.js +82 -0
  22. package/dist/components/avatar-group/index.js +10 -0
  23. package/dist/components/border-beam/border-beam.js +51 -0
  24. package/dist/components/border-beam/index.js +4 -0
  25. package/dist/components/candlestick-chart/candlestick-chart.js +215 -0
  26. package/dist/components/candlestick-chart/index.js +6 -0
  27. package/dist/components/combobox/combobox.js +130 -0
  28. package/dist/components/combobox/index.js +4 -0
  29. package/dist/components/countdown-timer/countdown-timer.js +184 -0
  30. package/dist/components/countdown-timer/index.js +4 -0
  31. package/dist/components/credit-badge/credit-badge.js +59 -0
  32. package/dist/components/credit-badge/index.js +6 -0
  33. package/dist/components/data-list/data-list.js +99 -0
  34. package/dist/components/data-list/index.js +16 -0
  35. package/dist/components/data-table/data-table.js +242 -0
  36. package/dist/components/data-table/index.js +6 -0
  37. package/dist/components/date-picker/date-picker.js +74 -0
  38. package/dist/components/date-picker/index.js +4 -0
  39. package/dist/components/file-upload/file-upload.js +227 -0
  40. package/dist/components/file-upload/index.js +4 -0
  41. package/dist/components/flashcard/flashcard.js +66 -0
  42. package/dist/components/flashcard/index.js +4 -0
  43. package/dist/components/index.js +172 -1
  44. package/dist/components/live-feed/index.js +4 -0
  45. package/dist/components/live-feed/live-feed.js +168 -0
  46. package/dist/components/market-treemap/index.js +6 -0
  47. package/dist/components/market-treemap/market-treemap.js +100 -0
  48. package/dist/components/marquee/index.js +4 -0
  49. package/dist/components/marquee/marquee.js +98 -0
  50. package/dist/components/metric-gauge/index.js +6 -0
  51. package/dist/components/metric-gauge/metric-gauge.js +213 -0
  52. package/dist/components/model-selector/model-selector.js +11 -2
  53. package/dist/components/number-input/index.js +4 -0
  54. package/dist/components/number-input/number-input.js +167 -0
  55. package/dist/components/number-ticker/index.js +4 -0
  56. package/dist/components/number-ticker/number-ticker.js +63 -0
  57. package/dist/components/order-book/index.js +6 -0
  58. package/dist/components/order-book/order-book.js +128 -0
  59. package/dist/components/password-input/index.js +4 -0
  60. package/dist/components/password-input/password-input.js +45 -0
  61. package/dist/components/plan-badge/index.js +6 -0
  62. package/dist/components/plan-badge/plan-badge.js +67 -0
  63. package/dist/components/rating/index.js +4 -0
  64. package/dist/components/rating/rating.js +121 -0
  65. package/dist/components/role-badge/index.js +6 -0
  66. package/dist/components/role-badge/role-badge.js +50 -0
  67. package/dist/components/scope-selector/index.js +6 -0
  68. package/dist/components/scope-selector/scope-selector.js +336 -0
  69. package/dist/components/severity-badge/index.js +8 -0
  70. package/dist/components/severity-badge/severity-badge.js +163 -0
  71. package/dist/components/sparkline-grid/index.js +6 -0
  72. package/dist/components/sparkline-grid/sparkline-grid.js +92 -0
  73. package/dist/components/spinner/index.js +5 -1
  74. package/dist/components/spinner/unicode-spinner.js +708 -0
  75. package/dist/components/stat-card/index.js +5 -0
  76. package/dist/components/stat-card/stat-card.js +102 -0
  77. package/dist/components/status-board/index.js +6 -0
  78. package/dist/components/status-board/status-board.js +138 -0
  79. package/dist/components/status-indicator/index.js +10 -0
  80. package/dist/components/status-indicator/status-indicator.js +175 -0
  81. package/dist/components/stepper/index.js +4 -0
  82. package/dist/components/stepper/stepper.js +117 -0
  83. package/dist/components/subscription-card/index.js +6 -0
  84. package/dist/components/subscription-card/subscription-card.js +161 -0
  85. package/dist/components/ticker-tape/index.js +6 -0
  86. package/dist/components/ticker-tape/ticker-tape.js +106 -0
  87. package/dist/components/tour/index.js +4 -0
  88. package/dist/components/tour/tour.js +157 -0
  89. package/dist/components/usage-breakdown/index.js +6 -0
  90. package/dist/components/usage-breakdown/usage-breakdown.js +140 -0
  91. package/dist/components/wallet-card/index.js +4 -0
  92. package/dist/components/wallet-card/wallet-card.js +115 -0
  93. package/dist/components/watchlist/index.js +6 -0
  94. package/dist/components/watchlist/watchlist.js +110 -0
  95. package/dist/components/world-clock-bar/index.js +6 -0
  96. package/dist/components/world-clock-bar/world-clock-bar.js +101 -0
  97. package/dist/index.d.ts +1173 -7
  98. package/dist/test-setup.js +19 -0
  99. package/package.json +27 -6
  100. package/styles.css +55 -0
@@ -0,0 +1,6 @@
1
+ import {
2
+ OrderBook
3
+ } from "./order-book";
4
+ export {
5
+ OrderBook
6
+ };
@@ -0,0 +1,128 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils";
4
+ function withCumulativeTotal(levels) {
5
+ let runningTotal = 0;
6
+ return levels.map((level) => {
7
+ runningTotal += level.total ?? level.size;
8
+ return {
9
+ ...level,
10
+ total: level.total ?? runningTotal
11
+ };
12
+ });
13
+ }
14
+ function formatNumber(value, precision = 2) {
15
+ return value.toLocaleString(void 0, {
16
+ maximumFractionDigits: precision,
17
+ minimumFractionDigits: precision
18
+ });
19
+ }
20
+ function BookSide({
21
+ accent,
22
+ levels,
23
+ precision,
24
+ title
25
+ }) {
26
+ const maxTotal = Math.max(...levels.map((level) => level.total ?? 0), 1);
27
+ const barClassName = accent === "ask" ? "bg-rose-500/12 border-rose-500/15" : "bg-emerald-500/12 border-emerald-500/15";
28
+ const priceClassName = accent === "ask" ? "text-rose-600 dark:text-rose-400" : "text-emerald-600 dark:text-emerald-400";
29
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
30
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
31
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold uppercase tracking-[0.24em] text-muted-foreground", children: title }),
32
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "Depth by total size" })
33
+ ] }),
34
+ /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/70 bg-background/60 p-2", children: [
35
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1.2fr_1fr_1fr] gap-3 px-3 py-2 text-[11px] font-medium uppercase tracking-[0.2em] text-muted-foreground", children: [
36
+ /* @__PURE__ */ jsx("span", { children: "Price" }),
37
+ /* @__PURE__ */ jsx("span", { className: "text-right", children: "Size" }),
38
+ /* @__PURE__ */ jsx("span", { className: "text-right", children: "Total" })
39
+ ] }),
40
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: levels.map((level) => {
41
+ const width = `${(level.total ?? 0) / maxTotal * 100}%`;
42
+ return /* @__PURE__ */ jsxs(
43
+ "div",
44
+ {
45
+ className: "relative overflow-hidden rounded-xl border border-transparent px-3 py-2",
46
+ children: [
47
+ /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ className: cn(
51
+ "absolute inset-y-0 right-0 rounded-xl border",
52
+ barClassName
53
+ ),
54
+ style: { width }
55
+ }
56
+ ),
57
+ /* @__PURE__ */ jsxs("div", { className: "relative grid grid-cols-[1.2fr_1fr_1fr] gap-3 text-sm tabular-nums", children: [
58
+ /* @__PURE__ */ jsx("span", { className: cn("font-medium", priceClassName), children: formatNumber(level.price, precision) }),
59
+ /* @__PURE__ */ jsx("span", { className: "text-right text-foreground", children: formatNumber(level.size, 3) }),
60
+ /* @__PURE__ */ jsx("span", { className: "text-right text-muted-foreground", children: formatNumber(level.total ?? 0, 3) })
61
+ ] })
62
+ ]
63
+ },
64
+ `${accent}-${level.price}-${level.size}`
65
+ );
66
+ }) })
67
+ ] })
68
+ ] });
69
+ }
70
+ const OrderBook = React.forwardRef(
71
+ ({ asks, bids, className, precision = 2, ...props }, reference) => {
72
+ if (asks.length === 0 && bids.length === 0) {
73
+ return null;
74
+ }
75
+ const askLevels = withCumulativeTotal(asks);
76
+ const bidLevels = withCumulativeTotal(bids);
77
+ const bestAsk = askLevels[0];
78
+ const bestBid = bidLevels[0];
79
+ const spread = bestAsk && bestBid ? Math.max(bestAsk.price - bestBid.price, 0) : 0;
80
+ return /* @__PURE__ */ jsxs(
81
+ "div",
82
+ {
83
+ className: cn(
84
+ "rounded-2xl border border-border bg-card/80 p-4 shadow-sm",
85
+ className
86
+ ),
87
+ ref: reference,
88
+ ...props,
89
+ children: [
90
+ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex flex-wrap items-start justify-between gap-3", children: [
91
+ /* @__PURE__ */ jsxs("div", { children: [
92
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-[0.28em] text-muted-foreground", children: "Level II" }),
93
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: "Order book" })
94
+ ] }),
95
+ /* @__PURE__ */ jsxs("div", { className: "rounded-full border border-border bg-background/70 px-3 py-1 text-sm text-muted-foreground tabular-nums", children: [
96
+ "Spread ",
97
+ formatNumber(spread, precision)
98
+ ] })
99
+ ] }),
100
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
101
+ /* @__PURE__ */ jsx(
102
+ BookSide,
103
+ {
104
+ accent: "ask",
105
+ levels: askLevels,
106
+ precision,
107
+ title: "Asks"
108
+ }
109
+ ),
110
+ /* @__PURE__ */ jsx(
111
+ BookSide,
112
+ {
113
+ accent: "bid",
114
+ levels: bidLevels,
115
+ precision,
116
+ title: "Bids"
117
+ }
118
+ )
119
+ ] })
120
+ ]
121
+ }
122
+ );
123
+ }
124
+ );
125
+ OrderBook.displayName = "OrderBook";
126
+ export {
127
+ OrderBook
128
+ };
@@ -0,0 +1,4 @@
1
+ import { PasswordInput } from "./password-input";
2
+ export {
3
+ PasswordInput
4
+ };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Eye, EyeOff } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ const PasswordInput = React.forwardRef(
7
+ ({
8
+ className,
9
+ hideLabel = "Hide password",
10
+ showLabel = "Show password",
11
+ ...props
12
+ }, reference) => {
13
+ const [visible, setVisible] = React.useState(false);
14
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
15
+ /* @__PURE__ */ jsx(
16
+ "input",
17
+ {
18
+ className: cn(
19
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
20
+ className
21
+ ),
22
+ ref: reference,
23
+ type: visible ? "text" : "password",
24
+ ...props
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsx(
28
+ "button",
29
+ {
30
+ "aria-label": visible ? hideLabel : showLabel,
31
+ className: "absolute inset-y-0 right-0 flex items-center justify-center px-3 text-muted-foreground transition-colors hover:text-foreground",
32
+ onClick: () => {
33
+ setVisible((previous) => !previous);
34
+ },
35
+ type: "button",
36
+ children: visible ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
37
+ }
38
+ )
39
+ ] });
40
+ }
41
+ );
42
+ PasswordInput.displayName = "PasswordInput";
43
+ export {
44
+ PasswordInput
45
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ PlanBadge
3
+ } from "./plan-badge";
4
+ export {
5
+ PlanBadge
6
+ };
@@ -0,0 +1,67 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils";
4
+ import { badgeVariants } from "../badge/badge";
5
+ function getPlanLabel(tier) {
6
+ switch (tier) {
7
+ case "enterprise":
8
+ return "Enterprise";
9
+ case "free":
10
+ return "Free";
11
+ case "growth":
12
+ return "Growth";
13
+ case "starter":
14
+ return "Starter";
15
+ }
16
+ }
17
+ function getPlanClasses(tier, state) {
18
+ if (state === "legacy") {
19
+ return "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300";
20
+ }
21
+ if (state === "trial") {
22
+ return "border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-300";
23
+ }
24
+ switch (tier) {
25
+ case "enterprise":
26
+ return "border-primary/30 bg-primary/10 text-primary";
27
+ case "free":
28
+ return "border-border bg-muted text-muted-foreground";
29
+ case "growth":
30
+ return "border-violet-500/30 bg-violet-500/10 text-violet-700 dark:text-violet-300";
31
+ case "starter":
32
+ return "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300";
33
+ }
34
+ }
35
+ const PlanBadge = React.forwardRef(
36
+ ({ className, label, state = "current", tier, ...props }, reference) => {
37
+ return /* @__PURE__ */ jsxs(
38
+ "span",
39
+ {
40
+ className: cn(
41
+ badgeVariants({ variant: "outline" }),
42
+ "gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium tracking-[0.02em] shadow-none",
43
+ getPlanClasses(tier, state),
44
+ className
45
+ ),
46
+ ref: reference,
47
+ ...props,
48
+ children: [
49
+ /* @__PURE__ */ jsx(
50
+ "span",
51
+ {
52
+ "aria-hidden": "true",
53
+ className: "h-1.5 w-1.5 rounded-full bg-current"
54
+ }
55
+ ),
56
+ /* @__PURE__ */ jsx("span", { children: label ?? getPlanLabel(tier) }),
57
+ state === "trial" ? /* @__PURE__ */ jsx("span", { className: "text-current/80", children: "Trial" }) : null,
58
+ state === "legacy" ? /* @__PURE__ */ jsx("span", { className: "text-current/80", children: "Legacy" }) : null
59
+ ]
60
+ }
61
+ );
62
+ }
63
+ );
64
+ PlanBadge.displayName = "PlanBadge";
65
+ export {
66
+ PlanBadge
67
+ };
@@ -0,0 +1,4 @@
1
+ import { Rating } from "./rating";
2
+ export {
3
+ Rating
4
+ };
@@ -0,0 +1,121 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo, useState } from "react";
4
+ import { Star } from "lucide-react";
5
+ import { cn } from "../../lib/utils";
6
+ const sizeClasses = {
7
+ lg: "h-6 w-6",
8
+ md: "h-5 w-5",
9
+ sm: "h-4 w-4"
10
+ };
11
+ function RatingStars({
12
+ activeValue,
13
+ hoveredValue,
14
+ label,
15
+ max,
16
+ onHoverChange,
17
+ onSelect,
18
+ readOnly,
19
+ size
20
+ }) {
21
+ const stars = useMemo(
22
+ () => Array.from({ length: max }, (_, index) => index + 1),
23
+ [max]
24
+ );
25
+ const displayValue = hoveredValue || activeValue;
26
+ return /* @__PURE__ */ jsx(
27
+ "div",
28
+ {
29
+ "aria-label": label,
30
+ className: "inline-flex items-center gap-1",
31
+ role: "radiogroup",
32
+ children: stars.map((starValue) => {
33
+ const isFilled = starValue <= displayValue;
34
+ return /* @__PURE__ */ jsx(
35
+ "button",
36
+ {
37
+ "aria-checked": activeValue === starValue,
38
+ "aria-label": `${starValue} ${starValue === 1 ? "star" : "stars"}`,
39
+ className: cn(
40
+ "rounded-sm text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
41
+ !readOnly && "hover:text-amber-500",
42
+ isFilled && "text-amber-500"
43
+ ),
44
+ disabled: readOnly,
45
+ onBlur: () => {
46
+ onHoverChange(0);
47
+ },
48
+ onClick: () => {
49
+ onSelect(starValue);
50
+ },
51
+ onMouseEnter: () => {
52
+ if (!readOnly) {
53
+ onHoverChange(starValue);
54
+ }
55
+ },
56
+ onMouseLeave: () => {
57
+ onHoverChange(0);
58
+ },
59
+ role: "radio",
60
+ type: "button",
61
+ children: /* @__PURE__ */ jsx(
62
+ Star,
63
+ {
64
+ className: cn(sizeClasses[size], isFilled && "fill-current"),
65
+ strokeWidth: 1.75
66
+ }
67
+ )
68
+ },
69
+ starValue
70
+ );
71
+ })
72
+ }
73
+ );
74
+ }
75
+ function Rating({
76
+ allowClear = false,
77
+ className,
78
+ defaultValue = 0,
79
+ label = "Rating",
80
+ max = 5,
81
+ onValueChange,
82
+ readOnly = false,
83
+ showValue = false,
84
+ size = "md",
85
+ value
86
+ }) {
87
+ const isControlled = value !== void 0;
88
+ const [internalValue, setInternalValue] = useState(defaultValue);
89
+ const [hoveredValue, setHoveredValue] = useState(0);
90
+ const activeValue = isControlled ? value ?? 0 : internalValue;
91
+ const handleSelect = (nextValue) => {
92
+ const resolvedValue = allowClear && activeValue === nextValue ? 0 : nextValue;
93
+ if (!isControlled) {
94
+ setInternalValue(resolvedValue);
95
+ }
96
+ onValueChange?.(resolvedValue);
97
+ };
98
+ return /* @__PURE__ */ jsx("div", { className: cn("inline-flex flex-col gap-2", className), children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-3", children: [
99
+ /* @__PURE__ */ jsx(
100
+ RatingStars,
101
+ {
102
+ activeValue,
103
+ hoveredValue,
104
+ label,
105
+ max,
106
+ onHoverChange: setHoveredValue,
107
+ onSelect: handleSelect,
108
+ readOnly,
109
+ size
110
+ }
111
+ ),
112
+ showValue ? /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
113
+ activeValue,
114
+ "/",
115
+ max
116
+ ] }) : null
117
+ ] }) });
118
+ }
119
+ export {
120
+ Rating
121
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ RoleBadge
3
+ } from "./role-badge";
4
+ export {
5
+ RoleBadge
6
+ };
@@ -0,0 +1,50 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../lib/utils";
4
+ import { badgeVariants } from "../badge/badge";
5
+ function getRoleLabel(accountRole) {
6
+ switch (accountRole) {
7
+ case "admin":
8
+ return "Admin";
9
+ case "billing":
10
+ return "Billing";
11
+ case "member":
12
+ return "Member";
13
+ case "owner":
14
+ return "Owner";
15
+ }
16
+ }
17
+ function getRoleClasses(accountRole) {
18
+ switch (accountRole) {
19
+ case "admin":
20
+ return "border-violet-500/30 bg-violet-500/10 text-violet-700 dark:text-violet-300";
21
+ case "billing":
22
+ return "border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-300";
23
+ case "member":
24
+ return "border-border bg-muted text-muted-foreground";
25
+ case "owner":
26
+ return "border-primary/30 bg-primary/10 text-primary";
27
+ }
28
+ }
29
+ const RoleBadge = React.forwardRef(
30
+ ({ accountRole, className, label, ...props }, reference) => {
31
+ return /* @__PURE__ */ jsx(
32
+ "span",
33
+ {
34
+ className: cn(
35
+ badgeVariants({ variant: "outline" }),
36
+ "rounded-full px-2.5 py-1 text-[11px] font-medium shadow-none",
37
+ getRoleClasses(accountRole),
38
+ className
39
+ ),
40
+ ref: reference,
41
+ ...props,
42
+ children: label ?? getRoleLabel(accountRole)
43
+ }
44
+ );
45
+ }
46
+ );
47
+ RoleBadge.displayName = "RoleBadge";
48
+ export {
49
+ RoleBadge
50
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ ScopeSelector
3
+ } from "./scope-selector";
4
+ export {
5
+ ScopeSelector
6
+ };