@heyramzi/ui 6.1.0 → 7.0.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.
- package/COMPONENTS.md +6 -25
- package/README.md +6 -4
- package/package.json +7 -15
- package/scripts/sync-shadcn.mjs +12 -3
- package/src/ai/index.ts +0 -18
- package/src/animations/README.md +3 -3
- package/src/lib/sliding-pill.ts +68 -0
- package/src/lib/theme-transition.ts +4 -2
- package/src/shadcn/code-block/code-block-actions.svelte +23 -0
- package/src/shadcn/code-block/code-block-content.svelte +55 -0
- package/src/shadcn/code-block/code-block-copy-button.svelte +59 -0
- package/src/shadcn/code-block/code-block-footer.svelte +20 -0
- package/src/shadcn/code-block/code-block-header.svelte +23 -0
- package/src/shadcn/code-block/code-block-line.svelte +71 -0
- package/src/shadcn/code-block/code-block-title.svelte +23 -0
- package/src/shadcn/code-block/code-block.svelte +47 -0
- package/src/shadcn/code-block/index.ts +42 -0
- package/src/shadcn/hooks/highlighter.ts +132 -0
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +98 -0
- package/src/shadcn/kbd/index.ts +10 -0
- package/src/shadcn/kbd/kbd-group.svelte +20 -0
- package/src/shadcn/kbd/kbd.svelte +23 -0
- package/src/shadcn/message-scroller/index.ts +28 -0
- package/src/shadcn/message-scroller/message-scroller-button.svelte +52 -0
- package/src/shadcn/message-scroller/message-scroller-content.svelte +17 -0
- package/src/shadcn/message-scroller/message-scroller-item.svelte +22 -0
- package/src/shadcn/message-scroller/message-scroller-provider.svelte +7 -0
- package/src/shadcn/message-scroller/message-scroller-viewport.svelte +20 -0
- package/src/shadcn/message-scroller/message-scroller.svelte +20 -0
- package/src/shadcn/tabs/tabs-list.svelte +13 -2
- package/src/shadcn/tabs/tabs-trigger.svelte +1 -1
- package/src/shadcn/trace/index.ts +29 -0
- package/src/shadcn/trace/trace-collapsible-content.svelte +29 -0
- package/src/shadcn/trace/trace-collapsible-trigger.svelte +29 -0
- package/src/shadcn/trace/trace-collapsible.svelte +20 -0
- package/src/shadcn/trace/trace-description.svelte +20 -0
- package/src/shadcn/trace/trace-icon.svelte +24 -0
- package/src/shadcn/trace/trace-line.svelte +31 -0
- package/src/shadcn/trace/trace-title.svelte +20 -0
- package/src/shadcn/trace/trace.svelte +23 -0
- package/src/showcase/AiSection.svelte +0 -7
- package/src/showcase/demos/shadcn/code-block.svelte +80 -0
- package/src/showcase/demos/shadcn/index.ts +24 -0
- package/src/showcase/demos/shadcn/message-scroller.svelte +44 -0
- package/src/showcase/demos/shadcn/trace.svelte +51 -0
- package/src/showcase/kit.ts +1 -2
- package/src/ai/conversation/Conversation.svelte +0 -28
- package/src/ai/conversation/ConversationContent.svelte +0 -35
- package/src/ai/conversation/ConversationEmptyState.svelte +0 -46
- package/src/ai/conversation/ConversationScrollButton.svelte +0 -51
- package/src/ai/conversation/index.ts +0 -33
- package/src/ai/conversation/stick-to-bottom-context.svelte.ts +0 -131
- package/src/charts/animated-value.css +0 -7
- package/src/charts/animated-value.svelte +0 -110
- package/src/charts/area-chart.css +0 -29
- package/src/charts/area-chart.svelte +0 -195
- package/src/charts/bar-chart.css +0 -119
- package/src/charts/bar-chart.svelte +0 -269
- package/src/charts/charts.css +0 -201
- package/src/charts/crosshair.svelte +0 -35
- package/src/charts/donut-chart.css +0 -56
- package/src/charts/donut-chart.svelte +0 -158
- package/src/charts/edge-fade.svelte +0 -43
- package/src/charts/edge-fade.ts +0 -16
- package/src/charts/figure.css +0 -100
- package/src/charts/figure.svelte +0 -122
- package/src/charts/gauge-chart.css +0 -94
- package/src/charts/gauge-chart.svelte +0 -303
- package/src/charts/hover-band.test.ts +0 -30
- package/src/charts/hover-band.ts +0 -21
- package/src/charts/hover-focus.svelte +0 -85
- package/src/charts/index.ts +0 -30
- package/src/charts/legend.css +0 -131
- package/src/charts/legend.svelte +0 -112
- package/src/charts/line-chart.css +0 -26
- package/src/charts/line-chart.svelte +0 -256
- package/src/charts/motion.ts +0 -19
- package/src/charts/number-chart.css +0 -168
- package/src/charts/number-chart.svelte +0 -177
- package/src/charts/primitives/chart-container.svelte +0 -57
- package/src/charts/primitives/chart-style.svelte +0 -36
- package/src/charts/primitives/chart-tooltip.svelte +0 -161
- package/src/charts/primitives/chart-utils.ts +0 -54
- package/src/charts/primitives/index.ts +0 -11
- package/src/charts/reveal.svelte +0 -61
- package/src/charts/ring-chart.css +0 -96
- package/src/charts/ring-chart.svelte +0 -158
- package/src/charts/sparkline.css +0 -45
- package/src/charts/sparkline.svelte +0 -140
- package/src/charts/stat-card.css +0 -103
- package/src/charts/stat-card.svelte +0 -267
- package/src/charts/time-series-chart.css +0 -28
- package/src/charts/time-series-chart.svelte +0 -179
- package/src/charts/trend-pill.css +0 -38
- package/src/charts/trend-pill.svelte +0 -48
- package/src/lib/hooks/is-mobile.svelte.ts +0 -11
- package/src/showcase/ChartsSection.svelte +0 -458
- package/src/showcase/demos/ai/conversation.svelte +0 -59
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "@heyramzi/utils";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<span
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="trace-description"
|
|
16
|
+
class={cn("shrink-0 text-muted-foreground/70 tabular-nums", className)}
|
|
17
|
+
{...restProps}
|
|
18
|
+
>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</span>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "@heyramzi/utils";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<span
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="trace-icon"
|
|
16
|
+
aria-hidden="true"
|
|
17
|
+
class={cn(
|
|
18
|
+
"size-4 [&_svg:not([class*='size-'])]:size-4 [[data-slot=trace-title]~&]:-ml-1 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...restProps}
|
|
22
|
+
>
|
|
23
|
+
{@render children?.()}
|
|
24
|
+
</span>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type TraceLineStatus = "running" | "error" | "pending";
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { cn, type WithElementRef } from "@heyramzi/utils";
|
|
7
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
ref = $bindable(null),
|
|
11
|
+
class: className,
|
|
12
|
+
status,
|
|
13
|
+
children,
|
|
14
|
+
...restProps
|
|
15
|
+
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> & {
|
|
16
|
+
status?: TraceLineStatus;
|
|
17
|
+
} = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<span
|
|
21
|
+
bind:this={ref}
|
|
22
|
+
data-slot="trace-line"
|
|
23
|
+
data-status={status}
|
|
24
|
+
class={cn(
|
|
25
|
+
"gap-2 text-sm flex w-fit max-w-full min-w-0 items-center text-muted-foreground transition-colors in-[a,button]:cursor-pointer in-[a:hover,button:hover]:text-foreground data-[status=error]:text-destructive data-[status=error]:in-[a:hover,button:hover]:text-destructive data-[status=pending]:opacity-60 data-[status=running]:*:data-[slot=trace-title]:shimmer",
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
{...restProps}
|
|
29
|
+
>
|
|
30
|
+
{@render children?.()}
|
|
31
|
+
</span>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "@heyramzi/utils";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<span
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="trace-title"
|
|
16
|
+
class={cn("min-w-0 truncate motion-reduce:shimmer-none", className)}
|
|
17
|
+
{...restProps}
|
|
18
|
+
>
|
|
19
|
+
{@render children?.()}
|
|
20
|
+
</span>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, type WithElementRef } from "@heyramzi/utils";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
class: className,
|
|
8
|
+
children,
|
|
9
|
+
...restProps
|
|
10
|
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
bind:this={ref}
|
|
15
|
+
data-slot="trace"
|
|
16
|
+
class={cn(
|
|
17
|
+
"gap-2 *:has-[>[data-slot=trace-line]]:rounded-md *:has-[>[data-slot=trace-line]]:focus-visible:ring-3 *:has-[>[data-slot=trace-line]]:focus-visible:ring-ring/50 flex w-full min-w-0 flex-col *:has-[>[data-slot=trace-line]]:flex *:has-[>[data-slot=trace-line]]:w-fit *:has-[>[data-slot=trace-line]]:max-w-full *:has-[>[data-slot=trace-line]]:min-w-0 *:has-[>[data-slot=trace-line]]:text-left *:has-[>[data-slot=trace-line]]:outline-none",
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
{...restProps}
|
|
21
|
+
>
|
|
22
|
+
{@render children?.()}
|
|
23
|
+
</div>
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
<!-- ========================== -->
|
|
4
4
|
<script lang="ts">
|
|
5
5
|
import ShowcaseStage from "./ShowcaseStage.svelte";
|
|
6
|
-
import Convo from "./demos/ai/conversation.svelte";
|
|
7
6
|
import Prompt from "./demos/ai/prompt-input.svelte";
|
|
8
7
|
import LoadingStateDemo from "./demos/ai/loading-state.svelte";
|
|
9
8
|
import ThinkingDotsDemo from "./demos/ai/thinking-dots.svelte";
|
|
@@ -22,12 +21,6 @@
|
|
|
22
21
|
// =========================
|
|
23
22
|
// The order is the order a turn happens in: the surface it is said on, the waiting, the thinking, the decision, and last the voice.
|
|
24
23
|
const demos: Demo[] = [
|
|
25
|
-
{
|
|
26
|
-
title: "Conversation",
|
|
27
|
-
note: "Chat bubbles, responses and per-message actions.",
|
|
28
|
-
Comp: Convo,
|
|
29
|
-
path: "import { Conversation, ConversationContent, Response } from '@heyramzi/ui/ai';\nimport * as Message from '@heyramzi/ui/shadcn/message';\nimport * as Bubble from '@heyramzi/ui/shadcn/bubble';",
|
|
30
|
-
},
|
|
31
24
|
{
|
|
32
25
|
title: "PromptInput",
|
|
33
26
|
note: "Suggestions, textarea, status-aware submit.",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import DownloadIcon from "@lucide/svelte/icons/download";
|
|
3
|
+
import FileCodeIcon from "@lucide/svelte/icons/file-code";
|
|
4
|
+
import WrapTextIcon from "@lucide/svelte/icons/text-wrap";
|
|
5
|
+
import * as CodeBlock from "../../../shadcn/code-block/index.js";
|
|
6
|
+
import { useHighlightedCode } from "../../../shadcn/hooks/use-highlighted-code.svelte.js";
|
|
7
|
+
import { Button } from "../../../shadcn/button/index.js";
|
|
8
|
+
|
|
9
|
+
const code = `import { streamText } from "ai"
|
|
10
|
+
|
|
11
|
+
export async function POST(request: Request) {
|
|
12
|
+
const { messages } = await request.json()
|
|
13
|
+
|
|
14
|
+
const result = streamText({
|
|
15
|
+
model: "anthropic/claude-sonnet-4.5",
|
|
16
|
+
system: "You are a helpful assistant. Answer in one short paragraph.",
|
|
17
|
+
messages,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return result.toUIMessageStreamResponse()
|
|
21
|
+
}`;
|
|
22
|
+
|
|
23
|
+
function download(value: string, filename: string) {
|
|
24
|
+
const url = URL.createObjectURL(new Blob([value], { type: "text/plain" }));
|
|
25
|
+
const link = document.createElement("a");
|
|
26
|
+
link.href = url;
|
|
27
|
+
link.download = filename;
|
|
28
|
+
link.click();
|
|
29
|
+
URL.revokeObjectURL(url);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let wrap = $state(false);
|
|
33
|
+
|
|
34
|
+
const lines = useHighlightedCode(
|
|
35
|
+
() => code,
|
|
36
|
+
() => "ts"
|
|
37
|
+
);
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div class="w-full max-w-lg">
|
|
41
|
+
<CodeBlock.Root>
|
|
42
|
+
<CodeBlock.Header>
|
|
43
|
+
<CodeBlock.Title>
|
|
44
|
+
<FileCodeIcon />
|
|
45
|
+
app/api/chat/route.ts
|
|
46
|
+
</CodeBlock.Title>
|
|
47
|
+
<CodeBlock.Actions>
|
|
48
|
+
<Button
|
|
49
|
+
variant="ghost"
|
|
50
|
+
size="sm"
|
|
51
|
+
icon
|
|
52
|
+
aria-label="Wrap lines"
|
|
53
|
+
aria-pressed={wrap}
|
|
54
|
+
class="aria-pressed:text-foreground"
|
|
55
|
+
onclick={() => (wrap = !wrap)}
|
|
56
|
+
>
|
|
57
|
+
<WrapTextIcon />
|
|
58
|
+
</Button>
|
|
59
|
+
<Button
|
|
60
|
+
variant="ghost"
|
|
61
|
+
size="sm"
|
|
62
|
+
icon
|
|
63
|
+
aria-label="Download"
|
|
64
|
+
onclick={() => download(code, "route.ts")}
|
|
65
|
+
>
|
|
66
|
+
<DownloadIcon />
|
|
67
|
+
</Button>
|
|
68
|
+
<CodeBlock.CopyButton value={code} />
|
|
69
|
+
</CodeBlock.Actions>
|
|
70
|
+
</CodeBlock.Header>
|
|
71
|
+
<CodeBlock.Content {wrap} lineNumbers>
|
|
72
|
+
{#each lines.current as line, index (index)}
|
|
73
|
+
<CodeBlock.Line
|
|
74
|
+
variant={index >= 5 && index <= 9 ? "highlighted" : "default"}
|
|
75
|
+
code={line}
|
|
76
|
+
/>
|
|
77
|
+
{/each}
|
|
78
|
+
</CodeBlock.Content>
|
|
79
|
+
</CodeBlock.Root>
|
|
80
|
+
</div>
|
|
@@ -13,6 +13,7 @@ import ButtonDemo from "./button.svelte";
|
|
|
13
13
|
import CalendarDemo from "./calendar.svelte";
|
|
14
14
|
import CardDemo from "./card.svelte";
|
|
15
15
|
import CheckboxDemo from "./checkbox.svelte";
|
|
16
|
+
import CodeBlockDemo from "./code-block.svelte";
|
|
16
17
|
import CollapsibleDemo from "./collapsible.svelte";
|
|
17
18
|
import CommandDemo from "./command.svelte";
|
|
18
19
|
import ContextMenuDemo from "./context-menu.svelte";
|
|
@@ -26,6 +27,7 @@ import InputOtpDemo from "./input-otp.svelte";
|
|
|
26
27
|
import LabelDemo from "./label.svelte";
|
|
27
28
|
import MarkerDemo from "./marker.svelte";
|
|
28
29
|
import MessageDemo from "./message.svelte";
|
|
30
|
+
import MessageScrollerDemo from "./message-scroller.svelte";
|
|
29
31
|
import PopoverDemo from "./popover.svelte";
|
|
30
32
|
import ProgressDemo from "./progress.svelte";
|
|
31
33
|
import RadioGroupDemo from "./radio-group.svelte";
|
|
@@ -44,6 +46,7 @@ import TextareaDemo from "./textarea.svelte";
|
|
|
44
46
|
import ToggleDemo from "./toggle.svelte";
|
|
45
47
|
import ToggleGroupDemo from "./toggle-group.svelte";
|
|
46
48
|
import TooltipDemo from "./tooltip.svelte";
|
|
49
|
+
import TraceDemo from "./trace.svelte";
|
|
47
50
|
|
|
48
51
|
export type ShadcnDemo = {
|
|
49
52
|
name: string;
|
|
@@ -138,6 +141,13 @@ export const SHADCN_DEMOS: ShadcnDemo[] = [
|
|
|
138
141
|
path: 'import { Checkbox } from "@heyramzi/ui/shadcn/checkbox";\nimport { Label } from "@heyramzi/ui/shadcn/label";',
|
|
139
142
|
Comp: CheckboxDemo,
|
|
140
143
|
},
|
|
144
|
+
{
|
|
145
|
+
name: "code-block",
|
|
146
|
+
title: "Code Block",
|
|
147
|
+
note: "Displays code, terminal output and diffs with an optional header, line numbers and a copy button.",
|
|
148
|
+
path: 'import * as CodeBlock from "@heyramzi/ui/shadcn/code-block";\nimport { useHighlightedCode } from "@heyramzi/ui/shadcn/hooks/use-highlighted-code.svelte.js";\nimport { Button } from "@heyramzi/ui/shadcn/button";',
|
|
149
|
+
Comp: CodeBlockDemo,
|
|
150
|
+
},
|
|
141
151
|
{
|
|
142
152
|
name: "collapsible",
|
|
143
153
|
title: "Collapsible",
|
|
@@ -229,6 +239,13 @@ export const SHADCN_DEMOS: ShadcnDemo[] = [
|
|
|
229
239
|
path: 'import * as Avatar from "@heyramzi/ui/shadcn/avatar";\nimport * as Bubble from "@heyramzi/ui/shadcn/bubble";\nimport * as Marker from "@heyramzi/ui/shadcn/marker";\nimport * as Message from "@heyramzi/ui/shadcn/message";',
|
|
230
240
|
Comp: MessageDemo,
|
|
231
241
|
},
|
|
242
|
+
{
|
|
243
|
+
name: "message-scroller",
|
|
244
|
+
title: "Message Scroller",
|
|
245
|
+
note: "A chat scroll container that anchors turns, opens saved transcripts, follows streamed responses, loads history without jumping, and jumps to any message.",
|
|
246
|
+
path: 'import * as Card from "@heyramzi/ui/shadcn/card";\nimport * as DropdownMenu from "@heyramzi/ui/shadcn/dropdown-menu";\nimport * as Empty from "@heyramzi/ui/shadcn/empty";\nimport * as InputGroup from "@heyramzi/ui/shadcn/input-group";\nimport * as MessageScroller from "@heyramzi/ui/shadcn/message-scroller";\nimport * as Tooltip from "@heyramzi/ui/shadcn/tooltip";\nimport { Button } from "@heyramzi/ui/shadcn/button";',
|
|
247
|
+
Comp: MessageScrollerDemo,
|
|
248
|
+
},
|
|
232
249
|
{
|
|
233
250
|
name: "popover",
|
|
234
251
|
title: "Popover",
|
|
@@ -355,4 +372,11 @@ export const SHADCN_DEMOS: ShadcnDemo[] = [
|
|
|
355
372
|
path: 'import * as Tooltip from "@heyramzi/ui/shadcn/tooltip";\nimport { buttonVariants } from "@heyramzi/ui/shadcn/button";',
|
|
356
373
|
Comp: TooltipDemo,
|
|
357
374
|
},
|
|
375
|
+
{
|
|
376
|
+
name: "trace",
|
|
377
|
+
title: "Trace",
|
|
378
|
+
note: "The building block for reasoning, tool calls, sources and more.",
|
|
379
|
+
path: 'import * as Bubble from "@heyramzi/ui/shadcn/bubble";\nimport * as CodeBlock from "@heyramzi/ui/shadcn/code-block";\nimport * as Message from "@heyramzi/ui/shadcn/message";\nimport * as Trace from "@heyramzi/ui/shadcn/trace";\nimport { Button } from "@heyramzi/ui/shadcn/button";',
|
|
380
|
+
Comp: TraceDemo,
|
|
381
|
+
},
|
|
358
382
|
];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!-- Ours, not upstream's: theirs streams through @ai-sdk/svelte and docs-only helpers this package doesn't ship. -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import * as Bubble from "../../../shadcn/bubble/index.js";
|
|
4
|
+
import * as Message from "../../../shadcn/message/index.js";
|
|
5
|
+
import * as MessageScroller from "../../../shadcn/message-scroller/index.js";
|
|
6
|
+
import { Response } from "../../../ai/index.js";
|
|
7
|
+
|
|
8
|
+
const turns = [
|
|
9
|
+
{ id: "q1", role: "user", text: "How should I clean up our beam effects?" },
|
|
10
|
+
{
|
|
11
|
+
id: "a1",
|
|
12
|
+
role: "assistant",
|
|
13
|
+
text: "Here is the plan:\n\n1. **Extract** the beam into the shared package\n2. **Showcase** it on the Effects page\n3. **Migrate** both apps onto the shared copy",
|
|
14
|
+
},
|
|
15
|
+
{ id: "q2", role: "user", text: "And the old copies?" },
|
|
16
|
+
{ id: "a2", role: "assistant", text: "Delete them in the same change, so nothing imports the stale one." },
|
|
17
|
+
] as const;
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<div class="h-68 w-full max-w-md">
|
|
21
|
+
<MessageScroller.Provider>
|
|
22
|
+
<MessageScroller.Root>
|
|
23
|
+
<MessageScroller.Viewport>
|
|
24
|
+
<MessageScroller.Content class="gap-4 p-1">
|
|
25
|
+
{#each turns as turn (turn.id)}
|
|
26
|
+
{@const user = turn.role === "user"}
|
|
27
|
+
<MessageScroller.Item messageId={turn.id} scrollAnchor={user}>
|
|
28
|
+
<Message.Root align={user ? "end" : "start"}>
|
|
29
|
+
<Message.Content>
|
|
30
|
+
<Bubble.Root variant={user ? "default" : "muted"} align={user ? "end" : "start"}>
|
|
31
|
+
<Bubble.Content>
|
|
32
|
+
{#if user}{turn.text}{:else}<Response content={turn.text} />{/if}
|
|
33
|
+
</Bubble.Content>
|
|
34
|
+
</Bubble.Root>
|
|
35
|
+
</Message.Content>
|
|
36
|
+
</Message.Root>
|
|
37
|
+
</MessageScroller.Item>
|
|
38
|
+
{/each}
|
|
39
|
+
</MessageScroller.Content>
|
|
40
|
+
</MessageScroller.Viewport>
|
|
41
|
+
<MessageScroller.Button />
|
|
42
|
+
</MessageScroller.Root>
|
|
43
|
+
</MessageScroller.Provider>
|
|
44
|
+
</div>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!-- Ours, not upstream's: theirs streams through @ai-sdk/svelte and docs-only helpers this package doesn't ship. -->
|
|
2
|
+
<script lang="ts">
|
|
3
|
+
import CircleAlertIcon from "@lucide/svelte/icons/circle-alert";
|
|
4
|
+
import CircleCheckIcon from "@lucide/svelte/icons/circle-check";
|
|
5
|
+
import LoaderCircleIcon from "@lucide/svelte/icons/loader-circle";
|
|
6
|
+
import * as CodeBlock from "../../../shadcn/code-block/index.js";
|
|
7
|
+
import * as Trace from "../../../shadcn/trace/index.js";
|
|
8
|
+
|
|
9
|
+
const steps = [
|
|
10
|
+
{ command: "pnpm --version", output: "12.10.1" },
|
|
11
|
+
{
|
|
12
|
+
command: "git diff --stat HEAD~1 -- package.json pnpm-lock.yaml",
|
|
13
|
+
output: " package.json | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
command: "pnpm install --frozen-lockfile",
|
|
17
|
+
error: "ERR_PNPM_OUTDATED_LOCKFILE pnpm-lock.yaml is not up to date with package.json",
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div class="w-full max-w-md">
|
|
23
|
+
<Trace.Root>
|
|
24
|
+
<Trace.Line>
|
|
25
|
+
<Trace.Icon><CircleCheckIcon /></Trace.Icon>
|
|
26
|
+
<Trace.Title>Thought for 5s</Trace.Title>
|
|
27
|
+
</Trace.Line>
|
|
28
|
+
{#each steps as step (step.command)}
|
|
29
|
+
<Trace.Collapsible>
|
|
30
|
+
<Trace.CollapsibleTrigger>
|
|
31
|
+
<Trace.Line status={step.error ? "error" : undefined}>
|
|
32
|
+
<Trace.Icon>
|
|
33
|
+
{#if step.error}<CircleAlertIcon />{:else}<CircleCheckIcon />{/if}
|
|
34
|
+
</Trace.Icon>
|
|
35
|
+
<Trace.Title>{step.error ? "Failed to run" : "Ran"} {step.command}</Trace.Title>
|
|
36
|
+
</Trace.Line>
|
|
37
|
+
</Trace.CollapsibleTrigger>
|
|
38
|
+
<Trace.CollapsibleContent>
|
|
39
|
+
<CodeBlock.Root size="sm" variant={step.error ? "destructive" : "default"}>
|
|
40
|
+
<CodeBlock.Content wrap class="max-h-64" code={step.error ?? step.output} />
|
|
41
|
+
</CodeBlock.Root>
|
|
42
|
+
</Trace.CollapsibleContent>
|
|
43
|
+
</Trace.Collapsible>
|
|
44
|
+
{/each}
|
|
45
|
+
<Trace.Line status="running">
|
|
46
|
+
<Trace.Icon><LoaderCircleIcon class="animate-spin" /></Trace.Icon>
|
|
47
|
+
<Trace.Title>Writing the fix</Trace.Title>
|
|
48
|
+
<Trace.Description>2 sources</Trace.Description>
|
|
49
|
+
</Trace.Line>
|
|
50
|
+
</Trace.Root>
|
|
51
|
+
</div>
|
package/src/showcase/kit.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The showcase of @heyramzi/ui itself: its shadcn primitives,
|
|
2
|
-
// its motion vocabulary, its visual effects
|
|
2
|
+
// its motion vocabulary, its visual effects and its AI surface. The chart set's own section ships with `@heyramzi/charts/showcase`.
|
|
3
3
|
|
|
4
4
|
// WHY they ship with the package and not with the app showing them: they demo
|
|
5
5
|
|
|
@@ -13,5 +13,4 @@
|
|
|
13
13
|
export { default as AnimationsSection } from "./AnimationsSection.svelte";
|
|
14
14
|
export { default as ShadcnSection } from "./ShadcnSection.svelte";
|
|
15
15
|
export { default as EffectsSection } from "./EffectsSection.svelte";
|
|
16
|
-
export { default as ChartsSection } from "./ChartsSection.svelte";
|
|
17
16
|
export { default as AiSection } from "./AiSection.svelte";
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { Snippet } from "svelte";
|
|
3
|
-
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
-
|
|
5
|
-
export interface ConversationProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
children?: Snippet;
|
|
7
|
-
class?: string;
|
|
8
|
-
}
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script lang="ts">
|
|
12
|
-
import { cn } from "@heyramzi/utils";
|
|
13
|
-
import { setStickToBottomContext } from "./stick-to-bottom-context.svelte.js";
|
|
14
|
-
|
|
15
|
-
let { class: className, children, ...rest }: ConversationProps = $props();
|
|
16
|
-
|
|
17
|
-
setStickToBottomContext();
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<div
|
|
21
|
-
class={cn("relative flex h-full flex-col overflow-hidden", className)}
|
|
22
|
-
role="log"
|
|
23
|
-
aria-live="polite"
|
|
24
|
-
aria-atomic="false"
|
|
25
|
-
{...rest}
|
|
26
|
-
>
|
|
27
|
-
{@render children?.()}
|
|
28
|
-
</div>
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { Snippet } from "svelte";
|
|
3
|
-
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
-
|
|
5
|
-
export interface ConversationContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
children?: Snippet;
|
|
7
|
-
class?: string;
|
|
8
|
-
}
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script lang="ts">
|
|
12
|
-
import { cn } from "@heyramzi/utils";
|
|
13
|
-
import { onDestroy } from "svelte";
|
|
14
|
-
import { getStickToBottomContext } from "./stick-to-bottom-context.svelte.js";
|
|
15
|
-
|
|
16
|
-
let { class: className, children, ...rest }: ConversationContentProps = $props();
|
|
17
|
-
|
|
18
|
-
const context = getStickToBottomContext();
|
|
19
|
-
let element = $state<HTMLDivElement | null>(null);
|
|
20
|
-
|
|
21
|
-
$effect(() => {
|
|
22
|
-
if (element) {
|
|
23
|
-
context.setElement(element);
|
|
24
|
-
context.scrollToBottom("smooth");
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
onDestroy(() => {
|
|
29
|
-
context.destroy();
|
|
30
|
-
});
|
|
31
|
-
</script>
|
|
32
|
-
|
|
33
|
-
<div bind:this={element} class={cn("flex-1 overflow-y-auto", className)} {...rest}>
|
|
34
|
-
{@render children?.()}
|
|
35
|
-
</div>
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { Snippet } from "svelte";
|
|
3
|
-
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
-
|
|
5
|
-
export interface ConversationEmptyStateProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
-
title?: string;
|
|
7
|
-
description?: string;
|
|
8
|
-
icon?: Snippet;
|
|
9
|
-
children?: Snippet;
|
|
10
|
-
class?: string;
|
|
11
|
-
}
|
|
12
|
-
</script>
|
|
13
|
-
|
|
14
|
-
<script lang="ts">
|
|
15
|
-
import { cn } from "@heyramzi/utils";
|
|
16
|
-
|
|
17
|
-
let {
|
|
18
|
-
class: className,
|
|
19
|
-
title,
|
|
20
|
-
description,
|
|
21
|
-
icon,
|
|
22
|
-
children,
|
|
23
|
-
...rest
|
|
24
|
-
}: ConversationEmptyStateProps = $props();
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<div
|
|
28
|
-
class={cn("flex size-full flex-col items-center justify-center gap-3 p-6 text-center", className)}
|
|
29
|
-
{...rest}
|
|
30
|
-
>
|
|
31
|
-
{#if children}
|
|
32
|
-
{@render children()}
|
|
33
|
-
{:else}
|
|
34
|
-
{#if icon}
|
|
35
|
-
<div class="text-[color:var(--muted-foreground,inherit)]">
|
|
36
|
-
{@render icon()}
|
|
37
|
-
</div>
|
|
38
|
-
{/if}
|
|
39
|
-
<div class="space-y-1">
|
|
40
|
-
{#if title}<h3 class="text-sm font-medium">{title}</h3>{/if}
|
|
41
|
-
{#if description}
|
|
42
|
-
<p class="text-[color:var(--muted-foreground,inherit)] text-sm">{description}</p>
|
|
43
|
-
{/if}
|
|
44
|
-
</div>
|
|
45
|
-
{/if}
|
|
46
|
-
</div>
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import type { ButtonProps } from "../../shadcn/button/index.js";
|
|
3
|
-
|
|
4
|
-
export interface ConversationScrollButtonProps extends Omit<ButtonProps, "onclick"> {
|
|
5
|
-
class?: string;
|
|
6
|
-
onclick?: (event: MouseEvent) => void;
|
|
7
|
-
}
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
import { cn } from "@heyramzi/utils";
|
|
12
|
-
import { Button } from "../../shadcn/button/index.js";
|
|
13
|
-
import ArrowDown from "phosphor-svelte/lib/ArrowDown";
|
|
14
|
-
import { fly } from "svelte/transition";
|
|
15
|
-
import { backOut } from "svelte/easing";
|
|
16
|
-
import { getStickToBottomContext } from "./stick-to-bottom-context.svelte.js";
|
|
17
|
-
|
|
18
|
-
let { class: className, onclick, ...rest }: ConversationScrollButtonProps = $props();
|
|
19
|
-
|
|
20
|
-
const context = getStickToBottomContext();
|
|
21
|
-
|
|
22
|
-
function handleClick(event: MouseEvent) {
|
|
23
|
-
context.scrollToBottom();
|
|
24
|
-
onclick?.(event);
|
|
25
|
-
}
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
{#if !context.isAtBottom}
|
|
29
|
-
<div
|
|
30
|
-
in:fly={{ duration: 300, y: 10, easing: backOut }}
|
|
31
|
-
out:fly={{ duration: 200, y: 10, easing: backOut }}
|
|
32
|
-
class="pointer-events-auto absolute bottom-3 left-1/2 -translate-x-1/2"
|
|
33
|
-
>
|
|
34
|
-
<Button
|
|
35
|
-
class={cn(
|
|
36
|
-
"rounded-full shadow-lg backdrop-blur-sm",
|
|
37
|
-
"bg-[color:var(--background,white)]/80 hover:bg-[color:var(--background,white)]/95",
|
|
38
|
-
"border-[color:var(--border,rgba(0,0,0,0.1))]",
|
|
39
|
-
className,
|
|
40
|
-
)}
|
|
41
|
-
onclick={handleClick}
|
|
42
|
-
icon
|
|
43
|
-
type="button"
|
|
44
|
-
variant="outline"
|
|
45
|
-
aria-label="Scroll to latest"
|
|
46
|
-
{...rest}
|
|
47
|
-
>
|
|
48
|
-
<ArrowDown class="size-4" />
|
|
49
|
-
</Button>
|
|
50
|
-
</div>
|
|
51
|
-
{/if}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import Conversation from "./Conversation.svelte";
|
|
2
|
-
import ConversationContent from "./ConversationContent.svelte";
|
|
3
|
-
import ConversationEmptyState from "./ConversationEmptyState.svelte";
|
|
4
|
-
import ConversationScrollButton from "./ConversationScrollButton.svelte";
|
|
5
|
-
import {
|
|
6
|
-
StickToBottomContext,
|
|
7
|
-
getStickToBottomContext,
|
|
8
|
-
setStickToBottomContext,
|
|
9
|
-
} from "./stick-to-bottom-context.svelte.js";
|
|
10
|
-
|
|
11
|
-
import type { ConversationProps } from "./Conversation.svelte";
|
|
12
|
-
import type { ConversationContentProps } from "./ConversationContent.svelte";
|
|
13
|
-
import type { ConversationEmptyStateProps } from "./ConversationEmptyState.svelte";
|
|
14
|
-
import type { ConversationScrollButtonProps } from "./ConversationScrollButton.svelte";
|
|
15
|
-
|
|
16
|
-
export {
|
|
17
|
-
Conversation,
|
|
18
|
-
ConversationContent,
|
|
19
|
-
ConversationEmptyState,
|
|
20
|
-
ConversationScrollButton,
|
|
21
|
-
StickToBottomContext,
|
|
22
|
-
getStickToBottomContext,
|
|
23
|
-
setStickToBottomContext,
|
|
24
|
-
type ConversationProps,
|
|
25
|
-
type ConversationContentProps,
|
|
26
|
-
type ConversationEmptyStateProps,
|
|
27
|
-
type ConversationScrollButtonProps,
|
|
28
|
-
//
|
|
29
|
-
Conversation as Root,
|
|
30
|
-
ConversationContent as Content,
|
|
31
|
-
ConversationEmptyState as EmptyState,
|
|
32
|
-
ConversationScrollButton as ScrollButton,
|
|
33
|
-
};
|