@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,87 @@
1
+ /**
2
+ * SocialRow — a quiet utility row of company-profile icon buttons.
3
+ * Same borderless `.btn-icon` grammar as the NavShell GitHub slot: radius 0,
4
+ * no fill, ink-mute → ink, phosphor (`--accent`) only on :focus-visible.
5
+ * Not a marketing share bar. The primitive carries no Discord (that network
6
+ * does not exist for the company); default `DIGITHINGS_SOCIALS` is the live
7
+ * GitHub / X / LinkedIn set. Pass `profiles` to retarget; the row never
8
+ * invents networks.
9
+ *
10
+ * Dress lives in styles/nav-shell.css (already imported wherever NavShell
11
+ * is), so a contact band or footer can reuse the buttons without a second
12
+ * sheet.
13
+ */
14
+ import type { ReactNode } from "react";
15
+
16
+ import { GitHubGlyph, LinkedInGlyph, XGlyph } from "./icons";
17
+
18
+ export type SocialNetwork = "github" | "x" | "linkedin";
19
+
20
+ export type SocialProfile = {
21
+ network: SocialNetwork;
22
+ href: string;
23
+ label: string;
24
+ };
25
+
26
+ /** Live company profiles only. Do not add networks we do not run. */
27
+ export const DIGITHINGS_SOCIALS: readonly SocialProfile[] = [
28
+ {
29
+ network: "github",
30
+ href: "https://github.com/digithings-ai/digithings",
31
+ label: "digithings on GitHub",
32
+ },
33
+ {
34
+ network: "x",
35
+ href: "https://x.com/digithingsai",
36
+ label: "digithings on X",
37
+ },
38
+ {
39
+ network: "linkedin",
40
+ href: "https://www.linkedin.com/company/digithingsai/",
41
+ label: "digithings on LinkedIn",
42
+ },
43
+ ];
44
+
45
+ export type SocialRowProps = {
46
+ profiles?: readonly SocialProfile[];
47
+ "aria-label"?: string;
48
+ className?: string;
49
+ };
50
+
51
+ function SocialGlyph({ network }: { network: SocialNetwork }): ReactNode {
52
+ switch (network) {
53
+ case "github":
54
+ return <GitHubGlyph />;
55
+ case "x":
56
+ return <XGlyph />;
57
+ case "linkedin":
58
+ return <LinkedInGlyph />;
59
+ default: {
60
+ const _exhaustive: never = network;
61
+ return _exhaustive;
62
+ }
63
+ }
64
+ }
65
+
66
+ export function SocialRow({
67
+ profiles = DIGITHINGS_SOCIALS,
68
+ "aria-label": ariaLabel = "Company profiles",
69
+ className,
70
+ }: SocialRowProps) {
71
+ return (
72
+ <nav className={className ? `social-row ${className}` : "social-row"} aria-label={ariaLabel}>
73
+ {profiles.map((profile) => (
74
+ <a
75
+ key={profile.network}
76
+ className="btn-icon"
77
+ href={profile.href}
78
+ target="_blank"
79
+ rel="noopener noreferrer"
80
+ aria-label={profile.label}
81
+ >
82
+ <SocialGlyph network={profile.network} />
83
+ </a>
84
+ ))}
85
+ </nav>
86
+ );
87
+ }
@@ -0,0 +1,27 @@
1
+ import { cn } from "../lib/utils";
2
+
3
+ export type SpinnerProps = {
4
+ /** Extra utilities (size overrides, margins, colours) merged after the base. */
5
+ className?: string;
6
+ };
7
+
8
+ /**
9
+ * Spinner — the canonical inline loading glyph. The wave-3 shared replacement
10
+ * for the hand-rolled `<span className="size-[11px] … animate-spin
11
+ * rounded-full border-2 border-current/30 border-t-current" />` idiom that had
12
+ * been copied into three reference specimens (task-1b review, Minor 3).
13
+ *
14
+ * `currentColor`-based, so it inherits the button/label tone; motion-reduce
15
+ * disables the rotation. Import from `@digithings-ai/ui`.
16
+ */
17
+ export function Spinner({ className }: SpinnerProps) {
18
+ return (
19
+ <span
20
+ aria-hidden="true"
21
+ className={cn(
22
+ "size-[11px] shrink-0 animate-spin rounded-full border-2 border-current/30 border-t-current motion-reduce:animate-none",
23
+ className
24
+ )}
25
+ />
26
+ );
27
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * StackLogo — renders a real vendor mark (Simple Icons, MIT data) tinted to
3
+ * --ink-soft, brand colour on hover; or a monogram chip when no mark exists.
4
+ * Icons resolved by slug via a namespace lookup so an unknown/typo'd slug
5
+ * degrades to a monogram rather than breaking the build.
6
+ *
7
+ * Brand marks are trademarks of their owners; Simple Icons provides the icon
8
+ * data under MIT. We render monochrome by default out of respect for brand use.
9
+ */
10
+ "use client";
11
+ import { ICONS } from "./logos";
12
+ import { type StackItem } from "../data/modules";
13
+
14
+ export function StackLogo({ item }: { item: StackItem }) {
15
+ const icon = item.icon ? ICONS[item.icon] ?? null : null;
16
+ if (icon) {
17
+ return (
18
+ <span className="stack-chip" title={item.name}>
19
+ <svg viewBox="0 0 24 24" width="15" height="15" className="stack-ico" style={{ ["--brand" as string]: `#${icon.hex}` }} aria-hidden="true">
20
+ <path d={icon.path} fill="currentColor" />
21
+ </svg>
22
+ <span className="stack-name">{item.name}</span>
23
+ </span>
24
+ );
25
+ }
26
+ return (
27
+ <span className="stack-chip" title={item.name}>
28
+ <span className="stack-mono" aria-hidden="true">{item.mono ?? item.name.slice(0, 2)}</span>
29
+ <span className="stack-name">{item.name}</span>
30
+ </span>
31
+ );
32
+ }
33
+
34
+ export function StackRow({ items, className }: { items: StackItem[]; className?: string }) {
35
+ return (
36
+ <div className={className ?? "stack-row"}>
37
+ {items.map((it) => <StackLogo key={it.name} item={it} />)}
38
+ </div>
39
+ );
40
+ }
@@ -0,0 +1,110 @@
1
+ "use client";
2
+ /** Typed terminal playback — the hero signature. Renders line-by-line with a
3
+ * blinking cursor; instant under reduced-motion. Content is component-authored. */
4
+ import { useEffect, useState } from "react";
5
+ import { useMotionSafe } from "../motion/primitives";
6
+
7
+ export type TermLine =
8
+ | { kind: "cmd" | "out" | "install" | "arrow"; text: string }
9
+ | { kind: "ok" | "mod"; name: string; text: string }
10
+ | { kind: "gap" };
11
+
12
+ /**
13
+ * The column the `ok`/`mod` text starts at — one past the longest name in the
14
+ * list.
15
+ *
16
+ * This used to be a hard-coded `padEnd(15)`, which looks like it guarantees a
17
+ * gap and does not: once a name reaches 15 characters `padEnd` returns it
18
+ * unchanged and the text runs straight into it. `otel-collector` (v13) and
19
+ * `digi-digisearch` (v15) were both glued to the word after them, and both were
20
+ * worked around by renaming the service rather than by fixing the padding.
21
+ *
22
+ * Deriving the column from the lines in hand is what actually holds it: every
23
+ * list aligns to its own longest name, and no name can outgrow it.
24
+ */
25
+ function nameColumn(lines: TermLine[]): number {
26
+ let longest = 0;
27
+ for (const l of lines) if ("name" in l) longest = Math.max(longest, l.name.length);
28
+ return longest + 1;
29
+ }
30
+
31
+ function Line({ l, col }: { l: TermLine; col: number }) {
32
+ switch (l.kind) {
33
+ case "gap": return <br />;
34
+ case "cmd": return <span className="tl-cmd">{l.text}</span>;
35
+ case "out": return <span className="tl-out">{l.text}</span>;
36
+ case "install": return <span className="tl-install">{l.text}</span>;
37
+ case "arrow": return <span className="tl-arrow">{l.text}</span>;
38
+ case "ok": return <span className="tl-ok"><b>{l.name.padEnd(col)}</b>{l.text}</span>;
39
+ case "mod": return <span className="tl-mod"><b>{l.name.padEnd(col)}</b>{l.text} →</span>;
40
+ }
41
+ }
42
+
43
+ export function Terminal({
44
+ title,
45
+ lines,
46
+ size = "default",
47
+ fill = false,
48
+ className,
49
+ }: {
50
+ title: string;
51
+ lines: TermLine[];
52
+ /** `compact` is the smaller register — tighter body type and window bar. */
53
+ size?: "default" | "compact";
54
+ /**
55
+ * Stretch `.term` to its wrapper's height instead of sizing to the text, so
56
+ * a scripted playback never grows the box as lines type in. Pair with a
57
+ * fixed-height wrapper; the body clips rather than expanding.
58
+ */
59
+ fill?: boolean;
60
+ className?: string;
61
+ }) {
62
+ const safe = useMotionSafe();
63
+ const [n, setN] = useState(safe ? 0 : lines.length);
64
+
65
+ useEffect(() => {
66
+ // useMotionSafe resolves after mount (hydration-safe): reduced-motion
67
+ // users reach here with safe=false on the second pass — show everything
68
+ // instantly.
69
+ if (!safe) {
70
+ setN(lines.length);
71
+ return;
72
+ }
73
+ // The lead-in and the inter-line waits are chained timeouts, so the whole
74
+ // chain is tracked and cleared together on cleanup. A first-render effect
75
+ // pass is guaranteed (useMotionSafe flips `mounted` one tick after mount),
76
+ // which re-runs this effect; every pending timer must be cancelled and the
77
+ // chain restarted from zero, or the re-run would leave the body empty.
78
+ let i = 0;
79
+ let timer: ReturnType<typeof setTimeout>;
80
+ const tick = () => {
81
+ i += 1;
82
+ setN(i);
83
+ if (i < lines.length) {
84
+ const prev = lines[i - 1];
85
+ timer = setTimeout(tick, prev.kind === "gap" ? 90 : prev.kind === "cmd" ? 420 : 200);
86
+ }
87
+ };
88
+ timer = setTimeout(tick, 420);
89
+ return () => clearTimeout(timer);
90
+ }, [safe, lines]);
91
+
92
+ const root = ["term", size === "compact" ? "term--compact" : "", fill ? "term--fill" : "", className]
93
+ .filter(Boolean)
94
+ .join(" ");
95
+ const col = nameColumn(lines);
96
+
97
+ return (
98
+ <div className={root}>
99
+ <div className="term-bar"><i /><i /><i /><span className="term-title">{title}</span></div>
100
+ <pre className="term-body">
101
+ {lines.slice(0, n).map((l, k) => (
102
+ <span key={k}>
103
+ <Line l={l} col={col} />{l.kind !== "gap" ? "\n" : ""}
104
+ </span>
105
+ ))}
106
+ {n >= lines.length && <span className="term-cursor" />}
107
+ </pre>
108
+ </div>
109
+ );
110
+ }
@@ -0,0 +1,212 @@
1
+ "use client";
2
+ /**
3
+ * Terminal manifest — the `cli ps` process pane behind digithings-web's
4
+ * ModuleManifest (#1415): a prompt head line, selectable rows (status dot,
5
+ * two-tone mono name, optional port, blurb), and an output panel where the
6
+ * selected row's detail types out at a blinking cursor. Rows arrive as props;
7
+ * selection is uncontrolled by default or controlled via `selectedId`.
8
+ * Row-appear stagger and the type-out both degrade under reduced motion.
9
+ * Pane surface, row states, keyframes, and the container-query column
10
+ * collapse live in styles/terminal-manifest.css (import it once app-wide).
11
+ * The pane deliberately wears the manifest chrome (prompt head line), not
12
+ * the <Terminal> window bar — its frame is page CSS and its body is a
13
+ * scripted playback; compose the two side by side when both are wanted.
14
+ */
15
+ import { useEffect, useState, type ReactNode } from "react";
16
+ import { useMotionSafe } from "../motion/primitives";
17
+
18
+ export type TerminalManifestStatus = "online" | "roadmap";
19
+
20
+ export type TerminalManifestRow = {
21
+ id: string;
22
+ /** Lowercase process name; `namePrefix` splits it into ink + accent. */
23
+ name: string;
24
+ /** Optional port column — rendered only when at least one row carries one. */
25
+ port?: string | number;
26
+ status: TerminalManifestStatus;
27
+ /** Row summary column; also the typed output when `detail` is absent. */
28
+ blurb: string;
29
+ /** Output typed at the cursor when the row is selected. */
30
+ detail?: string;
31
+ };
32
+
33
+ export type TerminalManifestProps = {
34
+ /** Head line, e.g. `modules`. Pair a non-shell `prompt` with a non-shell
35
+ * label: with the default `$` mark this reads as a command the visitor can
36
+ * type, so it must name one that exists. */
37
+ command: string;
38
+ rows: TerminalManifestRow[];
39
+ /** Head-line prompt mark. */
40
+ prompt?: string;
41
+ /** Trailing head-line annotation, e.g. `· 7 online · 3 on the roadmap`. */
42
+ meta?: string;
43
+ /** Idle output line shown before any row is selected. */
44
+ hint?: string;
45
+ /** Two-tone name split: this leading fragment renders ink, the rest accent. */
46
+ namePrefix?: string;
47
+ /** Staggered row-appear animation (CSS keyframe; off under reduced motion). */
48
+ animateRows?: boolean;
49
+ /** Controlled selection; omit to let the pane own it. */
50
+ selectedId?: string | null;
51
+ defaultSelectedId?: string | null;
52
+ onSelect?: (id: string | null) => void;
53
+ /** Rendered under the output panel — e.g. a hand-off button. */
54
+ footer?: ReactNode;
55
+ className?: string;
56
+ "aria-label"?: string;
57
+ };
58
+
59
+ function RowName({ name, prefix }: { name: string; prefix?: string }) {
60
+ if (prefix && name.startsWith(prefix) && name.length > prefix.length) {
61
+ return (
62
+ <>
63
+ <span className="text-ink">{prefix}</span>
64
+ <span className="text-accent">{name.slice(prefix.length)}</span>
65
+ </>
66
+ );
67
+ }
68
+ return <span className="text-ink">{name}</span>;
69
+ }
70
+
71
+ export function TerminalManifest({
72
+ command,
73
+ rows,
74
+ prompt = "$",
75
+ meta,
76
+ hint = "select a module",
77
+ namePrefix,
78
+ animateRows = true,
79
+ selectedId,
80
+ defaultSelectedId = null,
81
+ onSelect,
82
+ footer,
83
+ className,
84
+ "aria-label": ariaLabel,
85
+ }: TerminalManifestProps) {
86
+ const safe = useMotionSafe();
87
+ const [ownSel, setOwnSel] = useState<string | null>(defaultSelectedId);
88
+ const sel = selectedId !== undefined ? selectedId : ownSel;
89
+ const selRow = sel ? (rows.find((r) => r.id === sel) ?? null) : null;
90
+ const out = selRow ? (selRow.detail ?? selRow.blurb) : "";
91
+ const open = selRow !== null;
92
+
93
+ const [shown, setShown] = useState(0);
94
+
95
+ // The detail types out in ~1.5s regardless of length: this effect resets and
96
+ // then drives `shown` as an animation, so synchronous setState in the effect
97
+ // body is intentional (same pattern as digithings-web's ModuleManifest).
98
+ /* eslint-disable react-hooks/set-state-in-effect */
99
+ useEffect(() => {
100
+ if (!open) {
101
+ setShown(0);
102
+ return;
103
+ }
104
+ if (!safe) {
105
+ setShown(out.length);
106
+ return;
107
+ }
108
+ setShown(0);
109
+ let i = 0;
110
+ const step = Math.max(2, Math.ceil(out.length / 90));
111
+ const id = window.setInterval(() => {
112
+ i += step;
113
+ if (i >= out.length) {
114
+ i = out.length;
115
+ window.clearInterval(id);
116
+ }
117
+ setShown(i);
118
+ }, 16);
119
+ return () => window.clearInterval(id);
120
+ }, [open, out, safe]);
121
+ /* eslint-enable react-hooks/set-state-in-effect */
122
+
123
+ const select = (id: string) => {
124
+ const next = sel === id ? null : id;
125
+ if (selectedId === undefined) setOwnSel(next);
126
+ onSelect?.(next);
127
+ };
128
+
129
+ const hasPorts = rows.some((r) => r.port !== undefined);
130
+ const anim = animateRows && safe;
131
+ const shell = ["tm", hasPorts ? "has-ports" : "", anim ? "" : "no-anim", className ?? ""]
132
+ .filter(Boolean)
133
+ .join(" ");
134
+
135
+ return (
136
+ <div className={shell} aria-label={ariaLabel}>
137
+ <div className="tm-pane flex flex-col rounded-none border border-hair px-[clamp(1rem,2.4vw,1.6rem)] py-[clamp(1rem,2.4vw,1.5rem)] font-mono">
138
+ <div className="mb-[0.7rem] flex-none text-[0.8rem] tracking-[0.02em] text-ink-mute">
139
+ <span className="text-accent">{prompt}</span> {command}
140
+ {meta ? <span> {meta}</span> : null}
141
+ </div>
142
+ <div className="tm-body">
143
+ <ol className="tm-rows">
144
+ {rows.map((r, i) => {
145
+ const off = r.status === "roadmap";
146
+ const isSel = sel === r.id;
147
+ return (
148
+ <li
149
+ key={r.id}
150
+ className={`tm-row${off ? " is-off" : ""}${isSel ? " is-sel" : ""}`}
151
+ style={anim ? { animationDelay: `${i * 55}ms` } : undefined}
152
+ >
153
+ <button
154
+ type="button"
155
+ className="tm-row-link"
156
+ // Toggle buttons feeding one shared output pane: clicking a
157
+ // row selects it (re-clicking deselects), so aria-pressed —
158
+ // the selected state — is the accurate model. (aria-selected
159
+ // is invalid on role=button; a listbox would need arrow-key
160
+ // nav these rows don't implement.) The output pane always
161
+ // renders (hint vs detail — content swaps, nothing
162
+ // collapses), so this is selection, not disclosure. (#1434)
163
+ aria-pressed={isSel}
164
+ onClick={() => select(r.id)}
165
+ >
166
+ <span className={`tm-dot${off ? " off" : ""}`} aria-hidden="true" />
167
+ {/* The dot is the only running/roadmap signal (color +
168
+ glow), aria-hidden with no text equivalent elsewhere
169
+ in the row — a screen-reader user got zero indication
170
+ of which services are live. .tm-sr (terminal-manifest.css),
171
+ not Tailwind's .sr-only: this is a shared component and
172
+ that utility only exists in an app whose own source
173
+ happens to use the class (see .tl-sr's comment,
174
+ terminal-loaders.css, for the bug that already caused
175
+ once). */}
176
+ <span className="tm-sr">{off ? "On the roadmap" : "Online"}</span>
177
+ <span className="tm-name text-[0.92rem] font-medium">
178
+ <RowName name={r.name} prefix={namePrefix} />
179
+ </span>
180
+ {hasPorts ? (
181
+ <span className="tm-port text-[0.78rem] text-ink-mute">{r.port ?? ""}</span>
182
+ ) : null}
183
+ <span className="tm-blurb truncate text-[0.84rem] text-ink-soft">{r.blurb}</span>
184
+ </button>
185
+ </li>
186
+ );
187
+ })}
188
+ </ol>
189
+ <div className="tm-out">
190
+ <div className="tm-out-show pb-[0.2rem]" aria-live="polite">
191
+ {selRow ? (
192
+ <pre className="tm-out-body m-0 whitespace-pre-wrap break-words font-mono text-[0.84rem] leading-[1.6] text-ink-soft">
193
+ {out.slice(0, shown)}
194
+ <span className="tm-cursor" aria-hidden="true" />
195
+ </pre>
196
+ ) : (
197
+ <p className="m-0 text-[0.84rem] text-ink-mute">
198
+ {hint}
199
+ <span className="tm-cursor" aria-hidden="true" />
200
+ </p>
201
+ )}
202
+ </div>
203
+ {/* Fragment keeps the slot element out of this children array: an
204
+ element prop arriving across an RSC boundary trips React 19's
205
+ missing-key check when reconciled as a direct array member. */}
206
+ <>{footer}</>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ );
212
+ }