@arbidocs/blocks 0.3.184 → 0.4.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 (598) hide show
  1. package/README.md +100 -0
  2. package/dist/agents/approvals/AuthorizeAgentParts.d.ts +79 -0
  3. package/dist/agents/approvals/ConsentPage.d.ts +76 -0
  4. package/dist/agents/approvals/ConsentParts.d.ts +37 -0
  5. package/dist/agents/approvals/index.d.ts +3 -0
  6. package/dist/agents/config/ConfigField.d.ts +43 -0
  7. package/dist/agents/config/ConfigForm.d.ts +35 -0
  8. package/dist/agents/config/TupleArrayField.d.ts +32 -0
  9. package/dist/agents/config/index.d.ts +4 -0
  10. package/dist/agents/config/schema-utils.d.ts +28 -0
  11. package/dist/agents/definitions/AgentCard.d.ts +63 -0
  12. package/dist/agents/definitions/AgentCreator.d.ts +118 -0
  13. package/dist/agents/definitions/AgentEditorParts.d.ts +63 -0
  14. package/dist/agents/definitions/AgentGallery.d.ts +29 -0
  15. package/dist/agents/definitions/index.d.ts +4 -0
  16. package/dist/agents/index.cjs +595 -0
  17. package/dist/agents/index.cjs.map +1 -0
  18. package/dist/agents/index.d.ts +7 -0
  19. package/dist/agents/index.js +14 -0
  20. package/dist/agents/index.js.map +1 -0
  21. package/dist/agents/runs/AgentBar.d.ts +103 -0
  22. package/dist/agents/runs/AgentSteps.d.ts +157 -0
  23. package/dist/agents/runs/SubagentRoster.d.ts +37 -0
  24. package/dist/agents/runs/index.d.ts +3 -0
  25. package/dist/agents/skills/SkillBrowserParts.d.ts +70 -0
  26. package/dist/agents/skills/SkillCard.d.ts +48 -0
  27. package/dist/agents/skills/SkillForms.d.ts +64 -0
  28. package/dist/agents/skills/SkillParts.d.ts +31 -0
  29. package/dist/agents/skills/SkillRow.d.ts +34 -0
  30. package/dist/agents/skills/index.d.ts +5 -0
  31. package/dist/agents/tasks/LiveRunsBanner.d.ts +26 -0
  32. package/dist/agents/tasks/RecurrenceBuilder.d.ts +36 -0
  33. package/dist/agents/tasks/TaskComposer.d.ts +108 -0
  34. package/dist/agents/tasks/TaskPlan.d.ts +78 -0
  35. package/dist/agents/tasks/TaskRowActions.d.ts +43 -0
  36. package/dist/agents/tasks/TaskRunsDialog.d.ts +45 -0
  37. package/dist/agents/tasks/TasksChrome.d.ts +36 -0
  38. package/dist/agents/tasks/UploadTaskItem.d.ts +39 -0
  39. package/dist/agents/tasks/UploadTaskList.d.ts +35 -0
  40. package/dist/agents/tasks/elapsed.d.ts +2 -0
  41. package/dist/agents/tasks/index.d.ts +13 -0
  42. package/dist/agents/tasks/rrule.d.ts +36 -0
  43. package/dist/agents/tasks/taskColumns.d.ts +68 -0
  44. package/dist/agents/tasks/taskLabels.d.ts +26 -0
  45. package/dist/agents/workflows/AgentSelect.d.ts +33 -0
  46. package/dist/agents/workflows/SchemaForm.d.ts +37 -0
  47. package/dist/agents/workflows/WorkflowConfigDialog.d.ts +73 -0
  48. package/dist/agents/workflows/WorkflowLauncher.d.ts +38 -0
  49. package/dist/agents/workflows/index.d.ts +6 -0
  50. package/dist/agents/workflows/types.d.ts +125 -0
  51. package/dist/agents/workflows/workflow.d.ts +62 -0
  52. package/dist/auth/AuthFooter.d.ts +56 -0
  53. package/dist/auth/AuthForm.d.ts +105 -0
  54. package/dist/auth/AuthLayout.d.ts +46 -0
  55. package/dist/auth/PasswordStrengthInput.d.ts +44 -0
  56. package/dist/auth/RecoveryDialogs.d.ts +90 -0
  57. package/dist/auth/SsoLoginButton.d.ts +19 -0
  58. package/dist/auth/index.cjs +123 -0
  59. package/dist/auth/index.cjs.map +1 -0
  60. package/dist/auth/index.d.ts +6 -0
  61. package/dist/auth/index.js +6 -0
  62. package/dist/auth/index.js.map +1 -0
  63. package/dist/builder/AgentsPanel.d.ts +9 -0
  64. package/dist/builder/ModuleManager.d.ts +6 -0
  65. package/dist/builder/VerticalBuilder.d.ts +32 -0
  66. package/dist/builder/agents/store.d.ts +21 -0
  67. package/dist/builder/export.d.ts +30 -0
  68. package/dist/builder/modules/registry.d.ts +11 -0
  69. package/dist/builder/modules/store.d.ts +29 -0
  70. package/dist/builder/modules/types.d.ts +29 -0
  71. package/dist/builder/types.d.ts +28 -0
  72. package/dist/chat/BranchControls.d.ts +33 -0
  73. package/dist/chat/Composer.d.ts +156 -0
  74. package/dist/chat/ContextChip.d.ts +19 -0
  75. package/dist/chat/ContextPanel.d.ts +108 -0
  76. package/dist/chat/ConversationEmpty.d.ts +53 -0
  77. package/dist/chat/ConversationLayout.d.ts +40 -0
  78. package/dist/chat/ConversationParts.d.ts +62 -0
  79. package/dist/chat/ConversationSearchView.d.ts +57 -0
  80. package/dist/chat/LabelPinRow.d.ts +30 -0
  81. package/dist/chat/Message.d.ts +189 -0
  82. package/dist/chat/MessageAlert.d.ts +25 -0
  83. package/dist/chat/MessageList.d.ts +102 -0
  84. package/dist/chat/ModelPicker.d.ts +103 -0
  85. package/dist/chat/PendingAnswerBar.d.ts +36 -0
  86. package/dist/chat/PinnedDocChip.d.ts +22 -0
  87. package/dist/chat/SlashMenu.d.ts +57 -0
  88. package/dist/chat/ThreadMap.d.ts +45 -0
  89. package/dist/chat/index.cjs +423 -0
  90. package/dist/chat/index.cjs.map +1 -0
  91. package/dist/chat/index.d.ts +21 -0
  92. package/dist/chat/index.js +6 -0
  93. package/dist/chat/index.js.map +1 -0
  94. package/dist/chat/test-id.d.ts +16 -0
  95. package/dist/chat/useStreamAnnouncement.d.ts +19 -0
  96. package/dist/chunk-223D4727.cjs +50 -0
  97. package/dist/chunk-223D4727.cjs.map +1 -0
  98. package/dist/chunk-4EZVCGRL.js +803 -0
  99. package/dist/chunk-4EZVCGRL.js.map +1 -0
  100. package/dist/chunk-54Q3RNJU.cjs +516 -0
  101. package/dist/chunk-54Q3RNJU.cjs.map +1 -0
  102. package/dist/chunk-5B4PXAKI.cjs +287 -0
  103. package/dist/chunk-5B4PXAKI.cjs.map +1 -0
  104. package/dist/chunk-5TYEJOXY.js +1762 -0
  105. package/dist/chunk-5TYEJOXY.js.map +1 -0
  106. package/dist/chunk-6ALISABK.cjs +677 -0
  107. package/dist/chunk-6ALISABK.cjs.map +1 -0
  108. package/dist/chunk-6HIPFEID.cjs +574 -0
  109. package/dist/chunk-6HIPFEID.cjs.map +1 -0
  110. package/dist/chunk-76JDDMSP.js +31 -0
  111. package/dist/chunk-76JDDMSP.js.map +1 -0
  112. package/dist/chunk-7F6CBP3Z.js +12 -0
  113. package/dist/chunk-7F6CBP3Z.js.map +1 -0
  114. package/dist/chunk-7G2LJMUG.cjs +45 -0
  115. package/dist/chunk-7G2LJMUG.cjs.map +1 -0
  116. package/dist/chunk-7G3JNSJB.cjs +1809 -0
  117. package/dist/chunk-7G3JNSJB.cjs.map +1 -0
  118. package/dist/chunk-A2YAC22G.js +93 -0
  119. package/dist/chunk-A2YAC22G.js.map +1 -0
  120. package/dist/chunk-ADOKTJHV.cjs +262 -0
  121. package/dist/chunk-ADOKTJHV.cjs.map +1 -0
  122. package/dist/chunk-AXIZ2MDV.js +751 -0
  123. package/dist/chunk-AXIZ2MDV.js.map +1 -0
  124. package/dist/chunk-AZQDNYH4.js +2865 -0
  125. package/dist/chunk-AZQDNYH4.js.map +1 -0
  126. package/dist/chunk-C54XEN5T.cjs +34 -0
  127. package/dist/chunk-C54XEN5T.cjs.map +1 -0
  128. package/dist/chunk-CQCC7LE7.js +210 -0
  129. package/dist/chunk-CQCC7LE7.js.map +1 -0
  130. package/dist/chunk-CRIKTUEU.cjs +47 -0
  131. package/dist/chunk-CRIKTUEU.cjs.map +1 -0
  132. package/dist/chunk-CTZ5745I.js +564 -0
  133. package/dist/chunk-CTZ5745I.js.map +1 -0
  134. package/dist/chunk-DPLRHEJZ.js +78 -0
  135. package/dist/chunk-DPLRHEJZ.js.map +1 -0
  136. package/dist/chunk-DVLEQURC.js +672 -0
  137. package/dist/chunk-DVLEQURC.js.map +1 -0
  138. package/dist/chunk-ELR74ME6.cjs +68 -0
  139. package/dist/chunk-ELR74ME6.cjs.map +1 -0
  140. package/dist/{chunk-DBAUZD7A.cjs → chunk-FZQJ2S6P.cjs} +244 -1123
  141. package/dist/chunk-FZQJ2S6P.cjs.map +1 -0
  142. package/dist/chunk-G3G7LZPM.cjs +205 -0
  143. package/dist/chunk-G3G7LZPM.cjs.map +1 -0
  144. package/dist/chunk-GDFWJ73C.cjs +2973 -0
  145. package/dist/chunk-GDFWJ73C.cjs.map +1 -0
  146. package/dist/chunk-ITGHMJOM.js +5528 -0
  147. package/dist/chunk-ITGHMJOM.js.map +1 -0
  148. package/dist/chunk-K4BGOPGG.js +79 -0
  149. package/dist/chunk-K4BGOPGG.js.map +1 -0
  150. package/dist/chunk-KUA3BCT2.cjs +272 -0
  151. package/dist/chunk-KUA3BCT2.cjs.map +1 -0
  152. package/dist/chunk-LGBAZD37.js +341 -0
  153. package/dist/chunk-LGBAZD37.js.map +1 -0
  154. package/dist/chunk-MHVNT4J3.cjs +15 -0
  155. package/dist/chunk-MHVNT4J3.cjs.map +1 -0
  156. package/dist/chunk-MMYCZRKT.cjs +168 -0
  157. package/dist/chunk-MMYCZRKT.cjs.map +1 -0
  158. package/dist/chunk-NBV56SGU.js +42 -0
  159. package/dist/chunk-NBV56SGU.js.map +1 -0
  160. package/dist/chunk-NPLYHR2E.js +13 -0
  161. package/dist/chunk-NPLYHR2E.js.map +1 -0
  162. package/dist/chunk-NUNKSZKU.js +203 -0
  163. package/dist/chunk-NUNKSZKU.js.map +1 -0
  164. package/dist/chunk-OB5F4577.cjs +40 -0
  165. package/dist/chunk-OB5F4577.cjs.map +1 -0
  166. package/dist/chunk-OUW6G4O2.cjs +96 -0
  167. package/dist/chunk-OUW6G4O2.cjs.map +1 -0
  168. package/dist/chunk-OVEQERPO.js +66 -0
  169. package/dist/chunk-OVEQERPO.js.map +1 -0
  170. package/dist/chunk-P6GHJSLR.js +34 -0
  171. package/dist/chunk-P6GHJSLR.js.map +1 -0
  172. package/dist/chunk-PCB2BPN3.cjs +41 -0
  173. package/dist/chunk-PCB2BPN3.cjs.map +1 -0
  174. package/dist/chunk-PPCATBOY.cjs +15 -0
  175. package/dist/chunk-PPCATBOY.cjs.map +1 -0
  176. package/dist/chunk-QN42OA5J.js +887 -0
  177. package/dist/chunk-QN42OA5J.js.map +1 -0
  178. package/dist/{chunk-FZ2S6VAZ.js → chunk-RBXZYNVB.js} +223 -1102
  179. package/dist/chunk-RBXZYNVB.js.map +1 -0
  180. package/dist/chunk-RC6VTY2H.js +47 -0
  181. package/dist/chunk-RC6VTY2H.js.map +1 -0
  182. package/dist/chunk-RFIBUWLF.cjs +232 -0
  183. package/dist/chunk-RFIBUWLF.cjs.map +1 -0
  184. package/dist/chunk-S5T7ZTX2.js +266 -0
  185. package/dist/chunk-S5T7ZTX2.js.map +1 -0
  186. package/dist/chunk-S7PSMMRG.js +38 -0
  187. package/dist/chunk-S7PSMMRG.js.map +1 -0
  188. package/dist/chunk-SCFYPAG6.cjs +18 -0
  189. package/dist/chunk-SCFYPAG6.cjs.map +1 -0
  190. package/dist/chunk-SYDHKKRZ.cjs +818 -0
  191. package/dist/chunk-SYDHKKRZ.cjs.map +1 -0
  192. package/dist/chunk-TX2ZICS7.js +139 -0
  193. package/dist/chunk-TX2ZICS7.js.map +1 -0
  194. package/dist/chunk-TYZUCAT7.js +787 -0
  195. package/dist/chunk-TYZUCAT7.js.map +1 -0
  196. package/dist/chunk-U2E3WT3J.js +45 -0
  197. package/dist/chunk-U2E3WT3J.js.map +1 -0
  198. package/dist/chunk-UBNVIIBT.js +284 -0
  199. package/dist/chunk-UBNVIIBT.js.map +1 -0
  200. package/dist/chunk-UFHMLHIR.cjs +66 -0
  201. package/dist/chunk-UFHMLHIR.cjs.map +1 -0
  202. package/dist/chunk-UJE32SST.js +39 -0
  203. package/dist/chunk-UJE32SST.js.map +1 -0
  204. package/dist/chunk-ULWRNGGE.cjs +146 -0
  205. package/dist/chunk-ULWRNGGE.cjs.map +1 -0
  206. package/dist/chunk-UTWX2X2A.js +165 -0
  207. package/dist/chunk-UTWX2X2A.js.map +1 -0
  208. package/dist/chunk-UWGIB3VQ.js +64 -0
  209. package/dist/chunk-UWGIB3VQ.js.map +1 -0
  210. package/dist/chunk-V4ISCZJ7.cjs +207 -0
  211. package/dist/chunk-V4ISCZJ7.cjs.map +1 -0
  212. package/dist/chunk-VFUWWH52.cjs +83 -0
  213. package/dist/chunk-VFUWWH52.cjs.map +1 -0
  214. package/dist/chunk-VILAPTCB.js +259 -0
  215. package/dist/chunk-VILAPTCB.js.map +1 -0
  216. package/dist/chunk-VLCY46K6.cjs +82 -0
  217. package/dist/chunk-VLCY46K6.cjs.map +1 -0
  218. package/dist/chunk-VPPX5XUF.cjs +813 -0
  219. package/dist/chunk-VPPX5XUF.cjs.map +1 -0
  220. package/dist/chunk-WJMEXTVD.cjs +122 -0
  221. package/dist/chunk-WJMEXTVD.cjs.map +1 -0
  222. package/dist/chunk-WTNMWEBC.js +504 -0
  223. package/dist/chunk-WTNMWEBC.js.map +1 -0
  224. package/dist/chunk-WW6EOVZA.js +112 -0
  225. package/dist/chunk-WW6EOVZA.js.map +1 -0
  226. package/dist/chunk-XNBAXRY7.cjs +5673 -0
  227. package/dist/chunk-XNBAXRY7.cjs.map +1 -0
  228. package/dist/chunk-XQ7PKKDY.cjs +787 -0
  229. package/dist/chunk-XQ7PKKDY.cjs.map +1 -0
  230. package/dist/chunk-XZIYRKLW.cjs +347 -0
  231. package/dist/chunk-XZIYRKLW.cjs.map +1 -0
  232. package/dist/chunk-YBXCZEWS.js +187 -0
  233. package/dist/chunk-YBXCZEWS.js.map +1 -0
  234. package/dist/chunk-YDHO4AVL.js +16 -0
  235. package/dist/chunk-YDHO4AVL.js.map +1 -0
  236. package/dist/chunk-ZORQ5M3W.cjs +934 -0
  237. package/dist/chunk-ZORQ5M3W.cjs.map +1 -0
  238. package/dist/chunk-ZW6FPIFC.cjs +36 -0
  239. package/dist/chunk-ZW6FPIFC.cjs.map +1 -0
  240. package/dist/citations/CitationEditor.d.ts +58 -0
  241. package/dist/citations/PassagePill.d.ts +49 -0
  242. package/dist/citations/QuietMarks.d.ts +81 -0
  243. package/dist/citations/index.cjs +47 -0
  244. package/dist/citations/index.cjs.map +1 -0
  245. package/dist/citations/index.d.ts +3 -0
  246. package/dist/citations/index.js +6 -0
  247. package/dist/citations/index.js.map +1 -0
  248. package/dist/collaboration/contacts/AddContactsParts.d.ts +46 -0
  249. package/dist/collaboration/contacts/index.d.ts +1 -0
  250. package/dist/collaboration/direct-messages/DirectMessages.d.ts +33 -0
  251. package/dist/collaboration/direct-messages/DmParts.d.ts +139 -0
  252. package/dist/collaboration/direct-messages/index.d.ts +2 -0
  253. package/dist/collaboration/index.cjs +141 -0
  254. package/dist/collaboration/index.cjs.map +1 -0
  255. package/dist/collaboration/index.d.ts +5 -0
  256. package/dist/collaboration/index.js +8 -0
  257. package/dist/collaboration/index.js.map +1 -0
  258. package/dist/collaboration/mail/MailFolderTree.d.ts +34 -0
  259. package/dist/collaboration/mail/index.d.ts +2 -0
  260. package/dist/collaboration/mail/mailFolders.d.ts +25 -0
  261. package/dist/collaboration/members/WorkspaceMembers.d.ts +74 -0
  262. package/dist/collaboration/members/index.d.ts +1 -0
  263. package/dist/collaboration/sharing/ShareControl.d.ts +38 -0
  264. package/dist/collaboration/sharing/index.d.ts +1 -0
  265. package/dist/components/Accordion.d.ts +12 -0
  266. package/dist/components/ActionLink.d.ts +18 -0
  267. package/dist/components/AskBar.d.ts +48 -0
  268. package/dist/components/AvatarBlock.d.ts +9 -0
  269. package/dist/components/Banner.d.ts +12 -0
  270. package/dist/components/BlockImage.d.ts +18 -0
  271. package/dist/components/CTABanner.d.ts +17 -0
  272. package/dist/components/Callout.d.ts +9 -0
  273. package/dist/components/Chart.d.ts +27 -0
  274. package/dist/components/CollectionDetail.d.ts +23 -0
  275. package/dist/components/Columns.d.ts +11 -0
  276. package/dist/components/ContactForm.d.ts +42 -0
  277. package/dist/components/Container.d.ts +11 -0
  278. package/dist/components/DataTable.d.ts +47 -0
  279. package/dist/components/DataTableBlock.d.ts +26 -0
  280. package/dist/components/EmptyState.d.ts +11 -0
  281. package/dist/components/EntityChip.d.ts +24 -0
  282. package/dist/components/EntityIdentityBar.d.ts +90 -0
  283. package/dist/components/EntityTooltip.d.ts +43 -0
  284. package/dist/components/FAQ.d.ts +14 -0
  285. package/dist/components/FeatureGrid.d.ts +18 -0
  286. package/dist/components/Footer.d.ts +25 -0
  287. package/dist/components/Gallery.d.ts +15 -0
  288. package/dist/components/Hero.d.ts +35 -0
  289. package/dist/components/ListBlock.d.ts +10 -0
  290. package/dist/components/LogoCloud.d.ts +12 -0
  291. package/dist/components/MediaText.d.ts +15 -0
  292. package/dist/components/MemberAvatarStack.d.ts +36 -0
  293. package/dist/components/MetricCard.d.ts +28 -0
  294. package/dist/components/Navbar.d.ts +39 -0
  295. package/dist/components/PageHeader.d.ts +15 -0
  296. package/dist/components/PricingTable.d.ts +19 -0
  297. package/dist/components/RichTextBlock.d.ts +10 -0
  298. package/dist/components/SectionHeading.d.ts +11 -0
  299. package/dist/components/Spacer.d.ts +7 -0
  300. package/dist/components/StatGroup.d.ts +12 -0
  301. package/dist/components/Steps.d.ts +12 -0
  302. package/dist/components/Tabs.d.ts +15 -0
  303. package/dist/components/TeamGrid.d.ts +18 -0
  304. package/dist/components/Testimonial.d.ts +9 -0
  305. package/dist/components/TestimonialGrid.d.ts +13 -0
  306. package/dist/components/ToneBadge.d.ts +18 -0
  307. package/dist/components/Toolbar.d.ts +11 -0
  308. package/dist/components/UsageMeter.d.ts +21 -0
  309. package/dist/components/VideoEmbed.d.ts +16 -0
  310. package/dist/components/assetImage.d.ts +16 -0
  311. package/dist/components/assetResolver.d.ts +57 -0
  312. package/dist/components/blockLink.d.ts +26 -0
  313. package/dist/components/tones.d.ts +14 -0
  314. package/dist/connect/index.cjs +65 -0
  315. package/dist/connect/index.cjs.map +1 -0
  316. package/dist/connect/index.d.ts +8 -0
  317. package/dist/connect/index.js +28 -0
  318. package/dist/connect/index.js.map +1 -0
  319. package/dist/connection/ArbiAppProvider.d.ts +16 -0
  320. package/dist/connection/ConnectionProvider.d.ts +50 -0
  321. package/dist/connection/ai.d.ts +99 -0
  322. package/dist/connection/types.d.ts +54 -0
  323. package/dist/connection/useImageGen.d.ts +22 -0
  324. package/dist/facts/FactComposer.d.ts +75 -0
  325. package/dist/facts/FactDateInput.d.ts +34 -0
  326. package/dist/facts/FactLabelsCell.d.ts +35 -0
  327. package/dist/facts/FactPassages.d.ts +52 -0
  328. package/dist/facts/FactRowActions.d.ts +18 -0
  329. package/dist/facts/FactSearchParts.d.ts +80 -0
  330. package/dist/facts/FactSourceGroup.d.ts +26 -0
  331. package/dist/facts/FactTimelineViews.d.ts +37 -0
  332. package/dist/facts/FactsBulkBar.d.ts +53 -0
  333. package/dist/facts/FactsEmptyState.d.ts +38 -0
  334. package/dist/facts/FactsFieldsButton.d.ts +21 -0
  335. package/dist/facts/FactsFilterInput.d.ts +46 -0
  336. package/dist/facts/FactsTable.d.ts +28 -0
  337. package/dist/facts/FactsToolbar.d.ts +53 -0
  338. package/dist/facts/FactsViewToggle.d.ts +36 -0
  339. package/dist/facts/fact-date.d.ts +22 -0
  340. package/dist/facts/fact-text.d.ts +14 -0
  341. package/dist/facts/factColumns.d.ts +88 -0
  342. package/dist/facts/index.cjs +2372 -0
  343. package/dist/facts/index.cjs.map +1 -0
  344. package/dist/facts/index.d.ts +34 -0
  345. package/dist/facts/index.js +2316 -0
  346. package/dist/facts/index.js.map +1 -0
  347. package/dist/facts/timezone.d.ts +4 -0
  348. package/dist/files/AiReviewDialog.d.ts +77 -0
  349. package/dist/files/DocStatusIcon.d.ts +12 -0
  350. package/dist/files/DocumentGrid.d.ts +27 -0
  351. package/dist/files/Explorer.d.ts +10 -0
  352. package/dist/files/ExplorerSurface.d.ts +34 -0
  353. package/dist/files/ExplorerTile.d.ts +142 -0
  354. package/dist/files/ExportParts.d.ts +114 -0
  355. package/dist/files/FieldParts.d.ts +64 -0
  356. package/dist/files/FilesPage.d.ts +20 -0
  357. package/dist/files/FilesToolbar.d.ts +59 -0
  358. package/dist/files/FolderPicker.d.ts +82 -0
  359. package/dist/files/GridView.d.ts +59 -0
  360. package/dist/files/HtmlViewerParts.d.ts +183 -0
  361. package/dist/files/MoveToFolderDialog.d.ts +32 -0
  362. package/dist/files/RedlineParts.d.ts +72 -0
  363. package/dist/files/SelectionBar.d.ts +65 -0
  364. package/dist/files/StatusPill.d.ts +23 -0
  365. package/dist/files/TagPassagePanel.d.ts +60 -0
  366. package/dist/files/UploadDropzone.d.ts +33 -0
  367. package/dist/files/UploadFooter.d.ts +59 -0
  368. package/dist/files/UploadParts.d.ts +78 -0
  369. package/dist/files/UploadSources.d.ts +77 -0
  370. package/dist/files/VersionTimeline.d.ts +60 -0
  371. package/dist/files/ViewToggle.d.ts +49 -0
  372. package/dist/files/ViewerChrome.d.ts +155 -0
  373. package/dist/files/ViewerLayout.d.ts +32 -0
  374. package/dist/files/ViewerParts.d.ts +62 -0
  375. package/dist/files/bulk/BulkActionsBar.d.ts +76 -0
  376. package/dist/files/bulk/FolderFilterButton.d.ts +35 -0
  377. package/dist/files/bulk/index.d.ts +2 -0
  378. package/dist/files/cells/DocumentNameCell.d.ts +31 -0
  379. package/dist/files/cells/FolderCell.d.ts +25 -0
  380. package/dist/files/cells/HoverIconCell.d.ts +21 -0
  381. package/dist/files/cells/LabelMultiSelect.d.ts +50 -0
  382. package/dist/files/cells/RelatedDocsCell.d.ts +22 -0
  383. package/dist/files/cells/TagColumnParts.d.ts +29 -0
  384. package/dist/files/cells/index.d.ts +6 -0
  385. package/dist/files/documentGridLayout.d.ts +31 -0
  386. package/dist/files/grid-test-ids.d.ts +18 -0
  387. package/dist/files/import/CalendarImportRow.d.ts +26 -0
  388. package/dist/files/import/ImportParts.d.ts +114 -0
  389. package/dist/files/import/TaskSection.d.ts +51 -0
  390. package/dist/files/import/UrlInputDialogView.d.ts +63 -0
  391. package/dist/files/import/VendorLogo.d.ts +15 -0
  392. package/dist/files/import/index.d.ts +5 -0
  393. package/dist/files/index.cjs +7589 -0
  394. package/dist/files/index.cjs.map +1 -0
  395. package/dist/files/index.d.ts +34 -0
  396. package/dist/files/index.js +7374 -0
  397. package/dist/files/index.js.map +1 -0
  398. package/dist/files/page/FilesAddMenu.d.ts +30 -0
  399. package/dist/files/page/FilesPageParts.d.ts +24 -0
  400. package/dist/files/page/FilesPageTitle.d.ts +24 -0
  401. package/dist/files/page/index.d.ts +3 -0
  402. package/dist/files/tags/BulkTagEditor.d.ts +136 -0
  403. package/dist/files/tags/DocTagPopover.d.ts +113 -0
  404. package/dist/files/tags/TagManager.d.ts +54 -0
  405. package/dist/files/tags/index.d.ts +3 -0
  406. package/dist/files/views/FieldsEditorParts.d.ts +151 -0
  407. package/dist/files/views/FieldsManagerParts.d.ts +17 -0
  408. package/dist/files/views/TagFormParts.d.ts +109 -0
  409. package/dist/files/views/ViewSelectorMenu.d.ts +66 -0
  410. package/dist/files/views/fieldsEditorModel.d.ts +43 -0
  411. package/dist/files/views/index.d.ts +5 -0
  412. package/dist/home/ActionMenuDialog.d.ts +26 -0
  413. package/dist/home/AddFilesFirst.d.ts +22 -0
  414. package/dist/home/CardHeaderBar.d.ts +40 -0
  415. package/dist/home/CollapsibleSection.d.ts +43 -0
  416. package/dist/home/CreateTile.d.ts +17 -0
  417. package/dist/home/DashboardParts.d.ts +32 -0
  418. package/dist/home/FactsStrip.d.ts +41 -0
  419. package/dist/home/FoldSection.d.ts +19 -0
  420. package/dist/home/GettingStartedStrip.d.ts +49 -0
  421. package/dist/home/Greeting.d.ts +18 -0
  422. package/dist/home/HomeLayout.d.ts +28 -0
  423. package/dist/home/KeyValueRow.d.ts +43 -0
  424. package/dist/home/ProjectBandParts.d.ts +70 -0
  425. package/dist/home/QuickActionDialogHeader.d.ts +21 -0
  426. package/dist/home/RecentList.d.ts +48 -0
  427. package/dist/home/ScopePicker.d.ts +65 -0
  428. package/dist/home/StartTiles.d.ts +33 -0
  429. package/dist/home/index.cjs +854 -0
  430. package/dist/home/index.cjs.map +1 -0
  431. package/dist/home/index.d.ts +37 -0
  432. package/dist/home/index.js +763 -0
  433. package/dist/home/index.js.map +1 -0
  434. package/dist/home/sections.d.ts +33 -0
  435. package/dist/index.cjs +1932 -5547
  436. package/dist/index.cjs.map +1 -1
  437. package/dist/index.d.ts +71 -1716
  438. package/dist/index.js +142 -5316
  439. package/dist/index.js.map +1 -1
  440. package/dist/lib/balanced-columns.d.ts +8 -0
  441. package/dist/lib/format.d.ts +37 -0
  442. package/dist/lib/observe-resize.d.ts +6 -0
  443. package/dist/lib/password-strength.d.ts +24 -0
  444. package/dist/lib/sidebar-mode.d.ts +46 -0
  445. package/dist/lib/testid.d.ts +7 -0
  446. package/dist/lib/use-drawer.d.ts +11 -0
  447. package/dist/lib/useControllableState.d.ts +5 -0
  448. package/dist/lib/useDismissibleCard.d.ts +15 -0
  449. package/dist/lib/useListKeyNav.d.ts +42 -0
  450. package/dist/lib/useLongPaste.d.ts +15 -0
  451. package/dist/lib/useRestoreFocus.d.ts +11 -0
  452. package/dist/lib/useScopeSelection.d.ts +34 -0
  453. package/dist/nav/types.d.ts +19 -0
  454. package/dist/provider/BlocksProvider.d.ts +20 -0
  455. package/dist/provider/TooltipScope.d.ts +9 -0
  456. package/dist/record/index.cjs +2 -4
  457. package/dist/record/index.cjs.map +1 -1
  458. package/dist/record/index.d.ts +12 -16
  459. package/dist/record/index.js +2 -4
  460. package/dist/record/index.js.map +1 -1
  461. package/dist/retrieval/HighlightText.d.ts +21 -0
  462. package/dist/retrieval/SearchEmptyState.d.ts +39 -0
  463. package/dist/retrieval/SearchGroupHeader.d.ts +21 -0
  464. package/dist/retrieval/SearchHit.d.ts +36 -0
  465. package/dist/retrieval/SearchPage.d.ts +187 -0
  466. package/dist/retrieval/SearchPagination.d.ts +21 -0
  467. package/dist/retrieval/highlight.d.ts +21 -0
  468. package/dist/retrieval/index.cjs +160 -0
  469. package/dist/retrieval/index.cjs.map +1 -0
  470. package/dist/retrieval/index.d.ts +7 -0
  471. package/dist/retrieval/index.js +7 -0
  472. package/dist/retrieval/index.js.map +1 -0
  473. package/dist/settings/AccountDialogs.d.ts +89 -0
  474. package/dist/settings/AvatarPicker.d.ts +25 -0
  475. package/dist/settings/Billing.d.ts +113 -0
  476. package/dist/settings/ConfigSwitcherBar.d.ts +46 -0
  477. package/dist/settings/ConfirmDialog.d.ts +28 -0
  478. package/dist/settings/ConnectionCard.d.ts +58 -0
  479. package/dist/settings/ConversationSettingsParts.d.ts +53 -0
  480. package/dist/settings/DocumentPicker.d.ts +57 -0
  481. package/dist/settings/EmailWorkspaceDialogView.d.ts +60 -0
  482. package/dist/settings/ErrorDialog.d.ts +36 -0
  483. package/dist/settings/FloatingPanel.d.ts +32 -0
  484. package/dist/settings/JsonTree.d.ts +24 -0
  485. package/dist/settings/LogoutDialog.d.ts +51 -0
  486. package/dist/settings/ModalBreadcrumbHeader.d.ts +32 -0
  487. package/dist/settings/ModalScaffold.d.ts +60 -0
  488. package/dist/settings/MultiSelect.d.ts +111 -0
  489. package/dist/settings/NotificationCategoryList.d.ts +26 -0
  490. package/dist/settings/PanelFrame.d.ts +47 -0
  491. package/dist/settings/PasswordChangeDialog.d.ts +64 -0
  492. package/dist/settings/PlanBadge.d.ts +14 -0
  493. package/dist/settings/PlanCard.d.ts +97 -0
  494. package/dist/settings/PremiumModelsFrame.d.ts +17 -0
  495. package/dist/settings/ProfileCard.d.ts +67 -0
  496. package/dist/settings/Projects.d.ts +108 -0
  497. package/dist/settings/QuotaMeter.d.ts +31 -0
  498. package/dist/settings/ReferralCredit.d.ts +46 -0
  499. package/dist/settings/SegmentedControl.d.ts +20 -0
  500. package/dist/settings/ServerConnectionControls.d.ts +31 -0
  501. package/dist/settings/SettingsPanel.d.ts +61 -0
  502. package/dist/settings/SettingsSwitchRow.d.ts +21 -0
  503. package/dist/settings/SubscriptionParts.d.ts +215 -0
  504. package/dist/settings/SupportPanel.d.ts +32 -0
  505. package/dist/settings/SyncDialogParts.d.ts +155 -0
  506. package/dist/settings/ThreadPreviewDialog.d.ts +18 -0
  507. package/dist/settings/TipsEditorDialog.d.ts +94 -0
  508. package/dist/settings/TriStateFilterMenu.d.ts +66 -0
  509. package/dist/settings/Usage.d.ts +102 -0
  510. package/dist/settings/WelcomeDialog.d.ts +79 -0
  511. package/dist/settings/index.cjs +5131 -0
  512. package/dist/settings/index.cjs.map +1 -0
  513. package/dist/settings/index.d.ts +38 -0
  514. package/dist/settings/index.js +4922 -0
  515. package/dist/settings/index.js.map +1 -0
  516. package/dist/shell/ActionCluster.d.ts +28 -0
  517. package/dist/shell/AskField.d.ts +71 -0
  518. package/dist/shell/InfoBar.d.ts +20 -0
  519. package/dist/shell/MobileBars.d.ts +47 -0
  520. package/dist/shell/OfflinePill.d.ts +28 -0
  521. package/dist/shell/RemoteControlPill.d.ts +23 -0
  522. package/dist/shell/Shell.d.ts +123 -0
  523. package/dist/shell/Sidebar.d.ts +104 -0
  524. package/dist/shell/SidebarBadgeRow.d.ts +29 -0
  525. package/dist/shell/SidebarRowAction.d.ts +24 -0
  526. package/dist/shell/StatusRow.d.ts +20 -0
  527. package/dist/shell/TabHeader.d.ts +70 -0
  528. package/dist/shell/TipCard.d.ts +46 -0
  529. package/dist/shell/ToolButton.d.ts +12 -0
  530. package/dist/shell/Workspace.d.ts +90 -0
  531. package/dist/shell/index.cjs +187 -0
  532. package/dist/shell/index.cjs.map +1 -0
  533. package/dist/shell/index.d.ts +20 -0
  534. package/dist/shell/index.js +10 -0
  535. package/dist/shell/index.js.map +1 -0
  536. package/dist/shell/sidebar-context.d.ts +19 -0
  537. package/dist/shell/types.d.ts +48 -0
  538. package/dist/site/index.cjs +113 -90
  539. package/dist/site/index.d.ts +59 -4
  540. package/dist/site/index.js +8 -1
  541. package/dist/studio/PageRenderer.d.ts +35 -0
  542. package/dist/studio/Section.d.ts +24 -0
  543. package/dist/studio/StudioEditor.d.ts +32 -0
  544. package/dist/studio/aiFields.d.ts +17 -0
  545. package/dist/studio/blockKit.d.ts +36 -0
  546. package/dist/studio/blocksConfig.d.ts +42 -0
  547. package/dist/studio/imageFields.d.ts +14 -0
  548. package/dist/studio/index.cjs +3353 -0
  549. package/dist/studio/index.cjs.map +1 -0
  550. package/dist/studio/index.d.ts +32 -0
  551. package/dist/studio/index.js +3297 -0
  552. package/dist/studio/index.js.map +1 -0
  553. package/dist/studio/liveData.d.ts +4 -0
  554. package/dist/studio/liveWidgetRuntime.d.ts +41 -0
  555. package/dist/studio/persistence.d.ts +38 -0
  556. package/dist/studio/publish.d.ts +39 -0
  557. package/dist/studio/siteBlocks.d.ts +14 -0
  558. package/dist/studio/types.d.ts +46 -0
  559. package/dist/studio/websiteBlocks.d.ts +4 -0
  560. package/dist/studio/widgets.d.ts +20 -0
  561. package/dist/theme/ThemeEditor.d.ts +16 -0
  562. package/dist/theme/fontPairings.d.ts +48 -0
  563. package/dist/theme/store.d.ts +53 -0
  564. package/dist/theme/tokens.d.ts +105 -0
  565. package/dist/timeline/Timeline.d.ts +27 -0
  566. package/dist/timeline/TimelineCalendar.d.ts +54 -0
  567. package/dist/timeline/TimelineGantt.d.ts +71 -0
  568. package/dist/timeline/TimelineZoomControl.d.ts +17 -0
  569. package/dist/timeline/index.cjs +50 -0
  570. package/dist/timeline/index.cjs.map +1 -0
  571. package/dist/timeline/index.d.ts +13 -0
  572. package/dist/timeline/index.js +5 -0
  573. package/dist/timeline/index.js.map +1 -0
  574. package/dist/timeline/span.d.ts +29 -0
  575. package/dist/timeline/types.d.ts +30 -0
  576. package/dist/workspaces/WorkspaceBadges.d.ts +27 -0
  577. package/dist/workspaces/WorkspaceCard.d.ts +142 -0
  578. package/dist/workspaces/WorkspaceFormParts.d.ts +98 -0
  579. package/dist/workspaces/WorkspaceGroup.d.ts +31 -0
  580. package/dist/workspaces/WorkspaceSettingsParts.d.ts +70 -0
  581. package/dist/workspaces/index.cjs +690 -0
  582. package/dist/workspaces/index.cjs.map +1 -0
  583. package/dist/workspaces/index.d.ts +9 -0
  584. package/dist/workspaces/index.js +661 -0
  585. package/dist/workspaces/index.js.map +1 -0
  586. package/package.json +164 -9
  587. package/src/blocks.css +348 -0
  588. package/src/components/grid.css +60 -107
  589. package/src/source.css +20 -0
  590. package/src/studio/studio.css +3 -3
  591. package/src/tokens.css +226 -0
  592. package/dist/chunk-DBAUZD7A.cjs.map +0 -1
  593. package/dist/chunk-FZ2S6VAZ.js.map +0 -1
  594. package/dist/index-DduoEosi.d.cts +0 -846
  595. package/dist/index-DduoEosi.d.ts +0 -846
  596. package/dist/index.d.cts +0 -1717
  597. package/dist/record/index.d.cts +0 -96
  598. package/dist/site/index.d.cts +0 -4
