dreamboard 0.1.21 → 0.1.23

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 (186) hide show
  1. package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
  2. package/dist/chunk-2RCUHMGL.js.map +1 -0
  3. package/dist/{chunk-MOVHYB6E.js → chunk-GN7232BY.js} +1025 -695
  4. package/dist/chunk-GN7232BY.js.map +1 -0
  5. package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
  6. package/dist/chunk-H3O43F5P.js.map +1 -0
  7. package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
  8. package/dist/dev-host/dev-diagnostics.ts +62 -0
  9. package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
  10. package/dist/dev-host/dev-host-controller.ts +686 -0
  11. package/dist/dev-host/dev-host-player-query.ts +17 -0
  12. package/dist/dev-host/dev-host-session-transport.ts +52 -0
  13. package/dist/dev-host/dev-host-storage.ts +56 -0
  14. package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
  15. package/dist/dev-host/dev-runtime-config.ts +14 -0
  16. package/dist/dev-host/dev-runtime-platform.ts +419 -0
  17. package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
  18. package/dist/dev-host/host-main.css +182 -0
  19. package/dist/dev-host/host-main.tsx +754 -0
  20. package/dist/dev-host/index.html +56 -0
  21. package/dist/dev-host/plugin-main.ts +55 -0
  22. package/dist/dev-host/plugin.html +24 -0
  23. package/dist/dev-host/start-dev-server.ts +138 -0
  24. package/dist/dev-host/virtual-modules.d.ts +27 -0
  25. package/dist/dist-FEPN3BDN.js +16543 -0
  26. package/dist/dist-FEPN3BDN.js.map +1 -0
  27. package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
  28. package/dist/index.js +3 -3
  29. package/dist/internal.js +159 -124
  30. package/dist/internal.js.map +1 -1
  31. package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
  32. package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
  33. package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
  34. package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
  35. package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
  36. package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
  37. package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
  38. package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
  39. package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
  40. package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
  41. package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
  42. package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
  43. package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
  44. package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
  45. package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
  46. package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
  47. package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
  48. package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
  49. package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
  50. package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
  51. package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
  52. package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
  53. package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
  54. package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
  55. package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
  56. package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
  57. package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
  58. package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
  59. package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
  60. package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
  61. package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
  62. package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
  63. package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
  64. package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
  65. package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
  66. package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
  67. package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
  68. package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
  69. package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
  70. package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
  71. package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
  72. package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
  73. package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
  74. package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
  75. package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
  76. package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
  77. package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
  78. package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
  79. package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
  80. package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
  81. package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
  82. package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
  83. package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
  84. package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
  85. package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
  86. package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
  87. package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
  88. package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
  89. package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
  90. package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
  91. package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
  92. package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
  93. package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
  94. package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
  95. package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
  96. package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
  97. package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
  98. package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
  99. package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
  100. package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
  101. package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
  102. package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
  103. package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
  104. package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
  105. package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
  106. package/dist/runtime-packages/ui/src/index.ts +68 -0
  107. package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
  108. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
  109. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
  110. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
  111. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
  112. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
  113. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
  114. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
  115. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
  116. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
  117. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
  118. package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
  119. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
  120. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
  121. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
  122. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
  123. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
  124. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
  125. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
  126. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
  127. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
  128. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
  129. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
  130. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
  131. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
  132. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
  133. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
  134. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
  135. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
  136. package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
  137. package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
  138. package/package.json +52 -17
  139. package/skills/dreamboard/SKILL.md +41 -75
  140. package/LICENSE +0 -89
  141. package/NOTICE +0 -1
  142. package/dist/chunk-BMYC6772.js.map +0 -1
  143. package/dist/chunk-EYYWGWTO.js.map +0 -1
  144. package/dist/chunk-MOVHYB6E.js.map +0 -1
  145. package/dist/scaffold/assets/static/ui/App.tsx +0 -22
  146. package/dist/src-CUL7EGGG.js +0 -634
  147. package/dist/src-CUL7EGGG.js.map +0 -1
  148. package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
  149. package/skills/dreamboard/references/board-surfaces.md +0 -36
  150. package/skills/dreamboard/references/board-topology.md +0 -443
  151. package/skills/dreamboard/references/boards-and-topology.md +0 -100
  152. package/skills/dreamboard/references/card-actions.md +0 -107
  153. package/skills/dreamboard/references/cli.md +0 -120
  154. package/skills/dreamboard/references/core-concepts.md +0 -514
  155. package/skills/dreamboard/references/custom-renderers.md +0 -26
  156. package/skills/dreamboard/references/derived-values.md +0 -55
  157. package/skills/dreamboard/references/effects.md +0 -111
  158. package/skills/dreamboard/references/game-contract.md +0 -89
  159. package/skills/dreamboard/references/game-definition.md +0 -89
  160. package/skills/dreamboard/references/game-shell.md +0 -80
  161. package/skills/dreamboard/references/hand-surfaces.md +0 -33
  162. package/skills/dreamboard/references/index.md +0 -112
  163. package/skills/dreamboard/references/inputs-and-targets.md +0 -160
  164. package/skills/dreamboard/references/interactions.md +0 -158
  165. package/skills/dreamboard/references/manifest-fields.md +0 -137
  166. package/skills/dreamboard/references/manifest.md +0 -81
  167. package/skills/dreamboard/references/package-surfaces.md +0 -69
  168. package/skills/dreamboard/references/phases.md +0 -145
  169. package/skills/dreamboard/references/prompts-and-choices.md +0 -55
  170. package/skills/dreamboard/references/quickstart.md +0 -71
  171. package/skills/dreamboard/references/rule-authoring.md +0 -144
  172. package/skills/dreamboard/references/setup-bootstrap.md +0 -78
  173. package/skills/dreamboard/references/stages-and-zones.md +0 -59
  174. package/skills/dreamboard/references/static-views.md +0 -67
  175. package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
  176. package/skills/dreamboard/references/testing-bases.md +0 -147
  177. package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
  178. package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
  179. package/skills/dreamboard/references/testing-scenarios.md +0 -148
  180. package/skills/dreamboard/references/testing-ui-tests.md +0 -174
  181. package/skills/dreamboard/references/testing.md +0 -161
  182. package/skills/dreamboard/references/ui-architecture.md +0 -137
  183. package/skills/dreamboard/references/ui-components.md +0 -34
  184. package/skills/dreamboard/references/views.md +0 -72
  185. package/skills/dreamboard/references/workspace-layout.md +0 -136
  186. /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
