@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,197 @@
1
+ "use client";
2
+ import { useEffect, useState, type ReactNode } from "react";
3
+
4
+ /**
5
+ * Docs shell: a sticky, scroll-spied sidebar on desktop and a native
6
+ * <details> disclosure on mobile — the sidebar never just vanishes
7
+ * (canon §17). One nav model, rendered twice. Presentation-generic: nav
8
+ * groups, hero, and content arrive as props/children; nothing app-specific
9
+ * is baked in. Structural CSS (grid reveal, sticky offset, disclosure
10
+ * marker, scroll margins) lives in styles/docs.css; consumers with fixed
11
+ * chrome set --docs-nav-h on the shell or an ancestor.
12
+ */
13
+
14
+ export interface DocsNavItem {
15
+ /** id of the section element this entry links to (`#id`) and scroll-spies. */
16
+ id: string;
17
+ label: ReactNode;
18
+ /**
19
+ * A page link instead of an in-page section: the entry is not spied and is
20
+ * lit only when `current`. Lets one sidebar span a docs site's pages.
21
+ */
22
+ href?: string;
23
+ current?: boolean;
24
+ }
25
+
26
+ export interface DocsNavGroup {
27
+ label: ReactNode;
28
+ items: DocsNavItem[];
29
+ }
30
+
31
+ export interface DocsHero {
32
+ kicker?: ReactNode;
33
+ title: ReactNode;
34
+ lede?: ReactNode;
35
+ actions?: ReactNode;
36
+ }
37
+
38
+ /**
39
+ * Scroll-spy: the last of `ids` whose element's top has passed a line a
40
+ * quarter down the viewport. Position rather than intersection, so a section
41
+ * taller than the viewport stays active the whole way through it.
42
+ */
43
+ function useSpy(ids: string[], fallback: string): string {
44
+ const [active, setActive] = useState(fallback);
45
+ const key = ids.join("\n");
46
+ useEffect(() => {
47
+ const list = key ? key.split("\n") : [];
48
+ let frame = 0;
49
+ const read = () => {
50
+ frame = 0;
51
+ const line = window.innerHeight * 0.25;
52
+ let next = list[0] ?? "";
53
+ for (const id of list) {
54
+ const el = document.getElementById(id);
55
+ if (el && el.getBoundingClientRect().top <= line) next = id;
56
+ }
57
+ setActive(next);
58
+ };
59
+ const onScroll = () => {
60
+ if (frame === 0) frame = requestAnimationFrame(read);
61
+ };
62
+ read();
63
+ window.addEventListener("scroll", onScroll, { passive: true });
64
+ window.addEventListener("resize", onScroll);
65
+ return () => {
66
+ cancelAnimationFrame(frame);
67
+ window.removeEventListener("scroll", onScroll);
68
+ window.removeEventListener("resize", onScroll);
69
+ };
70
+ }, [key]);
71
+ return active;
72
+ }
73
+
74
+ export function DocsLayout({
75
+ nav,
76
+ hero,
77
+ children,
78
+ rail,
79
+ railLabel = "on this page",
80
+ search,
81
+ contentsLabel = "contents",
82
+ ariaLabel = "docs",
83
+ className,
84
+ }: {
85
+ nav: DocsNavGroup[];
86
+ hero?: DocsHero;
87
+ children: ReactNode;
88
+ /**
89
+ * On-this-page entries: a second, narrower rail on wide viewports. Either
90
+ * one list for the whole page, or a list per nav entry (keyed by nav item
91
+ * id) so the rail follows the section being read.
92
+ */
93
+ rail?: DocsNavItem[] | Record<string, DocsNavItem[]>;
94
+ /** Heading above the on-this-page rail. */
95
+ railLabel?: ReactNode;
96
+ /** Search affordance, rendered above the hero. */
97
+ search?: ReactNode;
98
+ /** Label on the collapsed mobile disclosure. */
99
+ contentsLabel?: string;
100
+ /** aria-label shared by both renderings of the nav. */
101
+ ariaLabel?: string;
102
+ /** Extra classes on the shell (e.g. a wider max-width). */
103
+ className?: string;
104
+ }) {
105
+ // Two spies: the sidebar tracks its entries, the rail tracks its own, so a
106
+ // lit sub-section never un-lights the entry it belongs to.
107
+ const navIds = nav.flatMap((g) => g.items.filter((i) => i.href == null).map((i) => i.id));
108
+ const navActive = useSpy(navIds, navIds[0] ?? "");
109
+ const railItems = Array.isArray(rail) ? rail : rail?.[navActive];
110
+ const railIds = (railItems ?? []).map((i) => i.id);
111
+ const railActive = useSpy(railIds, railIds[0] ?? "");
112
+
113
+ const itemLink = (it: DocsNavItem, active: string) => {
114
+ const on = it.href != null ? it.current === true : active === it.id;
115
+ const current = it.href != null ? "page" : "true";
116
+ return (
117
+ <a
118
+ key={it.id}
119
+ href={it.href ?? `#${it.id}`}
120
+ aria-current={on ? current : undefined}
121
+ className={`rounded-none border-s-2 px-[0.6rem] py-[0.28rem] font-mono text-[0.82rem] no-underline transition-colors duration-150 ease-brand ${
122
+ on
123
+ ? "border-s-accent bg-accent-weak text-ink"
124
+ : "border-s-transparent text-ink-soft hover:bg-accent-weak hover:text-ink"
125
+ }`}
126
+ >
127
+ {it.label}
128
+ </a>
129
+ );
130
+ };
131
+
132
+ const sideNav = (
133
+ <nav aria-label={ariaLabel} className="flex flex-col gap-[0.1rem]">
134
+ {nav.map((g, gi) => (
135
+ <div key={gi} className="mt-[0.8rem] flex flex-col gap-[0.1rem]">
136
+ <span className="mb-[0.2rem] px-[0.6rem] font-mono text-[0.68rem] uppercase tracking-[0.12em] text-ink-mute">
137
+ {g.label}
138
+ </span>
139
+ {g.items.map((it) => itemLink(it, navActive))}
140
+ </div>
141
+ ))}
142
+ </nav>
143
+ );
144
+
145
+ const railNav =
146
+ railItems && railItems.length > 0 ? (
147
+ <nav
148
+ aria-label={typeof railLabel === "string" ? railLabel : "on this page"}
149
+ className="mt-[0.8rem] flex flex-col gap-[0.1rem]"
150
+ >
151
+ <span className="mb-[0.2rem] px-[0.6rem] font-mono text-[0.68rem] uppercase tracking-[0.12em] text-ink-mute">
152
+ {railLabel}
153
+ </span>
154
+ {railItems.map((it) => itemLink(it, railActive))}
155
+ </nav>
156
+ ) : null;
157
+
158
+ return (
159
+ <div className={className ? `docs-shell ${className}` : "docs-shell"}>
160
+ <aside className="docs-side">{sideNav}</aside>
161
+
162
+ <div className="docs-content flex min-w-0 flex-col gap-[clamp(1.6rem,3.5vw,2.6rem)]">
163
+ <details className="docs-side-mobile mb-[1.3rem] rounded-none border border-hair px-[0.85rem] py-[0.55rem]">
164
+ <summary className="cursor-pointer font-mono text-[0.7rem] uppercase tracking-[0.12em] text-ink-mute">
165
+ {contentsLabel}
166
+ </summary>
167
+ {sideNav}
168
+ </details>
169
+
170
+ {search != null && <div className="docs-search">{search}</div>}
171
+
172
+ {hero && (
173
+ <header className="docs-hero">
174
+ {hero.kicker != null && (
175
+ <p className="m-0 font-mono text-[0.68rem] uppercase tracking-[0.14em] text-accent">
176
+ {hero.kicker}
177
+ </p>
178
+ )}
179
+ <h1 className="mb-[0.7rem] mt-[0.5rem] font-display text-[clamp(1.9rem,4vw,2.7rem)] font-normal tracking-[-0.02em] text-ink">
180
+ {hero.title}
181
+ </h1>
182
+ {hero.lede != null && (
183
+ <p className="m-0 max-w-[60ch] leading-[1.6] text-ink-soft">{hero.lede}</p>
184
+ )}
185
+ {hero.actions != null && <div className="mt-[1rem]">{hero.actions}</div>}
186
+ </header>
187
+ )}
188
+
189
+ {children}
190
+ </div>
191
+
192
+ {/* The column stays whenever a rail is given, so an entry with no
193
+ sub-sections empties it instead of reflowing the page. */}
194
+ {rail != null && <aside className="docs-rail">{railNav}</aside>}
195
+ </div>
196
+ );
197
+ }
@@ -0,0 +1,97 @@
1
+ "use client";
2
+ import { useEffect, useRef, useState } from "react";
3
+
4
+ import { cn } from "../../lib/utils";
5
+ import { Kbd } from "../../ui/kbd";
6
+ import { SearchBar } from "../../ui/search-bar";
7
+ import type { DocsNavItem } from "./DocsLayout";
8
+
9
+ /**
10
+ * Docs search — the bordered `⌘K` affordance over a page's own headings.
11
+ * There is no index and no dependency: the caller hands over the same
12
+ * `DocsNavItem[]` the rail renders, and the field filters them on the client.
13
+ * `⌘K` / `Ctrl-K` focuses the field from anywhere on the page (D1, #4429).
14
+ */
15
+
16
+ /** Case-insensitive match over an item's label, falling back to its id. */
17
+ export function filterDocsItems(items: DocsNavItem[], query: string): DocsNavItem[] {
18
+ const needle = query.trim().toLowerCase();
19
+ if (needle === "") return [];
20
+ return items.filter((item) =>
21
+ typeof item.label === "string"
22
+ ? item.label.toLowerCase().includes(needle)
23
+ : item.id.toLowerCase().includes(needle),
24
+ );
25
+ }
26
+
27
+ export interface DocsSearchProps {
28
+ items: DocsNavItem[];
29
+ /** Accessible name for the field. */
30
+ label?: string;
31
+ placeholder?: string;
32
+ className?: string;
33
+ }
34
+
35
+ export function DocsSearch({
36
+ items,
37
+ label = "Search sections",
38
+ placeholder = "Search",
39
+ className,
40
+ }: DocsSearchProps) {
41
+ const [query, setQuery] = useState("");
42
+ const wrapRef = useRef<HTMLDivElement>(null);
43
+
44
+ useEffect(() => {
45
+ const onKeyDown = (event: KeyboardEvent) => {
46
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
47
+ event.preventDefault();
48
+ wrapRef.current?.querySelector("input")?.focus();
49
+ }
50
+ };
51
+ window.addEventListener("keydown", onKeyDown);
52
+ return () => window.removeEventListener("keydown", onKeyDown);
53
+ }, []);
54
+
55
+ const matches = filterDocsItems(items, query);
56
+
57
+ /* Results float over the page, anchored under the field: an in-flow list
58
+ would push the hero down with every keystroke. */
59
+ return (
60
+ <div
61
+ ref={wrapRef}
62
+ className={cn("relative flex flex-col items-start", className)}
63
+ onKeyDown={(event) => {
64
+ if (event.key === "Escape") setQuery("");
65
+ }}
66
+ >
67
+ <SearchBar
68
+ value={query}
69
+ onChange={setQuery}
70
+ aria-label={label}
71
+ placeholder={placeholder}
72
+ hint={<Kbd>⌘K</Kbd>}
73
+ />
74
+ {query.trim() !== "" && (
75
+ <ul className="absolute end-0 top-full z-20 m-0 mt-[0.4rem] grid max-h-[min(60vh,24rem)] w-[min(100vw_-_2rem,26rem)] list-none gap-0 overflow-y-auto border border-hair bg-popover p-0 shadow-lg">
76
+ {matches.length > 0 ? (
77
+ matches.map((item) => (
78
+ <li key={item.id}>
79
+ <a
80
+ href={`#${item.id}`}
81
+ onClick={() => setQuery("")}
82
+ className="block px-[0.7rem] py-[0.45rem] font-mono text-[0.82rem] text-ink-soft no-underline transition-colors duration-150 ease-brand hover:bg-accent-weak hover:text-ink"
83
+ >
84
+ {item.label}
85
+ </a>
86
+ </li>
87
+ ))
88
+ ) : (
89
+ <li className="px-[0.7rem] py-[0.45rem] font-mono text-[0.82rem] text-ink-mute">
90
+ no section matches
91
+ </li>
92
+ )}
93
+ </ul>
94
+ )}
95
+ </div>
96
+ );
97
+ }
@@ -0,0 +1,135 @@
1
+ import { CodeTabs, DocsCodeBlock, type CodeSample } from "./CodeTabs";
2
+
3
+ /**
4
+ * One HTTP endpoint as doc chrome: method chip + path, summary, metadata
5
+ * badges, request/response field tables, and tabbed code samples.
6
+ * Presentation-generic — the endpoint arrives fully described as props.
7
+ * Method chips consume the theme-aware var(--method-*) custom props defined
8
+ * in styles/docs.css (never raw hex at the use site); the field-table row
9
+ * hairlines live there too.
10
+ */
11
+
12
+ export type DocsMethod = "GET" | "POST" | "PUT" | "DELETE";
13
+
14
+ export interface DocsField {
15
+ name: string;
16
+ type: string;
17
+ required?: boolean;
18
+ description: string;
19
+ }
20
+
21
+ export interface DocsEndpoint {
22
+ method: DocsMethod;
23
+ path: string;
24
+ summary: string;
25
+ /** Auth requirement, e.g. "none", "bearer · orders:write". */
26
+ auth?: string;
27
+ /** Rate limit note, e.g. "10/min/IP". */
28
+ rateLimit?: string;
29
+ /** Flag / gate note — rendered muted, e.g. an env toggle. */
30
+ flag?: string;
31
+ request?: DocsField[];
32
+ responseFields?: DocsField[];
33
+ /** JSON string, when a shape reads clearer than a table. */
34
+ responseExample?: string;
35
+ examples?: CodeSample[];
36
+ }
37
+
38
+ const METHOD_BG: Record<DocsMethod, string> = {
39
+ GET: "bg-(--method-get)",
40
+ POST: "bg-(--method-post)",
41
+ PUT: "bg-(--method-put)",
42
+ DELETE: "bg-(--method-delete)",
43
+ };
44
+
45
+ /** The colored HTTP-method chip, on its own for legends and indexes. */
46
+ export function MethodBadge({ method }: { method: DocsMethod }) {
47
+ return (
48
+ <span
49
+ className={`rounded-none px-[0.45rem] py-[0.15rem] font-mono text-[0.7rem] font-semibold tracking-[0.04em] text-on-accent ${METHOD_BG[method]}`}
50
+ >
51
+ {method}
52
+ </span>
53
+ );
54
+ }
55
+
56
+ function InlineCode({ children }: { children: React.ReactNode }) {
57
+ return (
58
+ <code className="rounded-none bg-ink/9 px-[0.3rem] py-[0.05rem] font-mono text-[0.82em]">
59
+ {children}
60
+ </code>
61
+ );
62
+ }
63
+
64
+ function FieldTable({ title, fields }: { title: string; fields: DocsField[] }) {
65
+ return (
66
+ <div className="flex flex-col gap-[0.3rem]">
67
+ <span className="font-mono text-[0.66rem] uppercase tracking-[0.12em] text-ink-mute">
68
+ {title}
69
+ </span>
70
+ <table className="doc-fields w-full border-collapse text-[0.84rem]">
71
+ <tbody>
72
+ {fields.map((f) => (
73
+ <tr key={f.name}>
74
+ <td className="whitespace-nowrap">
75
+ <InlineCode>{f.name}</InlineCode>
76
+ {f.required && (
77
+ <span className="ms-[0.15rem] text-down" title="required">
78
+ *
79
+ </span>
80
+ )}
81
+ </td>
82
+ <td className="whitespace-nowrap font-mono text-[0.78rem] text-ink-mute">{f.type}</td>
83
+ <td className="w-full leading-[1.5] text-ink-soft">{f.description}</td>
84
+ </tr>
85
+ ))}
86
+ </tbody>
87
+ </table>
88
+ </div>
89
+ );
90
+ }
91
+
92
+ /** Small bordered metadata chip beside the endpoint head. */
93
+ function DocBadge({ muted, children }: { muted?: boolean; children: React.ReactNode }) {
94
+ return (
95
+ <span
96
+ className={`whitespace-nowrap rounded-none border border-hair px-[0.45rem] py-[0.15rem] font-mono text-[0.68rem] ${
97
+ muted ? "text-ink-mute" : "text-ink-soft"
98
+ }`}
99
+ >
100
+ {children}
101
+ </span>
102
+ );
103
+ }
104
+
105
+ export function EndpointDoc({ ep }: { ep: DocsEndpoint }) {
106
+ return (
107
+ <div className="doc-endpoint flex flex-col gap-[0.55rem] rounded-none border border-hair bg-surface/55 p-[clamp(0.8rem,2vw,1.1rem)]">
108
+ <div className="flex flex-wrap items-center gap-[0.6rem]">
109
+ <MethodBadge method={ep.method} />
110
+ <code className="break-all font-mono text-[0.92rem] text-ink">{ep.path}</code>
111
+ </div>
112
+ <p className="m-0 text-[0.88rem] leading-[1.65] text-ink-soft">{ep.summary}</p>
113
+ {(ep.auth || ep.rateLimit || ep.flag) && (
114
+ <div className="flex flex-wrap gap-[0.35rem]">
115
+ {ep.auth && <DocBadge>auth · {ep.auth}</DocBadge>}
116
+ {ep.rateLimit && <DocBadge>{ep.rateLimit}</DocBadge>}
117
+ {ep.flag && <DocBadge muted>{ep.flag}</DocBadge>}
118
+ </div>
119
+ )}
120
+ {ep.request && ep.request.length > 0 && <FieldTable title="Request" fields={ep.request} />}
121
+ {ep.responseFields && ep.responseFields.length > 0 && (
122
+ <FieldTable title="Response" fields={ep.responseFields} />
123
+ )}
124
+ {ep.responseExample && (
125
+ <div className="flex flex-col gap-[0.3rem]">
126
+ <span className="font-mono text-[0.66rem] uppercase tracking-[0.12em] text-ink-mute">
127
+ Response
128
+ </span>
129
+ <DocsCodeBlock code={ep.responseExample} copyLabel="Copy response example" />
130
+ </div>
131
+ )}
132
+ {ep.examples && ep.examples.length > 0 && <CodeTabs samples={ep.examples} />}
133
+ </div>
134
+ );
135
+ }
@@ -0,0 +1,43 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+ import { LayoutLines } from "../page-geometry";
5
+
6
+ /**
7
+ * The framed document column (D1, #4429).
8
+ *
9
+ * Every marketing page sits between the same fixed dashed rails as the
10
+ * landing page (`LayoutLines`), one `--page-pad` outside the content column,
11
+ * so a subpage and the home page read as the same built object. Section
12
+ * hairlines are full-bleed and cross the rails, as the landing bands do; the
13
+ * outer wrapper clips them to the viewport so they never add a horizontal
14
+ * scroll.
15
+ *
16
+ * The frame also resets the counter the section headings number themselves
17
+ * from (`// 01`, `// 02`, …).
18
+ *
19
+ * Utilities only — no site/app CSS class. The column width and inline
20
+ * inset come from `--frame-w` / `--page-pad`.
21
+ */
22
+ export interface DocumentFrameProps {
23
+ children: ReactNode;
24
+ className?: string;
25
+ }
26
+
27
+ export function DocumentFrame({ children, className }: DocumentFrameProps) {
28
+ return (
29
+ <>
30
+ <LayoutLines />
31
+ <div className="relative z-10 overflow-x-clip [counter-reset:doc-section]">
32
+ <div
33
+ className={cn(
34
+ "mx-auto w-full max-w-[calc(var(--frame-w)+2*var(--page-pad))]",
35
+ className,
36
+ )}
37
+ >
38
+ {children}
39
+ </div>
40
+ </div>
41
+ </>
42
+ );
43
+ }
@@ -0,0 +1,51 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+
5
+ /**
6
+ * The glyph list (D1, #4429).
7
+ *
8
+ * One list grammar for the whole site: a muted `[*]` marker, then a bold
9
+ * lead-in and one unpunctuated clause. No borders, no bullets, no
10
+ * description columns — the list reads as a dense block of statements.
11
+ *
12
+ * Utilities only — no site/app CSS class.
13
+ */
14
+ export interface GlyphListProps {
15
+ children: ReactNode;
16
+ className?: string;
17
+ }
18
+
19
+ export function GlyphList({ children, className }: GlyphListProps) {
20
+ return (
21
+ <ul className={cn("m-0 grid list-none gap-[1rem] p-0", className)}>{children}</ul>
22
+ );
23
+ }
24
+
25
+ export interface GlyphRowProps {
26
+ /** The bold lead-in; rendered in ink at medium weight. */
27
+ label?: ReactNode;
28
+ children: ReactNode;
29
+ className?: string;
30
+ }
31
+
32
+ export function GlyphRow({ label, children, className }: GlyphRowProps) {
33
+ return (
34
+ <li
35
+ className={cn(
36
+ "flex gap-[0.75rem] text-[length:var(--type-body)] leading-[var(--leading-prose)] text-ink-soft",
37
+ className,
38
+ )}
39
+ >
40
+ <span aria-hidden="true" className="shrink-0 font-mono text-ink-mute">
41
+ [*]
42
+ </span>
43
+ <span>
44
+ {label ? (
45
+ <strong className="mr-[0.6rem] font-medium text-ink">{label}</strong>
46
+ ) : null}
47
+ {children}
48
+ </span>
49
+ </li>
50
+ );
51
+ }
@@ -0,0 +1,44 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+
5
+ /**
6
+ * The page opener (D1, #4429).
7
+ *
8
+ * The landing hero's grammar at page-title size: a muted `~/digithings/<path>`
9
+ * line, the title with a blinking block caret, and a one-sentence lede, staged
10
+ * in with `animate-appear` (the kit drops the entrance under reduced motion).
11
+ *
12
+ * Utilities only — no site/app CSS class.
13
+ */
14
+ export interface PageTitleProps {
15
+ title: ReactNode;
16
+ /** The page's path under `~/digithings/`, e.g. `services`. */
17
+ path?: string;
18
+ children?: ReactNode;
19
+ className?: string;
20
+ }
21
+
22
+ export function PageTitle({ title, path, children, className }: PageTitleProps) {
23
+ return (
24
+ <header className={cn("max-w-[var(--measure-prose)]", className)}>
25
+ {path ? (
26
+ <p className="animate-appear m-0 mb-[1.1rem] font-mono text-[0.75rem] tracking-[0.04em] text-ink-mute opacity-0">
27
+ {`~/digithings/${path}`}
28
+ </p>
29
+ ) : null}
30
+ <h1 className="animate-appear m-0 font-mono text-[length:var(--type-page-title)] font-medium leading-[1.2] tracking-[-0.02em] text-ink opacity-0 [animation-delay:90ms]">
31
+ {title}
32
+ <span
33
+ aria-hidden="true"
34
+ className="ml-[0.3em] inline-block h-[0.82em] w-[0.5em] bg-accent align-[-0.08em] [animation:chat-cursor-blink_1.1s_steps(1)_infinite] motion-reduce:[animation:none]"
35
+ />
36
+ </h1>
37
+ {children ? (
38
+ <p className="animate-appear mt-[0.9rem] mb-0 text-[length:var(--type-body)] leading-[var(--leading-prose)] text-ink-soft opacity-0 [animation-delay:200ms]">
39
+ {children}
40
+ </p>
41
+ ) : null}
42
+ </header>
43
+ );
44
+ }
@@ -0,0 +1,38 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+
5
+ /**
6
+ * Long-form prose wrapper (D1, #4429).
7
+ *
8
+ * Caps the measure and sets the loose reading leading, then styles the
9
+ * common inline elements (paragraph rhythm, links, emphasis, lists) so a
10
+ * prose block needs no per-element classes. Accent is furniture only —
11
+ * links and list markers, never body text.
12
+ *
13
+ * Utilities only — no site/app CSS class.
14
+ */
15
+ export interface ProseProps {
16
+ children: ReactNode;
17
+ className?: string;
18
+ }
19
+
20
+ export function Prose({ children, className }: ProseProps) {
21
+ return (
22
+ <div
23
+ className={cn(
24
+ "max-w-[var(--measure-prose)] text-[length:var(--type-body)] leading-[var(--leading-prose)] text-ink-soft",
25
+ "[&_p]:mt-[1.1em] [&_p:first-child]:mt-0",
26
+ "[&_a]:text-ink [&_a]:underline [&_a]:underline-offset-[3px]",
27
+ "[&_strong]:font-medium [&_strong]:text-ink",
28
+ "[&_em]:italic",
29
+ "[&_ul]:mt-[1.1em] [&_ul]:list-none [&_ul]:p-0 [&_li]:relative [&_li]:pl-[1.4em] [&_li]:leading-[var(--leading-prose)]",
30
+ "[&_li]:before:absolute [&_li]:before:left-0 [&_li]:before:text-ink-mute [&_li]:before:content-['[_*]_']",
31
+ "[&_ol]:mt-[1.1em] [&_ol]:pl-[1.4em] [&_li]:marker:text-ink-mute",
32
+ className,
33
+ )}
34
+ >
35
+ {children}
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1,55 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ import { cn } from "../../lib/utils";
4
+ import { Reveal } from "../../motion/primitives";
5
+
6
+ /**
7
+ * A document section (D1, #4429).
8
+ *
9
+ * A full-bleed hairline on top — it crosses the page rails, as the landing
10
+ * bands' rules do — then one inline inset (`--page-pad`) and a block step
11
+ * tighter than the landing's `--page-step`, because a document section is a
12
+ * few rows rather than a band. Headings number themselves `// 01`, `// 02`
13
+ * from the frame's counter. The content rises in once when scrolled into view.
14
+ *
15
+ * Utilities only — no site/app CSS class.
16
+ */
17
+ export interface SectionProps {
18
+ /** Anchor target, when a section is linked to. */
19
+ id?: string;
20
+ /** Section heading; the one h2 at `--type-section`. */
21
+ title?: ReactNode;
22
+ /** One sentence under the heading, at body size and prose leading. */
23
+ lede?: ReactNode;
24
+ children?: ReactNode;
25
+ className?: string;
26
+ }
27
+
28
+ export function Section({ id, title, lede, children, className }: SectionProps) {
29
+ return (
30
+ <section
31
+ id={id}
32
+ className={cn(
33
+ "relative px-[var(--page-pad)] py-[clamp(3rem,6vw,5rem)]",
34
+ "before:pointer-events-none before:absolute before:top-0 before:left-1/2 before:h-px before:w-screen before:-translate-x-1/2 before:bg-hair",
35
+ className,
36
+ )}
37
+ >
38
+ <Reveal>
39
+ {title ? (
40
+ <h2 className="m-0 max-w-[var(--measure-prose)] text-[length:var(--type-section)] font-medium leading-[1.35] tracking-[-0.01em] text-ink [counter-increment:doc-section] before:mb-[0.8rem] before:block before:font-mono before:text-[0.72rem] before:font-normal before:tracking-[0.04em] before:text-ink-mute before:content-['//_'_counter(doc-section,decimal-leading-zero)]">
41
+ {title}
42
+ </h2>
43
+ ) : null}
44
+ {lede ? (
45
+ <p className="mt-[0.9rem] mb-0 max-w-[var(--measure-prose)] text-[length:var(--type-body)] leading-[var(--leading-prose)] text-ink-soft">
46
+ {lede}
47
+ </p>
48
+ ) : null}
49
+ {children ? (
50
+ <div className={cn(title || lede ? "mt-[1.6rem]" : undefined)}>{children}</div>
51
+ ) : null}
52
+ </Reveal>
53
+ </section>
54
+ );
55
+ }
@@ -0,0 +1,13 @@
1
+ export {
2
+ DocumentFrame,
3
+ type DocumentFrameProps,
4
+ } from "./DocumentFrame";
5
+ export { Section, type SectionProps } from "./Section";
6
+ export { PageTitle, type PageTitleProps } from "./PageTitle";
7
+ export { Prose, type ProseProps } from "./Prose";
8
+ export {
9
+ GlyphList,
10
+ GlyphRow,
11
+ type GlyphListProps,
12
+ type GlyphRowProps,
13
+ } from "./GlyphList";