@@ -1,10 +1,12 @@
1
+ "use client";
2
+ import { initials } from './chunk-WW6EOVZA.js';
1
3
  import { create } from 'zustand';
2
4
  import { persist } from 'zustand/middleware';
3
- import { createContext, useState, useEffect, useMemo, useRef, useCallback, useContext } from 'react';
4
- import { RotateCcw, Palette, ChevronLeft, ChevronRight, ZoomOut, ZoomIn, Calendar, X, CalendarDays, GanttChartSquare, ImageIcon, ArrowRight, Quote, ChevronDown, XCircle, AlertTriangle, CheckCircle2, Info, Check, Save } from 'lucide-react';
5
+ import { createContext, useState, useEffect, useContext } from 'react';
6
+ import { RotateCcw, Palette, ImageIcon, ArrowRight, Quote, ChevronDown, X, Menu, Check, Save } from 'lucide-react';
5
7
  import { Input, Card, CardHeader, CardTitle, CardContent, cn, Button, Avatar, AvatarImage, AvatarFallback, AiMarkdown } from '@arbidocs/react/ui';
6
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
- import { createPortal } from 'react-dom';
9
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
8
10
 
9
11
  // src/theme/tokens.ts
10
12
  var THEME_STYLE_ID = "arbi-theme-vars";
