@vllnt/ui 0.2.1-canary.4abeac1 → 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.
@@ -0,0 +1,104 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ forwardRef
5
+ } from "react";
6
+ import { cn } from "../../lib/utils";
7
+ const DEFAULT_LABELS = {
8
+ region: "Comment",
9
+ unreadSuffix: "unread"
10
+ };
11
+ const STATE_FILL = {
12
+ open: "bg-foreground text-background",
13
+ resolved: "bg-muted text-muted-foreground"
14
+ };
15
+ const PinBody = (props) => {
16
+ const showBadge = typeof props.unread === "number" && props.unread > 0;
17
+ const useAccent = props.accent && props.state === "open";
18
+ return /* @__PURE__ */ jsxs(Fragment, { 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 border-background text-[11px] font-semibold shadow-sm",
25
+ STATE_FILL[props.state]
26
+ ),
27
+ "data-comment-pin-body": true,
28
+ style: useAccent ? { backgroundColor: props.accent, color: "white" } : void 0,
29
+ children: props.authorInitial ?? "\u2022"
30
+ }
31
+ ),
32
+ showBadge ? /* @__PURE__ */ jsx(
33
+ "span",
34
+ {
35
+ "aria-hidden": "true",
36
+ className: "absolute -right-1 -top-1 inline-flex min-h-[14px] min-w-[14px] items-center justify-center rounded-full bg-red-500 px-1 text-[9px] font-medium text-white",
37
+ "data-comment-pin-unread": true,
38
+ children: props.unread
39
+ }
40
+ ) : null
41
+ ] });
42
+ };
43
+ const CommentPin = forwardRef(
44
+ (props, ref) => {
45
+ const {
46
+ authorInitial,
47
+ className,
48
+ color,
49
+ labels,
50
+ onActivate,
51
+ state = "open",
52
+ unread,
53
+ x,
54
+ y,
55
+ ...rest
56
+ } = props;
57
+ const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
58
+ const showBadge = typeof unread === "number" && unread > 0;
59
+ const ariaLabel = showBadge ? `${resolvedLabels.region}, ${unread} ${resolvedLabels.unreadSuffix}` : resolvedLabels.region;
60
+ const handleClick = () => {
61
+ onActivate?.();
62
+ };
63
+ const body = /* @__PURE__ */ jsx(
64
+ PinBody,
65
+ {
66
+ accent: color,
67
+ authorInitial,
68
+ state,
69
+ unread
70
+ }
71
+ );
72
+ return /* @__PURE__ */ jsx(
73
+ "div",
74
+ {
75
+ "aria-label": ariaLabel,
76
+ className: cn(
77
+ "absolute z-30 inline-flex -translate-x-1/2 -translate-y-1/2",
78
+ className
79
+ ),
80
+ "data-comment-pin": true,
81
+ "data-comment-pin-state": state,
82
+ ref,
83
+ role: "img",
84
+ style: { left: x, top: y },
85
+ ...rest,
86
+ children: onActivate ? /* @__PURE__ */ jsx(
87
+ "button",
88
+ {
89
+ "aria-label": ariaLabel,
90
+ className: "relative inline-flex rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
91
+ "data-comment-pin-trigger": true,
92
+ onClick: handleClick,
93
+ type: "button",
94
+ children: body
95
+ }
96
+ ) : /* @__PURE__ */ jsx("span", { className: "relative inline-flex", children: body })
97
+ }
98
+ );
99
+ }
100
+ );
101
+ CommentPin.displayName = "CommentPin";
102
+ export {
103
+ CommentPin
104
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ CommentPin
3
+ } from "./comment-pin";
4
+ export {
5
+ CommentPin
6
+ };
@@ -306,6 +306,9 @@ import {
306
306
  ChatDockSection
307
307
  } from "./chat-dock-section";
308
308
  import { GlassPanel } from "./glass-panel";
309
+ import {
310
+ InfinitePlane
311
+ } from "./infinite-plane";
309
312
  import { LeftRail } from "./left-rail";
