@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.
Files changed (424) hide show
  1. package/README.md +48 -2
  2. package/package.json +143 -4
  3. package/src/components/NavShell.tsx +776 -0
  4. package/src/components/SocialRow.tsx +87 -0
  5. package/src/components/Spinner.tsx +27 -0
  6. package/src/components/StackLogo.tsx +40 -0
  7. package/src/components/Terminal.tsx +110 -0
  8. package/src/components/TerminalManifest.tsx +212 -0
  9. package/src/components/ThemeProvider.tsx +271 -0
  10. package/src/components/account/AuthCard.tsx +309 -0
  11. package/src/components/assistant-ui/elements/mermaid-diagram.aui.tsx +63 -0
  12. package/src/components/assistant-ui/elements/mermaid-diagram.tsx +340 -0
  13. package/src/components/brand/BrandWordmark.tsx +32 -0
  14. package/src/components/changelog/ReleaseRail.tsx +81 -0
  15. package/src/components/changelog/index.ts +1 -0
  16. package/src/components/chat/ChatCodeBlock.tsx +67 -0
  17. package/src/components/chat/ChatMarkdown.tsx +66 -0
  18. package/src/components/chat/ChatMarkdownSource.tsx +203 -0
  19. package/src/components/chat/ChatMermaidBlock.tsx +202 -0
  20. package/src/components/chat/ChatMessage.tsx +77 -0
  21. package/src/components/chat/ChatPlayback.tsx +422 -0
  22. package/src/components/chat/ChatStreamCursor.tsx +25 -0
  23. package/src/components/chat/ChatThinking.tsx +113 -0
  24. package/src/components/chat/ChatToolCall.tsx +190 -0
  25. package/src/components/chat/ChatTranscript.tsx +60 -0
  26. package/src/components/chat/ChatWidgetFrame.tsx +107 -0
  27. package/src/components/chat/DigichatBootLoader.tsx +683 -0
  28. package/src/components/chat/DigichatLauncher.tsx +361 -0
  29. package/src/components/chat/DigichatThread.tsx +118 -0
  30. package/src/components/chat/DigichatThreadList.tsx +54 -0
  31. package/src/components/chat/DigichatWordmark.tsx +24 -0
  32. package/src/components/chat/DotMatrix.tsx +650 -0
  33. package/src/components/chat/boot-lab.tsx +766 -0
  34. package/src/components/chat/boot-signal.ts +144 -0
  35. package/src/components/chat/chat-surfaces.ts +52 -0
  36. package/src/components/chat/connection-status.ts +40 -0
  37. package/src/components/chat/digichat-wordmark.ts +355 -0
  38. package/src/components/chat/disclosure-chevron.tsx +49 -0
  39. package/src/components/chat/followable-href.ts +9 -0
  40. package/src/components/chat/gallery-thread/action-icons.tsx +25 -0
  41. package/src/components/chat/gallery-thread/attachment.aui.tsx +262 -0
  42. package/src/components/chat/gallery-thread/block-caret.tsx +439 -0
  43. package/src/components/chat/gallery-thread/cn.ts +1 -0
  44. package/src/components/chat/gallery-thread/composer-keyboard.ts +106 -0
  45. package/src/components/chat/gallery-thread/composer-trigger-popover.aui.tsx +235 -0
  46. package/src/components/chat/gallery-thread/css.d.ts +6 -0
  47. package/src/components/chat/gallery-thread/file.tsx +238 -0
  48. package/src/components/chat/gallery-thread/follow-up-suggestions.aui.tsx +92 -0
  49. package/src/components/chat/gallery-thread/format-json-dump.ts +112 -0
  50. package/src/components/chat/gallery-thread/hooks/use-attachment-src.ts +46 -0
  51. package/src/components/chat/gallery-thread/hooks/use-copy-to-clipboard.ts +9 -0
  52. package/src/components/chat/gallery-thread/image.tsx +519 -0
  53. package/src/components/chat/gallery-thread/markdown-text.tsx +278 -0
  54. package/src/components/chat/gallery-thread/message-error.aui.tsx +105 -0
  55. package/src/components/chat/gallery-thread/message-timing.aui.tsx +143 -0
  56. package/src/components/chat/gallery-thread/private-work-step.tsx +188 -0
  57. package/src/components/chat/gallery-thread/reasoning.tsx +332 -0
  58. package/src/components/chat/gallery-thread/scroll-mode.ts +174 -0
  59. package/src/components/chat/gallery-thread/source.tsx +76 -0
  60. package/src/components/chat/gallery-thread/thread.aui.tsx +1619 -0
  61. package/src/components/chat/gallery-thread/tooltip-icon-button.tsx +53 -0
  62. package/src/components/chat/gallery-thread/typed-welcome-copy.tsx +18 -0
  63. package/src/components/chat/gallery-thread/ui/tooltip.tsx +22 -0
  64. package/src/components/chat/gallery-thread/work-chain-summary.tsx +48 -0
  65. package/src/components/chat/gallery-thread/work-chain.tsx +110 -0
  66. package/src/components/chat/gallery-thread/work-status.ts +66 -0
  67. package/src/components/chat/overlay-scrollbar.tsx +86 -0
  68. package/src/components/chat/sanitize-mermaid-svg.ts +38 -0
  69. package/src/components/chat/skins/SOURCE.md +36 -0
  70. package/src/components/chat/skins/base/attachment.aui.tsx +287 -0
  71. package/src/components/chat/skins/base/aui-default/README.md +45 -0
  72. package/src/components/chat/skins/base/aui-default/collapsible-root.tsx +19 -0
  73. package/src/components/chat/skins/base/aui-default/collapsible.tsx +21 -0
  74. package/src/components/chat/skins/base/aui-default/reasoning.aui.tsx +120 -0
  75. package/src/components/chat/skins/base/aui-default/reasoning.tsx +331 -0
  76. package/src/components/chat/skins/base/aui-default/surfaces.ts +7 -0
  77. package/src/components/chat/skins/base/aui-default/tool-fallback.aui.tsx +772 -0
  78. package/src/components/chat/skins/base/aui-default/tool-group.aui.tsx +241 -0
  79. package/src/components/chat/skins/base/docs-model-options.ts +6 -0
  80. package/src/components/chat/skins/base/elements/assistant-trace.aui.tsx +169 -0
  81. package/src/components/chat/skins/base/elements/composer-trigger-popover.aui.tsx +271 -0
  82. package/src/components/chat/skins/base/elements/directive-text.aui.tsx +29 -0
  83. package/src/components/chat/skins/base/elements/directive-text.tsx +76 -0
  84. package/src/components/chat/skins/base/elements/message-timing.aui.tsx +104 -0
  85. package/src/components/chat/skins/base/elements/model-selector.aui.tsx +140 -0
  86. package/src/components/chat/skins/base/elements/model-selector.tsx +720 -0
  87. package/src/components/chat/skins/base/elements/quote.aui.tsx +290 -0
  88. package/src/components/chat/skins/base/elements/work-chain.tsx +100 -0
  89. package/src/components/chat/skins/base/markdown-text.tsx +294 -0
  90. package/src/components/chat/skins/base/model.ts +1 -0
  91. package/src/components/chat/skins/base/thread.tsx +1050 -0
  92. package/src/components/chat/skins/base/tooltip-icon-button.tsx +56 -0
  93. package/src/components/chat/skins/base/ui/avatar.tsx +115 -0
  94. package/src/components/chat/skins/base/ui/badge.tsx +51 -0
  95. package/src/components/chat/skins/base/ui/button.tsx +67 -0
  96. package/src/components/chat/skins/base/ui/command.tsx +185 -0
  97. package/src/components/chat/skins/base/ui/dialog.tsx +168 -0
  98. package/src/components/chat/skins/base/ui/dot-matrix.tsx +267 -0
  99. package/src/components/chat/skins/base/ui/popover.tsx +97 -0
  100. package/src/components/chat/skins/base/ui/skeleton.tsx +20 -0
  101. package/src/components/chat/skins/base/ui/textarea.tsx +24 -0
  102. package/src/components/chat/skins/base/ui/tooltip.tsx +73 -0
  103. package/src/components/chat/skins/base-assistant-ui/config-provider.tsx +90 -0
  104. package/src/components/chat/skins/base-assistant-ui/defaults.ts +419 -0
  105. package/src/components/chat/skins/base-assistant-ui/index.tsx +44 -0
  106. package/src/components/chat/skins/chatgpt.tsx +448 -0
  107. package/src/components/chat/skins/claude.tsx +380 -0
  108. package/src/components/chat/skins/digichat-composer-toolbar.tsx +151 -0
  109. package/src/components/chat/skins/digichat-context-meter-shares.ts +158 -0
  110. package/src/components/chat/skins/digichat-context-meter.tsx +243 -0
  111. package/src/components/chat/skins/digichat-meter-tone.ts +26 -0
  112. package/src/components/chat/skins/digichat-usage-meter.tsx +103 -0
  113. package/src/components/chat/skins/digichat.tsx +144 -0
  114. package/src/components/chat/skins/expo-react-native.tsx +29 -0
  115. package/src/components/chat/skins/gemini.tsx +322 -0
  116. package/src/components/chat/skins/grok-icon.tsx +34 -0
  117. package/src/components/chat/skins/grok.tsx +369 -0
  118. package/src/components/chat/skins/index.ts +46 -0
  119. package/src/components/chat/skins/perplexity.tsx +462 -0
  120. package/src/components/chat/skins/product-page-assistant/assistant-modal.tsx +73 -0
  121. package/src/components/chat/skins/product-page-assistant/index.tsx +19 -0
  122. package/src/components/chat/skins/product-page-assistant/product-dashboard.tsx +164 -0
  123. package/src/components/chat/skins/react-ink.tsx +97 -0
  124. package/src/components/chat/skins/thread-skin-host-contract.ts +102 -0
  125. package/src/components/chat/skins/thread-skin-view.tsx +156 -0
  126. package/src/components/chat/skins/thread-skins.ts +143 -0
  127. package/src/components/chat/skins/tooltip-icon-button.tsx +35 -0
  128. package/src/components/chat/skins/ui/dropdown-menu.tsx +272 -0
  129. package/src/components/chat/skins/webpage-assistant/assistant-config.ts +238 -0
  130. package/src/components/chat/skins/webpage-assistant/assistant-modal.tsx +78 -0
  131. package/src/components/chat/skins/webpage-assistant/config-provider.tsx +132 -0
  132. package/src/components/chat/skins/webpage-assistant/docs-app.tsx +106 -0
  133. package/src/components/chat/skins/webpage-assistant/docs-article.tsx +109 -0
  134. package/src/components/chat/skins/webpage-assistant/docs-assistant.tsx +73 -0
  135. package/src/components/chat/skins/webpage-assistant/docs-nav.tsx +81 -0
  136. package/src/components/chat/skins/webpage-assistant/host-ui.ts +79 -0
  137. package/src/components/chat/skins/webpage-assistant/index.tsx +12 -0
  138. package/src/components/chat/skins/webpage-assistant/markdown-page.tsx +11 -0
  139. package/src/components/chat/skins/webpage-assistant/pages.ts +9 -0
  140. package/src/components/chat/skins/webpage-assistant/types.ts +178 -0
  141. package/src/components/chat/skins/webpage-assistant/use-mobile.ts +19 -0
  142. package/src/components/chat/stock/SOURCE.md +90 -0
  143. package/src/components/chat/stock/artifacts-panel.tsx +305 -0
  144. package/src/components/chat/stock/attachment.aui.tsx +280 -0
  145. package/src/components/chat/stock/chat-notice.tsx +143 -0
  146. package/src/components/chat/stock/chat-private-mode.tsx +64 -0
  147. package/src/components/chat/stock/deploy-ui-context.tsx +89 -0
  148. package/src/components/chat/stock/embed-chat-prefs.tsx +471 -0
  149. package/src/components/chat/stock/file.tsx +265 -0
  150. package/src/components/chat/stock/follow-up-suggestions.aui.tsx +83 -0
  151. package/src/components/chat/stock/image.tsx +531 -0
  152. package/src/components/chat/stock/index.ts +129 -0
  153. package/src/components/chat/stock/json-view.tsx +140 -0
  154. package/src/components/chat/stock/markdown-text.tsx +319 -0
  155. package/src/components/chat/stock/message-error.aui.tsx +96 -0
  156. package/src/components/chat/stock/message-export-menu.tsx +156 -0
  157. package/src/components/chat/stock/palette-row-preview.tsx +26 -0
  158. package/src/components/chat/stock/reasoning.aui.tsx +120 -0
  159. package/src/components/chat/stock/reasoning.tsx +335 -0
  160. package/src/components/chat/stock/skin-chrome.tsx +81 -0
  161. package/src/components/chat/stock/skin-credit.tsx +63 -0
  162. package/src/components/chat/stock/skin-palette-bridge.tsx +235 -0
  163. package/src/components/chat/stock/skin-palette-context.ts +16 -0
  164. package/src/components/chat/stock/skin-runtime.tsx +52 -0
  165. package/src/components/chat/stock/skin-slash-palette.tsx +393 -0
  166. package/src/components/chat/stock/skin-types.ts +217 -0
  167. package/src/components/chat/stock/stock-chat-prefs-host.tsx +501 -0
  168. package/src/components/chat/stock/stock-send-gate.tsx +94 -0
  169. package/src/components/chat/stock/stock-shape.tsx +39 -0
  170. package/src/components/chat/stock/thread.aui.tsx +645 -0
  171. package/src/components/chat/stock/tool-display.ts +6 -0
  172. package/src/components/chat/stock/tool-fallback.aui.tsx +866 -0
  173. package/src/components/chat/stock/tool-group.aui.tsx +244 -0
  174. package/src/components/chat/stock/tool-surface.ts +120 -0
  175. package/src/components/chat/stock/tooltip-icon-button.tsx +49 -0
  176. package/src/components/chat/stock/ui/avatar.tsx +108 -0
  177. package/src/components/chat/stock/ui/button.tsx +81 -0
  178. package/src/components/chat/stock/ui/collapsible.tsx +21 -0
  179. package/src/components/chat/stock/ui/dialog.tsx +163 -0
  180. package/src/components/chat/stock/ui/skeleton.tsx +13 -0
  181. package/src/components/chat/stock/ui/textarea.tsx +20 -0
  182. package/src/components/chat/stock/ui/tooltip.tsx +68 -0
  183. package/src/components/chat/stock/use-attachment-src.ts +42 -0
  184. package/src/components/chat/stock/use-copy-to-clipboard.ts +29 -0
  185. package/src/components/chat/strip-model-boilerplate.ts +42 -0
  186. package/src/components/chat/suggestion-cycle.tsx +230 -0
  187. package/src/components/chat/suggestion-scroll-row.tsx +81 -0
  188. package/src/components/chat/trace-grouping/chain-group-by.ts +44 -0
  189. package/src/components/chat/trace-grouping/chain-state.ts +141 -0
  190. package/src/components/chat/trace-grouping/index.ts +32 -0
  191. package/src/components/chat/trace-grouping/tool-row.ts +74 -0
  192. package/src/components/chat/trace-grouping/use-deploy-work-disclosure.ts +35 -0
  193. package/src/components/chat/trace-grouping/use-work-chain.ts +103 -0
  194. package/src/components/chat/trace-i18n/core.ts +48 -0
  195. package/src/components/chat/trace-i18n/index.tsx +23 -0
  196. package/src/components/chat/trace-i18n/locales/en.ts +24 -0
  197. package/src/components/chat/trace-i18n/locales/fr.ts +28 -0
  198. package/src/components/chat/trace-i18n/types.ts +35 -0
  199. package/src/components/chat/trace-spacing.ts +249 -0
  200. package/src/components/chat/transcript/activity-view.ts +375 -0
  201. package/src/components/chat/transcript/chat-export.ts +133 -0
  202. package/src/components/chat/transcript/index.ts +10 -0
  203. package/src/components/chat/transcript/save-file.ts +209 -0
  204. package/src/components/chat/transcript/transcript-markdown.ts +428 -0
  205. package/src/components/chat/transcript/types.ts +81 -0
  206. package/src/components/chat/turn-outcome.ts +52 -0
  207. package/src/components/chat/use-warmup-phase.ts +18 -0
  208. package/src/components/chat/work-status-lead.tsx +49 -0
  209. package/src/components/chrome.tsx +264 -0
  210. package/src/components/command-palette/CommandPalette.tsx +404 -0
  211. package/src/components/command-palette/index.ts +6 -0
  212. package/src/components/contact/ContactMailto.tsx +112 -0
  213. package/src/components/contact/index.ts +5 -0
  214. package/src/components/conviction/ConvictionMeter.tsx +40 -0
  215. package/src/components/conviction/SignedConvictionBadge.tsx +26 -0
  216. package/src/components/conviction/index.ts +7 -0
  217. package/src/components/data-layout/BentoGrid.tsx +52 -0
  218. package/src/components/data-layout/CardRail.tsx +150 -0
  219. package/src/components/data-layout/DotMatrixStat.tsx +65 -0
  220. package/src/components/data-layout/FeatureCell.tsx +80 -0
  221. package/src/components/data-layout/MediaFrame.tsx +125 -0
  222. package/src/components/data-layout/ModuleGrid.tsx +735 -0
  223. package/src/components/data-layout/Odometer.tsx +149 -0
  224. package/src/components/data-layout/ProductFrame.tsx +79 -0
  225. package/src/components/data-layout/TestimonialWall.tsx +139 -0
  226. package/src/components/data-layout/index.ts +19 -0
  227. package/src/components/data-layout/treemap.ts +368 -0
  228. package/src/components/deck/DeckStack.tsx +243 -0
  229. package/src/components/desk/DataTable.tsx +373 -0
  230. package/src/components/desk/KpiGrid.tsx +80 -0
  231. package/src/components/desk/Sparkline.tsx +63 -0
  232. package/src/components/desk/StateBlock.tsx +132 -0
  233. package/src/components/desk/index.ts +18 -0
  234. package/src/components/diagrams/ArchitectureDiagram.tsx +350 -0
  235. package/src/components/diagrams/ArchitectureTour.tsx +912 -0
  236. package/src/components/diagrams/TerminalSchematic.tsx +192 -0
  237. package/src/components/diagrams/architecture-svg.tsx +384 -0
  238. package/src/components/diagrams/index.ts +30 -0
  239. package/src/components/diagrams/mermaid-theme.ts +115 -0
  240. package/src/components/diagrams/tour-camera.ts +171 -0
  241. package/src/components/docs/CodeTabs.tsx +90 -0
  242. package/src/components/docs/CopyCommand.tsx +151 -0
  243. package/src/components/docs/DocsLayout.tsx +197 -0
  244. package/src/components/docs/DocsSearch.tsx +97 -0
  245. package/src/components/docs/Endpoint.tsx +135 -0
  246. package/src/components/document/DocumentFrame.tsx +43 -0
  247. package/src/components/document/GlyphList.tsx +51 -0
  248. package/src/components/document/PageTitle.tsx +44 -0
  249. package/src/components/document/Prose.tsx +38 -0
  250. package/src/components/document/Section.tsx +55 -0
  251. package/src/components/document/index.ts +13 -0
  252. package/src/components/effects-chrome/AnnouncementBar.tsx +88 -0
  253. package/src/components/effects-chrome/HorizontalScrollTrack.tsx +461 -0
  254. package/src/components/effects-chrome/Pipeline.tsx +226 -0
  255. package/src/components/effects-chrome/RotatingPrompts.tsx +116 -0
  256. package/src/components/effects-chrome/StackingPanels.tsx +101 -0
  257. package/src/components/effects-chrome/TabStrip.tsx +232 -0
  258. package/src/components/effects-chrome/ToastStack.tsx +201 -0
  259. package/src/components/effects-chrome/horizontal-track-core.ts +70 -0
  260. package/src/components/effects-chrome/index.ts +35 -0
  261. package/src/components/emblems.tsx +188 -0
  262. package/src/components/faviconTheme.ts +23 -0
  263. package/src/components/figure/Figure.tsx +38 -0
  264. package/src/components/figure/index.ts +2 -0
  265. package/src/components/finance-charts/DrawdownPlot.tsx +76 -0
  266. package/src/components/finance-charts/EquityCurve.tsx +71 -0
  267. package/src/components/finance-charts/PriceChart.tsx +119 -0
  268. package/src/components/finance-charts/chart-host.tsx +236 -0
  269. package/src/components/finance-charts/chart-scale.ts +93 -0
  270. package/src/components/finance-charts/demo-data.ts +88 -0
  271. package/src/components/finance-charts/index.ts +46 -0
  272. package/src/components/finance-charts/lw-chart.tsx +292 -0
  273. package/src/components/finance-composites/MarketBar.tsx +243 -0
  274. package/src/components/finance-composites/OrderBook.tsx +133 -0
  275. package/src/components/finance-composites/PerformanceDashboard.tsx +185 -0
  276. package/src/components/finance-composites/SortableTable.tsx +144 -0
  277. package/src/components/finance-composites/StockTicker.tsx +65 -0
  278. package/src/components/finance-composites/SyncedTearsheet.tsx +226 -0
  279. package/src/components/finance-composites/index.ts +28 -0
  280. package/src/components/finance-tearsheet/KpiStrip.tsx +49 -0
  281. package/src/components/finance-tearsheet/LiveBadge.tsx +29 -0
  282. package/src/components/finance-tearsheet/ReturnsMatrix.tsx +321 -0
  283. package/src/components/finance-tearsheet/StrategyTearsheet.tsx +99 -0
  284. package/src/components/finance-tearsheet/TearsheetCard.tsx +54 -0
  285. package/src/components/finance-tearsheet/TradeLogTable.tsx +73 -0
  286. package/src/components/finance-tearsheet/charts.tsx +2624 -0
  287. package/src/components/finance-tearsheet/demo-data.ts +177 -0
  288. package/src/components/finance-tearsheet/format.ts +41 -0
  289. package/src/components/finance-tearsheet/index.ts +120 -0
  290. package/src/components/finance-tearsheet/print.ts +52 -0
  291. package/src/components/finance-tearsheet/risk-bands.ts +48 -0
  292. package/src/components/finance-tearsheet/stats.ts +35 -0
  293. package/src/components/finance-tearsheet/strategy-sheet-model.ts +238 -0
  294. package/src/components/finance-tearsheet/types.ts +58 -0
  295. package/src/components/footer/FooterCells.tsx +109 -0
  296. package/src/components/footer/index.ts +6 -0
  297. package/src/components/graph.tsx +158 -0
  298. package/src/components/icons.tsx +98 -0
  299. package/src/components/landing/PixelWordmark.tsx +36 -0
  300. package/src/components/logos.ts +39 -0
  301. package/src/components/marquee/Marquee.tsx +204 -0
  302. package/src/components/metrics/PerfMetrics.tsx +68 -0
  303. package/src/components/metrics/StatCounter.tsx +104 -0
  304. package/src/components/page-geometry.tsx +177 -0
  305. package/src/components/pricing/Pricing.tsx +174 -0
  306. package/src/components/pricing/PricingMatrix.tsx +219 -0
  307. package/src/components/prose/index.ts +2 -0
  308. package/src/components/prose/prose.tsx +86 -0
  309. package/src/components/repo-activity/RepoActivity.tsx +599 -0
  310. package/src/components/repo-activity/RepoHeatmap.tsx +225 -0
  311. package/src/components/repo-activity/demo.ts +201 -0
  312. package/src/components/repo-activity/fetch.ts +211 -0
  313. package/src/components/repo-activity/heatmap.ts +123 -0
  314. package/src/components/repo-activity/index.ts +28 -0
  315. package/src/components/repo-activity/types.ts +99 -0
  316. package/src/components/stages/NumberedStages.tsx +116 -0
  317. package/src/components/symbols/marks.tsx +116 -0
  318. package/src/components/symbols/terminal-lockup.tsx +136 -0
  319. package/src/components/symbols/terminal-marks.tsx +226 -0
  320. package/src/components/terminal/ChatResponseLoader.tsx +67 -0
  321. package/src/components/terminal/ContainerBootLoader.tsx +82 -0
  322. package/src/components/terminal/TerminalStepCaret.tsx +202 -0
  323. package/src/components/themeInit.ts +24 -0
  324. package/src/components/typography/MotionReveal.tsx +108 -0
  325. package/src/components/typography/TypewriterReveal.tsx +101 -0
  326. package/src/components/typography/WordReveal.tsx +143 -0
  327. package/src/data/modules.ts +378 -0
  328. package/src/data/subsystems.ts +101 -0
  329. package/src/index.ts +587 -0
  330. package/src/lib/base-path.ts +60 -0
  331. package/src/lib/cx.ts +25 -0
  332. package/src/lib/gloomberb.ts +69 -0
  333. package/src/lib/record.ts +19 -0
  334. package/src/lib/stub-payload.ts +183 -0
  335. package/src/lib/useBodyScrollLock.ts +44 -0
  336. package/src/lib/utils.ts +6 -0
  337. package/src/motion/primitives.tsx +105 -0
  338. package/src/motion/scroll-glide.ts +62 -0
  339. package/src/motion/scrolly-core.ts +38 -0
  340. package/src/motion/scrolly.tsx +95 -0
  341. package/src/navigation/HashScrollManager.tsx +167 -0
  342. package/src/navigation/hashScroll.ts +78 -0
  343. package/src/replay/browser.ts +280 -0
  344. package/src/replay/chat-export-run.ts +121 -0
  345. package/src/replay/export-format.ts +25 -0
  346. package/src/replay/export-mount.ts +32 -0
  347. package/src/replay/filename.ts +54 -0
  348. package/src/replay/index.ts +21 -0
  349. package/src/replay/redact-dom.ts +178 -0
  350. package/src/replay/redact.ts +113 -0
  351. package/src/replay/snapshot.ts +659 -0
  352. package/src/styles/account-auth.css +339 -0
  353. package/src/styles/brand-wordmark.css +11 -0
  354. package/src/styles/card-rail.css +120 -0
  355. package/src/styles/chat-aui.css +1143 -0
  356. package/src/styles/chat-core.css +469 -0
  357. package/src/styles/chat-digichat.css +2531 -0
  358. package/src/styles/chat-math.css +70 -0
  359. package/src/styles/chat-skin-palette.css +138 -0
  360. package/src/styles/chat-stock-menu.css +37 -0
  361. package/src/styles/chat-widgets.css +190 -0
  362. package/src/styles/command-palette.css +372 -0
  363. package/src/styles/controls-core.css +2261 -0
  364. package/src/styles/controls-overlay.css +603 -0
  365. package/src/styles/data-layout.css +288 -0
  366. package/src/styles/deck.css +141 -0
  367. package/src/styles/diagrams.css +1860 -0
  368. package/src/styles/digichat-app-theme.css +250 -0
  369. package/src/styles/digichat-boot-loader.css +487 -0
  370. package/src/styles/digichat-launcher.css +377 -0
  371. package/src/styles/docs.css +165 -0
  372. package/src/styles/effects-chrome.css +888 -0
  373. package/src/styles/finance-composites.css +214 -0
  374. package/src/styles/finance-tearsheet-overlay.css +90 -0
  375. package/src/styles/finance-tearsheet.css +945 -0
  376. package/src/styles/marquee.css +168 -0
  377. package/src/styles/metrics.css +82 -0
  378. package/src/styles/nav-shell.css +551 -0
  379. package/src/styles/pricing.css +79 -0
  380. package/src/styles/repo-activity.css +575 -0
  381. package/src/styles/stages.css +69 -0
  382. package/src/styles/terminal-loaders.css +122 -0
  383. package/src/styles/terminal-manifest.css +228 -0
  384. package/src/styles/web-theme.css +1007 -0
  385. package/src/styles/word-reveal.css +204 -0
  386. package/src/theme/apply-theme.ts +214 -0
  387. package/src/theme/index.ts +27 -0
  388. package/src/theme/palette-registry.ts +855 -0
  389. package/src/theme/tui-prefs.ts +64 -0
  390. package/src/ui/alert.tsx +78 -0
  391. package/src/ui/avatar.tsx +104 -0
  392. package/src/ui/badge.tsx +75 -0
  393. package/src/ui/breadcrumb.tsx +61 -0
  394. package/src/ui/button.tsx +67 -0
  395. package/src/ui/card.tsx +139 -0
  396. package/src/ui/checkbox.tsx +27 -0
  397. package/src/ui/collapsible.tsx +32 -0
  398. package/src/ui/date-pager.tsx +325 -0
  399. package/src/ui/dialog.tsx +157 -0
  400. package/src/ui/dropdown-menu.tsx +267 -0
  401. package/src/ui/empty-state.tsx +165 -0
  402. package/src/ui/field.tsx +104 -0
  403. package/src/ui/form.tsx +36 -0
  404. package/src/ui/icon-button.tsx +36 -0
  405. package/src/ui/index.ts +34 -0
  406. package/src/ui/input.tsx +33 -0
  407. package/src/ui/kbd.tsx +30 -0
  408. package/src/ui/label.tsx +32 -0
  409. package/src/ui/pager.tsx +119 -0
  410. package/src/ui/pagination.tsx +126 -0
  411. package/src/ui/radio-group.tsx +51 -0
  412. package/src/ui/search-bar.tsx +85 -0
  413. package/src/ui/segmented-control.tsx +76 -0
  414. package/src/ui/select.tsx +257 -0
  415. package/src/ui/separator.tsx +24 -0
  416. package/src/ui/sheet.tsx +141 -0
  417. package/src/ui/skeleton.tsx +76 -0
  418. package/src/ui/slider.tsx +76 -0
  419. package/src/ui/switch.tsx +31 -0
  420. package/src/ui/table.tsx +179 -0
  421. package/src/ui/tabs.tsx +89 -0
  422. package/src/ui/tags-input.tsx +168 -0
  423. package/src/ui/textarea.tsx +17 -0
  424. package/src/ui/tooltip.tsx +71 -0