@@ -244,110 +246,6 @@ function applyStoredTheme(bundle) {
244
246
  const { colors, fonts, radius } = bundle.useStore.getState();
245
247
  applyThemeVars({ colors, fonts, radius }, { mode: bundle.mode, dark: bundle.darkColors });
246
248
  }
247
-
248
- // src/lib/format.ts
249
- function gbp(value, compact = false) {
250
- return new Intl.NumberFormat("en-GB", {
251
- style: "currency",
252
- currency: "GBP",
253
- maximumFractionDigits: compact && Math.abs(value) >= 1e3 ? 1 : 0,
254
- notation: compact ? "compact" : "standard"
255
- }).format(value);
256
- }
257
- function initials(name) {
258
- const parts = name.trim().split(/\s+/);
259
- if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
260
- return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
261
- }
262
- function parseIso(iso) {
263
- const dateOnly = /^\d{4}-\d{2}-\d{2}$/.test(iso);
264
- const d = new Date(dateOnly ? `${iso}T00:00:00` : iso);
265
- if (Number.isNaN(d.getTime())) throw new Error(`Invalid ISO date: ${iso}`);
266
- return d;
267
- }
268
- function fmtDate(iso) {
269
- try {
270
- return new Intl.DateTimeFormat("en-GB", {
271
- day: "numeric",
272
- month: "short",
273
- year: "numeric"
274
- }).format(parseIso(iso));
275
- } catch {
276
- return iso;
277
- }
278
- }
279
- function fmtDateTime(iso) {
280
- try {
281
- return new Intl.DateTimeFormat("en-GB", {
282
- day: "numeric",
283
- month: "short",
284
- year: "numeric",
285
- hour: "2-digit",
286
- minute: "2-digit",
287
- hour12: false
288
- }).format(parseIso(iso));
289
- } catch {
290
- return iso;
291
- }
292
- }
293
- var RELATIVE_UNITS = [
294
- ["year", 31536e3],
295
- ["month", 2592e3],
296
- ["week", 604800],
297
- ["day", 86400],
298
- ["hour", 3600],
299
- ["minute", 60],
300
- ["second", 1]
301
- ];
302
- function fromNow(iso, from = /* @__PURE__ */ new Date()) {
303
- try {
304
- const diffSeconds = (parseIso(iso).getTime() - from.getTime()) / 1e3;
305
- const abs = Math.abs(diffSeconds);
306
- const rtf = new Intl.RelativeTimeFormat("en-GB", { numeric: "always" });
307
- for (const [unit, secs] of RELATIVE_UNITS) {
308
- if (abs >= secs || unit === "second") {
309
- const value = Math.round(diffSeconds / secs);
310
- return rtf.format(value, unit);
311
- }
312
- }
313
- return rtf.format(0, "second");
314
- } catch {
315
- return iso;
316
- }
317
- }
318
- function daysUntil(iso, from = /* @__PURE__ */ new Date()) {
319
- try {
320
- const target = parseIso(iso);
321
- const a = Date.UTC(target.getFullYear(), target.getMonth(), target.getDate());
322
- const b = Date.UTC(from.getFullYear(), from.getMonth(), from.getDate());
323
- return Math.round((a - b) / 864e5);
324
- } catch {
325
- return 0;
326
- }
327
- }
328
- function hrs(n) {
329
- return `${n.toFixed(1)}h`;
330
- }
331
- function pct(n) {
332
- return `${Math.round(n)}%`;
333
- }
334
- function formatPageRefs(pages) {
335
- const sorted = [...new Set(pages)].sort((a, b) => a - b);
336
- if (sorted.length === 0) return "";
337
- const parts = [];
338
- let start = sorted[0];
339
- let end = sorted[0];
340
- for (const page of sorted.slice(1)) {
341
- if (page === end + 1) {
342
- end = page;
343
- continue;
344
- }
345
- parts.push(start === end ? `${start}` : `${start}\u2013${end}`);
346
- start = end = page;
347
- }
348
- parts.push(start === end ? `${start}` : `${start}\u2013${end}`);
349
- return `${sorted.length === 1 ? "p" : "pp"} ${parts.join(", ")}`;
350
- }
351
249
  function ThemeEditor({
352
250
  bundle,
353
251
  variant = "panel",
@@ -376,9 +274,14 @@ function ThemeEditor({
376
274
  const save = async () => {
377
275
  if (!onSave) return;
378
276
  setSaving(true);
379
- const via = await onSave();
380
- setSavedVia(typeof via === "string" ? via : "saved");
381
- setSaving(false);
277
+ try {
278
+ const via = await onSave();
279
+ setSavedVia(typeof via === "string" ? via : "saved");
280
+ } catch {
281
+ setSavedVia(null);
282
+ } finally {
283
+ setSaving(false);
284
+ }
382
285
  };
383
286
  const Presets = /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
384
287
  presets.map((p) => /* @__PURE__ */ jsx(
@@ -425,7 +328,7 @@ function ThemeEditor({
425
328
  {
426
329
  value: colors[k] ?? "",
427
330
  onChange: (e) => setColor(k, e.target.value),
428
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 h-7 font-mono text-xs",
331
+ className: "bg-card placeholder:text-muted-foreground focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring h-7 font-mono text-xs",
429
332
  "data-testid": tid2(`hex-${k}`)
430
333
  }
431
334
  )
@@ -440,7 +343,7 @@ function ThemeEditor({
440
343
  {
441
344
  value: activePairing?.id ?? "",
442
345
  onChange: (e) => setFontPairing(e.target.value),
443
- className: "mt-1 h-8 w-full rounded-md border border-border bg-card px-2 text-xs text-foreground focus-visible:border-ring/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50",
346
+ className: "mt-1 h-8 w-full rounded-md border border-border bg-card px-2 text-xs text-foreground focus-visible:border-ring/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
444
347
  "data-testid": tid2("font-pairing"),
445
348
  children: [
446
349
  !activePairing && /* @__PURE__ */ jsx("option", { value: "", children: "Custom" }),
@@ -448,7 +351,7 @@ function ThemeEditor({
448
351
  ]
449
352
  }
450
353
  ),
451
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-muted-foreground", children: activePairing?.description ?? "Hand-edited font stacks." })
354
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: activePairing?.description ?? "Hand-edited font stacks." })
452
355
  ] }),
453
356
  /* @__PURE__ */ jsxs("div", { children: [
454
357
  /* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground", children: "Display font stack" }),
@@ -457,7 +360,7 @@ function ThemeEditor({
457
360
  {
458
361
  value: fonts.display,
459
362
  onChange: (e) => setFont("display", e.target.value),
460
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 mt-1 font-mono text-xs",
363
+ className: "bg-card placeholder:text-muted-foreground focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring mt-1 font-mono text-xs",
461
364
  "data-testid": tid2("font-display")
462
365
  }
463
366
  )
@@ -469,7 +372,7 @@ function ThemeEditor({
469
372
  {
470
373
  value: fonts.sans,
471
374
  onChange: (e) => setFont("sans", e.target.value),
472
- className: "bg-card placeholder:text-muted-foreground/70 focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/50 mt-1 font-mono text-xs",
375
+ className: "bg-card placeholder:text-muted-foreground focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring mt-1 font-mono text-xs",
473
376
  "data-testid": tid2("font-sans")
474
377
  }
475
378
  )
@@ -495,7 +398,7 @@ function ThemeEditor({
495
398
  )
496
399
  ] })
497
400
  ] });
498
- const Preview = /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-xl", "data-testid": tid2("preview"), children: [
401
+ const Preview = /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-lg", "data-testid": tid2("preview"), children: [
499
402
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: "Live preview" }) }),
500
403
  /* @__PURE__ */ jsxs(CardContent, { className: "space-y-3", children: [
501
404
  /* @__PURE__ */ jsxs("div", { className: "rounded-[var(--radius)] bg-primary p-4 text-primary-foreground", children: [
@@ -541,16 +444,16 @@ function ThemeEditor({
541
444
  return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col overflow-y-auto bg-card p-5", "data-testid": testIdPrefix, children: [
542
445
  /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center justify-between", children: /* @__PURE__ */ jsx("h2", { className: "font-display text-lg font-semibold text-foreground", children: "Theme" }) }),
543
446
  Presets,
544
- /* @__PURE__ */ jsx("p", { className: "mt-5 mb-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Colours" }),
447
+ /* @__PURE__ */ jsx("p", { className: "mt-5 mb-2 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Colours" }),
545
448
  /* @__PURE__ */ jsx("div", { className: "space-y-3", children: tokens.map((t) => colorRow(t.key, t.label)) }),
546
- /* @__PURE__ */ jsx("p", { className: "mt-6 mb-2 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Typography & shape" }),
449
+ /* @__PURE__ */ jsx("p", { className: "mt-6 mb-2 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: "Typography & shape" }),
547
450
  Typography,
548
451
  SaveBar
549
452
  ] });
550
453
  }
551
454
  return /* @__PURE__ */ jsxs("div", { className: "grid gap-6 lg:grid-cols-[1fr_320px]", "data-testid": testIdPrefix, children: [
552
455
  /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
553
- /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-xl", children: [
456
+ /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-lg", children: [
554
457
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [
555
458
  /* @__PURE__ */ jsx(Palette, { className: "size-4 text-[color:var(--color-primary)]" }),
556
459
  " Presets"
@@ -561,7 +464,7 @@ function ThemeEditor({
561
464
  Card,
562
465
  {
563
466
  variant: "elevated",
564
- className: "rounded-xl",
467
+ className: "rounded-lg",
565
468
  "data-testid": tid2(`group-${group}`),
566
469
  children: [
567
470
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: groupLabels[group] ?? group }) }),
@@ -570,7 +473,7 @@ function ThemeEditor({
570
473
  },
571
474
  group
572
475
  )),
573
- /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-xl", children: [
476
+ /* @__PURE__ */ jsxs(Card, { variant: "elevated", className: "rounded-lg", children: [
574
477
  /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: "Typography & shape" }) }),
575
478
  /* @__PURE__ */ jsx(CardContent, { children: Typography })
576
479
  ] }),
@@ -586,854 +489,6 @@ function tid(...parts) {
586
489
  (p) => String(p).trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "")
587
490
  ).join("-");
588
491
  }
589
-
590
- // src/timeline/span.ts
591
- var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
592
- var MONTH_NAMES = [
593
- "January",
594
- "February",
595
- "March",
596
- "April",
597
- "May",
598
- "June",
599
- "July",
600
- "August",
601
- "September",
602
- "October",
603
- "November",
604
- "December"
605
- ];
606
- var WEEKDAY_NAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
607
- var DAY_MS = 864e5;
608
- function monthLabel(d) {
609
- return `${MONTH_NAMES[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
610
- }
611
- function utcDay(d) {
612
- return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
613
- }
614
- function dayKey(d) {
615
- return d.toISOString().slice(0, 10);
616
- }
617
- function parseIso2(iso) {
618
- if (!iso) return null;
619
- const d = new Date(iso);
620
- return isNaN(d.getTime()) ? null : d;
621
- }
622
- function isMidnight(d) {
623
- return d.getUTCHours() === 0 && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0;
624
- }
625
- function isEndOfDay(d) {
626
- return d.getUTCHours() === 23 && d.getUTCMinutes() === 59;
627
- }
628
- function lastDayOfMonth(d) {
629
- return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0)).getUTCDate();
630
- }
631
- function day(d) {
632
- return `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
633
- }
634
- function zonedDayAndTime(d, timeZone) {
635
- const parts = Object.fromEntries(
636
- new Intl.DateTimeFormat("en-US", {
637
- timeZone,
638
- hourCycle: "h23",
639
- year: "numeric",
640
- month: "short",
641
- day: "numeric",
642
- hour: "2-digit",
643
- minute: "2-digit"
644
- }).formatToParts(d).map((p) => [p.type, p.value])
645
- );
646
- return { day: `${parts.day} ${parts.month} ${parts.year}`, hh: parts.hour, mm: parts.minute };
647
- }
648
- function formatSpan(startIso, endIso, timezone) {
649
- if (!startIso) return "";
650
- const start = new Date(startIso);
651
- const end = endIso ? new Date(endIso) : start;
652
- if (startIso === endIso) {
653
- if (timezone) {
654
- try {
655
- const zoned = zonedDayAndTime(start, timezone);
656
- return `${zoned.day}, ${zoned.hh}:${zoned.mm} ${timezone}`;
657
- } catch {
658
- }
659
- }
660
- const hh = String(start.getUTCHours()).padStart(2, "0");
661
- const mm = String(start.getUTCMinutes()).padStart(2, "0");
662
- return `${day(start)}, ${hh}:${mm} UTC`;
663
- }
664
- if (isMidnight(start) && isEndOfDay(end)) {
665
- const sameDay = start.getUTCFullYear() === end.getUTCFullYear() && start.getUTCMonth() === end.getUTCMonth() && start.getUTCDate() === end.getUTCDate();
666
- if (sameDay) return day(start);
667
- const firstOfMonth = start.getUTCDate() === 1;
668
- const endsMonth = end.getUTCDate() === lastDayOfMonth(end);
669
- const sameMonth = start.getUTCFullYear() === end.getUTCFullYear() && start.getUTCMonth() === end.getUTCMonth();
670
- if (firstOfMonth && endsMonth && sameMonth) {
671
- return `${MONTHS[start.getUTCMonth()]} ${start.getUTCFullYear()}`;
672
- }
673
- const wholeYear = firstOfMonth && endsMonth && start.getUTCMonth() === 0 && end.getUTCMonth() === 11 && start.getUTCFullYear() === end.getUTCFullYear();
674
- if (wholeYear) return String(start.getUTCFullYear());
675
- return `${day(start)} \u2013 ${day(end)}`;
676
- }
677
- return `${day(start)} \u2013 ${day(end)}`;
678
- }
679
- var DEFAULT_MAX_LANES = 3;
680
- var MAX_WEEKS = 2600;
681
- function TimelineCalendar({
682
- items,
683
- onSelect,
684
- selectedIds,
685
- maxLanes = DEFAULT_MAX_LANES,
686
- navigatorContainer,
687
- navigatorTotal,
688
- emptyState,
689
- className,
690
- testId = "timeline-calendar"
691
- }) {
692
- const dated = useMemo(() => items.filter((i) => i.start), [items]);
693
- const sortedItems = useMemo(
694
- () => [...dated].sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime()),
695
- [dated]
696
- );
697
- const indexById = useMemo(() => new Map(sortedItems.map((it, i) => [it.id, i])), [sortedItems]);
698
- const [activeIndex, setActiveIndex] = useState(null);
699
- const scrollRef = useRef(null);
700
- const select = useCallback(
701
- (index) => {
702
- const clamped = Math.max(0, Math.min(sortedItems.length - 1, index));
703
- setActiveIndex(clamped);
704
- onSelect?.(sortedItems[clamped]);
705
- return clamped;
706
- },
707
- [onSelect, sortedItems]
708
- );
709
- const scrollToItem = useCallback(
710
- (id, behavior) => {
711
- scrollRef.current?.querySelector(`[data-testid="${testId}-entry-${id}"]`)?.scrollIntoView({ block: "center", behavior });
712
- },
713
- [testId]
714
- );
715
- const lastNavScrollRef = useRef(null);
716
- const goTo = useCallback(
717
- (index) => {
718
- const target = sortedItems[select(index)];
719
- if (target) {
720
- lastNavScrollRef.current = target.id;
721
- scrollToItem(target.id, "smooth");
722
- }
723
- },
724
- [select, sortedItems, scrollToItem]
725
- );
726
- const selectedKey = (selectedIds ?? []).join("\0");
727
- useEffect(() => {
728
- const id = selectedKey ? selectedKey.split("\0")[0] : null;
729
- if (!id) return;
730
- if (lastNavScrollRef.current === id) {
731
- lastNavScrollRef.current = null;
732
- return;
733
- }
734
- scrollToItem(id, "auto");
735
- }, [selectedKey, scrollToItem]);
736
- const weeks = useMemo(() => {
737
- if (dated.length === 0) return [];
738
- const times = dated.flatMap((i) => [
739
- new Date(i.start).getTime(),
740
- new Date(i.end ?? i.start).getTime()
741
- ]);
742
- const first = utcDay(new Date(Math.min(...times)));
743
- const last = utcDay(new Date(Math.max(...times)));
744
- const gridStart = new Date(first);
745
- gridStart.setUTCDate(first.getUTCDate() - (first.getUTCDay() + 6) % 7);
746
- const out = [];
747
- const cursor = new Date(gridStart);
748
- while (cursor <= last && out.length < MAX_WEEKS) {
749
- out.push(
750
- Array.from({ length: 7 }, (_, d) => {
751
- const day2 = new Date(cursor);
752
- day2.setUTCDate(cursor.getUTCDate() + d);
753
- return day2;
754
- })
755
- );
756
- cursor.setUTCDate(cursor.getUTCDate() + 7);
757
- }
758
- return out;
759
- }, [dated]);
760
- const segmentsByWeek = useMemo(() => {
761
- if (weeks.length === 0) return [];
762
- const gridStartMs = weeks[0][0].getTime();
763
- const WEEK_MS2 = 7 * DAY_MS;
764
- const ranged = dated.map((item) => ({
765
- item,
766
- start: utcDay(new Date(item.start)),
767
- end: utcDay(new Date(item.end ?? item.start))
768
- }));
769
- ranged.sort((a, b) => {
770
- const lenA = b.end.getTime() - b.start.getTime();
771
- const lenB = a.end.getTime() - a.start.getTime();
772
- return lenA - lenB || a.start.getTime() - b.start.getTime();
773
- });
774
- const buckets = weeks.map(() => []);
775
- for (const r of ranged) {
776
- const from = Math.max(0, Math.floor((r.start.getTime() - gridStartMs) / WEEK_MS2));
777
- const to = Math.min(weeks.length - 1, Math.floor((r.end.getTime() - gridStartMs) / WEEK_MS2));
778
- for (let w = from; w <= to; w++) buckets[w].push(r);
779
- }
780
- return weeks.map((week, wi) => {
781
- const weekStart = week[0];
782
- const weekEnd = week[6];
783
- const laneEnds = [];
784
- const segments = [];
785
- let overflow = 0;
786
- for (const { item, start, end } of buckets[wi]) {
787
- const from = start < weekStart ? weekStart : start;
788
- const to = end > weekEnd ? weekEnd : end;
789
- const startCol = Math.round((from.getTime() - weekStart.getTime()) / DAY_MS);
790
- const endCol = Math.round((to.getTime() - weekStart.getTime()) / DAY_MS);
791
- let lane = laneEnds.findIndex((last) => last < startCol);
792
- if (lane === -1) lane = laneEnds.length;
793
- if (lane >= maxLanes) {
794
- overflow += 1;
795
- continue;
796
- }
797
- laneEnds[lane] = endCol;
798
- segments.push({
799
- item,
800
- startCol,
801
- span: endCol - startCol + 1,
802
- isStart: start >= weekStart,
803
- isEnd: end <= weekEnd,
804
- lane
805
- });
806
- }
807
- return { segments, overflow };
808
- });
809
- }, [weeks, dated, maxLanes]);
810
- if (weeks.length === 0 && emptyState) {
811
- return /* @__PURE__ */ jsx(Fragment, { children: emptyState });
812
- }
813
- const selectedSet = new Set(selectedIds ?? []);
814
- const selectedIndex = sortedItems.findIndex((i) => selectedSet.has(i.id));
815
- const currentIndex = selectedIndex >= 0 ? selectedIndex : activeIndex;
816
- const navigator = /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5", "data-testid": `${testId}-nav`, children: [
817
- /* @__PURE__ */ jsx(
818
- "button",
819
- {
820
- type: "button",
821
- "aria-label": "Previous event",
822
- "data-testid": `${testId}-nav-prev`,
823
- disabled: sortedItems.length === 0 || currentIndex === null || currentIndex <= 0,
824
- onClick: () => goTo((currentIndex ?? 0) - 1),
825
- className: "rounded p-0.5 text-muted-foreground enabled:hover:bg-accent enabled:hover:text-foreground disabled:opacity-30",
826
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
827
- }
828
- ),
829
- /* @__PURE__ */ jsxs(
830
- "span",
831
- {
832
- className: "tabular-nums text-sm font-light text-muted-foreground",
833
- "data-testid": `${testId}-nav-position`,
834
- children: [
835
- currentIndex !== null ? currentIndex + 1 : "\u2013",
836
- " /",
837
- " ",
838
- navigatorTotal ?? (sortedItems.length > 0 ? sortedItems.length : "\u2013")
839
- ]
840
- }
841
- ),
842
- /* @__PURE__ */ jsx(
843
- "button",
844
- {
845
- type: "button",
846
- "aria-label": "Next event",
847
- "data-testid": `${testId}-nav-next`,
848
- disabled: sortedItems.length === 0 || currentIndex !== null && currentIndex >= sortedItems.length - 1,
849
- onClick: () => goTo(currentIndex === null ? 0 : currentIndex + 1),
850
- className: "rounded p-0.5 text-muted-foreground enabled:hover:bg-accent enabled:hover:text-foreground disabled:opacity-30",
851
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
852
- }
853
- )
854
- ] });
855
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full", className), "data-testid": testId, children: [
856
- navigatorContainer === void 0 ? navigator && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center justify-end border-b border-border px-2 py-1", children: navigator }) : navigatorContainer && navigator && createPortal(navigator, navigatorContainer),
857
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 border-b border-border bg-background", children: WEEKDAY_NAMES.map((d) => /* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-[11px] text-muted-foreground text-center", children: d }, d)) }),
858
- /* @__PURE__ */ jsx("div", { ref: scrollRef, className: "flex-1 overflow-auto", "data-testid": `${testId}-scroll`, children: weeks.map((week, wi) => {
859
- const { segments, overflow } = segmentsByWeek[wi];
860
- const monthStartDay = week.find((d) => d.getUTCDate() === 1);
861
- const marker = monthStartDay ?? (wi === 0 ? week[0] : void 0);
862
- return /* @__PURE__ */ jsxs("div", { children: [
863
- marker && // Sticky, so the month you are LOOKING at names itself: it
864
- // pins to the top of the scroller while you are inside it and
865
- // is pushed up by the next one. No scroll listener needed.
866
- /* @__PURE__ */ jsx(
867
- "div",
868
- {
869
- className: "sticky top-0 z-10 px-3 py-1 text-xs font-medium text-foreground bg-background/95 backdrop-blur border-y border-border/60",
870
- "data-testid": `${testId}-month-${marker.getUTCFullYear()}-${String(
871
- marker.getUTCMonth() + 1
872
- ).padStart(2, "0")}`,
873
- children: monthLabel(marker)
874
- }
875
- ),
876
- /* @__PURE__ */ jsxs("div", { className: "border-b border-border/40", children: [
877
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 bg-background", children: week.map((day2) => /* @__PURE__ */ jsx(
878
- "div",
879
- {
880
- "data-testid": `${testId}-day-${dayKey(day2)}`,
881
- className: cn(
882
- "px-1 pt-1 text-[11px] border-r border-border/40",
883
- day2.getUTCDate() === 1 ? "text-foreground font-medium" : "text-muted-foreground/60"
884
- ),
885
- children: day2.getUTCDate()
886
- },
887
- dayKey(day2)
888
- )) }),
889
- /* @__PURE__ */ jsxs(
890
- "div",
891
- {
892
- className: "grid grid-cols-7 gap-y-0.5 px-0.5 pb-1 bg-muted/40",
893
- style: { gridAutoRows: "18px", minHeight: 62 },
894
- children: [
895
- segments.map((seg) => /* @__PURE__ */ jsx(
896
- "button",
897
- {
898
- type: "button",
899
- onClick: () => select(indexById.get(seg.item.id) ?? 0),
900
- title: `${formatSpan(seg.item.start, seg.item.end)} \u2014 ${seg.item.label}`,
901
- "data-testid": `${testId}-entry-${seg.item.id}`,
902
- style: {
903
- gridColumn: `${seg.startCol + 1} / span ${seg.span}`,
904
- gridRow: seg.lane + 1
905
- },
906
- className: cn(
907
- // One line per event (truncated), so several events stack
908
- // compactly on the same day instead of a few tall bars
909
- // pushing the rest into a "+n more". Every event is the
910
- // SAME neutral colour; the one open in the composer is
911
- // marked by the caller (a ring), not by a different fill.
912
- "block h-full w-full truncate text-left text-[10px] leading-[14px] py-[1px] px-1",
913
- "bg-muted text-muted-foreground",
914
- seg.isStart && "rounded-l",
915
- seg.isEnd && "rounded-r"
916
- ),
917
- children: seg.isStart ? seg.item.label : " "
918
- },
919
- `${seg.item.id}-${seg.startCol}`
920
- )),
921
- overflow > 0 && /* @__PURE__ */ jsxs(
922
- "span",
923
- {
924
- className: "text-[10px] text-muted-foreground px-1",
925
- style: { gridColumn: "1 / span 7", gridRow: maxLanes + 1 },
926
- children: [
927
- "+",
928
- overflow,
929
- " more"
930
- ]
931
- }
932
- )
933
- ]
934
- }
935
- )
936
- ] })
937
- ] }, dayKey(week[0]));
938
- }) })
939
- ] });
940
- }
941
- var TIMELINE_ZOOM = { MIN: 1, MAX: 10, STEP: 0.25 };
942
- function TimelineZoomControl({
943
- zoom,
944
- onZoomChange,
945
- className,
946
- testId = "timeline-gantt"
947
- }) {
948
- return /* @__PURE__ */ jsxs(
949
- "div",
950
- {
951
- className: cn(
952
- "flex items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1",
953
- className
954
- ),
955
- "data-testid": `${testId}-zoom`,
956
- children: [
957
- /* @__PURE__ */ jsx(ZoomOut, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true }),
958
- /* @__PURE__ */ jsx(
959
- "input",
960
- {
961
- type: "range",
962
- "aria-label": "Timeline zoom",
963
- "data-testid": `${testId}-zoom-slider`,
964
- min: TIMELINE_ZOOM.MIN,
965
- max: TIMELINE_ZOOM.MAX,
966
- step: TIMELINE_ZOOM.STEP,
967
- value: zoom,
968
- onChange: (e) => onZoomChange(Number(e.target.value)),
969
- className: "h-1 w-24 cursor-pointer accent-primary"
970
- }
971
- ),
972
- /* @__PURE__ */ jsx(ZoomIn, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true }),
973
- /* @__PURE__ */ jsxs("span", { className: "w-11 shrink-0 text-right text-[11px] tabular-nums text-muted-foreground", children: [
974
- Math.round(zoom * 100),
975
- "%"
976
- ] })
977
- ]
978
- }
979
- );
980
- }
981
- var NEUTRAL_BAR = "#94a3b8";
982
- function barBackground(colors) {
983
- const c = (colors ?? []).filter(Boolean).slice(0, 3);
984
- if (c.length === 0) return NEUTRAL_BAR;
985
- if (c.length === 1) return c[0];
986
- const step = 100 / c.length;
987
- const stops = c.map((col, i) => `${col} ${i * step}% ${(i + 1) * step}%`).join(", ");
988
- return `linear-gradient(180deg, ${stops})`;
989
- }
990
- var WEEK_MS = 7 * 24 * 60 * 60 * 1e3;
991
- function formatAxisDate(d, intervalDays) {
992
- if (intervalDays < 45) {
993
- return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
994
- }
995
- if (intervalDays < 365 * 2) {
996
- return d.toLocaleDateString("en-US", { month: "short", year: "numeric" });
997
- }
998
- return d.toLocaleDateString("en-US", { year: "numeric" });
999
- }
1000
- function TimelineGantt({
1001
- items,
1002
- onSelect,
1003
- selectedIds,
1004
- renderDetail,
1005
- labelWidth = 240,
1006
- onLabelWidthChange,
1007
- minLabelWidth = 120,
1008
- maxLabelWidth = 600,
1009
- zoom: zoomProp,
1010
- onZoomChange,
1011
- navigatorContainer,
1012
- navigatorTotal,
1013
- emptyMessage = "Nothing dated yet.",
1014
- className,
1015
- testId = "timeline-gantt"
1016
- }) {
1017
- const [activeIndex, setActiveIndex] = useState(null);
1018
- const [internalZoom, setInternalZoom] = useState(1);
1019
- const zoomControlled = zoomProp != null && onZoomChange != null;
1020
- const zoomValue = zoomControlled ? zoomProp : internalZoom;
1021
- const setZoomValue = zoomControlled ? onZoomChange : setInternalZoom;
1022
- const dragRef = useRef(null);
1023
- const chartRef = useRef(null);
1024
- const gutterBodyRef = useRef(null);
1025
- const startResize = (e) => {
1026
- if (!onLabelWidthChange) return;
1027
- e.preventDefault();
1028
- dragRef.current = { startX: e.clientX, startWidth: labelWidth };
1029
- const onMove = (ev) => {
1030
- const drag = dragRef.current;
1031
- if (!drag) return;
1032
- const next = Math.min(
1033
- maxLabelWidth,
1034
- Math.max(minLabelWidth, drag.startWidth + (ev.clientX - drag.startX))
1035
- );
1036
- onLabelWidthChange(next);
1037
- };
1038
- const onUp = () => {
1039
- dragRef.current = null;
1040
- window.removeEventListener("mousemove", onMove);
1041
- window.removeEventListener("mouseup", onUp);
1042
- };
1043
- window.addEventListener("mousemove", onMove);
1044
- window.addEventListener("mouseup", onUp);
1045
- };
1046
- const rows = items.filter((i) => parseIso2(i.start) !== null).slice().sort((a, b) => parseIso2(a.start).getTime() - parseIso2(b.start).getTime());
1047
- const select = (index) => {
1048
- setActiveIndex(index);
1049
- onSelect?.(index === null ? null : rows[index]);
1050
- };
1051
- const selectedSet = new Set(selectedIds ?? []);
1052
- const selectedRowIndex = rows.findIndex((r) => selectedSet.has(r.id));
1053
- const currentIndex = selectedRowIndex >= 0 ? selectedRowIndex : activeIndex;
1054
- const goTo = (index) => select(Math.max(0, Math.min(rows.length - 1, index)));
1055
- const navigator = /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5 text-sm font-light", "data-testid": `${testId}-nav`, children: [
1056
- /* @__PURE__ */ jsx(
1057
- "button",
1058
- {
1059
- type: "button",
1060
- "aria-label": "Previous event",
1061
- "data-testid": `${testId}-nav-prev`,
1062
- disabled: rows.length === 0 || currentIndex === null || currentIndex <= 0,
1063
- onClick: () => goTo((currentIndex ?? 0) - 1),
1064
- className: "rounded p-0.5 text-muted-foreground enabled:hover:bg-accent enabled:hover:text-foreground disabled:opacity-30",
1065
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
1066
- }
1067
- ),
1068
- /* @__PURE__ */ jsxs("span", { className: "tabular-nums text-muted-foreground", "data-testid": `${testId}-nav-position`, children: [
1069
- currentIndex !== null ? currentIndex + 1 : "\u2013",
1070
- " /",
1071
- " ",
1072
- navigatorTotal ?? (rows.length > 0 ? rows.length : "\u2013")
1073
- ] }),
1074
- /* @__PURE__ */ jsx(
1075
- "button",
1076
- {
1077
- type: "button",
1078
- "aria-label": "Next event",
1079
- "data-testid": `${testId}-nav-next`,
1080
- disabled: rows.length === 0 || currentIndex !== null && currentIndex >= rows.length - 1,
1081
- onClick: () => goTo(currentIndex === null ? 0 : currentIndex + 1),
1082
- className: "rounded p-0.5 text-muted-foreground enabled:hover:bg-accent enabled:hover:text-foreground disabled:opacity-30",
1083
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
1084
- }
1085
- )
1086
- ] });
1087
- if (rows.length === 0) {
1088
- return /* @__PURE__ */ jsxs(
1089
- "div",
1090
- {
1091
- "data-testid": `${testId}-empty-state`,
1092
- className: cn(
1093
- "flex flex-col items-center justify-center py-16 text-muted-foreground",
1094
- className
1095
- ),
1096
- children: [
1097
- /* @__PURE__ */ jsx(Calendar, { className: "w-12 h-12 mb-3 opacity-30" }),
1098
- /* @__PURE__ */ jsx("p", { className: "text-sm", children: emptyMessage }),
1099
- navigatorContainer && createPortal(navigator, navigatorContainer)
1100
- ]
1101
- }
1102
- );
1103
- }
1104
- const allDates = rows.flatMap((i) => {
1105
- const s = parseIso2(i.start);
1106
- return [s, parseIso2(i.end ?? null) ?? s];
1107
- });
1108
- const minTime = Math.min(...allDates.map((d) => d.getTime()));
1109
- const maxTime = Math.max(...allDates.map((d) => d.getTime()));
1110
- const pad = Math.max((maxTime - minTime) * 0.04, WEEK_MS);
1111
- const axisMin = new Date(minTime - pad);
1112
- const axisMax = new Date(maxTime + pad);
1113
- const axisRange = axisMax.getTime() - axisMin.getTime();
1114
- const toPercent = (d) => Math.min(100, Math.max(0, (d.getTime() - axisMin.getTime()) / axisRange * 100));
1115
- const tickCount = Math.max(2, Math.min(50, Math.round(8 * zoomValue) + 1));
1116
- const tickStep = axisRange / (tickCount - 1);
1117
- const tickIntervalDays = tickStep / DAY_MS;
1118
- const ticks = Array.from(
1119
- { length: tickCount },
1120
- (_, i) => new Date(axisMin.getTime() + tickStep * i)
1121
- );
1122
- const today = /* @__PURE__ */ new Date();
1123
- const todayPct = toPercent(today);
1124
- const showToday = today > axisMin && today < axisMax;
1125
- const activeItem = activeIndex !== null ? rows[activeIndex] : null;
1126
- const detail = activeItem ? renderDetail?.(activeItem) : null;
1127
- return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0", className), children: [
1128
- /* @__PURE__ */ jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col p-5", children: [
1129
- /* @__PURE__ */ jsx(
1130
- "div",
1131
- {
1132
- "aria-hidden": true,
1133
- "data-testid": `${testId}-gutter-divider`,
1134
- style: { left: `calc(20px + ${labelWidth}px)` },
1135
- className: "pointer-events-none absolute top-0 bottom-0 z-30 w-[3px] -translate-x-1/2 bg-border"
1136
- }
1137
- ),
1138
- onLabelWidthChange && /* @__PURE__ */ jsx(
1139
- "div",
1140
- {
1141
- role: "separator",
1142
- "aria-orientation": "vertical",
1143
- "aria-label": "Resize event column",
1144
- "data-testid": `${testId}-label-resizer`,
1145
- onMouseDown: startResize,
1146
- style: { left: `calc(20px + ${labelWidth}px)` },
1147
- className: "absolute top-0 bottom-0 z-30 w-2 -translate-x-1/2 cursor-col-resize group",
1148
- children: /* @__PURE__ */ jsx("div", { className: "mx-auto h-full w-[3px] transition-colors group-hover:bg-primary" })
1149
- }
1150
- ),
1151
- !zoomControlled && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 z-30 shadow-sm", children: /* @__PURE__ */ jsx(TimelineZoomControl, { zoom: zoomValue, onZoomChange: setZoomValue, testId }) }),
1152
- /* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-h-0 flex-1", children: [
1153
- /* @__PURE__ */ jsxs("div", { style: { width: labelWidth, flexShrink: 0 }, className: "flex min-h-0 flex-col", children: [
1154
- /* @__PURE__ */ jsxs("div", { className: "mb-1 flex h-6 shrink-0 items-center gap-1 border-b border-border pr-3 text-sm font-medium text-muted-foreground", children: [
1155
- /* @__PURE__ */ jsx("span", { children: "Event" }),
1156
- navigatorContainer === void 0 ? /* @__PURE__ */ jsx("span", { className: "ml-auto", children: navigator }) : navigatorContainer && createPortal(navigator, navigatorContainer)
1157
- ] }),
1158
- /* @__PURE__ */ jsx(
1159
- "div",
1160
- {
1161
- ref: gutterBodyRef,
1162
- "data-testid": `${testId}-gutter`,
1163
- className: "min-h-0 flex-1 overflow-hidden",
1164
- onWheel: (e) => {
1165
- if (chartRef.current) chartRef.current.scrollTop += e.deltaY;
1166
- },
1167
- children: /* @__PURE__ */ jsx("div", { className: "pt-4 pb-6", children: rows.map((item, i) => {
1168
- const isActive = activeIndex === i;
1169
- const isSelected = selectedIds?.includes(item.id) ?? false;
1170
- const highlighted = isActive || isSelected;
1171
- const zebra = i % 2 === 1;
1172
- return (
1173
- // Fixed h-9 = the track row's h-7 bar + py-1, so the two
1174
- // columns stay row-for-row aligned. Clicking the label
1175
- // selects the row exactly like its bar does — the label IS
1176
- // the event's title, so it should be a target too. Keep the
1177
- // `break-words leading-snug` tail on THIS element — a scoped
1178
- // CSS rule (.facts-gantt .break-words.leading-snug) clamps it
1179
- // to one line. A selected row gets the tint plus a left
1180
- // accent bar, mirroring the facts table's edited-row mark.
1181
- /* @__PURE__ */ jsx(
1182
- "div",
1183
- {
1184
- onClick: () => select(isActive ? null : i),
1185
- className: cn(
1186
- "flex h-9 cursor-pointer items-center rounded border-l-[3px] pr-3 text-xs font-medium",
1187
- isSelected ? "border-l-primary bg-primary/10" : zebra ? "border-l-transparent bg-muted" : "border-l-transparent bg-background",
1188
- highlighted ? "text-foreground" : "text-muted-foreground",
1189
- "break-words leading-snug"
1190
- ),
1191
- title: item.label,
1192
- children: /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate", children: [
1193
- /* @__PURE__ */ jsxs("span", { className: "mr-1 tabular-nums text-muted-foreground/60", children: [
1194
- i + 1,
1195
- "."
1196
- ] }),
1197
- item.label
1198
- ] })
1199
- },
1200
- item.id
1201
- )
1202
- );
1203
- }) })
1204
- }
1205
- )
1206
- ] }),
1207
- /* @__PURE__ */ jsx(
1208
- "div",
1209
- {
1210
- ref: chartRef,
1211
- "data-testid": `${testId}-scroller`,
1212
- onScroll: (e) => {
1213
- if (gutterBodyRef.current) gutterBodyRef.current.scrollTop = e.currentTarget.scrollTop;
1214
- },
1215
- className: cn(
1216
- "scrollbar-subtle relative min-h-0 min-w-0 flex-1 overflow-y-auto",
1217
- zoomValue > 1 ? "overflow-x-auto" : "overflow-x-hidden"
1218
- ),
1219
- children: /* @__PURE__ */ jsxs(
1220
- "div",
1221
- {
1222
- className: "relative min-h-full",
1223
- style: { width: `${zoomValue * 100}%`, minWidth: "100%" },
1224
- children: [
1225
- /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-20 mb-1 h-6 border-b border-border bg-background", children: ticks.map((tick, i) => {
1226
- const isFirst = i === 0;
1227
- const isLast = i === ticks.length - 1;
1228
- const edgeShift = isFirst ? "translate-x-1" : isLast ? "-translate-x-full" : "-translate-x-1/2";
1229
- return /* @__PURE__ */ jsx(
1230
- "span",
1231
- {
1232
- style: { left: `${toPercent(tick)}%` },
1233
- className: `absolute bottom-1 text-[10px] text-muted-foreground whitespace-nowrap select-none ${edgeShift}`,
1234
- children: formatAxisDate(tick, tickIntervalDays)
1235
- },
1236
- i
1237
- );
1238
- }) }),
1239
- /* @__PURE__ */ jsxs("div", { className: "relative pt-4", children: [
1240
- ticks.map((tick, i) => /* @__PURE__ */ jsx(
1241
- "div",
1242
- {
1243
- "aria-hidden": true,
1244
- className: "pointer-events-none absolute top-0 bottom-0 z-10 border-l-2 border-border/30",
1245
- style: { left: `${toPercent(tick)}%` }
1246
- },
1247
- `grid-${i}`
1248
- )),
1249
- showToday && /* @__PURE__ */ jsxs(
1250
- "div",
1251
- {
1252
- className: "pointer-events-none absolute top-0 bottom-0 z-10",
1253
- style: { left: `${todayPct}%` },
1254
- children: [
1255
- /* @__PURE__ */ jsx("div", { className: "h-full border-l-2 border-dashed border-muted-foreground/50" }),
1256
- /* @__PURE__ */ jsx("span", { className: "absolute top-0 -translate-x-1/2 rounded border bg-background px-1 text-[9px] text-muted-foreground", children: "today" })
1257
- ]
1258
- }
1259
- ),
1260
- rows.map((item, i) => {
1261
- const startDate = parseIso2(item.start);
1262
- const endDate = parseIso2(item.end ?? null) ?? startDate;
1263
- const leftPct = toPercent(startDate);
1264
- const dayPct = DAY_MS / axisRange * 100;
1265
- const widthPct = Math.max(dayPct, toPercent(endDate) - toPercent(startDate));
1266
- const isActive = activeIndex === i;
1267
- const isSelected = selectedIds?.includes(item.id) ?? false;
1268
- const highlighted = isActive || isSelected;
1269
- const zebra = i % 2 === 1;
1270
- return (
1271
- // Fixed h-9 (h-7 bar + py-1) — the gutter's label rows use
1272
- // the same height, which is what keeps the columns aligned.
1273
- /* @__PURE__ */ jsx("div", { className: "h-9 py-1", children: /* @__PURE__ */ jsx(
1274
- "div",
1275
- {
1276
- className: cn(
1277
- "relative h-7 overflow-visible rounded-md border border-border",
1278
- isSelected ? "bg-primary/10" : zebra ? "bg-muted" : "bg-background"
1279
- ),
1280
- children: /* @__PURE__ */ jsx(
1281
- "button",
1282
- {
1283
- "data-testid": `${testId}-bar-${i}`,
1284
- "aria-label": item.label,
1285
- "aria-pressed": highlighted,
1286
- style: {
1287
- left: `${leftPct}%`,
1288
- width: `${widthPct}%`,
1289
- // Colour-coded by the item's labels (up to three), not by
1290
- // row order — see barBackground / TimelineItem.colors.
1291
- background: barBackground(item.colors),
1292
- boxShadow: highlighted ? "0 0 0 2px white, 0 0 0 4px #6366f1" : "0 1px 3px rgba(0,0,0,.2)"
1293
- },
1294
- title: formatSpan(item.start, item.end) || void 0,
1295
- className: "absolute top-0.5 h-6 min-w-[6px] rounded cursor-pointer transition-[filter] hover:brightness-110 focus:outline-none",
1296
- onClick: () => select(isActive ? null : i)
1297
- }
1298
- )
1299
- }
1300
- ) }, item.id)
1301
- );
1302
- })
1303
- ] })
1304
- ]
1305
- }
1306
- )
1307
- }
1308
- )
1309
- ] })
1310
- ] }),
1311
- /* @__PURE__ */ jsx(
1312
- "div",
1313
- {
1314
- "data-testid": `${testId}-side-panel`,
1315
- className: cn(
1316
- "border-l bg-muted/20 flex flex-col shrink-0 overflow-hidden transition-all duration-300",
1317
- activeItem ? "w-60 open" : "w-0"
1318
- ),
1319
- children: /* @__PURE__ */ jsx(
1320
- "div",
1321
- {
1322
- className: cn(
1323
- "w-60 p-4 flex flex-col gap-3 transition-opacity duration-200",
1324
- activeItem ? "opacity-100" : "opacity-0"
1325
- ),
1326
- children: activeItem && /* @__PURE__ */ jsxs(Fragment, { children: [
1327
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
1328
- "button",
1329
- {
1330
- "data-testid": `${testId}-panel-close`,
1331
- className: "w-6 h-6 rounded flex items-center justify-center text-muted-foreground hover:bg-muted",
1332
- onClick: () => select(null),
1333
- "aria-label": "Close panel",
1334
- children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
1335
- }
1336
- ) }),
1337
- /* @__PURE__ */ jsxs("div", { children: [
1338
- /* @__PURE__ */ jsxs(
1339
- "div",
1340
- {
1341
- "data-testid": `${testId}-panel-title`,
1342
- className: "text-sm font-semibold text-foreground leading-snug",
1343
- children: [
1344
- activeIndex !== null && /* @__PURE__ */ jsxs("span", { className: "mr-1 tabular-nums text-muted-foreground", children: [
1345
- activeIndex + 1,
1346
- "."
1347
- ] }),
1348
- activeItem.label
1349
- ]
1350
- }
1351
- ),
1352
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 mt-1 text-xs text-muted-foreground", children: [
1353
- /* @__PURE__ */ jsx(Calendar, { className: "w-3 h-3 shrink-0" }),
1354
- /* @__PURE__ */ jsx("span", { children: formatSpan(activeItem.start, activeItem.end) || "Date unknown" })
1355
- ] })
1356
- ] }),
1357
- activeItem.description && /* @__PURE__ */ jsxs(Fragment, { children: [
1358
- /* @__PURE__ */ jsx("hr", { className: "border-border" }),
1359
- /* @__PURE__ */ jsxs("div", { children: [
1360
- /* @__PURE__ */ jsx("div", { className: "text-[10px] font-semibold uppercase tracking-wider text-muted-foreground mb-1", children: "Summary" }),
1361
- /* @__PURE__ */ jsx(
1362
- "p",
1363
- {
1364
- "data-testid": `${testId}-panel-desc`,
1365
- className: "text-xs text-muted-foreground leading-relaxed",
1366
- children: activeItem.description
1367
- }
1368
- )
1369
- ] })
1370
- ] }),
1371
- detail && /* @__PURE__ */ jsxs(Fragment, { children: [
1372
- /* @__PURE__ */ jsx("hr", { className: "border-border" }),
1373
- detail
1374
- ] })
1375
- ] })
1376
- }
1377
- )
1378
- }
1379
- )
1380
- ] });
1381
- }
1382
- var TOGGLE = [
1383
- { mode: "calendar", label: "Calendar", Icon: CalendarDays },
1384
- { mode: "gantt", label: "Gantt", Icon: GanttChartSquare }
1385
- ];
1386
- function Timeline({
1387
- items,
1388
- view,
1389
- defaultView = "calendar",
1390
- onSelect,
1391
- renderDetail,
1392
- emptyMessage,
1393
- className,
1394
- testId = "timeline"
1395
- }) {
1396
- const [picked, setPicked] = useState(defaultView);
1397
- const mode = view ?? picked;
1398
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full min-h-0", className), "data-testid": testId, children: [
1399
- !view && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 p-2 border-b border-border", children: TOGGLE.map(({ mode: m, label, Icon }) => /* @__PURE__ */ jsxs(
1400
- "button",
1401
- {
1402
- type: "button",
1403
- onClick: () => setPicked(m),
1404
- "aria-pressed": mode === m,
1405
- "data-testid": `${testId}-view-${m}`,
1406
- className: cn(
1407
- "flex items-center gap-1.5 rounded px-2 py-1 text-xs",
1408
- mode === m ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground"
1409
- ),
1410
- children: [
1411
- /* @__PURE__ */ jsx(Icon, { className: "w-3.5 h-3.5" }),
1412
- label
1413
- ]
1414
- },
1415
- m
1416
- )) }),
1417
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0", children: mode === "calendar" ? /* @__PURE__ */ jsx(
1418
- TimelineCalendar,
1419
- {
1420
- items,
1421
- onSelect,
1422
- testId: `${testId}-calendar`,
1423
- emptyState: /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center p-8 text-sm text-muted-foreground", children: emptyMessage ?? "Nothing dated yet." })
1424
- }
1425
- ) : /* @__PURE__ */ jsx(
1426
- TimelineGantt,
1427
- {
1428
- items,
1429
- onSelect: (item) => item && onSelect?.(item),
1430
- renderDetail,
1431
- emptyMessage,
1432
- testId: `${testId}-gantt`
1433
- }
1434
- ) })
1435
- ] });
1436
- }
1437
492
  function SectionHeading({
1438
493
  eyebrow,
1439
494
  title,
@@ -1509,7 +564,7 @@ var ASPECT = {
1509
564
  var ROUNDED = {
1510
565
  none: "rounded-none",
1511
566
  md: "rounded-md",
1512
- lg: "rounded-xl",
567
+ lg: "rounded-lg",
1513
568
  full: "rounded-full"
1514
569
  };
1515
570
  function BlockImage({
@@ -1571,18 +626,23 @@ var TONE_SURFACE = {
1571
626
  ink: "bg-foreground text-background"
1572
627
  };
1573
628
  function renderTitle(title, emphasis) {
1574
- if (!emphasis || !title.includes(emphasis)) return title;
629
+ if (typeof title !== "string" || !emphasis || !title.includes(emphasis)) return title;
1575
630
  const parts = title.split(emphasis);
1576
631
  return parts.map((part, i) => /* @__PURE__ */ jsxs("span", { children: [
1577
632
  part,
1578
633
  i < parts.length - 1 && /* @__PURE__ */ jsx("span", { className: "text-primary", children: emphasis })
1579
634
  ] }, i));
1580
635
  }
636
+ function renderLink(Link, href, children) {
637
+ return Link ? /* @__PURE__ */ jsx(Link, { href, children }) : /* @__PURE__ */ jsx("a", { href, children });
638
+ }
1581
639
  function Hero({
1582
640
  eyebrow,
1583
641
  title,
1584
642
  emphasis,
1585
643
  subtitle,
644
+ caption,
645
+ linkComponent: Link,
1586
646
  primaryCta,
1587
647
  secondaryCta,
1588
648
  align = "left",
@@ -1615,10 +675,14 @@ function Hero({
1615
675
  {
1616
676
  className: cn("mt-8 flex flex-col gap-3 sm:flex-row", centered && "sm:justify-center"),
1617
677
  children: [
1618
- primaryCta?.label && /* @__PURE__ */ jsx(Button, { asChild: true, size: "lg", children: /* @__PURE__ */ jsxs("a", { href: primaryCta.href || "#", children: [
1619
- primaryCta.label,
1620
- /* @__PURE__ */ jsx(ArrowRight, { className: "size-4" })
1621
- ] }) }),
678
+ primaryCta?.label && /* @__PURE__ */ jsx(Button, { asChild: true, size: "lg", children: renderLink(
679
+ Link,
680
+ primaryCta.href || "#",
681
+ /* @__PURE__ */ jsxs(Fragment, { children: [
682
+ primaryCta.label,
683
+ /* @__PURE__ */ jsx(ArrowRight, { className: "size-4" })
684
+ ] })
685
+ ) }),
1622
686
  secondaryCta?.label && /* @__PURE__ */ jsx(
1623
687
  Button,
1624
688
  {
@@ -1628,12 +692,13 @@ function Hero({
1628
692
  className: cn(
1629
693
  onDark && "border-background/35 bg-transparent text-background hover:bg-background/10 hover:text-background"
1630
694
  ),
1631
- children: /* @__PURE__ */ jsx("a", { href: secondaryCta.href || "#", children: secondaryCta.label })
695
+ children: renderLink(Link, secondaryCta.href || "#", secondaryCta.label)
1632
696
  }
1633
697
  )
1634
698
  ]
1635
699
  }
1636
- )
700
+ ),
701
+ caption && /* @__PURE__ */ jsx("div", { className: cn("mt-4 text-sm", subtle), children: caption })
1637
702
  ]
1638
703
  }
1639
704
  );
@@ -1764,7 +829,7 @@ function CTABanner({
1764
829
  "div",
1765
830
  {
1766
831
  className: cn(
1767
- "relative isolate overflow-hidden rounded-2xl px-8 py-14 text-center",
832
+ "relative isolate overflow-hidden rounded-lg px-8 py-14 text-center",
1768
833
  onImage ? "text-white" : TONE_SURFACE2[tone] ?? TONE_SURFACE2.default
1769
834
  ),
1770
835
  style: bgStyle,
@@ -1814,35 +879,6 @@ function FAQ({ items, testId }) {
1814
879
  function RichTextBlock({ content, testId }) {
1815
880
  return /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-3xl", "data-testid": testId, children: /* @__PURE__ */ jsx(AiMarkdown, { children: content ?? "" }) });
1816
881
  }
1817
- var STYLES = {
1818
- info: { wrap: "border-primary/30 bg-primary/5", icon: "text-primary", Icon: Info },
1819
- success: { wrap: "border-success/30 bg-success/10", icon: "text-success", Icon: CheckCircle2 },
1820
- warning: { wrap: "border-warning/40 bg-warning/10", icon: "text-warning", Icon: AlertTriangle },
1821
- danger: {
1822
- wrap: "border-destructive/30 bg-destructive/10",
1823
- icon: "text-destructive",
1824
- Icon: XCircle
1825
- }
1826
- };
1827
- function Callout({ variant = "info", title, body, testId }) {
1828
- const style = STYLES[variant] ?? STYLES.info;
1829
- const Icon = style.Icon;
1830
- return /* @__PURE__ */ jsxs(
1831
- "div",
1832
- {
1833
- className: cn("flex gap-3 rounded-lg border p-4 text-foreground", style.wrap),
1834
- "data-testid": testId,
1835
- role: "note",
1836
- children: [
1837
- /* @__PURE__ */ jsx(Icon, { className: cn("mt-0.5 size-5 shrink-0", style.icon), "aria-hidden": true }),
1838
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1839
- title && /* @__PURE__ */ jsx("p", { className: "font-semibold", children: title }),
1840
- body && /* @__PURE__ */ jsx("p", { className: "text-sm leading-relaxed text-muted-foreground", children: body })
1841
- ] })
1842
- ]
1843
- }
1844
- );
1845
- }
1846
882
  var SIZE = {
1847
883
  sm: "size-8 text-xs",
1848
884
  md: "size-10 text-sm",
@@ -1855,36 +891,87 @@ function AvatarBlock({ src, name = "", size = "md", testId }) {
1855
891
  /* @__PURE__ */ jsx(AvatarFallback, { className: "font-semibold", children: initials(name || "?") })
1856
892
  ] });
1857
893
  }
1858
- function Navbar({ brand, links, cta, testId }) {
1859
- return /* @__PURE__ */ jsx("header", { className: "border-b border-border bg-background", "data-testid": testId, children: /* @__PURE__ */ jsxs("nav", { className: "mx-auto flex max-w-7xl items-center justify-between gap-6 px-5 py-4 lg:px-8", children: [
1860
- /* @__PURE__ */ jsx("span", { className: "text-lg font-semibold tracking-tight", children: brand }),
1861
- /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-6 md:flex", children: (links ?? []).map((link, i) => /* @__PURE__ */ jsx(
1862
- "a",
894
+ var DEFAULT_LABELS = { openMenu: "Open menu", closeMenu: "Close menu" };
895
+ function Navbar({
896
+ brand,
897
+ brandHref,
898
+ links,
899
+ cta,
900
+ ctaSlot,
901
+ linkComponent: Link,
902
+ mobileMenu,
903
+ labels,
904
+ testId,
905
+ testIds
906
+ }) {
907
+ const [isOpen, setIsOpen] = useState(false);
908
+ const l = { ...DEFAULT_LABELS, ...labels };
909
+ const items = links ?? [];
910
+ const linkId = (i) => testIds?.link?.(i) ?? (testId ? `${testId}-link-${i}` : void 0);
911
+ const ctaId = testIds?.cta ?? (testId ? `${testId}-cta` : void 0);
912
+ const menuId = testIds?.menu ?? (testId ? `${testId}-menu` : void 0);
913
+ const menuButtonId = testIds?.menuButton ?? (testId ? `${testId}-menu-button` : void 0);
914
+ const anchor = (href, className, children, id) => Link ? /* @__PURE__ */ jsx(Link, { href, className, "data-testid": id, children }) : /* @__PURE__ */ jsx("a", { href, className, "data-testid": id, children });
915
+ const linkClass = "text-sm font-medium text-muted-foreground transition-colors hover:text-foreground";
916
+ const brandNode = /* @__PURE__ */ jsx("span", { className: "text-lg font-semibold tracking-tight", children: brand });
917
+ const ctaNode = ctaSlot ?? (cta?.label && /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", children: anchor(cta.href || "#", void 0, cta.label, ctaId) }));
918
+ return /* @__PURE__ */ jsxs("header", { className: "border-b border-border bg-background", "data-testid": testId, children: [
919
+ /* @__PURE__ */ jsxs("nav", { className: "mx-auto flex max-w-7xl items-center justify-between gap-6 px-5 py-4 lg:px-8", children: [
920
+ brandHref ? anchor(brandHref, void 0, brandNode) : brandNode,
921
+ /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-6 md:flex", children: items.map((link, i) => /* @__PURE__ */ jsx("span", { children: anchor(link.href || "#", linkClass, link.label, linkId(i)) }, i)) }),
922
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
923
+ /* @__PURE__ */ jsx("div", { className: "hidden md:block", children: ctaNode }),
924
+ /* @__PURE__ */ jsx(
925
+ "button",
926
+ {
927
+ type: "button",
928
+ className: "rounded-md p-2 text-foreground hover:bg-muted md:hidden",
929
+ "aria-expanded": isOpen,
930
+ "aria-label": isOpen ? l.closeMenu : l.openMenu,
931
+ onClick: () => setIsOpen((open) => !open),
932
+ "data-testid": menuButtonId,
933
+ children: isOpen ? /* @__PURE__ */ jsx(X, { className: "size-5" }) : /* @__PURE__ */ jsx(Menu, { className: "size-5" })
934
+ }
935
+ )
936
+ ] })
937
+ ] }),
938
+ isOpen && /* @__PURE__ */ jsx(
939
+ "div",
1863
940
  {
1864
- href: link.href || "#",
1865
- className: "text-sm font-medium text-muted-foreground transition-colors hover:text-foreground",
1866
- "data-testid": testId && `${testId}-link-${i}`,
1867
- children: link.label
1868
- },
1869
- i
1870
- )) }),
1871
- cta?.label && /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", children: /* @__PURE__ */ jsx("a", { href: cta.href || "#", children: cta.label }) })
1872
- ] }) });
941
+ className: "border-t border-border px-5 py-4 md:hidden",
942
+ "data-slot": "navbar-mobile-menu",
943
+ "data-testid": menuId,
944
+ children: mobileMenu ?? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
945
+ items.map((link, i) => /* @__PURE__ */ jsx("span", { children: anchor(link.href || "#", linkClass, link.label) }, i)),
946
+ ctaNode
947
+ ] })
948
+ }
949
+ )
950
+ ] });
1873
951
  }
