@drawnagency/primitives 0.1.113 → 0.1.114

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 (483) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/cookies.d.ts +39 -0
  3. package/dist/auth/cookies.d.ts.map +1 -1
  4. package/dist/auth/index.js +3 -3
  5. package/dist/{chunk-GPPVYLEI.js → chunk-45FA7Z55.js} +1 -1
  6. package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
  7. package/dist/chunk-5GFACGSN.js +6 -0
  8. package/dist/chunk-5KSAS4VY.js +275 -0
  9. package/dist/{chunk-Z7W3DQTR.js → chunk-7SAAJVDE.js} +408 -28
  10. package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
  11. package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
  12. package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
  13. package/dist/chunk-DIMDRBFK.js +11 -0
  14. package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
  15. package/dist/{chunk-NHN2LSIU.js → chunk-IP2SEBAJ.js} +5 -1
  16. package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
  17. package/dist/chunk-JR24U7FJ.js +120 -0
  18. package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
  19. package/dist/{chunk-KR2MHTNJ.js → chunk-N3G7DOU3.js} +609 -61
  20. package/dist/chunk-OAGJBCSH.js +67 -0
  21. package/dist/{chunk-6BZ2KNTP.js → chunk-PLANHXS7.js} +191 -61
  22. package/dist/{chunk-VWWY5TL5.js → chunk-PNSCDBU7.js} +38 -56
  23. package/dist/{chunk-AHALSCQH.js → chunk-PTY2RG2K.js} +1 -1
  24. package/dist/{chunk-BDFTMGCL.js → chunk-PZPGJZRG.js} +9 -8
  25. package/dist/{chunk-FRE2CCLV.js → chunk-QHMKIODQ.js} +17 -4
  26. package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
  27. package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
  28. package/dist/chunk-VUYCRBJK.js +174 -0
  29. package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
  30. package/dist/{chunk-DS4GCYV2.js → chunk-Y5QECJX7.js} +223 -16
  31. package/dist/collab/rebase.d.ts +2 -1
  32. package/dist/collab/rebase.d.ts.map +1 -1
  33. package/dist/collab/rebase.js +20 -5
  34. package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
  35. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  36. package/dist/components/chat/ChatWidget.d.ts.map +1 -1
  37. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  38. package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
  39. package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
  40. package/dist/components/editor/DragHandle.d.ts +12 -2
  41. package/dist/components/editor/DragHandle.d.ts.map +1 -1
  42. package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
  43. package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
  44. package/dist/components/editor/NavGroupRow.d.ts +4 -1
  45. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  46. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  47. package/dist/components/editor/SectionWrapper.d.ts +1 -1
  48. package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
  49. package/dist/components/editor/SettingsForm.d.ts.map +1 -1
  50. package/dist/components/editor/TagIndicator.d.ts +15 -0
  51. package/dist/components/editor/TagIndicator.d.ts.map +1 -0
  52. package/dist/components/editor/index.js +148 -77
  53. package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
  54. package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
  55. package/dist/components/primitives/EditableList.d.ts.map +1 -1
  56. package/dist/components/primitives/HeadingSection.d.ts +4 -1
  57. package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
  58. package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
  59. package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
  60. package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
  61. package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
  62. package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
  63. package/dist/components/primitives/grid-drop.d.ts.map +1 -0
  64. package/dist/components/primitives/index.d.ts +1 -1
  65. package/dist/components/primitives/index.d.ts.map +1 -1
  66. package/dist/components/primitives/index.js +17 -154
  67. package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
  68. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
  69. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
  70. package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
  71. package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
  72. package/dist/components/sections/IconList/IconList.d.ts +2 -1
  73. package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
  74. package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
  75. package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
  76. package/dist/components/sections/IconList/index.d.ts +1 -0
  77. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  78. package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
  79. package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
  80. package/dist/components/sections/Media/index.d.ts +8 -0
  81. package/dist/components/sections/Media/index.d.ts.map +1 -1
  82. package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
  83. package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
  84. package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
  85. package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
  86. package/dist/components/sections/Reference/index.d.ts +9 -0
  87. package/dist/components/sections/Reference/index.d.ts.map +1 -0
  88. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
  89. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
  90. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
  91. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
  92. package/dist/components/sections/SectionSummary/index.d.ts +33 -0
  93. package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
  94. package/dist/components/sections/all-sections.d.ts +53 -0
  95. package/dist/components/sections/all-sections.d.ts.map +1 -1
  96. package/dist/components/sections/brand-guide.d.ts +41 -2
  97. package/dist/components/sections/brand-guide.d.ts.map +1 -1
  98. package/dist/components/sections/brand-guide.js +12 -10
  99. package/dist/components/sections/core-sections.d.ts +14 -0
  100. package/dist/components/sections/core-sections.d.ts.map +1 -1
  101. package/dist/components/sections/register-schemas.js +19 -17
  102. package/dist/components/sections/register.js +19 -17
  103. package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
  104. package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
  105. package/dist/components/shared/Button.d.ts +11 -3
  106. package/dist/components/shared/Button.d.ts.map +1 -1
  107. package/dist/components/shared/Checkbox.d.ts +6 -0
  108. package/dist/components/shared/Checkbox.d.ts.map +1 -1
  109. package/dist/components/shared/ConfirmDialog.d.ts +25 -0
  110. package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
  111. package/dist/components/shared/ConfirmInline.d.ts +25 -0
  112. package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
  113. package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
  114. package/dist/components/shared/Fab.d.ts +11 -2
  115. package/dist/components/shared/Fab.d.ts.map +1 -1
  116. package/dist/components/shared/FabStack.d.ts +22 -0
  117. package/dist/components/shared/FabStack.d.ts.map +1 -0
  118. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  119. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  120. package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
  121. package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
  122. package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
  123. package/dist/components/shared/InlineAlert.d.ts.map +1 -0
  124. package/dist/components/shared/Input.d.ts +10 -0
  125. package/dist/components/shared/Input.d.ts.map +1 -1
  126. package/dist/components/shared/Navigation.d.ts.map +1 -1
  127. package/dist/components/shared/Notice.d.ts +10 -0
  128. package/dist/components/shared/Notice.d.ts.map +1 -0
  129. package/dist/components/shared/Popover.d.ts.map +1 -1
  130. package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
  131. package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
  132. package/dist/components/shared/Select.d.ts +3 -2
  133. package/dist/components/shared/Select.d.ts.map +1 -1
  134. package/dist/components/shared/SplitButton.d.ts.map +1 -1
  135. package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
  136. package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
  137. package/dist/components/shared/Textarea.d.ts +7 -0
  138. package/dist/components/shared/Textarea.d.ts.map +1 -1
  139. package/dist/components/shared/ToolbarFrame.d.ts +17 -0
  140. package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
  141. package/dist/components/shared/copy.d.ts +13 -0
  142. package/dist/components/shared/copy.d.ts.map +1 -0
  143. package/dist/components/shared/icons.d.ts +0 -12
  144. package/dist/components/shared/icons.d.ts.map +1 -1
  145. package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
  146. package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
  147. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  148. package/dist/components/shell/BugReportFAB.d.ts +7 -1
  149. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  150. package/dist/components/shell/CredentialList.d.ts.map +1 -1
  151. package/dist/components/shell/DocInspector.d.ts.map +1 -1
  152. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
  153. package/dist/components/shell/EditorContext.d.ts +4 -0
  154. package/dist/components/shell/EditorContext.d.ts.map +1 -1
  155. package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
  156. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  157. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  158. package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
  159. package/dist/components/shell/MediaFolderTile.d.ts +4 -1
  160. package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
  161. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  162. package/dist/components/shell/RestoreModal.d.ts.map +1 -1
  163. package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
  164. package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
  165. package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
  166. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  167. package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
  168. package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
  169. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  170. package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
  171. package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
  172. package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
  173. package/dist/components/shell/reference-sources.d.ts +22 -0
  174. package/dist/components/shell/reference-sources.d.ts.map +1 -0
  175. package/dist/deck/index.d.ts +2 -2
  176. package/dist/deck/index.d.ts.map +1 -1
  177. package/dist/deck/index.js +1 -3
  178. package/dist/deck-builder/index.js +11 -18
  179. package/dist/document/index.d.ts +2 -2
  180. package/dist/document/index.d.ts.map +1 -1
  181. package/dist/hooks/useBlockDnd.d.ts +11 -0
  182. package/dist/hooks/useBlockDnd.d.ts.map +1 -1
  183. package/dist/hooks/useBuildStatus.d.ts +1 -1
  184. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  185. package/dist/hooks/useDocumentUploads.d.ts +1 -1
  186. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  187. package/dist/hooks/useEditorPersistence.d.ts +5 -1
  188. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  189. package/dist/hooks/useEditorPublish.d.ts +2 -2
  190. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  191. package/dist/hooks/useNotice.d.ts +19 -0
  192. package/dist/hooks/useNotice.d.ts.map +1 -0
  193. package/dist/hooks/useSortableNavRow.d.ts +11 -0
  194. package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
  195. package/dist/hooks/useSortableRow.d.ts +11 -0
  196. package/dist/hooks/useSortableRow.d.ts.map +1 -1
  197. package/dist/hooks/useStackedEscape.d.ts +32 -0
  198. package/dist/hooks/useStackedEscape.d.ts.map +1 -0
  199. package/dist/index.js +67 -49
  200. package/dist/lib/audience-secret.js +2 -2
  201. package/dist/lib/block-dnd.d.ts +5 -0
  202. package/dist/lib/block-dnd.d.ts.map +1 -1
  203. package/dist/lib/block-move.d.ts.map +1 -1
  204. package/dist/lib/brand-swatches.d.ts +12 -0
  205. package/dist/lib/brand-swatches.d.ts.map +1 -0
  206. package/dist/lib/container-ops.d.ts +3 -2
  207. package/dist/lib/container-ops.d.ts.map +1 -1
  208. package/dist/lib/dexie.d.ts.map +1 -1
  209. package/dist/lib/dexie.js +9 -1
  210. package/dist/lib/env.d.ts +4 -0
  211. package/dist/lib/env.d.ts.map +1 -1
  212. package/dist/lib/env.js +5 -3
  213. package/dist/lib/events.d.ts +1 -2
  214. package/dist/lib/events.d.ts.map +1 -1
  215. package/dist/lib/image-background.d.ts +8 -0
  216. package/dist/lib/image-background.d.ts.map +1 -0
  217. package/dist/lib/index-ops.js +3 -3
  218. package/dist/lib/index.d.ts +6 -4
  219. package/dist/lib/index.d.ts.map +1 -1
  220. package/dist/lib/index.js +29 -21
  221. package/dist/lib/loader.d.ts +21 -7
  222. package/dist/lib/loader.d.ts.map +1 -1
  223. package/dist/lib/nav-tree.d.ts +1 -0
  224. package/dist/lib/nav-tree.d.ts.map +1 -1
  225. package/dist/lib/nav.d.ts +38 -0
  226. package/dist/lib/nav.d.ts.map +1 -1
  227. package/dist/lib/platform-broker.d.ts +4 -2
  228. package/dist/lib/platform-broker.d.ts.map +1 -1
  229. package/dist/lib/platform-broker.js +21 -13
  230. package/dist/lib/reference-type.d.ts +2 -0
  231. package/dist/lib/reference-type.d.ts.map +1 -0
  232. package/dist/lib/reference-validation.d.ts +31 -0
  233. package/dist/lib/reference-validation.d.ts.map +1 -0
  234. package/dist/lib/reference-validation.js +39 -0
  235. package/dist/lib/references.d.ts +74 -0
  236. package/dist/lib/references.d.ts.map +1 -0
  237. package/dist/lib/registry.d.ts +35 -0
  238. package/dist/lib/registry.d.ts.map +1 -1
  239. package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
  240. package/dist/lib/safe-redirect.d.ts.map +1 -0
  241. package/dist/lib/tags.d.ts +58 -0
  242. package/dist/lib/tags.d.ts.map +1 -0
  243. package/dist/lib/theme-vars.d.ts +9 -0
  244. package/dist/lib/theme-vars.d.ts.map +1 -1
  245. package/dist/media/index.d.ts +1 -1
  246. package/dist/media/index.d.ts.map +1 -1
  247. package/dist/media/index.js +8 -4
  248. package/dist/media/utils.d.ts +2 -0
  249. package/dist/media/utils.d.ts.map +1 -1
  250. package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
  251. package/dist/media/video-poster.d.ts.map +1 -0
  252. package/dist/schemas/audience.js +2 -2
  253. package/dist/schemas/index.d.ts +1 -0
  254. package/dist/schemas/index.d.ts.map +1 -1
  255. package/dist/schemas/index.js +14 -8
  256. package/dist/schemas/shared.d.ts +26 -0
  257. package/dist/schemas/shared.d.ts.map +1 -1
  258. package/dist/schemas/site-config.d.ts +6 -0
  259. package/dist/schemas/site-config.d.ts.map +1 -1
  260. package/dist/schemas/tags.d.ts +27 -0
  261. package/dist/schemas/tags.d.ts.map +1 -0
  262. package/dist/storage/index.js +1 -1
  263. package/dist/types/database.d.ts.map +1 -1
  264. package/package.json +6 -1
  265. package/src/auth/cookies.ts +111 -0
  266. package/src/collab/rebase.ts +26 -2
  267. package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
  268. package/src/components/brandguide/ColorsEditable.tsx +1 -0
  269. package/src/components/chat/ChatPanel.tsx +2 -3
  270. package/src/components/chat/ChatWidget.tsx +2 -3
  271. package/src/components/docfile/DocFilePane.tsx +4 -12
  272. package/src/components/editor/ChildBlockWrapper.tsx +13 -19
  273. package/src/components/editor/ConflictDialog.tsx +27 -35
  274. package/src/components/editor/DeleteButton.tsx +2 -2
  275. package/src/components/editor/DragHandle.tsx +16 -3
  276. package/src/components/editor/DropEdgeIndicator.tsx +36 -10
  277. package/src/components/editor/InsertButton.tsx +2 -2
  278. package/src/components/editor/NavGroupRow.tsx +43 -14
  279. package/src/components/editor/PagesModal.tsx +99 -26
  280. package/src/components/editor/SectionWrapper.tsx +64 -23
  281. package/src/components/editor/SettingsButton.tsx +2 -2
  282. package/src/components/editor/SettingsForm.tsx +19 -2
  283. package/src/components/editor/StatusIndicator.tsx +4 -4
  284. package/src/components/editor/TagIndicator.tsx +80 -0
  285. package/src/components/primitives/DocumentDropZone.tsx +1 -1
  286. package/src/components/primitives/EditableGrid.tsx +15 -14
  287. package/src/components/primitives/EditableList.tsx +27 -74
  288. package/src/components/primitives/HeadingSection.tsx +5 -2
  289. package/src/components/primitives/ResolvedMedia.tsx +13 -0
  290. package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
  291. package/src/components/primitives/index.ts +1 -1
  292. package/src/components/primitives/useEditablePlainText.ts +5 -5
  293. package/src/components/sections/Button/CTAButton.tsx +3 -1
  294. package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
  295. package/src/components/sections/DoDontMedia/index.tsx +12 -3
  296. package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
  297. package/src/components/sections/IconList/IconList.tsx +70 -37
  298. package/src/components/sections/IconList/IconListSettings.tsx +55 -17
  299. package/src/components/sections/IconList/index.tsx +10 -3
  300. package/src/components/sections/LinkHeading/index.tsx +1 -1
  301. package/src/components/sections/Media/MediaBlock.tsx +13 -2
  302. package/src/components/sections/Media/index.tsx +12 -4
  303. package/src/components/sections/Reference/ReferenceList.tsx +214 -0
  304. package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
  305. package/src/components/sections/Reference/index.tsx +47 -0
  306. package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
  307. package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
  308. package/src/components/sections/SectionSummary/index.tsx +149 -0
  309. package/src/components/sections/SubHeading/index.tsx +1 -1
  310. package/src/components/sections/SubSubHeading/index.tsx +1 -1
  311. package/src/components/sections/brand-guide.ts +4 -3
  312. package/src/components/sections/core-sections.ts +2 -0
  313. package/src/components/shared/BrandSwatchesContext.ts +13 -0
  314. package/src/components/shared/Button.tsx +47 -34
  315. package/src/components/shared/Checkbox.tsx +21 -12
  316. package/src/components/shared/ConfirmDialog.tsx +87 -0
  317. package/src/components/shared/ConfirmInline.tsx +90 -0
  318. package/src/components/shared/ErrorBoundary.tsx +6 -18
  319. package/src/components/shared/Fab.tsx +15 -5
  320. package/src/components/shared/FabStack.tsx +28 -0
  321. package/src/components/shared/HistoryChangesModal.tsx +43 -41
  322. package/src/components/shared/HistoryPopover.tsx +7 -20
  323. package/src/components/shared/ImageBackgroundField.tsx +92 -0
  324. package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
  325. package/src/components/shared/Input.tsx +23 -7
  326. package/src/components/shared/Navigation.tsx +22 -17
  327. package/src/components/shared/Notice.tsx +59 -0
  328. package/src/components/shared/Popover.tsx +7 -11
  329. package/src/components/shared/ReferenceSourcesContext.ts +27 -0
  330. package/src/components/shared/Select.tsx +5 -2
  331. package/src/components/shared/SplitButton.tsx +11 -17
  332. package/src/components/shared/SummaryAnchorsContext.ts +11 -0
  333. package/src/components/shared/Textarea.tsx +17 -2
  334. package/src/components/shared/ToolbarFrame.tsx +28 -0
  335. package/src/components/shared/VideoSourceField.tsx +1 -1
  336. package/src/components/shared/copy.ts +18 -0
  337. package/src/components/shared/icons.tsx +1 -17
  338. package/src/components/shell/AudienceAddForm.tsx +2 -2
  339. package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
  340. package/src/components/shell/AudienceRow.tsx +22 -15
  341. package/src/components/shell/BugReportFAB.tsx +50 -40
  342. package/src/components/shell/CredentialList.tsx +33 -13
  343. package/src/components/shell/DocInspector.tsx +3 -12
  344. package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
  345. package/src/components/shell/EditorContext.tsx +7 -0
  346. package/src/components/shell/EditorLoginForm.tsx +26 -36
  347. package/src/components/shell/EditorModal.tsx +8 -10
  348. package/src/components/shell/EditorShell.tsx +499 -339
  349. package/src/components/shell/HistoryToolbar.tsx +24 -26
  350. package/src/components/shell/MediaFolderTile.tsx +8 -3
  351. package/src/components/shell/MediaLibraryModal.tsx +59 -60
  352. package/src/components/shell/ProcessingIndicator.tsx +2 -2
  353. package/src/components/shell/RestoreModal.tsx +17 -16
  354. package/src/components/shell/SetPasswordForm.tsx +3 -3
  355. package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
  356. package/src/components/shell/SiteSettingsDisplay.tsx +10 -20
  357. package/src/components/shell/SiteSettingsModal.tsx +24 -2
  358. package/src/components/shell/SiteSettingsTags.tsx +143 -0
  359. package/src/components/shell/SiteSettingsUsers.tsx +36 -26
  360. package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
  361. package/src/components/shell/ViewerLoginForm.tsx +5 -4
  362. package/src/components/shell/reference-sources.ts +36 -0
  363. package/src/deck/index.ts +2 -2
  364. package/src/document/index.ts +2 -2
  365. package/src/hooks/useBlockDnd.ts +11 -0
  366. package/src/hooks/useBuildStatus.ts +53 -6
  367. package/src/hooks/useDocumentUploads.ts +1 -1
  368. package/src/hooks/useEditorPersistence.ts +141 -35
  369. package/src/hooks/useEditorPublish.ts +18 -27
  370. package/src/hooks/useMediaPipeline.ts +1 -1
  371. package/src/hooks/useNotice.ts +45 -0
  372. package/src/hooks/useSortableNavRow.ts +11 -0
  373. package/src/hooks/useSortableRow.ts +22 -2
  374. package/src/hooks/useStackedEscape.ts +62 -0
  375. package/src/lib/block-dnd.ts +6 -1
  376. package/src/lib/block-move.ts +3 -0
  377. package/src/lib/brand-swatches.ts +32 -0
  378. package/src/lib/container-ops.ts +5 -3
  379. package/src/lib/dexie.ts +15 -1
  380. package/src/lib/env.ts +9 -0
  381. package/src/lib/events.ts +1 -2
  382. package/src/lib/image-background.ts +31 -0
  383. package/src/lib/index.ts +5 -4
  384. package/src/lib/loader.ts +54 -55
  385. package/src/lib/nav-tree.ts +71 -0
  386. package/src/lib/nav.ts +196 -36
  387. package/src/lib/platform-broker.ts +32 -14
  388. package/src/lib/reference-type.ts +3 -0
  389. package/src/lib/reference-validation.ts +69 -0
  390. package/src/lib/references.ts +130 -0
  391. package/src/lib/registry.ts +37 -0
  392. package/src/lib/tags.ts +148 -0
  393. package/src/lib/theme-vars.ts +23 -0
  394. package/src/media/index.ts +1 -1
  395. package/src/media/utils.ts +18 -0
  396. package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
  397. package/src/schemas/index.ts +1 -0
  398. package/src/schemas/shared.ts +24 -1
  399. package/src/schemas/site-config.ts +6 -1
  400. package/src/schemas/tags.ts +33 -0
  401. package/src/storage/types.ts +1 -1
  402. package/src/types/database.ts +2 -0
  403. package/dist/chunk-DNY72JZN.js +0 -86
  404. package/dist/chunk-F2LYQPXV.js +0 -77
  405. package/dist/chunk-JH762VUH.js +0 -128
  406. package/dist/chunk-K7DYZXVU.js +0 -138
  407. package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
  408. package/dist/components/primitives/gridDrop.d.ts.map +0 -1
  409. package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
  410. package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
  411. package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
  412. package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
  413. package/dist/hooks/index.d.ts +0 -9
  414. package/dist/hooks/index.d.ts.map +0 -1
  415. package/dist/lib/grid.d.ts +0 -2
  416. package/dist/lib/grid.d.ts.map +0 -1
  417. package/dist/lib/safeRedirect.d.ts.map +0 -1
  418. package/dist/media/videoPoster.d.ts.map +0 -1
  419. package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
  420. package/src/components/brandguide/Colors.d.ts.map +0 -1
  421. package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
  422. package/src/components/primitives/EditableGrid.d.ts.map +0 -1
  423. package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
  424. package/src/components/primitives/EditableRichText.d.ts.map +0 -1
  425. package/src/components/primitives/HeadingSection.d.ts.map +0 -1
  426. package/src/components/primitives/IconPicker.d.ts.map +0 -1
  427. package/src/components/primitives/LinkPopover.d.ts.map +0 -1
  428. package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
  429. package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
  430. package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
  431. package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
  432. package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
  433. package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
  434. package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
  435. package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
  436. package/src/components/sections/Button/index.d.ts.map +0 -1
  437. package/src/components/sections/Colors/index.d.ts.map +0 -1
  438. package/src/components/sections/IconList/IconList.d.ts.map +0 -1
  439. package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
  440. package/src/components/sections/IconList/index.d.ts.map +0 -1
  441. package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
  442. package/src/components/sections/Prose/Prose.d.ts.map +0 -1
  443. package/src/components/sections/Prose/index.d.ts.map +0 -1
  444. package/src/components/sections/SubHeading/index.d.ts.map +0 -1
  445. package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
  446. package/src/components/sections/register-schemas.d.ts.map +0 -1
  447. package/src/components/shared/Button.d.ts.map +0 -1
  448. package/src/components/shared/Checkbox.d.ts.map +0 -1
  449. package/src/components/shared/FormLabel.d.ts.map +0 -1
  450. package/src/components/shared/IconButton.d.ts.map +0 -1
  451. package/src/components/shared/Input.d.ts.map +0 -1
  452. package/src/components/shared/Select.d.ts.map +0 -1
  453. package/src/components/shared/icons.d.ts.map +0 -1
  454. package/src/components/shell/BuildStatusIndicator.tsx +0 -59
  455. package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
  456. package/src/hooks/index.ts +0 -8
  457. package/src/hooks/useResolvedMedia.d.ts.map +0 -1
  458. package/src/lib/cn.d.ts.map +0 -1
  459. package/src/lib/grid.d.ts.map +0 -1
  460. package/src/lib/grid.ts +0 -7
  461. package/src/lib/icons.d.ts.map +0 -1
  462. package/src/lib/loader.d.ts.map +0 -1
  463. package/src/lib/nav.d.ts.map +0 -1
  464. package/src/lib/registry.d.ts.map +0 -1
  465. package/src/lib/sanitize.d.ts.map +0 -1
  466. package/src/media/github.d.ts.map +0 -1
  467. package/src/media/index.d.ts.map +0 -1
  468. package/src/media/queue.d.ts.map +0 -1
  469. package/src/media/resolve.d.ts.map +0 -1
  470. package/src/media/types.d.ts.map +0 -1
  471. package/src/media/utils.d.ts.map +0 -1
  472. package/src/media/videoPoster.d.ts.map +0 -1
  473. package/src/schemas/auth.d.ts.map +0 -1
  474. package/src/schemas/media-grid-options.d.ts.map +0 -1
  475. package/src/schemas/media.d.ts.map +0 -1
  476. package/src/schemas/sections.d.ts.map +0 -1
  477. package/src/schemas/shared.d.ts.map +0 -1
  478. package/src/schemas/site-config.d.ts.map +0 -1
  479. /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
  480. /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
  481. /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
  482. /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
  483. /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
