@vvedantb/ui 0.17.0 → 0.18.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 (130) hide show
  1. package/README.md +253 -3
  2. package/package.json +13 -5
  3. package/shell/src/SidebarResize.tsx +1 -4
  4. package/src/ai-elements/__snapshots__/queue.test.tsx.snap +11 -0
  5. package/src/ai-elements/activity-question-utils.ts +26 -0
  6. package/src/ai-elements/activity-question.tsx +159 -0
  7. package/src/ai-elements/activity-shared.tsx +459 -0
  8. package/src/ai-elements/activity-step-detail.tsx +115 -0
  9. package/src/ai-elements/activity-step-label.ts +981 -0
  10. package/src/ai-elements/activity-tasks-utils.ts +199 -0
  11. package/src/ai-elements/activity-tasks.tsx +770 -0
  12. package/src/ai-elements/artifact.tsx +162 -52
  13. package/src/ai-elements/attachments.tsx +62 -32
  14. package/src/ai-elements/code-block.tsx +76 -22
  15. package/src/ai-elements/context.tsx +370 -0
  16. package/src/ai-elements/conversation.tsx +186 -62
  17. package/src/ai-elements/file-chip.tsx +53 -0
  18. package/src/ai-elements/message.tsx +161 -50
  19. package/src/ai-elements/model-picker-content.tsx +505 -0
  20. package/src/ai-elements/model-picker-types.ts +56 -0
  21. package/src/ai-elements/model-picker.tsx +301 -0
  22. package/src/ai-elements/model-selector.tsx +102 -21
  23. package/src/ai-elements/plan.tsx +130 -0
  24. package/src/ai-elements/prompt-input-settings.tsx +144 -0
  25. package/src/ai-elements/prompt-input-speech.tsx +189 -0
  26. package/src/ai-elements/prompt-input-traits.tsx +281 -0
  27. package/src/ai-elements/prompt-input.tsx +320 -134
  28. package/src/ai-elements/provider-icon.tsx +133 -0
  29. package/src/ai-elements/queue.tsx +293 -9
  30. package/src/ai-elements/shimmer.tsx +72 -1
  31. package/src/ai-elements/simple-model-ladder.tsx +108 -0
  32. package/src/ai-elements/test-results.tsx +510 -0
  33. package/src/ai-elements/trace.tsx +243 -0
  34. package/src/ai-elements/use-streaming-disclosure.ts +50 -0
  35. package/src/ai-elements/web-preview.tsx +349 -0
  36. package/src/composer/input-area/ComposerSlashMenu.tsx +1 -1
  37. package/src/index.ts +66 -12
  38. package/src/kibo/avatar-stack.tsx +40 -0
  39. package/src/kibo/contribution-graph.tsx +539 -0
  40. package/src/kibo/cursor.tsx +72 -0
  41. package/src/kibo/gantt-features.tsx +439 -0
  42. package/src/kibo/gantt-header.tsx +181 -0
  43. package/src/kibo/gantt-provider.tsx +657 -0
  44. package/src/kibo/gantt-sidebar.tsx +157 -0
  45. package/src/kibo/gantt-timeline.tsx +154 -0
  46. package/src/kibo/index.ts +151 -0
  47. package/src/kibo/kanban.tsx +338 -0
  48. package/src/kibo/kanbanDropTarget.ts +25 -0
  49. package/src/kibo/list.tsx +162 -0
  50. package/src/kibo/theme-switcher.tsx +109 -0
  51. package/src/kibo/video-player.tsx +237 -0
  52. package/src/markdown/Markdown.tsx +112 -0
  53. package/src/markdown/MarkdownBlockquote.tsx +45 -0
  54. package/src/markdown/MarkdownCodeBlock.tsx +197 -0
  55. package/src/markdown/MarkdownInlineCode.tsx +40 -0
  56. package/src/markdown/MarkdownLink.tsx +92 -0
  57. package/src/markdown/codeFence.ts +57 -0
  58. package/src/markdown/codeHighlight.ts +138 -0
  59. package/src/markdown/incrementalBlocks.ts +182 -0
  60. package/src/markdown/index.ts +3 -0
  61. package/src/markdown/markdownClipboard.ts +178 -0
  62. package/src/markdown/mermaid.ts +155 -0
  63. package/src/markdown/rehypeGithubAlerts.ts +80 -0
  64. package/src/motion/presets.ts +24 -0
  65. package/src/ui/__snapshots__/alt-wrappers.test.tsx.snap +19 -0
  66. package/src/ui/__snapshots__/sonner-dom.test.tsx.snap +5 -0
  67. package/src/ui/_menu-parts.tsx +29 -0
  68. package/src/ui/accordion.alt.tsx +46 -53
  69. package/src/ui/accordion.tsx +59 -10
  70. package/src/ui/avatar.tsx +56 -0
  71. package/src/ui/badge.tsx +45 -21
  72. package/src/ui/border-beam.tsx +97 -0
  73. package/src/ui/button-group.tsx +50 -21
  74. package/src/ui/button.tsx +67 -45
  75. package/src/ui/calendar.tsx +48 -5
  76. package/src/ui/card.tsx +77 -8
  77. package/src/ui/carousel.tsx +60 -0
  78. package/src/ui/centered-spinner.tsx +30 -0
  79. package/src/ui/checkbox.tsx +34 -16
  80. package/src/ui/clear-input.alt.tsx +33 -75
  81. package/src/ui/clear-input.tsx +140 -15
  82. package/src/ui/collapsible.tsx +40 -2
  83. package/src/ui/command.tsx +143 -70
  84. package/src/ui/context-menu.tsx +159 -93
  85. package/src/ui/crossfade-icon.tsx +123 -0
  86. package/src/ui/dialog.tsx +154 -70
  87. package/src/ui/dropdown-menu.tsx +177 -117
  88. package/src/ui/hover-card.tsx +59 -17
  89. package/src/ui/input-group.alt.tsx +83 -83
  90. package/src/ui/input-group.tsx +129 -58
  91. package/src/ui/input.tsx +13 -4
  92. package/src/ui/label.tsx +11 -8
  93. package/src/ui/list-row.tsx +232 -0
  94. package/src/ui/loading-state.tsx +215 -0
  95. package/src/ui/popover.tsx +56 -23
  96. package/src/ui/progress.tsx +28 -16
  97. package/src/ui/refresh-spin-icon.tsx +41 -0
  98. package/src/ui/search-input.tsx +66 -15
  99. package/src/ui/select.tsx +171 -100
  100. package/src/ui/separator.tsx +23 -14
  101. package/src/ui/slider.tsx +21 -7
  102. package/src/ui/sonner.tsx +68 -30
  103. package/src/ui/spinner.tsx +229 -11
  104. package/src/ui/status-dot.tsx +84 -0
  105. package/src/ui/surface.tsx +49 -0
  106. package/src/ui/switch.tsx +29 -15
  107. package/src/ui/table.tsx +38 -16
  108. package/src/ui/tabs.tsx +123 -35
  109. package/src/ui/tabsSliding.ts +33 -1
  110. package/src/ui/textarea.tsx +13 -4
  111. package/src/ui/tooltip.tsx +50 -14
  112. package/src/ui/ui-config.tsx +149 -0
  113. package/src/utils/cat-color.ts +123 -0
  114. package/src/utils/dayjs.ts +6 -0
  115. package/src/utils/gesture.ts +59 -0
  116. package/src/utils/runtimeVisibility.ts +167 -0
  117. package/src/utils/sharedClock.ts +96 -0
  118. package/src/utils/surface-radius.ts +16 -0
  119. package/src/utils/useDragSensors.ts +58 -0
  120. package/tokens/examples/tokens-moved/Fixture.tsx +283 -0
  121. package/tokens/examples/tokens-moved/README.md +20 -0
  122. package/tokens/examples/tokens-moved/index.html +12 -0
  123. package/tokens/examples/tokens-moved/main.tsx +6 -0
  124. package/tokens/examples/tokens-moved/package.json +14 -0
  125. package/tokens/examples/tokens-moved/styles.css +12 -0
  126. package/tokens/examples/tokens-moved/tsconfig.json +14 -0
  127. package/tokens/examples/tokens-moved/vite.config.ts +11 -0
  128. package/tokens/src/css/border-beam.css +116 -0
  129. package/tokens/src/css/compat-shadcn-rgb.css +6 -0
  130. package/tokens/src/css/markdown.css +318 -0