1874
- function Footer({ columns, copyright, testId }) {
952
+ function Footer({
953
+ columns,
954
+ copyright,
955
+ brand,
956
+ blurb,
957
+ legal,
958
+ linkComponent: Link,
959
+ testId
960
+ }) {
961
+ const linkClass = "text-sm text-muted-foreground transition-colors hover:text-foreground";
1875
962
  return /* @__PURE__ */ jsx("footer", { className: "border-t border-border bg-muted text-foreground", "data-testid": testId, children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-7xl px-5 py-14 lg:px-8", children: [
963
+ (brand || blurb) && /* @__PURE__ */ jsxs("div", { className: "mb-10 max-w-md", "data-slot": "footer-brand", children: [
964
+ brand && /* @__PURE__ */ jsx("div", { className: "text-lg font-semibold tracking-tight", children: brand }),
965
+ blurb && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: blurb })
966
+ ] }),
1876
967
  /* @__PURE__ */ jsx("div", { className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-4", children: (columns ?? []).map((col, i) => /* @__PURE__ */ jsxs("div", { "data-testid": testId && `${testId}-col-${i}`, children: [
1877
968
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold tracking-tight", children: col.heading }),
1878
- /* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-2", children: (col.links ?? []).map((link, j) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1879
- "a",
1880
- {
1881
- href: link.href || "#",
1882
- className: "text-sm text-muted-foreground transition-colors hover:text-foreground",
1883
- children: link.label
1884
- }
1885
- ) }, j)) })
969
+ /* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-2", children: (col.links ?? []).map((link, j) => /* @__PURE__ */ jsx("li", { children: Link ? /* @__PURE__ */ jsx(Link, { href: link.href || "#", className: linkClass, children: link.label }) : /* @__PURE__ */ jsx("a", { href: link.href || "#", className: linkClass, children: link.label }) }, j)) })
1886
970
  ] }, i)) }),
