@signal9/era-ui 2.2.0 → 2.4.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 (189) hide show
  1. package/dist/ai/actions/action.svelte +41 -0
  2. package/dist/ai/actions/action.svelte.d.ts +12 -0
  3. package/dist/ai/actions/actions.svelte +15 -0
  4. package/dist/ai/actions/actions.svelte.d.ts +8 -0
  5. package/dist/ai/actions/index.d.ts +2 -0
  6. package/dist/ai/actions/index.js +2 -0
  7. package/dist/ai/artifact/artifact-actions.svelte +7 -0
  8. package/dist/ai/artifact/artifact-actions.svelte.d.ts +8 -0
  9. package/dist/ai/artifact/artifact-close.svelte +9 -0
  10. package/dist/ai/artifact/artifact-close.svelte.d.ts +6 -0
  11. package/dist/ai/artifact/artifact-content.svelte +7 -0
  12. package/dist/ai/artifact/artifact-content.svelte.d.ts +8 -0
  13. package/dist/ai/artifact/artifact-description.svelte +7 -0
  14. package/dist/ai/artifact/artifact-description.svelte.d.ts +8 -0
  15. package/dist/ai/artifact/artifact-header.svelte +16 -0
  16. package/dist/ai/artifact/artifact-header.svelte.d.ts +8 -0
  17. package/dist/ai/artifact/artifact-title.svelte +7 -0
  18. package/dist/ai/artifact/artifact-title.svelte.d.ts +8 -0
  19. package/dist/ai/artifact/artifact.svelte +16 -0
  20. package/dist/ai/artifact/artifact.svelte.d.ts +8 -0
  21. package/dist/ai/artifact/index.d.ts +8 -0
  22. package/dist/ai/artifact/index.js +8 -0
  23. package/dist/ai/chain-of-thought/chain-of-thought-step.svelte +39 -0
  24. package/dist/ai/chain-of-thought/chain-of-thought-step.svelte.d.ts +11 -0
  25. package/dist/ai/chain-of-thought/chain-of-thought.svelte +30 -0
  26. package/dist/ai/chain-of-thought/chain-of-thought.svelte.d.ts +11 -0
  27. package/dist/ai/chain-of-thought/index.d.ts +3 -0
  28. package/dist/ai/chain-of-thought/index.js +3 -0
  29. package/dist/ai/checkpoint.svelte +27 -0
  30. package/dist/ai/checkpoint.svelte.d.ts +10 -0
  31. package/dist/ai/confirmation/confirmation-actions.svelte +9 -0
  32. package/dist/ai/confirmation/confirmation-actions.svelte.d.ts +8 -0
  33. package/dist/ai/confirmation/confirmation.svelte +36 -0
  34. package/dist/ai/confirmation/confirmation.svelte.d.ts +11 -0
  35. package/dist/ai/confirmation/index.d.ts +2 -0
  36. package/dist/ai/confirmation/index.js +2 -0
  37. package/dist/ai/context/context.svelte +49 -0
  38. package/dist/ai/context/context.svelte.d.ts +9 -0
  39. package/dist/ai/context/index.d.ts +1 -0
  40. package/dist/ai/context/index.js +1 -0
  41. package/dist/ai/conversation/context.d.ts +3 -0
  42. package/dist/ai/conversation/context.js +12 -0
  43. package/dist/ai/conversation/conversation-content.svelte +32 -0
  44. package/dist/ai/conversation/conversation-content.svelte.d.ts +8 -0
  45. package/dist/ai/conversation/conversation-empty-state.svelte +32 -0
  46. package/dist/ai/conversation/conversation-empty-state.svelte.d.ts +11 -0
  47. package/dist/ai/conversation/conversation-scroll-button.svelte +27 -0
  48. package/dist/ai/conversation/conversation-scroll-button.svelte.d.ts +6 -0
  49. package/dist/ai/conversation/conversation.svelte +21 -0
  50. package/dist/ai/conversation/conversation.svelte.d.ts +8 -0
  51. package/dist/ai/conversation/index.d.ts +5 -0
  52. package/dist/ai/conversation/index.js +5 -0
  53. package/dist/ai/copy-button.svelte +42 -0
  54. package/dist/ai/copy-button.svelte.d.ts +8 -0
  55. package/dist/ai/image.svelte +19 -0
  56. package/dist/ai/image.svelte.d.ts +8 -0
  57. package/dist/ai/index.d.ts +29 -0
  58. package/dist/ai/index.js +31 -0
  59. package/dist/ai/inline-citation/index.d.ts +1 -0
  60. package/dist/ai/inline-citation/index.js +1 -0
  61. package/dist/ai/inline-citation/inline-citation.svelte +66 -0
  62. package/dist/ai/inline-citation/inline-citation.svelte.d.ts +11 -0
  63. package/dist/ai/loader.svelte +8 -0
  64. package/dist/ai/loader.svelte.d.ts +6 -0
  65. package/dist/ai/message/branch.svelte.d.ts +10 -0
  66. package/dist/ai/message/branch.svelte.js +28 -0
  67. package/dist/ai/message/context.d.ts +6 -0
  68. package/dist/ai/message/context.js +1 -0
  69. package/dist/ai/message/index.d.ts +8 -0
  70. package/dist/ai/message/index.js +7 -0
  71. package/dist/ai/message/message-branch-content.svelte +24 -0
  72. package/dist/ai/message/message-branch-content.svelte.d.ts +10 -0
  73. package/dist/ai/message/message-branch-selector.svelte +25 -0
  74. package/dist/ai/message/message-branch-selector.svelte.d.ts +6 -0
  75. package/dist/ai/message/message-branch.svelte +25 -0
  76. package/dist/ai/message/message-branch.svelte.d.ts +9 -0
  77. package/dist/ai/message/message-content.svelte +24 -0
  78. package/dist/ai/message/message-content.svelte.d.ts +8 -0
  79. package/dist/ai/message/message-toolbar.svelte +23 -0
  80. package/dist/ai/message/message-toolbar.svelte.d.ts +8 -0
  81. package/dist/ai/message/message.svelte +27 -0
  82. package/dist/ai/message/message.svelte.d.ts +10 -0
  83. package/dist/ai/model-selector/index.d.ts +1 -0
  84. package/dist/ai/model-selector/index.js +1 -0
  85. package/dist/ai/model-selector/model-selector.svelte +61 -0
  86. package/dist/ai/model-selector/model-selector.svelte.d.ts +15 -0
  87. package/dist/ai/open-in-chat/index.d.ts +1 -0
  88. package/dist/ai/open-in-chat/index.js +1 -0
  89. package/dist/ai/open-in-chat/open-in-chat.svelte +41 -0
  90. package/dist/ai/open-in-chat/open-in-chat.svelte.d.ts +32 -0
  91. package/dist/ai/plan/index.d.ts +3 -0
  92. package/dist/ai/plan/index.js +3 -0
  93. package/dist/ai/plan/plan-content.svelte +13 -0
  94. package/dist/ai/plan/plan-content.svelte.d.ts +8 -0
  95. package/dist/ai/plan/plan-header.svelte +22 -0
  96. package/dist/ai/plan/plan-header.svelte.d.ts +9 -0
  97. package/dist/ai/plan/plan.svelte +23 -0
  98. package/dist/ai/plan/plan.svelte.d.ts +10 -0
  99. package/dist/ai/prompt-input/attachments.svelte.d.ts +27 -0
  100. package/dist/ai/prompt-input/attachments.svelte.js +60 -0
  101. package/dist/ai/prompt-input/index.d.ts +7 -0
  102. package/dist/ai/prompt-input/index.js +7 -0
  103. package/dist/ai/prompt-input/prompt-input-add-attachments.svelte +12 -0
  104. package/dist/ai/prompt-input/prompt-input-add-attachments.svelte.d.ts +6 -0
  105. package/dist/ai/prompt-input/prompt-input-attachments.svelte +40 -0
  106. package/dist/ai/prompt-input/prompt-input-attachments.svelte.d.ts +18 -0
  107. package/dist/ai/prompt-input/prompt-input-submit.svelte +49 -0
  108. package/dist/ai/prompt-input/prompt-input-submit.svelte.d.ts +10 -0
  109. package/dist/ai/prompt-input/prompt-input-textarea.svelte +57 -0
  110. package/dist/ai/prompt-input/prompt-input-textarea.svelte.d.ts +7 -0
  111. package/dist/ai/prompt-input/prompt-input-toolbar.svelte +15 -0
  112. package/dist/ai/prompt-input/prompt-input-toolbar.svelte.d.ts +8 -0
  113. package/dist/ai/prompt-input/prompt-input.svelte +98 -0
  114. package/dist/ai/prompt-input/prompt-input.svelte.d.ts +17 -0
  115. package/dist/ai/queue/index.d.ts +2 -0
  116. package/dist/ai/queue/index.js +2 -0
  117. package/dist/ai/queue/queue-item.svelte +26 -0
  118. package/dist/ai/queue/queue-item.svelte.d.ts +9 -0
  119. package/dist/ai/queue/queue.svelte +14 -0
  120. package/dist/ai/queue/queue.svelte.d.ts +8 -0
  121. package/dist/ai/reasoning/index.d.ts +3 -0
  122. package/dist/ai/reasoning/index.js +3 -0
  123. package/dist/ai/reasoning/reasoning-trigger.svelte +22 -0
  124. package/dist/ai/reasoning/reasoning-trigger.svelte.d.ts +9 -0
  125. package/dist/ai/reasoning/reasoning.svelte +52 -0
  126. package/dist/ai/reasoning/reasoning.svelte.d.ts +13 -0
  127. package/dist/ai/response/index.d.ts +2 -0
  128. package/dist/ai/response/index.js +2 -0
  129. package/dist/ai/response/repair.d.ts +7 -0
  130. package/dist/ai/response/repair.js +26 -0
  131. package/dist/ai/response/response.svelte +112 -0
  132. package/dist/ai/response/response.svelte.d.ts +10 -0
  133. package/dist/ai/shimmer.svelte +15 -0
  134. package/dist/ai/shimmer.svelte.d.ts +9 -0
  135. package/dist/ai/sources/index.d.ts +4 -0
  136. package/dist/ai/sources/index.js +4 -0
  137. package/dist/ai/sources/source.svelte +16 -0
  138. package/dist/ai/sources/source.svelte.d.ts +7 -0
  139. package/dist/ai/sources/sources-trigger.svelte +12 -0
  140. package/dist/ai/sources/sources-trigger.svelte.d.ts +8 -0
  141. package/dist/ai/sources/sources.svelte +15 -0
  142. package/dist/ai/sources/sources.svelte.d.ts +9 -0
  143. package/dist/ai/suggestion/index.d.ts +2 -0
  144. package/dist/ai/suggestion/index.js +2 -0
  145. package/dist/ai/suggestion/suggestion.svelte +25 -0
  146. package/dist/ai/suggestion/suggestion.svelte.d.ts +10 -0
  147. package/dist/ai/suggestion/suggestions.svelte +18 -0
  148. package/dist/ai/suggestion/suggestions.svelte.d.ts +8 -0
  149. package/dist/ai/task/index.d.ts +5 -0
  150. package/dist/ai/task/index.js +5 -0
  151. package/dist/ai/task/task-content.svelte +14 -0
  152. package/dist/ai/task/task-content.svelte.d.ts +8 -0
  153. package/dist/ai/task/task-item-file.svelte +8 -0
  154. package/dist/ai/task/task-item-file.svelte.d.ts +7 -0
  155. package/dist/ai/task/task-item.svelte +8 -0
  156. package/dist/ai/task/task-item.svelte.d.ts +8 -0
  157. package/dist/ai/task/task-trigger.svelte +12 -0
  158. package/dist/ai/task/task-trigger.svelte.d.ts +8 -0
  159. package/dist/ai/task/task.svelte +17 -0
  160. package/dist/ai/task/task.svelte.d.ts +11 -0
  161. package/dist/ai/tool/index.d.ts +5 -0
  162. package/dist/ai/tool/index.js +5 -0
  163. package/dist/ai/tool/tool-header.svelte +20 -0
  164. package/dist/ai/tool/tool-header.svelte.d.ts +9 -0
  165. package/dist/ai/tool/tool-input.svelte +10 -0
  166. package/dist/ai/tool/tool-input.svelte.d.ts +6 -0
  167. package/dist/ai/tool/tool-output.svelte +20 -0
  168. package/dist/ai/tool/tool-output.svelte.d.ts +7 -0
  169. package/dist/ai/tool/tool.svelte +41 -0
  170. package/dist/ai/tool/tool.svelte.d.ts +12 -0
  171. package/dist/ai/web-preview/index.d.ts +1 -0
  172. package/dist/ai/web-preview/index.js +1 -0
  173. package/dist/ai/web-preview/web-preview.svelte +48 -0
  174. package/dist/ai/web-preview/web-preview.svelte.d.ts +8 -0
  175. package/dist/ai/workflow/canvas.svelte +19 -0
  176. package/dist/ai/workflow/canvas.svelte.d.ts +11 -0
  177. package/dist/ai/workflow/index.d.ts +2 -0
  178. package/dist/ai/workflow/index.js +2 -0
  179. package/dist/ai/workflow/node.svelte +27 -0
  180. package/dist/ai/workflow/node.svelte.d.ts +9 -0
  181. package/dist/era-ui.css +1 -1
  182. package/dist/generated-docs/llm-shell.md +3 -0
  183. package/dist/generated-docs/llms-full.txt +8 -0
  184. package/dist/generated-docs/llms.txt +1 -1
  185. package/dist/generated-docs/manifest.json +8 -0
  186. package/dist/index.d.ts +1 -0
  187. package/dist/index.js +1 -0
  188. package/dist/ui/step/step-content.svelte +3 -3
  189. package/package.json +14 -1
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
+ title?: string;
5
+ description?: string;
6
+ icon?: Snippet;
7
+ children?: Snippet;
8
+ };
9
+ declare const ConversationEmptyState: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type ConversationEmptyState = ReturnType<typeof ConversationEmptyState>;
11
+ export default ConversationEmptyState;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import ArrowDown from '@lucide/svelte/icons/arrow-down';
3
+ import { Button } from '../../ui/button/index.js';
4
+ import { cn, eraFly } from '../../utils/index.js';
5
+ import { getConversationContext } from './context.js';
6
+
7
+ let { class: className }: { class?: string } = $props();
8
+
9
+ const stick = getConversationContext();
10
+ </script>
11
+
12
+ {#if !stick.pinned}
13
+ <div
14
+ class={cn('absolute bottom-(--era-pad-sm) left-1/2 z-10 -translate-x-1/2', className)}
15
+ transition:eraFly={{ y: 8 }}
16
+ >
17
+ <Button
18
+ icon
19
+ size="default"
20
+ aria-label="Scroll to bottom"
21
+ class="rounded-full shadow-(--era-shadow-lg)"
22
+ onclick={() => stick.repin()}
23
+ >
24
+ <ArrowDown class="size-(--era-h-xs)" />
25
+ </Button>
26
+ </div>
27
+ {/if}
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const ConversationScrollButton: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type ConversationScrollButton = ReturnType<typeof ConversationScrollButton>;
6
+ export default ConversationScrollButton;
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils/index.js';
5
+ import { StickToBottom } from '../stick-to-bottom.svelte.js';
6
+ import { setConversationContext } from './context.js';
7
+
8
+ let {
9
+ children,
10
+ class: className,
11
+ ...restProps
12
+ }: HTMLAttributes<HTMLDivElement> & { children?: Snippet } = $props();
13
+
14
+ // One stick-to-bottom engine per conversation, shared with Content (which
15
+ // attaches it) and ScrollButton (which reads `pinned`).
16
+ setConversationContext(new StickToBottom());
17
+ </script>
18
+
19
+ <div class={cn('relative flex h-full min-h-0 flex-col', className)} {...restProps}>
20
+ {@render children?.()}
21
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
+ children?: Snippet;
5
+ };
6
+ declare const Conversation: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Conversation = ReturnType<typeof Conversation>;
8
+ export default Conversation;
@@ -0,0 +1,5 @@
1
+ export { default as Root } from './conversation.svelte';
2
+ export { default as Content } from './conversation-content.svelte';
3
+ export { default as ScrollButton } from './conversation-scroll-button.svelte';
4
+ export { default as EmptyState } from './conversation-empty-state.svelte';
5
+ export { setConversationContext, getConversationContext } from './context.js';
@@ -0,0 +1,5 @@
1
+ export { default as Root } from './conversation.svelte';
2
+ export { default as Content } from './conversation-content.svelte';
3
+ export { default as ScrollButton } from './conversation-scroll-button.svelte';
4
+ export { default as EmptyState } from './conversation-empty-state.svelte';
5
+ export { setConversationContext, getConversationContext } from './context.js';
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ import Copy from '@lucide/svelte/icons/copy';
3
+ import Check from '@lucide/svelte/icons/check';
4
+ import X from '@lucide/svelte/icons/x';
5
+ import { Button } from '../ui/button/index.js';
6
+ import { cn } from '../utils/index.js';
7
+
8
+ let {
9
+ text,
10
+ onCopy,
11
+ class: className
12
+ }: {
13
+ text: string;
14
+ onCopy?: (status: 'success' | 'failure') => void;
15
+ class?: string;
16
+ } = $props();
17
+
18
+ let status = $state<'idle' | 'success' | 'failure'>('idle');
19
+ let timer: ReturnType<typeof setTimeout>;
20
+
21
+ async function copy() {
22
+ try {
23
+ await navigator.clipboard.writeText(text);
24
+ status = 'success';
25
+ } catch {
26
+ status = 'failure';
27
+ }
28
+ onCopy?.(status as 'success' | 'failure');
29
+ clearTimeout(timer);
30
+ timer = setTimeout(() => (status = 'idle'), 1500);
31
+ }
32
+ </script>
33
+
34
+ <Button icon size="icon" aria-label="Copy" class={cn(className)} onclick={copy}>
35
+ {#if status === 'success'}
36
+ <Check class="size-(--era-h-xs) text-success" />
37
+ {:else if status === 'failure'}
38
+ <X class="size-(--era-h-xs) text-destructive" />
39
+ {:else}
40
+ <Copy class="size-(--era-h-xs)" />
41
+ {/if}
42
+ </Button>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ text: string;
3
+ onCopy?: (status: 'success' | 'failure') => void;
4
+ class?: string;
5
+ };
6
+ declare const CopyButton: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type CopyButton = ReturnType<typeof CopyButton>;
8
+ export default CopyButton;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import type { HTMLImgAttributes } from 'svelte/elements';
3
+ import { cn } from '../utils/index.js';
4
+
5
+ let {
6
+ base64,
7
+ mediaType = 'image/png',
8
+ alt = '',
9
+ class: className,
10
+ ...restProps
11
+ }: HTMLImgAttributes & { base64: string; mediaType?: string } = $props();
12
+ </script>
13
+
14
+ <img
15
+ src="data:{mediaType};base64,{base64}"
16
+ {alt}
17
+ class={cn('max-w-full rounded-(--era-rd-md) shadow-(--era-shadow)', className)}
18
+ {...restProps}
19
+ />
@@ -0,0 +1,8 @@
1
+ import type { HTMLImgAttributes } from 'svelte/elements';
2
+ type $$ComponentProps = HTMLImgAttributes & {
3
+ base64: string;
4
+ mediaType?: string;
5
+ };
6
+ declare const Image: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Image = ReturnType<typeof Image>;
8
+ export default Image;
@@ -0,0 +1,29 @@
1
+ export * as Conversation from './conversation/index.js';
2
+ export * as Message from './message/index.js';
3
+ export * as PromptInput from './prompt-input/index.js';
4
+ export * as Tool from './tool/index.js';
5
+ export * as Reasoning from './reasoning/index.js';
6
+ export * as Task from './task/index.js';
7
+ export * as Sources from './sources/index.js';
8
+ export * as Suggestions from './suggestion/index.js';
9
+ export * as Actions from './actions/index.js';
10
+ export * as Artifact from './artifact/index.js';
11
+ export * as Plan from './plan/index.js';
12
+ export * as Queue from './queue/index.js';
13
+ export * as Confirmation from './confirmation/index.js';
14
+ export * as InlineCitation from './inline-citation/index.js';
15
+ export { Response, repairStreamingMarkdown } from './response/index.js';
16
+ export { default as ContextGauge } from './context/context.svelte';
17
+ export { default as ModelSelector } from './model-selector/model-selector.svelte';
18
+ export { default as OpenInChat, providers as openInProviders } from './open-in-chat/open-in-chat.svelte';
19
+ export { default as WebPreview } from './web-preview/web-preview.svelte';
20
+ export * as ChainOfThought from './chain-of-thought/index.js';
21
+ export { default as Checkpoint } from './checkpoint.svelte';
22
+ export { default as Loader } from './loader.svelte';
23
+ export { default as Shimmer } from './shimmer.svelte';
24
+ export { default as AIImage } from './image.svelte';
25
+ export { default as CopyButton } from './copy-button.svelte';
26
+ export { StickToBottom } from './stick-to-bottom.svelte.js';
27
+ export type { PromptAttachment, PromptMessage, ChatStatus } from './prompt-input/index.js';
28
+ export type { MessageRole, MessageVersion } from './message/index.js';
29
+ export type { ToolState } from './tool/index.js';
@@ -0,0 +1,31 @@
1
+ // The AI layer — chat and agent-UI composites over the ui/ primitives, an
2
+ // era-ui take on Vercel's AI Elements (via the Svelte port). Namespaced parts
3
+ // for the families, flat exports for the singles. `workflow/` is deliberately
4
+ // NOT exported here: it depends on @xyflow/svelte and lives on its own
5
+ // subpath (`@sig-nine/era-ui/ai/workflow`) so the dependency stays opt-in.
6
+ export * as Conversation from './conversation/index.js';
7
+ export * as Message from './message/index.js';
8
+ export * as PromptInput from './prompt-input/index.js';
9
+ export * as Tool from './tool/index.js';
10
+ export * as Reasoning from './reasoning/index.js';
11
+ export * as Task from './task/index.js';
12
+ export * as Sources from './sources/index.js';
13
+ export * as Suggestions from './suggestion/index.js';
14
+ export * as Actions from './actions/index.js';
15
+ export * as Artifact from './artifact/index.js';
16
+ export * as Plan from './plan/index.js';
17
+ export * as Queue from './queue/index.js';
18
+ export * as Confirmation from './confirmation/index.js';
19
+ export * as InlineCitation from './inline-citation/index.js';
20
+ export { Response, repairStreamingMarkdown } from './response/index.js';
21
+ export { default as ContextGauge } from './context/context.svelte';
22
+ export { default as ModelSelector } from './model-selector/model-selector.svelte';
23
+ export { default as OpenInChat, providers as openInProviders } from './open-in-chat/open-in-chat.svelte';
24
+ export { default as WebPreview } from './web-preview/web-preview.svelte';
25
+ export * as ChainOfThought from './chain-of-thought/index.js';
26
+ export { default as Checkpoint } from './checkpoint.svelte';
27
+ export { default as Loader } from './loader.svelte';
28
+ export { default as Shimmer } from './shimmer.svelte';
29
+ export { default as AIImage } from './image.svelte';
30
+ export { default as CopyButton } from './copy-button.svelte';
31
+ export { StickToBottom } from './stick-to-bottom.svelte.js';
@@ -0,0 +1 @@
1
+ export { default as Root } from './inline-citation.svelte';
@@ -0,0 +1 @@
1
+ export { default as Root } from './inline-citation.svelte';
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ import ChevronLeft from '@lucide/svelte/icons/chevron-left';
3
+ import ChevronRight from '@lucide/svelte/icons/chevron-right';
4
+ import * as LinkPreview from '../../ui/link-preview/index.js';
5
+ import { Badge } from '../../ui/badge/index.js';
6
+ import { Button } from '../../ui/button/index.js';
7
+ import { cn } from '../../utils/index.js';
8
+
9
+ let {
10
+ sources,
11
+ class: className
12
+ }: {
13
+ sources: { href: string; title?: string; quote?: string }[];
14
+ class?: string;
15
+ } = $props();
16
+
17
+ let index = $state(0);
18
+ const active = $derived(sources[Math.min(index, sources.length - 1)]);
19
+ const host = (href: string) => {
20
+ try {
21
+ return new URL(href).hostname;
22
+ } catch {
23
+ return href;
24
+ }
25
+ };
26
+ </script>
27
+
28
+ <!-- eslint-disable svelte/no-navigation-without-resolve -- external citation URLs -->
29
+
30
+ <!-- A citation badge inline with prose; hovering opens the source card with a
31
+ simple index stepper (no carousel physics — count, prev, next). -->
32
+ <LinkPreview.Root openDelay={100} closeDelay={100}>
33
+ <LinkPreview.Trigger
34
+ class={cn('align-baseline', className)}
35
+ href={active?.href}
36
+ target="_blank"
37
+ rel="noreferrer"
38
+ >
39
+ <Badge class="ml-1">{host(sources[0]?.href ?? '')}{sources.length > 1 ? ` +${sources.length - 1}` : ''}</Badge>
40
+ </LinkPreview.Trigger>
41
+ <LinkPreview.Content class="flex w-72 flex-col gap-(--era-gap)">
42
+ {#if sources.length > 1}
43
+ <div class="flex items-center justify-between">
44
+ <span class="text-body text-muted tabular-nums">{index + 1} of {sources.length}</span>
45
+ <div class="flex gap-(--era-gap)">
46
+ <Button icon size="icon" aria-label="Previous source" onclick={() => (index = (index - 1 + sources.length) % sources.length)}>
47
+ <ChevronLeft class="size-(--era-h-xs)" />
48
+ </Button>
49
+ <Button icon size="icon" aria-label="Next source" onclick={() => (index = (index + 1) % sources.length)}>
50
+ <ChevronRight class="size-(--era-h-xs)" />
51
+ </Button>
52
+ </div>
53
+ </div>
54
+ {/if}
55
+ {#if active}
56
+ <a href={active.href} target="_blank" rel="noreferrer" class="truncate text-body text-primary hover:underline">
57
+ {active.title ?? active.href}
58
+ </a>
59
+ {#if active.quote}
60
+ <blockquote class="border-s-2 border-divider-faded ps-(--era-gap) text-body text-muted">
61
+ {active.quote}
62
+ </blockquote>
63
+ {/if}
64
+ {/if}
65
+ </LinkPreview.Content>
66
+ </LinkPreview.Root>
@@ -0,0 +1,11 @@
1
+ type $$ComponentProps = {
2
+ sources: {
3
+ href: string;
4
+ title?: string;
5
+ quote?: string;
6
+ }[];
7
+ class?: string;
8
+ };
9
+ declare const InlineCitation: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type InlineCitation = ReturnType<typeof InlineCitation>;
11
+ export default InlineCitation;
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ import LoaderCircle from '@lucide/svelte/icons/loader-circle';
3
+ import { cn } from '../utils/index.js';
4
+
5
+ let { class: className }: { class?: string } = $props();
6
+ </script>
7
+
8
+ <LoaderCircle class={cn('size-(--era-h-xs) animate-spin text-muted', className)} aria-label="Loading" />
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const Loader: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type Loader = ReturnType<typeof Loader>;
6
+ export default Loader;
@@ -0,0 +1,10 @@
1
+ /** Wrap-around cursor over a message's alternative versions. */
2
+ export declare class BranchController {
3
+ current: number;
4
+ total: number;
5
+ set(index: number): void;
6
+ previous(): void;
7
+ next(): void;
8
+ }
9
+ export declare function setBranchContext(ctrl: BranchController): BranchController;
10
+ export declare function getBranchContext(): BranchController;
@@ -0,0 +1,28 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ /** Wrap-around cursor over a message's alternative versions. */
3
+ export class BranchController {
4
+ current = $state(0);
5
+ total = $state(0);
6
+ set(index) {
7
+ this.current = Math.min(Math.max(index, 0), Math.max(this.total - 1, 0));
8
+ }
9
+ previous() {
10
+ if (this.total)
11
+ this.current = (this.current - 1 + this.total) % this.total;
12
+ }
13
+ next() {
14
+ if (this.total)
15
+ this.current = (this.current + 1) % this.total;
16
+ }
17
+ }
18
+ const KEY = Symbol('era-ai-branch');
19
+ export function setBranchContext(ctrl) {
20
+ setContext(KEY, ctrl);
21
+ return ctrl;
22
+ }
23
+ export function getBranchContext() {
24
+ const ctx = getContext(KEY);
25
+ if (!ctx)
26
+ throw new Error('Branch parts must be used inside <Message.Branch>.');
27
+ return ctx;
28
+ }
@@ -0,0 +1,6 @@
1
+ export type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
2
+ /** One alternative rendering of the same turn (regenerations). */
3
+ export interface MessageVersion {
4
+ id: string;
5
+ content: string;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export { default as Root } from './message.svelte';
2
+ export { default as Content } from './message-content.svelte';
3
+ export { default as Toolbar } from './message-toolbar.svelte';
4
+ export { default as Branch } from './message-branch.svelte';
5
+ export { default as BranchContent } from './message-branch-content.svelte';
6
+ export { default as BranchSelector } from './message-branch-selector.svelte';
7
+ export { BranchController, setBranchContext, getBranchContext } from './branch.svelte.js';
8
+ export type { MessageRole, MessageVersion } from './context.js';
@@ -0,0 +1,7 @@
1
+ export { default as Root } from './message.svelte';
2
+ export { default as Content } from './message-content.svelte';
3
+ export { default as Toolbar } from './message-toolbar.svelte';
4
+ export { default as Branch } from './message-branch.svelte';
5
+ export { default as BranchContent } from './message-branch-content.svelte';
6
+ export { default as BranchSelector } from './message-branch-selector.svelte';
7
+ export { BranchController, setBranchContext, getBranchContext } from './branch.svelte.js';
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { getBranchContext } from './branch.svelte.js';
4
+ import type { MessageVersion } from './context.js';
5
+
6
+ let {
7
+ versions,
8
+ children
9
+ }: {
10
+ versions: MessageVersion[];
11
+ /** Renders the ACTIVE version. */
12
+ children: Snippet<[MessageVersion]>;
13
+ } = $props();
14
+
15
+ const ctrl = getBranchContext();
16
+ $effect(() => {
17
+ ctrl.total = versions.length;
18
+ });
19
+ const active = $derived(versions[Math.min(ctrl.current, versions.length - 1)]);
20
+ </script>
21
+
22
+ {#if active}
23
+ {@render children(active)}
24
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { MessageVersion } from './context.js';
3
+ type $$ComponentProps = {
4
+ versions: MessageVersion[];
5
+ /** Renders the ACTIVE version. */
6
+ children: Snippet<[MessageVersion]>;
7
+ };
8
+ declare const MessageBranchContent: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type MessageBranchContent = ReturnType<typeof MessageBranchContent>;
10
+ export default MessageBranchContent;
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import ChevronLeft from '@lucide/svelte/icons/chevron-left';
3
+ import ChevronRight from '@lucide/svelte/icons/chevron-right';
4
+ import { Button } from '../../ui/button/index.js';
5
+ import { ButtonGroup } from '../../ui/button-group/index.js';
6
+ import { cn } from '../../utils/index.js';
7
+ import { getBranchContext } from './branch.svelte.js';
8
+
9
+ let { class: className }: { class?: string } = $props();
10
+ const ctrl = getBranchContext();
11
+ </script>
12
+
13
+ {#if ctrl.total > 1}
14
+ <ButtonGroup class={cn(className)}>
15
+ <Button icon size="sm" aria-label="Previous version" onclick={() => ctrl.previous()}>
16
+ <ChevronLeft class="size-(--era-h-xs)" />
17
+ </Button>
18
+ <span class="flex items-center px-(--era-inset-sm) text-body text-muted tabular-nums">
19
+ {ctrl.current + 1} of {ctrl.total}
20
+ </span>
21
+ <Button icon size="sm" aria-label="Next version" onclick={() => ctrl.next()}>
22
+ <ChevronRight class="size-(--era-h-xs)" />
23
+ </Button>
24
+ </ButtonGroup>
25
+ {/if}
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ class?: string;
3
+ };
4
+ declare const MessageBranchSelector: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type MessageBranchSelector = ReturnType<typeof MessageBranchSelector>;
6
+ export default MessageBranchSelector;
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils/index.js';
5
+ import { BranchController, setBranchContext } from './branch.svelte.js';
6
+
7
+ let {
8
+ onBranchChange,
9
+ children,
10
+ class: className,
11
+ ...restProps
12
+ }: HTMLAttributes<HTMLDivElement> & {
13
+ onBranchChange?: (index: number) => void;
14
+ children?: Snippet;
15
+ } = $props();
16
+
17
+ const ctrl = setBranchContext(new BranchController());
18
+ $effect(() => {
19
+ onBranchChange?.(ctrl.current);
20
+ });
21
+ </script>
22
+
23
+ <div class={cn('flex min-w-0 flex-col gap-(--era-gap)', className)} {...restProps}>
24
+ {@render children?.()}
25
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
+ onBranchChange?: (index: number) => void;
5
+ children?: Snippet;
6
+ };
7
+ declare const MessageBranch: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type MessageBranch = ReturnType<typeof MessageBranch>;
9
+ export default MessageBranch;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils/index.js';
5
+
6
+ let {
7
+ children,
8
+ class: className,
9
+ ...restProps
10
+ }: HTMLAttributes<HTMLDivElement> & { children?: Snippet } = $props();
11
+ </script>
12
+
13
+ <!-- Styles itself by the parent Message's role: bubble for the user
14
+ (whitespace preserved, no markdown), plain full-width prose otherwise. -->
15
+ <div
16
+ class={cn(
17
+ 'min-w-0 text-body leading-relaxed text-fg',
18
+ 'group-data-[role=user]:max-w-[80%] group-data-[role=user]:rounded-(--era-rd-lg) group-data-[role=user]:bg-(--era-surface-bg-elevated) group-data-[role=user]:p-(--era-pad-sm) group-data-[role=user]:whitespace-pre-wrap group-data-[role=user]:shadow-(--era-shadow)',
19
+ className
20
+ )}
21
+ {...restProps}
22
+ >
23
+ {@render children?.()}
24
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
+ children?: Snippet;
5
+ };
6
+ declare const MessageContent: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type MessageContent = ReturnType<typeof MessageContent>;
8
+ export default MessageContent;
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils/index.js';
5
+
6
+ let {
7
+ children,
8
+ class: className,
9
+ ...restProps
10
+ }: HTMLAttributes<HTMLDivElement> & { children?: Snippet } = $props();
11
+ </script>
12
+
13
+ <!-- Ghost action row under an assistant message — hidden until the message is
14
+ hovered (the convention), always reachable by keyboard focus. -->
15
+ <div
16
+ class={cn(
17
+ 'flex items-center gap-(--era-gap) opacity-0 transition-opacity duration-(--era-duration) ease-(--era-ease) group-hover:opacity-100 focus-within:opacity-100',
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ {@render children?.()}
23
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
+ children?: Snippet;
5
+ };
6
+ declare const MessageToolbar: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type MessageToolbar = ReturnType<typeof MessageToolbar>;
8
+ export default MessageToolbar;
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn } from '../../utils/index.js';
5
+ import type { MessageRole } from './context.js';
6
+
7
+ let {
8
+ from,
9
+ children,
10
+ class: className,
11
+ ...restProps
12
+ }: HTMLAttributes<HTMLDivElement> & { from: MessageRole; children?: Snippet } = $props();
13
+ </script>
14
+
15
+ <!-- The modern chat convention: user turns are right-aligned bubbles,
16
+ assistant turns are full-width prose. No avatars, no timestamps. -->
17
+ <div
18
+ data-role={from}
19
+ class={cn(
20
+ 'group flex w-full min-w-0 flex-col gap-(--era-gap)',
21
+ from === 'user' && 'items-end',
22
+ className
23
+ )}
24
+ {...restProps}
25
+ >
26
+ {@render children?.()}
27
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { MessageRole } from './context.js';
4
+ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
5
+ from: MessageRole;
6
+ children?: Snippet;
7
+ };
8
+ declare const Message: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type Message = ReturnType<typeof Message>;
10
+ export default Message;
@@ -0,0 +1 @@
1
+ export { default as Root } from './model-selector.svelte';
@@ -0,0 +1 @@
1
+ export { default as Root } from './model-selector.svelte';