@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,683 @@
1
+ "use client";
2
+
3
+ // The boot styles (.dboot-overlay included) ship with the loader, not with one
4
+ // skin: a host on any skin mounts this overlay, and without them it renders
5
+ // unpositioned at the top of the page with the wordmark clipped.
6
+ import "../../styles/digichat-boot-loader.css";
7
+ import { useCallback, useEffect, useRef, useState, type CSSProperties } from "react";
8
+
9
+ import { signalDigichatReady } from "./boot-signal";
10
+
11
+ /**
12
+ * DigichatBootLoader — the default DigiChat loading animation.
13
+ *
14
+ * A field of 3px cubes rides the composer outline: two heads start in
15
+ * opposite corners and sweep out-and-back (lighting cubes on the way out,
16
+ * clearing them on the way back) until the consumer reports `ready`.
17
+ * The heads then refill the outline to their far corners and park, the
18
+ * cube layer hands off to the composer's 1px border, and the welcome copy,
19
+ * suggestion rows, attachment glyph and send glyph type/build in.
20
+ *
21
+ * Pace and geometry are ported from the approved demo (loading-demos G6):
22
+ * 3px cubes on a 4px pitch, six cubes per head per 32ms tick.
23
+ * Styles: @digithings-ai/ui/styles/digichat-boot-loader.css.
24
+ */
25
+
26
+ /** 5x5 cube geometry, mirroring DotMatrix so every glyph reads identically. */
27
+ const GRID = 5;
28
+ const CELL_SIZE = 2.3;
29
+ const CELL_PITCH = 4;
30
+ const CELL_OFFSET = 0.85;
31
+
32
+ /** Loader pace: 3px cubes on a 4px pitch, six cubes per head per tick. */
33
+ const CFG = { SIZE: 3, PITCH: 4, TICK_MS: 32, STEP: 6 } as const;
34
+
35
+ type Dot = readonly [number, number];
36
+ const cellIndex = (row: number, col: number) => row * GRID + col;
37
+ const cellsFrom = (dots: readonly Dot[]) => dots.map(([row, col]) => cellIndex(row, col));
38
+
39
+ /** DotMatrix state glyphs rendered while the composer settles. */
40
+ const SEND_CELLS = cellsFrom([
41
+ [0, 2],
42
+ [0, 3],
43
+ [0, 4],
44
+ [1, 4],
45
+ [2, 1],
46
+ [2, 4],
47
+ [3, 0],
48
+ [3, 1],
49
+ [3, 2],
50
+ [3, 3],
51
+ [3, 4],
52
+ [4, 1],
53
+ ]);
54
+ const PLUS_CELLS = cellsFrom([
55
+ [1, 2],
56
+ [2, 1],
57
+ [2, 2],
58
+ [2, 3],
59
+ [3, 2],
60
+ ]);
61
+ const EXAMPLE_CELLS = cellsFrom([
62
+ [1, 2],
63
+ [2, 1],
64
+ [2, 3],
65
+ [3, 2],
66
+ ]);
67
+
68
+ const DEFAULT_WELCOME = "Ask a question";
69
+ const DEFAULT_WELCOME_BODY = "Ask about anything you need help with.";
70
+ const DEFAULT_PLACEHOLDER = "Ask a question";
71
+ const DEFAULT_SUGGESTIONS = [
72
+ "What can you help me with?",
73
+ "Search my workspace",
74
+ "Connect a tool",
75
+ "Change the appearance",
76
+ ];
77
+
78
+ /** Settle timeline (ms after both heads park). */
79
+ const SETTLE = {
80
+ HIDE_GRID: 280,
81
+ SOLID: 340,
82
+ POP: 640,
83
+ PLACEHOLDER: 700,
84
+ SEND: 760,
85
+ WELCOME: 860,
86
+ CHIPS: 1060,
87
+ BODY: 1300,
88
+ DONE: 2400,
89
+ /** Breathing room after the last typed character before the host reveals. */
90
+ PAD: 320,
91
+ } as const;
92
+
93
+ /** Typewriter speeds (ms per character), matching the approved demo. */
94
+ const TYPE = { PLACEHOLDER: 34, SEND_BUILD: 48, WELCOME: 32, CHIP: 12, BODY: 22 } as const;
95
+
96
+ function Glyph({ cells, className }: { cells: readonly number[]; className?: string }) {
97
+ return (
98
+ <svg viewBox="0 0 20 20" aria-hidden="true" focusable="false" shapeRendering="crispEdges" className={className}>
99
+ {cells.map((cell) => {
100
+ const row = Math.floor(cell / GRID);
101
+ const col = cell % GRID;
102
+ return (
103
+ <rect
104
+ key={`${row}-${col}`}
105
+ x={CELL_OFFSET + col * CELL_PITCH}
106
+ y={CELL_OFFSET + row * CELL_PITCH}
107
+ width={CELL_SIZE}
108
+ height={CELL_SIZE}
109
+ fill="currentColor"
110
+ />
111
+ );
112
+ })}
113
+ </svg>
114
+ );
115
+ }
116
+
117
+ function TypedText({
118
+ text,
119
+ active,
120
+ speedMs,
121
+ delayMs = 0,
122
+ instant = false,
123
+ }: {
124
+ text: string;
125
+ active: boolean;
126
+ speedMs: number;
127
+ delayMs?: number;
128
+ instant?: boolean;
129
+ }) {
130
+ const [count, setCount] = useState(instant ? text.length : 0);
131
+ const [started, setStarted] = useState(false);
132
+
133
+ useEffect(() => {
134
+ if (instant) {
135
+ setCount(text.length);
136
+ return;
137
+ }
138
+ if (!active) return;
139
+ let interval: number | undefined;
140
+ const timeout = window.setTimeout(() => {
141
+ setStarted(true);
142
+ interval = window.setInterval(() => {
143
+ setCount((current) => {
144
+ if (current >= text.length) {
145
+ if (interval !== undefined) window.clearInterval(interval);
146
+ return current;
147
+ }
148
+ return current + 1;
149
+ });
150
+ }, speedMs);
151
+ }, delayMs);
152
+ return () => {
153
+ window.clearTimeout(timeout);
154
+ if (interval !== undefined) window.clearInterval(interval);
155
+ };
156
+ }, [active, delayMs, instant, speedMs, text]);
157
+
158
+ if (instant) return <>{text}</>;
159
+ return (
160
+ <>
161
+ {text.slice(0, count)}
162
+ {started && count < text.length ? <span className="dboot-caret" aria-hidden="true" /> : null}
163
+ </>
164
+ );
165
+ }
166
+
167
+ function BuildingGlyph({
168
+ cells,
169
+ active,
170
+ speedMs,
171
+ delayMs = 0,
172
+ instant = false,
173
+ className,
174
+ }: {
175
+ cells: readonly number[];
176
+ active: boolean;
177
+ speedMs: number;
178
+ delayMs?: number;
179
+ instant?: boolean;
180
+ className?: string;
181
+ }) {
182
+ const [count, setCount] = useState(instant ? cells.length : 0);
183
+
184
+ useEffect(() => {
185
+ if (instant) {
186
+ setCount(cells.length);
187
+ return;
188
+ }
189
+ if (!active) return;
190
+ let interval: number | undefined;
191
+ const timeout = window.setTimeout(() => {
192
+ interval = window.setInterval(() => {
193
+ setCount((current) => {
194
+ if (current >= cells.length) {
195
+ if (interval !== undefined) window.clearInterval(interval);
196
+ return current;
197
+ }
198
+ return current + 1;
199
+ });
200
+ }, speedMs);
201
+ }, delayMs);
202
+ return () => {
203
+ window.clearTimeout(timeout);
204
+ if (interval !== undefined) window.clearInterval(interval);
205
+ };
206
+ }, [active, cells.length, delayMs, instant, speedMs]);
207
+
208
+ if (instant) return <Glyph cells={cells} className={className} />;
209
+ if (count === 0) return null;
210
+ return <Glyph cells={cells.slice(0, count)} className={className} />;
211
+ }
212
+
213
+ interface BorderCube {
214
+ rect: SVGRectElement;
215
+ lit: boolean;
216
+ op: number;
217
+ }
218
+
219
+ interface BorderEngine {
220
+ start: () => void;
221
+ rebuild: () => void;
222
+ finish: () => void;
223
+ destroy: () => void;
224
+ }
225
+
226
+ function createBorderEngine({
227
+ wrap,
228
+ svg,
229
+ onParked,
230
+ }: {
231
+ wrap: HTMLElement;
232
+ svg: SVGSVGElement;
233
+ onParked: () => void;
234
+ }): BorderEngine {
235
+ let cubes: BorderCube[] = [];
236
+ let headEls: SVGRectElement[] = [];
237
+ let width = 0;
238
+ let height = 0;
239
+ let litCount = 0;
240
+ let mode: "warm" | "finish" = "warm";
241
+ let cornerA = 0;
242
+ let cornerB = 0;
243
+ let tickId: number | null = null;
244
+ let rafId: number | null = null;
245
+ let destroyed = false;
246
+ const pos: [number, number] = [0, 0];
247
+ const phase: Array<"out" | "back"> = ["out", "out"];
248
+ const parked = [false, false];
249
+
250
+ function draw() {
251
+ for (const cube of cubes) {
252
+ const op = cube.lit ? 1 : 0;
253
+ if (op !== cube.op) {
254
+ cube.op = op;
255
+ cube.rect.style.opacity = String(op);
256
+ }
257
+ }
258
+ }
259
+
260
+ function setHeads() {
261
+ for (const el of headEls) el.classList.remove("fhead");
262
+ headEls = pos
263
+ .map((index) => (cubes[index] ? cubes[index].rect : null))
264
+ .filter((el): el is SVGRectElement => el !== null);
265
+ for (const el of headEls) el.classList.add("fhead");
266
+ }
267
+
268
+ function build() {
269
+ const nextWidth = Math.round(wrap.clientWidth);
270
+ const nextHeight = Math.round(wrap.clientHeight);
271
+ if (!nextWidth || !nextHeight) return false;
272
+ width = nextWidth;
273
+ height = nextHeight;
274
+ svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
275
+ while (svg.firstChild) svg.removeChild(svg.firstChild);
276
+ const size = CFG.SIZE;
277
+ const pitch = CFG.PITCH;
278
+ const cols = Math.max(2, Math.round(width / pitch) + 1);
279
+ const rows = Math.max(2, Math.round(height / pitch) + 1);
280
+ const x = (i: number) => (i * width) / (cols - 1);
281
+ const y = (j: number) => (j * height) / (rows - 1);
282
+ const points: Array<[number, number]> = [];
283
+ for (let i = 0; i < cols; i += 1) points.push([x(i), 0]);
284
+ for (let j = 1; j < rows; j += 1) points.push([width, y(j)]);
285
+ for (let i = cols - 2; i >= 0; i -= 1) points.push([x(i), height]);
286
+ for (let j = rows - 2; j >= 1; j -= 1) points.push([0, y(j)]);
287
+ cubes = points.map(([cx, cy]) => {
288
+ const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
289
+ rect.setAttribute("x", String(cx - size / 2));
290
+ rect.setAttribute("y", String(cy - size / 2));
291
+ rect.setAttribute("width", String(size));
292
+ rect.setAttribute("height", String(size));
293
+ rect.style.opacity = "0";
294
+ svg.appendChild(rect);
295
+ return { rect, lit: false, op: 0 };
296
+ });
297
+ return true;
298
+ }
299
+
300
+ function tick() {
301
+ if (destroyed) return;
302
+ const count = cubes.length;
303
+ if (!count) return;
304
+ for (let head = 0; head < 2; head += 1) {
305
+ if (parked[head]) continue;
306
+ const far = head === 0 ? cornerB : cornerA;
307
+ const anchor = head === 0 ? cornerA : cornerB;
308
+ if (mode === "finish" && pos[head] === far) {
309
+ parked[head] = true;
310
+ continue;
311
+ }
312
+ let current = pos[head];
313
+ for (let k = 0; k < CFG.STEP; k += 1) {
314
+ if (phase[head] === "out") {
315
+ const next = (current + 1) % count;
316
+ current = next;
317
+ const cube = cubes[next];
318
+ if (cube && !cube.lit) {
319
+ cube.lit = true;
320
+ litCount += 1;
321
+ }
322
+ if (next === far) {
323
+ if (mode === "finish") parked[head] = true;
324
+ else phase[head] = "back";
325
+ break;
326
+ }
327
+ } else {
328
+ const leaving = cubes[current];
329
+ if (leaving && leaving.lit) {
330
+ leaving.lit = false;
331
+ litCount -= 1;
332
+ }
333
+ current = (current - 1 + count) % count;
334
+ if (current === anchor) {
335
+ phase[head] = "out";
336
+ break;
337
+ }
338
+ }
339
+ }
340
+ pos[head] = current;
341
+ }
342
+ setHeads();
343
+ draw();
344
+ if (mode === "finish" && parked[0] && parked[1]) {
345
+ stop();
346
+ onParked();
347
+ }
348
+ }
349
+
350
+ function startTicker() {
351
+ if (tickId !== null) window.clearInterval(tickId);
352
+ tickId = window.setInterval(tick, CFG.TICK_MS);
353
+ }
354
+
355
+ function startRaf() {
356
+ if (rafId !== null) return;
357
+ const loop = () => {
358
+ if (destroyed || rafId === null) return;
359
+ draw();
360
+ rafId = window.requestAnimationFrame(loop);
361
+ };
362
+ rafId = window.requestAnimationFrame(loop);
363
+ }
364
+
365
+ function stop() {
366
+ if (tickId !== null) {
367
+ window.clearInterval(tickId);
368
+ tickId = null;
369
+ }
370
+ if (rafId !== null) {
371
+ window.cancelAnimationFrame(rafId);
372
+ rafId = null;
373
+ }
374
+ }
375
+
376
+ function reset() {
377
+ mode = "warm";
378
+ litCount = 0;
379
+ cornerA = 0;
380
+ cornerB = Math.floor(cubes.length / 2);
381
+ pos[0] = cornerA;
382
+ pos[1] = cornerB;
383
+ phase[0] = "out";
384
+ phase[1] = "out";
385
+ parked[0] = false;
386
+ parked[1] = false;
387
+ for (const index of pos) {
388
+ const cube = cubes[index];
389
+ if (cube && !cube.lit) {
390
+ cube.lit = true;
391
+ litCount += 1;
392
+ }
393
+ }
394
+ setHeads();
395
+ draw();
396
+ }
397
+
398
+ return {
399
+ start() {
400
+ if (destroyed) return;
401
+ if (!build()) return;
402
+ reset();
403
+ startTicker();
404
+ startRaf();
405
+ },
406
+ rebuild() {
407
+ if (destroyed || mode === "finish") return;
408
+ const nextWidth = Math.round(wrap.clientWidth);
409
+ const nextHeight = Math.round(wrap.clientHeight);
410
+ if (!nextWidth || !nextHeight) return;
411
+ if (nextWidth === width && nextHeight === height) return;
412
+ build();
413
+ reset();
414
+ },
415
+ finish() {
416
+ if (destroyed) return;
417
+ if (!cubes.length) {
418
+ stop();
419
+ onParked();
420
+ return;
421
+ }
422
+ mode = "finish";
423
+ phase[0] = "out";
424
+ phase[1] = "out";
425
+ },
426
+ destroy() {
427
+ destroyed = true;
428
+ stop();
429
+ while (svg.firstChild) svg.removeChild(svg.firstChild);
430
+ cubes = [];
431
+ headEls = [];
432
+ },
433
+ };
434
+ }
435
+
436
+ export interface DigichatBootLoaderProps {
437
+ /** Flip true when the embed has painted; the loader then parks and hands off. */
438
+ ready?: boolean;
439
+ /** Fired after the settle + typewriter sequence finishes (or on ready in reduced motion). */
440
+ onSettled?: () => void;
441
+ welcome?: string;
442
+ welcomeBody?: string;
443
+ suggestions?: readonly string[];
444
+ placeholder?: string;
445
+ /** Accessible status text (visually hidden). */
446
+ label?: string;
447
+ /** Visible boot step under the welcome, e.g. "Waking up services…" (null hides). */
448
+ statusText?: string | null;
449
+ /** Chat accent for the loader cursor; falls back to the accent/ink chain. */
450
+ accent?: string;
451
+ /** Render the attach plus glyph in the mock composer; mirrors the tenant attachments flag. */
452
+ showAttachment?: boolean;
453
+ className?: string;
454
+ }
455
+
456
+ export function DigichatBootLoader({
457
+ ready = false,
458
+ onSettled,
459
+ welcome = DEFAULT_WELCOME,
460
+ welcomeBody = DEFAULT_WELCOME_BODY,
461
+ suggestions = DEFAULT_SUGGESTIONS,
462
+ placeholder = DEFAULT_PLACEHOLDER,
463
+ label = "Loading chat",
464
+ statusText = null,
465
+ accent,
466
+ showAttachment = true,
467
+ className,
468
+ }: DigichatBootLoaderProps) {
469
+ const [reduced, setReduced] = useState(false);
470
+ const [gridHidden, setGridHidden] = useState(false);
471
+ const [lineUp, setLineUp] = useState(false);
472
+ const [solid, setSolid] = useState(false);
473
+ const [pop, setPop] = useState(false);
474
+ const [chipsVisible, setChipsVisible] = useState(false);
475
+ const [placeholderTyping, setPlaceholderTyping] = useState(false);
476
+ const [welcomeTyping, setWelcomeTyping] = useState(false);
477
+ const [bodyTyping, setBodyTyping] = useState(false);
478
+ const [chipsTyping, setChipsTyping] = useState(false);
479
+ const [sendBuilding, setSendBuilding] = useState(false);
480
+
481
+ const wrapRef = useRef<HTMLDivElement | null>(null);
482
+ const gridRef = useRef<SVGSVGElement | null>(null);
483
+ const engineRef = useRef<BorderEngine | null>(null);
484
+ const settleStartedRef = useRef(false);
485
+ const timeoutsRef = useRef<number[]>([]);
486
+ const onSettledRef = useRef(onSettled);
487
+ const copyRef = useRef({ welcome, welcomeBody, suggestions });
488
+ const startedAtRef = useRef(0);
489
+
490
+ useEffect(() => {
491
+ onSettledRef.current = onSettled;
492
+ }, [onSettled]);
493
+
494
+ useEffect(() => {
495
+ copyRef.current = { welcome, welcomeBody, suggestions };
496
+ }, [welcome, welcomeBody, suggestions]);
497
+
498
+ useEffect(() => {
499
+ const query = window.matchMedia("(prefers-reduced-motion: reduce)");
500
+ const update = () => setReduced(query.matches);
501
+ update();
502
+ query.addEventListener("change", update);
503
+ return () => query.removeEventListener("change", update);
504
+ }, []);
505
+
506
+ useEffect(
507
+ () => () => {
508
+ for (const id of timeoutsRef.current) window.clearTimeout(id);
509
+ },
510
+ [],
511
+ );
512
+
513
+ const typingStartedRef = useRef(false);
514
+
515
+ // Type from mount; the ready-driven park (handleParked via onParked) keeps
516
+ // the cube field alive until the embed is ready, then plays the
517
+ // grid/solid/pop settle. Running the whole settle at mount used to hide the
518
+ // contour ~280ms in and leave a static mock composer on a cold start.
519
+ const startTyping = useCallback(() => {
520
+ if (typingStartedRef.current) return;
521
+ typingStartedRef.current = true;
522
+ const schedule = (ms: number, fn: () => void) => {
523
+ timeoutsRef.current.push(window.setTimeout(fn, ms));
524
+ };
525
+ schedule(SETTLE.PLACEHOLDER, () => setPlaceholderTyping(true));
526
+ schedule(SETTLE.SEND, () => setSendBuilding(true));
527
+ schedule(SETTLE.WELCOME, () => setWelcomeTyping(true));
528
+ schedule(SETTLE.CHIPS, () => {
529
+ setChipsVisible(true);
530
+ setChipsTyping(true);
531
+ });
532
+ schedule(SETTLE.BODY, () => setBodyTyping(true));
533
+ }, []);
534
+
535
+ const handleParked = useCallback(() => {
536
+ if (settleStartedRef.current) return;
537
+ settleStartedRef.current = true;
538
+ setLineUp(true);
539
+ const schedule = (ms: number, fn: () => void) => {
540
+ timeoutsRef.current.push(window.setTimeout(fn, ms));
541
+ };
542
+ schedule(SETTLE.HIDE_GRID, () => setGridHidden(true));
543
+ schedule(SETTLE.SOLID, () => setSolid(true));
544
+ schedule(SETTLE.POP, () => setPop(true));
545
+ schedule(SETTLE.PLACEHOLDER, () => setPlaceholderTyping(true));
546
+ schedule(SETTLE.SEND, () => setSendBuilding(true));
547
+ schedule(SETTLE.WELCOME, () => setWelcomeTyping(true));
548
+ schedule(SETTLE.CHIPS, () => {
549
+ setChipsVisible(true);
550
+ setChipsTyping(true);
551
+ });
552
+ schedule(SETTLE.BODY, () => setBodyTyping(true));
553
+ // Hold the overlay until every line has finished typing: fixed 2400ms cut
554
+ // long copy (e.g. a two-line welcome body) mid-sentence and the host then
555
+ // unmounted the loader. PAD gives the caret a beat on the last character.
556
+ const { welcome: welcomeCopy, welcomeBody: bodyCopy, suggestions: chipCopy } = copyRef.current;
557
+ const typingEnd = Math.max(
558
+ SETTLE.WELCOME + welcomeCopy.length * TYPE.WELCOME,
559
+ SETTLE.BODY + bodyCopy.length * TYPE.BODY,
560
+ ...chipCopy.map((chip) => SETTLE.CHIPS + chip.length * TYPE.CHIP),
561
+ );
562
+ // Park can land well after mount (the ready edge); subtract the typing
563
+ // already served so the reveal still lands at mount + typingEnd + PAD.
564
+ const elapsed = startedAtRef.current === 0 ? 0 : performance.now() - startedAtRef.current;
565
+ schedule(Math.max(SETTLE.DONE, Math.max(0, typingEnd - elapsed) + SETTLE.PAD), () => {
566
+ signalDigichatReady();
567
+ onSettledRef.current?.();
568
+ });
569
+ }, []);
570
+
571
+ useEffect(() => {
572
+ if (reduced) return;
573
+ const wrap = wrapRef.current;
574
+ const grid = gridRef.current;
575
+ if (!wrap || !grid) return;
576
+ const engine = createBorderEngine({ wrap, svg: grid, onParked: handleParked });
577
+ engineRef.current = engine;
578
+ engine.start();
579
+ // Type from mount, not from ready: gating the sequence on ready let the
580
+ // host crossfade (ChatEmbedShell, keyed on embedReady) hide the typed
581
+ // welcome + examples before they played -- datatap types during the load.
582
+ // The park-driven settle (handleParked via onParked) stays on the ready
583
+ // edge so the cube contour keeps sweeping through the load.
584
+ startedAtRef.current = performance.now();
585
+ startTyping();
586
+ const observer = new ResizeObserver(() => engine.rebuild());
587
+ observer.observe(wrap);
588
+ return () => {
589
+ observer.disconnect();
590
+ engine.destroy();
591
+ engineRef.current = null;
592
+ };
593
+ }, [startTyping, reduced]);
594
+
595
+ useEffect(() => {
596
+ if (!ready) return;
597
+ if (reduced) {
598
+ signalDigichatReady();
599
+ onSettledRef.current?.();
600
+ return;
601
+ }
602
+ engineRef.current?.finish();
603
+ }, [ready, reduced]);
604
+
605
+ const instant = reduced;
606
+
607
+ return (
608
+ <div
609
+ className={className ? `dboot ${className}` : "dboot"}
610
+ data-attach={showAttachment ? "1" : "0"}
611
+ data-digichat-boot=""
612
+ style={accent ? ({ "--dboot-caret": accent } as CSSProperties) : undefined}
613
+ >
614
+ <span className="dboot-sr" role="status">
615
+ {statusText ?? label}
616
+ </span>
617
+ {statusText ? (
618
+ <div className="dboot-status" data-slot="digichat-boot-status" aria-hidden="true">
619
+ {statusText}
620
+ </div>
621
+ ) : null}
622
+ <div className="dboot-dock" aria-hidden="true">
623
+ <div className="dboot-welcome">
624
+ <TypedText text={welcome} active={welcomeTyping} speedMs={TYPE.WELCOME} instant={instant} />
625
+ </div>
626
+ <div className="dboot-body">
627
+ <TypedText text={welcomeBody} active={bodyTyping} speedMs={TYPE.BODY} instant={instant} />
628
+ </div>
629
+ <div className="dboot-chips" data-visible={chipsVisible || instant ? "true" : "false"}>
630
+ {suggestions.map((suggestion) => (
631
+ <div className="dboot-chip" key={suggestion}>
632
+ <span className="dboot-chip-mark">
633
+ <Glyph cells={EXAMPLE_CELLS} className="dboot-glyph" />
634
+ </span>
635
+ <span className="dboot-chip-text">
636
+ <TypedText text={suggestion} active={chipsTyping} speedMs={TYPE.CHIP} instant={instant} />
637
+ </span>
638
+ </div>
639
+ ))}
640
+ </div>
641
+ <div className="dboot-composer-wrap" ref={wrapRef}>
642
+ <div className="dboot-composer" data-solid={solid || instant ? "true" : "false"}>
643
+ <span className="dboot-placeholder">
644
+ <TypedText
645
+ text={placeholder}
646
+ active={placeholderTyping}
647
+ speedMs={TYPE.PLACEHOLDER}
648
+ instant={instant}
649
+ />
650
+ </span>
651
+ <span className="dboot-send">
652
+ <BuildingGlyph
653
+ cells={SEND_CELLS}
654
+ active={sendBuilding}
655
+ speedMs={TYPE.SEND_BUILD}
656
+ instant={instant}
657
+ className="dboot-glyph"
658
+ />
659
+ </span>
660
+ </div>
661
+ {instant ? null : (
662
+ <svg
663
+ ref={gridRef}
664
+ className="dboot-grid"
665
+ data-hidden={gridHidden ? "true" : "false"}
666
+ aria-hidden="true"
667
+ />
668
+ )}
669
+ <span
670
+ className="dboot-line"
671
+ data-visible={lineUp ? "true" : "false"}
672
+ data-solid={solid || instant ? "true" : "false"}
673
+ />
674
+ {showAttachment ? (
675
+ <span className="dboot-plus" data-pop={pop || instant ? "true" : "false"}>
676
+ <Glyph cells={PLUS_CELLS} className="dboot-glyph" />
677
+ </span>
678
+ ) : null}
679
+ </div>
680
+ </div>
681
+ </div>
682
+ );
683
+ }