@ciridae/ui 0.2.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/README.md +31 -0
- package/dist/components/agentic/agent-card.d.ts +28 -0
- package/dist/components/agentic/agent-card.js +27 -0
- package/dist/components/agentic/agent-composer.d.ts +44 -0
- package/dist/components/agentic/agent-composer.js +104 -0
- package/dist/components/agentic/agent-context.d.ts +28 -0
- package/dist/components/agentic/agent-context.js +102 -0
- package/dist/components/agentic/agent-plan.d.ts +27 -0
- package/dist/components/agentic/agent-plan.js +43 -0
- package/dist/components/agentic/agent-queue.d.ts +46 -0
- package/dist/components/agentic/agent-queue.js +53 -0
- package/dist/components/agentic/agent-task.d.ts +16 -0
- package/dist/components/agentic/agent-task.js +20 -0
- package/dist/components/agentic/approval-request.d.ts +24 -0
- package/dist/components/agentic/approval-request.js +57 -0
- package/dist/components/agentic/artifact.d.ts +24 -0
- package/dist/components/agentic/artifact.js +72 -0
- package/dist/components/agentic/attachments.d.ts +124 -0
- package/dist/components/agentic/attachments.js +595 -0
- package/dist/components/agentic/audio-player.d.ts +16 -0
- package/dist/components/agentic/audio-player.js +21 -0
- package/dist/components/agentic/canvas.d.ts +10 -0
- package/dist/components/agentic/canvas.js +22 -0
- package/dist/components/agentic/clipboard.d.ts +2 -0
- package/dist/components/agentic/clipboard.js +12 -0
- package/dist/components/agentic/code-block.d.ts +43 -0
- package/dist/components/agentic/code-block.js +92 -0
- package/dist/components/agentic/commit.d.ts +57 -0
- package/dist/components/agentic/commit.js +85 -0
- package/dist/components/agentic/connection.d.ts +3 -0
- package/dist/components/agentic/connection.js +8 -0
- package/dist/components/agentic/controls.d.ts +6 -0
- package/dist/components/agentic/controls.js +7 -0
- package/dist/components/agentic/conversation.d.ts +25 -0
- package/dist/components/agentic/conversation.js +56 -0
- package/dist/components/agentic/edge.d.ts +8 -0
- package/dist/components/agentic/edge.js +65 -0
- package/dist/components/agentic/effort-selector.d.ts +43 -0
- package/dist/components/agentic/effort-selector.js +47 -0
- package/dist/components/agentic/environment-variables.d.ts +32 -0
- package/dist/components/agentic/environment-variables.js +66 -0
- package/dist/components/agentic/file-tree.d.ts +24 -0
- package/dist/components/agentic/file-tree.js +56 -0
- package/dist/components/agentic/image.d.ts +9 -0
- package/dist/components/agentic/image.js +11 -0
- package/dist/components/agentic/inline-citation.d.ts +40 -0
- package/dist/components/agentic/inline-citation.js +111 -0
- package/dist/components/agentic/jsx-preview.d.ts +19 -0
- package/dist/components/agentic/jsx-preview.js +34 -0
- package/dist/components/agentic/message-branch.d.ts +20 -0
- package/dist/components/agentic/message-branch.js +83 -0
- package/dist/components/agentic/message-response.css +265 -0
- package/dist/components/agentic/message-response.css.d.ts +2 -0
- package/dist/components/agentic/message.d.ts +27 -0
- package/dist/components/agentic/message.js +57 -0
- package/dist/components/agentic/mic-selector.d.ts +58 -0
- package/dist/components/agentic/mic-selector.js +173 -0
- package/dist/components/agentic/model-selector.d.ts +39 -0
- package/dist/components/agentic/model-selector.js +47 -0
- package/dist/components/agentic/node.d.ts +26 -0
- package/dist/components/agentic/node.js +29 -0
- package/dist/components/agentic/open-in-chat.d.ts +9 -0
- package/dist/components/agentic/open-in-chat.js +8 -0
- package/dist/components/agentic/package-info.d.ts +30 -0
- package/dist/components/agentic/package-info.js +44 -0
- package/dist/components/agentic/panel.d.ts +6 -0
- package/dist/components/agentic/panel.js +7 -0
- package/dist/components/agentic/persona.d.ts +16 -0
- package/dist/components/agentic/persona.js +116 -0
- package/dist/components/agentic/prompt-input-action-menu.d.ts +16 -0
- package/dist/components/agentic/prompt-input-action-menu.js +22 -0
- package/dist/components/agentic/prompt-input-command.d.ts +18 -0
- package/dist/components/agentic/prompt-input-command.js +25 -0
- package/dist/components/agentic/prompt-input-hover-card.d.ts +10 -0
- package/dist/components/agentic/prompt-input-hover-card.js +13 -0
- package/dist/components/agentic/prompt-input-select.d.ts +14 -0
- package/dist/components/agentic/prompt-input-select.js +19 -0
- package/dist/components/agentic/prompt-input-tabs.d.ts +17 -0
- package/dist/components/agentic/prompt-input-tabs.js +45 -0
- package/dist/components/agentic/prompt-input.d.ts +79 -0
- package/dist/components/agentic/prompt-input.js +206 -0
- package/dist/components/agentic/reasoning.d.ts +21 -0
- package/dist/components/agentic/reasoning.js +106 -0
- package/dist/components/agentic/run-checkpoint.d.ts +13 -0
- package/dist/components/agentic/run-checkpoint.js +19 -0
- package/dist/components/agentic/run-trace.d.ts +30 -0
- package/dist/components/agentic/run-trace.js +56 -0
- package/dist/components/agentic/sandbox.d.ts +24 -0
- package/dist/components/agentic/sandbox.js +33 -0
- package/dist/components/agentic/schema-display.d.ts +39 -0
- package/dist/components/agentic/schema-display.js +56 -0
- package/dist/components/agentic/shimmer.d.ts +11 -0
- package/dist/components/agentic/shimmer.js +16 -0
- package/dist/components/agentic/snippet.d.ts +18 -0
- package/dist/components/agentic/snippet.js +35 -0
- package/dist/components/agentic/sources.d.ts +16 -0
- package/dist/components/agentic/sources.js +17 -0
- package/dist/components/agentic/speech-input.d.ts +24 -0
- package/dist/components/agentic/speech-input.js +30 -0
- package/dist/components/agentic/stack-trace.d.ts +27 -0
- package/dist/components/agentic/stack-trace.js +76 -0
- package/dist/components/agentic/suggestion.d.ts +12 -0
- package/dist/components/agentic/suggestion.js +15 -0
- package/dist/components/agentic/terminal.d.ts +24 -0
- package/dist/components/agentic/terminal.js +47 -0
- package/dist/components/agentic/test-results.d.ts +51 -0
- package/dist/components/agentic/test-results.js +83 -0
- package/dist/components/agentic/theme.d.ts +5 -0
- package/dist/components/agentic/theme.js +31 -0
- package/dist/components/agentic/tool.d.ts +25 -0
- package/dist/components/agentic/tool.js +73 -0
- package/dist/components/agentic/toolbar.d.ts +6 -0
- package/dist/components/agentic/toolbar.js +7 -0
- package/dist/components/agentic/transcription.d.ts +20 -0
- package/dist/components/agentic/transcription.js +32 -0
- package/dist/components/agentic/types.d.ts +172 -0
- package/dist/components/agentic/types.js +1 -0
- package/dist/components/agentic/use-controllable-state.d.ts +6 -0
- package/dist/components/agentic/use-controllable-state.js +13 -0
- package/dist/components/agentic/voice-selector.d.ts +69 -0
- package/dist/components/agentic/voice-selector.js +122 -0
- package/dist/components/agentic/web-preview.d.ts +25 -0
- package/dist/components/agentic/web-preview.js +33 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/accordion.js +17 -0
- package/dist/components/ui/alert-dialog.d.ts +22 -0
- package/dist/components/ui/alert-dialog.js +51 -0
- package/dist/components/ui/alert.d.ts +9 -0
- package/dist/components/ui/alert.js +24 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/aspect-ratio.js +7 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +22 -0
- package/dist/components/ui/badge-variants.d.ts +100 -0
- package/dist/components/ui/badge-variants.js +140 -0
- package/dist/components/ui/badge.d.ts +6 -0
- package/dist/components/ui/badge.js +9 -0
- package/dist/components/ui/breadcrumb.d.ts +11 -0
- package/dist/components/ui/breadcrumb.js +27 -0
- package/dist/components/ui/button-group-variants.d.ts +6 -0
- package/dist/components/ui/button-group-variants.js +13 -0
- package/dist/components/ui/button-group.d.ts +8 -0
- package/dist/components/ui/button-group.js +16 -0
- package/dist/components/ui/button-variants.d.ts +133 -0
- package/dist/components/ui/button-variants.js +170 -0
- package/dist/components/ui/button.d.ts +8 -0
- package/dist/components/ui/button.js +67 -0
- package/dist/components/ui/calendar.d.ts +9 -0
- package/dist/components/ui/calendar.js +99 -0
- package/dist/components/ui/card.d.ts +14 -0
- package/dist/components/ui/card.js +28 -0
- package/dist/components/ui/carousel.d.ts +19 -0
- package/dist/components/ui/carousel.js +104 -0
- package/dist/components/ui/chart-context.d.ts +33 -0
- package/dist/components/ui/chart-context.js +36 -0
- package/dist/components/ui/chart-panel.d.ts +11 -0
- package/dist/components/ui/chart-panel.js +6 -0
- package/dist/components/ui/chart-tooltip.d.ts +13 -0
- package/dist/components/ui/chart-tooltip.js +84 -0
- package/dist/components/ui/chart.d.ts +23 -0
- package/dist/components/ui/chart.js +52 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.js +9 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/collapsible.js +12 -0
- package/dist/components/ui/combobox-anchor.d.ts +3 -0
- package/dist/components/ui/combobox-anchor.js +5 -0
- package/dist/components/ui/combobox.d.ts +23 -0
- package/dist/components/ui/combobox.js +54 -0
- package/dist/components/ui/command.d.ts +19 -0
- package/dist/components/ui/command.js +38 -0
- package/dist/components/ui/context-menu.d.ts +30 -0
- package/dist/components/ui/context-menu.js +63 -0
- package/dist/components/ui/data-table.d.ts +17 -0
- package/dist/components/ui/data-table.js +26 -0
- package/dist/components/ui/dialog.d.ts +22 -0
- package/dist/components/ui/dialog.js +48 -0
- package/dist/components/ui/direction-context.d.ts +3 -0
- package/dist/components/ui/direction-context.js +3 -0
- package/dist/components/ui/direction.d.ts +6 -0
- package/dist/components/ui/direction.js +7 -0
- package/dist/components/ui/drawer.d.ts +18 -0
- package/dist/components/ui/drawer.js +47 -0
- package/dist/components/ui/dropdown-menu.d.ts +30 -0
- package/dist/components/ui/dropdown-menu.js +63 -0
- package/dist/components/ui/empty.d.ts +11 -0
- package/dist/components/ui/empty.js +33 -0
- package/dist/components/ui/expandable-data-table.d.ts +24 -0
- package/dist/components/ui/expandable-data-table.js +62 -0
- package/dist/components/ui/field.d.ts +26 -0
- package/dist/components/ui/field.js +74 -0
- package/dist/components/ui/file-upload-field-parts.d.ts +21 -0
- package/dist/components/ui/file-upload-field-parts.js +55 -0
- package/dist/components/ui/file-upload-field.d.ts +15 -0
- package/dist/components/ui/file-upload-field.js +85 -0
- package/dist/components/ui/form-context.d.ts +23 -0
- package/dist/components/ui/form-context.js +35 -0
- package/dist/components/ui/form.d.ts +12 -0
- package/dist/components/ui/form.js +38 -0
- package/dist/components/ui/hover-card.d.ts +10 -0
- package/dist/components/ui/hover-card.js +22 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input-group.js +62 -0
- package/dist/components/ui/input-otp.d.ts +11 -0
- package/dist/components/ui/input-otp.js +21 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +6 -0
- package/dist/components/ui/item.d.ts +23 -0
- package/dist/components/ui/item.js +66 -0
- package/dist/components/ui/kbd.d.ts +3 -0
- package/dist/components/ui/kbd.js +9 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.js +7 -0
- package/dist/components/ui/loading-state.d.ts +27 -0
- package/dist/components/ui/loading-state.js +44 -0
- package/dist/components/ui/menubar.d.ts +30 -0
- package/dist/components/ui/menubar.js +63 -0
- package/dist/components/ui/metrics-strip.d.ts +7 -0
- package/dist/components/ui/metrics-strip.js +18 -0
- package/dist/components/ui/native-select.d.ts +7 -0
- package/dist/components/ui/native-select.js +13 -0
- package/dist/components/ui/navigation-menu-variants.d.ts +2 -0
- package/dist/components/ui/navigation-menu-variants.js +3 -0
- package/dist/components/ui/navigation-menu.d.ts +13 -0
- package/dist/components/ui/navigation-menu.js +30 -0
- package/dist/components/ui/page-header.d.ts +19 -0
- package/dist/components/ui/page-header.js +36 -0
- package/dist/components/ui/pagination.d.ts +13 -0
- package/dist/components/ui/pagination.js +29 -0
- package/dist/components/ui/popover.d.ts +14 -0
- package/dist/components/ui/popover.js +34 -0
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/progress.js +8 -0
- package/dist/components/ui/property-list.d.ts +6 -0
- package/dist/components/ui/property-list.js +15 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/radio-group.js +11 -0
- package/dist/components/ui/registry-docs-api.d.ts +11 -0
- package/dist/components/ui/registry-docs-api.js +9 -0
- package/dist/components/ui/registry-docs-code.d.ts +19 -0
- package/dist/components/ui/registry-docs-code.js +78 -0
- package/dist/components/ui/registry-docs-showcase.d.ts +11 -0
- package/dist/components/ui/registry-docs-showcase.js +27 -0
- package/dist/components/ui/registry-docs.d.ts +27 -0
- package/dist/components/ui/registry-docs.js +32 -0
- package/dist/components/ui/resizable.d.ts +7 -0
- package/dist/components/ui/resizable.js +15 -0
- package/dist/components/ui/scroll-area.d.ts +7 -0
- package/dist/components/ui/scroll-area.js +10 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/select.js +38 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +7 -0
- package/dist/components/ui/sheet.d.ts +21 -0
- package/dist/components/ui/sheet.js +62 -0
- package/dist/components/ui/sidebar/context.d.ts +21 -0
- package/dist/components/ui/sidebar/context.js +15 -0
- package/dist/components/ui/sidebar/group.d.ts +10 -0
- package/dist/components/ui/sidebar/group.js +18 -0
- package/dist/components/ui/sidebar/layout.d.ts +17 -0
- package/dist/components/ui/sidebar/layout.js +73 -0
- package/dist/components/ui/sidebar/menu.d.ts +30 -0
- package/dist/components/ui/sidebar/menu.js +64 -0
- package/dist/components/ui/sidebar/provider.d.ts +7 -0
- package/dist/components/ui/sidebar/provider.js +53 -0
- package/dist/components/ui/sidebar/rail.d.ts +3 -0
- package/dist/components/ui/sidebar/rail.js +12 -0
- package/dist/components/ui/sidebar/trigger.d.ts +4 -0
- package/dist/components/ui/sidebar/trigger.js +16 -0
- package/dist/components/ui/sidebar-account-menu-theme.d.ts +7 -0
- package/dist/components/ui/sidebar-account-menu-theme.js +32 -0
- package/dist/components/ui/sidebar-account-menu.d.ts +14 -0
- package/dist/components/ui/sidebar-account-menu.js +51 -0
- package/dist/components/ui/sidebar.d.ts +7 -0
- package/dist/components/ui/sidebar.js +7 -0
- package/dist/components/ui/skeleton.d.ts +2 -0
- package/dist/components/ui/skeleton.js +15 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/slider.js +9 -0
- package/dist/components/ui/sonner.d.ts +3 -0
- package/dist/components/ui/sonner.js +33 -0
- package/dist/components/ui/spinner.d.ts +2 -0
- package/dist/components/ui/spinner.js +16 -0
- package/dist/components/ui/switch.d.ts +6 -0
- package/dist/components/ui/switch.js +7 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/table.js +28 -0
- package/dist/components/ui/tabs-variants.d.ts +6 -0
- package/dist/components/ui/tabs-variants.js +13 -0
- package/dist/components/ui/tabs.d.ts +8 -0
- package/dist/components/ui/tabs.js +17 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +6 -0
- package/dist/components/ui/toggle-group.d.ts +9 -0
- package/dist/components/ui/toggle-group.js +24 -0
- package/dist/components/ui/toggle-variants.d.ts +7 -0
- package/dist/components/ui/toggle-variants.js +19 -0
- package/dist/components/ui/toggle.d.ts +5 -0
- package/dist/components/ui/toggle.js +9 -0
- package/dist/components/ui/tooltip.d.ts +11 -0
- package/dist/components/ui/tooltip.js +25 -0
- package/dist/components/ui/workflow-timeline.d.ts +20 -0
- package/dist/components/ui/workflow-timeline.js +92 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +8 -0
- package/dist/styled-system/css/conditions.mjs +36 -0
- package/dist/styled-system/css/css.mjs +45 -0
- package/dist/styled-system/css/cva.mjs +87 -0
- package/dist/styled-system/css/cx.mjs +15 -0
- package/dist/styled-system/css/index.mjs +4 -0
- package/dist/styled-system/css/sva.mjs +46 -0
- package/dist/styled-system/helpers.mjs +316 -0
- package/dist/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/dist/styled-system/patterns/bleed.mjs +24 -0
- package/dist/styled-system/patterns/box.mjs +15 -0
- package/dist/styled-system/patterns/center.mjs +21 -0
- package/dist/styled-system/patterns/circle.mjs +25 -0
- package/dist/styled-system/patterns/container.mjs +21 -0
- package/dist/styled-system/patterns/cq.mjs +21 -0
- package/dist/styled-system/patterns/divider.mjs +25 -0
- package/dist/styled-system/patterns/flex.mjs +26 -0
- package/dist/styled-system/patterns/float.mjs +52 -0
- package/dist/styled-system/patterns/grid-item.mjs +25 -0
- package/dist/styled-system/patterns/grid.mjs +27 -0
- package/dist/styled-system/patterns/hstack.mjs +24 -0
- package/dist/styled-system/patterns/index.mjs +20 -0
- package/dist/styled-system/patterns/link-overlay.mjs +24 -0
- package/dist/styled-system/patterns/spacer.mjs +25 -0
- package/dist/styled-system/patterns/square.mjs +24 -0
- package/dist/styled-system/patterns/stack.mjs +24 -0
- package/dist/styled-system/patterns/visually-hidden.mjs +18 -0
- package/dist/styled-system/patterns/vstack.mjs +24 -0
- package/dist/styled-system/patterns/wrap.mjs +25 -0
- package/dist/styled-system/styles.css +1089 -0
- package/dist/styled-system/styles.css.d.ts +2 -0
- package/dist/styled-system/tokens/index.mjs +2304 -0
- package/package.json +688 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
@import "katex/dist/katex.min.css";
|
|
2
|
+
|
|
3
|
+
@keyframes sd-fade-in {
|
|
4
|
+
from {
|
|
5
|
+
opacity: 0;
|
|
6
|
+
}
|
|
7
|
+
to {
|
|
8
|
+
opacity: 1;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@keyframes sd-blur-in {
|
|
13
|
+
from {
|
|
14
|
+
filter: blur(4px);
|
|
15
|
+
opacity: 0;
|
|
16
|
+
}
|
|
17
|
+
to {
|
|
18
|
+
filter: blur(0);
|
|
19
|
+
opacity: 1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes sd-slide-up {
|
|
24
|
+
from {
|
|
25
|
+
opacity: 0;
|
|
26
|
+
transform: translateY(4px);
|
|
27
|
+
}
|
|
28
|
+
to {
|
|
29
|
+
opacity: 1;
|
|
30
|
+
transform: translateY(0);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
[data-sd-animate] {
|
|
35
|
+
animation: var(--sd-animation, sd-fade-in) var(--sd-duration, var(--motion-duration-fast))
|
|
36
|
+
var(--sd-easing, var(--motion-ease-standard)) var(--sd-delay, 0ms) both;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.agentic-message-response {
|
|
40
|
+
color: var(--foreground);
|
|
41
|
+
font-size: 0.875rem;
|
|
42
|
+
line-height: 1.6;
|
|
43
|
+
max-width: 100%;
|
|
44
|
+
min-width: 0;
|
|
45
|
+
overflow-wrap: anywhere;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.agentic-message-response :where(h1, h2, h3, h4, h5, h6) {
|
|
49
|
+
color: var(--foreground);
|
|
50
|
+
font-family: var(--font-ciridae-display);
|
|
51
|
+
font-weight: var(--font-ciridae-heading-weight);
|
|
52
|
+
letter-spacing: 0;
|
|
53
|
+
line-height: 1.2;
|
|
54
|
+
margin-block: 1.25rem 0.5rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.agentic-message-response :where(h1) {
|
|
58
|
+
font-size: 1.35rem;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.agentic-message-response :where(h2) {
|
|
62
|
+
font-size: 1.2rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.agentic-message-response :where(h3) {
|
|
66
|
+
font-size: 1.05rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.agentic-message-response :where(h4, h5, h6) {
|
|
70
|
+
font-size: 0.95rem;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.agentic-message-response :where(p) {
|
|
74
|
+
margin-block: 0.75rem;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.agentic-message-response :where(ul, ol) {
|
|
78
|
+
margin-block: 0.75rem;
|
|
79
|
+
padding-inline-start: 1.25rem;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.agentic-message-response :where(ul) {
|
|
83
|
+
list-style: disc;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.agentic-message-response :where(ol) {
|
|
87
|
+
list-style: decimal;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.agentic-message-response :where(li) {
|
|
91
|
+
margin-block: 0.25rem;
|
|
92
|
+
padding-inline-start: 0.125rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.agentic-message-response :where(a) {
|
|
96
|
+
color: var(--foreground);
|
|
97
|
+
text-decoration-color: color-mix(in oklch, var(--foreground) 36%, transparent);
|
|
98
|
+
text-decoration-line: underline;
|
|
99
|
+
text-underline-offset: 0.18em;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.agentic-message-response :where(a:hover) {
|
|
103
|
+
text-decoration-color: var(--foreground);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.agentic-message-response :where(strong) {
|
|
107
|
+
font-weight: var(--font-ciridae-strong-weight);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.agentic-message-response :where(hr) {
|
|
111
|
+
border: 0;
|
|
112
|
+
border-block-start: 1px solid var(--border);
|
|
113
|
+
margin-block: 1rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.agentic-message-response :where(blockquote) {
|
|
117
|
+
border-inline-start: 2px solid var(--border);
|
|
118
|
+
color: var(--muted-foreground);
|
|
119
|
+
font-style: normal;
|
|
120
|
+
margin-block: 1rem;
|
|
121
|
+
padding-inline-start: 0.875rem;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.agentic-message-response :where(code),
|
|
125
|
+
.agentic-message-response :where(kbd),
|
|
126
|
+
.agentic-message-response :where(pre) {
|
|
127
|
+
font-family: var(--font-ciridae-mono);
|
|
128
|
+
font-variant-numeric: tabular-nums;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.agentic-message-response :where(:not(pre) > code),
|
|
132
|
+
.agentic-message-response [data-streamdown="inline-code"] {
|
|
133
|
+
background: var(--muted);
|
|
134
|
+
border: 1px solid color-mix(in oklch, var(--border) 72%, transparent);
|
|
135
|
+
border-radius: var(--radius-sm);
|
|
136
|
+
color: var(--foreground);
|
|
137
|
+
font-size: 0.8125rem;
|
|
138
|
+
padding: 0.0625rem 0.3125rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.agentic-message-response [data-streamdown="code-block"],
|
|
142
|
+
.agentic-message-response [data-streamdown="mermaid-block"] {
|
|
143
|
+
background: color-mix(in oklch, var(--muted) 52%, transparent);
|
|
144
|
+
border: 1px solid var(--border);
|
|
145
|
+
border-radius: var(--radius-lg);
|
|
146
|
+
box-shadow: var(--shadow-xs);
|
|
147
|
+
margin-block: 1rem;
|
|
148
|
+
max-width: 100%;
|
|
149
|
+
overflow: hidden;
|
|
150
|
+
padding: 0.5rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.agentic-message-response [data-streamdown="code-block-header"] {
|
|
154
|
+
color: var(--muted-foreground);
|
|
155
|
+
font-size: 0.75rem;
|
|
156
|
+
height: 1.75rem;
|
|
157
|
+
line-height: 1.75rem;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.agentic-message-response [data-streamdown="code-block-body"] {
|
|
161
|
+
background: var(--background);
|
|
162
|
+
border: 1px solid color-mix(in oklch, var(--border) 72%, transparent);
|
|
163
|
+
border-radius: var(--radius-md);
|
|
164
|
+
font-size: 0.8125rem;
|
|
165
|
+
line-height: 1.55;
|
|
166
|
+
overflow-x: auto;
|
|
167
|
+
padding: 0.875rem;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.agentic-message-response [data-streamdown="code-block-body"] pre {
|
|
171
|
+
background: transparent;
|
|
172
|
+
margin: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.agentic-message-response [data-streamdown="code-block-actions"],
|
|
176
|
+
.agentic-message-response [data-streamdown="mermaid-block-actions"] {
|
|
177
|
+
align-items: center;
|
|
178
|
+
background: color-mix(in oklch, var(--background) 88%, transparent);
|
|
179
|
+
border: 1px solid var(--border);
|
|
180
|
+
border-radius: var(--radius-md);
|
|
181
|
+
gap: 0.125rem;
|
|
182
|
+
min-height: 1.75rem;
|
|
183
|
+
padding: 0.125rem;
|
|
184
|
+
transform: translateY(-0.625rem);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.agentic-message-response [data-streamdown="code-block-copy-button"],
|
|
188
|
+
.agentic-message-response [data-streamdown="code-block-download-button"],
|
|
189
|
+
.agentic-message-response [data-streamdown="table-copy-button"],
|
|
190
|
+
.agentic-message-response [data-streamdown="table-download-button"],
|
|
191
|
+
.agentic-message-response [data-streamdown="mermaid-copy-button"],
|
|
192
|
+
.agentic-message-response [data-streamdown="mermaid-download-button"] {
|
|
193
|
+
align-items: center;
|
|
194
|
+
color: var(--muted-foreground);
|
|
195
|
+
display: inline-flex;
|
|
196
|
+
height: 1.5rem;
|
|
197
|
+
justify-content: center;
|
|
198
|
+
transition:
|
|
199
|
+
background-color var(--motion-duration-fast) var(--motion-ease-standard),
|
|
200
|
+
color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
201
|
+
width: 1.5rem;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.agentic-message-response [data-streamdown="code-block-copy-button"]:hover,
|
|
205
|
+
.agentic-message-response [data-streamdown="code-block-download-button"]:hover,
|
|
206
|
+
.agentic-message-response [data-streamdown="table-copy-button"]:hover,
|
|
207
|
+
.agentic-message-response [data-streamdown="table-download-button"]:hover,
|
|
208
|
+
.agentic-message-response [data-streamdown="mermaid-copy-button"]:hover,
|
|
209
|
+
.agentic-message-response [data-streamdown="mermaid-download-button"]:hover {
|
|
210
|
+
background: var(--accent);
|
|
211
|
+
color: var(--accent-foreground);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.agentic-message-response :where(table) {
|
|
215
|
+
border: 1px solid var(--border);
|
|
216
|
+
border-collapse: separate;
|
|
217
|
+
border-radius: var(--radius-md);
|
|
218
|
+
border-spacing: 0;
|
|
219
|
+
display: block;
|
|
220
|
+
margin-block: 1rem;
|
|
221
|
+
max-width: 100%;
|
|
222
|
+
overflow-x: auto;
|
|
223
|
+
width: max-content;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.agentic-message-response :where(thead) {
|
|
227
|
+
background: var(--muted);
|
|
228
|
+
color: var(--table-header-foreground);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.agentic-message-response :where(th, td) {
|
|
232
|
+
border-block-end: 1px solid var(--border);
|
|
233
|
+
font-size: 0.8125rem;
|
|
234
|
+
padding: 0.5rem 0.625rem;
|
|
235
|
+
text-align: start;
|
|
236
|
+
vertical-align: top;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.agentic-message-response :where(th) {
|
|
240
|
+
font-weight: var(--font-ciridae-metadata-weight);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.agentic-message-response :where(tr:last-child td) {
|
|
244
|
+
border-block-end: 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.agentic-message-response :where(.katex-display) {
|
|
248
|
+
overflow-x: auto;
|
|
249
|
+
overflow-y: hidden;
|
|
250
|
+
padding-block: 0.25rem;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.agentic-message-response [data-streamdown="mermaid"] {
|
|
254
|
+
background: var(--background);
|
|
255
|
+
border: 1px solid color-mix(in oklch, var(--border) 72%, transparent);
|
|
256
|
+
border-radius: var(--radius-md);
|
|
257
|
+
color: var(--foreground);
|
|
258
|
+
padding: 1rem;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@media (prefers-reduced-motion: reduce) {
|
|
262
|
+
.agentic-message-response [data-sd-animate] {
|
|
263
|
+
animation: none !important;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { Streamdown } from "streamdown";
|
|
3
|
+
import { MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, type MessageBranchContentProps, type MessageBranchNextProps, type MessageBranchPageProps, type MessageBranchPreviousProps, type MessageBranchProps, type MessageBranchSelectorProps } from "@ciridae/ui/message-branch";
|
|
4
|
+
import type { AgenticMessageRole } from "@ciridae/ui/types";
|
|
5
|
+
import "@ciridae/ui/message-response.css";
|
|
6
|
+
import { Button } from "@ciridae/ui/button";
|
|
7
|
+
type MessageProps = React.ComponentProps<"div"> & {
|
|
8
|
+
role: AgenticMessageRole;
|
|
9
|
+
};
|
|
10
|
+
type MessageContentProps = React.ComponentProps<"div"> & {
|
|
11
|
+
variant?: "default" | "bubble";
|
|
12
|
+
};
|
|
13
|
+
type MessageActionsProps = React.ComponentProps<"div">;
|
|
14
|
+
type MessageActionProps = React.ComponentProps<typeof Button> & {
|
|
15
|
+
label?: string;
|
|
16
|
+
tooltip?: string;
|
|
17
|
+
};
|
|
18
|
+
type MessageToolbarProps = React.ComponentProps<"div">;
|
|
19
|
+
type MessageResponseProps = React.ComponentProps<typeof Streamdown>;
|
|
20
|
+
declare function Message({ className, role, ...props }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
declare function MessageContent({ className, variant, ...props }: MessageContentProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
declare function MessageActions({ className, ...props }: MessageActionsProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
declare function MessageAction({ children, label, tooltip, variant, size, ...props }: MessageActionProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
declare const MessageResponse: React.MemoExoticComponent<({ animated, className, plugins, ...props }: MessageResponseProps) => import("react/jsx-runtime").JSX.Element>;
|
|
25
|
+
declare function MessageToolbar({ className, ...props }: MessageToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export { Message, MessageAction, MessageActions, MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, MessageContent, MessageResponse, MessageToolbar, };
|
|
27
|
+
export type { MessageActionProps, MessageActionsProps, MessageBranchContentProps, MessageBranchNextProps, MessageBranchPageProps, MessageBranchPreviousProps, MessageBranchProps, MessageBranchSelectorProps, MessageContentProps, MessageProps, MessageResponseProps, MessageToolbarProps, };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cjk } from "@streamdown/cjk";
|
|
3
|
+
import { code } from "@streamdown/code";
|
|
4
|
+
import { math } from "@streamdown/math";
|
|
5
|
+
import { mermaid } from "@streamdown/mermaid";
|
|
6
|
+
import { memo, useEffect, useState } from "react";
|
|
7
|
+
import { Streamdown } from "streamdown";
|
|
8
|
+
import { MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, } from "@ciridae/ui/message-branch";
|
|
9
|
+
import "@ciridae/ui/message-response.css";
|
|
10
|
+
import { Button } from "@ciridae/ui/button";
|
|
11
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@ciridae/ui/tooltip";
|
|
12
|
+
import { cn } from "@ciridae/ui/utils";
|
|
13
|
+
const streamdownPlugins = { cjk, code, math, mermaid };
|
|
14
|
+
const messageResponseAnimation = {
|
|
15
|
+
animation: "fade-in",
|
|
16
|
+
duration: 200,
|
|
17
|
+
easing: "var(--motion-ease-standard)",
|
|
18
|
+
sep: "word",
|
|
19
|
+
};
|
|
20
|
+
function Message({ className, role, ...props }) {
|
|
21
|
+
return (_jsx("div", { "data-role": role, "data-slot": "message", className: cn("group/message flex w-full flex-col gap-2", role === "user" ? "items-end" : "items-start", role === "system" ? "py-1" : undefined, className), ...props }));
|
|
22
|
+
}
|
|
23
|
+
function MessageContent({ className, variant = "default", ...props }) {
|
|
24
|
+
return (_jsx("div", { "data-slot": "message-content", "data-variant": variant, className: cn("min-w-0 max-w-[min(42rem,100%)] text-sm leading-relaxed", "data-[variant=bubble]:rounded-lg data-[variant=bubble]:border data-[variant=bubble]:bg-card data-[variant=bubble]:px-4 data-[variant=bubble]:py-3 data-[variant=bubble]:text-card-foreground data-[variant=bubble]:shadow-xs", "group-data-[role=user]/message:max-w-[min(34rem,78%)] group-data-[role=user]/message:rounded-lg group-data-[role=user]/message:border group-data-[role=user]/message:bg-secondary group-data-[role=user]/message:px-4 group-data-[role=user]/message:py-3 group-data-[role=user]/message:text-secondary-foreground group-data-[role=user]/message:shadow-xs", "group-data-[role=assistant]/message:text-foreground", "group-data-[role=system]/message:max-w-full group-data-[role=system]/message:rounded-md group-data-[role=system]/message:border group-data-[role=system]/message:bg-muted/30 group-data-[role=system]/message:px-3 group-data-[role=system]/message:py-2 group-data-[role=system]/message:text-xs group-data-[role=system]/message:text-muted-foreground", className), ...props }));
|
|
25
|
+
}
|
|
26
|
+
function MessageActions({ className, ...props }) {
|
|
27
|
+
return (_jsx("div", { "data-slot": "message-actions", className: cn("flex items-center gap-1", className), ...props }));
|
|
28
|
+
}
|
|
29
|
+
function MessageAction({ children, label, tooltip, variant = "ghost", size = "icon-sm", ...props }) {
|
|
30
|
+
const accessibleLabel = props["aria-label"] ?? label ?? tooltip;
|
|
31
|
+
const button = (_jsxs(Button, { "aria-label": accessibleLabel, size: size, type: "button", variant: variant, ...props, children: [children, label || tooltip ? _jsx("span", { className: "sr-only", children: label ?? tooltip }) : null] }));
|
|
32
|
+
if (!tooltip)
|
|
33
|
+
return button;
|
|
34
|
+
return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: button }), _jsx(TooltipContent, { children: _jsx("p", { children: tooltip }) })] }) }));
|
|
35
|
+
}
|
|
36
|
+
const MessageResponse = memo(function MessageResponse({ animated, className, plugins, ...props }) {
|
|
37
|
+
const prefersReducedMotion = usePrefersReducedMotion();
|
|
38
|
+
const resolvedAnimation = animated === true ? messageResponseAnimation : animated;
|
|
39
|
+
return (_jsx(Streamdown, { animated: prefersReducedMotion ? false : resolvedAnimation, className: cn("agentic-message-response", className), plugins: { ...streamdownPlugins, ...plugins }, ...props }));
|
|
40
|
+
});
|
|
41
|
+
MessageResponse.displayName = "MessageResponse";
|
|
42
|
+
function usePrefersReducedMotion() {
|
|
43
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (typeof window === "undefined")
|
|
46
|
+
return;
|
|
47
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
48
|
+
const handleChange = (event) => setPrefersReducedMotion(event.matches);
|
|
49
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
50
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
51
|
+
}, []);
|
|
52
|
+
return prefersReducedMotion;
|
|
53
|
+
}
|
|
54
|
+
function MessageToolbar({ className, ...props }) {
|
|
55
|
+
return (_jsx("div", { "data-slot": "message-toolbar", className: cn("mt-1 flex w-full max-w-[min(42rem,100%)] items-center justify-between gap-3", "group-data-[role=user]/message:ml-auto group-data-[role=system]/message:max-w-full", className), ...props }));
|
|
56
|
+
}
|
|
57
|
+
export { Message, MessageAction, MessageActions, MessageBranch, MessageBranchContent, MessageBranchNext, MessageBranchPage, MessageBranchPrevious, MessageBranchSelector, MessageContent, MessageResponse, MessageToolbar, };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { AgenticMicOption } from "@ciridae/ui/types";
|
|
3
|
+
import { CommandEmpty, CommandInput, CommandItem, CommandList } from "@ciridae/ui/command";
|
|
4
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@ciridae/ui/popover";
|
|
5
|
+
type MicSelectorContextValue = {
|
|
6
|
+
data: AgenticMicOption[];
|
|
7
|
+
open: boolean;
|
|
8
|
+
setOpen: (open: boolean) => void;
|
|
9
|
+
setValue: (value: string | undefined) => void;
|
|
10
|
+
setWidth: (width: number) => void;
|
|
11
|
+
value: string | undefined;
|
|
12
|
+
width: number;
|
|
13
|
+
};
|
|
14
|
+
type MicSelectorProps = React.ComponentProps<typeof Popover> & {
|
|
15
|
+
defaultValue?: string;
|
|
16
|
+
mics?: AgenticMicOption[];
|
|
17
|
+
onValueChange?: (value: string | undefined) => void;
|
|
18
|
+
value?: string;
|
|
19
|
+
};
|
|
20
|
+
type MicSelectorTriggerProps = React.ComponentProps<typeof PopoverTrigger>;
|
|
21
|
+
type MicSelectorContentProps = React.ComponentProps<typeof PopoverContent> & {
|
|
22
|
+
popoverOptions?: React.ComponentProps<typeof PopoverContent>;
|
|
23
|
+
};
|
|
24
|
+
type MicSelectorInputProps = React.ComponentProps<typeof CommandInput>;
|
|
25
|
+
type MicSelectorListProps = Omit<React.ComponentProps<typeof CommandList>, "children"> & {
|
|
26
|
+
children: (mics: AgenticMicOption[]) => React.ReactNode;
|
|
27
|
+
};
|
|
28
|
+
type MicSelectorEmptyProps = React.ComponentProps<typeof CommandEmpty>;
|
|
29
|
+
type MicSelectorItemProps = React.ComponentProps<typeof CommandItem> & {
|
|
30
|
+
mic?: AgenticMicOption;
|
|
31
|
+
};
|
|
32
|
+
type MicSelectorLabelProps = React.ComponentProps<"span"> & {
|
|
33
|
+
mic: AgenticMicOption;
|
|
34
|
+
};
|
|
35
|
+
type MicSelectorValueProps = React.ComponentProps<"span"> & {
|
|
36
|
+
placeholder?: string;
|
|
37
|
+
};
|
|
38
|
+
declare function MicSelector({ children, defaultOpen, defaultValue, mics, onOpenChange, onValueChange, open: openProp, value: valueProp, ...props }: MicSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
declare function useMicSelector(): MicSelectorContextValue;
|
|
40
|
+
declare function useAudioDevices({ enabled }?: {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
}): {
|
|
43
|
+
devices: AgenticMicOption[];
|
|
44
|
+
error: string | null;
|
|
45
|
+
hasPermission: boolean;
|
|
46
|
+
loadDevices: () => Promise<void>;
|
|
47
|
+
loading: boolean;
|
|
48
|
+
};
|
|
49
|
+
declare function MicSelectorTrigger({ children, ...props }: MicSelectorTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
declare function MicSelectorContent({ className, popoverOptions, style, ...props }: MicSelectorContentProps): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
declare function MicSelectorInput(props: MicSelectorInputProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
declare function MicSelectorList({ children, ...props }: MicSelectorListProps): import("react/jsx-runtime").JSX.Element;
|
|
53
|
+
declare function MicSelectorEmpty({ children, ...props }: MicSelectorEmptyProps): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
declare function MicSelectorItem({ children, mic, onSelect, value, ...props }: MicSelectorItemProps): import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
declare function MicSelectorLabel({ className, mic, ...props }: MicSelectorLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
56
|
+
declare function MicSelectorValue({ className, placeholder, ...props }: MicSelectorValueProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export { MicSelector, MicSelectorContent, MicSelectorEmpty, MicSelectorInput, MicSelectorItem, MicSelectorLabel, MicSelectorList, MicSelectorTrigger, MicSelectorValue, useAudioDevices, useMicSelector, };
|
|
58
|
+
export type { MicSelectorContentProps, MicSelectorEmptyProps, MicSelectorInputProps, MicSelectorItemProps, MicSelectorLabelProps, MicSelectorListProps, MicSelectorProps, MicSelectorTriggerProps, MicSelectorValueProps, };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable max-lines, react-refresh/only-export-components */
|
|
3
|
+
import { ChevronsUpDownIcon } from "lucide-react";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { Button } from "@ciridae/ui/button";
|
|
6
|
+
import { Command, CommandEmpty, CommandInput, CommandItem, CommandList, } from "@ciridae/ui/command";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@ciridae/ui/popover";
|
|
8
|
+
import { cn } from "@ciridae/ui/utils";
|
|
9
|
+
import { useControllableState } from "./use-controllable-state";
|
|
10
|
+
const deviceIdRegex = /\(([\da-fA-F]{4}:[\da-fA-F]{4})\)$/;
|
|
11
|
+
const MicSelectorContext = React.createContext(null);
|
|
12
|
+
function MicSelector({ children, defaultOpen = false, defaultValue, mics, onOpenChange, onValueChange, open: openProp, value: valueProp, ...props }) {
|
|
13
|
+
const [value, setValue] = useControllableState({
|
|
14
|
+
defaultValue,
|
|
15
|
+
onChange: onValueChange,
|
|
16
|
+
value: valueProp,
|
|
17
|
+
});
|
|
18
|
+
const [open, setOpen] = useControllableState({
|
|
19
|
+
defaultValue: defaultOpen,
|
|
20
|
+
onChange: onOpenChange,
|
|
21
|
+
value: openProp,
|
|
22
|
+
});
|
|
23
|
+
const [width, setWidth] = React.useState(200);
|
|
24
|
+
const audioDevices = useAudioDevices({ enabled: !mics });
|
|
25
|
+
const { devices: detectedMics, hasPermission, loadDevices, loading: devicesLoading, } = audioDevices;
|
|
26
|
+
const attemptedPermissionRef = React.useRef(false);
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
if (open && !mics && !hasPermission && !devicesLoading && !attemptedPermissionRef.current) {
|
|
29
|
+
attemptedPermissionRef.current = true;
|
|
30
|
+
void loadDevices();
|
|
31
|
+
}
|
|
32
|
+
}, [devicesLoading, hasPermission, loadDevices, mics, open]);
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
if (!open)
|
|
35
|
+
attemptedPermissionRef.current = false;
|
|
36
|
+
}, [open]);
|
|
37
|
+
const contextValue = React.useMemo(() => ({
|
|
38
|
+
data: mics ?? detectedMics,
|
|
39
|
+
open,
|
|
40
|
+
setOpen,
|
|
41
|
+
setValue,
|
|
42
|
+
setWidth,
|
|
43
|
+
value,
|
|
44
|
+
width,
|
|
45
|
+
}), [detectedMics, mics, open, setOpen, setValue, value, width]);
|
|
46
|
+
return (_jsx(MicSelectorContext.Provider, { value: contextValue, children: _jsx(Popover, { onOpenChange: setOpen, open: open, ...props, children: children ?? _jsx(MicSelectorDefaultContent, {}) }) }));
|
|
47
|
+
}
|
|
48
|
+
function MicSelectorDefaultContent() {
|
|
49
|
+
return (_jsxs(_Fragment, { children: [_jsx(MicSelectorTrigger, { asChild: true, children: _jsxs(Button, { className: "w-64 justify-between", variant: "outline", children: [_jsx(MicSelectorValue, { className: "max-w-52 text-left" }), _jsx(ChevronsUpDownIcon, { className: "size-4 opacity-60" })] }) }), _jsxs(MicSelectorContent, { children: [_jsx(MicSelectorInput, { placeholder: "Search microphones..." }), _jsx(MicSelectorList, { children: (devices) => (_jsxs(_Fragment, { children: [_jsx(MicSelectorEmpty, { children: "No microphone found." }), devices.map((mic) => (_jsx(MicSelectorItem, { mic: mic }, mic.id)))] })) })] })] }));
|
|
50
|
+
}
|
|
51
|
+
function useMicSelector() {
|
|
52
|
+
const context = React.useContext(MicSelectorContext);
|
|
53
|
+
if (!context)
|
|
54
|
+
throw new Error("MicSelector components must be used within MicSelector");
|
|
55
|
+
return context;
|
|
56
|
+
}
|
|
57
|
+
function useAudioDevices({ enabled = true } = {}) {
|
|
58
|
+
const [devices, setDevices] = React.useState([]);
|
|
59
|
+
const [error, setError] = React.useState(null);
|
|
60
|
+
const [hasPermission, setHasPermission] = React.useState(false);
|
|
61
|
+
const [loading, setLoading] = React.useState(false);
|
|
62
|
+
const loadDevicesWithoutPermission = React.useCallback(async () => {
|
|
63
|
+
if (!enabled || !navigator.mediaDevices?.enumerateDevices)
|
|
64
|
+
return;
|
|
65
|
+
try {
|
|
66
|
+
setLoading(true);
|
|
67
|
+
setError(null);
|
|
68
|
+
const deviceList = await navigator.mediaDevices.enumerateDevices();
|
|
69
|
+
setDevices(deviceList.filter(isAudioInput).map(mediaDeviceToMicOption));
|
|
70
|
+
}
|
|
71
|
+
catch (caughtError) {
|
|
72
|
+
setError(caughtError instanceof Error ? caughtError.message : "Failed to get audio devices");
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
setLoading(false);
|
|
76
|
+
}
|
|
77
|
+
}, [enabled]);
|
|
78
|
+
const loadDevices = React.useCallback(async () => {
|
|
79
|
+
if (!enabled || !navigator.mediaDevices?.getUserMedia)
|
|
80
|
+
return;
|
|
81
|
+
try {
|
|
82
|
+
setLoading(true);
|
|
83
|
+
setError(null);
|
|
84
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
85
|
+
for (const track of stream.getTracks())
|
|
86
|
+
track.stop();
|
|
87
|
+
const deviceList = await navigator.mediaDevices.enumerateDevices();
|
|
88
|
+
setDevices(deviceList.filter(isAudioInput).map(mediaDeviceToMicOption));
|
|
89
|
+
setHasPermission(true);
|
|
90
|
+
}
|
|
91
|
+
catch (caughtError) {
|
|
92
|
+
setError(caughtError instanceof Error ? caughtError.message : "Failed to get audio devices");
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
setLoading(false);
|
|
96
|
+
}
|
|
97
|
+
}, [enabled]);
|
|
98
|
+
React.useEffect(() => {
|
|
99
|
+
void loadDevicesWithoutPermission();
|
|
100
|
+
}, [loadDevicesWithoutPermission]);
|
|
101
|
+
React.useEffect(() => {
|
|
102
|
+
if (!enabled || !navigator.mediaDevices?.addEventListener)
|
|
103
|
+
return;
|
|
104
|
+
const handleDeviceChange = () => {
|
|
105
|
+
void (hasPermission ? loadDevices() : loadDevicesWithoutPermission());
|
|
106
|
+
};
|
|
107
|
+
navigator.mediaDevices.addEventListener("devicechange", handleDeviceChange);
|
|
108
|
+
return () => navigator.mediaDevices.removeEventListener("devicechange", handleDeviceChange);
|
|
109
|
+
}, [enabled, hasPermission, loadDevices, loadDevicesWithoutPermission]);
|
|
110
|
+
return { devices, error, hasPermission, loadDevices, loading };
|
|
111
|
+
}
|
|
112
|
+
function MicSelectorTrigger({ children, ...props }) {
|
|
113
|
+
const { setWidth } = useMicSelector();
|
|
114
|
+
const ref = React.useRef(null);
|
|
115
|
+
React.useEffect(() => {
|
|
116
|
+
if (!ref.current)
|
|
117
|
+
return;
|
|
118
|
+
const resizeObserver = new ResizeObserver(([entry]) => {
|
|
119
|
+
if (entry?.target instanceof HTMLElement)
|
|
120
|
+
setWidth(entry.target.offsetWidth);
|
|
121
|
+
});
|
|
122
|
+
resizeObserver.observe(ref.current);
|
|
123
|
+
return () => resizeObserver.disconnect();
|
|
124
|
+
}, [setWidth]);
|
|
125
|
+
return (_jsx(PopoverTrigger, { ref: ref, ...props, children: children }));
|
|
126
|
+
}
|
|
127
|
+
function MicSelectorContent({ className, popoverOptions, style, ...props }) {
|
|
128
|
+
const { width } = useMicSelector();
|
|
129
|
+
const { className: popoverClassName, style: popoverStyle, ...popoverContentOptions } = popoverOptions ?? {};
|
|
130
|
+
return (_jsx(PopoverContent, { align: "start", ...popoverContentOptions, ...props, className: cn("p-0", popoverClassName, className), style: { ...popoverStyle, ...style, width }, children: _jsx(Command, { children: props.children }) }));
|
|
131
|
+
}
|
|
132
|
+
function MicSelectorInput(props) {
|
|
133
|
+
return _jsx(CommandInput, { ...props });
|
|
134
|
+
}
|
|
135
|
+
function MicSelectorList({ children, ...props }) {
|
|
136
|
+
const { data } = useMicSelector();
|
|
137
|
+
return _jsx(CommandList, { ...props, children: children(data) });
|
|
138
|
+
}
|
|
139
|
+
function MicSelectorEmpty({ children = "No microphone found.", ...props }) {
|
|
140
|
+
return _jsx(CommandEmpty, { ...props, children: children });
|
|
141
|
+
}
|
|
142
|
+
function MicSelectorItem({ children, mic, onSelect, value, ...props }) {
|
|
143
|
+
const { setOpen, setValue } = useMicSelector();
|
|
144
|
+
const itemValue = value ?? mic?.id;
|
|
145
|
+
return (_jsx(CommandItem, { onSelect: (currentValue) => {
|
|
146
|
+
setValue(itemValue ?? currentValue);
|
|
147
|
+
setOpen(false);
|
|
148
|
+
onSelect?.(currentValue);
|
|
149
|
+
}, value: itemValue, ...props, children: children ?? (mic ? _jsx(MicSelectorLabel, { mic: mic }) : null) }));
|
|
150
|
+
}
|
|
151
|
+
function MicSelectorLabel({ className, mic, ...props }) {
|
|
152
|
+
const matches = mic.label.match(deviceIdRegex);
|
|
153
|
+
const deviceId = matches?.[1];
|
|
154
|
+
const name = deviceId ? mic.label.replace(deviceIdRegex, "").trim() : mic.label;
|
|
155
|
+
return (_jsxs("span", { className: cn("grid min-w-0 gap-0.5", className), ...props, children: [_jsx("span", { className: "truncate", children: name }), _jsx("span", { className: "truncate text-xs text-muted-foreground", children: mic.description ?? (deviceId ? `Device ${deviceId}` : "Audio input") })] }));
|
|
156
|
+
}
|
|
157
|
+
function MicSelectorValue({ className, placeholder = "Select microphone...", ...props }) {
|
|
158
|
+
const { data, value } = useMicSelector();
|
|
159
|
+
const currentDevice = data.find((device) => device.id === value);
|
|
160
|
+
return (_jsx("span", { className: cn("truncate", className), ...props, children: currentDevice?.label ?? placeholder }));
|
|
161
|
+
}
|
|
162
|
+
function isAudioInput(device) {
|
|
163
|
+
return device.kind === "audioinput";
|
|
164
|
+
}
|
|
165
|
+
function mediaDeviceToMicOption(device) {
|
|
166
|
+
return {
|
|
167
|
+
description: device.groupId ? `Group ${device.groupId.slice(0, 8)}` : undefined,
|
|
168
|
+
id: device.deviceId,
|
|
169
|
+
label: device.label || "Microphone",
|
|
170
|
+
mediaType: device.kind,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
export { MicSelector, MicSelectorContent, MicSelectorEmpty, MicSelectorInput, MicSelectorItem, MicSelectorLabel, MicSelectorList, MicSelectorTrigger, MicSelectorValue, useAudioDevices, useMicSelector, };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut } from "@ciridae/ui/command";
|
|
3
|
+
import { Dialog, DialogContent, DialogTrigger } from "@ciridae/ui/dialog";
|
|
4
|
+
type ModelSelectorProps = React.ComponentProps<typeof Dialog>;
|
|
5
|
+
type ModelSelectorTriggerProps = React.ComponentProps<typeof DialogTrigger>;
|
|
6
|
+
type ModelSelectorContentProps = React.ComponentProps<typeof DialogContent> & {
|
|
7
|
+
title?: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
type ModelSelectorDialogProps = React.ComponentProps<typeof CommandDialog>;
|
|
10
|
+
type ModelSelectorInputProps = React.ComponentProps<typeof CommandInput>;
|
|
11
|
+
type ModelSelectorListProps = React.ComponentProps<typeof CommandList>;
|
|
12
|
+
type ModelSelectorEmptyProps = React.ComponentProps<typeof CommandEmpty>;
|
|
13
|
+
type ModelSelectorGroupProps = React.ComponentProps<typeof CommandGroup>;
|
|
14
|
+
type ModelSelectorItemProps = React.ComponentProps<typeof CommandItem>;
|
|
15
|
+
type ModelSelectorShortcutProps = React.ComponentProps<typeof CommandShortcut>;
|
|
16
|
+
type ModelSelectorSeparatorProps = React.ComponentProps<typeof CommandSeparator>;
|
|
17
|
+
type ModelSelectorLogoProps = Omit<React.ComponentProps<"img">, "alt" | "src"> & {
|
|
18
|
+
alt?: string;
|
|
19
|
+
provider: string;
|
|
20
|
+
src?: string;
|
|
21
|
+
};
|
|
22
|
+
type ModelSelectorLogoGroupProps = React.ComponentProps<"div">;
|
|
23
|
+
type ModelSelectorNameProps = React.ComponentProps<"span">;
|
|
24
|
+
declare function ModelSelector(props: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
declare function ModelSelectorTrigger(props: ModelSelectorTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
declare function ModelSelectorContent({ children, className, title, ...props }: ModelSelectorContentProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
declare function ModelSelectorDialog(props: ModelSelectorDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
declare function ModelSelectorInput({ className, ...props }: ModelSelectorInputProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
declare function ModelSelectorList(props: ModelSelectorListProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
declare function ModelSelectorEmpty(props: ModelSelectorEmptyProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
declare function ModelSelectorGroup(props: ModelSelectorGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
declare function ModelSelectorItem(props: ModelSelectorItemProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
declare function ModelSelectorShortcut(props: ModelSelectorShortcutProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
declare function ModelSelectorSeparator(props: ModelSelectorSeparatorProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
declare function ModelSelectorLogo({ alt, className, provider, src, ...props }: ModelSelectorLogoProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
declare function ModelSelectorLogoGroup({ className, ...props }: ModelSelectorLogoGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
declare function ModelSelectorName({ className, ...props }: ModelSelectorNameProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export { ModelSelector, ModelSelectorContent, ModelSelectorDialog, ModelSelectorEmpty, ModelSelectorGroup, ModelSelectorInput, ModelSelectorItem, ModelSelectorList, ModelSelectorLogo, ModelSelectorLogoGroup, ModelSelectorName, ModelSelectorSeparator, ModelSelectorShortcut, ModelSelectorTrigger, };
|
|
39
|
+
export type { ModelSelectorContentProps, ModelSelectorDialogProps, ModelSelectorEmptyProps, ModelSelectorGroupProps, ModelSelectorInputProps, ModelSelectorItemProps, ModelSelectorListProps, ModelSelectorLogoGroupProps, ModelSelectorLogoProps, ModelSelectorNameProps, ModelSelectorProps, ModelSelectorSeparatorProps, ModelSelectorShortcutProps, ModelSelectorTriggerProps, };
|