@@ -0,0 +1,177 @@
1
+ /**
2
+ * DEMO DATA ONLY (#1463) — one deterministic backtest for the
3
+ * finance-tearsheet reference specimens: a three-year daily OHLC walk, a
4
+ * long/short trade log marked on it (last leg open), and the
5
+ * mark-to-market equity / underwater curves those trades imply. Same LCG
6
+ * doctrine as the finance-charts demos: stable across renders and runtimes,
7
+ * and the components take data via required props precisely so demo numbers
8
+ * can never ship by omission.
9
+ */
10
+ import type {
11
+ TearsheetOhlcBar,
12
+ TearsheetSeriesPoint,
13
+ TearsheetTrade,
14
+ TradeReturnBar,
15
+ } from "./types";
16
+
17
+ /** Deterministic LCG in [0, 1) — stable across renders and runtimes. */
18
+ function lcg(seed: number): () => number {
19
+ let s = seed;
20
+ return () => {
21
+ s = (s * 1103515245 + 12345) & 0x7fffffff;
22
+ return s / 0x7fffffff;
23
+ };
24
+ }
25
+
26
+ function isoOffset(startUtc: Date, days: number): string {
27
+ const date = new Date(startUtc);
28
+ date.setUTCDate(startUtc.getUTCDate() + days);
29
+ return date.toISOString().slice(0, 10);
30
+ }
31
+
32
+ const N_BARS = 780;
33
+ const START = new Date(Date.UTC(2023, 0, 2));
34
+
35
+ function ohlcDemo(): TearsheetOhlcBar[] {
36
+ const rnd = lcg(1463);
37
+ const bars: TearsheetOhlcBar[] = [];
38
+ let price = 68;
39
+ for (let i = 0; i < N_BARS; i++) {
40
+ // Regime-y drift: slow sine bias + noise, so trends exist for trades to ride.
41
+ const bias = Math.sin(i / 90) * 0.008 + 0.0008;
42
+ const o = price;
43
+ const c = Math.max(9, o * (1 + bias + (rnd() - 0.5) * 0.045));
44
+ const h = Math.max(o, c) * (1 + rnd() * 0.014);
45
+ const l = Math.min(o, c) * (1 - rnd() * 0.014);
46
+ bars.push({ t: isoOffset(START, i), o, h, l, c });
47
+ price = c;
48
+ }
49
+ return bars;
50
+ }
51
+
52
+ interface DemoBuild {
53
+ bars: TearsheetOhlcBar[];
54
+ trades: TearsheetTrade[];
55
+ equity: TearsheetSeriesPoint[];
56
+ drawdown: TearsheetSeriesPoint[];
57
+ tradeReturnBars: TradeReturnBar[];
58
+ }
59
+
60
+ function build(): DemoBuild {
61
+ const bars = ohlcDemo();
62
+ const rnd = lcg(97031);
63
+ const trades: TearsheetTrade[] = [];
64
+
65
+ // Round trips over the bar walk: hold 12–60 bars, sit out 3–18, flip
66
+ // direction with the local regime. The final leg stays open (marked to the
67
+ // last close) so the open-trade grammar shows everywhere it exists.
68
+ let i = 5;
69
+ let n = 1;
70
+ let equityMark = 100_000;
71
+ while (i < N_BARS - 70) {
72
+ const hold = 12 + Math.floor(rnd() * 48);
73
+ const exitIdx = Math.min(N_BARS - 2, i + hold);
74
+ const direction: "long" | "short" = Math.sin(i / 90) + (rnd() - 0.5) * 0.6 > 0 ? "long" : "short";
75
+ const entry = bars[i].c;
76
+ const exit = bars[exitIdx].c;
77
+ const pnlPct = direction === "long" ? (exit / entry - 1) * 100 : (entry / exit - 1) * 100;
78
+ const qty = Math.round((equityMark / entry) * 100) / 100;
79
+ const pnl = equityMark * (pnlPct / 100);
80
+ equityMark += pnl;
81
+ trades.push({
82
+ n,
83
+ direction,
84
+ entry_label: direction === "long" ? "breakout" : "fade",
85
+ entry_date: bars[i].t,
86
+ entry_price: entry,
87
+ exit_date: bars[exitIdx].t,
88
+ exit_price: exit,
89
+ qty,
90
+ pnl,
91
+ pnl_pct: pnlPct,
92
+ equity_after: equityMark,
93
+ exit_reason: rnd() > 0.5 ? "signal" : "stop",
94
+ max_runup_pct: Math.abs(pnlPct) * (1 + rnd() * 0.4),
95
+ max_drawdown_pct: -Math.abs(pnlPct) * rnd() * 0.6,
96
+ });
97
+ n += 1;
98
+ i = exitIdx + 3 + Math.floor(rnd() * 15);
99
+ }
100
+
101
+ // Open leg: enters near the end, marks to the last close.
102
+ const lastBar = bars[N_BARS - 1];
103
+ const openIdx = N_BARS - 40;
104
+ const openEntry = bars[openIdx].c;
105
+ const openPct = (lastBar.c / openEntry - 1) * 100;
106
+ trades.push({
107
+ n,
108
+ direction: "long",
109
+ entry_label: "breakout",
110
+ entry_date: bars[openIdx].t,
111
+ entry_price: openEntry,
112
+ exit_date: "",
113
+ exit_price: lastBar.c,
114
+ qty: Math.round((equityMark / openEntry) * 100) / 100,
115
+ pnl: equityMark * (openPct / 100),
116
+ pnl_pct: openPct,
117
+ equity_after: equityMark,
118
+ exit_reason: "open",
119
+ max_runup_pct: Math.max(0, openPct) * 1.2,
120
+ max_drawdown_pct: Math.min(0, openPct) * 0.8,
121
+ });
122
+
123
+ // Mark-to-market equity: ride each trade's direction bar to bar, flat
124
+ // between trades — the curve the KPIs, matrix, and drawdown derive from.
125
+ const equity: TearsheetSeriesPoint[] = [];
126
+ const drawdown: TearsheetSeriesPoint[] = [];
127
+ let eq = 100_000;
128
+ let peak = eq;
129
+ let t = 0;
130
+ for (let b = 0; b < N_BARS; b++) {
131
+ const bar = bars[b];
132
+ let active: TearsheetTrade | undefined;
133
+ while (t < trades.length && bar.t >= trades[t].entry_date) {
134
+ const exitT = trades[t].exit_date || lastBar.t;
135
+ if (bar.t <= exitT) {
136
+ active = trades[t];
137
+ break;
138
+ }
139
+ t += 1;
140
+ }
141
+ if (b > 0 && active) {
142
+ const barRet = bars[b].c / bars[b - 1].c - 1;
143
+ eq *= 1 + (active.direction === "long" ? barRet : -barRet);
144
+ }
145
+ peak = Math.max(peak, eq);
146
+ equity.push({ t: bar.t, v: eq });
147
+ drawdown.push({ t: bar.t, v: Math.round((eq / peak - 1) * 1000) / 10 });
148
+ }
149
+
150
+ const closed = trades.filter((tr) => tr.exit_reason !== "open");
151
+ const open = trades[trades.length - 1];
152
+ const tradeReturnBars: TradeReturnBar[] = closed.map((tr) => ({
153
+ t: tr.exit_date,
154
+ pct: tr.pnl_pct,
155
+ open: false,
156
+ trade: tr,
157
+ }));
158
+ tradeReturnBars.push({ t: lastBar.t, pct: open.pnl_pct, open: true, trade: open });
159
+
160
+ return { bars, trades, equity, drawdown, tradeReturnBars };
161
+ }
162
+
163
+ const BUILT = build();
164
+
165
+ /** The demo backtest the reference tearsheet specimens compose. */
166
+ export const TEARSHEET_DEMO = {
167
+ symbol: "DGQ-USD",
168
+ periodStart: BUILT.bars[0].t,
169
+ periodEnd: BUILT.bars[BUILT.bars.length - 1].t,
170
+ /** Shared x-span for the synced charts. */
171
+ fullSpan: [BUILT.bars[0].t, BUILT.bars[BUILT.bars.length - 1].t] as [string, string],
172
+ bars: BUILT.bars,
173
+ trades: BUILT.trades,
174
+ equity: BUILT.equity,
175
+ drawdown: BUILT.drawdown,
176
+ tradeReturnBars: BUILT.tradeReturnBars,
177
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Number formatting shared by the finance-tearsheet charts, tables, and card
3
+ * KPIs (#1463) — verbatim from
4
+ * apps/digiquant-web/components/tearsheet/format.ts so promoted surfaces
5
+ * render figure-for-figure identical.
6
+ */
7
+
8
+ /** Compact axis/KPI formatting so huge compounded figures never overflow. */
9
+ export function fmtCompact(v: number | null | undefined): string {
10
+ if (v === null || v === undefined || Number.isNaN(v)) return "";
11
+ const a = Math.abs(v);
12
+ if (a >= 1e9) return (v / 1e9).toFixed(a >= 1e10 ? 0 : 1) + "B";
13
+ if (a >= 1e6) return (v / 1e6).toFixed(a >= 1e7 ? 0 : 1) + "M";
14
+ if (a >= 1e3) return (v / 1e3).toFixed(a >= 1e4 ? 0 : 1) + "K";
15
+ if (a >= 1) return v.toFixed(0);
16
+ if (a === 0) return "0";
17
+ return v.toFixed(2);
18
+ }
19
+
20
+ export function fmtPct(v: number | null | undefined): string {
21
+ if (v === null || v === undefined) return "n/a";
22
+ if (Math.abs(v) >= 10000) return fmtCompact(v) + "%";
23
+ return v.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + "%";
24
+ }
25
+
26
+ export function fmtMoney(v: number | null | undefined): string {
27
+ if (v === null || v === undefined) return "n/a";
28
+ if (Math.abs(v) >= 100000) return fmtCompact(v);
29
+ return v.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
30
+ }
31
+
32
+ export function fmtNum(v: number | null | undefined, d = 0): string {
33
+ if (v === null || v === undefined) return "n/a";
34
+ return v.toLocaleString("en-US", { minimumFractionDigits: d, maximumFractionDigits: d });
35
+ }
36
+
37
+ /** Money tone class for a signed value: `.is-pos` / `.is-neg` / none at 0. */
38
+ export function toneClass(v: number | null | undefined): string {
39
+ if (v === null || v === undefined) return "";
40
+ return v > 0 ? "is-pos" : v < 0 ? "is-neg" : "";
41
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * finance-tearsheet family barrel (#1463) — the print-grade SVG tearsheet
3
+ * grammar reverse-promoted from apps/digiquant-web/components/tearsheet/.
4
+ * Everything here participates in the PDF export (flushSync + window.print
5
+ * over ONE render tree), so the charts are pure SVG — the canvas
6
+ * finance-charts / finance-composites families are the screen-only DASHBOARD
7
+ * grammar. The split ruling lives in packages/ui/CHARTS.md.
8
+ *
9
+ * Wiring (consuming app):
10
+ * globals.css @import "@digithings-ai/ui/styles/finance-tearsheet.css";
11
+ * (plainly — the sheet manages its own layering)
12
+ * @source "<path-to>/packages/ui/src/components/finance-tearsheet";
13
+ * Data derivation (series clipping, pivot stats, trade sorting, CAGR et al.)
14
+ * stays app-owned — components take render-ready props.
15
+ */
16
+
17
+ export {
18
+ CandlestickChart,
19
+ TimeSeries,
20
+ MultiTimeSeries,
21
+ RiskBandStrip,
22
+ AllocationStepChart,
23
+ SignedBars,
24
+ ContributionReturnChart,
25
+ TradeReturnChart,
26
+ SegToggle,
27
+ ChartLegend,
28
+ ChartResetButton,
29
+ LOOKBACK_OPTIONS,
30
+ MIN_VIEW,
31
+ clampView,
32
+ viewWindowForPreset,
33
+ viewWindowLastYear,
34
+ matchLookbackPreset,
35
+ viewsNear,
36
+ sliceByView,
37
+ type CandlestickChartProps,
38
+ type TimeSeriesProps,
39
+ type MultiTimeSeriesProps,
40
+ type OverlaySeries,
41
+ type RiskBandStripProps,
42
+ type AllocationStepChartProps,
43
+ type AllocationFillMarker,
44
+ type SignedBarsProps,
45
+ type ContributionReturnChartProps,
46
+ type ContributionReturnPoint,
47
+ type TradeReturnChartProps,
48
+ type ChartScale,
49
+ type ChartTone,
50
+ type OverlayTone,
51
+ type ReferenceTone,
52
+ type ReferenceLineSpec,
53
+ type ReferenceBandSpec,
54
+ type ReferenceMarkerSpec,
55
+ type ChartReferences,
56
+ type ChartLegendKind,
57
+ type ViewWindow,
58
+ type LookbackPreset,
59
+ } from "./charts";
60
+ export { RISK_BANDS, riskBandLabel, dcaRateCopy, type RiskBand } from "./risk-bands";
61
+ export { ReturnsMatrix, type ReturnsPeriod, type MatrixMetric } from "./ReturnsMatrix";
62
+ export { KpiStrip, Kpi, type KpiStripProps, type KpiProps } from "./KpiStrip";
63
+ export {
64
+ TradeLogTable,
65
+ DirectionPill,
66
+ type TradeLogTableProps,
67
+ type TradeLogColumn,
68
+ type TradeLogRow,
69
+ } from "./TradeLogTable";
70
+ export {
71
+ TearsheetCard,
72
+ TearsheetCardKpis,
73
+ TearsheetCardKpi,
74
+ type TearsheetCardProps,
75
+ } from "./TearsheetCard";
76
+ export { LiveBadge, type LiveBadgeProps } from "./LiveBadge";
77
+ export { PRINT_FULL_VIEW, runTearsheetPrint } from "./print";
78
+ export {
79
+ isOpenTrade,
80
+ type TearsheetSeriesPoint,
81
+ type TearsheetOhlcBar,
82
+ type TearsheetTrade,
83
+ type TradeReturnBar,
84
+ } from "./types";
85
+ export { fmtCompact, fmtPct, fmtMoney, fmtNum, toneClass } from "./format";
86
+ export { dailyReturnsFromEquity, annualizedVolPct } from "./stats";
87
+ export {
88
+ computeLivePerformanceKpis,
89
+ computeLiveVsMarkPct,
90
+ dayReturnAnchorNav,
91
+ derivePriceAsOfDate,
92
+ inceptionSignAgreesWithBase100,
93
+ informationRatioFromDaily,
94
+ olsBeta,
95
+ overlappingDailyReturns,
96
+ navHistoryForLiveOverlap,
97
+ relativeMetricsFromReturnSeries,
98
+ sinceInceptionPctFromNav,
99
+ MIN_OVERLAP_DAYS,
100
+ type LiveKpiPosition,
101
+ type LiveKpiNavPoint,
102
+ type LiveKpiBenchmarkPoint,
103
+ type LivePerformanceKpis,
104
+ type LivePerformanceKpisInput,
105
+ // Moved to @digithings-ai/perf-math so framework-free consumers (contract, the R5
106
+ // Worker bundle) never pull React. Re-exported here so existing imports from
107
+ // `@digithings-ai/ui` keep working.
108
+ } from "@digithings-ai/perf-math/live-performance-kpis";
109
+ export { TEARSHEET_DEMO } from "./demo-data";
110
+ export { StrategyTearsheet } from "./StrategyTearsheet";
111
+ export {
112
+ buildStrategyTearsheet,
113
+ seriesOrNull,
114
+ seriesSparkline,
115
+ sheetCagr,
116
+ type StrategySheetBar,
117
+ type StrategySheetMetric,
118
+ type StrategySheetModel,
119
+ type StrategySheetPoint,
120
+ } from "./strategy-sheet-model";
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ /**
3
+ * The tearsheet PDF pipeline (#1463) — promoted from
4
+ * apps/digiquant-web/components/tearsheet/print-tearsheet.ts. "Download
5
+ * PDF" is a shipped feature of this family and the reason it is pure SVG:
6
+ * the same chart component instances re-render synchronously at full span
7
+ * (PRINT_FULL_VIEW, linear scale) before the system print dialog opens, so
8
+ * screen and print share ONE render tree. Canvas engines are disqualified
9
+ * on any surface that participates in this export.
10
+ */
11
+ import { flushSync } from "react-dom";
12
+ import type { ViewWindow } from "./charts";
13
+
14
+ /** Full backtest window — used when rendering charts for PDF export. */
15
+ export const PRINT_FULL_VIEW: ViewWindow = { lo: 0, hi: 1 };
16
+
17
+ /**
18
+ * Prepare the DOM + React state, invoke the system print dialog, then restore.
19
+ * Uses flushSync so charts re-render at full span before the print layout
20
+ * runs. Pins the light theme for paper output (the print grammar in
21
+ * styles/finance-tearsheet.css pins the light tokens as literals) and tags
22
+ * `html.ts-printing` for print-only rules.
23
+ */
24
+ export function runTearsheetPrint(opts: {
25
+ /** document.title while the dialog is open (names the exported PDF). */
26
+ documentTitle: string;
27
+ /** The consumer's `printing` state setter — charts read it to swap to
28
+ * PRINT_FULL_VIEW / linear scale. */
29
+ setPrinting: (printing: boolean) => void;
30
+ }): void {
31
+ const html = document.documentElement;
32
+ const prevTheme = html.getAttribute("data-theme");
33
+ const prevTitle = document.title;
34
+
35
+ html.setAttribute("data-theme", "light");
36
+ html.classList.add("ts-printing");
37
+ document.title = opts.documentTitle;
38
+
39
+ flushSync(() => opts.setPrinting(true));
40
+ try {
41
+ window.print();
42
+ } finally {
43
+ html.classList.remove("ts-printing");
44
+ if (prevTheme === null) {
45
+ html.removeAttribute("data-theme");
46
+ } else {
47
+ html.setAttribute("data-theme", prevTheme);
48
+ }
49
+ document.title = prevTitle;
50
+ flushSync(() => opts.setPrinting(false));
51
+ }
52
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Composite-risk bands for DCA / SDCA tearsheets (#3172).
3
+ *
4
+ * The artifact's scale is 0–100 (cheap → rich). Labels match the published
5
+ * SDCA bands: Fire sale / Accumulate / Value / Above mid / Hot / Bubble.
6
+ * 95–100 is Bubble (the spec's 95–99 band plus the closed top of the scale).
7
+ */
8
+
9
+ export interface RiskBand {
10
+ /** Inclusive lower bound. */
11
+ lo: number;
12
+ /** Exclusive upper bound, except the last band which includes 100. */
13
+ hi: number;
14
+ id: "fire" | "acc" | "value" | "mid" | "hot" | "bubble";
15
+ label: string;
16
+ }
17
+
18
+ export const RISK_BANDS: readonly RiskBand[] = [
19
+ { lo: 0, hi: 10, id: "fire", label: "Fire sale" },
20
+ { lo: 10, hi: 25, id: "acc", label: "Accumulate" },
21
+ { lo: 25, hi: 50, id: "value", label: "Value" },
22
+ { lo: 50, hi: 75, id: "mid", label: "Above mid" },
23
+ { lo: 75, hi: 95, id: "hot", label: "Hot" },
24
+ { lo: 95, hi: 100, id: "bubble", label: "Bubble" },
25
+ ] as const;
26
+
27
+ /** Band copy for a composite risk in [0, 100]. Null/NaN → null. */
28
+ export function riskBandLabel(risk: number | null | undefined): string | null {
29
+ if (risk === null || risk === undefined || Number.isNaN(risk)) return null;
30
+ for (const band of RISK_BANDS) {
31
+ if (risk < band.hi) return band.label;
32
+ }
33
+ return "Bubble";
34
+ }
35
+
36
+ /** Today's-rate sentence for a DCA current signal. */
37
+ export function dcaRateCopy(dailyRatePct: number | null | undefined): string | null {
38
+ if (dailyRatePct === null || dailyRatePct === undefined || Number.isNaN(dailyRatePct)) {
39
+ return null;
40
+ }
41
+ const abs = Math.abs(dailyRatePct).toLocaleString("en-US", {
42
+ minimumFractionDigits: 1,
43
+ maximumFractionDigits: 1,
44
+ });
45
+ if (dailyRatePct > 0) return `buying ${abs}% of remaining cash today`;
46
+ if (dailyRatePct < 0) return `selling ${abs}% of remaining holdings today`;
47
+ return "holding, no trade today";
48
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The two derived statistics the ReturnsMatrix volatility metric needs
3
+ * (#1463), verbatim from apps/digiquant-web/components/tearsheet/stats.ts.
4
+ * The full derived-stats library (CAGR, Sharpe/Sortino/Omega, annual rows …)
5
+ * is app-owned data wiring and stays with the consumers.
6
+ */
7
+
8
+ /** Daily simple returns from a mark-to-market equity curve. */
9
+ export function dailyReturnsFromEquity(points: { v: number }[]): number[] {
10
+ const rets: number[] = [];
11
+ for (let i = 1; i < points.length; i++) {
12
+ const prev = points[i - 1].v;
13
+ if (prev > 0) rets.push(points[i].v / prev - 1);
14
+ }
15
+ return rets;
16
+ }
17
+
18
+ function mean(xs: number[]): number {
19
+ return xs.length ? xs.reduce((a, b) => a + b, 0) / xs.length : 0;
20
+ }
21
+
22
+ function sampleStd(xs: number[]): number {
23
+ if (xs.length < 2) return 0;
24
+ const m = mean(xs);
25
+ const v = xs.reduce((a, x) => a + (x - m) ** 2, 0) / (xs.length - 1);
26
+ return Math.sqrt(v);
27
+ }
28
+
29
+ const TRADING_DAYS = 252;
30
+
31
+ /** Annualized volatility (%) from daily returns. */
32
+ export function annualizedVolPct(returns: number[]): number | null {
33
+ if (returns.length < 2) return null;
34
+ return sampleStd(returns) * Math.sqrt(TRADING_DAYS) * 100;
35
+ }