1887
- copyright && /* @__PURE__ */ jsx("p", { className: "mt-12 border-t border-border pt-6 text-sm text-muted-foreground", children: copyright })
971
+ (copyright || legal) && /* @__PURE__ */ jsxs("div", { className: "mt-12 flex flex-col gap-3 border-t border-border pt-6 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between", children: [
972
+ copyright && /* @__PURE__ */ jsx("p", { children: copyright }),
973
+ legal && /* @__PURE__ */ jsx("div", { "data-slot": "footer-legal", children: legal })
974
+ ] })
1888
975
  ] }) });
1889
976
  }
1890
977
  function ListBlock({ ordered = false, items, testId }) {
@@ -1986,38 +1073,33 @@ function PricingTable({ plans, testId }) {
1986
1073
  );
1987
1074
  }
1988
1075
  function Tabs({ items, testId }) {
1989
- const [active, setActive] = useState(0);
1990
1076
  const list = items ?? [];
1991
- const current = list[Math.min(active, Math.max(list.length - 1, 0))];
1992
- return /* @__PURE__ */ jsxs("div", { "data-testid": testId, children: [
1993
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 border-b border-border", role: "tablist", children: list.map((t, i) => {
1994
- const selected = i === active;
1995
- return /* @__PURE__ */ jsx(
1996
- "button",
1997
- {
1998
- type: "button",
1999
- role: "tab",
2000
- "aria-selected": selected,
2001
- onClick: () => setActive(i),
2002
- className: cn(
2003
- "-mb-px border-b-2 px-4 py-2 text-sm font-medium transition-colors",
2004
- selected ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
2005
- ),
2006
- "data-testid": testId && `${testId}-tab-${i}`,
2007
- children: t.label
2008
- },
2009
- i
2010
- );
2011
- }) }),
2012
- current && /* @__PURE__ */ jsx(
2013
- "div",
1077
+ const [active, setActive] = useState("0");
1078
+ const activeIndex = Math.min(Number(active), Math.max(list.length - 1, 0));
1079
+ return /* @__PURE__ */ jsxs(TabsPrimitive.Root, { value: String(activeIndex), onValueChange: setActive, "data-testid": testId, children: [
1080
+ /* @__PURE__ */ jsx(TabsPrimitive.List, { className: "flex flex-wrap gap-1 border-b border-border", children: list.map((t, i) => /* @__PURE__ */ jsx(
1081
+ TabsPrimitive.Trigger,
2014
1082
  {
2015
- role: "tabpanel",
2016
- className: "pt-5 text-sm leading-relaxed text-muted-foreground",
2017
- "data-testid": testId && `${testId}-panel`,
2018
- children: current.content
2019
- }
2020
- )
1083
+ value: String(i),
1084
+ className: cn(
1085
+ "-mb-px border-b-2 px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
1086
+ i === activeIndex ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
1087
+ ),
1088
+ "data-testid": testId && `${testId}-tab-${i}`,
1089
+ children: t.label
1090
+ },
1091
+ i
1092
+ )) }),
1093
+ list.map((t, i) => /* @__PURE__ */ jsx(
1094
+ TabsPrimitive.Content,
1095
+ {
1096
+ value: String(i),
1097
+ className: "pt-5 text-sm leading-relaxed text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1098
+ "data-testid": i === activeIndex ? testId && `${testId}-panel` : void 0,
1099
+ children: t.content
1100
+ },
1101
+ i
1102
+ ))
2021
1103
  ] });