310
313
  import {
311
314
  MiniMapPanel
@@ -323,6 +326,12 @@ import { Sidebar } from "./sidebar";
323
326
  import { SidebarProvider, useSidebar } from "./sidebar-provider";
324
327
  import { TableOfContents } from "./table-of-contents";
325
328
  import { TopBar } from "./top-bar";
329
+ import {
330
+ ViewportBookmarks
331
+ } from "./viewport-bookmarks";
332
+ import {
333
+ WorldBreadcrumbs
334
+ } from "./world-breadcrumbs";
326
335
  import { ZoomHUD } from "./zoom-hud";
327
336
  import {
328
337
  ActivityLog
@@ -530,15 +539,36 @@ import {
530
539
  useFlowDiagram
531
540
  } from "./flow-diagram";
532
541
  import { AnchorPort } from "./anchor-port";
542
+ import {
543
+ CommentPin
544
+ } from "./comment-pin";
533
545
  import {
534
546
  ConnectorEdge
535
547
  } from "./connector-edge";
536
548
  import { EdgeLabel } from "./edge-label";
537
549
  import { GroupHull } from "./group-hull";
550
+ import {
551
+ LiveCursor
552
+ } from "./live-cursor";
538
553
  import {
539
554
  ObjectCard
540
555
  } from "./object-card";
541
556
  import { ObjectHandle } from "./object-handle";
557
+ import {
558
+ PresenceStack
559
+ } from "./presence-stack";
560
+ import {
561
+ PresenceSyncIndicator
562
+ } from "./presence-sync-indicator";
563
+ import {
564
+ RunTimeline
565
+ } from "./run-timeline";
566
+ import {
567
+ SelectionPresence
568
+ } from "./selection-presence";
569
+ import {
570
+ ThreadBubble
571
+ } from "./thread-bubble";
542
572
  import {
543
573
  ConversationEmpty,
544
574
  ConversationHeader,
@@ -633,6 +663,7 @@ export {
633
663
  CommandList,
634
664
  CommandSeparator,
635
665
  CommandShortcut,
666
+ CommentPin,
636
667
  CommonMistake,
637
668
  Comparison,
638
669
  CompletionDialog,
@@ -737,6 +768,7 @@ export {
737
768
  HoverCard,
738
769
  HoverCardContent,
739
770
  HoverCardTrigger,
771
+ InfinitePlane,
740
772
  InlineInput,
741
773
  Input,
742
774
  InputOTP,
@@ -750,6 +782,7 @@ export {
750
782
  LearningObjectives,
751
783
  LeftRail,
752
784
  LineChart,
785
+ LiveCursor,
753
786
  LiveFeed,
754
787
  MDXContent,
755
788
  MarketTreemap,
@@ -798,6 +831,8 @@ export {
798
831
  PopoverContent,
799
832
  PopoverTrigger,
800
833
  Prerequisites,
834
+ PresenceStack,
835
+ PresenceSyncIndicator,
801
836
  ProTip,
802
837
  ProfileSection,
803
838
  ProgressBar,
@@ -818,6 +853,7 @@ export {
818
853
  ResizablePanelGroup,
819
854
  RightDock,
820
855
  RoleBadge,
856
+ RunTimeline,
821
857
  ScopeSelector,
822
858
  ScrollArea,
823
859
  ScrollBar,
@@ -835,6 +871,7 @@ export {
835
871
  SelectSeparator,
836
872
  SelectTrigger,
837
873
  SelectValue,
874
+ SelectionPresence,
838
875
  Separator,
839
876
  SeverityBadge,
840
877
  ShareDialog,
@@ -890,6 +927,7 @@ export {
890
927
  ThemeProvider,
891
928
  ThemeToggle,
892
929
  ThinkingBlock,
930
+ ThreadBubble,
893
931
  TickerTape,
894
932
  Toast,
895
933
  ToastAction,
@@ -916,9 +954,11 @@ export {
916
954
  UsageBreakdown,
917
955
  VideoEmbed,
918
956
  ViewSwitcher,
957
+ ViewportBookmarks,
919
958
  WalletCard,
920
959
  Watchlist,
921
960
  WorkspaceSwitcher,
961
+ WorldBreadcrumbs,
922
962
  WorldClockBar,
923
963
  ZoomHUD,
924
964
  alertVariants,
@@ -0,0 +1,6 @@
1
+ import {
2
+ InfinitePlane
3
+ } from "./infinite-plane";
4
+ export {
5
+ InfinitePlane
6
+ };
@@ -0,0 +1,75 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import {
4
+ forwardRef
5
+ } from "react";
6
+ import { cn } from "../../lib/utils";
7
+ const DEFAULT_LABELS = {
8
+ region: "Infinite plane"
9
+ };
10
+ const safeSpacing = (value) => value < 4 ? 4 : value;
11
+ const safeZoom = (value) => {
12
+ if (value < 0.1) {
13
+ return 0.1;
14
+ }
15
+ if (value > 10) {
16
+ return 10;
17
+ }
18
+ return value;
19
+ };
20
+ const buildBackground = (input) => {
21
+ if (input.pattern === "blank") {
22
+ return {};
23
+ }
24
+ const size = safeSpacing(input.spacing) * safeZoom(input.zoom);
25
+ const pos = `${input.translate.x}px ${input.translate.y}px`;
26
+ if (input.pattern === "grid") {
27
+ return {
28
+ backgroundImage: "linear-gradient(to right, hsl(var(--border)) 1px, transparent 1px), linear-gradient(to bottom, hsl(var(--border)) 1px, transparent 1px)",
29
+ backgroundPosition: pos,
30
+ backgroundSize: `${size}px ${size}px`
31
+ };
32
+ }
33
+ return {
34
+ backgroundImage: "radial-gradient(circle, hsl(var(--border)) 1px, transparent 1px)",
35
+ backgroundPosition: pos,
36
+ backgroundSize: `${size}px ${size}px`
37
+ };
38
+ };
39
+ const InfinitePlane = forwardRef(
40
+ (props, ref) => {
41
+ const {
42
+ children,
43
+ className,
44
+ labels,
45
+ pattern = "dot",
46
+ spacing = 32,
47
+ translate = { x: 0, y: 0 },
48
+ zoom = 1,
49
+ ...rest
50
+ } = props;
51
+ const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
52
+ const background = buildBackground({ pattern, spacing, translate, zoom });
53
+ return /* @__PURE__ */ jsx(
54
+ "div",
55
+ {
56
+ "aria-label": resolvedLabels.region,
57
+ className: cn(
58
+ "relative h-full w-full overflow-hidden bg-background",
59
+ className
60
+ ),
61
+ "data-infinite-plane": true,
62
+ "data-infinite-plane-pattern": pattern,
63
+ ref,
64
+ role: "region",
65
+ style: background,
66
+ ...rest,
67
+ children
68
+ }
69
+ );
70
+ }
71
+ );
72
+ InfinitePlane.displayName = "InfinitePlane";
73
+ export {
74
+ InfinitePlane
75
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ LiveCursor
3
+ } from "./live-cursor";
4
+ export {
5
+ LiveCursor
6
+ };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ forwardRef
5
+ } from "react";
6
+ import { cn } from "../../lib/utils";
7
+ const DEFAULT_LABELS = {
8
+ region: "Live cursor"
9
+ };
10
+ const LiveCursor = forwardRef(
11
+ (props, ref) => {
12
+ const { className, color, labels, name, status, x, y, ...rest } = props;
13
+ const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
14
+ const resolvedColor = color ?? "var(--foreground)";
15
+ return /* @__PURE__ */ jsxs(
16
+ "div",
17
+ {
18
+ "aria-label": typeof name === "string" ? `${resolvedLabels.region}: ${name}` : resolvedLabels.region,
19
+ className: cn(
20
+ "pointer-events-none absolute z-30 flex items-start gap-1",
21
+ className
22
+ ),
23
+ "data-live-cursor": true,
24
+ ref,
25
+ role: "img",
26
+ style: { left: x, top: y },
27
+ ...rest,
28
+ children: [
29
+ /* @__PURE__ */ jsx(
30
+ "svg",
31
+ {
32
+ "aria-hidden": "true",
33
+ className: "-ml-1 -mt-1 drop-shadow-sm",
34
+ "data-live-cursor-pointer": true,
35
+ fill: resolvedColor,
36
+ height: 18,
37
+ viewBox: "0 0 16 18",
38
+ width: 16,
39
+ children: /* @__PURE__ */ jsx("path", { d: "M0 0 L0 14 L4 11 L7 17 L10 16 L7 10 L13 10 Z" })
40
+ }
41
+ ),
42
+ name === null || name === void 0 ? null : /* @__PURE__ */ jsxs(
43
+ "span",
44
+ {
45
+ className: "ml-2 mt-2 inline-flex flex-col rounded-md px-1.5 py-0.5 text-[10px] font-medium text-white shadow-sm",
46
+ "data-live-cursor-chip": true,
47
+ style: { backgroundColor: resolvedColor },
48
+ children: [
49
+ /* @__PURE__ */ jsx("span", { children: name }),
50
+ status ? /* @__PURE__ */ jsx("span", { className: "text-[9px] opacity-80", "data-live-cursor-status": true, children: status }) : null
51
+ ]
52
+ }
53
+ )
54
+ ]
55
+ }
56
+ );
57
+ }
58
+ );
59
+ LiveCursor.displayName = "LiveCursor";
60
+ export {
61
+ LiveCursor
62
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ PresenceStack
3
+ } from "./presence-stack";
4
+ export {
5
+ PresenceStack
6
+ };
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ forwardRef
5
+ } from "react";
6
+ import { cn } from "../../lib/utils";
7
+ const STATUS_DOT = {
8
+ active: "bg-emerald-500",
9
+ away: "bg-amber-500",
10
+ idle: "bg-muted-foreground",
11
+ offline: "bg-muted-foreground/40"
12
+ };
13
+ const DEFAULT_LABELS = {
14
+ overflowSuffix: "more",
15
+ region: "Live presence"
16
+ };
17
+ const Avatar = (props) => {
18
+ const { user } = props;
19
+ const status = user.status ?? "active";
20
+ return /* @__PURE__ */ jsxs(
21
+ "span",
22
+ {
23
+ className: "relative -ml-2 inline-flex h-7 w-7 items-center justify-center rounded-full border-2 border-background text-[11px] font-semibold text-white shadow-sm first:ml-0",
24
+ "data-presence-stack-status": status,
25
+ "data-presence-stack-user": user.id,
26
+ style: { backgroundColor: user.color ?? "var(--foreground)" },
27
+ title: user.name,
28
+ children: [
29
+ user.initial,
30
+ /* @__PURE__ */ jsx(
31
+ "span",
32
+ {
33
+ "aria-hidden": "true",
34
+ className: cn(
35
+ "absolute -bottom-0.5 -right-0.5 h-2 w-2 rounded-full border border-background",
36
+ STATUS_DOT[status]
37
+ ),
38
+ "data-presence-stack-dot": true
39
+ }
40
+ )
41
+ ]
42
+ }
43
+ );
44
+ };
45
+ const PresenceStack = forwardRef(
46
+ (props, ref) => {
47
+ const {
48
+ className,
49
+ labels,
50
+ max = 5,
51
+ onOverflowActivate,
52
+ users,
53
+ ...rest
54
+ } = props;
55
+ const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
56
+ const visible = max >= users.length ? users : users.slice(0, max);
57
+ const hidden = users.length - visible.length;
58
+ const handleOverflow = () => {
59
+ onOverflowActivate?.();
60
+ };
61
+ return /* @__PURE__ */ jsxs(
62
+ "div",
63
+ {
64
+ "aria-label": resolvedLabels.region,
65
+ className: cn("inline-flex items-center pl-2", className),
66
+ "data-presence-stack": true,
67
+ ref,
68
+ role: "group",
69
+ ...rest,
70
+ children: [
71
+ visible.map((user) => /* @__PURE__ */ jsx(Avatar, { user }, user.id)),
72
+ hidden > 0 ? renderOverflow({
73
+ count: hidden,
74
+ handleClick: handleOverflow,
75
+ handlerProvided: Boolean(onOverflowActivate),
76
+ labels: resolvedLabels
77
+ }) : null
78
+ ]
79
+ }
80
+ );
81
+ }
82
+ );
83
+ PresenceStack.displayName = "PresenceStack";
84
+ const renderOverflow = (input) => {
85
+ const text = `+${input.count}`;
86
+ const aria = `${input.count} ${input.labels.overflowSuffix}`;
87
+ const className = "relative -ml-2 inline-flex h-7 min-w-7 items-center justify-center rounded-full border-2 border-background bg-muted px-1.5 text-[10px] font-semibold text-muted-foreground shadow-sm";
88
+ if (input.handlerProvided) {
89
+ return /* @__PURE__ */ jsx(
90
+ "button",
91
+ {
92
+ "aria-label": aria,
93
+ className: cn(
94
+ className,
95
+ "transition-colors hover:bg-muted/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
96
+ ),
97
+ "data-presence-stack-overflow": true,
98
+ onClick: input.handleClick,
99
+ type: "button",
100
+ children: text
101
+ }
102
+ );
103
+ }
104
+ return /* @__PURE__ */ jsx("span", { "aria-label": aria, className, "data-presence-stack-overflow": true, children: text });
105
+ };
106
+ export {
107
+ PresenceStack
108
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ PresenceSyncIndicator
3
+ } from "./presence-sync-indicator";
4
+ export {
5
+ PresenceSyncIndicator
6
+ };
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import {
4
+ forwardRef
5
+ } from "react";
6
+ import { cn } from "../../lib/utils";
7
+ const STATE_LABEL = {
8
+ error: "Sync error",
9
+ live: "Live",
10
+ offline: "Offline",
11
+ reconnecting: "Reconnecting",
12
+ syncing: "Syncing"
13
+ };
14
+ const STATE_DOT = {
15
+ error: "bg-red-500",
16
+ live: "bg-emerald-500",
17
+ offline: "bg-muted-foreground",
18
+ reconnecting: "bg-amber-500 animate-pulse",
19
+ syncing: "bg-blue-500 animate-pulse"
20
+ };
21
+ const STATE_TEXT = {
22
+ error: "text-red-700 dark:text-red-300",
23
+ live: "text-emerald-700 dark:text-emerald-300",
24
+ offline: "text-muted-foreground",
25
+ reconnecting: "text-amber-700 dark:text-amber-300",
26
+ syncing: "text-blue-700 dark:text-blue-300"
27
+ };
28
+ const DEFAULT_LABELS = {
29
+ region: "Presence sync"
30
+ };
31
+ const PresenceSyncIndicator = forwardRef((props, ref) => {
32
+ const { className, label, labels, state, status, ...rest } = props;
33
+ const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
34
+ const text = label ?? STATE_LABEL[state];
35
+ return /* @__PURE__ */ jsxs(
36
+ "div",
37
+ {
38
+ "aria-label": `${resolvedLabels.region}: ${STATE_LABEL[state]}`,
39
+ className: cn(
40
+ "inline-flex items-center gap-1.5 rounded-full border border-border bg-background px-2 py-1 text-[11px] shadow-sm",
41
+ className
42
+ ),
43
+ "data-presence-state": state,
44
+ "data-presence-sync": true,
45
+ ref,
46
+ role: "status",
47
+ ...rest,
48
+ children: [
49
+ /* @__PURE__ */ jsx(
50
+ "span",
51
+ {
52
+ "aria-hidden": "true",
53
+ className: cn("h-1.5 w-1.5 rounded-full", STATE_DOT[state]),
54
+ "data-presence-sync-dot": true
55
+ }
56
+ ),
57
+ /* @__PURE__ */ jsx("span", { className: cn("font-medium", STATE_TEXT[state]), children: text }),
58
+ status ? /* @__PURE__ */ jsx(
59
+ "span",
60
+ {
61
+ className: "text-[10px] text-muted-foreground",
62
+ "data-presence-sync-status": true,
63
+ children: status
64
+ }
65
+ ) : null
66
+ ]
67
+ }
68
+ );
69
+ });
70
+ PresenceSyncIndicator.displayName = "PresenceSyncIndicator";
71
+ export {
72
+ PresenceSyncIndicator
73
+ };
@@ -0,0 +1,6 @@
1
+ import {
2
+ RunTimeline
3
+ } from "./run-timeline";
4
+ export {
5
+ RunTimeline
6
+ };