@@ -0,0 +1,157 @@
1
+ "use client";
2
+
3
+ import dayjs from "../utils/dayjs";
4
+ import type { FC, ReactNode } from "react";
5
+ import { useCn } from "../ui/ui-config";
6
+ import { CONTROL_RADIUS_CLASS } from "../utils/surface-radius";
7
+ import { useGanttContext, type GanttFeature } from "./gantt-provider";
8
+
9
+ export type GanttSidebarItemProps = {
10
+ feature: GanttFeature;
11
+ onSelectItem?: (id: string) => void;
12
+ /** Leading slot (e.g. a phase status icon). Falls back to a colour dot. */
13
+ icon?: ReactNode;
14
+ /** Trailing slot (e.g. avatars + progress). Falls back to the duration. */
15
+ meta?: ReactNode;
16
+ selected?: boolean;
17
+ className?: string;
18
+ };
19
+
20
+ export const GanttSidebarItem: FC<GanttSidebarItemProps> = ({
21
+ feature,
22
+ onSelectItem,
23
+ icon,
24
+ meta,
25
+ selected,
26
+ className,
27
+ }) => {
28
+ const gantt = useGanttContext();
29
+ const merge = useCn();
30
+ const tempEndAt =
31
+ feature.endAt && dayjs(feature.startAt).isSame(dayjs(feature.endAt), "day")
32
+ ? dayjs(feature.endAt).add(1, "day").toDate()
33
+ : feature.endAt;
34
+ const duration = tempEndAt
35
+ ? dayjs(feature.startAt).from(dayjs(tempEndAt), true)
36
+ : `${dayjs(feature.startAt).from(dayjs(), true)} so far`;
37
+
38
+ const select = () => {
39
+ gantt.scrollToFeature?.(feature);
40
+ onSelectItem?.(feature.id);
41
+ };
42
+
43
+ return (
44
+ // A plain row with a real `<button>` stretched across it, not a
45
+ // `role="button" tabIndex={0}` div — see `ui/list-row.tsx`, which documents
46
+ // why the div form needs a hand-written Enter/Space handler and still gets
47
+ // the role, focus and press semantics wrong. The row keeps its own `relative`
48
+ // so the overlay is bounded by it.
49
+ <div
50
+ className={merge(
51
+ "relative flex cursor-pointer items-center gap-2.5 px-2.5 text-xs transition-colors hover:bg-surface-secondary/50 has-[button:focus-visible]:ring-2 has-[button:focus-visible]:ring-ring/35",
52
+ CONTROL_RADIUS_CLASS,
53
+ selected && "bg-surface-secondary/60 ring-1 ring-inset ring-border",
54
+ className,
55
+ )}
56
+ key={feature.id}
57
+ style={{ height: "var(--gantt-row-height)" }}
58
+ >
59
+ <button
60
+ type="button"
61
+ onClick={select}
62
+ aria-label={feature.name}
63
+ className="absolute inset-0 z-1 outline-hidden"
64
+ />
65
+ {icon ? (
66
+ <span className="pointer-events-none flex shrink-0 items-center">
67
+ {icon}
68
+ </span>
69
+ ) : (
70
+ <div
71
+ className="pointer-events-none h-2 w-2 shrink-0 rounded-full"
72
+ style={{ backgroundColor: feature.status.color }}
73
+ />
74
+ )}
75
+ <p className="pointer-events-none flex-1 truncate text-left font-medium">
76
+ {feature.name}
77
+ </p>
78
+ {meta ? (
79
+ <div className="pointer-events-none flex shrink-0 items-center">
80
+ {meta}
81
+ </div>
82
+ ) : (
83
+ <p className="pointer-events-none text-muted-foreground tabular-nums">
84
+ {duration}
85
+ </p>
86
+ )}
87
+ </div>
88
+ );
89
+ };
90
+
91
+ type GanttSidebarHeaderProps = {
92
+ title?: string;
93
+ metaLabel?: string;
94
+ };
95
+
96
+ export const GanttSidebarHeader: FC<GanttSidebarHeaderProps> = ({
97
+ title = "Issues",
98
+ metaLabel = "Duration",
99
+ }) => (
100
+ <div
101
+ className="sticky top-0 z-10 flex shrink-0 items-end justify-between gap-2.5 border-b border-border bg-background/95 p-2.5 font-medium text-muted-foreground text-xs backdrop-blur-xs"
102
+ style={{ height: "var(--gantt-header-height)" }}
103
+ >
104
+ <p className="flex-1 truncate text-left">{title}</p>
105
+ <p className="shrink-0">{metaLabel}</p>
106
+ </div>
107
+ );
108
+
109
+ export type GanttSidebarGroupProps = {
110
+ children: ReactNode;
111
+ name: string;
112
+ className?: string;
113
+ };
114
+
115
+ export const GanttSidebarGroup: FC<GanttSidebarGroupProps> = ({
116
+ children,
117
+ name,
118
+ className,
119
+ }) => (
120
+ <div className={className}>
121
+ <p
122
+ className="w-full truncate p-2.5 text-left font-medium text-muted-foreground text-xs"
123
+ style={{ height: "var(--gantt-row-height)" }}
124
+ >
125
+ {name}
126
+ </p>
127
+ <div>{children}</div>
128
+ </div>
129
+ );
130
+
131
+ export type GanttSidebarProps = {
132
+ children: ReactNode;
133
+ className?: string;
134
+ headerTitle?: string;
135
+ headerMeta?: string;
136
+ };
137
+
138
+ export const GanttSidebar: FC<GanttSidebarProps> = ({
139
+ children,
140
+ className,
141
+ headerTitle,
142
+ headerMeta,
143
+ }) => {
144
+ const merge = useCn();
145
+ return (
146
+ <div
147
+ className={merge(
148
+ "sticky left-0 z-30 h-max min-h-full overflow-clip border-r border-border bg-background/95 backdrop-blur-md",
149
+ className,
150
+ )}
151
+ data-roadmap-ui="gantt-sidebar"
152
+ >
153
+ <GanttSidebarHeader title={headerTitle} metaLabel={headerMeta} />
154
+ <div>{children}</div>
155
+ </div>
156
+ );
157
+ };
@@ -0,0 +1,154 @@
1
+ "use client";
2
+
3
+ import dayjs from "../utils/dayjs";
4
+ import type { FC, ReactNode } from "react";
5
+ import { useId, useMemo } from "react";
6
+ import { useCn } from "../ui/ui-config";
7
+ import {
8
+ useGanttContext,
9
+ useGanttClasses,
10
+ getDifferenceIn,
11
+ calculateInnerOffset,
12
+ } from "./gantt-provider";
13
+
14
+ export type GanttTimelineProps = {
15
+ children: ReactNode;
16
+ className?: string;
17
+ };
18
+
19
+ export const GanttTimeline: FC<GanttTimelineProps> = ({
20
+ children,
21
+ className,
22
+ }) => {
23
+ const merge = useCn();
24
+ return (
25
+ <div
26
+ className={merge(
27
+ "relative flex h-full w-max flex-none overflow-clip",
28
+ className,
29
+ )}
30
+ >
31
+ {children}
32
+ </div>
33
+ );
34
+ };
35
+
36
+ export type GanttColumnsProps = {
37
+ columns: number;
38
+ isColumnSecondary?: (item: number) => boolean;
39
+ isColumnDivider?: (item: number) => boolean;
40
+ };
41
+
42
+ export const GanttColumns: FC<GanttColumnsProps> = ({
43
+ columns,
44
+ isColumnSecondary,
45
+ isColumnDivider,
46
+ }) => {
47
+ const id = useId();
48
+
49
+ return (
50
+ <div
51
+ className="grid h-full w-full"
52
+ style={{
53
+ gridTemplateColumns: `repeat(${columns}, var(--gantt-column-width))`,
54
+ }}
55
+ >
56
+ {Array.from({ length: columns }).map((_, index) => (
57
+ <GanttColumn
58
+ index={index}
59
+ isColumnSecondary={isColumnSecondary}
60
+ isColumnDivider={isColumnDivider}
61
+ key={`${id}-${index}`}
62
+ />
63
+ ))}
64
+ </div>
65
+ );
66
+ };
67
+
68
+ export type GanttColumnProps = {
69
+ index: number;
70
+ isColumnSecondary?: (item: number) => boolean;
71
+ isColumnDivider?: (item: number) => boolean;
72
+ };
73
+
74
+ export const GanttColumn: FC<GanttColumnProps> = ({
75
+ index,
76
+ isColumnSecondary,
77
+ isColumnDivider,
78
+ }) => {
79
+ const merge = useCn();
80
+ return (
81
+ <div
82
+ className={merge(
83
+ "group relative h-full overflow-hidden",
84
+ isColumnDivider
85
+ ? isColumnDivider(index)
86
+ ? "border-l border-border/50"
87
+ : ""
88
+ : "border-r border-border/40",
89
+ isColumnSecondary?.(index) ? "bg-surface-secondary/30" : "",
90
+ )}
91
+ />
92
+ );
93
+ };
94
+
95
+ export type GanttTodayProps = {
96
+ className?: string;
97
+ };
98
+
99
+ export const GanttToday: FC<GanttTodayProps> = ({ className }) => {
100
+ const gantt = useGanttContext();
101
+ const classes = useGanttClasses();
102
+ const merge = useCn();
103
+ const date = useMemo(() => new Date(), []);
104
+
105
+ const differenceIn = useMemo(
106
+ () => getDifferenceIn(gantt.range),
107
+ [gantt.range],
108
+ );
109
+ const timelineStartDate = useMemo(() => {
110
+ const firstYear = gantt.timelineData[0]?.year ?? new Date().getFullYear();
111
+ return new Date(firstYear, 0, 1);
112
+ }, [gantt.timelineData]);
113
+
114
+ const offset = useMemo(
115
+ () => differenceIn(date, timelineStartDate),
116
+ [differenceIn, date, timelineStartDate],
117
+ );
118
+ const innerOffset = useMemo(
119
+ () =>
120
+ calculateInnerOffset(
121
+ date,
122
+ gantt.range,
123
+ (gantt.columnWidth * gantt.zoom) / 100,
124
+ ),
125
+ [date, gantt.range, gantt.columnWidth, gantt.zoom],
126
+ );
127
+
128
+ return (
129
+ <div
130
+ className="pointer-events-none absolute top-0 left-0 z-20 flex h-full select-none flex-col items-center justify-center overflow-visible"
131
+ style={{
132
+ width: 0,
133
+ transform: `translateX(calc(var(--gantt-column-width) * ${offset} + ${innerOffset}px))`,
134
+ }}
135
+ >
136
+ <div
137
+ className={merge(
138
+ classes.today,
139
+ className,
140
+ )}
141
+ >
142
+ Today
143
+ {/* Only max-height, not `all`: the pill inherits colour from its
144
+ parent, so `transition-all` also dragged those along. The height
145
+ animation relayouts nothing outside the marker, which is absolutely
146
+ positioned at zero width. */}
147
+ <span className={classes.todayDate}>
148
+ {dayjs(date).format("MMM DD, YYYY")}
149
+ </span>
150
+ </div>
151
+ <div className={merge("h-full w-px bg-primary/70", className)} />
152
+ </div>
153
+ );
154
+ };
@@ -0,0 +1,151 @@
1
+ export {
2
+ GanttProvider,
3
+ GanttContext,
4
+ useGanttContext,
5
+ type GanttProviderProps,
6
+ type GanttStatus,
7
+ type GanttFeature,
8
+ type GanttMarkerProps,
9
+ type GanttRange,
10
+ type GanttTimelineData,
11
+ type GanttContextProps,
12
+ type GanttConfig,
13
+ } from "./gantt-provider";
14
+
15
+ export {
16
+ GanttHeader,
17
+ GanttContentHeader,
18
+ type GanttHeaderProps,
19
+ type GanttContentHeaderProps,
20
+ } from "./gantt-header";
21
+
22
+ export {
23
+ GanttTimeline,
24
+ GanttColumns,
25
+ GanttColumn,
26
+ GanttToday,
27
+ type GanttTimelineProps,
28
+ type GanttColumnsProps,
29
+ type GanttColumnProps,
30
+ type GanttTodayProps,
31
+ } from "./gantt-timeline";
32
+
33
+ export {
34
+ GanttSidebar,
35
+ GanttSidebarHeader,
36
+ GanttSidebarItem,
37
+ GanttSidebarGroup,
38
+ type GanttSidebarProps,
39
+ type GanttSidebarItemProps,
40
+ type GanttSidebarGroupProps,
41
+ } from "./gantt-sidebar";
42
+
43
+ export {
44
+ ContributionGraph,
45
+ ContributionGraphBlock,
46
+ ContributionGraphCalendar,
47
+ ContributionGraphFooter,
48
+ ContributionGraphTotalCount,
49
+ ContributionGraphLegend,
50
+ type ContributionGraphActivity,
51
+ type ContributionGraphLabels,
52
+ type ContributionGraphProps,
53
+ type ContributionGraphBlockProps,
54
+ type ContributionGraphCalendarProps,
55
+ type ContributionGraphFooterProps,
56
+ type ContributionGraphTotalCountProps,
57
+ type ContributionGraphLegendProps,
58
+ } from "./contribution-graph";
59
+
60
+ export {
61
+ KanbanProvider,
62
+ KanbanBoard,
63
+ KanbanHeader,
64
+ KanbanCards,
65
+ KanbanCard,
66
+ useKanbanContext,
67
+ type KanbanProviderProps,
68
+ type KanbanBoardProps,
69
+ type KanbanHeaderProps,
70
+ type KanbanCardsProps,
71
+ type KanbanCardProps,
72
+ type KanbanItem,
73
+ type KanbanColumnDef,
74
+ type KanbanConfig,
75
+ } from "./kanban";
76
+
77
+ export {
78
+ SortableListProvider,
79
+ SortableListGroup,
80
+ SortableListHeader,
81
+ SortableListItems,
82
+ SortableListItem,
83
+ type SortableListProviderProps,
84
+ type SortableListGroupProps,
85
+ type SortableListHeaderProps,
86
+ type SortableListItemsProps,
87
+ type SortableListItemProps,
88
+ type SortableListDragEndEvent,
89
+ } from "./list";
90
+
91
+ export {
92
+ GanttFeatureList,
93
+ GanttFeatureListGroup,
94
+ GanttFeatureRow,
95
+ GanttFeatureItem,
96
+ GanttFeatureItemCard,
97
+ GanttFeatureDragHelper,
98
+ type GanttFeatureListProps,
99
+ type GanttFeatureListGroupProps,
100
+ type GanttFeatureRowProps,
101
+ type GanttFeatureItemProps,
102
+ type GanttFeatureItemCardProps,
103
+ type GanttFeatureDragHelperProps,
104
+ } from "./gantt-features";
105
+
106
+ export {
107
+ ThemeSwitcher,
108
+ type ThemeSwitcherProps,
109
+ type ThemeSwitcherConfig,
110
+ } from "./theme-switcher";
111
+
112
+ export {
113
+ VideoPlayer,
114
+ VideoPlayerControlBar,
115
+ VideoPlayerTimeRange,
116
+ VideoPlayerTimeDisplay,
117
+ VideoPlayerVolumeRange,
118
+ VideoPlayerPlayButton,
119
+ VideoPlayerSeekBackwardButton,
120
+ VideoPlayerSeekForwardButton,
121
+ VideoPlayerMuteButton,
122
+ VideoPlayerPlaybackRateButton,
123
+ VideoPlayerFullscreenButton,
124
+ VideoPlayerContent,
125
+ type VideoPlayerProps,
126
+ type VideoPlayerControlBarProps,
127
+ type VideoPlayerTimeRangeProps,
128
+ type VideoPlayerTimeDisplayProps,
129
+ type VideoPlayerVolumeRangeProps,
130
+ type VideoPlayerPlayButtonProps,
131
+ type VideoPlayerSeekBackwardButtonProps,
132
+ type VideoPlayerSeekForwardButtonProps,
133
+ type VideoPlayerMuteButtonProps,
134
+ type VideoPlayerPlaybackRateButtonProps,
135
+ type VideoPlayerFullscreenButtonProps,
136
+ type VideoPlayerContentProps,
137
+ type VideoPlayerConfig,
138
+ } from "./video-player";
139
+
140
+ export { AvatarStack, type AvatarStackProps } from "./avatar-stack";
141
+
142
+ export {
143
+ LiveCursor,
144
+ LiveCursorPointer,
145
+ LiveCursorBody,
146
+ LiveCursorName,
147
+ type LiveCursorProps,
148
+ type LiveCursorPointerProps,
149
+ type LiveCursorBodyProps,
150
+ type LiveCursorNameProps,
151
+ } from "./cursor";