2022
1104
  }
2023
1105
  function Accordion({ items, allowMultiple = false, testId }) {
@@ -2124,28 +1206,52 @@ function VideoEmbed({
2124
1206
  }
2125
1207
  ) : url ? /* @__PURE__ */ jsx("video", { src: url, controls: true, className: "size-full", "data-testid": testId && `${testId}-video` }) : null });
2126
1208
  }
1209
+ var INPUT_CLASS = "w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground outline-none focus:border-primary";
2127
1210
  function ContactForm({
2128
1211
  fields,
2129
1212
  submitLabel = "Send",
2130
1213
  action,
1214
+ onSubmit,
2131
1215
  successMessage = "Thanks \u2014 we\u2019ll be in touch shortly.",
2132
- testId
1216
+ renderSuccess,
1217
+ testId,
1218
+ testIds
2133
1219
  }) {
2134
- const [sent, setSent] = useState(false);
1220
+ const [sentValues, setSentValues] = useState(null);
1221
+ const [isSending, setIsSending] = useState(false);
2135
1222
  const list = fields ?? [];
2136
- const onSubmit = (e) => {
2137
- if (!action) {
2138
- e.preventDefault();
2139
- setSent(true);
1223
+ const ids = {
1224
+ form: testIds?.form ?? testId,
1225
+ success: testIds?.success ?? (testId ? `${testId}-success` : void 0),
1226
+ submit: testIds?.submit ?? (testId ? `${testId}-submit` : void 0),
1227
+ field: (name) => testIds?.field?.(name) ?? (testId ? `${testId}-field-${name}` : void 0)
1228
+ };
1229
+ const handleSubmit = async (e) => {
1230
+ if (action && !onSubmit) return;
1231
+ e.preventDefault();
1232
+ const values = {};
1233
+ new FormData(e.currentTarget).forEach((v, k) => {
1234
+ if (typeof v === "string") values[k] = v;
1235
+ });
1236
+ if (onSubmit) {
1237
+ setIsSending(true);
1238
+ try {
1239
+ await onSubmit(values);
1240
+ } catch {
1241
+ return;
1242
+ } finally {
1243
+ setIsSending(false);
1244
+ }
2140
1245
  }
1246
+ setSentValues(values);
2141
1247
  };
2142
- if (sent) {
2143
- return /* @__PURE__ */ jsx(
1248
+ if (sentValues) {
1249
+ return renderSuccess ? /* @__PURE__ */ jsx("div", { "data-testid": ids.success, children: renderSuccess(sentValues) }) : /* @__PURE__ */ jsx(
2144
1250
  "p",
2145
1251
  {
2146
1252
  className: "rounded-lg border border-border bg-muted p-6 text-center text-sm text-foreground",
2147
1253
  role: "status",
2148
- "data-testid": testId && `${testId}-success`,
1254
+ "data-testid": ids.success,
2149
1255
  children: successMessage
2150
1256
  }
2151
1257
  );
@@ -2154,42 +1260,57 @@ function ContactForm({
2154
1260
  "form",
2155
1261
  {
2156
1262
  action,
2157
- method: action ? "post" : void 0,
2158
- onSubmit,
1263
+ method: action && !onSubmit ? "post" : void 0,
1264
+ onSubmit: handleSubmit,
2159
1265
  className: "mx-auto flex max-w-xl flex-col gap-4",
2160
- "data-testid": testId,
1266
+ "data-testid": ids.form,
2161
1267
  children: [
2162
- list.map((f, i) => {
2163
- const inputClass = "w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground outline-none focus:border-primary";
2164
- return /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1.5 text-left", children: [
2165
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: f.label }),
2166
- f.type === "textarea" ? /* @__PURE__ */ jsx(
2167
- "textarea",
2168
- {
2169
- name: f.name,
2170
- required: f.required,
2171
- rows: 4,
2172
- className: inputClass,
2173
- "data-testid": testId && `${testId}-field-${f.name}`
2174
- }
2175
- ) : /* @__PURE__ */ jsx(
2176
- "input",
2177
- {
2178
- name: f.name,
2179
- type: f.type || "text",
2180
- required: f.required,
2181
- className: inputClass,
2182
- "data-testid": testId && `${testId}-field-${f.name}`
2183
- }
2184
- )
2185
- ] }, i);
2186
- }),
1268
+ list.map((f, i) => /* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1.5 text-left", children: [
1269
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: f.label }),
1270
+ f.type === "textarea" ? /* @__PURE__ */ jsx(
1271
+ "textarea",
1272
+ {
1273
+ name: f.name,
1274
+ required: f.required,
1275
+ rows: 4,
1276
+ defaultValue: f.defaultValue,
1277
+ placeholder: f.placeholder,
1278
+ className: INPUT_CLASS,
1279
+ "data-testid": ids.field(f.name)
1280
+ }
1281
+ ) : f.type === "select" ? /* @__PURE__ */ jsxs(
1282
+ "select",
1283
+ {
1284
+ name: f.name,
1285
+ required: f.required,
1286
+ defaultValue: f.defaultValue ?? "",
1287
+ className: INPUT_CLASS,
1288
+ "data-testid": ids.field(f.name),
1289
+ children: [
1290
+ /* @__PURE__ */ jsx("option", { value: "", disabled: f.required, children: f.placeholder ?? "" }),
1291
+ (f.options ?? []).map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
1292
+ ]
1293
+ }
1294
+ ) : /* @__PURE__ */ jsx(
1295
+ "input",
1296
+ {
1297
+ name: f.name,
1298
+ type: f.type || "text",
1299
+ required: f.required,
1300
+ defaultValue: f.defaultValue,
1301
+ placeholder: f.placeholder,
1302
+ className: INPUT_CLASS,
1303
+ "data-testid": ids.field(f.name)
1304
+ }
1305
+ )
1306
+ ] }, i)),
2187
1307
  /* @__PURE__ */ jsx(
2188
1308
  Button,
2189
1309
  {
2190
1310
  type: "submit",
2191
1311
  className: cn("mt-1 self-start"),
2192
- "data-testid": testId && `${testId}-submit`,
1312
+ disabled: isSending,
1313
+ "data-testid": ids.submit,
2193
1314
  children: submitLabel
2194
1315
  }
2195
1316
  )
@@ -2341,6 +1462,6 @@ function TestimonialGrid({ items, columns = "3", testId }) {
2341
1462
  )) });