@@ -0,0 +1,149 @@
1
+ import { useContext } from "react";
2
+ import { z } from "zod";
3
+ import { ListChecks } from "lucide-react";
4
+ import { defineSection } from "../../../lib/registry";
5
+ import { LinkValueSchema, DEFAULT_LINK } from "../../../schemas/link";
6
+ import { SummaryAnchorsContext } from "../../shared/SummaryAnchorsContext";
7
+ import { SectionSummaryBlock, type SectionSummaryOptions } from "./SectionSummaryBlock";
8
+ import { SectionSummarySettings } from "./SectionSummarySettings";
9
+
10
+ // The end-of-section TL;DR plate, promoted from Siete's site-local section (#59).
11
+ // The type id and content shape are unchanged, so existing Siete content loads
12
+ // as-is; nav/navLabel are the only additions.
13
+
14
+ const itemSchema = z.object({
15
+ headline: z.string().default("").describe("The principle, short and bold, e.g. \"Saturation > Subtlety\"."),
16
+ explainer: z
17
+ .string()
18
+ .default("")
19
+ .describe("Optional one-sentence explainer rendered softly beneath the headline."),
20
+ link: LinkValueSchema.default(DEFAULT_LINK).describe(
21
+ "Optional jump-link trailing the principle, back to the sub-section it distills. Set with the link picker: an internal page/section (label auto-derived from the page or section name) or an external URL. An empty link renders nothing, but its space is reserved so the layout stays stable.",
22
+ ),
23
+ linkLabel: z
24
+ .string()
25
+ .default("")
26
+ .describe(
27
+ "The jump-link label. Auto-derived from the linked page or section name for internal links (kept in sync as you edit); for external links it falls back to the URL.",
28
+ ),
29
+ });
30
+
31
+ const schema = z.object({
32
+ type: z.literal("section_summary"),
33
+ content: z.object({
34
+ kicker: z
35
+ .string()
36
+ .default("")
37
+ .describe('Uppercase label in the plate\'s top-left, e.g. "Brand Color — Summary".'),
38
+ accent: z
39
+ .string()
40
+ .default("")
41
+ .describe('Script flourish in the plate\'s top-right, e.g. "tl;dr".'),
42
+ items: z
43
+ .array(itemSchema)
44
+ .default([])
45
+ .describe("The summary principles, in display order (numbered automatically)."),
46
+ footNote: z
47
+ .string()
48
+ .default("")
49
+ .describe(
50
+ 'Contextual note in the footer\'s bottom-left, e.g. "Brand Color · 06 principles". Empty = auto "<count> principles".',
51
+ ),
52
+ }),
53
+ options: z
54
+ .object({
55
+ showAccent: z.boolean().describe("Show the script accent (default true).").optional(),
56
+ showFooter: z.boolean().describe("Show the footer row (default true).").optional(),
57
+ showCopy: z
58
+ .boolean()
59
+ .describe("Show the copy-summary action in the footer (default true).")
60
+ .optional(),
61
+ numbered: z.boolean().describe("Show the accent-colored item numerals (default true).").optional(),
62
+ nav: z
63
+ .enum(["off", "heading", "subheading"])
64
+ .describe(
65
+ 'Put this plate in the page nav: "heading" = top level (like a Link Heading), "subheading" = nested under the preceding Link Heading (dropped from the nav if there is none, like a Sub Heading). Absent or "off" = not in the nav.',
66
+ )
67
+ .optional(),
68
+ navLabel: z
69
+ .string()
70
+ .describe(
71
+ "The plate's nav entry text; REQUIRED while nav is on (no label = no entry). Its anchor is derived from it, suffixed -2, -3… if another anchor on the page already has it.",
72
+ )
73
+ .optional(),
74
+ })
75
+ .default({}),
76
+ });
77
+
78
+ export default defineSection({
79
+ type: "section_summary",
80
+ category: "brand-guide",
81
+ label: "TL;DR / Summary",
82
+ icon: <ListChecks size={18} />,
83
+ schema,
84
+ authoringNote:
85
+ "An end-of-section TL;DR plate: numbered principles (bold headline + optional one-sentence explainer) with " +
86
+ "an optional jump-link trailing each explainer back to the sub-section it distills. Place it as the LAST " +
87
+ "block of a major section. Each principle's jump-link is set with the link picker — an internal page/section " +
88
+ "(its label auto-derived from the page or section name) or an external URL; an empty link renders nothing. " +
89
+ 'The footer shows footNote (or an auto "<count> principles" note) plus a copy action that puts the whole ' +
90
+ 'summary on the clipboard as plain text (kicker + "• headline — explainer" lines). Fully functional on the ' +
91
+ "logged-out viewer — no hydration. Optionally appears in the page nav (options.nav heading/subheading with a " +
92
+ "required options.navLabel). Headlines/explainers are composed from truths in the section above; never " +
93
+ "introduce facts here that the section itself does not state.",
94
+ component: function SectionSummarySection({ content, options, onChange, openModal }) {
95
+ const c = content.content;
96
+ const set = (patch: Partial<typeof c>) => onChange?.({ ...content, content: { ...c, ...patch } });
97
+ const id = (content as { id?: string }).id;
98
+ const opts = (options ?? {}) as SectionSummaryOptions;
99
+ const editorAnchor = useContext(SummaryAnchorsContext)[id ?? ""];
100
+ const navAnchor = editorAnchor?.anchor ?? (content as { navAnchor?: string }).navAnchor;
101
+ const navOn = opts.nav === "heading" || opts.nav === "subheading";
102
+ const navHint = !navOn
103
+ ? undefined
104
+ : !opts.navLabel?.trim()
105
+ ? "Not in the nav: add a nav label in Settings."
106
+ : editorAnchor && !editorAnchor.inNav
107
+ ? "Not in the nav: a Subheading needs a Link Heading above it."
108
+ : undefined;
109
+ return (
110
+ <SectionSummaryBlock
111
+ sectionId={id}
112
+ kicker={c.kicker}
113
+ accent={c.accent}
114
+ footNote={c.footNote}
115
+ items={c.items}
116
+ options={opts}
117
+ isEditMode={!!onChange}
118
+ openModal={openModal}
119
+ onKickerChange={onChange ? (kicker) => set({ kicker }) : undefined}
120
+ onAccentChange={onChange ? (accent) => set({ accent }) : undefined}
121
+ onFootNoteChange={onChange ? (footNote) => set({ footNote }) : undefined}
122
+ onItemsChange={onChange ? (items) => set({ items }) : undefined}
123
+ navAnchor={navAnchor}
124
+ navHint={navHint}
125
+ />
126
+ );
127
+ },
128
+ // Inserts ready-to-use with one starter row to overwrite — no empty state to
129
+ // climb out of.
130
+ defaults: () => ({
131
+ type: "section_summary" as const,
132
+ content: {
133
+ kicker: "Summary",
134
+ accent: "tl;dr",
135
+ items: [
136
+ {
137
+ headline: "First principle",
138
+ explainer: "One sentence on why it matters.",
139
+ link: DEFAULT_LINK,
140
+ linkLabel: "",
141
+ },
142
+ ],
143
+ footNote: "",
144
+ },
145
+ options: {},
146
+ }),
147
+ getLabel: (content) => content.content.kicker || "TL;DR / Summary",
148
+ settingsForm: SectionSummarySettings,
149
+ });
@@ -1,5 +1,5 @@
1
1
  import { Heading2 } from "lucide-react";
