@exegia/corpora-ui 3.0.0 → 3.1.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 +20 -0
- package/dist-lib/button-CIRkQXA6.js +152 -0
- package/dist-lib/button.js +3 -0
- package/dist-lib/card.js +150 -0
- package/dist-lib/components/atoms/text/default.d.ts +2 -1143
- package/dist-lib/components/blocks/shell/index.d.ts +1 -0
- package/dist-lib/components/ui/badge.d.ts +2 -2
- package/dist-lib/components/ui/button.d.ts +2 -2
- package/dist-lib/components/ui/glasscn/lazy-glass-surface.d.ts +6 -0
- package/dist-lib/components/ui/modal.d.ts +10 -0
- package/dist-lib/components/ui/overlays.d.ts +4 -0
- package/dist-lib/components/ui/select.d.ts +1 -1
- package/dist-lib/components/ui/toast.d.ts +2 -0
- package/dist-lib/ease-C9At8rnB.js +120 -0
- package/dist-lib/exegia-provider-DNTuLljX.js +124 -0
- package/dist-lib/index.css +3 -0
- package/dist-lib/index.d.ts +3 -0
- package/dist-lib/index.js +6482 -8894
- package/dist-lib/input.js +28 -0
- package/dist-lib/label.js +19 -0
- package/dist-lib/lib/segmented-control.d.ts +1 -1
- package/dist-lib/lib/state/exegia-provider.d.ts +17 -8
- package/dist-lib/lib/state/index.d.ts +2 -0
- package/dist-lib/lib/state/portal-context.d.ts +5 -0
- package/dist-lib/lib/state/sound-loading.d.ts +4 -0
- package/dist-lib/liquid-glass-BihU6nMl.js +50 -0
- package/dist-lib/modal-DLaOK-s1.js +82 -0
- package/dist-lib/overlays.js +3 -0
- package/dist-lib/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/dist-lib/scaffold-Qv4hs5Pf.js +925 -0
- package/dist-lib/scaffold.js +2 -0
- package/dist-lib/shell-BQ9cjIEu.js +722 -0
- package/dist-lib/shell.js +2 -0
- package/dist-lib/sound-knGH4lj-.js +19 -0
- package/dist-lib/state.js +2 -0
- package/dist-lib/toast-CataVXHN.js +193 -0
- package/dist-lib/utils-BO0qfoA6.js +61 -0
- package/package.json +64 -23
- package/dist-lib/components/atoms/_layout.d.ts +0 -4
- package/dist-lib/components/atoms/bubble/__tests__/bubble.test.d.ts +0 -1
- package/dist-lib/components/atoms/bubble/__tests__/reference.test.d.ts +0 -1
- package/dist-lib/components/atoms/text/__tests__/text.test.d.ts +0 -1
- package/dist-lib/components/atoms/text-selection/__tests__/click-popover.test.d.ts +0 -1
- package/dist-lib/components/atoms/text-selection/__tests__/text-selection.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/auth-flow-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/auth-state-atom.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/linked-accounts-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/onboarding-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/passkey-manager-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/passkey-sign-in-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/signup-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/auth/__tests__/update-password-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/chat/__tests__/ai-panel.test.d.ts +0 -1
- package/dist-lib/components/blocks/profile/__tests__/profile-card-block.test.d.ts +0 -1
- package/dist-lib/components/blocks/scaffold/__tests__/scaffold-atom.test.d.ts +0 -1
- package/dist-lib/components/blocks/scaffold/__tests__/scaffold.test.d.ts +0 -1
- package/dist-lib/components/blocks/shell/__tests__/shell-fit-atom.test.d.ts +0 -1
- package/dist-lib/components/blocks/shell/__tests__/shell-layout.test.d.ts +0 -1
- package/dist-lib/components/blocks/shell/__tests__/shell-metrics.test.d.ts +0 -1
- package/dist-lib/components/blocks/sidebar/__tests__/ai-sidebar-atom.test.d.ts +0 -1
- package/dist-lib/components/blocks/sidebar/__tests__/ai-sidebar.test.d.ts +0 -1
- package/dist-lib/components/blocks/sidebar/__tests__/use-ai-sidebar.test.d.ts +0 -1
- package/dist-lib/components/composed/__tests__/logo.test.d.ts +0 -1
- package/dist-lib/components/composed/action-bar/__tests__/action-bar.test.d.ts +0 -1
- package/dist-lib/components/composed/ai/__tests__/ai.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/attachment.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/beautiful-ui.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/chart.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/code-block.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/composer-attachments.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/composer.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/flowchart.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/glass-material.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/markdown.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/menu-command.test.d.ts +0 -1
- package/dist-lib/components/composed/chat/__tests__/recommendation.test.d.ts +0 -1
- package/dist-lib/components/composed/tree/__tests__/tree-atom.test.d.ts +0 -1
- package/dist-lib/components/composed/tree/__tests__/tree.test.d.ts +0 -1
- package/dist-lib/components/composed/tree/__tests__/use-tree.test.d.ts +0 -1
- package/dist-lib/components/composed/user/__tests__/message.test.d.ts +0 -1
- package/dist-lib/components/composed/verse/__tests__/verse.test.d.ts +0 -1
- package/dist-lib/components/docs/atoms-gallery.d.ts +0 -12
- package/dist-lib/components/docs/block-demo-stage.d.ts +0 -7
- package/dist-lib/components/docs/blocks-gallery.d.ts +0 -2
- package/dist-lib/components/docs/browser.d.ts +0 -10
- package/dist-lib/components/docs/code-block.d.ts +0 -4
- package/dist-lib/components/docs/components-gallery.d.ts +0 -2
- package/dist-lib/components/docs/demo-controls.d.ts +0 -21
- package/dist-lib/components/docs/hero.d.ts +0 -5
- package/dist-lib/components/docs/mermaid.d.ts +0 -3
- package/dist-lib/components/icons/__tests__/icons.test.d.ts +0 -1
- package/dist-lib/components/stories/attachment.story.d.ts +0 -11
- package/dist-lib/components/stories/auth-flow-block.story.d.ts +0 -2
- package/dist-lib/components/stories/avatar.story.d.ts +0 -6
- package/dist-lib/components/stories/base.story.d.ts +0 -6
- package/dist-lib/components/stories/bubble.story.d.ts +0 -6
- package/dist-lib/components/stories/button.story.d.ts +0 -9
- package/dist-lib/components/stories/card.story.d.ts +0 -8
- package/dist-lib/components/stories/chart.story.d.ts +0 -71
- package/dist-lib/components/stories/checkbox.story.d.ts +0 -6
- package/dist-lib/components/stories/code-auth-block.story.d.ts +0 -2
- package/dist-lib/components/stories/code-block.story.d.ts +0 -12
- package/dist-lib/components/stories/composed-password-input.story.d.ts +0 -6
- package/dist-lib/components/stories/context-cards.story.d.ts +0 -3
- package/dist-lib/components/stories/emoji-action-bar.story.d.ts +0 -3
- package/dist-lib/components/stories/field.story.d.ts +0 -6
- package/dist-lib/components/stories/file-icons.story.d.ts +0 -5
- package/dist-lib/components/stories/filter-table.story.d.ts +0 -21
- package/dist-lib/components/stories/flowchart.story.d.ts +0 -3
- package/dist-lib/components/stories/forgot-password-block.story.d.ts +0 -2
- package/dist-lib/components/stories/frame.story.d.ts +0 -8
- package/dist-lib/components/stories/index.d.ts +0 -54
- package/dist-lib/components/stories/input-group.story.d.ts +0 -6
- package/dist-lib/components/stories/input.story.d.ts +0 -8
- package/dist-lib/components/stories/insight-cards.story.d.ts +0 -74
- package/dist-lib/components/stories/label.story.d.ts +0 -8
- package/dist-lib/components/stories/linked-accounts-block.story.d.ts +0 -2
- package/dist-lib/components/stories/login-block.story.d.ts +0 -2
- package/dist-lib/components/stories/logo.story.d.ts +0 -3
- package/dist-lib/components/stories/markdown.story.d.ts +0 -7
- package/dist-lib/components/stories/menu-command.story.d.ts +0 -13
- package/dist-lib/components/stories/onboarding-block.story.d.ts +0 -2
- package/dist-lib/components/stories/otp-field.story.d.ts +0 -8
- package/dist-lib/components/stories/passkey-manager-block.story.d.ts +0 -2
- package/dist-lib/components/stories/passkey-sign-in-block.story.d.ts +0 -2
- package/dist-lib/components/stories/password-input.story.d.ts +0 -9
- package/dist-lib/components/stories/profile-card-block.story.d.ts +0 -6
- package/dist-lib/components/stories/recommendation-card.story.d.ts +0 -3
- package/dist-lib/components/stories/records-table.story.d.ts +0 -23
- package/dist-lib/components/stories/reference.story.d.ts +0 -9
- package/dist-lib/components/stories/research-answer.story.d.ts +0 -10
- package/dist-lib/components/stories/scaffold-root.story.d.ts +0 -6
- package/dist-lib/components/stories/separator.story.d.ts +0 -6
- package/dist-lib/components/stories/shell-layout.story.d.ts +0 -2
- package/dist-lib/components/stories/signup-block.story.d.ts +0 -2
- package/dist-lib/components/stories/social-providers.story.d.ts +0 -3
- package/dist-lib/components/stories/streaming-text.story.d.ts +0 -3
- package/dist-lib/components/stories/text.story.d.ts +0 -8
- package/dist-lib/components/stories/textarea.story.d.ts +0 -6
- package/dist-lib/components/stories/tree.story.d.ts +0 -4
- package/dist-lib/components/stories/update-password-block.story.d.ts +0 -2
- package/dist-lib/components/stories/user.story.d.ts +0 -8
- package/dist-lib/components/stories/verse.story.d.ts +0 -6
- package/dist-lib/components/ui/chat/__tests__/segmented-toggle.test.d.ts +0 -1
- package/dist-lib/index.js.map +0 -1
- package/dist-lib/lib/state/__tests__/sound.test.d.ts +0 -1
- package/dist-lib/lib/utils.test.d.ts +0 -1
- package/src/assets/css/base.css +0 -62
- package/src/assets/css/chat.css +0 -229
- package/src/assets/css/shadows.css +0 -157
- package/src/assets/css/theme.css +0 -321
- package/src/components/AGENTS.md +0 -0
- package/src/components/atoms/_layout.tsx +0 -9
- package/src/components/atoms/avatar/base.tsx +0 -70
- package/src/components/atoms/avatar/index.ts +0 -10
- package/src/components/atoms/avatar/types.ts +0 -24
- package/src/components/atoms/avatar/utils.ts +0 -54
- package/src/components/atoms/avatar/verified.tsx +0 -16
- package/src/components/atoms/background/index.ts +0 -8
- package/src/components/atoms/background/texture.tsx +0 -29
- package/src/components/atoms/background/type.ts +0 -10
- package/src/components/atoms/background/utils.ts +0 -13
- package/src/components/atoms/bubble/__tests__/bubble.test.tsx +0 -193
- package/src/components/atoms/bubble/__tests__/reference.test.tsx +0 -25
- package/src/components/atoms/bubble/actions.tsx +0 -28
- package/src/components/atoms/bubble/context.ts +0 -11
- package/src/components/atoms/bubble/default.tsx +0 -46
- package/src/components/atoms/bubble/header.tsx +0 -36
- package/src/components/atoms/bubble/index.ts +0 -37
- package/src/components/atoms/bubble/message.tsx +0 -32
- package/src/components/atoms/bubble/reactions.tsx +0 -191
- package/src/components/atoms/bubble/types.ts +0 -82
- package/src/components/atoms/bubble/utils.ts +0 -46
- package/src/components/atoms/chip.tsx +0 -61
- package/src/components/atoms/field.tsx +0 -43
- package/src/components/atoms/index.ts +0 -26
- package/src/components/atoms/loader.tsx +0 -33
- package/src/components/atoms/reference.tsx +0 -41
- package/src/components/atoms/text/__tests__/text.test.tsx +0 -47
- package/src/components/atoms/text/default.tsx +0 -59
- package/src/components/atoms/text/heading.tsx +0 -58
- package/src/components/atoms/text/index.ts +0 -28
- package/src/components/atoms/text/label.tsx +0 -16
- package/src/components/atoms/text/paragraph.tsx +0 -55
- package/src/components/atoms/text/span.tsx +0 -14
- package/src/components/atoms/text/types.ts +0 -41
- package/src/components/atoms/text/utils.ts +0 -16
- package/src/components/atoms/text-selection/__tests__/click-popover.test.tsx +0 -61
- package/src/components/atoms/text-selection/__tests__/text-selection.test.tsx +0 -90
- package/src/components/atoms/text-selection/click-popover.tsx +0 -62
- package/src/components/atoms/text-selection/index.ts +0 -30
- package/src/components/atoms/text-selection/popover.tsx +0 -103
- package/src/components/atoms/text-selection/selection-atom.ts +0 -51
- package/src/components/atoms/text-selection/selection.tsx +0 -56
- package/src/components/atoms/text-selection/types.ts +0 -125
- package/src/components/atoms/text-selection/use-selection.ts +0 -84
- package/src/components/atoms/types.ts +0 -46
- package/src/components/blocks/.gitkeep +0 -0
- package/src/components/blocks/auth/__tests__/auth-flow-block.test.tsx +0 -183
- package/src/components/blocks/auth/__tests__/auth-state-atom.test.tsx +0 -247
- package/src/components/blocks/auth/__tests__/linked-accounts-block.test.tsx +0 -128
- package/src/components/blocks/auth/__tests__/onboarding-block.test.tsx +0 -183
- package/src/components/blocks/auth/__tests__/passkey-manager-block.test.tsx +0 -131
- package/src/components/blocks/auth/__tests__/passkey-sign-in-block.test.tsx +0 -59
- package/src/components/blocks/auth/__tests__/signup-block.test.tsx +0 -176
- package/src/components/blocks/auth/__tests__/update-password-block.test.tsx +0 -95
- package/src/components/blocks/auth/auth-flow-atom.ts +0 -238
- package/src/components/blocks/auth/auth-flow-block.tsx +0 -211
- package/src/components/blocks/auth/auth-session-atom.ts +0 -82
- package/src/components/blocks/auth/auth-shell.tsx +0 -265
- package/src/components/blocks/auth/auth-state.ts +0 -40
- package/src/components/blocks/auth/code-auth-block.tsx +0 -176
- package/src/components/blocks/auth/forgot-password-block.tsx +0 -112
- package/src/components/blocks/auth/linked-accounts-block.tsx +0 -203
- package/src/components/blocks/auth/login-block.tsx +0 -217
- package/src/components/blocks/auth/onboarding/profile-step.tsx +0 -216
- package/src/components/blocks/auth/onboarding-block.tsx +0 -183
- package/src/components/blocks/auth/passkey-manager-block.tsx +0 -316
- package/src/components/blocks/auth/passkey-sign-in-block.tsx +0 -67
- package/src/components/blocks/auth/signup-block.tsx +0 -256
- package/src/components/blocks/auth/type.ts +0 -436
- package/src/components/blocks/auth/update-password-block.tsx +0 -139
- package/src/components/blocks/auth/use-auth-state.ts +0 -127
- package/src/components/blocks/chat/__tests__/ai-panel.test.tsx +0 -65
- package/src/components/blocks/chat/banners.tsx +0 -61
- package/src/components/blocks/chat/base.tsx +0 -84
- package/src/components/blocks/chat/header.tsx +0 -60
- package/src/components/blocks/chat/index.ts +0 -37
- package/src/components/blocks/chat/recommendation-stack.tsx +0 -41
- package/src/components/blocks/chat/shared.tsx +0 -27
- package/src/components/blocks/chat/suggested-prompts.tsx +0 -45
- package/src/components/blocks/chat/type.ts +0 -96
- package/src/components/blocks/chat/version-history-record.tsx +0 -37
- package/src/components/blocks/layout.ts +0 -35
- package/src/components/blocks/profile/__tests__/profile-card-block.test.tsx +0 -362
- package/src/components/blocks/profile/index.ts +0 -28
- package/src/components/blocks/profile/profile-card-atom.ts +0 -247
- package/src/components/blocks/profile/profile-card-block.tsx +0 -369
- package/src/components/blocks/profile/type.ts +0 -93
- package/src/components/blocks/profile/use-profile-card-state.ts +0 -67
- package/src/components/blocks/profile/use-profile-card.ts +0 -132
- package/src/components/blocks/scaffold/__tests__/scaffold-atom.test.tsx +0 -236
- package/src/components/blocks/scaffold/__tests__/scaffold.test.tsx +0 -524
- package/src/components/blocks/scaffold/constants.ts +0 -39
- package/src/components/blocks/scaffold/index.ts +0 -60
- package/src/components/blocks/scaffold/panel-close-button.tsx +0 -36
- package/src/components/blocks/scaffold/panel-menu-button.tsx +0 -221
- package/src/components/blocks/scaffold/scaffold-actions.tsx +0 -92
- package/src/components/blocks/scaffold/scaffold-atom.ts +0 -427
- package/src/components/blocks/scaffold/scaffold-canvas.tsx +0 -162
- package/src/components/blocks/scaffold/scaffold-context.ts +0 -20
- package/src/components/blocks/scaffold/scaffold-inspector.tsx +0 -137
- package/src/components/blocks/scaffold/scaffold-main.tsx +0 -28
- package/src/components/blocks/scaffold/scaffold-panel.tsx +0 -186
- package/src/components/blocks/scaffold/scaffold-root.tsx +0 -120
- package/src/components/blocks/scaffold/scaffold-sidebar.tsx +0 -31
- package/src/components/blocks/scaffold/scaffold-sub-panel.tsx +0 -122
- package/src/components/blocks/scaffold/scaffold-tab.tsx +0 -108
- package/src/components/blocks/scaffold/type.ts +0 -264
- package/src/components/blocks/scaffold/use-scaffold-state.ts +0 -85
- package/src/components/blocks/scaffold/use-scaffold.ts +0 -59
- package/src/components/blocks/scaffold/utils.ts +0 -112
- package/src/components/blocks/shell/__tests__/shell-fit-atom.test.tsx +0 -362
- package/src/components/blocks/shell/__tests__/shell-layout.test.tsx +0 -596
- package/src/components/blocks/shell/__tests__/shell-metrics.test.ts +0 -154
- package/src/components/blocks/shell/animated-panel-inset.tsx +0 -27
- package/src/components/blocks/shell/animated-panel-provider.tsx +0 -269
- package/src/components/blocks/shell/animated-panel-trigger.tsx +0 -51
- package/src/components/blocks/shell/animated-panel.tsx +0 -180
- package/src/components/blocks/shell/index.ts +0 -30
- package/src/components/blocks/shell/shell-fit-atom.ts +0 -246
- package/src/components/blocks/shell/shell-layout.tsx +0 -139
- package/src/components/blocks/shell/shell-metrics.ts +0 -133
- package/src/components/blocks/shell/shell-panel-atom.ts +0 -74
- package/src/components/blocks/shell/type.ts +0 -361
- package/src/components/blocks/shell/use-shell-fit-state.ts +0 -49
- package/src/components/blocks/shell/use-shell-fit.ts +0 -153
- package/src/components/blocks/shell/use-shell-panels.ts +0 -126
- package/src/components/blocks/shell/utils.ts +0 -187
- package/src/components/blocks/sidebar/__tests__/ai-sidebar-atom.test.tsx +0 -325
- package/src/components/blocks/sidebar/__tests__/ai-sidebar.test.tsx +0 -93
- package/src/components/blocks/sidebar/__tests__/use-ai-sidebar.test.tsx +0 -310
- package/src/components/blocks/sidebar/ai-sidebar-atom.ts +0 -698
- package/src/components/blocks/sidebar/ai-sidebar.tsx +0 -150
- package/src/components/blocks/sidebar/index.ts +0 -67
- package/src/components/blocks/sidebar/marquee-label.tsx +0 -59
- package/src/components/blocks/sidebar/sidebar-context.ts +0 -15
- package/src/components/blocks/sidebar/sidebar-icon.tsx +0 -14
- package/src/components/blocks/sidebar/sidebar-row.tsx +0 -378
- package/src/components/blocks/sidebar/type.ts +0 -294
- package/src/components/blocks/sidebar/use-ai-sidebar-state.ts +0 -123
- package/src/components/blocks/sidebar/use-ai-sidebar.ts +0 -619
- package/src/components/blocks/sidebar/utils.ts +0 -170
- package/src/components/blocks/types.ts +0 -6
- package/src/components/composed/.gitkeep +0 -0
- package/src/components/composed/__tests__/logo.test.tsx +0 -60
- package/src/components/composed/action-bar/__tests__/action-bar.test.tsx +0 -125
- package/src/components/composed/action-bar/action.tsx +0 -77
- package/src/components/composed/action-bar/emojis.tsx +0 -97
- package/src/components/composed/action-bar/index.ts +0 -24
- package/src/components/composed/action-bar/toolbar.tsx +0 -66
- package/src/components/composed/action-bar/types.ts +0 -58
- package/src/components/composed/action-bar/utils.ts +0 -140
- package/src/components/composed/ai/__tests__/ai.test.tsx +0 -66
- package/src/components/composed/ai/avatar.tsx +0 -19
- package/src/components/composed/ai/index.ts +0 -36
- package/src/components/composed/ai/message.tsx +0 -49
- package/src/components/composed/ai/research-answer.tsx +0 -157
- package/src/components/composed/ai/shared.tsx +0 -94
- package/src/components/composed/ai/streaming-text.tsx +0 -94
- package/src/components/composed/ai/suggested-prompt.tsx +0 -183
- package/src/components/composed/ai/types.ts +0 -81
- package/src/components/composed/chat/__tests__/attachment.test.tsx +0 -218
- package/src/components/composed/chat/__tests__/beautiful-ui.test.tsx +0 -57
- package/src/components/composed/chat/__tests__/chart.test.tsx +0 -316
- package/src/components/composed/chat/__tests__/code-block.test.tsx +0 -12
- package/src/components/composed/chat/__tests__/composer-attachments.test.tsx +0 -101
- package/src/components/composed/chat/__tests__/composer.test.tsx +0 -248
- package/src/components/composed/chat/__tests__/flowchart.test.tsx +0 -145
- package/src/components/composed/chat/__tests__/glass-material.test.tsx +0 -54
- package/src/components/composed/chat/__tests__/markdown.test.tsx +0 -25
- package/src/components/composed/chat/__tests__/menu-command.test.tsx +0 -35
- package/src/components/composed/chat/__tests__/recommendation.test.tsx +0 -43
- package/src/components/composed/chat/actions.tsx +0 -81
- package/src/components/composed/chat/attachment-file.ts +0 -82
- package/src/components/composed/chat/attachment.tsx +0 -498
- package/src/components/composed/chat/chart/chart-atom.ts +0 -55
- package/src/components/composed/chat/chart/chart-context.ts +0 -9
- package/src/components/composed/chat/chart/chart-legend.tsx +0 -75
- package/src/components/composed/chat/chart/chart-plot.tsx +0 -233
- package/src/components/composed/chat/chart/chart-root.tsx +0 -229
- package/src/components/composed/chat/chart/chart-tooltip.tsx +0 -74
- package/src/components/composed/chat/chart/constants.ts +0 -8
- package/src/components/composed/chat/chart/evilcharts/README.md +0 -8
- package/src/components/composed/chat/chart/evilcharts/echarts-area-chart.tsx +0 -2358
- package/src/components/composed/chat/chart/evilcharts/echarts-bar-chart.tsx +0 -2261
- package/src/components/composed/chat/chart/evilcharts/echarts-brush.tsx +0 -233
- package/src/components/composed/chat/chart/evilcharts/echarts-chart.tsx +0 -214
- package/src/components/composed/chat/chart/evilcharts/echarts-dot.tsx +0 -111
- package/src/components/composed/chat/chart/evilcharts/echarts-legend.tsx +0 -131
- package/src/components/composed/chat/chart/evilcharts/echarts-line-chart.tsx +0 -2112
- package/src/components/composed/chat/chart/evilcharts/echarts-pie-chart.tsx +0 -1235
- package/src/components/composed/chat/chart/evilcharts/echarts-tooltip.tsx +0 -125
- package/src/components/composed/chat/chart/index.ts +0 -13
- package/src/components/composed/chat/chart/type.ts +0 -88
- package/src/components/composed/chat/chart/use-chart-state.ts +0 -22
- package/src/components/composed/chat/chart/use-chart.ts +0 -70
- package/src/components/composed/chat/chart/utils.ts +0 -47
- package/src/components/composed/chat/chart.tsx +0 -3
- package/src/components/composed/chat/code-block.tsx +0 -123
- package/src/components/composed/chat/composer/add-button.tsx +0 -29
- package/src/components/composed/chat/composer/base.tsx +0 -573
- package/src/components/composed/chat/composer/command-menu.tsx +0 -47
- package/src/components/composed/chat/composer/hooks.ts +0 -29
- package/src/components/composed/chat/composer/index.ts +0 -19
- package/src/components/composed/chat/composer/send-button.tsx +0 -36
- package/src/components/composed/chat/composer/suggestions.tsx +0 -115
- package/src/components/composed/chat/composer/use-dictation.ts +0 -123
- package/src/components/composed/chat/composer/utils.ts +0 -74
- package/src/components/composed/chat/context-cards.tsx +0 -63
- package/src/components/composed/chat/filter-table.tsx +0 -119
- package/src/components/composed/chat/flowchart/chart-node.tsx +0 -162
- package/src/components/composed/chat/flowchart/connector.tsx +0 -32
- package/src/components/composed/chat/flowchart/constant.ts +0 -26
- package/src/components/composed/chat/flowchart/default.tsx +0 -230
- package/src/components/composed/chat/flowchart/edge-toolbar.tsx +0 -73
- package/src/components/composed/chat/flowchart/hooks.tsx +0 -347
- package/src/components/composed/chat/flowchart/index.ts +0 -14
- package/src/components/composed/chat/flowchart/step-body.tsx +0 -82
- package/src/components/composed/chat/flowchart/types.ts +0 -89
- package/src/components/composed/chat/flowchart/utils.ts +0 -78
- package/src/components/composed/chat/hint.tsx +0 -59
- package/src/components/composed/chat/index.ts +0 -92
- package/src/components/composed/chat/insight-cards.tsx +0 -199
- package/src/components/composed/chat/markdown-atom.ts +0 -15
- package/src/components/composed/chat/markdown.tsx +0 -213
- package/src/components/composed/chat/recommendation/checkbox.tsx +0 -122
- package/src/components/composed/chat/recommendation/constant.ts +0 -54
- package/src/components/composed/chat/recommendation/default.tsx +0 -25
- package/src/components/composed/chat/recommendation/group.tsx +0 -36
- package/src/components/composed/chat/recommendation/index.ts +0 -17
- package/src/components/composed/chat/recommendation/item.tsx +0 -215
- package/src/components/composed/chat/recommendation/types.ts +0 -76
- package/src/components/composed/chat/records-table.tsx +0 -130
- package/src/components/composed/chat/type.ts +0 -157
- package/src/components/composed/logo.tsx +0 -171
- package/src/components/composed/password-input.tsx +0 -179
- package/src/components/composed/reader/applied-mark.tsx +0 -32
- package/src/components/composed/reader/apply-toast.tsx +0 -49
- package/src/components/composed/reader/index.ts +0 -10
- package/src/components/composed/reader/selection-highlight.tsx +0 -26
- package/src/components/composed/reader/selection-popover.tsx +0 -149
- package/src/components/composed/reader/type.ts +0 -48
- package/src/components/composed/social-providers.tsx +0 -154
- package/src/components/composed/tree/CLAUDE.md +0 -145
- package/src/components/composed/tree/__tests__/tree-atom.test.tsx +0 -217
- package/src/components/composed/tree/__tests__/tree.test.tsx +0 -522
- package/src/components/composed/tree/__tests__/use-tree.test.tsx +0 -333
- package/src/components/composed/tree/constants.ts +0 -55
- package/src/components/composed/tree/index.ts +0 -51
- package/src/components/composed/tree/tree-atom.ts +0 -590
- package/src/components/composed/tree/tree-context.ts +0 -13
- package/src/components/composed/tree/tree-node.tsx +0 -496
- package/src/components/composed/tree/tree.tsx +0 -233
- package/src/components/composed/tree/type.ts +0 -322
- package/src/components/composed/tree/use-tree-dnd.ts +0 -179
- package/src/components/composed/tree/use-tree-state.ts +0 -105
- package/src/components/composed/tree/use-tree.ts +0 -311
- package/src/components/composed/tree/utils.ts +0 -172
- package/src/components/composed/types.ts +0 -9
- package/src/components/composed/user/__tests__/message.test.tsx +0 -79
- package/src/components/composed/user/index.ts +0 -14
- package/src/components/composed/user/info.tsx +0 -56
- package/src/components/composed/user/message.tsx +0 -36
- package/src/components/composed/user/pill.tsx +0 -20
- package/src/components/composed/user/types.ts +0 -47
- package/src/components/composed/user/utils.ts +0 -0
- package/src/components/composed/verse/__tests__/verse.test.tsx +0 -57
- package/src/components/composed/verse/index.ts +0 -2
- package/src/components/composed/verse/types.ts +0 -24
- package/src/components/composed/verse/verse.tsx +0 -100
- package/src/components/docs/atoms-gallery.tsx +0 -286
- package/src/components/docs/block-demo-stage.tsx +0 -38
- package/src/components/docs/blocks-gallery.tsx +0 -224
- package/src/components/docs/browser.tsx +0 -87
- package/src/components/docs/code-block.tsx +0 -10
- package/src/components/docs/components-gallery.tsx +0 -182
- package/src/components/docs/demo-controls.tsx +0 -142
- package/src/components/docs/hero.tsx +0 -197
- package/src/components/docs/mermaid.tsx +0 -55
- package/src/components/icons/README.md +0 -91
- package/src/components/icons/__tests__/icons.test.tsx +0 -58
- package/src/components/icons/file-badge-cfm.tsx +0 -615
- package/src/components/icons/file-badge-corpus.tsx +0 -604
- package/src/components/icons/file-badge-pdf.tsx +0 -570
- package/src/components/icons/file-badge-tei.tsx +0 -524
- package/src/components/icons/file-badge-tf.tsx +0 -620
- package/src/components/icons/file-badge-txt.tsx +0 -607
- package/src/components/icons/file-badge-xml.tsx +0 -576
- package/src/components/icons/file-wordmark-cfm.tsx +0 -424
- package/src/components/icons/file-wordmark-corpus.tsx +0 -454
- package/src/components/icons/file-wordmark-pdf.tsx +0 -470
- package/src/components/icons/file-wordmark-tei.tsx +0 -424
- package/src/components/icons/file-wordmark-tf.tsx +0 -406
- package/src/components/icons/file-wordmark-txt.tsx +0 -421
- package/src/components/icons/file-wordmark-xml.tsx +0 -424
- package/src/components/icons/index.ts +0 -16
- package/src/components/icons/types.ts +0 -8
- package/src/components/motion/index.ts +0 -0
- package/src/components/motion/overflow-actions.tsx +0 -376
- package/src/components/motion/popover-morph.tsx +0 -292
- package/src/components/motion/popover-position.ts +0 -86
- package/src/components/motion/shared-layout-bg.tsx +0 -151
- package/src/components/stories/attachment.story.tsx +0 -40
- package/src/components/stories/auth-flow-block.story.tsx +0 -17
- package/src/components/stories/avatar.story.tsx +0 -33
- package/src/components/stories/base.story.tsx +0 -70
- package/src/components/stories/bubble.story.tsx +0 -61
- package/src/components/stories/button.story.tsx +0 -32
- package/src/components/stories/card.story.tsx +0 -36
- package/src/components/stories/chart.story.tsx +0 -69
- package/src/components/stories/checkbox.story.tsx +0 -30
- package/src/components/stories/code-auth-block.story.tsx +0 -20
- package/src/components/stories/code-block.story.tsx +0 -35
- package/src/components/stories/composed-password-input.story.tsx +0 -41
- package/src/components/stories/context-cards.story.tsx +0 -30
- package/src/components/stories/emoji-action-bar.story.tsx +0 -20
- package/src/components/stories/field.story.tsx +0 -32
- package/src/components/stories/file-icons.story.tsx +0 -20
- package/src/components/stories/filter-table.story.tsx +0 -63
- package/src/components/stories/flowchart.story.tsx +0 -25
- package/src/components/stories/forgot-password-block.story.tsx +0 -14
- package/src/components/stories/frame.story.tsx +0 -32
- package/src/components/stories/index.ts +0 -57
- package/src/components/stories/input-group.story.tsx +0 -27
- package/src/components/stories/input.story.tsx +0 -42
- package/src/components/stories/insight-cards.story.tsx +0 -67
- package/src/components/stories/label.story.tsx +0 -32
- package/src/components/stories/linked-accounts-block.story.tsx +0 -23
- package/src/components/stories/login-block.story.tsx +0 -18
- package/src/components/stories/logo.story.tsx +0 -21
- package/src/components/stories/markdown.story.tsx +0 -31
- package/src/components/stories/menu-command.story.tsx +0 -43
- package/src/components/stories/onboarding-block.story.tsx +0 -14
- package/src/components/stories/otp-field.story.tsx +0 -35
- package/src/components/stories/passkey-manager-block.story.tsx +0 -18
- package/src/components/stories/passkey-sign-in-block.story.tsx +0 -15
- package/src/components/stories/password-input.story.tsx +0 -35
- package/src/components/stories/profile-card-block.story.tsx +0 -29
- package/src/components/stories/recommendation-card.story.tsx +0 -37
- package/src/components/stories/records-table.story.tsx +0 -52
- package/src/components/stories/reference.story.tsx +0 -33
- package/src/components/stories/research-answer.story.tsx +0 -32
- package/src/components/stories/scaffold-root.story.tsx +0 -47
- package/src/components/stories/separator.story.tsx +0 -37
- package/src/components/stories/shell-layout.story.tsx +0 -19
- package/src/components/stories/signup-block.story.tsx +0 -18
- package/src/components/stories/social-providers.story.tsx +0 -26
- package/src/components/stories/streaming-text.story.tsx +0 -25
- package/src/components/stories/text.story.tsx +0 -31
- package/src/components/stories/textarea.story.tsx +0 -34
- package/src/components/stories/tree.story.tsx +0 -31
- package/src/components/stories/update-password-block.story.tsx +0 -14
- package/src/components/stories/user.story.tsx +0 -32
- package/src/components/stories/verse.story.tsx +0 -42
- package/src/components/theme-provider.tsx +0 -230
- package/src/components/types.ts +0 -106
- package/src/components/ui/accordion.tsx +0 -68
- package/src/components/ui/alert-dialog.tsx +0 -167
- package/src/components/ui/alert.tsx +0 -84
- package/src/components/ui/autocomplete.tsx +0 -303
- package/src/components/ui/avatar.tsx +0 -109
- package/src/components/ui/badge.tsx +0 -101
- package/src/components/ui/button-group.tsx +0 -88
- package/src/components/ui/button.tsx +0 -192
- package/src/components/ui/card.tsx +0 -253
- package/src/components/ui/chat/__tests__/segmented-toggle.test.tsx +0 -27
- package/src/components/ui/chat/avatar-handle.tsx +0 -30
- package/src/components/ui/chat/badges.tsx +0 -85
- package/src/components/ui/chat/buttons.tsx +0 -94
- package/src/components/ui/chat/chips.tsx +0 -106
- package/src/components/ui/chat/dot.tsx +0 -81
- package/src/components/ui/chat/icon-button.tsx +0 -43
- package/src/components/ui/chat/icon-tile.tsx +0 -33
- package/src/components/ui/chat/index.ts +0 -12
- package/src/components/ui/chat/inline-source.tsx +0 -94
- package/src/components/ui/chat/segmented-toggle.tsx +0 -99
- package/src/components/ui/chat/tag.tsx +0 -61
- package/src/components/ui/chat/thumbnail.tsx +0 -31
- package/src/components/ui/chat/waveform.tsx +0 -30
- package/src/components/ui/checkbox.tsx +0 -83
- package/src/components/ui/collapsible.tsx +0 -42
- package/src/components/ui/command.tsx +0 -263
- package/src/components/ui/context-menu.tsx +0 -342
- package/src/components/ui/emoji-picker.tsx +0 -161
- package/src/components/ui/field.tsx +0 -89
- package/src/components/ui/frame.tsx +0 -87
- package/src/components/ui/glasscn/glass-button-group.tsx +0 -34
- package/src/components/ui/glasscn/glass-button.tsx +0 -25
- package/src/components/ui/glasscn/glass-container.tsx +0 -94
- package/src/components/ui/glasscn/glass-separator.tsx +0 -39
- package/src/components/ui/glasscn/liquid-glass.tsx +0 -59
- package/src/components/ui/group.tsx +0 -92
- package/src/components/ui/input-group.tsx +0 -105
- package/src/components/ui/input.tsx +0 -70
- package/src/components/ui/kbd.tsx +0 -32
- package/src/components/ui/label.tsx +0 -36
- package/src/components/ui/menu-command.tsx +0 -156
- package/src/components/ui/menu.tsx +0 -352
- package/src/components/ui/otp-field.tsx +0 -88
- package/src/components/ui/popover-glass.tsx +0 -158
- package/src/components/ui/popover.tsx +0 -120
- package/src/components/ui/preview-card.tsx +0 -61
- package/src/components/ui/scroll-area.tsx +0 -80
- package/src/components/ui/select.tsx +0 -257
- package/src/components/ui/separator.tsx +0 -23
- package/src/components/ui/sheet.tsx +0 -135
- package/src/components/ui/skeleton.tsx +0 -18
- package/src/components/ui/spinner.tsx +0 -17
- package/src/components/ui/switch.tsx +0 -30
- package/src/components/ui/tabs.tsx +0 -120
- package/src/components/ui/textarea.tsx +0 -58
- package/src/components/ui/toast.tsx +0 -325
- package/src/components/ui/toolbar.tsx +0 -92
- package/src/components/ui/tooltip.tsx +0 -67
- package/src/index.css +0 -10
- package/src/index.ts +0 -102
- package/src/lib/attachment-content.ts +0 -28
- package/src/lib/auth-accent.ts +0 -49
- package/src/lib/ease.ts +0 -90
- package/src/lib/glass-variants.ts +0 -22
- package/src/lib/hooks/use-hover-capable.ts +0 -23
- package/src/lib/hooks/use-mobile.ts +0 -21
- package/src/lib/keyed-atom.ts +0 -60
- package/src/lib/segmented-control.ts +0 -42
- package/src/lib/sound.ts +0 -39
- package/src/lib/specular.ts +0 -10
- package/src/lib/state/__tests__/sound.test.tsx +0 -53
- package/src/lib/state/exegia-provider.tsx +0 -83
- package/src/lib/state/index.ts +0 -4
- package/src/lib/state/store.ts +0 -19
- package/src/lib/use-motion-panel.ts +0 -78
- package/src/lib/utils.test.ts +0 -22
- package/src/lib/utils.ts +0 -100
- package/src/specular.js +0 -4
- /package/{src/components/composed/chat/composer → dist-lib}/BEAUTIFUL-UI-LICENSE.txt +0 -0
- /package/{src/components/composed/chat/chart/evilcharts/LICENSE → dist-lib/EVILCHARTS-LICENSE.txt} +0 -0
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { createContext, useMemo, useState } from "react"
|
|
2
|
-
import { Tooltip } from "@base-ui/react/tooltip"
|
|
3
|
-
import type {
|
|
4
|
-
TActionBarSegment,
|
|
5
|
-
TActionEntry,
|
|
6
|
-
TActionItemsByGroup,
|
|
7
|
-
TActionKey,
|
|
8
|
-
TActionMap,
|
|
9
|
-
IEmojiActionBarProps,
|
|
10
|
-
} from "./types"
|
|
11
|
-
import type { Emoji } from "frimousse"
|
|
12
|
-
|
|
13
|
-
// Each toolbar owns its handle; a shared handle cannot control multiple roots.
|
|
14
|
-
export const ActionTooltipContext = createContext<
|
|
15
|
-
Tooltip.Handle<string> | undefined
|
|
16
|
-
>(undefined)
|
|
17
|
-
|
|
18
|
-
export const isSeparator = (key: string): boolean => key.includes("separator")
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Splits `actions` into render-ready segments at every `separator-*` key.
|
|
22
|
-
*
|
|
23
|
-
* Order comes from the map's insertion order (see `ActionMap`) — the grouping
|
|
24
|
-
* is positional, so actions written before a separator group ahead of it.
|
|
25
|
-
* Empty groups are dropped, which is what keeps a leading, trailing or
|
|
26
|
-
* doubled separator from rendering a `ToolbarGroup` with nothing in it.
|
|
27
|
-
*/
|
|
28
|
-
export const useActionBar = ({
|
|
29
|
-
actions,
|
|
30
|
-
}: {
|
|
31
|
-
actions: TActionMap<TActionKey>
|
|
32
|
-
}) => {
|
|
33
|
-
return useMemo(() => {
|
|
34
|
-
const entries = Object.entries(actions) as TActionEntry[]
|
|
35
|
-
const segments: TActionBarSegment[] = []
|
|
36
|
-
let open: TActionEntry[] = []
|
|
37
|
-
|
|
38
|
-
const closeGroup = (): void => {
|
|
39
|
-
if (open.length === 0) return
|
|
40
|
-
segments.push({ type: "group", key: `group-${open[0][0]}`, items: open })
|
|
41
|
-
open = []
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
for (const entry of entries) {
|
|
45
|
-
const [key, Item] = entry
|
|
46
|
-
if (isSeparator(key)) {
|
|
47
|
-
closeGroup()
|
|
48
|
-
segments.push({ type: "separator", key, Separator: Item })
|
|
49
|
-
continue
|
|
50
|
-
}
|
|
51
|
-
open.push(entry)
|
|
52
|
-
}
|
|
53
|
-
closeGroup()
|
|
54
|
-
|
|
55
|
-
const groups = segments.filter((s) => s.type === "group")
|
|
56
|
-
|
|
57
|
-
// A bar with no separators renders flat — `ToolbarGroup` is only added
|
|
58
|
-
// once the caller has actually asked for grouping.
|
|
59
|
-
const hasGroups = segments.some((s) => s.type === "separator")
|
|
60
|
-
|
|
61
|
-
const actionItemsByGroup: TActionItemsByGroup = Object.fromEntries(
|
|
62
|
-
groups.map((group) => [group.key, group.items])
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
segments,
|
|
67
|
-
entries,
|
|
68
|
-
hasGroups,
|
|
69
|
-
groupsCount: groups.length,
|
|
70
|
-
separatorCount: segments.length - groups.length,
|
|
71
|
-
actionItemsByGroup,
|
|
72
|
-
}
|
|
73
|
-
}, [actions])
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* The quick row. frimousse has no way to render a subset — `EmojiPicker.Root`
|
|
78
|
-
* takes `columns`/`skinTone`/`locale`/`emojiVersion`/`emojibaseUrl`/`sticky`
|
|
79
|
-
* and nothing else, and its list is virtualized on fixed-height rows, so a
|
|
80
|
-
* custom `Emoji` component that returns null leaves holes rather than a short
|
|
81
|
-
* row. A fixed list is the only way to show just these, and it costs no
|
|
82
|
-
* network request — the CDN fetch only happens if "More" is opened.
|
|
83
|
-
*/
|
|
84
|
-
export const QUICK_REACTIONS: readonly Emoji[] = [
|
|
85
|
-
{ emoji: "❤️", label: "heart" },
|
|
86
|
-
{ emoji: "👍", label: "thumbs up" },
|
|
87
|
-
{ emoji: "😊", label: "smiling face" },
|
|
88
|
-
{ emoji: "😂", label: "face with tears of joy" },
|
|
89
|
-
{ emoji: "🎉", label: "party popper" },
|
|
90
|
-
{ emoji: "🙏", label: "folded hands" },
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Hook for managing the emoji picker state and actions.
|
|
95
|
-
*
|
|
96
|
-
* @param props - The emoji picker props.
|
|
97
|
-
* @returns The emoji picker state and actions.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```tsx
|
|
101
|
-
* const { isFullPicker, quickReactions, actions, togglePicker, selectEmoji } = useEmojiPicker({ onEmojiSelect });
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
export const useEmojiPicker = ({
|
|
105
|
-
onEmojiSelect,
|
|
106
|
-
reactions,
|
|
107
|
-
hideMore,
|
|
108
|
-
}: IEmojiActionBarProps) => {
|
|
109
|
-
const [isFullPicker, setShowAll] = useState(false)
|
|
110
|
-
|
|
111
|
-
// Toggles the picker between quick reactions and the full picker.
|
|
112
|
-
const togglePicker = () => setShowAll((previous) => !previous)
|
|
113
|
-
/**
|
|
114
|
-
* Reports the pick and folds the full picker back to the quick row. The bar
|
|
115
|
-
* lives inside a `keepMounted` popover, so it is never unmounted on close —
|
|
116
|
-
* without this reset the next open would still show the full picker.
|
|
117
|
-
*/
|
|
118
|
-
const selectEmoji = (emoji: Emoji): void => {
|
|
119
|
-
setShowAll(false)
|
|
120
|
-
onEmojiSelect?.(emoji)
|
|
121
|
-
}
|
|
122
|
-
// The quick reactions to display.
|
|
123
|
-
const quickReactions = reactions ?? QUICK_REACTIONS
|
|
124
|
-
const actions = useMemo(() => {
|
|
125
|
-
if (hideMore) return quickReactions
|
|
126
|
-
return [
|
|
127
|
-
...quickReactions,
|
|
128
|
-
{ emoji: "Separator", label: "separator" },
|
|
129
|
-
{ emoji: "More", label: "More emoji" },
|
|
130
|
-
]
|
|
131
|
-
}, [quickReactions, hideMore])
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
isFullPicker,
|
|
135
|
-
quickReactions,
|
|
136
|
-
actions,
|
|
137
|
-
togglePicker,
|
|
138
|
-
selectEmoji,
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { describe, expect, mock, test } from "bun:test"
|
|
2
|
-
import { render, screen } from "@testing-library/react"
|
|
3
|
-
import { Message } from "../message"
|
|
4
|
-
import type { TAIContentProps } from "../types"
|
|
5
|
-
|
|
6
|
-
describe("Message", () => {
|
|
7
|
-
test("renders the agent identity row and the body as a polite live region", () => {
|
|
8
|
-
const { container } = render(
|
|
9
|
-
<Message type="markdown">Hello reader</Message>
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
expect(screen.getByText("Exegia")).toBeDefined()
|
|
13
|
-
expect(screen.getByText("AI Scholar")).toBeDefined()
|
|
14
|
-
|
|
15
|
-
const root = container.querySelector('[data-slot="ai-message"]')
|
|
16
|
-
expect(root).not.toBeNull()
|
|
17
|
-
expect(root!.getAttribute("data-variant")).toBe("ai")
|
|
18
|
-
|
|
19
|
-
const body = container.querySelector('[data-slot="ai-message-body"]')
|
|
20
|
-
expect(body).not.toBeNull()
|
|
21
|
-
expect(body!.getAttribute("aria-live")).toBe("polite")
|
|
22
|
-
expect(body!.textContent).toContain("Hello reader")
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test("marks the root while streaming and drops the flag at rest", () => {
|
|
26
|
-
const { container, rerender } = render(
|
|
27
|
-
<Message isStreaming type="markdown" />
|
|
28
|
-
)
|
|
29
|
-
const root = container.querySelector('[data-slot="ai-message"]')!
|
|
30
|
-
expect(root.hasAttribute("data-streaming")).toBe(true)
|
|
31
|
-
|
|
32
|
-
rerender(<Message type="markdown" />)
|
|
33
|
-
expect(root.hasAttribute("data-streaming")).toBe(false)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
test("hands AttachedContent the message type as `kind` plus contentProps", () => {
|
|
37
|
-
const seen = mock<(props: TAIContentProps<"chart">) => void>(() => {})
|
|
38
|
-
const Attached = (props: TAIContentProps<"chart">) => {
|
|
39
|
-
seen(props)
|
|
40
|
-
return <div data-testid="attached">chart goes here</div>
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
render(
|
|
44
|
-
<Message
|
|
45
|
-
AttachedContent={Attached}
|
|
46
|
-
contentProps={{ type: "bar", data: [], series: [] }}
|
|
47
|
-
type="chart"
|
|
48
|
-
/>
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
expect(screen.getByTestId("attached")).toBeDefined()
|
|
52
|
-
expect(seen).toHaveBeenCalledTimes(1)
|
|
53
|
-
expect(seen.mock.calls[0]?.[0]).toMatchObject({
|
|
54
|
-
kind: "chart",
|
|
55
|
-
type: "bar",
|
|
56
|
-
data: [],
|
|
57
|
-
series: [],
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test("renders no attachment slot when AttachedContent is omitted", () => {
|
|
62
|
-
const { container } = render(<Message type="markdown">Prose only</Message>)
|
|
63
|
-
const body = container.querySelector('[data-slot="ai-message-body"]')!
|
|
64
|
-
expect(body.textContent).toBe("Prose only")
|
|
65
|
-
})
|
|
66
|
-
})
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import OWLImage from "@/assets/owl-avatar.png"
|
|
2
|
-
import { Badge } from "@/components/ui/badge";
|
|
3
|
-
import { Avatar as AvatarAtom } from "@/components/atoms";
|
|
4
|
-
|
|
5
|
-
export const Avatar = () => {
|
|
6
|
-
return (
|
|
7
|
-
<div className="flex items-center gap-1.5">
|
|
8
|
-
<AvatarAtom size="default" className="bg-indigo-900/20 dark:bg-indigo-100/40 p-0.5 scale-90 shadow-debossed inset-shadow-accent" user={{ avatarUrl: OWLImage }} />
|
|
9
|
-
<div className="flex flex-col">
|
|
10
|
-
<div className="inline-flex items-center gap-1.5">
|
|
11
|
-
<span className="text-sm font-semibold">Exegia</span>
|
|
12
|
-
<Badge variant="default" size="xs">
|
|
13
|
-
AI Scholar
|
|
14
|
-
</Badge>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { Message } from "./message"
|
|
2
|
-
import { StreamingText } from "./streaming-text"
|
|
3
|
-
import { ResearchAnswer } from "./research-answer"
|
|
4
|
-
import { SuggestedPrompt } from "./suggested-prompt"
|
|
5
|
-
import { Avatar } from "./avatar"
|
|
6
|
-
|
|
7
|
-
export type { ISuggestedPromptProps } from "./suggested-prompt"
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
accentRing,
|
|
11
|
-
accentSolid,
|
|
12
|
-
accentText,
|
|
13
|
-
agentText,
|
|
14
|
-
ghostMuted,
|
|
15
|
-
glassCard,
|
|
16
|
-
mutedText,
|
|
17
|
-
surface,
|
|
18
|
-
} from "./shared"
|
|
19
|
-
export { type IStreamingTextProps, type TStreamingToken } from "./streaming-text"
|
|
20
|
-
export type { IResearchAnswerProps } from "./research-answer"
|
|
21
|
-
export type {
|
|
22
|
-
IAISuggestionBase,
|
|
23
|
-
IDiffRow,
|
|
24
|
-
IReferenceBase,
|
|
25
|
-
TSuggestionState,
|
|
26
|
-
} from "./types"
|
|
27
|
-
|
|
28
|
-
const AI = {
|
|
29
|
-
Message,
|
|
30
|
-
Avatar,
|
|
31
|
-
StreamingText,
|
|
32
|
-
SuggestedPrompt,
|
|
33
|
-
ResearchAnswer,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default AI
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { TAIContentProps, IAIMessageProps, TAIMessageType } from "./types"
|
|
2
|
-
import { Bubble } from "@/components/atoms"
|
|
3
|
-
import { cn } from "@/lib/utils"
|
|
4
|
-
import { Avatar } from "./avatar"
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* An agent turn: author row, prose body and — when the model proposed
|
|
8
|
-
* changes — a "Suggestions" disclosure that fans the cards out below with a
|
|
9
|
-
* staggered spring.
|
|
10
|
-
*/
|
|
11
|
-
export function Message<T extends TAIMessageType>({
|
|
12
|
-
children,
|
|
13
|
-
isStreaming = false,
|
|
14
|
-
className,
|
|
15
|
-
AttachedContent,
|
|
16
|
-
type,
|
|
17
|
-
contentProps,
|
|
18
|
-
...props
|
|
19
|
-
}: IAIMessageProps<T>): React.ReactElement {
|
|
20
|
-
// TS can't relate `AIContentProps<T>` to JSX's IntrinsicAttributes while `T`
|
|
21
|
-
// is unresolved; widen to the full union for the render site only.
|
|
22
|
-
const Content = AttachedContent as
|
|
23
|
-
React.ComponentType<TAIContentProps> | undefined
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<Bubble
|
|
27
|
-
className={cn("my-1.5", className)}
|
|
28
|
-
data-slot="ai-message"
|
|
29
|
-
data-streaming={isStreaming ? "" : undefined}
|
|
30
|
-
variant="ai"
|
|
31
|
-
{...props}
|
|
32
|
-
>
|
|
33
|
-
<Bubble.Header>
|
|
34
|
-
<Avatar />
|
|
35
|
-
</Bubble.Header>
|
|
36
|
-
|
|
37
|
-
<Bubble.Message
|
|
38
|
-
aria-atomic="false"
|
|
39
|
-
aria-live="polite"
|
|
40
|
-
data-slot="ai-message-body"
|
|
41
|
-
>
|
|
42
|
-
<div className="ml-3">{children}</div>
|
|
43
|
-
{Content && (
|
|
44
|
-
<Content {...({ kind: type, ...contentProps } as TAIContentProps)} />
|
|
45
|
-
)}
|
|
46
|
-
</Bubble.Message>
|
|
47
|
-
</Bubble>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { BookOpen, Calendar, Copy, ListPlus, Share2, Users } from "lucide-react"
|
|
4
|
-
import type * as React from "react"
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
import {
|
|
7
|
-
Card,
|
|
8
|
-
CardFrame,
|
|
9
|
-
CardFrameFooter,
|
|
10
|
-
CardFrameHeader,
|
|
11
|
-
CardPanel,
|
|
12
|
-
} from "@/components/ui/card"
|
|
13
|
-
import { Button } from "@/components/ui/button"
|
|
14
|
-
import { IconTile, InlineSource } from "@/components/ui/chat"
|
|
15
|
-
|
|
16
|
-
export interface IResearchReference {
|
|
17
|
-
/** Pill label, e.g. "Iliad · Homer corpus". */
|
|
18
|
-
label: React.ReactNode
|
|
19
|
-
/** Preview-card content shown on hover. */
|
|
20
|
-
favicon?: string
|
|
21
|
-
title?: React.ReactNode
|
|
22
|
-
description?: React.ReactNode
|
|
23
|
-
href?: string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface IResearchAnswerProps extends Omit<
|
|
27
|
-
React.ComponentPropsWithoutRef<"div">,
|
|
28
|
-
"content"
|
|
29
|
-
> {
|
|
30
|
-
kicker?: React.ReactNode
|
|
31
|
-
/** "Answered from 3 passages · 0.8 s" */
|
|
32
|
-
kickerSub?: React.ReactNode
|
|
33
|
-
content: React.ReactNode
|
|
34
|
-
source?: React.ReactNode | IResearchReference
|
|
35
|
-
date?: React.ReactNode
|
|
36
|
-
authors?: React.ReactNode | IResearchReference
|
|
37
|
-
onCopyCitation?: () => void
|
|
38
|
-
onShare?: () => void
|
|
39
|
-
/** TODO(spec 003): the design shows the control only; behaviour is the caller's. */
|
|
40
|
-
onAddToList?: () => void
|
|
41
|
-
bare?: boolean
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const GHOST =
|
|
45
|
-
"h-6 gap-1.5 rounded-md px-2 text-[11.5px] font-medium text-text-secondary hover:bg-surface-subtle hover:text-text-primary sm:h-6 [&_svg]:size-3.5! [&_svg]:opacity-100"
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Research answer card: kicker, content, Source / Date / Author(s) meta, actions.
|
|
49
|
-
*
|
|
50
|
-
* @sketch "Component / Research Answer"
|
|
51
|
-
*/
|
|
52
|
-
export function ResearchAnswer({
|
|
53
|
-
kicker = "Research answer",
|
|
54
|
-
kickerSub,
|
|
55
|
-
content,
|
|
56
|
-
source,
|
|
57
|
-
date,
|
|
58
|
-
authors,
|
|
59
|
-
onCopyCitation,
|
|
60
|
-
onShare,
|
|
61
|
-
onAddToList,
|
|
62
|
-
bare = false,
|
|
63
|
-
className,
|
|
64
|
-
...props
|
|
65
|
-
}: IResearchAnswerProps): React.ReactElement {
|
|
66
|
-
// A structured value renders as a reference pill with a hover preview;
|
|
67
|
-
// plain strings stay plain text.
|
|
68
|
-
const asPill = (
|
|
69
|
-
value: React.ReactNode | IResearchReference
|
|
70
|
-
): React.ReactNode => {
|
|
71
|
-
if (value && typeof value === "object" && "label" in value) {
|
|
72
|
-
const { label, ...preview } = value as IResearchReference
|
|
73
|
-
return <InlineSource domain={label} {...preview} />
|
|
74
|
-
}
|
|
75
|
-
return value
|
|
76
|
-
}
|
|
77
|
-
const meta = [
|
|
78
|
-
{ icon: <BookOpen />, label: "Source", value: source },
|
|
79
|
-
{ icon: <Calendar />, label: "Date", value: date },
|
|
80
|
-
{ icon: <Users />, label: "Author(s)", value: authors },
|
|
81
|
-
].filter((m) => m.value !== undefined)
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<CardFrame
|
|
85
|
-
data-slot="research-answer"
|
|
86
|
-
className={cn(
|
|
87
|
-
"w-[380px] max-w-full [--frame-radius:var(--radius-md)]",
|
|
88
|
-
bare && "border-transparent shadow-none",
|
|
89
|
-
className
|
|
90
|
-
)}
|
|
91
|
-
{...props}
|
|
92
|
-
>
|
|
93
|
-
<CardFrameHeader className="flex flex-row items-start gap-2 px-3.5 py-3">
|
|
94
|
-
<IconTile size={28}>
|
|
95
|
-
<BookOpen />
|
|
96
|
-
</IconTile>
|
|
97
|
-
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
98
|
-
<span className="text-[13px] leading-4 font-semibold text-text-primary">
|
|
99
|
-
{kicker}
|
|
100
|
-
</span>
|
|
101
|
-
{kickerSub ? (
|
|
102
|
-
<span className="text-[11px] leading-3 text-text-secondary">
|
|
103
|
-
{kickerSub}
|
|
104
|
-
</span>
|
|
105
|
-
) : null}
|
|
106
|
-
</div>
|
|
107
|
-
</CardFrameHeader>
|
|
108
|
-
<Card>
|
|
109
|
-
<CardPanel className="px-3.5 py-3.5 text-[13px] leading-[18px] text-text-primary">
|
|
110
|
-
{content}
|
|
111
|
-
</CardPanel>
|
|
112
|
-
{meta.length ? (
|
|
113
|
-
<>
|
|
114
|
-
<div className="mx-3.5 h-px bg-border-default" />
|
|
115
|
-
<dl className="flex flex-col gap-1.5 px-3.5 py-3">
|
|
116
|
-
{meta.map((m) => (
|
|
117
|
-
<div key={m.label} className="flex items-baseline gap-3">
|
|
118
|
-
<dt className="flex w-20 shrink-0 items-center gap-1 text-[11px] leading-4 text-text-secondary [&_svg]:size-3 [&_svg]:self-center [&_svg]:text-icon">
|
|
119
|
-
{m.icon}
|
|
120
|
-
{m.label}
|
|
121
|
-
</dt>
|
|
122
|
-
<dd className="min-w-0 flex-1 text-[12px] leading-4 text-text-primary">
|
|
123
|
-
{asPill(m.value)}
|
|
124
|
-
</dd>
|
|
125
|
-
</div>
|
|
126
|
-
))}
|
|
127
|
-
</dl>
|
|
128
|
-
</>
|
|
129
|
-
) : null}
|
|
130
|
-
</Card>
|
|
131
|
-
<CardFrameFooter className="flex items-center gap-0.5 p-2">
|
|
132
|
-
<Button
|
|
133
|
-
variant="ghost"
|
|
134
|
-
size="xs"
|
|
135
|
-
className={GHOST}
|
|
136
|
-
onClick={onCopyCitation}
|
|
137
|
-
>
|
|
138
|
-
<Copy />
|
|
139
|
-
Copy
|
|
140
|
-
</Button>
|
|
141
|
-
<Button variant="ghost" size="xs" className={GHOST} onClick={onShare}>
|
|
142
|
-
<Share2 />
|
|
143
|
-
Share
|
|
144
|
-
</Button>
|
|
145
|
-
<Button
|
|
146
|
-
variant="ghost"
|
|
147
|
-
size="xs"
|
|
148
|
-
className={GHOST}
|
|
149
|
-
onClick={onAddToList}
|
|
150
|
-
>
|
|
151
|
-
<ListPlus />
|
|
152
|
-
Add to list
|
|
153
|
-
</Button>
|
|
154
|
-
</CardFrameFooter>
|
|
155
|
-
</CardFrame>
|
|
156
|
-
)
|
|
157
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { Children, Fragment, isValidElement } from "react"
|
|
2
|
-
import type * as React from "react"
|
|
3
|
-
import { cn } from "@/lib/utils"
|
|
4
|
-
import { EASE_IN_OUT, SPRING_PANEL } from "@/lib/ease"
|
|
5
|
-
import type { Variants } from "motion"
|
|
6
|
-
|
|
7
|
-
// The AI accent is a muted amber used sparingly — the ✦ icon, small labels
|
|
8
|
-
// and the primary Apply action. Everything else reads from theme tokens so
|
|
9
|
-
// these components inherit whatever surface hosts them (e.g. the shell
|
|
10
|
-
// right panel).
|
|
11
|
-
export const accentText = "text-amber-600 dark:text-amber-300/90"
|
|
12
|
-
|
|
13
|
-
export const accentRing = "ring-offset-0 focus-visible:ring-amber-400/40"
|
|
14
|
-
|
|
15
|
-
export const accentSolid = cn(
|
|
16
|
-
"border-amber-500/60 bg-amber-400/90 text-amber-950 shadow-none hover:bg-amber-400 disabled:opacity-35 data-pressed:bg-amber-400 *:data-[slot=button-loading-indicator]:text-amber-950",
|
|
17
|
-
accentRing
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
// The agent's own voice is violet: its badge, the suggestions disclosure and
|
|
21
|
-
// the accepted mark on a suggestion card.
|
|
22
|
-
export const agentText = "text-violet-600 dark:text-violet-400"
|
|
23
|
-
|
|
24
|
-
export const ghostMuted = cn(
|
|
25
|
-
"text-muted-foreground hover:text-foreground",
|
|
26
|
-
accentRing
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
export const mutedText = "text-[13px] leading-5 text-muted-foreground"
|
|
30
|
-
|
|
31
|
-
// Floating surfaces (scope picker list, selection popover) — theme tokens,
|
|
32
|
-
// not a hard-coded dark panel.
|
|
33
|
-
export const surface = "border bg-popover text-popover-foreground shadow-lg"
|
|
34
|
-
|
|
35
|
-
/** The AI spark — the accent-coloured ✦ that marks every AI affordance. */
|
|
36
|
-
export function AiIcon({
|
|
37
|
-
className,
|
|
38
|
-
}: {
|
|
39
|
-
className?: string
|
|
40
|
-
}): React.ReactElement {
|
|
41
|
-
return (
|
|
42
|
-
<span aria-hidden="true" className={cn(accentText, className)}>
|
|
43
|
-
✦
|
|
44
|
-
</span>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function CloseIcon(): React.ReactElement {
|
|
49
|
-
return (
|
|
50
|
-
<svg
|
|
51
|
-
aria-hidden="true"
|
|
52
|
-
className="size-4"
|
|
53
|
-
fill="none"
|
|
54
|
-
viewBox="0 0 24 24"
|
|
55
|
-
stroke="currentColor"
|
|
56
|
-
strokeWidth="1.8"
|
|
57
|
-
>
|
|
58
|
-
<path d="m6 6 12 12M18 6 6 18" />
|
|
59
|
-
</svg>
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Frosted card used by suggestion cards: a translucent field with a lit top
|
|
64
|
-
// edge and a light backdrop blur so the thread reads through it.
|
|
65
|
-
export const glassCard =
|
|
66
|
-
"rounded-md border-0 border-t-2 border-t-white/70 bg-neutral-200/45 shadow-none backdrop-blur-[3px] backdrop-saturate-125 before:hidden dark:border-t-neutral-700 dark:bg-neutral-800/50"
|
|
67
|
-
|
|
68
|
-
// The suggestions fan-out: the list holds the stagger, each item springs up
|
|
69
|
-
// into place. Shared by `AiMessage`'s disclosure and `SuggestedPrompts`, so
|
|
70
|
-
// both fan out with the same rhythm.
|
|
71
|
-
export const LIST_VARIANTS: Variants = {
|
|
72
|
-
hidden: { transition: { staggerChildren: 0.04, staggerDirection: -1 } },
|
|
73
|
-
visible: { transition: { staggerChildren: 0.07, delayChildren: 0.05 } },
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export const ITEM_VARIANTS: Variants = {
|
|
77
|
-
hidden: {
|
|
78
|
-
opacity: 0,
|
|
79
|
-
y: 14,
|
|
80
|
-
scale: 0.97,
|
|
81
|
-
transition: { duration: 0.18, ease: EASE_IN_OUT },
|
|
82
|
-
},
|
|
83
|
-
visible: { opacity: 1, y: 0, scale: 1, transition: SPRING_PANEL },
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Children.toArray, but looking through fragments so `<>{a}{b}</>` counts two. */
|
|
87
|
-
export function flattenChildren(children: React.ReactNode): React.ReactNode[] {
|
|
88
|
-
return Children.toArray(children).flatMap((child) =>
|
|
89
|
-
isValidElement<{ children?: React.ReactNode }>(child) &&
|
|
90
|
-
child.type === Fragment
|
|
91
|
-
? flattenChildren(child.props.children)
|
|
92
|
-
: [child]
|
|
93
|
-
)
|
|
94
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import { useReducedMotion } from "motion/react"
|
|
4
|
-
import * as React from "react"
|
|
5
|
-
import { cn } from "@/lib/utils"
|
|
6
|
-
import { InlineSource } from "@/components/ui/chat"
|
|
7
|
-
|
|
8
|
-
/** A word, or an inline citation; extra fields turn the chip into a hover preview. */
|
|
9
|
-
export type TStreamingToken =
|
|
10
|
-
| { text: string }
|
|
11
|
-
| { cite: string; favicon?: string; title?: string; description?: string; href?: string }
|
|
12
|
-
|
|
13
|
-
export interface IStreamingTextProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
14
|
-
/** Paragraphs, each a token list; a string is split on spaces. */
|
|
15
|
-
paragraphs: (string | TStreamingToken[])[]
|
|
16
|
-
/** Reveal words over time and show the caret. */
|
|
17
|
-
streaming?: boolean
|
|
18
|
-
/** Reveal gap in ms; defaults to the --stream-gap token (60ms). */
|
|
19
|
-
wordMs?: number
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const toTokens = (p: string | TStreamingToken[]): TStreamingToken[] => (typeof p === "string" ? p.split(" ").map((text) => ({ text })) : p)
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Streamed answer: paragraphs with inline source previews and a caret.
|
|
28
|
-
* Actions, sources and follow-ups belong to the host.
|
|
29
|
-
*
|
|
30
|
-
* @sketch "Component / Streaming Text"
|
|
31
|
-
*/
|
|
32
|
-
export function StreamingText({
|
|
33
|
-
paragraphs, streaming = false, wordMs, className, ...props
|
|
34
|
-
}: IStreamingTextProps): React.ReactElement {
|
|
35
|
-
const reduceMotion = useReducedMotion()
|
|
36
|
-
const tokens = React.useMemo(() => paragraphs.map(toTokens), [paragraphs])
|
|
37
|
-
const total = tokens.reduce((n, p) => n + p.length, 0)
|
|
38
|
-
// Revealed-word counter; a change in `total` resets it during render (the
|
|
39
|
-
// React "adjust state on prop change" pattern), and only the interval
|
|
40
|
-
// advances it, so no effect ever sets state synchronously.
|
|
41
|
-
const [reveal, setReveal] = React.useState({ total, n: 0 })
|
|
42
|
-
if (reveal.total !== total) setReveal({ total, n: 0 })
|
|
43
|
-
const animate = streaming && !reduceMotion
|
|
44
|
-
const shown = animate ? Math.min(reveal.n, total) : total
|
|
45
|
-
|
|
46
|
-
React.useEffect(() => {
|
|
47
|
-
if (!animate) return
|
|
48
|
-
// The JS cadence reads --stream-gap so the token stays the single source
|
|
49
|
-
// of truth; an explicit wordMs still wins. Reading it here keeps SSR safe.
|
|
50
|
-
const gapMs =
|
|
51
|
-
wordMs ??
|
|
52
|
-
(parseFloat(
|
|
53
|
-
getComputedStyle(document.documentElement).getPropertyValue("--stream-gap")
|
|
54
|
-
) || 60)
|
|
55
|
-
const timer = setInterval(() => setReveal((r) => (r.n >= r.total ? r : { ...r, n: r.n + 1 })), gapMs)
|
|
56
|
-
return () => clearInterval(timer)
|
|
57
|
-
}, [animate, wordMs, total])
|
|
58
|
-
|
|
59
|
-
const done = shown >= total
|
|
60
|
-
let cursor = 0
|
|
61
|
-
// Plain CSS transitions: each word fades in once and never re-animates on
|
|
62
|
-
// re-render, which is what kept the Motion version flickering.
|
|
63
|
-
const word = (visible: boolean) =>
|
|
64
|
-
cn(
|
|
65
|
-
"inline transition-[opacity,filter] duration-[var(--stream-fade)] ease-[var(--stream-ease)]",
|
|
66
|
-
!reduceMotion && !visible ? "opacity-0 blur-[var(--stream-blur)]" : "blur-[0px]",
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<div data-slot="streaming-text" data-streaming={streaming && !done} className={cn("flex w-[380px] max-w-full flex-col", className)} {...props}>
|
|
71
|
-
{tokens.map((p, pi) => (
|
|
72
|
-
<p key={pi} className="text-[13px] leading-5 text-text-primary">
|
|
73
|
-
{p.map((t, ti) => {
|
|
74
|
-
const index = cursor++
|
|
75
|
-
const visible = index < shown
|
|
76
|
-
const last = index === shown - 1 && streaming && !done
|
|
77
|
-
return (
|
|
78
|
-
<React.Fragment key={ti}>
|
|
79
|
-
<span className={word(visible)}>
|
|
80
|
-
{"cite" in t ? (
|
|
81
|
-
<InlineSource domain={t.cite} favicon={t.favicon} title={t.title} description={t.description} href={t.href} />
|
|
82
|
-
) : (
|
|
83
|
-
t.text
|
|
84
|
-
)}{" "}
|
|
85
|
-
</span>
|
|
86
|
-
{last ? <span aria-hidden="true" className="ml-px inline-block h-3.5 w-0.5 animate-pulse bg-text-primary align-middle" /> : null}
|
|
87
|
-
</React.Fragment>
|
|
88
|
-
)
|
|
89
|
-
})}
|
|
90
|
-
</p>
|
|
91
|
-
))}
|
|
92
|
-
</div>
|
|
93
|
-
)
|
|
94
|
-
}
|