2342
1463
  }
2343
1464
 
2344
- export { ASSET_REF_PREFIX, Accordion, AssetResolverProvider, AvatarBlock, Banner, BlockImage, BlockLink, CTABanner, Callout, Columns, ContactForm, Container, FAQ, FONT_PAIRINGS, FeatureGrid, Footer, Gallery, Hero, ListBlock, LogoCloud, MediaText, Navbar, PricingTable, RichTextBlock, SectionHeading, Spacer, Steps, THEME_STYLE_ID, TIMELINE_ZOOM, Tabs, TeamGrid, Testimonial, TestimonialGrid, ThemeEditor, Timeline, TimelineCalendar, TimelineGantt, TimelineZoomControl, VideoEmbed, applyFontVars, applyStoredTheme, applyThemeVars, asAssetRef, assetRefId, clearFontVars, clearThemeVars, createThemeStore, dayKey, daysUntil, fmtDate, fmtDateTime, fontPackages, formatPageRefs, formatSpan, fromNow, gbp, getFontPairing, hrs, initials, isAssetRef, matchFontPairing, monthLabel, parseIso2 as parseIso, pct, tid, toEmbedUrl, toHslTriplet, useAssetRenderer, useAssetResolverActive, utcDay };
2345
- //# sourceMappingURL=chunk-FZ2S6VAZ.js.map
2346
- //# sourceMappingURL=chunk-FZ2S6VAZ.js.map
1465
+ export { ASSET_REF_PREFIX, Accordion, AssetResolverProvider, AvatarBlock, Banner, BlockImage, BlockLink, CTABanner, Columns, ContactForm, Container, FAQ, FONT_PAIRINGS, FeatureGrid, Footer, Gallery, Hero, ListBlock, LogoCloud, MediaText, Navbar, PricingTable, RichTextBlock, SectionHeading, Spacer, Steps, THEME_STYLE_ID, Tabs, TeamGrid, Testimonial, TestimonialGrid, ThemeEditor, VideoEmbed, applyFontVars, applyStoredTheme, applyThemeVars, asAssetRef, assetRefId, clearFontVars, clearThemeVars, createThemeStore, fontPackages, getFontPairing, isAssetRef, matchFontPairing, tid, toEmbedUrl, toHslTriplet, useAssetRenderer, useAssetResolverActive };
1466
+ //# sourceMappingURL=chunk-RBXZYNVB.js.map
1467
+ //# sourceMappingURL=chunk-RBXZYNVB.js.map