@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,185 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PerformanceDashboard — the book-level surface promoted from the design
|
|
5
|
+
* reference (finance/performance-dashboard): a value/return headline row, a
|
|
6
|
+
* strip of aggregate ratios, and an allocation-by-strategy breakdown. Sits
|
|
7
|
+
* above the single-strategy tearsheet metrics (<PerfMetrics/>): this is the
|
|
8
|
+
* whole book. P&L reads wear the money colors (`tone`); ratios stay ink; the
|
|
9
|
+
* allocation bars take the module accent. Server component — no state, no
|
|
10
|
+
* effects.
|
|
11
|
+
*
|
|
12
|
+
* `children` is the composite slot: an optional chart section rendered
|
|
13
|
+
* between the headline row and the ratio strip (intended for the
|
|
14
|
+
* finance-charts family — <EquityCurve/>, <SyncedTearsheet/> — passed in by
|
|
15
|
+
* the page, never imported here). Give the slot content a definite height;
|
|
16
|
+
* the dashboard only contributes the hairline divider.
|
|
17
|
+
*
|
|
18
|
+
* The hairline grammar between headline cells and ratio cells is
|
|
19
|
+
* sibling-index CSS (styles/finance-composites.css, pdash-*) keyed off the
|
|
20
|
+
* strip's `data-cols` — Tailwind can't express nth-child, so it stays CSS.
|
|
21
|
+
* Below 720px the headline stacks and the ratio strip collapses to 3-up.
|
|
22
|
+
*
|
|
23
|
+
* Wiring (in the consuming app):
|
|
24
|
+
* globals.css @import "@digithings-ai/ui/styles/finance-composites.css";
|
|
25
|
+
* @source "<path-to>/packages/ui/src/components/finance-composites";
|
|
26
|
+
*/
|
|
27
|
+
export type DashboardHeadline = {
|
|
28
|
+
/** Mono micro-caps label — "portfolio value", "total return" … */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Big tabular read — "$1.284M", "+28.4%" … */
|
|
31
|
+
value: string;
|
|
32
|
+
/** Money semantics on the value: only P&L reads take a tone. */
|
|
33
|
+
tone?: "up" | "down";
|
|
34
|
+
/** Small line under the value — "+$5.47K · +0.43% today", "since inception · 2y" … */
|
|
35
|
+
note?: string;
|
|
36
|
+
/** Money semantics on the note; untoned notes read muted ink. */
|
|
37
|
+
noteTone?: "up" | "down";
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type DashboardRatio = {
|
|
41
|
+
/** Mono micro-caps label — "sharpe", "max drawdown" … */
|
|
42
|
+
label: string;
|
|
43
|
+
/** Preformatted read — "2.31", "−18.4%" … */
|
|
44
|
+
value: string;
|
|
45
|
+
/** Money semantics: drawdown-class reads take "down"; ratios stay ink. */
|
|
46
|
+
tone?: "up" | "down";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type DashboardAllocation = {
|
|
50
|
+
/** Strategy / sleeve name — "trend_xsec" … */
|
|
51
|
+
name: string;
|
|
52
|
+
/** Share of the book, 0–100; drives the accent bar width. */
|
|
53
|
+
pct: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type PerformanceDashboardProps = {
|
|
57
|
+
/** Headline cells; designed for two (value + return), 1.4fr/1fr split. */
|
|
58
|
+
headlines: DashboardHeadline[];
|
|
59
|
+
ratios?: DashboardRatio[];
|
|
60
|
+
/** Desktop ratio cells per row (collapses to 3-up below 720px). */
|
|
61
|
+
ratioColumns?: 3 | 4 | 5 | 6;
|
|
62
|
+
allocations?: DashboardAllocation[];
|
|
63
|
+
/** Mono micro-caps heading over the allocation bars. */
|
|
64
|
+
allocationsLabel?: string;
|
|
65
|
+
/** Optional chart slot rendered after the headline row (see docblock). */
|
|
66
|
+
children?: ReactNode;
|
|
67
|
+
/** Extra classes on the dashboard shell (margins — the call site's business). */
|
|
68
|
+
className?: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const HEAD_COLS: Record<number, string> = {
|
|
72
|
+
1: "grid-cols-1",
|
|
73
|
+
2: "grid-cols-[1.4fr_1fr]",
|
|
74
|
+
3: "grid-cols-3",
|
|
75
|
+
4: "grid-cols-4",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const RATIO_COLS: Record<3 | 4 | 5 | 6, string> = {
|
|
79
|
+
3: "grid-cols-3",
|
|
80
|
+
4: "grid-cols-4",
|
|
81
|
+
5: "grid-cols-5",
|
|
82
|
+
6: "grid-cols-6",
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export function PerformanceDashboard({
|
|
86
|
+
headlines,
|
|
87
|
+
ratios,
|
|
88
|
+
ratioColumns = 6,
|
|
89
|
+
allocations,
|
|
90
|
+
allocationsLabel = "allocation by strategy",
|
|
91
|
+
children,
|
|
92
|
+
className,
|
|
93
|
+
}: PerformanceDashboardProps) {
|
|
94
|
+
return (
|
|
95
|
+
<div
|
|
96
|
+
className={`overflow-hidden rounded-none border border-hair bg-surface${
|
|
97
|
+
className ? ` ${className}` : ""
|
|
98
|
+
}`}
|
|
99
|
+
>
|
|
100
|
+
<div className={`grid ${HEAD_COLS[headlines.length] ?? "grid-cols-2"} max-[720px]:grid-cols-1`}>
|
|
101
|
+
{headlines.map((h) => (
|
|
102
|
+
<div
|
|
103
|
+
key={h.label}
|
|
104
|
+
className="pdash-head flex flex-col gap-[0.3rem] px-[1.4rem] pb-[1.2rem] pt-[1.4rem]"
|
|
105
|
+
>
|
|
106
|
+
<span className="font-mono text-[0.58rem] uppercase tracking-[0.1em] text-ink-mute">
|
|
107
|
+
{h.label}
|
|
108
|
+
</span>
|
|
109
|
+
<span
|
|
110
|
+
className={`font-mono text-[clamp(1.6rem,4vw,2.2rem)] [font-variant-numeric:tabular-nums] ${
|
|
111
|
+
h.tone === "up" ? "text-up" : h.tone === "down" ? "text-down" : "text-ink"
|
|
112
|
+
}`}
|
|
113
|
+
>
|
|
114
|
+
{h.value}
|
|
115
|
+
</span>
|
|
116
|
+
{h.note ? (
|
|
117
|
+
<span
|
|
118
|
+
className={`font-mono ${
|
|
119
|
+
h.noteTone === "up"
|
|
120
|
+
? "text-[0.72rem] text-up"
|
|
121
|
+
: h.noteTone === "down"
|
|
122
|
+
? "text-[0.72rem] text-down"
|
|
123
|
+
: "text-[0.66rem] text-ink-mute"
|
|
124
|
+
}`}
|
|
125
|
+
>
|
|
126
|
+
{h.note}
|
|
127
|
+
</span>
|
|
128
|
+
) : null}
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
{children ? <div className="border-t border-hair">{children}</div> : null}
|
|
134
|
+
|
|
135
|
+
{ratios && ratios.length > 0 ? (
|
|
136
|
+
<div
|
|
137
|
+
data-cols={ratioColumns}
|
|
138
|
+
className={`pdash-ratios grid ${RATIO_COLS[ratioColumns]} border-t border-hair max-[720px]:grid-cols-3`}
|
|
139
|
+
>
|
|
140
|
+
{ratios.map((r) => (
|
|
141
|
+
<div key={r.label} className="pdash-ratio flex flex-col gap-[0.3rem] px-4 py-[0.9rem]">
|
|
142
|
+
<span className="font-mono text-[0.52rem] uppercase tracking-[0.08em] text-ink-mute">
|
|
143
|
+
{r.label}
|
|
144
|
+
</span>
|
|
145
|
+
<span
|
|
146
|
+
className={`font-mono text-[0.98rem] [font-variant-numeric:tabular-nums] ${
|
|
147
|
+
r.tone === "up" ? "text-up" : r.tone === "down" ? "text-down" : "text-ink"
|
|
148
|
+
}`}
|
|
149
|
+
>
|
|
150
|
+
{r.value}
|
|
151
|
+
</span>
|
|
152
|
+
</div>
|
|
153
|
+
))}
|
|
154
|
+
</div>
|
|
155
|
+
) : null}
|
|
156
|
+
|
|
157
|
+
{allocations && allocations.length > 0 ? (
|
|
158
|
+
<div className="border-t border-hair px-[1.4rem] pb-[1.4rem] pt-[1.2rem]">
|
|
159
|
+
<p className="mx-0 mb-[0.8rem] mt-0 font-mono text-[0.58rem] uppercase tracking-[0.1em] text-ink-mute">
|
|
160
|
+
{allocationsLabel}
|
|
161
|
+
</p>
|
|
162
|
+
{allocations.map((a) => (
|
|
163
|
+
<div
|
|
164
|
+
key={a.name}
|
|
165
|
+
className="grid grid-cols-[6rem_1fr_3rem] items-center gap-[0.9rem] py-[0.35rem] font-mono text-[0.78rem] text-ink-soft"
|
|
166
|
+
>
|
|
167
|
+
<span className="min-w-0 truncate text-ink" title={a.name}>
|
|
168
|
+
{a.name}
|
|
169
|
+
</span>
|
|
170
|
+
<span className="h-2 overflow-hidden rounded-none bg-ink/[0.08]">
|
|
171
|
+
<span
|
|
172
|
+
className="block h-full rounded-none bg-accent"
|
|
173
|
+
style={{ width: `${a.pct}%` }}
|
|
174
|
+
/>
|
|
175
|
+
</span>
|
|
176
|
+
<span className="text-end text-ink-soft [font-variant-numeric:tabular-nums]">
|
|
177
|
+
{a.pct}%
|
|
178
|
+
</span>
|
|
179
|
+
</div>
|
|
180
|
+
))}
|
|
181
|
+
</div>
|
|
182
|
+
) : null}
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SortableTable — the reorderable leaderboard promoted from the design
|
|
7
|
+
* reference (data/sortable-table): click (or keyboard-activate — real
|
|
8
|
+
* <button>s in the headers) a column to sort, click again to flip. The active
|
|
9
|
+
* column shows a caret and reports `aria-sort` on its <th>; numeric columns
|
|
10
|
+
* sort numerically and right-align, text sorts lexically. Column `tone`
|
|
11
|
+
* wears the money colors (--up / --down) — returns up, drawdowns down —
|
|
12
|
+
* and everything else stays ink.
|
|
13
|
+
*
|
|
14
|
+
* The table grammar (srt-*) lives in styles/finance-composites.css: header
|
|
15
|
+
* hover/active state, caret accent, hairline row rules, td money colors —
|
|
16
|
+
* descendant/state selectors that stay CSS per migrate-vs-leave. Rows render
|
|
17
|
+
* fully server-side markup-wise; without JS you get the table in its default
|
|
18
|
+
* order.
|
|
19
|
+
*
|
|
20
|
+
* Wiring (in the consuming app):
|
|
21
|
+
* globals.css @import "@digithings-ai/ui/styles/finance-composites.css";
|
|
22
|
+
* @source "<path-to>/packages/ui/src/components/finance-composites";
|
|
23
|
+
*/
|
|
24
|
+
export type SortableColumn<Row> = {
|
|
25
|
+
/** Row field this column reads (and sorts by). */
|
|
26
|
+
key: keyof Row & string;
|
|
27
|
+
/** Mono micro-caps header label. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** Numeric columns right-align and default to descending on first sort. */
|
|
30
|
+
numeric?: boolean;
|
|
31
|
+
/** Preformats the cell read; defaults to String(value). */
|
|
32
|
+
format?: (value: Row[keyof Row & string], row: Row) => string;
|
|
33
|
+
/** Money semantics for the whole column: returns "up", drawdowns "down". */
|
|
34
|
+
tone?: "up" | "down";
|
|
35
|
+
/** Identifier column emphasis — the read stays ink instead of ink-soft. */
|
|
36
|
+
emphasis?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type SortableTableProps<Row> = {
|
|
40
|
+
rows: Row[];
|
|
41
|
+
columns: SortableColumn<Row>[];
|
|
42
|
+
/** Stable React key per row — e.g. `(r) => r.strat`. */
|
|
43
|
+
rowKey: (row: Row) => string;
|
|
44
|
+
/** Initial sort; defaults to the first column in its natural direction. */
|
|
45
|
+
defaultSort?: { key: keyof Row & string; dir?: "asc" | "desc" };
|
|
46
|
+
/** Extra classes on the scroll shell (margins — the call site's business). */
|
|
47
|
+
className?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function SortableTable<Row>({
|
|
51
|
+
rows,
|
|
52
|
+
columns,
|
|
53
|
+
rowKey,
|
|
54
|
+
defaultSort,
|
|
55
|
+
className,
|
|
56
|
+
}: SortableTableProps<Row>) {
|
|
57
|
+
const naturalDir = (key: keyof Row & string): "asc" | "desc" =>
|
|
58
|
+
columns.find((c) => c.key === key)?.numeric ? "desc" : "asc";
|
|
59
|
+
|
|
60
|
+
const initialKey = defaultSort?.key ?? columns[0]?.key;
|
|
61
|
+
const [sortKey, setSortKey] = useState<keyof Row & string>(initialKey);
|
|
62
|
+
const [dir, setDir] = useState<"asc" | "desc">(
|
|
63
|
+
defaultSort?.dir ?? (initialKey ? naturalDir(initialKey) : "asc"),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const sorted = [...rows].sort((a, b) => {
|
|
67
|
+
const av = a[sortKey];
|
|
68
|
+
const bv = b[sortKey];
|
|
69
|
+
const cmp =
|
|
70
|
+
typeof av === "number" && typeof bv === "number"
|
|
71
|
+
? av - bv
|
|
72
|
+
: String(av).localeCompare(String(bv));
|
|
73
|
+
return dir === "asc" ? cmp : -cmp;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const onSort = (key: keyof Row & string) => {
|
|
77
|
+
if (key === sortKey) {
|
|
78
|
+
setDir((d) => (d === "asc" ? "desc" : "asc"));
|
|
79
|
+
} else {
|
|
80
|
+
setSortKey(key);
|
|
81
|
+
setDir(naturalDir(key));
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
// tabIndex + role/aria-label: this is a horizontally-scrolling region on
|
|
88
|
+
// narrow viewports (no wrap point in the table itself) — without a tab
|
|
89
|
+
// stop, a keyboard-only user (no touch, no scrollbar drag) has no way
|
|
90
|
+
// to focus it and arrow-key-scroll the columns that overflow.
|
|
91
|
+
tabIndex={0}
|
|
92
|
+
role="region"
|
|
93
|
+
aria-label="Table, scrollable horizontally"
|
|
94
|
+
className={`overflow-x-auto rounded-none border border-hair bg-surface${
|
|
95
|
+
className ? ` ${className}` : ""
|
|
96
|
+
}`}
|
|
97
|
+
>
|
|
98
|
+
<table className="srt-table">
|
|
99
|
+
<thead>
|
|
100
|
+
<tr>
|
|
101
|
+
{columns.map((c) => {
|
|
102
|
+
const active = c.key === sortKey;
|
|
103
|
+
return (
|
|
104
|
+
<th
|
|
105
|
+
key={c.key}
|
|
106
|
+
scope="col"
|
|
107
|
+
className={c.numeric ? "srt-r" : "srt-l"}
|
|
108
|
+
aria-sort={active ? (dir === "asc" ? "ascending" : "descending") : "none"}
|
|
109
|
+
>
|
|
110
|
+
<button
|
|
111
|
+
type="button"
|
|
112
|
+
className={`srt-head${active ? " is-active" : ""}`}
|
|
113
|
+
onClick={() => onSort(c.key)}
|
|
114
|
+
>
|
|
115
|
+
{c.label}
|
|
116
|
+
<span className="srt-caret" aria-hidden="true">
|
|
117
|
+
{active ? (dir === "asc" ? "▲" : "▼") : "↕"}
|
|
118
|
+
</span>
|
|
119
|
+
</button>
|
|
120
|
+
</th>
|
|
121
|
+
);
|
|
122
|
+
})}
|
|
123
|
+
</tr>
|
|
124
|
+
</thead>
|
|
125
|
+
<tbody>
|
|
126
|
+
{sorted.map((row) => (
|
|
127
|
+
<tr key={rowKey(row)}>
|
|
128
|
+
{columns.map((c) => (
|
|
129
|
+
<td
|
|
130
|
+
key={c.key}
|
|
131
|
+
className={`${c.numeric ? "srt-r" : "srt-l"}${c.tone ? ` ${c.tone}` : ""}${
|
|
132
|
+
c.emphasis ? " srt-sym" : ""
|
|
133
|
+
}`}
|
|
134
|
+
>
|
|
135
|
+
{c.format ? c.format(row[c.key], row) : String(row[c.key])}
|
|
136
|
+
</td>
|
|
137
|
+
))}
|
|
138
|
+
</tr>
|
|
139
|
+
))}
|
|
140
|
+
</tbody>
|
|
141
|
+
</table>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StockTicker — the scrolling market strip promoted from the design reference
|
|
3
|
+
* (finance/ticker-tape): one mono row of symbol · last · change looping
|
|
4
|
+
* seamlessly (content duplicated once, track translated exactly -50%) behind
|
|
5
|
+
* edge-fade masks, pause-on-hover/focus-within/tap (the container is
|
|
6
|
+
* tabbable so touch users can tap-to-focus and keyboard users can tab to it —
|
|
7
|
+
* :focus-within mirrors the :hover rule, no JS state needed). This is the one
|
|
8
|
+
* marquee that legitimately wears the money colors — a price change IS the
|
|
9
|
+
* up/down semantic — while the module accent stays out of it entirely. Pure
|
|
10
|
+
* CSS animation (styles/finance-composites.css), so a plain server component;
|
|
11
|
+
* the tape is fully readable with no JS and prefers-reduced-motion holds it
|
|
12
|
+
* still.
|
|
13
|
+
*
|
|
14
|
+
* Wiring (in the consuming app):
|
|
15
|
+
* globals.css @import "@digithings-ai/ui/styles/finance-composites.css";
|
|
16
|
+
* @source "<path-to>/packages/ui/src/components/finance-composites";
|
|
17
|
+
*/
|
|
18
|
+
export type TickerItem = {
|
|
19
|
+
/** Instrument symbol — "BTC-PERP", "SPY", "US10Y" … */
|
|
20
|
+
symbol: string;
|
|
21
|
+
/** Preformatted last price — "63,410", "4.281%" … */
|
|
22
|
+
last: string;
|
|
23
|
+
/** Preformatted change magnitude — "1.24%" (direction carried by `up`). */
|
|
24
|
+
change: string;
|
|
25
|
+
/** Direction of the change: true wears --up, false wears --down. */
|
|
26
|
+
up: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type StockTickerProps = {
|
|
30
|
+
/** The ticks on the tape — duplicated internally for the seamless loop. */
|
|
31
|
+
items: TickerItem[];
|
|
32
|
+
/** Extra classes on the tape shell (margins, widths — the call site's business). */
|
|
33
|
+
className?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function StockTicker({ items, className }: StockTickerProps) {
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
className={`tk${className ? ` ${className}` : ""}`}
|
|
40
|
+
tabIndex={0}
|
|
41
|
+
aria-label="Price ticker, tab or tap to pause"
|
|
42
|
+
>
|
|
43
|
+
<div className="tk-track">
|
|
44
|
+
{[...items, ...items].map((t, i) => (
|
|
45
|
+
<span
|
|
46
|
+
className="inline-flex items-baseline gap-2 whitespace-nowrap border-e border-hair px-[1.3rem] py-[0.7rem] font-mono text-[0.82rem] [font-variant-numeric:tabular-nums]"
|
|
47
|
+
key={`${t.symbol}-${i}`}
|
|
48
|
+
aria-hidden={i >= items.length || undefined}
|
|
49
|
+
>
|
|
50
|
+
<span className="tracking-[0.02em] text-ink">{t.symbol}</span>
|
|
51
|
+
<span className="text-ink-soft">{t.last}</span>
|
|
52
|
+
<span
|
|
53
|
+
className={`inline-flex items-center gap-[0.28rem] text-[0.76rem] ${
|
|
54
|
+
t.up ? "text-up" : "text-down"
|
|
55
|
+
}`}
|
|
56
|
+
>
|
|
57
|
+
<span aria-hidden="true">{t.up ? "▲" : "▼"}</span>
|
|
58
|
+
{t.change}
|
|
59
|
+
</span>
|
|
60
|
+
</span>
|
|
61
|
+
))}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import {
|
|
5
|
+
AreaSeries,
|
|
6
|
+
BaselineSeries,
|
|
7
|
+
ColorType,
|
|
8
|
+
createChart,
|
|
9
|
+
CrosshairMode,
|
|
10
|
+
type AreaData,
|
|
11
|
+
type BaselineData,
|
|
12
|
+
type IChartApi,
|
|
13
|
+
type Time,
|
|
14
|
+
} from "lightweight-charts";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* SyncedTearsheet — the multi-pane tearsheet chart promoted from the design
|
|
18
|
+
* reference (finance/synced-tearsheet): ONE Lightweight Charts instance, two
|
|
19
|
+
* panes sharing a single time axis — cumulative equity on top, the underwater
|
|
20
|
+
* drawdown below. Because both live in one chart, the x-axis, crosshair and
|
|
21
|
+
* zoom are synced natively (no cross-chart plumbing). Equity wears the module
|
|
22
|
+
* accent (identity); drawdown wears --down (it only ever reads negative) —
|
|
23
|
+
* per the charting house rules, every color is read from a design token at
|
|
24
|
+
* runtime and a MutationObserver on data-theme re-themes live.
|
|
25
|
+
*
|
|
26
|
+
* This IS the multi-series primitive: add a pane per series rather than
|
|
27
|
+
* stacking separate charts. The finance-charts family's single-series
|
|
28
|
+
* specimens (price-chart / equity-curve / drawdown-plot) are siblings, not
|
|
29
|
+
* children — composites embed this component directly. Give the host a
|
|
30
|
+
* definite height (the reference wraps it in `.pc-frame--tall`); autoSize
|
|
31
|
+
* fills it. Canvas-only, so nothing to read without JS — decorative by
|
|
32
|
+
* default (aria-hidden) unless you pass `ariaLabel`.
|
|
33
|
+
*
|
|
34
|
+
* Wiring (in the consuming app):
|
|
35
|
+
* package: lightweight-charts ^5.2.0
|
|
36
|
+
* globals.css @source "<path-to>/packages/ui/src/components/finance-composites";
|
|
37
|
+
* (no family CSS needed — the chart paints from tokens on canvas)
|
|
38
|
+
*/
|
|
39
|
+
export type TearsheetPoint = {
|
|
40
|
+
/** ISO date, yyyy-mm-dd — Lightweight Charts business-day time. */
|
|
41
|
+
time: string;
|
|
42
|
+
value: number;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type SyncedTearsheetProps = {
|
|
46
|
+
/** Cumulative equity series (pane 0, module accent). */
|
|
47
|
+
equity: TearsheetPoint[];
|
|
48
|
+
/**
|
|
49
|
+
* Underwater drawdown series (pane 1, --down), in percent (≤ 0). Derived
|
|
50
|
+
* from `equity`'s running peak (one decimal) when omitted.
|
|
51
|
+
*/
|
|
52
|
+
drawdown?: TearsheetPoint[];
|
|
53
|
+
/** Height share of the equity pane relative to the drawdown pane's 1. */
|
|
54
|
+
equityStretch?: number;
|
|
55
|
+
/** Describes the chart to AT; omitted = decorative (aria-hidden). */
|
|
56
|
+
ariaLabel?: string;
|
|
57
|
+
/** Extra classes on the host (defaults fill the parent: h-full w-full). */
|
|
58
|
+
className?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Let page scroll/wheel/touch-drag pass through instead of panning or
|
|
61
|
+
* zooming the chart. Off by default — this component rides real dashboard
|
|
62
|
+
* dashboard surfaces (e.g. a workspace's drawdown view) where pan/zoom on
|
|
63
|
+
* the chart is an intended interaction. Turn it on only for a display
|
|
64
|
+
* specimen embedded in scrolling prose (see synced-tearsheet-reference.tsx)
|
|
65
|
+
* where nobody is meant to interact with the chart itself.
|
|
66
|
+
*/
|
|
67
|
+
pageScrollThrough?: boolean;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function deriveDrawdown(equity: TearsheetPoint[]): TearsheetPoint[] {
|
|
71
|
+
let peak = -Infinity;
|
|
72
|
+
return equity.map((p) => {
|
|
73
|
+
peak = Math.max(peak, p.value);
|
|
74
|
+
return { time: p.time, value: Math.round((p.value / peak - 1) * 1000) / 10 };
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function SyncedTearsheet({
|
|
79
|
+
equity,
|
|
80
|
+
drawdown,
|
|
81
|
+
equityStretch = 2.4,
|
|
82
|
+
ariaLabel,
|
|
83
|
+
className,
|
|
84
|
+
pageScrollThrough = false,
|
|
85
|
+
}: SyncedTearsheetProps) {
|
|
86
|
+
const hostRef = useRef<HTMLDivElement | null>(null);
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
const host = hostRef.current;
|
|
90
|
+
if (!host || equity.length === 0) return;
|
|
91
|
+
const cssVar = (name: string, fb: string) =>
|
|
92
|
+
getComputedStyle(host).getPropertyValue(name).trim() || fb;
|
|
93
|
+
const toRgba = (col: string, a: number) => {
|
|
94
|
+
const m = col.match(/[\d.]+/g);
|
|
95
|
+
if (col.startsWith("#") || !m || m.length < 3) return col;
|
|
96
|
+
return `rgba(${m[0]},${m[1]},${m[2]},${a})`;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const palette = () => ({
|
|
100
|
+
inkMute: cssVar("--ink-mute", "#7D8389"),
|
|
101
|
+
hair: cssVar("--hair", "rgba(255,255,255,0.09)"),
|
|
102
|
+
accent: cssVar("--accent", "#3dd6c4"),
|
|
103
|
+
down: cssVar("--down", "#E5533E"),
|
|
104
|
+
mono: cssVar("--font-mono", "monospace"),
|
|
105
|
+
});
|
|
106
|
+
let p = palette();
|
|
107
|
+
|
|
108
|
+
const chart: IChartApi = createChart(host, {
|
|
109
|
+
autoSize: true,
|
|
110
|
+
layout: {
|
|
111
|
+
background: { type: ColorType.Solid, color: "transparent" },
|
|
112
|
+
textColor: p.inkMute,
|
|
113
|
+
fontFamily: p.mono,
|
|
114
|
+
fontSize: 11,
|
|
115
|
+
attributionLogo: false,
|
|
116
|
+
},
|
|
117
|
+
grid: { vertLines: { color: p.hair }, horzLines: { color: p.hair } },
|
|
118
|
+
rightPriceScale: { borderColor: p.hair },
|
|
119
|
+
timeScale: { borderColor: p.hair, timeVisible: false },
|
|
120
|
+
crosshair: {
|
|
121
|
+
mode: CrosshairMode.Normal,
|
|
122
|
+
vertLine: { color: p.inkMute, labelBackgroundColor: p.accent },
|
|
123
|
+
horzLine: { color: p.inkMute, labelBackgroundColor: p.accent },
|
|
124
|
+
},
|
|
125
|
+
...(pageScrollThrough
|
|
126
|
+
? {
|
|
127
|
+
handleScroll: {
|
|
128
|
+
mouseWheel: false,
|
|
129
|
+
pressedMouseMove: false,
|
|
130
|
+
horzTouchDrag: false,
|
|
131
|
+
vertTouchDrag: false,
|
|
132
|
+
},
|
|
133
|
+
handleScale: { axisPressedMouseMove: false, mouseWheel: false, pinch: false },
|
|
134
|
+
}
|
|
135
|
+
: {}),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// pane 0 — cumulative equity (identity accent)
|
|
139
|
+
const equitySeries = chart.addSeries(
|
|
140
|
+
AreaSeries,
|
|
141
|
+
{
|
|
142
|
+
lineColor: p.accent,
|
|
143
|
+
topColor: toRgba(p.accent, 0.28),
|
|
144
|
+
bottomColor: toRgba(p.accent, 0.02),
|
|
145
|
+
lineWidth: 2,
|
|
146
|
+
priceLineVisible: false,
|
|
147
|
+
},
|
|
148
|
+
0,
|
|
149
|
+
);
|
|
150
|
+
equitySeries.setData(
|
|
151
|
+
equity.map((pt): AreaData => ({ time: pt.time as Time, value: pt.value })),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// pane 1 — underwater drawdown (money --down)
|
|
155
|
+
const drawdownSeries = chart.addSeries(
|
|
156
|
+
BaselineSeries,
|
|
157
|
+
{
|
|
158
|
+
baseValue: { type: "price", price: 0 },
|
|
159
|
+
topLineColor: "transparent",
|
|
160
|
+
topFillColor1: "transparent",
|
|
161
|
+
topFillColor2: "transparent",
|
|
162
|
+
bottomLineColor: p.down,
|
|
163
|
+
bottomFillColor1: toRgba(p.down, 0.05),
|
|
164
|
+
bottomFillColor2: toRgba(p.down, 0.32),
|
|
165
|
+
lineWidth: 2,
|
|
166
|
+
priceLineVisible: false,
|
|
167
|
+
// this pane is always the underwater drawdown series (percent, ≤ 0) —
|
|
168
|
+
// format the axis accordingly rather than leaving it bare numbers.
|
|
169
|
+
priceFormat: { type: "custom", formatter: (v: number) => `${v.toFixed(1)}%`, minMove: 0.1 },
|
|
170
|
+
},
|
|
171
|
+
1,
|
|
172
|
+
);
|
|
173
|
+
drawdownSeries.setData(
|
|
174
|
+
(drawdown ?? deriveDrawdown(equity)).map(
|
|
175
|
+
(pt): BaselineData => ({ time: pt.time as Time, value: pt.value }),
|
|
176
|
+
),
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// give the equity pane the lion's share of the height
|
|
180
|
+
const panes = chart.panes();
|
|
181
|
+
panes[0]?.setStretchFactor(equityStretch);
|
|
182
|
+
panes[1]?.setStretchFactor(1);
|
|
183
|
+
|
|
184
|
+
chart.timeScale().fitContent();
|
|
185
|
+
|
|
186
|
+
const retheme = () => {
|
|
187
|
+
p = palette();
|
|
188
|
+
chart.applyOptions({
|
|
189
|
+
layout: { textColor: p.inkMute },
|
|
190
|
+
grid: { vertLines: { color: p.hair }, horzLines: { color: p.hair } },
|
|
191
|
+
rightPriceScale: { borderColor: p.hair },
|
|
192
|
+
timeScale: { borderColor: p.hair },
|
|
193
|
+
});
|
|
194
|
+
equitySeries.applyOptions({
|
|
195
|
+
lineColor: p.accent,
|
|
196
|
+
topColor: toRgba(p.accent, 0.28),
|
|
197
|
+
bottomColor: toRgba(p.accent, 0.02),
|
|
198
|
+
});
|
|
199
|
+
drawdownSeries.applyOptions({
|
|
200
|
+
bottomLineColor: p.down,
|
|
201
|
+
bottomFillColor1: toRgba(p.down, 0.05),
|
|
202
|
+
bottomFillColor2: toRgba(p.down, 0.32),
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
const themeObs = new MutationObserver(retheme);
|
|
206
|
+
themeObs.observe(document.documentElement, {
|
|
207
|
+
attributes: true,
|
|
208
|
+
attributeFilter: ["data-theme"],
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
return () => {
|
|
212
|
+
themeObs.disconnect();
|
|
213
|
+
chart.remove();
|
|
214
|
+
};
|
|
215
|
+
}, [equity, drawdown, equityStretch, pageScrollThrough]);
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div
|
|
219
|
+
className={className ?? "h-full w-full"}
|
|
220
|
+
ref={hostRef}
|
|
221
|
+
role={ariaLabel ? "img" : undefined}
|
|
222
|
+
aria-label={ariaLabel}
|
|
223
|
+
aria-hidden={ariaLabel ? undefined : "true"}
|
|
224
|
+
/>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finance-composites family barrel (#1450) — the composite finance surfaces
|
|
3
|
+
* promoted from the reference finance/data pages: ticker tape, order book,
|
|
4
|
+
* sortable leaderboard, book-level performance dashboard, and the synced
|
|
5
|
+
* two-pane tearsheet chart. Structural CSS: styles/finance-composites.css.
|
|
6
|
+
* Re-exported from the package barrel (src/index.ts) by the F1 wire-up.
|
|
7
|
+
*/
|
|
8
|
+
export { StockTicker, type TickerItem, type StockTickerProps } from "./StockTicker";
|
|
9
|
+
export {
|
|
10
|
+
MarketBar,
|
|
11
|
+
type MarketBarProps,
|
|
12
|
+
type MarketBarCell,
|
|
13
|
+
type MarketBarStatus,
|
|
14
|
+
} from "./MarketBar";
|
|
15
|
+
export { OrderBook, type OrderBookLevel, type OrderBookProps } from "./OrderBook";
|
|
16
|
+
export { SortableTable, type SortableColumn, type SortableTableProps } from "./SortableTable";
|
|
17
|
+
export {
|
|
18
|
+
PerformanceDashboard,
|
|
19
|
+
type DashboardHeadline,
|
|
20
|
+
type DashboardRatio,
|
|
21
|
+
type DashboardAllocation,
|
|
22
|
+
type PerformanceDashboardProps,
|
|
23
|
+
} from "./PerformanceDashboard";
|
|
24
|
+
export {
|
|
25
|
+
SyncedTearsheet,
|
|
26
|
+
type TearsheetPoint,
|
|
27
|
+
type SyncedTearsheetProps,
|
|
28
|
+
} from "./SyncedTearsheet";
|