@vllnt/ui 0.2.0 → 0.2.1-canary.73a93ee

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 (86) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +27 -12
  3. package/dist/components/activity-log/activity-log.js +1 -0
  4. package/dist/components/anchor-port/anchor-port.js +51 -0
  5. package/dist/components/anchor-port/index.js +4 -0
  6. package/dist/components/animated-text/animated-text.js +1 -0
  7. package/dist/components/bottom-bar/bottom-bar.js +25 -0
  8. package/dist/components/bottom-bar/index.js +4 -0
  9. package/dist/components/canvas-shell/canvas-foundation-demo.js +183 -0
  10. package/dist/components/canvas-shell/canvas-shell-route-config.js +0 -0
  11. package/dist/components/canvas-shell/canvas-shell.js +261 -0
  12. package/dist/components/canvas-shell/index.js +4 -0
  13. package/dist/components/canvas-view/canvas-view.js +461 -0
  14. package/dist/components/canvas-view/index.js +6 -0
  15. package/dist/components/chart/area-chart.js +1 -0
  16. package/dist/components/chart/line-chart.js +1 -0
  17. package/dist/components/chat-dock-section/chat-dock-section.js +56 -0
  18. package/dist/components/chat-dock-section/index.js +6 -0
  19. package/dist/components/checklist/checklist.js +7 -0
  20. package/dist/components/checklist/index.js +3 -1
  21. package/dist/components/comment-pin/comment-pin.js +104 -0
  22. package/dist/components/comment-pin/index.js +6 -0
  23. package/dist/components/connector-edge/connector-edge.js +66 -0
  24. package/dist/components/connector-edge/index.js +6 -0
  25. package/dist/components/conversation-thread/conversation-thread.js +348 -0
  26. package/dist/components/conversation-thread/index.js +20 -0
  27. package/dist/components/curriculum/curriculum.js +349 -0
  28. package/dist/components/curriculum/index.js +10 -0
  29. package/dist/components/data-list/data-list.js +1 -0
  30. package/dist/components/edge-label/edge-label.js +26 -0
  31. package/dist/components/edge-label/index.js +4 -0
  32. package/dist/components/form/form.js +432 -0
  33. package/dist/components/form/index.js +20 -0
  34. package/dist/components/glass-panel/glass-panel.js +21 -0
  35. package/dist/components/glass-panel/index.js +4 -0
  36. package/dist/components/group-hull/group-hull.js +29 -0
  37. package/dist/components/group-hull/index.js +4 -0
  38. package/dist/components/index.js +176 -0
  39. package/dist/components/infinite-plane/index.js +6 -0
  40. package/dist/components/infinite-plane/infinite-plane.js +75 -0
  41. package/dist/components/left-rail/index.js +4 -0
  42. package/dist/components/left-rail/left-rail.js +25 -0
  43. package/dist/components/live-cursor/index.js +6 -0
  44. package/dist/components/live-cursor/live-cursor.js +62 -0
  45. package/dist/components/mini-map-panel/index.js +6 -0
  46. package/dist/components/mini-map-panel/mini-map-panel.js +74 -0
  47. package/dist/components/multi-select/index.js +6 -0
  48. package/dist/components/multi-select/multi-select.js +258 -0
  49. package/dist/components/object-card/index.js +6 -0
  50. package/dist/components/object-card/object-card.js +126 -0
  51. package/dist/components/object-handle/index.js +4 -0
  52. package/dist/components/object-handle/object-handle.js +38 -0
  53. package/dist/components/overview-board/index.js +8 -0
  54. package/dist/components/overview-board/overview-board.js +127 -0
  55. package/dist/components/presence-stack/index.js +6 -0
  56. package/dist/components/presence-stack/presence-stack.js +108 -0
  57. package/dist/components/presence-sync-indicator/index.js +6 -0
  58. package/dist/components/presence-sync-indicator/presence-sync-indicator.js +73 -0
  59. package/dist/components/progress-tracker/index.js +20 -0
  60. package/dist/components/progress-tracker/progress-tracker.js +527 -0
  61. package/dist/components/right-dock/index.js +4 -0
  62. package/dist/components/right-dock/right-dock.js +28 -0
  63. package/dist/components/run-timeline/index.js +6 -0
  64. package/dist/components/run-timeline/run-timeline.js +221 -0
  65. package/dist/components/segmented-control/index.js +12 -0
  66. package/dist/components/segmented-control/segmented-control.js +61 -0
  67. package/dist/components/selection-presence/index.js +6 -0
  68. package/dist/components/selection-presence/selection-presence.js +50 -0
  69. package/dist/components/spinner/unicode-spinner.js +1 -0
  70. package/dist/components/tags-input/index.js +4 -0
  71. package/dist/components/tags-input/tags-input.js +178 -0
  72. package/dist/components/thread-bubble/index.js +6 -0
  73. package/dist/components/thread-bubble/thread-bubble.js +85 -0
  74. package/dist/components/top-bar/index.js +4 -0
  75. package/dist/components/top-bar/top-bar.js +31 -0
  76. package/dist/components/usage-breakdown/usage-breakdown.js +1 -0
  77. package/dist/components/viewport-bookmarks/index.js +6 -0
  78. package/dist/components/viewport-bookmarks/viewport-bookmarks.js +116 -0
  79. package/dist/components/workspace-switcher/index.js +6 -0
  80. package/dist/components/workspace-switcher/workspace-switcher.js +61 -0
  81. package/dist/components/world-breadcrumbs/index.js +6 -0
  82. package/dist/components/world-breadcrumbs/world-breadcrumbs.js +114 -0
  83. package/dist/components/zoom-hud/index.js +4 -0
  84. package/dist/components/zoom-hud/zoom-hud.js +61 -0
  85. package/dist/index.d.ts +1468 -6
  86. package/package.json +7 -3