2
- import { defineHeadingSection } from "../../primitives/defineHeadingSection";
2
+ import { defineHeadingSection } from "../../primitives/define-heading-section";
3
3
 
4
4
  export default defineHeadingSection({
5
5
  type: "sub_heading",
@@ -1,5 +1,5 @@
1
1
  import { Heading3 } from "lucide-react";
2
- import { defineHeadingSection } from "../../primitives/defineHeadingSection";
2
+ import { defineHeadingSection } from "../../primitives/define-heading-section";
3
3
 
4
4
  export default defineHeadingSection({
5
5
  type: "sub_sub_heading",
@@ -2,13 +2,14 @@ import colors from "./Colors";
2
2
  import iconList from "./IconList";
3
3
  import doDontMedia from "./DoDontMedia";
4
4
  import documentSection from "./Document";
5
+ import sectionSummary from "./SectionSummary";
5
6
 
6
7
  /** Opinionated brand-guide sections. Self-contained subtree: a build that does
7
- * not import this module drops these sections (and their cmyk/pantone schemas
8
- * and do/dont compositions) entirely. Exposed at
8
+ * not import this module drops these sections (and their cmyk/pantone schemas,
9
+ * do/dont compositions and the TL;DR plate) entirely. Exposed at
9
10
  * `@drawnagency/primitives/components/sections/brand-guide`. */
10
11
  // Un-annotated for the same generic-variance reason as coreSectionDefs.
11
- export const brandGuideSectionDefs = [colors, iconList, doDontMedia, documentSection];
12
+ export const brandGuideSectionDefs = [colors, iconList, doDontMedia, documentSection, sectionSummary];
12
13
 
13
14
  export { ColorSpaceSchema, ColorItemSchema } from "./Colors/schema";
14
15
  export type { ColorSpace, ColorItem } from "./Colors/schema";
@@ -7,6 +7,7 @@ import video from "./Video";
7
7
  import button from "./Button";
8
8
  import container from "./Container";
9
9
  import spacer from "./Spacer";
10
+ import reference from "./Reference";
10
11
 
11
12
  /** Generic, brand-agnostic built-in sections. A non-brand site can register
12
13
  * exactly these (plus its own custom sections) and tree-shake the brand-guide
@@ -25,4 +26,5 @@ export const coreSectionDefs = [
25
26
  button,
26
27
  container,
27
28
  spacer,
29
+ reference,
28
30
  ];
@@ -0,0 +1,13 @@
1
+ import { createContext, useContext } from "react";
2
+ import type { BrandSwatch } from "../../lib/brand-swatches";
3
+
4
+ /**
5
+ * Hex values from every Colors section site-wide, for color pickers in
6
+ * settings forms. A form only receives its own section's values, so EditorShell
7
+ * provides these from all loaded sections (collectBrandSwatches).
8
+ */
9
+ export const BrandSwatchesContext = createContext<BrandSwatch[]>([]);
10
+
11
+ export function useBrandSwatches(): BrandSwatch[] {
12
+ return useContext(BrandSwatchesContext);
13
+ }
@@ -1,20 +1,29 @@
1
- import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react";
1
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode, Ref } from "react";
2
2
  import { cn } from "../../lib/cn";
3
3
 
4
4
  export type ButtonVariant = "primary" | "brand" | "secondary" | "destructive" | "ghost";
5
5
  export type ButtonSize = "sm" | "md";
6
6
  export type ButtonTone = "neutral" | "destructive";
7
7
 
8
- export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
8
+ interface ButtonCommon {
9
9
  variant?: ButtonVariant;
10
10
  size?: ButtonSize;
11
11
  tone?: ButtonTone;
12
12
  fullWidth?: boolean;
13
13
  isLoading?: boolean;
14
14
  loadingLabel?: string;
15
+ className?: string;
15
16
  children?: ReactNode;
16
17
  }
17
18
 
19
+ // Same discriminated-union shape as Fab: `href` renders an <a> with identical
20
+ // classes (ref excluded — an <a> ref is a different element type, and no
21
+ // caller needs one today); its absence renders a <button> and accepts a ref.
22
+ export type ButtonProps =
23
+ | ({ href: string } & ButtonCommon & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children" | "className">)
24
+ | ({ href?: undefined; ref?: Ref<HTMLButtonElement> } & ButtonCommon &
25
+ Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "className">);
26
+
18
27
  const boxSize: Record<ButtonSize, string> = {
19
28
  sm: "rounded px-3 py-1.5 text-xs font-medium",
20
29
  md: "rounded px-4 py-2 text-sm font-medium",
@@ -30,48 +39,52 @@ const variantClasses: Record<Exclude<ButtonVariant, "ghost">, string> = {
30
39
  brand: "bg-primary text-primary-contrast hover:opacity-90",
31
40
  secondary: "border border-base-200 text-base-contrast hover:bg-base-accent",
32
41
  destructive:
33
- "border border-red-600 text-red-600 hover:bg-red-600 hover:text-white",
42
+ "border border-danger text-danger hover:bg-danger hover:text-white",
34
43
  };
35
44
 
36
45
  const ghostToneClasses: Record<ButtonTone, string> = {
37
46
  neutral: "text-base-contrast-light hover:text-base-contrast",
38
- destructive: "text-red-600 hover:text-red-800",
47
+ destructive: "text-danger hover:text-danger-hover",
39
48
  };
40
49
 
41
- export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
42
- {
43
- variant = "primary",
44
- size = "sm",
45
- tone = "neutral",
46
- fullWidth = false,
47
- isLoading = false,
48
- loadingLabel,
49
- disabled,
50
- className,
51
- children,
52
- ...rest
53
- },
54
- ref,
55
- ) {
50
+ export function Button({
51
+ variant = "primary",
52
+ size = "sm",
53
+ tone = "neutral",
54
+ fullWidth = false,
55
+ isLoading = false,
56
+ loadingLabel,
57
+ className,
58
+ children,
59
+ ...rest
60
+ }: ButtonProps) {
56
61
  const isGhost = variant === "ghost";
57
- const resolvedDisabled = disabled || isLoading;
62
+ const disabled = rest.href === undefined ? rest.disabled || isLoading : false;
58
63
  const label = isLoading && loadingLabel ? loadingLabel : children;
59
64
 
65
+ const classes = cn(
66
+ "inline-flex items-center justify-center transition-colors",
67
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
68
+ isGhost ? ghostSize[size] : boxSize[size],
69
+ isGhost ? ghostToneClasses[tone] : variantClasses[variant],
70
+ fullWidth && "w-full",
71
+ disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
72
+ className,
73
+ );
74
+
75
+ if (rest.href !== undefined) {
76
+ return (
77
+ <a className={classes} {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}>
78
+ {label}
79
+ </a>
80
+ );
81
+ }
82
+
83
+ const { ref, disabled: _disabled, ...buttonRest } = rest as { ref?: Ref<HTMLButtonElement> } &
84
+ ButtonHTMLAttributes<HTMLButtonElement>;
60
85
  return (
61
- <button
62
- ref={ref}
63
- disabled={resolvedDisabled}
64
- className={cn(
65
- "inline-flex items-center justify-center transition-colors",
66
- isGhost ? ghostSize[size] : boxSize[size],
67
- isGhost ? ghostToneClasses[tone] : variantClasses[variant],
68
- fullWidth && "w-full",
69
- resolvedDisabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
70
- className,
71
- )}
72
- {...rest}
73
- >
86
+ <button ref={ref} disabled={disabled} className={classes} {...buttonRest}>
74
87
  {label}
75
88
  </button>
76
89
  );
77
- });
90
+ }
@@ -48,18 +48,10 @@ export function Checkbox({
48
48
  onChange={(e) => onChange(e.target.checked)}
49
49
  className="sr-only"
50
50
  />
51
- <span
52
- aria-hidden="true"
53
- className={cn(
54
- "flex h-5 w-5 items-center justify-center rounded border transition-colors",
55
- checked
56
- ? "border-primary bg-primary text-primary-contrast"
57
- : "border-base-300 bg-base hover:border-primary",
58
- disabled && "pointer-events-none",
59
- )}
60
- >
61
- {checked && <Check size={14} strokeWidth={3} />}
62
- </span>
51
+ <CheckboxBox
52
+ checked={checked}
53
+ className={cn(!checked && "hover:border-primary", disabled && "pointer-events-none")}
54
+ />
63
55
  </span>
64
56
  {startAdornment}
65
57
  <div className="text-sm">
@@ -71,3 +63,20 @@ export function Checkbox({
71
63
  </label>
72
64
  );
73
65
  }
66
+
67
+ /** The visual square alone, for rows whose own element carries the checkbox
68
+ * role (a menu item, a picker row) and so can't nest a labelled input. */
69
+ export function CheckboxBox({ checked, className }: { checked: boolean; className?: string }) {
70
+ return (
71
+ <span
72
+ aria-hidden="true"
73
+ className={cn(
74
+ "flex h-5 w-5 shrink-0 items-center justify-center rounded border transition-colors",
75
+ checked ? "border-primary bg-primary text-primary-contrast" : "border-base-300 bg-base",
76
+ className,
77
+ )}
78
+ >
79
+ {checked && <Check size={14} strokeWidth={3} />}
80
+ </span>
81
+ );
82
+ }
@@ -0,0 +1,87 @@
1
+ import type { ReactNode } from "react";
2
+ import { Button } from "./Button";
3
+ import { EditorModal } from "../shell/EditorModal";
4
+
5
+ // Stable identity: EditorModal wires this into useStackedEscape, whose effect
6
+ // deps include it — a fresh `() => {}` literal every render (while `busy`)
7
+ // would tear down and re-add its Escape listener on every render instead of
8
+ // just when `busy` actually flips.
9
+ const NOOP = () => {};
10
+
11
+ export interface ConfirmDialogProps {
12
+ isOpen: boolean;
13
+ title: string;
14
+ body?: ReactNode;
15
+ confirmLabel: string;
16
+ cancelLabel?: string;
17
+ tone?: "destructive" | "neutral";
18
+ busy?: boolean;
19
+ busyLabel?: string;
20
+ /** The typed-name page delete gates on this. */
21
+ confirmDisabled?: boolean;
22
+ onConfirm: () => void;
23
+ onCancel: () => void;
24
+ /**
25
+ * Renders title/body/buttons with no `EditorModal` wrapper — for a confirm
26
+ * that appears inside an ALREADY-OPEN `EditorModal` (PagesModal's typed-name
27
+ * delete, HistoryChangesModal's restore mode-swap). Two nested EditorModals
28
+ * would each register their own document Escape listener, so one Escape
29
+ * would close both.
30
+ */
31
+ embedded?: boolean;
32
+ }
33
+
34
+ export function ConfirmDialog({
35
+ isOpen,
36
+ title,
37
+ body,
38
+ confirmLabel,
39
+ cancelLabel = "Cancel",
40
+ tone = "destructive",
41
+ busy = false,
42
+ busyLabel,
43
+ confirmDisabled = false,
44
+ onConfirm,
45
+ onCancel,
46
+ embedded = false,
47
+ }: ConfirmDialogProps) {
48
+ if (!isOpen) return null;
49
+
50
+ const buttons = (
51
+ <div className="flex justify-end gap-3">
52
+ <Button type="button" variant="secondary" size="md" onClick={onCancel} disabled={busy}>
53
+ {cancelLabel}
54
+ </Button>
55
+ <Button
56
+ type="button"
57
+ variant={tone === "destructive" ? "destructive" : "primary"}
58
+ size="md"
59
+ onClick={onConfirm}
60
+ disabled={confirmDisabled}
61
+ isLoading={busy}
62
+ loadingLabel={busyLabel}
63
+ >
64
+ {confirmLabel}
65
+ </Button>
66
+ </div>
67
+ );
68
+
69
+ if (embedded) {
70
+ return (
71
+ <div className="flex flex-col gap-3">
72
+ <h4 className="text-base font-semibold text-base-contrast">{title}</h4>
73
+ {body}
74
+ {buttons}
75
+ </div>
76
+ );
77
+ }
78
+
79
+ return (
80
+ <EditorModal isOpen={isOpen} onClose={busy ? NOOP : onCancel} title={title} size="standard">
81
+ <div className="flex flex-col gap-3">
82
+ {body}
83
+ {buttons}
84
+ </div>
85
+ </EditorModal>
86
+ );
87
+ }
@@ -0,0 +1,90 @@
1
+ import { useEffect, useRef, type ReactNode, type RefObject } from "react";
2
+ import { cn } from "../../lib/cn";
3
+ import { Button } from "./Button";
4
+
5
+ export type ConfirmTone = "destructive" | "neutral";
6
+
7
+ const toneClasses: Record<ConfirmTone, string> = {
8
+ destructive: "border-danger bg-danger-bg text-danger",
9
+ neutral: "border-base-200 bg-base text-base-contrast",
10
+ };
11
+
12
+ export interface ConfirmInlineProps {
13
+ message: ReactNode;
14
+ confirmLabel: string;
15
+ cancelLabel?: string;
16
+ tone: ConfirmTone;
17
+ busy?: boolean;
18
+ confirmDisabled?: boolean;
19
+ /** Overrides the confirm button's accessible name when the visible label is
20
+ * ambiguous across multiple rows (NavGroupRow's pinned "Confirm delete"). */
21
+ confirmAriaLabel?: string;
22
+ /** Sits between Cancel and confirm as `Button variant="secondary"` — the
23
+ * folder delete's "Move contents to parent" is the one user today. */
24
+ secondaryAction?: { label: string; onClick: () => void };
25
+ onConfirm: () => void;
26
+ onCancel: () => void;
27
+ /** Focus returns here on unmount — the row's trigger button, typically. */
28
+ returnFocusTo?: RefObject<HTMLElement | null>;
29
+ }
30
+
31
+ export function ConfirmInline({
32
+ message,
33
+ confirmLabel,
34
+ cancelLabel = "Cancel",
35
+ tone,
36
+ busy = false,
37
+ confirmDisabled = false,
38
+ confirmAriaLabel,
39
+ secondaryAction,
40
+ onConfirm,
41
+ onCancel,
42
+ returnFocusTo,
43
+ }: ConfirmInlineProps) {
44
+ const cancelRef = useRef<HTMLButtonElement>(null);
45
+
46
+ // Focus moves to Cancel on mount and back to the trigger on unmount — a
47
+ // destructive/neutral confirm appearing inline (not in a trapped modal)
48
+ // still owes a keyboard user a predictable landing spot.
49
+ useEffect(() => {
50
+ cancelRef.current?.focus();
51
+ return () => {
52
+ returnFocusTo?.current?.focus();
53
+ };
54
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- mount/unmount only
55
+ }, []);
56
+
57
+ return (
58
+ <div
59
+ role="alertdialog"
60
+ aria-live="assertive"
61
+ className={cn(
62
+ "flex flex-col items-center gap-2 rounded-lg border px-4 py-3 lg:flex-row lg:justify-between",
63
+ toneClasses[tone],
64
+ )}
65
+ >
66
+ <p className="text-center text-sm lg:text-left">{message}</p>
67
+ <div className="flex shrink-0 flex-wrap items-center justify-end gap-2">
68
+ <Button type="button" ref={cancelRef} variant="secondary" size="sm" onClick={onCancel} disabled={busy}>
69
+ {cancelLabel}
70
+ </Button>
71
+ {secondaryAction && (
72
+ <Button type="button" variant="secondary" size="sm" onClick={secondaryAction.onClick} disabled={busy}>
73
+ {secondaryAction.label}
74
+ </Button>
75
+ )}
76
+ <Button
77
+ type="button"
78
+ variant={tone === "destructive" ? "destructive" : "primary"}
79
+ size="sm"
80
+ onClick={onConfirm}
81
+ disabled={confirmDisabled}
82
+ isLoading={busy}
83
+ aria-label={confirmAriaLabel}
84
+ >
85
+ {confirmLabel}
86
+ </Button>
87
+ </div>
88
+ </div>
89
+ );
90
+ }
@@ -1,4 +1,5 @@
1
1
  import { Component, type ReactNode, type ErrorInfo } from "react";
2
+ import { AlertTriangle } from "lucide-react";
2
3
  import { cn } from "../../lib/cn";
3
4
  import { Button } from "./Button";
4
5
 
@@ -46,36 +47,23 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
46
47
  <div
47
48
  role="alert"
48
49
  className={cn(
49
- "flex flex-col items-center justify-center gap-3 rounded border border-red-200 bg-red-50 px-6 py-10 text-center",
50
- "dark:border-red-900/40 dark:bg-red-950/20",
50
+ "flex flex-col items-center justify-center gap-3 rounded border border-danger bg-danger-bg px-6 py-10 text-center",
51
51
  )}
52
52
  >
53
- <svg
54
- xmlns="http://www.w3.org/2000/svg"
55
- viewBox="0 0 20 20"
56
- fill="currentColor"
57
- className="h-6 w-6 text-red-500"
58
- aria-hidden="true"
59
- >
60
- <path
61
- fillRule="evenodd"
62
- d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
63
- clipRule="evenodd"
64
- />
65
- </svg>
53
+ <AlertTriangle className="h-6 w-6 text-danger" aria-hidden="true" />
66
54
 
67
- <p className="text-sm font-medium text-red-700 dark:text-red-400">
55
+ <p className="text-sm font-medium text-danger">
68
56
  This section couldn&apos;t be rendered
69
57
  </p>
70
58
 
71
59
  {this.props.label && (
72
- <p className="text-xs text-red-500 dark:text-red-500/80">
60
+ <p className="text-xs text-danger">
73
61
  Section: {this.props.label}
74
62
  </p>
75
63
  )}
76
64
 
77
65
  {this.state.error && (
78
- <p className="max-w-md text-xs text-red-400 dark:text-red-500/60">
66
+ <p className="max-w-md text-xs text-danger">
79
67
  {this.state.error.message}
80
68
  </p>
81
69
  )}
@@ -24,9 +24,18 @@ interface FabCommon {
24
24
  /** Accessible name — FABs are icon-only. */
25
25
  label: string;
26
26
  column: "viewer" | "editor";
27
- /** Vertical slot (bottom-*) plus any per-FAB extras. */
27
+ /** Vertical slot (bottom-*) plus any per-FAB extras. Ignored when `stacked`
28
+ * — `FabStack` owns spacing then. */
28
29
  className?: string;
29
30
  children: ReactNode;
31
+ /** Renders as a static, non-fixed member of a `FabStack` instead of an
32
+ * independently viewport-fixed button: `relative`, no `bottom-*`/`right-*`
33
+ * of its own. React context can't cross the viewer page's separate Astro
34
+ * islands, so this is a prop, not a stacking context — `FabStack` is
35
+ * editor-shell only; the viewer page's FABs never set it. `fab-stacked`
36
+ * suppresses the lg+ position rule base.css gives `.fab-container-right`
37
+ * (see FabStack), so the two positioning mechanisms don't compound. */
38
+ stacked?: boolean;
30
39
  }
31
40
 
32
41
  export type FabProps =
@@ -34,12 +43,13 @@ export type FabProps =
34
43
  | ({ href?: undefined; ref?: Ref<HTMLButtonElement> } & FabCommon &
35
44
  Omit<ComponentPropsWithoutRef<"button">, "children" | "className" | "aria-label" | "type">);
36
45
 
37
- export default function Fab({ label, column, className, children, ...rest }: FabProps) {
46
+ export default function Fab({ label, column, className, children, stacked, ...rest }: FabProps) {
38
47
  const classes = cn(
39
- "cursor-pointer fixed flex items-center justify-center rounded-full bg-primary text-primary-contrast shadow-lg hover:opacity-90 transition-opacity",
48
+ "cursor-pointer flex items-center justify-center rounded-full bg-primary text-primary-contrast shadow-lg hover:opacity-90 transition-opacity",
49
+ stacked ? "relative" : "fixed",
40
50
  column === "viewer"
41
- ? "z-40 h-12 w-12 right-4 viewer-fab"
42
- : "z-50 h-10 w-10 right-4 lg:right-auto fab-container-right",
51
+ ? cn("h-12 w-12 viewer-fab", !stacked && "z-40 right-4")
52
+ : cn("h-10 w-10 fab-container-right", stacked ? "fab-stacked" : "z-50 right-4 lg:right-auto"),
43
53
  className,
44
54
  );
45
55
  if (rest.href !== undefined) {
@@ -0,0 +1,28 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ interface FabStackProps {
4
+ children: ReactNode;
5
+ }
6
+
7
+ /** Vertical stack for the /edit FAB column — EditorShell's own FABs
8
+ * (mode toggle, doc-edit, BugReportFAB) share this rhythm so they can never
9
+ * overlap. ChatWidget's launcher stays independently `fixed` (a React
10
+ * context here can't reach it anyway: the viewer page renders each `<Fab>`
11
+ * as its own Astro island, and the chat launcher lives inside the
12
+ * ChatWidget island).
13
+ *
14
+ * Positioning lives on the container only: `right-4 lg:right-auto` plus
15
+ * `fab-container-right`, whose lg+ rule in base.css re-sets `right` to the
16
+ * content edge. That rule skips `.fab-stacked`, so stacked children are never
17
+ * shifted twice — but it means the container MUST carry the class: without
18
+ * it, `lg:right-auto` leaves the fixed column with no horizontal inset at all
19
+ * and it falls back to its static position over the page content. Children
20
+ * render with `stacked` (relative, no position classes of their own) and
21
+ * contribute only spacing via this flex column. */
22
+ export function FabStack({ children }: FabStackProps) {
23
+ return (
24
+ <div className="fab-container-right fixed z-50 bottom-16 right-4 lg:right-auto flex flex-col items-end gap-4">
25
+ {children}
26
+ </div>
27
+ );
28
+ }