@@ -0,0 +1,274 @@
1
+ "use client";
2
+
3
+ import { Button } from "@dreamboard/ui/components/button";
4
+ import {
5
+ Collapsible,
6
+ CollapsibleContent,
7
+ CollapsibleTrigger,
8
+ } from "@dreamboard/ui/components/collapsible";
9
+ import { ScrollArea } from "@dreamboard/ui/components/scroll-area";
10
+ import { cn } from "@dreamboard/ui/lib/utils";
11
+ import { ChevronDownIcon, PaperclipIcon } from "lucide-react";
12
+ import type { ComponentProps } from "react";
13
+
14
+ export interface QueueMessagePart {
15
+ type: string;
16
+ text?: string;
17
+ url?: string;
18
+ filename?: string;
19
+ mediaType?: string;
20
+ }
21
+
22
+ export interface QueueMessage {
23
+ id: string;
24
+ parts: QueueMessagePart[];
25
+ }
26
+
27
+ export interface QueueTodo {
28
+ id: string;
29
+ title: string;
30
+ description?: string;
31
+ status?: "pending" | "completed";
32
+ }
33
+
34
+ export type QueueItemProps = ComponentProps<"li">;
35
+
36
+ export const QueueItem = ({ className, ...props }: QueueItemProps) => (
37
+ <li
38
+ className={cn(
39
+ "group flex flex-col gap-1 rounded-md px-3 py-1 text-sm transition-colors hover:bg-muted",
40
+ className,
41
+ )}
42
+ {...props}
43
+ />
44
+ );
45
+
46
+ export type QueueItemIndicatorProps = ComponentProps<"span"> & {
47
+ completed?: boolean;
48
+ };
49
+
50
+ export const QueueItemIndicator = ({
51
+ completed = false,
52
+ className,
53
+ ...props
54
+ }: QueueItemIndicatorProps) => (
55
+ <span
56
+ className={cn(
57
+ "mt-0.5 inline-block size-2.5 rounded-full border",
58
+ completed
59
+ ? "border-muted-foreground/20 bg-muted-foreground/10"
60
+ : "border-muted-foreground/50",
61
+ className,
62
+ )}
63
+ {...props}
64
+ />
65
+ );
66
+
67
+ export type QueueItemContentProps = ComponentProps<"span"> & {
68
+ completed?: boolean;
69
+ };
70
+
71
+ export const QueueItemContent = ({
72
+ completed = false,
73
+ className,
74
+ ...props
75
+ }: QueueItemContentProps) => (
76
+ <span
77
+ className={cn(
78
+ "line-clamp-1 grow break-words",
79
+ completed
80
+ ? "text-muted-foreground/50 line-through"
81
+ : "text-muted-foreground",
82
+ className,
83
+ )}
84
+ {...props}
85
+ />
86
+ );
87
+
88
+ export type QueueItemDescriptionProps = ComponentProps<"div"> & {
89
+ completed?: boolean;
90
+ };
91
+
92
+ export const QueueItemDescription = ({
93
+ completed = false,
94
+ className,
95
+ ...props
96
+ }: QueueItemDescriptionProps) => (
97
+ <div
98
+ className={cn(
99
+ "ml-6 text-xs",
100
+ completed
101
+ ? "text-muted-foreground/40 line-through"
102
+ : "text-muted-foreground",
103
+ className,
104
+ )}
105
+ {...props}
106
+ />
107
+ );
108
+
109
+ export type QueueItemActionsProps = ComponentProps<"div">;
110
+
111
+ export const QueueItemActions = ({
112
+ className,
113
+ ...props
114
+ }: QueueItemActionsProps) => (
115
+ <div className={cn("flex gap-1", className)} {...props} />
116
+ );
117
+
118
+ export type QueueItemActionProps = Omit<
119
+ ComponentProps<typeof Button>,
120
+ "variant" | "size"
121
+ >;
122
+
123
+ export const QueueItemAction = ({
124
+ className,
125
+ ...props
126
+ }: QueueItemActionProps) => (
127
+ <Button
128
+ className={cn(
129
+ "size-auto rounded p-1 text-muted-foreground opacity-0 transition-opacity hover:bg-muted-foreground/10 hover:text-foreground group-hover:opacity-100",
130
+ className,
131
+ )}
132
+ size="icon"
133
+ type="button"
134
+ variant="ghost"
135
+ {...props}
136
+ />
137
+ );
138
+
139
+ export type QueueItemAttachmentProps = ComponentProps<"div">;
140
+
141
+ export const QueueItemAttachment = ({
142
+ className,
143
+ ...props
144
+ }: QueueItemAttachmentProps) => (
145
+ <div className={cn("mt-1 flex flex-wrap gap-2", className)} {...props} />
146
+ );
147
+
148
+ export type QueueItemImageProps = ComponentProps<"img">;
149
+
150
+ export const QueueItemImage = ({
151
+ className,
152
+ ...props
153
+ }: QueueItemImageProps) => (
154
+ <img
155
+ alt=""
156
+ className={cn("h-8 w-8 rounded border object-cover", className)}
157
+ height={32}
158
+ width={32}
159
+ {...props}
160
+ />
161
+ );
162
+
163
+ export type QueueItemFileProps = ComponentProps<"span">;
164
+
165
+ export const QueueItemFile = ({
166
+ children,
167
+ className,
168
+ ...props
169
+ }: QueueItemFileProps) => (
170
+ <span
171
+ className={cn(
172
+ "flex items-center gap-1 rounded border bg-muted px-2 py-1 text-xs",
173
+ className,
174
+ )}
175
+ {...props}
176
+ >
177
+ <PaperclipIcon size={12} />
178
+ <span className="max-w-[100px] truncate">{children}</span>
179
+ </span>
180
+ );
181
+
182
+ export type QueueListProps = ComponentProps<typeof ScrollArea>;
183
+
184
+ export const QueueList = ({
185
+ children,
186
+ className,
187
+ ...props
188
+ }: QueueListProps) => (
189
+ <ScrollArea className={cn("-mb-1 mt-2", className)} {...props}>
190
+ <div className="max-h-40 pr-4">
191
+ <ul>{children}</ul>
192
+ </div>
193
+ </ScrollArea>
194
+ );
195
+
196
+ // QueueSection - collapsible section container
197
+ export type QueueSectionProps = ComponentProps<typeof Collapsible>;
198
+
199
+ export const QueueSection = ({
200
+ className,
201
+ defaultOpen = true,
202
+ ...props
203
+ }: QueueSectionProps) => (
204
+ <Collapsible className={cn(className)} defaultOpen={defaultOpen} {...props} />
205
+ );
206
+
207
+ // QueueSectionTrigger - section header/trigger
208
+ export type QueueSectionTriggerProps = ComponentProps<"button">;
209
+
210
+ export const QueueSectionTrigger = ({
211
+ children,
212
+ className,
213
+ ...props
214
+ }: QueueSectionTriggerProps) => (
215
+ <CollapsibleTrigger asChild>
216
+ <button
217
+ className={cn(
218
+ "group flex w-full items-center justify-between rounded-md bg-muted/40 px-3 py-2 text-left font-medium text-muted-foreground text-sm transition-colors hover:bg-muted",
219
+ className,
220
+ )}
221
+ type="button"
222
+ {...props}
223
+ >
224
+ {children}
225
+ </button>
226
+ </CollapsibleTrigger>
227
+ );
228
+
229
+ // QueueSectionLabel - label content with icon and count
230
+ export type QueueSectionLabelProps = ComponentProps<"span"> & {
231
+ count?: number;
232
+ label: string;
233
+ icon?: React.ReactNode;
234
+ };
235
+
236
+ export const QueueSectionLabel = ({
237
+ count,
238
+ label,
239
+ icon,
240
+ className,
241
+ ...props
242
+ }: QueueSectionLabelProps) => (
243
+ <span className={cn("flex items-center gap-2", className)} {...props}>
244
+ <ChevronDownIcon className="group-data-[state=closed]:-rotate-90 size-4 transition-transform" />
245
+ {icon}
246
+ <span>
247
+ {count} {label}
248
+ </span>
249
+ </span>
250
+ );
251
+
252
+ // QueueSectionContent - collapsible content area
253
+ export type QueueSectionContentProps = ComponentProps<
254
+ typeof CollapsibleContent
255
+ >;
256
+
257
+ export const QueueSectionContent = ({
258
+ className,
259
+ ...props
260
+ }: QueueSectionContentProps) => (
261
+ <CollapsibleContent className={cn(className)} {...props} />
262
+ );
263
+
264
+ export type QueueProps = ComponentProps<"div">;
265
+
266
+ export const Queue = ({ className, ...props }: QueueProps) => (
267
+ <div
268
+ className={cn(
269
+ "flex flex-col gap-2 rounded-xl border border-border bg-background px-3 pt-2 pb-2 shadow-xs",
270
+ className,
271
+ )}
272
+ {...props}
273
+ />
274
+ );
@@ -0,0 +1,182 @@
1
+ "use client";
2
+
3
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
4
+ import {
5
+ Collapsible,
6
+ CollapsibleContent,
7
+ CollapsibleTrigger,
8
+ } from "@dreamboard/ui/components/collapsible";
9
+ import { cn } from "@dreamboard/ui/lib/utils";
10
+ import { BrainIcon, ChevronDownIcon } from "lucide-react";
11
+ import type { ComponentProps } from "react";
12
+ import { createContext, memo, useContext, useEffect, useState } from "react";
13
+ import { Response } from "./response.js";
14
+ import { Shimmer } from "./shimmer.js";
15
+
16
+ interface ReasoningContextValue {
17
+ isStreaming: boolean;
18
+ isOpen: boolean;
19
+ setIsOpen: (open: boolean) => void;
20
+ duration: number;
21
+ }
22
+
23
+ const ReasoningContext = createContext<ReasoningContextValue | null>(null);
24
+
25
+ const useReasoning = () => {
26
+ const context = useContext(ReasoningContext);
27
+ if (!context) {
28
+ throw new Error("Reasoning components must be used within Reasoning");
29
+ }
30
+ return context;
31
+ };
32
+
33
+ export type ReasoningProps = ComponentProps<typeof Collapsible> & {
34
+ isStreaming?: boolean;
35
+ open?: boolean;
36
+ defaultOpen?: boolean;
37
+ onOpenChange?: (open: boolean) => void;
38
+ duration?: number;
39
+ };
40
+
41
+ const AUTO_CLOSE_DELAY = 1000;
42
+ const MS_IN_S = 1000;
43
+
44
+ export const Reasoning = memo(
45
+ ({
46
+ className,
47
+ isStreaming = false,
48
+ open,
49
+ defaultOpen = true,
50
+ onOpenChange,
51
+ duration: durationProp,
52
+ children,
53
+ ...props
54
+ }: ReasoningProps) => {
55
+ const [isOpen, setIsOpen] = useControllableState({
56
+ prop: open,
57
+ defaultProp: defaultOpen,
58
+ onChange: onOpenChange,
59
+ });
60
+ const [duration, setDuration] = useControllableState({
61
+ prop: durationProp,
62
+ defaultProp: 0,
63
+ });
64
+
65
+ const [hasAutoClosed, setHasAutoClosed] = useState(false);
66
+ const [startTime, setStartTime] = useState<number | null>(null);
67
+
68
+ // Track duration when streaming starts and ends
69
+ useEffect(() => {
70
+ if (isStreaming) {
71
+ if (startTime === null) {
72
+ setStartTime(Date.now());
73
+ }
74
+ } else if (startTime !== null) {
75
+ setDuration(Math.ceil((Date.now() - startTime) / MS_IN_S));
76
+ setStartTime(null);
77
+ }
78
+ }, [isStreaming, startTime, setDuration]);
79
+
80
+ // Auto-open when streaming starts, auto-close when streaming ends (once only)
81
+ useEffect(() => {
82
+ if (defaultOpen && !isStreaming && isOpen && !hasAutoClosed) {
83
+ // Add a small delay before closing to allow user to see the content
84
+ const timer = setTimeout(() => {
85
+ setIsOpen(false);
86
+ setHasAutoClosed(true);
87
+ }, AUTO_CLOSE_DELAY);
88
+
89
+ return () => clearTimeout(timer);
90
+ }
91
+ return undefined;
92
+ }, [isStreaming, isOpen, defaultOpen, setIsOpen, hasAutoClosed]);
93
+
94
+ const handleOpenChange = (newOpen: boolean) => {
95
+ setIsOpen(newOpen);
96
+ };
97
+
98
+ return (
99
+ <ReasoningContext.Provider
100
+ value={{ isStreaming, isOpen, setIsOpen, duration }}
101
+ >
102
+ <Collapsible
103
+ className={cn("not-prose mb-4", className)}
104
+ onOpenChange={handleOpenChange}
105
+ open={isOpen}
106
+ {...props}
107
+ >
108
+ {children}
109
+ </Collapsible>
110
+ </ReasoningContext.Provider>
111
+ );
112
+ },
113
+ );
114
+
115
+ export type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger>;
116
+
117
+ const getThinkingMessage = (
118
+ isStreaming: boolean,
119
+ duration?: number,
120
+ ): React.ReactElement => {
121
+ if (isStreaming || duration === 0) {
122
+ return <Shimmer duration={1}>Thinking...</Shimmer>;
123
+ }
124
+ if (duration === undefined) {
125
+ return <p>Thought for a few seconds</p>;
126
+ }
127
+ return <p>Thought for {duration} seconds</p>;
128
+ };
129
+
130
+ export const ReasoningTrigger = memo(
131
+ ({ className, children, ...props }: ReasoningTriggerProps) => {
132
+ const { isStreaming, isOpen, duration } = useReasoning();
133
+
134
+ return (
135
+ <CollapsibleTrigger
136
+ className={cn(
137
+ "flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
138
+ className,
139
+ )}
140
+ {...props}
141
+ >
142
+ {children ?? (
143
+ <>
144
+ <BrainIcon className="size-4" />
145
+ {getThinkingMessage(isStreaming, duration)}
146
+ <ChevronDownIcon
147
+ className={cn(
148
+ "size-4 transition-transform",
149
+ isOpen ? "rotate-180" : "rotate-0",
150
+ )}
151
+ />
152
+ </>
153
+ )}
154
+ </CollapsibleTrigger>
155
+ );
156
+ },
157
+ );
158
+
159
+ export type ReasoningContentProps = ComponentProps<
160
+ typeof CollapsibleContent
161
+ > & {
162
+ children: string;
163
+ };
164
+
165
+ export const ReasoningContent = memo(
166
+ ({ className, children, ...props }: ReasoningContentProps) => (
167
+ <CollapsibleContent
168
+ className={cn(
169
+ "mt-4 text-sm",
170
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
171
+ className,
172
+ )}
173
+ {...props}
174
+ >
175
+ <Response className="grid gap-2">{children}</Response>
176
+ </CollapsibleContent>
177
+ ),
178
+ );
179
+
180
+ Reasoning.displayName = "Reasoning";
181
+ ReasoningTrigger.displayName = "ReasoningTrigger";
182
+ ReasoningContent.displayName = "ReasoningContent";
@@ -0,0 +1,22 @@
1
+ "use client";
2
+
3
+ import { cn } from "@dreamboard/ui/lib/utils";
4
+ import { type ComponentProps, memo } from "react";
5
+ import { Streamdown } from "streamdown";
6
+
7
+ type ResponseProps = ComponentProps<typeof Streamdown>;
8
+
9
+ export const Response = memo(
10
+ ({ className, ...props }: ResponseProps) => (
11
+ <Streamdown
12
+ className={cn(
13
+ "size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
14
+ className,
15
+ )}
16
+ {...props}
17
+ />
18
+ ),
19
+ (prevProps, nextProps) => prevProps.children === nextProps.children,
20
+ );
21
+
22
+ Response.displayName = "Response";
@@ -0,0 +1,64 @@
1
+ "use client";
2
+
3
+ import { cn } from "@dreamboard/ui/lib/utils";
4
+ import { motion } from "motion/react";
5
+ import {
6
+ type CSSProperties,
7
+ type ElementType,
8
+ type JSX,
9
+ memo,
10
+ useMemo,
11
+ } from "react";
12
+
13
+ export interface TextShimmerProps {
14
+ children: string;
15
+ as?: ElementType;
16
+ className?: string;
17
+ duration?: number;
18
+ spread?: number;
19
+ }
20
+
21
+ const ShimmerComponent = ({
22
+ children,
23
+ as: Component = "p",
24
+ className,
25
+ duration = 2,
26
+ spread = 2,
27
+ }: TextShimmerProps) => {
28
+ const MotionComponent = motion.create(
29
+ Component as keyof JSX.IntrinsicElements,
30
+ );
31
+
32
+ const dynamicSpread = useMemo(
33
+ () => (children?.length ?? 0) * spread,
34
+ [children, spread],
35
+ );
36
+
37
+ return (
38
+ <MotionComponent
39
+ animate={{ backgroundPosition: "0% center" }}
40
+ className={cn(
41
+ "relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent",
42
+ "[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),var(--color-background),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]",
43
+ className,
44
+ )}
45
+ initial={{ backgroundPosition: "100% center" }}
46
+ style={
47
+ {
48
+ "--spread": `${dynamicSpread}px`,
49
+ backgroundImage:
50
+ "var(--bg), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))",
51
+ } as CSSProperties
52
+ }
53
+ transition={{
54
+ repeat: Number.POSITIVE_INFINITY,
55
+ duration,
56
+ ease: "linear",
57
+ }}
58
+ >
59
+ {children}
60
+ </MotionComponent>
61
+ );
62
+ };
63
+
64
+ export const Shimmer = memo(ShimmerComponent);
@@ -0,0 +1,77 @@
1
+ "use client";
2
+
3
+ import {
4
+ Collapsible,
5
+ CollapsibleContent,
6
+ CollapsibleTrigger,
7
+ } from "@dreamboard/ui/components/collapsible";
8
+ import { cn } from "@dreamboard/ui/lib/utils";
9
+ import { BookIcon, ChevronDownIcon } from "lucide-react";
10
+ import type { ComponentProps } from "react";
11
+
12
+ export type SourcesProps = ComponentProps<"div">;
13
+
14
+ export const Sources = ({ className, ...props }: SourcesProps) => (
15
+ <Collapsible
16
+ className={cn("not-prose mb-4 text-primary text-xs", className)}
17
+ {...props}
18
+ />
19
+ );
20
+
21
+ export type SourcesTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {
22
+ count: number;
23
+ };
24
+
25
+ export const SourcesTrigger = ({
26
+ className,
27
+ count,
28
+ children,
29
+ ...props
30
+ }: SourcesTriggerProps) => (
31
+ <CollapsibleTrigger
32
+ className={cn("flex items-center gap-2", className)}
33
+ {...props}
34
+ >
35
+ {children ?? (
36
+ <>
37
+ <p className="font-medium">Used {count} sources</p>
38
+ <ChevronDownIcon className="h-4 w-4" />
39
+ </>
40
+ )}
41
+ </CollapsibleTrigger>
42
+ );
43
+
44
+ export type SourcesContentProps = ComponentProps<typeof CollapsibleContent>;
45
+
46
+ export const SourcesContent = ({
47
+ className,
48
+ ...props
49
+ }: SourcesContentProps) => (
50
+ <CollapsibleContent
51
+ className={cn(
52
+ "mt-3 flex w-fit flex-col gap-2",
53
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
54
+ className,
55
+ )}
56
+ {...props}
57
+ />
58
+ );
59
+
60
+ export type SourceProps = ComponentProps<"a">;
61
+
62
+ export const Source = ({ href, title, children, ...props }: SourceProps) => (
63
+ <a
64
+ className="flex items-center gap-2"
65
+ href={href}
66
+ rel="noreferrer"
67
+ target="_blank"
68
+ {...props}
69
+ >
70
+ {children ?? (
71
+ <>
72
+ <BookIcon className="h-4 w-4" />
73
+ <span className="block font-medium">{title}</span>
74
+ </>
75
+ )}
76
+ </a>
77
+ );
@@ -0,0 +1,53 @@
1
+ "use client";
2
+
3
+ import { Button } from "@dreamboard/ui/components/button";
4
+ import { ScrollArea, ScrollBar } from "@dreamboard/ui/components/scroll-area";
5
+ import { cn } from "@dreamboard/ui/lib/utils";
6
+ import type { ComponentProps } from "react";
7
+
8
+ export type SuggestionsProps = ComponentProps<typeof ScrollArea>;
9
+
10
+ export const Suggestions = ({
11
+ className,
12
+ children,
13
+ ...props
14
+ }: SuggestionsProps) => (
15
+ <ScrollArea className="w-full overflow-x-auto whitespace-nowrap" {...props}>
16
+ <div className={cn("flex w-max flex-nowrap items-center gap-2", className)}>
17
+ {children}
18
+ </div>
19
+ <ScrollBar className="hidden" orientation="horizontal" />
20
+ </ScrollArea>
21
+ );
22
+
23
+ export type SuggestionProps = Omit<ComponentProps<typeof Button>, "onClick"> & {
24
+ suggestion: string;
25
+ onClick?: (suggestion: string) => void;
26
+ };
27
+
28
+ export const Suggestion = ({
29
+ suggestion,
30
+ onClick,
31
+ className,
32
+ variant = "outline",
33
+ size = "sm",
34
+ children,
35
+ ...props
36
+ }: SuggestionProps) => {
37
+ const handleClick = () => {
38
+ onClick?.(suggestion);
39
+ };
40
+
41
+ return (
42
+ <Button
43
+ className={cn("cursor-pointer rounded-full px-4", className)}
44
+ onClick={handleClick}
45
+ size={size}
46
+ type="button"
47
+ variant={variant}
48
+ {...props}
49
+ >
50
+ {children || suggestion}
51
+ </Button>
52
+ );
53
+ };