@@ -0,0 +1,349 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ Children,
5
+ createContext,
6
+ isValidElement,
7
+ useCallback,
8
+ useContext,
9
+ useMemo,
10
+ useState
11
+ } from "react";
12
+ import {
13
+ BookOpen,
14
+ CheckCircle2,
15
+ ChevronDown,
16
+ Clock,
17
+ GraduationCap,
18
+ Link2,
19
+ Lock,
20
+ PlayCircle
21
+ } from "lucide-react";
22
+ import { cn } from "../../lib/utils";
23
+ const CurriculumContext = createContext(null);
24
+ function useCurriculumContext() {
25
+ const ctx = useContext(CurriculumContext);
26
+ if (!ctx) {
27
+ throw new Error("CurriculumModule must be used within a Curriculum");
28
+ }
29
+ return ctx;
30
+ }
31
+ function summarizeLessonProgress(children) {
32
+ let completed = 0;
33
+ let total = 0;
34
+ Children.forEach(children, (child) => {
35
+ if (!isValidElement(child)) {
36
+ return;
37
+ }
38
+ if (child.type === CurriculumLesson) {
39
+ total += 1;
40
+ if (child.props.status === "completed") {
41
+ completed += 1;
42
+ }
43
+ return;
44
+ }
45
+ const nested = summarizeLessonProgress(child.props.children);
46
+ total += nested.total;
47
+ completed += nested.completed;
48
+ });
49
+ return { completed, total };
50
+ }
51
+ function statusLabel(status) {
52
+ if (status === "completed") return "Completed";
53
+ if (status === "in-progress") return "In progress";
54
+ if (status === "locked") return "Locked";
55
+ return "Available";
56
+ }
57
+ function statusIcon(status) {
58
+ if (status === "completed") {
59
+ return /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 flex-shrink-0 text-green-500" });
60
+ }
61
+ if (status === "in-progress") {
62
+ return /* @__PURE__ */ jsx(PlayCircle, { className: "h-4 w-4 flex-shrink-0 text-primary" });
63
+ }
64
+ if (status === "locked") {
65
+ return /* @__PURE__ */ jsx(Lock, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" });
66
+ }
67
+ return /* @__PURE__ */ jsx(BookOpen, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" });
68
+ }
69
+ const difficultyStyles = {
70
+ advanced: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
71
+ beginner: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
72
+ intermediate: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
73
+ };
74
+ function ProgressBar({
75
+ completed,
76
+ progressPct,
77
+ total
78
+ }) {
79
+ if (total === 0) return null;
80
+ return /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2", children: [
81
+ /* @__PURE__ */ jsx("div", { className: "h-1.5 max-w-[120px] flex-1 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx(
82
+ "div",
83
+ {
84
+ className: "h-full rounded-full bg-primary transition-all",
85
+ style: { width: `${progressPct}%` }
86
+ }
87
+ ) }),
88
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
89
+ completed,
90
+ "/",
91
+ total
92
+ ] })
93
+ ] });
94
+ }
95
+ function LessonMeta({
96
+ difficulty,
97
+ duration,
98
+ prerequisites
99
+ }) {
100
+ const prerequisitesLabel = prerequisites?.length ? `Requires: ${prerequisites.join(", ")}` : null;
101
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-2", children: [
102
+ prerequisitesLabel ? /* @__PURE__ */ jsx(
103
+ "span",
104
+ {
105
+ "aria-label": prerequisitesLabel,
106
+ className: "flex items-center gap-1 text-xs text-muted-foreground",
107
+ title: prerequisitesLabel,
108
+ children: /* @__PURE__ */ jsx(Link2, { "aria-hidden": "true", className: "h-3 w-3" })
109
+ }
110
+ ) : null,
111
+ difficulty ? /* @__PURE__ */ jsx(
112
+ "span",
113
+ {
114
+ className: cn(
115
+ "rounded px-1.5 py-0.5 text-xs font-medium capitalize",
116
+ difficultyStyles[difficulty]
117
+ ),
118
+ children: difficulty
119
+ }
120
+ ) : null,
121
+ duration ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
122
+ /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
123
+ duration
124
+ ] }) : null
125
+ ] });
126
+ }
127
+ function ModuleTrigger({
128
+ completed,
129
+ description,
130
+ estimatedHours,
131
+ id,
132
+ isExpanded,
133
+ progressPct,
134
+ title,
135
+ toggle,
136
+ total
137
+ }) {
138
+ return /* @__PURE__ */ jsxs(
139
+ "button",
140
+ {
141
+ "aria-controls": `module-content-${id}`,
142
+ "aria-expanded": isExpanded,
143
+ className: cn(
144
+ "w-full flex items-start justify-between gap-3 rounded-md px-6 py-4 text-left transition-colors",
145
+ "hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2",
146
+ isExpanded && "bg-muted/30"
147
+ ),
148
+ onClick: toggle,
149
+ type: "button",
150
+ children: [
151
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
152
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: title }),
153
+ description ? /* @__PURE__ */ jsx("span", { className: "line-clamp-1 text-xs text-muted-foreground", children: description }) : null,
154
+ /* @__PURE__ */ jsx(
155
+ ProgressBar,
156
+ {
157
+ completed,
158
+ progressPct,
159
+ total
160
+ }
161
+ )
162
+ ] }),
163
+ /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex flex-shrink-0 items-center gap-3", children: [
164
+ estimatedHours === void 0 ? null : /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
165
+ /* @__PURE__ */ jsx(Clock, { className: "h-3.5 w-3.5" }),
166
+ estimatedHours,
167
+ "h"
168
+ ] }),
169
+ /* @__PURE__ */ jsx(
170
+ ChevronDown,
171
+ {
172
+ className: cn(
173
+ "h-4 w-4 text-muted-foreground transition-transform duration-200",
174
+ isExpanded && "rotate-180"
175
+ )
176
+ }
177
+ )
178
+ ] })
179
+ ]
180
+ }
181
+ );
182
+ }
183
+ function CurriculumRoot({
184
+ children,
185
+ className,
186
+ defaultExpandedModules,
187
+ title,
188
+ totalHours
189
+ }) {
190
+ const [expandedModules, setExpandedModules] = useState(
191
+ () => new Set(defaultExpandedModules ?? [])
192
+ );
193
+ const toggleModule = useCallback((id) => {
194
+ setExpandedModules((previous) => {
195
+ const next = new Set(previous);
196
+ if (next.has(id)) {
197
+ next.delete(id);
198
+ } else {
199
+ next.add(id);
200
+ }
201
+ return next;
202
+ });
203
+ }, []);
204
+ const contextValue = useMemo(
205
+ () => ({ expandedModules, toggleModule }),
206
+ [expandedModules, toggleModule]
207
+ );
208
+ return /* @__PURE__ */ jsx(CurriculumContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
209
+ "div",
210
+ {
211
+ className: cn(
212
+ "my-6 rounded-lg border bg-card text-card-foreground shadow-sm",
213
+ className
214
+ ),
215
+ children: [
216
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-6 py-4", children: [
217
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
218
+ /* @__PURE__ */ jsx(GraduationCap, { className: "h-5 w-5 text-primary" }),
219
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: title })
220
+ ] }),
221
+ totalHours === void 0 ? null : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
222
+ /* @__PURE__ */ jsx(Clock, { className: "h-4 w-4" }),
223
+ /* @__PURE__ */ jsxs("span", { children: [
224
+ totalHours,
225
+ "h total"
226
+ ] })
227
+ ] })
228
+ ] }),
229
+ /* @__PURE__ */ jsx("div", { "aria-label": title, className: "divide-y", children })
230
+ ]
231
+ }
232
+ ) });
233
+ }
234
+ function CurriculumModule({
235
+ children,
236
+ className,
237
+ description,
238
+ estimatedHours,
239
+ id,
240
+ title
241
+ }) {
242
+ const { expandedModules, toggleModule } = useCurriculumContext();
243
+ const isExpanded = expandedModules.has(id);
244
+ const { completed, total } = useMemo(
245
+ () => summarizeLessonProgress(children),
246
+ [children]
247
+ );
248
+ const progressPct = total > 0 ? Math.round(completed / total * 100) : 0;
249
+ return /* @__PURE__ */ jsxs("section", { className, children: [
250
+ /* @__PURE__ */ jsx(
251
+ ModuleTrigger,
252
+ {
253
+ completed,
254
+ description,
255
+ estimatedHours,
256
+ id,
257
+ isExpanded,
258
+ progressPct,
259
+ title,
260
+ toggle: () => {
261
+ toggleModule(id);
262
+ },
263
+ total
264
+ }
265
+ ),
266
+ /* @__PURE__ */ jsx(
267
+ "div",
268
+ {
269
+ "aria-hidden": !isExpanded,
270
+ className: cn(
271
+ "overflow-hidden transition-all duration-200",
272
+ isExpanded ? "max-h-[9999px] opacity-100" : "max-h-0 opacity-0"
273
+ ),
274
+ hidden: !isExpanded,
275
+ id: `module-content-${id}`,
276
+ children: /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50 pb-2", children })
277
+ }
278
+ )
279
+ ] });
280
+ }
281
+ function CurriculumLesson({
282
+ className,
283
+ difficulty,
284
+ duration,
285
+ href,
286
+ prerequisites,
287
+ status = "available",
288
+ title
289
+ }) {
290
+ const isLocked = status === "locked";
291
+ const inner = /* @__PURE__ */ jsxs(
292
+ "div",
293
+ {
294
+ "aria-disabled": isLocked || void 0,
295
+ className: cn(
296
+ "flex items-center gap-3 px-6 py-3 pl-10 text-sm transition-colors",
297
+ isLocked ? "cursor-not-allowed opacity-60" : "",
298
+ !isLocked && href ? "cursor-pointer hover:bg-muted/40" : "",
299
+ className
300
+ ),
301
+ children: [
302
+ statusIcon(status),
303
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: statusLabel(status) }),
304
+ /* @__PURE__ */ jsxs(
305
+ "span",
306
+ {
307
+ className: cn(
308
+ "min-w-0 flex-1 truncate",
309
+ status === "completed" && "text-muted-foreground line-through",
310
+ status === "in-progress" && "font-medium"
311
+ ),
312
+ children: [
313
+ title,
314
+ isLocked ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (Locked)" }) : null
315
+ ]
316
+ }
317
+ ),
318
+ /* @__PURE__ */ jsx(
319
+ LessonMeta,
320
+ {
321
+ difficulty,
322
+ duration,
323
+ prerequisites
324
+ }
325
+ )
326
+ ]
327
+ }
328
+ );
329
+ if (href && !isLocked) {
330
+ return /* @__PURE__ */ jsx(
331
+ "a",
332
+ {
333
+ className: "block rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2",
334
+ href,
335
+ children: inner
336
+ }
337
+ );
338
+ }
339
+ return inner;
340
+ }
341
+ const Curriculum = Object.assign(CurriculumRoot, {
342
+ Lesson: CurriculumLesson,
343
+ Module: CurriculumModule
344
+ });
345
+ export {
346
+ Curriculum,
347
+ CurriculumLesson,
348
+ CurriculumModule
349
+ };
@@ -0,0 +1,10 @@
1
+ import {
2
+ Curriculum,
3
+ CurriculumLesson,
4
+ CurriculumModule
5
+ } from "./curriculum";
6
+ export {
7
+ Curriculum,
8
+ CurriculumLesson,
9
+ CurriculumModule
10
+ };
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx } from "react/jsx-runtime";
2
3
  import * as React from "react";
3
4
  import { cva } from "class-variance-authority";
@@ -0,0 +1,26 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { cn } from "../../lib/utils";
4
+ const emphasisClasses = {
5
+ active: "border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-300",
6
+ subtle: "border-border/60 bg-background/90 text-muted-foreground"
7
+ };
8
+ const EdgeLabel = forwardRef(
9
+ ({ className, emphasis = "subtle", ...props }, ref) => /* @__PURE__ */ jsx(
10
+ "span",
11
+ {
12
+ className: cn(
13
+ "inline-flex items-center rounded-full border px-2.5 py-1 text-[11px] font-medium uppercase tracking-[0.18em] shadow-sm",
14
+ emphasisClasses[emphasis],
15
+ className
16
+ ),
17
+ "data-emphasis": emphasis,
18
+ ref,
19
+ ...props
20
+ }
21
+ )
22
+ );
23
+ EdgeLabel.displayName = "EdgeLabel";
24
+ export {
25
+ EdgeLabel
26
+ };
@@ -0,0 +1,4 @@
1
+ import { EdgeLabel } from "./edge-label";
2
+ export {
3
+ EdgeLabel
4
+ };