@digithings-ai/ui 0.0.0-stage → 0.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 +48 -2
- package/package.json +143 -4
- package/src/components/NavShell.tsx +776 -0
- package/src/components/SocialRow.tsx +87 -0
- package/src/components/Spinner.tsx +27 -0
- package/src/components/StackLogo.tsx +40 -0
- package/src/components/Terminal.tsx +110 -0
- package/src/components/TerminalManifest.tsx +212 -0
- package/src/components/ThemeProvider.tsx +271 -0
- package/src/components/account/AuthCard.tsx +309 -0
- package/src/components/assistant-ui/elements/mermaid-diagram.aui.tsx +63 -0
- package/src/components/assistant-ui/elements/mermaid-diagram.tsx +340 -0
- package/src/components/brand/BrandWordmark.tsx +32 -0
- package/src/components/changelog/ReleaseRail.tsx +81 -0
- package/src/components/changelog/index.ts +1 -0
- package/src/components/chat/ChatCodeBlock.tsx +67 -0
- package/src/components/chat/ChatMarkdown.tsx +66 -0
- package/src/components/chat/ChatMarkdownSource.tsx +203 -0
- package/src/components/chat/ChatMermaidBlock.tsx +202 -0
- package/src/components/chat/ChatMessage.tsx +77 -0
- package/src/components/chat/ChatPlayback.tsx +422 -0
- package/src/components/chat/ChatStreamCursor.tsx +25 -0
- package/src/components/chat/ChatThinking.tsx +113 -0
- package/src/components/chat/ChatToolCall.tsx +190 -0
- package/src/components/chat/ChatTranscript.tsx +60 -0
- package/src/components/chat/ChatWidgetFrame.tsx +107 -0
- package/src/components/chat/DigichatBootLoader.tsx +683 -0
- package/src/components/chat/DigichatLauncher.tsx +361 -0
- package/src/components/chat/DigichatThread.tsx +118 -0
- package/src/components/chat/DigichatThreadList.tsx +54 -0
- package/src/components/chat/DigichatWordmark.tsx +24 -0
- package/src/components/chat/DotMatrix.tsx +650 -0
- package/src/components/chat/boot-lab.tsx +766 -0
- package/src/components/chat/boot-signal.ts +144 -0
- package/src/components/chat/chat-surfaces.ts +52 -0
- package/src/components/chat/connection-status.ts +40 -0
- package/src/components/chat/digichat-wordmark.ts +355 -0
- package/src/components/chat/disclosure-chevron.tsx +49 -0
- package/src/components/chat/followable-href.ts +9 -0
- package/src/components/chat/gallery-thread/action-icons.tsx +25 -0
- package/src/components/chat/gallery-thread/attachment.aui.tsx +262 -0
- package/src/components/chat/gallery-thread/block-caret.tsx +439 -0
- package/src/components/chat/gallery-thread/cn.ts +1 -0
- package/src/components/chat/gallery-thread/composer-keyboard.ts +106 -0
- package/src/components/chat/gallery-thread/composer-trigger-popover.aui.tsx +235 -0
- package/src/components/chat/gallery-thread/css.d.ts +6 -0
- package/src/components/chat/gallery-thread/file.tsx +238 -0
- package/src/components/chat/gallery-thread/follow-up-suggestions.aui.tsx +92 -0
- package/src/components/chat/gallery-thread/format-json-dump.ts +112 -0
- package/src/components/chat/gallery-thread/hooks/use-attachment-src.ts +46 -0
- package/src/components/chat/gallery-thread/hooks/use-copy-to-clipboard.ts +9 -0
- package/src/components/chat/gallery-thread/image.tsx +519 -0
- package/src/components/chat/gallery-thread/markdown-text.tsx +278 -0
- package/src/components/chat/gallery-thread/message-error.aui.tsx +105 -0
- package/src/components/chat/gallery-thread/message-timing.aui.tsx +143 -0
- package/src/components/chat/gallery-thread/private-work-step.tsx +188 -0
- package/src/components/chat/gallery-thread/reasoning.tsx +332 -0
- package/src/components/chat/gallery-thread/scroll-mode.ts +174 -0
- package/src/components/chat/gallery-thread/source.tsx +76 -0
- package/src/components/chat/gallery-thread/thread.aui.tsx +1619 -0
- package/src/components/chat/gallery-thread/tooltip-icon-button.tsx +53 -0
- package/src/components/chat/gallery-thread/typed-welcome-copy.tsx +18 -0
- package/src/components/chat/gallery-thread/ui/tooltip.tsx +22 -0
- package/src/components/chat/gallery-thread/work-chain-summary.tsx +48 -0
- package/src/components/chat/gallery-thread/work-chain.tsx +110 -0
- package/src/components/chat/gallery-thread/work-status.ts +66 -0
- package/src/components/chat/overlay-scrollbar.tsx +86 -0
- package/src/components/chat/sanitize-mermaid-svg.ts +38 -0
- package/src/components/chat/skins/SOURCE.md +36 -0
- package/src/components/chat/skins/base/attachment.aui.tsx +287 -0
- package/src/components/chat/skins/base/aui-default/README.md +45 -0
- package/src/components/chat/skins/base/aui-default/collapsible-root.tsx +19 -0
- package/src/components/chat/skins/base/aui-default/collapsible.tsx +21 -0
- package/src/components/chat/skins/base/aui-default/reasoning.aui.tsx +120 -0
- package/src/components/chat/skins/base/aui-default/reasoning.tsx +331 -0
- package/src/components/chat/skins/base/aui-default/surfaces.ts +7 -0
- package/src/components/chat/skins/base/aui-default/tool-fallback.aui.tsx +772 -0
- package/src/components/chat/skins/base/aui-default/tool-group.aui.tsx +241 -0
- package/src/components/chat/skins/base/docs-model-options.ts +6 -0
- package/src/components/chat/skins/base/elements/assistant-trace.aui.tsx +169 -0
- package/src/components/chat/skins/base/elements/composer-trigger-popover.aui.tsx +271 -0
- package/src/components/chat/skins/base/elements/directive-text.aui.tsx +29 -0
- package/src/components/chat/skins/base/elements/directive-text.tsx +76 -0
- package/src/components/chat/skins/base/elements/message-timing.aui.tsx +104 -0
- package/src/components/chat/skins/base/elements/model-selector.aui.tsx +140 -0
- package/src/components/chat/skins/base/elements/model-selector.tsx +720 -0
- package/src/components/chat/skins/base/elements/quote.aui.tsx +290 -0
- package/src/components/chat/skins/base/elements/work-chain.tsx +100 -0
- package/src/components/chat/skins/base/markdown-text.tsx +294 -0
- package/src/components/chat/skins/base/model.ts +1 -0
- package/src/components/chat/skins/base/thread.tsx +1050 -0
- package/src/components/chat/skins/base/tooltip-icon-button.tsx +56 -0
- package/src/components/chat/skins/base/ui/avatar.tsx +115 -0
- package/src/components/chat/skins/base/ui/badge.tsx +51 -0
- package/src/components/chat/skins/base/ui/button.tsx +67 -0
- package/src/components/chat/skins/base/ui/command.tsx +185 -0
- package/src/components/chat/skins/base/ui/dialog.tsx +168 -0
- package/src/components/chat/skins/base/ui/dot-matrix.tsx +267 -0
- package/src/components/chat/skins/base/ui/popover.tsx +97 -0
- package/src/components/chat/skins/base/ui/skeleton.tsx +20 -0
- package/src/components/chat/skins/base/ui/textarea.tsx +24 -0
- package/src/components/chat/skins/base/ui/tooltip.tsx +73 -0
- package/src/components/chat/skins/base-assistant-ui/config-provider.tsx +90 -0
- package/src/components/chat/skins/base-assistant-ui/defaults.ts +419 -0
- package/src/components/chat/skins/base-assistant-ui/index.tsx +44 -0
- package/src/components/chat/skins/chatgpt.tsx +448 -0
- package/src/components/chat/skins/claude.tsx +380 -0
- package/src/components/chat/skins/digichat-composer-toolbar.tsx +151 -0
- package/src/components/chat/skins/digichat-context-meter-shares.ts +158 -0
- package/src/components/chat/skins/digichat-context-meter.tsx +243 -0
- package/src/components/chat/skins/digichat-meter-tone.ts +26 -0
- package/src/components/chat/skins/digichat-usage-meter.tsx +103 -0
- package/src/components/chat/skins/digichat.tsx +144 -0
- package/src/components/chat/skins/expo-react-native.tsx +29 -0
- package/src/components/chat/skins/gemini.tsx +322 -0
- package/src/components/chat/skins/grok-icon.tsx +34 -0
- package/src/components/chat/skins/grok.tsx +369 -0
- package/src/components/chat/skins/index.ts +46 -0
- package/src/components/chat/skins/perplexity.tsx +462 -0
- package/src/components/chat/skins/product-page-assistant/assistant-modal.tsx +73 -0
- package/src/components/chat/skins/product-page-assistant/index.tsx +19 -0
- package/src/components/chat/skins/product-page-assistant/product-dashboard.tsx +164 -0
- package/src/components/chat/skins/react-ink.tsx +97 -0
- package/src/components/chat/skins/thread-skin-host-contract.ts +102 -0
- package/src/components/chat/skins/thread-skin-view.tsx +156 -0
- package/src/components/chat/skins/thread-skins.ts +143 -0
- package/src/components/chat/skins/tooltip-icon-button.tsx +35 -0
- package/src/components/chat/skins/ui/dropdown-menu.tsx +272 -0
- package/src/components/chat/skins/webpage-assistant/assistant-config.ts +238 -0
- package/src/components/chat/skins/webpage-assistant/assistant-modal.tsx +78 -0
- package/src/components/chat/skins/webpage-assistant/config-provider.tsx +132 -0
- package/src/components/chat/skins/webpage-assistant/docs-app.tsx +106 -0
- package/src/components/chat/skins/webpage-assistant/docs-article.tsx +109 -0
- package/src/components/chat/skins/webpage-assistant/docs-assistant.tsx +73 -0
- package/src/components/chat/skins/webpage-assistant/docs-nav.tsx +81 -0
- package/src/components/chat/skins/webpage-assistant/host-ui.ts +79 -0
- package/src/components/chat/skins/webpage-assistant/index.tsx +12 -0
- package/src/components/chat/skins/webpage-assistant/markdown-page.tsx +11 -0
- package/src/components/chat/skins/webpage-assistant/pages.ts +9 -0
- package/src/components/chat/skins/webpage-assistant/types.ts +178 -0
- package/src/components/chat/skins/webpage-assistant/use-mobile.ts +19 -0
- package/src/components/chat/stock/SOURCE.md +90 -0
- package/src/components/chat/stock/artifacts-panel.tsx +305 -0
- package/src/components/chat/stock/attachment.aui.tsx +280 -0
- package/src/components/chat/stock/chat-notice.tsx +143 -0
- package/src/components/chat/stock/chat-private-mode.tsx +64 -0
- package/src/components/chat/stock/deploy-ui-context.tsx +89 -0
- package/src/components/chat/stock/embed-chat-prefs.tsx +471 -0
- package/src/components/chat/stock/file.tsx +265 -0
- package/src/components/chat/stock/follow-up-suggestions.aui.tsx +83 -0
- package/src/components/chat/stock/image.tsx +531 -0
- package/src/components/chat/stock/index.ts +129 -0
- package/src/components/chat/stock/json-view.tsx +140 -0
- package/src/components/chat/stock/markdown-text.tsx +319 -0
- package/src/components/chat/stock/message-error.aui.tsx +96 -0
- package/src/components/chat/stock/message-export-menu.tsx +156 -0
- package/src/components/chat/stock/palette-row-preview.tsx +26 -0
- package/src/components/chat/stock/reasoning.aui.tsx +120 -0
- package/src/components/chat/stock/reasoning.tsx +335 -0
- package/src/components/chat/stock/skin-chrome.tsx +81 -0
- package/src/components/chat/stock/skin-credit.tsx +63 -0
- package/src/components/chat/stock/skin-palette-bridge.tsx +235 -0
- package/src/components/chat/stock/skin-palette-context.ts +16 -0
- package/src/components/chat/stock/skin-runtime.tsx +52 -0
- package/src/components/chat/stock/skin-slash-palette.tsx +393 -0
- package/src/components/chat/stock/skin-types.ts +217 -0
- package/src/components/chat/stock/stock-chat-prefs-host.tsx +501 -0
- package/src/components/chat/stock/stock-send-gate.tsx +94 -0
- package/src/components/chat/stock/stock-shape.tsx +39 -0
- package/src/components/chat/stock/thread.aui.tsx +645 -0
- package/src/components/chat/stock/tool-display.ts +6 -0
- package/src/components/chat/stock/tool-fallback.aui.tsx +866 -0
- package/src/components/chat/stock/tool-group.aui.tsx +244 -0
- package/src/components/chat/stock/tool-surface.ts +120 -0
- package/src/components/chat/stock/tooltip-icon-button.tsx +49 -0
- package/src/components/chat/stock/ui/avatar.tsx +108 -0
- package/src/components/chat/stock/ui/button.tsx +81 -0
- package/src/components/chat/stock/ui/collapsible.tsx +21 -0
- package/src/components/chat/stock/ui/dialog.tsx +163 -0
- package/src/components/chat/stock/ui/skeleton.tsx +13 -0
- package/src/components/chat/stock/ui/textarea.tsx +20 -0
- package/src/components/chat/stock/ui/tooltip.tsx +68 -0
- package/src/components/chat/stock/use-attachment-src.ts +42 -0
- package/src/components/chat/stock/use-copy-to-clipboard.ts +29 -0
- package/src/components/chat/strip-model-boilerplate.ts +42 -0
- package/src/components/chat/suggestion-cycle.tsx +230 -0
- package/src/components/chat/suggestion-scroll-row.tsx +81 -0
- package/src/components/chat/trace-grouping/chain-group-by.ts +44 -0
- package/src/components/chat/trace-grouping/chain-state.ts +141 -0
- package/src/components/chat/trace-grouping/index.ts +32 -0
- package/src/components/chat/trace-grouping/tool-row.ts +74 -0
- package/src/components/chat/trace-grouping/use-deploy-work-disclosure.ts +35 -0
- package/src/components/chat/trace-grouping/use-work-chain.ts +103 -0
- package/src/components/chat/trace-i18n/core.ts +48 -0
- package/src/components/chat/trace-i18n/index.tsx +23 -0
- package/src/components/chat/trace-i18n/locales/en.ts +24 -0
- package/src/components/chat/trace-i18n/locales/fr.ts +28 -0
- package/src/components/chat/trace-i18n/types.ts +35 -0
- package/src/components/chat/trace-spacing.ts +249 -0
- package/src/components/chat/transcript/activity-view.ts +375 -0
- package/src/components/chat/transcript/chat-export.ts +133 -0
- package/src/components/chat/transcript/index.ts +10 -0
- package/src/components/chat/transcript/save-file.ts +209 -0
- package/src/components/chat/transcript/transcript-markdown.ts +428 -0
- package/src/components/chat/transcript/types.ts +81 -0
- package/src/components/chat/turn-outcome.ts +52 -0
- package/src/components/chat/use-warmup-phase.ts +18 -0
- package/src/components/chat/work-status-lead.tsx +49 -0
- package/src/components/chrome.tsx +264 -0
- package/src/components/command-palette/CommandPalette.tsx +404 -0
- package/src/components/command-palette/index.ts +6 -0
- package/src/components/contact/ContactMailto.tsx +112 -0
- package/src/components/contact/index.ts +5 -0
- package/src/components/conviction/ConvictionMeter.tsx +40 -0
- package/src/components/conviction/SignedConvictionBadge.tsx +26 -0
- package/src/components/conviction/index.ts +7 -0
- package/src/components/data-layout/BentoGrid.tsx +52 -0
- package/src/components/data-layout/CardRail.tsx +150 -0
- package/src/components/data-layout/DotMatrixStat.tsx +65 -0
- package/src/components/data-layout/FeatureCell.tsx +80 -0
- package/src/components/data-layout/MediaFrame.tsx +125 -0
- package/src/components/data-layout/ModuleGrid.tsx +735 -0
- package/src/components/data-layout/Odometer.tsx +149 -0
- package/src/components/data-layout/ProductFrame.tsx +79 -0
- package/src/components/data-layout/TestimonialWall.tsx +139 -0
- package/src/components/data-layout/index.ts +19 -0
- package/src/components/data-layout/treemap.ts +368 -0
- package/src/components/deck/DeckStack.tsx +243 -0
- package/src/components/desk/DataTable.tsx +373 -0
- package/src/components/desk/KpiGrid.tsx +80 -0
- package/src/components/desk/Sparkline.tsx +63 -0
- package/src/components/desk/StateBlock.tsx +132 -0
- package/src/components/desk/index.ts +18 -0
- package/src/components/diagrams/ArchitectureDiagram.tsx +350 -0
- package/src/components/diagrams/ArchitectureTour.tsx +912 -0
- package/src/components/diagrams/TerminalSchematic.tsx +192 -0
- package/src/components/diagrams/architecture-svg.tsx +384 -0
- package/src/components/diagrams/index.ts +30 -0
- package/src/components/diagrams/mermaid-theme.ts +115 -0
- package/src/components/diagrams/tour-camera.ts +171 -0
- package/src/components/docs/CodeTabs.tsx +90 -0
- package/src/components/docs/CopyCommand.tsx +151 -0
- package/src/components/docs/DocsLayout.tsx +197 -0
- package/src/components/docs/DocsSearch.tsx +97 -0
- package/src/components/docs/Endpoint.tsx +135 -0
- package/src/components/document/DocumentFrame.tsx +43 -0
- package/src/components/document/GlyphList.tsx +51 -0
- package/src/components/document/PageTitle.tsx +44 -0
- package/src/components/document/Prose.tsx +38 -0
- package/src/components/document/Section.tsx +55 -0
- package/src/components/document/index.ts +13 -0
- package/src/components/effects-chrome/AnnouncementBar.tsx +88 -0
- package/src/components/effects-chrome/HorizontalScrollTrack.tsx +461 -0
- package/src/components/effects-chrome/Pipeline.tsx +226 -0
- package/src/components/effects-chrome/RotatingPrompts.tsx +116 -0
- package/src/components/effects-chrome/StackingPanels.tsx +101 -0
- package/src/components/effects-chrome/TabStrip.tsx +232 -0
- package/src/components/effects-chrome/ToastStack.tsx +201 -0
- package/src/components/effects-chrome/horizontal-track-core.ts +70 -0
- package/src/components/effects-chrome/index.ts +35 -0
- package/src/components/emblems.tsx +188 -0
- package/src/components/faviconTheme.ts +23 -0
- package/src/components/figure/Figure.tsx +38 -0
- package/src/components/figure/index.ts +2 -0
- package/src/components/finance-charts/DrawdownPlot.tsx +76 -0
- package/src/components/finance-charts/EquityCurve.tsx +71 -0
- package/src/components/finance-charts/PriceChart.tsx +119 -0
- package/src/components/finance-charts/chart-host.tsx +236 -0
- package/src/components/finance-charts/chart-scale.ts +93 -0
- package/src/components/finance-charts/demo-data.ts +88 -0
- package/src/components/finance-charts/index.ts +46 -0
- package/src/components/finance-charts/lw-chart.tsx +292 -0
- package/src/components/finance-composites/MarketBar.tsx +243 -0
- package/src/components/finance-composites/OrderBook.tsx +133 -0
- package/src/components/finance-composites/PerformanceDashboard.tsx +185 -0
- package/src/components/finance-composites/SortableTable.tsx +144 -0
- package/src/components/finance-composites/StockTicker.tsx +65 -0
- package/src/components/finance-composites/SyncedTearsheet.tsx +226 -0
- package/src/components/finance-composites/index.ts +28 -0
- package/src/components/finance-tearsheet/KpiStrip.tsx +49 -0
- package/src/components/finance-tearsheet/LiveBadge.tsx +29 -0
- package/src/components/finance-tearsheet/ReturnsMatrix.tsx +321 -0
- package/src/components/finance-tearsheet/StrategyTearsheet.tsx +99 -0
- package/src/components/finance-tearsheet/TearsheetCard.tsx +54 -0
- package/src/components/finance-tearsheet/TradeLogTable.tsx +73 -0
- package/src/components/finance-tearsheet/charts.tsx +2624 -0
- package/src/components/finance-tearsheet/demo-data.ts +177 -0
- package/src/components/finance-tearsheet/format.ts +41 -0
- package/src/components/finance-tearsheet/index.ts +120 -0
- package/src/components/finance-tearsheet/print.ts +52 -0
- package/src/components/finance-tearsheet/risk-bands.ts +48 -0
- package/src/components/finance-tearsheet/stats.ts +35 -0
- package/src/components/finance-tearsheet/strategy-sheet-model.ts +238 -0
- package/src/components/finance-tearsheet/types.ts +58 -0
- package/src/components/footer/FooterCells.tsx +109 -0
- package/src/components/footer/index.ts +6 -0
- package/src/components/graph.tsx +158 -0
- package/src/components/icons.tsx +98 -0
- package/src/components/landing/PixelWordmark.tsx +36 -0
- package/src/components/logos.ts +39 -0
- package/src/components/marquee/Marquee.tsx +204 -0
- package/src/components/metrics/PerfMetrics.tsx +68 -0
- package/src/components/metrics/StatCounter.tsx +104 -0
- package/src/components/page-geometry.tsx +177 -0
- package/src/components/pricing/Pricing.tsx +174 -0
- package/src/components/pricing/PricingMatrix.tsx +219 -0
- package/src/components/prose/index.ts +2 -0
- package/src/components/prose/prose.tsx +86 -0
- package/src/components/repo-activity/RepoActivity.tsx +599 -0
- package/src/components/repo-activity/RepoHeatmap.tsx +225 -0
- package/src/components/repo-activity/demo.ts +201 -0
- package/src/components/repo-activity/fetch.ts +211 -0
- package/src/components/repo-activity/heatmap.ts +123 -0
- package/src/components/repo-activity/index.ts +28 -0
- package/src/components/repo-activity/types.ts +99 -0
- package/src/components/stages/NumberedStages.tsx +116 -0
- package/src/components/symbols/marks.tsx +116 -0
- package/src/components/symbols/terminal-lockup.tsx +136 -0
- package/src/components/symbols/terminal-marks.tsx +226 -0
- package/src/components/terminal/ChatResponseLoader.tsx +67 -0
- package/src/components/terminal/ContainerBootLoader.tsx +82 -0
- package/src/components/terminal/TerminalStepCaret.tsx +202 -0
- package/src/components/themeInit.ts +24 -0
- package/src/components/typography/MotionReveal.tsx +108 -0
- package/src/components/typography/TypewriterReveal.tsx +101 -0
- package/src/components/typography/WordReveal.tsx +143 -0
- package/src/data/modules.ts +378 -0
- package/src/data/subsystems.ts +101 -0
- package/src/index.ts +587 -0
- package/src/lib/base-path.ts +60 -0
- package/src/lib/cx.ts +25 -0
- package/src/lib/gloomberb.ts +69 -0
- package/src/lib/record.ts +19 -0
- package/src/lib/stub-payload.ts +183 -0
- package/src/lib/useBodyScrollLock.ts +44 -0
- package/src/lib/utils.ts +6 -0
- package/src/motion/primitives.tsx +105 -0
- package/src/motion/scroll-glide.ts +62 -0
- package/src/motion/scrolly-core.ts +38 -0
- package/src/motion/scrolly.tsx +95 -0
- package/src/navigation/HashScrollManager.tsx +167 -0
- package/src/navigation/hashScroll.ts +78 -0
- package/src/replay/browser.ts +280 -0
- package/src/replay/chat-export-run.ts +121 -0
- package/src/replay/export-format.ts +25 -0
- package/src/replay/export-mount.ts +32 -0
- package/src/replay/filename.ts +54 -0
- package/src/replay/index.ts +21 -0
- package/src/replay/redact-dom.ts +178 -0
- package/src/replay/redact.ts +113 -0
- package/src/replay/snapshot.ts +659 -0
- package/src/styles/account-auth.css +339 -0
- package/src/styles/brand-wordmark.css +11 -0
- package/src/styles/card-rail.css +120 -0
- package/src/styles/chat-aui.css +1143 -0
- package/src/styles/chat-core.css +469 -0
- package/src/styles/chat-digichat.css +2531 -0
- package/src/styles/chat-math.css +70 -0
- package/src/styles/chat-skin-palette.css +138 -0
- package/src/styles/chat-stock-menu.css +37 -0
- package/src/styles/chat-widgets.css +190 -0
- package/src/styles/command-palette.css +372 -0
- package/src/styles/controls-core.css +2261 -0
- package/src/styles/controls-overlay.css +603 -0
- package/src/styles/data-layout.css +288 -0
- package/src/styles/deck.css +141 -0
- package/src/styles/diagrams.css +1860 -0
- package/src/styles/digichat-app-theme.css +250 -0
- package/src/styles/digichat-boot-loader.css +487 -0
- package/src/styles/digichat-launcher.css +377 -0
- package/src/styles/docs.css +165 -0
- package/src/styles/effects-chrome.css +888 -0
- package/src/styles/finance-composites.css +214 -0
- package/src/styles/finance-tearsheet-overlay.css +90 -0
- package/src/styles/finance-tearsheet.css +945 -0
- package/src/styles/marquee.css +168 -0
- package/src/styles/metrics.css +82 -0
- package/src/styles/nav-shell.css +551 -0
- package/src/styles/pricing.css +79 -0
- package/src/styles/repo-activity.css +575 -0
- package/src/styles/stages.css +69 -0
- package/src/styles/terminal-loaders.css +122 -0
- package/src/styles/terminal-manifest.css +228 -0
- package/src/styles/web-theme.css +1007 -0
- package/src/styles/word-reveal.css +204 -0
- package/src/theme/apply-theme.ts +214 -0
- package/src/theme/index.ts +27 -0
- package/src/theme/palette-registry.ts +855 -0
- package/src/theme/tui-prefs.ts +64 -0
- package/src/ui/alert.tsx +78 -0
- package/src/ui/avatar.tsx +104 -0
- package/src/ui/badge.tsx +75 -0
- package/src/ui/breadcrumb.tsx +61 -0
- package/src/ui/button.tsx +67 -0
- package/src/ui/card.tsx +139 -0
- package/src/ui/checkbox.tsx +27 -0
- package/src/ui/collapsible.tsx +32 -0
- package/src/ui/date-pager.tsx +325 -0
- package/src/ui/dialog.tsx +157 -0
- package/src/ui/dropdown-menu.tsx +267 -0
- package/src/ui/empty-state.tsx +165 -0
- package/src/ui/field.tsx +104 -0
- package/src/ui/form.tsx +36 -0
- package/src/ui/icon-button.tsx +36 -0
- package/src/ui/index.ts +34 -0
- package/src/ui/input.tsx +33 -0
- package/src/ui/kbd.tsx +30 -0
- package/src/ui/label.tsx +32 -0
- package/src/ui/pager.tsx +119 -0
- package/src/ui/pagination.tsx +126 -0
- package/src/ui/radio-group.tsx +51 -0
- package/src/ui/search-bar.tsx +85 -0
- package/src/ui/segmented-control.tsx +76 -0
- package/src/ui/select.tsx +257 -0
- package/src/ui/separator.tsx +24 -0
- package/src/ui/sheet.tsx +141 -0
- package/src/ui/skeleton.tsx +76 -0
- package/src/ui/slider.tsx +76 -0
- package/src/ui/switch.tsx +31 -0
- package/src/ui/table.tsx +179 -0
- package/src/ui/tabs.tsx +89 -0
- package/src/ui/tags-input.tsx +168 -0
- package/src/ui/textarea.tsx +17 -0
- package/src/ui/tooltip.tsx +71 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { renderMermaidSVG } from "beautiful-mermaid";
|
|
4
|
+
import { Maximize2, Minus, Plus, RotateCcw, X } from "lucide-react";
|
|
5
|
+
import {
|
|
6
|
+
type FC,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
memo,
|
|
9
|
+
useCallback,
|
|
10
|
+
useEffect,
|
|
11
|
+
useMemo,
|
|
12
|
+
useRef,
|
|
13
|
+
useState,
|
|
14
|
+
} from "react";
|
|
15
|
+
import { createPortal } from "react-dom";
|
|
16
|
+
import { sanitizeMermaidSvg } from "../../chat/sanitize-mermaid-svg";
|
|
17
|
+
import { cn } from "../../chat/gallery-thread/cn";
|
|
18
|
+
|
|
19
|
+
export type MermaidDiagramProps = {
|
|
20
|
+
code: string;
|
|
21
|
+
className?: string;
|
|
22
|
+
/** Renders a skeleton instead of the diagram while `true`. */
|
|
23
|
+
streaming?: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const MIN_SCALE = 0.5;
|
|
27
|
+
const MAX_SCALE = 4;
|
|
28
|
+
|
|
29
|
+
type MermaidZoomProps = {
|
|
30
|
+
svg: string;
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function MermaidZoom({ svg, children }: MermaidZoomProps) {
|
|
35
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
36
|
+
const [transform, setTransform] = useState({ x: 0, y: 0, scale: 1 });
|
|
37
|
+
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
38
|
+
const closeRef = useRef<HTMLButtonElement>(null);
|
|
39
|
+
const overlayRef = useRef<HTMLDivElement>(null);
|
|
40
|
+
const viewportRef = useRef<HTMLDivElement>(null);
|
|
41
|
+
const drag = useRef<{
|
|
42
|
+
startX: number;
|
|
43
|
+
startY: number;
|
|
44
|
+
originX: number;
|
|
45
|
+
originY: number;
|
|
46
|
+
} | null>(null);
|
|
47
|
+
const transformRef = useRef(transform);
|
|
48
|
+
transformRef.current = transform;
|
|
49
|
+
|
|
50
|
+
const zoomSvg = useMemo(
|
|
51
|
+
() =>
|
|
52
|
+
sanitizeMermaidSvg(
|
|
53
|
+
svg
|
|
54
|
+
.replace(/id="([^"]+)"/g, 'id="$1-zoom"')
|
|
55
|
+
.replace(/url\(#([^)]+)\)/g, "url(#$1-zoom)")
|
|
56
|
+
.replace(/(href|xlink:href)="#([^"]+)"/g, '$1="#$2-zoom"'),
|
|
57
|
+
),
|
|
58
|
+
[svg],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const handleClose = useCallback(() => {
|
|
62
|
+
setIsOpen(false);
|
|
63
|
+
setTransform({ x: 0, y: 0, scale: 1 });
|
|
64
|
+
triggerRef.current?.focus();
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (!isOpen) return;
|
|
69
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
70
|
+
if (e.key === "Escape") {
|
|
71
|
+
handleClose();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (e.key !== "Tab") return;
|
|
75
|
+
const focusables = overlayRef.current?.querySelectorAll<HTMLElement>(
|
|
76
|
+
'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])',
|
|
77
|
+
);
|
|
78
|
+
const first = focusables?.[0];
|
|
79
|
+
const last = focusables?.[focusables.length - 1];
|
|
80
|
+
if (!first || !last) return;
|
|
81
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
last.focus();
|
|
84
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
first.focus();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
90
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
91
|
+
}, [isOpen, handleClose]);
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (!isOpen) return;
|
|
95
|
+
const originalOverflow = document.body.style.overflow;
|
|
96
|
+
document.body.style.overflow = "hidden";
|
|
97
|
+
return () => {
|
|
98
|
+
document.body.style.overflow = originalOverflow;
|
|
99
|
+
};
|
|
100
|
+
}, [isOpen]);
|
|
101
|
+
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (isOpen) closeRef.current?.focus();
|
|
104
|
+
}, [isOpen]);
|
|
105
|
+
|
|
106
|
+
const zoomBy = useCallback((factor: number, cx?: number, cy?: number) => {
|
|
107
|
+
setTransform((t) => {
|
|
108
|
+
const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, t.scale * factor));
|
|
109
|
+
const ratio = scale / t.scale;
|
|
110
|
+
if (cx === undefined || cy === undefined) {
|
|
111
|
+
const viewport = viewportRef.current;
|
|
112
|
+
cx = (viewport?.clientWidth ?? 0) / 2;
|
|
113
|
+
cy = (viewport?.clientHeight ?? 0) / 2;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
scale,
|
|
117
|
+
x: cx - (cx - t.x) * ratio,
|
|
118
|
+
y: cy - (cy - t.y) * ratio,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
const onWheel = useCallback(
|
|
124
|
+
(e: React.WheelEvent) => {
|
|
125
|
+
const viewport = viewportRef.current;
|
|
126
|
+
if (!viewport) return;
|
|
127
|
+
const rect = viewport.getBoundingClientRect();
|
|
128
|
+
zoomBy(
|
|
129
|
+
Math.exp(-e.deltaY * 0.0015),
|
|
130
|
+
e.clientX - rect.left,
|
|
131
|
+
e.clientY - rect.top,
|
|
132
|
+
);
|
|
133
|
+
},
|
|
134
|
+
[zoomBy],
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const onPointerDown = useCallback((e: React.PointerEvent) => {
|
|
138
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
139
|
+
const t = transformRef.current;
|
|
140
|
+
drag.current = {
|
|
141
|
+
startX: e.clientX,
|
|
142
|
+
startY: e.clientY,
|
|
143
|
+
originX: t.x,
|
|
144
|
+
originY: t.y,
|
|
145
|
+
};
|
|
146
|
+
}, []);
|
|
147
|
+
|
|
148
|
+
const onPointerMove = useCallback((e: React.PointerEvent) => {
|
|
149
|
+
const d = drag.current;
|
|
150
|
+
if (!d) return;
|
|
151
|
+
setTransform((t) => ({
|
|
152
|
+
...t,
|
|
153
|
+
x: d.originX + e.clientX - d.startX,
|
|
154
|
+
y: d.originY + e.clientY - d.startY,
|
|
155
|
+
}));
|
|
156
|
+
}, []);
|
|
157
|
+
|
|
158
|
+
const onPointerUp = useCallback(() => {
|
|
159
|
+
drag.current = null;
|
|
160
|
+
}, []);
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<div
|
|
164
|
+
data-slot="mermaid-zoom-wrap"
|
|
165
|
+
className="aui-mermaid-zoom-wrap group/mermaid relative"
|
|
166
|
+
>
|
|
167
|
+
{children}
|
|
168
|
+
<button
|
|
169
|
+
ref={triggerRef}
|
|
170
|
+
type="button"
|
|
171
|
+
data-slot="mermaid-zoom-trigger"
|
|
172
|
+
aria-label="Expand diagram"
|
|
173
|
+
onClick={() => setIsOpen(true)}
|
|
174
|
+
className="aui-mermaid-zoom-trigger text-muted-foreground hover:text-foreground hover:border-muted-foreground/70 border-border bg-background absolute top-2 end-2 cursor-pointer rounded-md border p-1.5 opacity-0 transition group-hover/mermaid:opacity-100 focus-visible:opacity-100"
|
|
175
|
+
>
|
|
176
|
+
<Maximize2 className="size-3.5" />
|
|
177
|
+
</button>
|
|
178
|
+
{isOpen &&
|
|
179
|
+
createPortal(
|
|
180
|
+
<div
|
|
181
|
+
ref={overlayRef}
|
|
182
|
+
data-slot="mermaid-zoom-overlay"
|
|
183
|
+
role="dialog"
|
|
184
|
+
aria-modal="true"
|
|
185
|
+
aria-label="Diagram"
|
|
186
|
+
className="aui-mermaid-zoom-overlay fade-in animate-in bg-background fixed inset-0 z-50 duration-200"
|
|
187
|
+
>
|
|
188
|
+
<div
|
|
189
|
+
ref={viewportRef}
|
|
190
|
+
className="aui-mermaid-zoom-viewport h-full w-full cursor-grab touch-none overflow-hidden active:cursor-grabbing"
|
|
191
|
+
onWheel={onWheel}
|
|
192
|
+
onPointerDown={onPointerDown}
|
|
193
|
+
onPointerMove={onPointerMove}
|
|
194
|
+
onPointerUp={onPointerUp}
|
|
195
|
+
onPointerCancel={onPointerUp}
|
|
196
|
+
>
|
|
197
|
+
<div
|
|
198
|
+
data-slot="mermaid-zoom-content"
|
|
199
|
+
className="aui-mermaid-zoom-content flex h-full w-full items-center justify-center [&_svg]:max-h-[80vh] [&_svg]:max-w-[90vw]"
|
|
200
|
+
style={{
|
|
201
|
+
transform: `translate(${transform.x}px, ${transform.y}px) scale(${transform.scale})`,
|
|
202
|
+
transformOrigin: "0 0",
|
|
203
|
+
}}
|
|
204
|
+
dangerouslySetInnerHTML={{ __html: zoomSvg }}
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
<div
|
|
208
|
+
data-slot="mermaid-zoom-toolbar"
|
|
209
|
+
className="aui-mermaid-zoom-toolbar border-border bg-background absolute top-4 end-4 flex items-center gap-1 rounded-lg border p-1"
|
|
210
|
+
>
|
|
211
|
+
<button
|
|
212
|
+
type="button"
|
|
213
|
+
aria-label="Zoom in"
|
|
214
|
+
onClick={() => zoomBy(1.25)}
|
|
215
|
+
className="text-muted-foreground hover:text-foreground cursor-pointer rounded-sm p-1.5"
|
|
216
|
+
>
|
|
217
|
+
<Plus className="size-4" />
|
|
218
|
+
</button>
|
|
219
|
+
<button
|
|
220
|
+
type="button"
|
|
221
|
+
aria-label="Zoom out"
|
|
222
|
+
onClick={() => zoomBy(0.8)}
|
|
223
|
+
className="text-muted-foreground hover:text-foreground cursor-pointer rounded-sm p-1.5"
|
|
224
|
+
>
|
|
225
|
+
<Minus className="size-4" />
|
|
226
|
+
</button>
|
|
227
|
+
<button
|
|
228
|
+
type="button"
|
|
229
|
+
aria-label="Reset zoom"
|
|
230
|
+
onClick={() => setTransform({ x: 0, y: 0, scale: 1 })}
|
|
231
|
+
className="text-muted-foreground hover:text-foreground cursor-pointer rounded-sm p-1.5"
|
|
232
|
+
>
|
|
233
|
+
<RotateCcw className="size-4" />
|
|
234
|
+
</button>
|
|
235
|
+
<button
|
|
236
|
+
ref={closeRef}
|
|
237
|
+
type="button"
|
|
238
|
+
aria-label="Close"
|
|
239
|
+
onClick={handleClose}
|
|
240
|
+
className="text-muted-foreground hover:text-foreground cursor-pointer rounded-sm p-1.5"
|
|
241
|
+
>
|
|
242
|
+
<X className="size-4" />
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
</div>,
|
|
246
|
+
document.body,
|
|
247
|
+
)}
|
|
248
|
+
</div>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const MermaidDiagramImpl: FC<MermaidDiagramProps> = ({
|
|
253
|
+
code,
|
|
254
|
+
className,
|
|
255
|
+
streaming = false,
|
|
256
|
+
}) => {
|
|
257
|
+
const result = useMemo(() => {
|
|
258
|
+
if (streaming) return null;
|
|
259
|
+
try {
|
|
260
|
+
return {
|
|
261
|
+
svg: sanitizeMermaidSvg(
|
|
262
|
+
renderMermaidSVG(code, {
|
|
263
|
+
bg: "var(--background)",
|
|
264
|
+
fg: "var(--foreground)",
|
|
265
|
+
muted: "var(--muted-foreground)",
|
|
266
|
+
border: "var(--border)",
|
|
267
|
+
accent: "var(--foreground)",
|
|
268
|
+
transparent: true,
|
|
269
|
+
}),
|
|
270
|
+
),
|
|
271
|
+
error: null,
|
|
272
|
+
};
|
|
273
|
+
} catch (err) {
|
|
274
|
+
return {
|
|
275
|
+
svg: null,
|
|
276
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}, [streaming, code]);
|
|
280
|
+
|
|
281
|
+
if (!result) {
|
|
282
|
+
return (
|
|
283
|
+
<div
|
|
284
|
+
data-slot="mermaid-skeleton"
|
|
285
|
+
aria-label="Rendering diagram"
|
|
286
|
+
className={cn(
|
|
287
|
+
"aui-mermaid-skeleton bg-muted flex h-32 animate-pulse items-center justify-center gap-3 rounded-b-lg p-4",
|
|
288
|
+
className,
|
|
289
|
+
)}
|
|
290
|
+
>
|
|
291
|
+
<div className="bg-muted-foreground/20 h-8 w-20 rounded-md" />
|
|
292
|
+
<div className="bg-muted-foreground/20 h-px w-10" />
|
|
293
|
+
<div className="bg-muted-foreground/20 h-8 w-20 rounded-md" />
|
|
294
|
+
<div className="bg-muted-foreground/20 h-px w-10" />
|
|
295
|
+
<div className="bg-muted-foreground/20 h-8 w-20 rounded-md" />
|
|
296
|
+
</div>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (result.error) {
|
|
301
|
+
return (
|
|
302
|
+
<div
|
|
303
|
+
data-slot="mermaid-fallback"
|
|
304
|
+
className={cn(
|
|
305
|
+
"aui-mermaid-fallback bg-muted/75 rounded-b-lg",
|
|
306
|
+
className,
|
|
307
|
+
)}
|
|
308
|
+
>
|
|
309
|
+
<pre className="overflow-x-auto p-4 text-sm">{code.trim()}</pre>
|
|
310
|
+
<p className="text-muted-foreground border-border border-t px-4 py-1.5 text-xs">
|
|
311
|
+
diagram could not be rendered
|
|
312
|
+
</p>
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return (
|
|
318
|
+
<MermaidZoom svg={result.svg}>
|
|
319
|
+
<div
|
|
320
|
+
data-slot="mermaid-diagram"
|
|
321
|
+
className={cn(
|
|
322
|
+
"aui-mermaid-diagram bg-muted overflow-x-auto rounded-b-lg p-2 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full",
|
|
323
|
+
className,
|
|
324
|
+
)}
|
|
325
|
+
dangerouslySetInnerHTML={{ __html: result.svg }}
|
|
326
|
+
/>
|
|
327
|
+
</MermaidZoom>
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const MermaidDiagram = memo(
|
|
332
|
+
MermaidDiagramImpl,
|
|
333
|
+
) as unknown as FC<MermaidDiagramProps> & {
|
|
334
|
+
Zoom: typeof MermaidZoom;
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
MermaidDiagram.displayName = "MermaidDiagram";
|
|
338
|
+
MermaidDiagram.Zoom = MermaidZoom;
|
|
339
|
+
|
|
340
|
+
export { MermaidDiagram, MermaidZoom };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The digithings wordmark.
|
|
3
|
+
*
|
|
4
|
+
* Same 4×4 mask the brand studio composes
|
|
5
|
+
* (`packages/brand/studio/wordmark-mask.svg`), drawn in `currentColor`.
|
|
6
|
+
* Each app mirrors that file to `/wordmark-mask.svg` (see
|
|
7
|
+
* `packages/brand/build-studio.py`). Static on purpose: the animated build
|
|
8
|
+
* belongs to the studio, not to a page header.
|
|
9
|
+
*/
|
|
10
|
+
export function BrandWordmark({
|
|
11
|
+
className,
|
|
12
|
+
label = "digithings",
|
|
13
|
+
mask = "/wordmark-mask.svg",
|
|
14
|
+
}: {
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Accessible name. The mark is ink, not text. */
|
|
17
|
+
label?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Mask URL. Apps served under a base path pass the prefixed path; the
|
|
20
|
+
* default is the site root.
|
|
21
|
+
*/
|
|
22
|
+
mask?: string;
|
|
23
|
+
}) {
|
|
24
|
+
return (
|
|
25
|
+
<span
|
|
26
|
+
className={className ? `brand-wordmark ${className}` : "brand-wordmark"}
|
|
27
|
+
role="img"
|
|
28
|
+
aria-label={label}
|
|
29
|
+
style={{ ["--brand-wordmark" as string]: `url("${mask}")` }}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The release rail — the changelog's row grammar, OpenCode-informed: a two-column
|
|
3
|
+
* grid per release with the version, date and product pinned in a sticky aside,
|
|
4
|
+
* and the shipped title with its highlights in the wide column under a hairline.
|
|
5
|
+
* Static, so the whole changelog renders without JavaScript (D1, #4429). Generic:
|
|
6
|
+
* rows arrive as data and the caller owns the order, so a site can fold its own
|
|
7
|
+
* release source in without this part knowing where releases come from.
|
|
8
|
+
*/
|
|
9
|
+
import type { ReactNode } from "react";
|
|
10
|
+
import { cn } from "../../lib/utils";
|
|
11
|
+
|
|
12
|
+
export interface ReleaseRailItem {
|
|
13
|
+
/** The product or package the release belongs to, e.g. `digichat`. */
|
|
14
|
+
product: string;
|
|
15
|
+
/** The version as published, e.g. `v2.3.1`. */
|
|
16
|
+
version: string;
|
|
17
|
+
/** The release date, ISO `YYYY-MM-DD`. */
|
|
18
|
+
date: string;
|
|
19
|
+
/** The published title. */
|
|
20
|
+
title: string;
|
|
21
|
+
/** The release URL, so the version stays the link. */
|
|
22
|
+
href: string;
|
|
23
|
+
/** The release kind as tagged upstream, e.g. `fix` or `release`. */
|
|
24
|
+
tag?: string;
|
|
25
|
+
/** Optional highlights, one plain clause each. */
|
|
26
|
+
entries?: ReactNode[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ReleaseRailProps {
|
|
30
|
+
items: ReleaseRailItem[];
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function ReleaseRail({ items, className }: ReleaseRailProps) {
|
|
35
|
+
return (
|
|
36
|
+
<ol className={cn("m-0 grid list-none gap-0 p-0", className)}>
|
|
37
|
+
{items.map((item) => (
|
|
38
|
+
<li
|
|
39
|
+
key={`${item.product}-${item.version}`}
|
|
40
|
+
className="grid gap-[0.9rem] border-t border-hair py-[1.6rem] first:border-t-0 first:pt-0 last:pb-0 sm:grid-cols-[180px_1fr] sm:gap-[3rem]"
|
|
41
|
+
>
|
|
42
|
+
<div className="flex flex-col gap-[0.3rem] sm:sticky sm:top-[5rem] sm:self-start">
|
|
43
|
+
<a
|
|
44
|
+
href={item.href}
|
|
45
|
+
className="font-mono text-[0.9rem] font-medium text-ink underline-offset-[3px] hover:underline"
|
|
46
|
+
>
|
|
47
|
+
{item.version}
|
|
48
|
+
</a>
|
|
49
|
+
<span className="font-mono text-[length:var(--type-meta)] tracking-[0.02em] text-ink-mute">
|
|
50
|
+
<time dateTime={item.date}>{item.date}</time>
|
|
51
|
+
{item.tag ? ` · ${item.tag}` : ""}
|
|
52
|
+
</span>
|
|
53
|
+
<span className="font-mono text-[length:var(--type-meta)] tracking-[0.02em] text-ink-mute">
|
|
54
|
+
{item.product}
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div className="min-w-0">
|
|
58
|
+
<p className="m-0 text-[length:var(--type-body)] font-medium leading-[1.5] text-ink">
|
|
59
|
+
{item.title}
|
|
60
|
+
</p>
|
|
61
|
+
{item.entries && item.entries.length > 0 ? (
|
|
62
|
+
<ul className="m-0 mt-[0.8rem] grid list-none gap-[0.6rem] p-0">
|
|
63
|
+
{item.entries.map((entry, index) => (
|
|
64
|
+
<li
|
|
65
|
+
key={index}
|
|
66
|
+
className="flex gap-[0.75rem] text-[0.9rem] leading-[1.7] text-ink-soft"
|
|
67
|
+
>
|
|
68
|
+
<span aria-hidden="true" className="shrink-0 font-mono text-ink-mute">
|
|
69
|
+
[*]
|
|
70
|
+
</span>
|
|
71
|
+
<span>{entry}</span>
|
|
72
|
+
</li>
|
|
73
|
+
))}
|
|
74
|
+
</ul>
|
|
75
|
+
) : null}
|
|
76
|
+
</div>
|
|
77
|
+
</li>
|
|
78
|
+
))}
|
|
79
|
+
</ol>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ReleaseRail, type ReleaseRailItem, type ReleaseRailProps } from "./ReleaseRail";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Fenced code + copy affordance for <ChatMarkdown> (#1418): a hairline
|
|
4
|
+
* figure with a microtype caption (language label · copy) over verbatim
|
|
5
|
+
* code. The copy button is the only stateful piece — it flips to `copied`
|
|
6
|
+
* for a beat via navigator.clipboard and silently no-ops where the API is
|
|
7
|
+
* unavailable (e.g. cross-origin iframes — the digichat embed rule).
|
|
8
|
+
* <ChatCopyButton> is exported solo so transcripts can pin the same
|
|
9
|
+
* affordance to whole turns (digichat-ui's .dc-msg-copy / .dc-code-copy
|
|
10
|
+
* rebuild on it). Box surface, caption row, and button mechanics live in
|
|
11
|
+
* styles/chat-core.css.
|
|
12
|
+
*/
|
|
13
|
+
import { useState } from "react";
|
|
14
|
+
|
|
15
|
+
export type ChatCopyButtonProps = {
|
|
16
|
+
/** Payload written to the clipboard. */
|
|
17
|
+
text: string;
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function ChatCopyButton({ text, ariaLabel = "Copy", className }: ChatCopyButtonProps) {
|
|
23
|
+
const [copied, setCopied] = useState(false);
|
|
24
|
+
const cls = ["chat-md-copy", copied ? "is-copied" : "", className ?? ""]
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.join(" ");
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
className={cls}
|
|
31
|
+
aria-label={ariaLabel}
|
|
32
|
+
onClick={() =>
|
|
33
|
+
navigator.clipboard?.writeText(text).then(
|
|
34
|
+
() => {
|
|
35
|
+
setCopied(true);
|
|
36
|
+
window.setTimeout(() => setCopied(false), 1200);
|
|
37
|
+
},
|
|
38
|
+
() => {},
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
{copied ? "copied" : "copy"}
|
|
43
|
+
</button>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type ChatCodeBlockProps = {
|
|
48
|
+
/** Raw source — rendered verbatim and used as the copy payload. */
|
|
49
|
+
code: string;
|
|
50
|
+
/** Caption language label, e.g. `python`. */
|
|
51
|
+
lang?: string;
|
|
52
|
+
className?: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function ChatCodeBlock({ code, lang, className }: ChatCodeBlockProps) {
|
|
56
|
+
return (
|
|
57
|
+
<figure className={["chat-md-code", className ?? ""].filter(Boolean).join(" ")}>
|
|
58
|
+
<figcaption>
|
|
59
|
+
<span>{lang}</span>
|
|
60
|
+
<ChatCopyButton text={code} ariaLabel="Copy code" />
|
|
61
|
+
</figcaption>
|
|
62
|
+
<pre>
|
|
63
|
+
<code>{code}</code>
|
|
64
|
+
</pre>
|
|
65
|
+
</figure>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat markdown — the rich-text frame for an assistant turn (#1418):
|
|
3
|
+
* headings, emphasis, lists, quotes, links, tables, math and diagrams styled
|
|
4
|
+
* on the token palette so rendered markdown reads as one surface with the
|
|
5
|
+
* transcript. Renders a `.chat-md` scope whose ELEMENT combinators (with their
|
|
6
|
+
* color-mix washes and ::marker accents) live in styles/chat-core.css —
|
|
7
|
+
* markdown renderers need no per-node classes; bare tags pick up the
|
|
8
|
+
* grammar, which is exactly how digichat-ui's .dc-md-* map onto it. Fenced
|
|
9
|
+
* code with the copy affordance is <ChatCodeBlock>; a bare <pre> still
|
|
10
|
+
* reads as the same hairline box.
|
|
11
|
+
*
|
|
12
|
+
* Two ways in:
|
|
13
|
+
*
|
|
14
|
+
* <ChatMarkdown>{nodes}</ChatMarkdown> frame only — static, server-safe
|
|
15
|
+
* <ChatMarkdown source={md} /> frame + renderer
|
|
16
|
+
*
|
|
17
|
+
* `source` runs the shared pipeline in <ChatMarkdownSource>: GFM, `$inline$` /
|
|
18
|
+
* `$$block$$` math via remark-math + rehype-katex (rendered at parse time, so
|
|
19
|
+
* it survives with JS off), and ```mermaid fences via <ChatMermaidBlock>
|
|
20
|
+
* (client-only, lazily imported, source shown until it draws). Both may be
|
|
21
|
+
* combined — `source` renders first, then children, which is how a streaming
|
|
22
|
+
* turn pins <ChatStreamCursor> to the end of the text.
|
|
23
|
+
*
|
|
24
|
+
* The children-only path stays directive-free and server-safe.
|
|
25
|
+
*
|
|
26
|
+
* It does NOT, however, avoid the cost: `ChatMarkdownSource` is a **static**
|
|
27
|
+
* import below, so react-markdown, remark-gfm, remark-math, rehype-katex (→ katex,
|
|
28
|
+
* 266 KB raw / 76 KB gzipped) and <ChatMermaidBlock> are in the module graph of
|
|
29
|
+
* every consumer, including one that only ever passes children. An earlier version
|
|
30
|
+
* of this comment claimed "passing `source` pulls in the client renderer", implying
|
|
31
|
+
* the children path escaped it; that was wrong. Only `mermaid` itself (~2.9 MB) is
|
|
32
|
+
* genuinely deferred, via `await import("mermaid")` inside the effect.
|
|
33
|
+
*
|
|
34
|
+
* Making the whole renderer dynamic would be the real fix and is not done here: it
|
|
35
|
+
* would turn every `source` render into a suspense boundary and change the
|
|
36
|
+
* streaming behaviour, which needs its own change with its own review.
|
|
37
|
+
*/
|
|
38
|
+
import type { ReactNode } from "react";
|
|
39
|
+
|
|
40
|
+
import { ChatMarkdownSource, type CodeBlockOverride } from "./ChatMarkdownSource";
|
|
41
|
+
|
|
42
|
+
export type { CodeBlockOverride } from "./ChatMarkdownSource";
|
|
43
|
+
|
|
44
|
+
export type ChatMarkdownProps = {
|
|
45
|
+
children?: ReactNode;
|
|
46
|
+
/** Markdown source — GFM + `$math$` + ```mermaid, rendered by the shared pipeline. */
|
|
47
|
+
source?: string;
|
|
48
|
+
className?: string;
|
|
49
|
+
/** Per-fence-language block-code hook — see {@link CodeBlockOverride}. Only
|
|
50
|
+
* consulted when `source` is passed; the children-only frame has nothing to
|
|
51
|
+
* parse. Optional, and additive: omit it and every fence renders exactly as
|
|
52
|
+
* before (mermaid diagram, or the copy-caption code block). */
|
|
53
|
+
renderCodeBlock?: CodeBlockOverride;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export function ChatMarkdown({ children, source, className, renderCodeBlock }: ChatMarkdownProps) {
|
|
57
|
+
const cls = ["chat-md min-w-0 text-[0.88rem] leading-[1.6]", className ?? ""]
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.join(" ");
|
|
60
|
+
return (
|
|
61
|
+
<div className={cls}>
|
|
62
|
+
{source ? <ChatMarkdownSource source={source} renderCodeBlock={renderCodeBlock} /> : null}
|
|
63
|
+
{children}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|