@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
@@ -1,5 +1,7 @@
1
1
  import { formatDateTime } from "../../lib/timestamp";
2
2
  import { Button } from "../shared/Button";
3
+ import { Select } from "../shared/Select";
4
+ import { ToolbarFrame } from "../shared/ToolbarFrame";
3
5
 
4
6
  interface HistoryPageOption {
5
7
  id: string;
@@ -17,38 +19,34 @@ interface HistoryToolbarProps {
17
19
 
18
20
  export function HistoryToolbar({ date, pages, activePageId, onPageChange, onBackToCurrent, onRestore }: HistoryToolbarProps) {
19
21
  return (
20
- <div className="fixed top-0 right-0 left-0 z-50 border-b border-base-200 bg-base">
21
- <div className="mx-auto max-w-screen-xl grid grid-cols-3 items-center px-4 py-2">
22
- <div className="flex items-center">
23
- <Button variant="secondary" size="sm" onClick={onBackToCurrent}>
24
- Back to current
25
- </Button>
26
- </div>
27
- <div className="flex items-center justify-center gap-2">
22
+ <ToolbarFrame
23
+ left={
24
+ <Button variant="secondary" size="sm" onClick={onBackToCurrent}>
25
+ Back to current
26
+ </Button>
27
+ }
28
+ center={
29
+ <>
28
30
  <span className="text-xs font-medium text-base-contrast-light">
29
31
  Viewing {formatDateTime(date)}
30
32
  </span>
31
33
  {pages.length > 1 && (
32
- <select
34
+ <Select
33
35
  value={activePageId}
34
- onChange={(e) => onPageChange(e.target.value)}
35
- className="rounded border border-base-200 bg-base px-1.5 py-0.5 text-xs font-medium text-base-contrast"
36
+ onChange={onPageChange}
37
+ options={pages.map((p) => ({ value: p.id, label: p.title }))}
38
+ selectClassName="py-0.5 pl-1.5 text-xs"
39
+ className="w-auto"
36
40
  aria-label="Page at this version"
37
- >
38
- {pages.map((p) => (
39
- <option key={p.id} value={p.id}>
40
- {p.title}
41
- </option>
42
- ))}
43
- </select>
41
+ />
44
42
  )}
45
- </div>
46
- <div className="flex items-center justify-end">
47
- <Button variant="primary" size="sm" onClick={onRestore}>
48
- Restore this version
49
- </Button>
50
- </div>
51
- </div>
52
- </div>
43
+ </>
44
+ }
45
+ right={
46
+ <Button variant="primary" size="sm" onClick={onRestore}>
47
+ Restore this version
48
+ </Button>
49
+ }
50
+ />
53
51
  );
54
52
  }
@@ -13,7 +13,10 @@ export interface MediaFolderTileProps {
13
13
  onOpen: (id: string) => void;
14
14
  manage: boolean;
15
15
  onRename?: (id: string, name: string) => void;
16
- onDeleteRequest?: (id: string) => void;
16
+ /** `trigger` is the kebab "Folder actions" button — the Delete menu item
17
+ * itself unmounts (menu closes) the instant it's clicked, so the caller's
18
+ * ConfirmInline returns focus to the kebab button instead. */
19
+ onDeleteRequest?: (id: string, trigger: HTMLElement | null) => void;
17
20
  dnd?: MediaFolderDndBindings;
18
21
  /** Optional accessible label override for the root element (e.g. "Open folder Logos"). */
19
22
  ariaLabel?: string;
@@ -29,6 +32,7 @@ export function MediaFolderTile({
29
32
  const [renaming, setRenaming] = useState(false);
30
33
  const [draft, setDraft] = useState(name);
31
34
  const menuRef = useRef<HTMLDivElement>(null);
35
+ const kebabButtonRef = useRef<HTMLButtonElement>(null);
32
36
  const emptyFoldersRef = useRef<Record<string, MediaFolder>>({});
33
37
  const emptyItemsRef = useRef<Record<string, MediaItem>>({});
34
38
 
@@ -105,6 +109,7 @@ export function MediaFolderTile({
105
109
  {manage && !renaming && (
106
110
  <div ref={menuRef} className="relative shrink-0">
107
111
  <button
112
+ ref={kebabButtonRef}
108
113
  type="button"
109
114
  aria-label={`Folder actions: ${name}`}
110
115
  onClick={(e) => { e.stopPropagation(); setMenuOpen((v) => !v); }}
@@ -128,8 +133,8 @@ export function MediaFolderTile({
128
133
  </button>
129
134
  <button
130
135
  type="button"
131
- className="block w-full px-3 py-1.5 text-left text-sm text-red-600 hover:bg-base-accent dark:text-red-400"
132
- onClick={(e) => { e.stopPropagation(); setMenuOpen(false); onDeleteRequest?.(id); }}
136
+ className="block w-full px-3 py-1.5 text-left text-sm text-danger hover:bg-base-accent dark:text-danger"
137
+ onClick={(e) => { e.stopPropagation(); setMenuOpen(false); onDeleteRequest?.(id, kebabButtonRef.current); }}
133
138
  onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") e.stopPropagation(); }}
134
139
  >
135
140
  Delete
@@ -2,10 +2,13 @@ import { useState, useRef, useCallback, useMemo, useEffect } from "react";
2
2
  import { Search, Upload, Trash2, FolderPlus, FolderInput, FileText } from "lucide-react";
3
3
  import { cn } from "../../lib/cn";
4
4
  import { Button } from "../shared/Button";
5
- import { UploadRejectionAlert } from "../shared/UploadRejectionAlert";
5
+ import { Input } from "../shared/Input";
6
+ import { InlineAlert } from "../shared/InlineAlert";
7
+ import { ConfirmInline } from "../shared/ConfirmInline";
8
+ import { Notice } from "../shared/Notice";
6
9
  import { Select } from "../shared/Select";
7
10
  import type { MediaFolder, MediaItem } from "../../media/types";
8
- import { displayFilename, displayName, formatFileSize, mimeToExt } from "../../media/utils";
11
+ import { displayFilename, displayName, formatFileSize, mediaThumbnailUrl } from "../../media/utils";
9
12
  import {
10
13
  childFolderIds, descendantFolderIds, DOCUMENTS_FOLDER_ID, folderPathIds, folderPathNames,
11
14
  itemFolderId, recursiveItemCounts,
@@ -75,17 +78,8 @@ export interface MediaLibraryModalProps {
75
78
 
76
79
  type KindFilter = "all" | LibraryKind;
77
80
 
78
- function thumbnailSrc(item: MediaItem, localUrls: Record<string, string>): string {
79
- const localUrl = localUrls[item.id];
80
- if (localUrl) return localUrl;
81
- if (item.kind === "video") {
82
- return `/api/media/${item.id}/original.${mimeToExt(item.mimeType)}`;
83
- }
84
- if (item.kind === "image" && item.variants.length > 0) {
85
- const smallest = item.variants.reduce((a, b) => (a.width < b.width ? a : b));
86
- return `/api/media/${item.id}/${smallest.width}.webp`;
87
- }
88
- return `/api/media/${item.id}/poster.webp`;
81
+ function thumbnailSrc(item: MediaItem, localUrls: Record<string, string>): string | undefined {
82
+ return localUrls[item.id] ?? mediaThumbnailUrl(item) ?? undefined;
89
83
  }
90
84
 
91
85
  function DocumentTile({ doc, manage, isSelected, refCount, showFolderChip, onClick }: {
@@ -540,6 +534,8 @@ export function MediaLibraryModal({
540
534
  }
541
535
 
542
536
  const [confirmDelete, setConfirmDelete] = useState(false);
537
+ const batchDeleteButtonRef = useRef<HTMLButtonElement>(null);
538
+ const folderDeleteTriggerRef = useRef<HTMLElement | null>(null);
543
539
 
544
540
  // One selection, two kinds. Everything downstream — delete dispatch, usage
545
541
  // totals, the move dialog — splits on this: documents have no folder and
@@ -685,12 +681,14 @@ export function MediaLibraryModal({
685
681
  size={14}
686
682
  className="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-base-contrast-light"
687
683
  />
688
- <input
684
+ <Input
685
+ label="Search media"
686
+ hideLabel
689
687
  type="text"
690
688
  placeholder="Search media..."
691
689
  value={search}
692
- onChange={(e) => setSearch(e.target.value)}
693
- className="w-full rounded border border-base-200 bg-base py-1.5 pl-8 pr-3 text-sm text-base-contrast placeholder:text-base-contrast-light focus:outline-none focus:ring-1 focus:ring-primary"
690
+ onChange={setSearch}
691
+ inputClassName="py-1.5 pl-8 pr-3 focus:ring-primary"
694
692
  />
695
693
  </div>
696
694
 
@@ -725,6 +723,7 @@ export function MediaLibraryModal({
725
723
 
726
724
  {mode === "manage" && selected.size > 0 && (
727
725
  <Button
726
+ ref={batchDeleteButtonRef}
728
727
  variant="destructive"
729
728
  size="sm"
730
729
  onClick={handleBatchDelete}
@@ -750,16 +749,19 @@ export function MediaLibraryModal({
750
749
 
751
750
  {newFolderOpen && (
752
751
  <div className="flex items-center gap-2">
753
- <input
752
+ <Input
753
+ label="Folder name"
754
+ hideLabel
754
755
  autoFocus
755
756
  placeholder="Folder name"
756
757
  value={newFolderName}
757
- onChange={(e) => setNewFolderName(e.target.value)}
758
+ onChange={setNewFolderName}
758
759
  onKeyDown={(e) => {
759
760
  if (e.key === "Enter") commitNewFolder();
760
761
  if (e.key === "Escape") { setNewFolderOpen(false); setNewFolderName(""); }
761
762
  }}
762
- className="flex-1 rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast focus:outline-none focus:ring-1 focus:ring-primary"
763
+ className="flex-1"
764
+ inputClassName="px-2 py-1 focus:ring-primary"
763
765
  />
764
766
  <Button variant="secondary" size="sm" onClick={() => { setNewFolderOpen(false); setNewFolderName(""); }}>Cancel</Button>
765
767
  <Button variant="primary" size="sm" onClick={commitNewFolder}>Create</Button>
@@ -768,49 +770,46 @@ export function MediaLibraryModal({
768
770
 
769
771
  {/* Delete confirmation */}
770
772
  {confirmDelete && (
771
- <div className="flex flex-col items-center rounded-lg border border-red-200 bg-red-50 px-4 py-3 lg:flex-row lg:justify-between dark:border-red-900/50 dark:bg-red-950/30">
772
- <p className="mb-2 text-center text-sm text-red-800 lg:mb-0 lg:text-left dark:text-red-200">
773
- {totalUsage > 0
773
+ <ConfirmInline
774
+ message={
775
+ totalUsage > 0
774
776
  ? `Some of these ${usedNoun} are being used. Deleting them will remove them from the sections that use them.`
775
- : `Delete ${selectedIds.length} ${usedNoun}? No section uses them.`}
776
- </p>
777
- <div className="flex shrink-0 items-center gap-2">
778
- <Button variant="secondary" size="sm" onClick={() => setConfirmDelete(false)}>
779
- Cancel
780
- </Button>
781
- <Button variant="destructive" size="sm" onClick={handleConfirmDelete}>
782
- Confirm Delete
783
- </Button>
784
- </div>
785
- </div>
777
+ : `Delete ${selectedIds.length} ${usedNoun}? No section uses them.`
778
+ }
779
+ confirmLabel="Confirm Delete"
780
+ tone="destructive"
781
+ onConfirm={handleConfirmDelete}
782
+ onCancel={() => setConfirmDelete(false)}
783
+ returnFocusTo={batchDeleteButtonRef}
784
+ />
786
785
  )}
787
786
 
788
787
  {folderToDelete && folderDeleteInfo && onDeleteFolder && (
789
- <div className="flex flex-col gap-2 rounded-lg border border-red-200 bg-red-50 px-4 py-3 dark:border-red-900/50 dark:bg-red-950/30">
790
- <p className="text-sm text-red-800 dark:text-red-200">
791
- Delete &ldquo;{folderDeleteInfo.name}&rdquo;? It contains {folderDeleteInfo.count} item{folderDeleteInfo.count === 1 ? "" : "s"}
792
- {folderDeleteInfo.inUse > 0 && (
793
- <> — {folderDeleteInfo.inUse === 1 ? "1 is in use" : `${folderDeleteInfo.inUse} are in use`} and will be removed from those sections</>
794
- )}
795
- .
796
- </p>
797
- <div className="flex flex-wrap items-center justify-end gap-2">
798
- <Button variant="secondary" size="sm" onClick={() => setFolderToDelete(null)}>Cancel</Button>
799
- <Button variant="secondary" size="sm"
800
- onClick={() => { onDeleteFolder(folderToDelete, "move"); setFolderToDelete(null); }}>
801
- Move contents to parent
802
- </Button>
803
- <Button variant="destructive" size="sm"
804
- onClick={() => { onDeleteFolder(folderToDelete, "delete"); setFolderToDelete(null); }}>
805
- Delete {folderDeleteInfo.count} item{folderDeleteInfo.count === 1 ? "" : "s"}
806
- </Button>
807
- </div>
808
- </div>
788
+ <ConfirmInline
789
+ message={
790
+ <>
791
+ Delete &ldquo;{folderDeleteInfo.name}&rdquo;? It contains {folderDeleteInfo.count} item{folderDeleteInfo.count === 1 ? "" : "s"}
792
+ {folderDeleteInfo.inUse > 0 && (
793
+ <> — {folderDeleteInfo.inUse === 1 ? "1 is in use" : `${folderDeleteInfo.inUse} are in use`} and will be removed from those sections</>
794
+ )}
795
+ .
796
+ </>
797
+ }
798
+ confirmLabel={`Delete ${folderDeleteInfo.count} item${folderDeleteInfo.count === 1 ? "" : "s"}`}
799
+ tone="destructive"
800
+ secondaryAction={{
801
+ label: "Move contents to parent",
802
+ onClick: () => { onDeleteFolder(folderToDelete, "move"); setFolderToDelete(null); },
803
+ }}
804
+ onConfirm={() => { onDeleteFolder(folderToDelete, "delete"); setFolderToDelete(null); }}
805
+ onCancel={() => setFolderToDelete(null)}
806
+ returnFocusTo={folderDeleteTriggerRef}
807
+ />
809
808
  )}
810
809
 
811
810
  {/* File size rejection alert */}
812
811
  {rejectedFiles.length > 0 && maxFileSize && (
813
- <UploadRejectionAlert
812
+ <InlineAlert
814
813
  message={
815
814
  rejectedFiles.length === 1
816
815
  ? `"${rejectedFiles[0]}" exceeds the ${formatFileSize(maxFileSize)} file size limit.`
@@ -823,7 +822,7 @@ export function MediaLibraryModal({
823
822
  {/* Async upload failure (oversized/disallowed file, upload-intent error,
824
823
  direct-to-bucket PUT failure) — distinct from the client-side check above. */}
825
824
  {uploadError && (
826
- <UploadRejectionAlert
825
+ <InlineAlert
827
826
  message={uploadError}
828
827
  onDismiss={() => onDismissUploadError?.()}
829
828
  />
@@ -831,10 +830,9 @@ export function MediaLibraryModal({
831
830
 
832
831
  {/* Informational, non-error upload notice (e.g. dedup skip). */}
833
832
  {uploadNotice && (
834
- <UploadRejectionAlert
835
- message={uploadNotice}
836
- onDismiss={() => onDismissUploadNotice?.()}
837
- />
833
+ <Notice tone="info" placement="inline" onDismiss={() => onDismissUploadNotice?.()}>
834
+ {uploadNotice}
835
+ </Notice>
838
836
  )}
839
837
  </div>
840
838
 
@@ -868,7 +866,7 @@ export function MediaLibraryModal({
868
866
  onRename={onRenameFolder}
869
867
  onDeleteRequest={
870
868
  manage && onDeleteFolder
871
- ? (id) => {
869
+ ? (id, trigger) => {
872
870
  const doomed = descendantFolderIds(folders, id);
873
871
  const hasContents =
874
872
  items.some((item) => {
@@ -876,6 +874,7 @@ export function MediaLibraryModal({
876
874
  return fid !== null && doomed.has(fid);
877
875
  }) || doomed.size > 1;
878
876
  if (hasContents) {
877
+ folderDeleteTriggerRef.current = trigger;
879
878
  setFolderToDelete(id);
880
879
  setConfirmDelete(false); // the two delete confirmations are mutually exclusive
881
880
  } else onDeleteFolder(id, "move"); // empty: no dialog needed
@@ -59,11 +59,11 @@ export function ProcessingIndicator({ items }: ProcessingIndicatorProps) {
59
59
  {/* Error items */}
60
60
  {errorItems.map((item) => (
61
61
  <div key={item.id} className="flex flex-col gap-0.5 px-3 py-2">
62
- <span className="truncate text-xs font-medium text-red-600">
62
+ <span className="truncate text-xs font-medium text-danger">
63
63
  {item.originalName}
64
64
  </span>
65
65
  {item.error && (
66
- <span className="text-xs text-red-500">{item.error}</span>
66
+ <span className="text-xs text-danger">{item.error}</span>
67
67
  )}
68
68
  </div>
69
69
  ))}
@@ -1,6 +1,5 @@
1
1
  import { formatDateTime } from "../../lib/timestamp";
2
- import { EditorModal } from "./EditorModal";
3
- import { Button } from "../shared/Button";
2
+ import { ConfirmDialog } from "../shared/ConfirmDialog";
4
3
 
5
4
  interface RestoreModalProps {
6
5
  isOpen: boolean;
@@ -12,19 +11,21 @@ interface RestoreModalProps {
12
11
 
13
12
  export function RestoreModal({ isOpen, onClose, date, onConfirm, isRestoring }: RestoreModalProps) {
14
13
  return (
15
- <EditorModal isOpen={isOpen} onClose={onClose} title="Restore this version?">
16
- <p className="mb-4 text-sm text-base-contrast-light">
17
- This will publish the content from {formatDateTime(date)} as a new update.
18
- Your current content will still be available in the history.
19
- </p>
20
- <div className="flex justify-end gap-3">
21
- <Button variant="secondary" size="md" onClick={onClose} disabled={isRestoring}>
22
- Cancel
23
- </Button>
24
- <Button variant="primary" size="md" onClick={onConfirm} disabled={isRestoring}>
25
- {isRestoring ? "Restoring..." : "Restore"}
26
- </Button>
27
- </div>
28
- </EditorModal>
14
+ <ConfirmDialog
15
+ isOpen={isOpen}
16
+ title="Restore this version?"
17
+ body={
18
+ <p className="text-sm text-base-contrast-light">
19
+ This will publish the content from {formatDateTime(date)} as a new update.
20
+ Your current content will still be available in the history.
21
+ </p>
22
+ }
23
+ confirmLabel="Restore"
24
+ tone="destructive"
25
+ busy={isRestoring}
26
+ busyLabel="Restoring…"
27
+ onConfirm={onConfirm}
28
+ onCancel={onClose}
29
+ />
29
30
  );
30
31
  }
@@ -42,7 +42,7 @@ export function SetPasswordForm({ reason }: Props) {
42
42
  return;
43
43
  }
44
44
  const data = await response.json().catch(() => ({}));
45
- setError(data.error || "Failed to set password");
45
+ setError(data.error || "Couldn't set password");
46
46
  return;
47
47
  }
48
48
 
@@ -82,14 +82,14 @@ export function SetPasswordForm({ reason }: Props) {
82
82
  autoComplete="new-password"
83
83
  />
84
84
 
85
- {error && <p className="text-sm text-red-600">{error}</p>}
85
+ {error && <p className="text-sm text-danger">{error}</p>}
86
86
 
87
87
  <Button
88
88
  type="submit"
89
89
  variant="primary"
90
90
  size="md"
91
91
  isLoading={loading}
92
- loadingLabel="Saving..."
92
+ loadingLabel="Saving…"
93
93
  className="w-full"
94
94
  >
95
95
  {buttonLabel}
@@ -1,5 +1,7 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import { Button } from "../shared/Button";
3
+ import { Input } from "../shared/Input";
4
+ import { Textarea } from "../shared/Textarea";
3
5
  import { SubTabs } from "../shared/SubTabs";
4
6
  import { AudienceChips } from "./AudienceChips";
5
7
  import ChatPanel from "../chat/ChatPanel";
@@ -90,32 +92,33 @@ export function SiteSettingsChatbot({ siteConfig, onSiteConfigChange, audiences,
90
92
  Show the chat widget to viewers
91
93
  </label>
92
94
 
93
- <div>
94
- <label htmlFor="chatbot-name" className="mb-1 block text-sm font-medium text-base-contrast">Assistant name</label>
95
- <input id="chatbot-name" aria-label="Assistant name" maxLength={60} value={chatbot.name}
96
- onChange={(e) => patch({ name: e.target.value })}
97
- placeholder={DEFAULT_CHATBOT_NAME}
98
- className="w-full rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast" />
99
- <p className="mt-1 text-xs text-base-contrast-light">Shown in the widget header. Leave blank for “{DEFAULT_CHATBOT_NAME}”. Audiences can override it below.</p>
100
- </div>
95
+ <Input
96
+ label="Assistant name"
97
+ maxLength={60}
98
+ value={chatbot.name}
99
+ onChange={(v) => patch({ name: v })}
100
+ placeholder={DEFAULT_CHATBOT_NAME}
101
+ hint={`Shown in the widget header. Leave blank for “${DEFAULT_CHATBOT_NAME}”. Audiences can override it below.`}
102
+ />
101
103
 
102
- <div>
103
- <label htmlFor="chatbot-thinking-phrases" className="mb-1 block text-sm font-medium text-base-contrast">Thinking phrases</label>
104
- <textarea id="chatbot-thinking-phrases" aria-label="Thinking phrases" rows={2}
105
- value={thinkingText}
106
- onChange={(e) => { setThinkingText(e.target.value); patch({ thinkingPhrases: parseThinkingPhrases(e.target.value) }); }}
107
- placeholder="Mixing the palette, Checking the guide, Consulting the brand book"
108
- className="w-full rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast" />
109
- <p className="mt-1 text-xs text-base-contrast-light">Comma-separated; one is shown at random while the assistant thinks, with “…” added automatically. Leave blank for “Thinking…”.</p>
110
- </div>
104
+ <Textarea
105
+ label="Thinking phrases"
106
+ rows={2}
107
+ value={thinkingText}
108
+ onChange={(v) => { setThinkingText(v); patch({ thinkingPhrases: parseThinkingPhrases(v) }); }}
109
+ placeholder="Mixing the palette, Checking the guide, Consulting the brand book"
110
+ hint="Comma-separated; one is shown at random while the assistant thinks, with “…” added automatically. Leave blank for “Thinking…”."
111
+ />
111
112
 
112
113
  <div>
113
- <label htmlFor="chatbot-system-prompt" className="mb-1 block text-sm font-medium text-base-contrast">System prompt</label>
114
- <textarea id="chatbot-system-prompt" aria-label="System prompt" rows={5} maxLength={8000}
114
+ <Textarea
115
+ label="System prompt"
116
+ rows={5}
117
+ maxLength={8000}
115
118
  value={chatbot.systemPrompt}
116
- onChange={(e) => patch({ systemPrompt: e.target.value })}
119
+ onChange={(v) => patch({ systemPrompt: v })}
117
120
  placeholder="Describe the brand's voice and how the assistant should behave — e.g. “Speak warmly and concisely; always reference our color names, never hex codes.”"
118
- className="w-full rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast" />
121
+ />
119
122
  <p className="text-right text-xs text-base-contrast-light">{chatbot.systemPrompt.length}/8000</p>
120
123
  </div>
121
124
  </div>
@@ -129,22 +132,22 @@ export function SiteSettingsChatbot({ siteConfig, onSiteConfigChange, audiences,
129
132
  <AudienceChips audiences={audiences} selected={chatbot.audiences} onToggle={(n) => patch({ audiences: toggleName(chatbot.audiences, n) })} />
130
133
  {chatbot.audiences.map((name) => (
131
134
  <div key={name} className="mt-2">
132
- <label htmlFor={`audience-name-${name}`} className="mb-1 block text-xs font-medium text-base-contrast">
133
- Assistant name for {name}
134
- </label>
135
- <input id={`audience-name-${name}`} aria-label={`Assistant name for ${name}`} maxLength={60}
135
+ <Input
136
+ label={`Assistant name for ${name}`}
137
+ maxLength={60}
136
138
  value={audienceNameValue(name)}
137
- onChange={(e) => patch({ audienceNames: { ...chatbot.audienceNames, [name]: e.target.value } })}
139
+ onChange={(v) => patch({ audienceNames: { ...chatbot.audienceNames, [name]: v } })}
138
140
  placeholder={resolveChatbotName(chatbot, null)}
139
- className="mb-1 w-full rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast" />
140
- <label htmlFor={`audience-prompt-${name}`} className="mb-1 block text-xs font-medium text-base-contrast">
141
- Additional guidance for {name}
142
- </label>
143
- <textarea id={`audience-prompt-${name}`} aria-label={`Guidance for ${name}`} rows={2} maxLength={8000}
141
+ className="mb-1"
142
+ />
143
+ <Textarea
144
+ label={`Additional guidance for ${name}`}
145
+ rows={2}
146
+ maxLength={8000}
144
147
  value={overlayValue(name)}
145
- onChange={(e) => patch({ audiencePrompts: { ...chatbot.audiencePrompts, [name]: e.target.value } })}
148
+ onChange={(v) => patch({ audiencePrompts: { ...chatbot.audiencePrompts, [name]: v } })}
146
149
  placeholder={`Only ${name} sees answers shaped by this — safe for ${name}-level info.`}
147
- className="w-full rounded border border-base-200 bg-base px-2 py-1 text-sm text-base-contrast" />
150
+ />
148
151
  </div>
149
152
  ))}
150
153
  </div>
@@ -160,27 +163,43 @@ export function SiteSettingsChatbot({ siteConfig, onSiteConfigChange, audiences,
160
163
  {chatbot.tasks.map((t, i) => (
161
164
  <div key={t.id} className="rounded border border-base-200 p-2">
162
165
  <div className="mb-1 flex items-center justify-between gap-2">
163
- <input aria-label={`Task ${t.id} label`} value={t.label} maxLength={60}
164
- onChange={(e) => patchTask(i, { label: e.target.value })}
165
- className="min-w-0 flex-1 rounded border border-base-200 bg-base px-2 py-1 text-sm" />
166
+ <Input
167
+ label={`Task ${t.id} label`}
168
+ hideLabel
169
+ value={t.label}
170
+ maxLength={60}
171
+ onChange={(v) => patchTask(i, { label: v })}
172
+ className="min-w-0 flex-1"
173
+ />
166
174
  <Button type="button" variant="destructive"
167
175
  onClick={() => patch({ tasks: chatbot.tasks.filter((_, idx) => idx !== i) })}>
168
176
  Remove
169
177
  </Button>
170
178
  </div>
171
- <textarea aria-label={`Task ${t.id} prompt`} rows={2} maxLength={4000} value={t.prompt}
172
- onChange={(e) => patchTask(i, { prompt: e.target.value })}
179
+ <Textarea
180
+ label={`Task ${t.id} prompt`}
181
+ hideLabel
182
+ rows={2}
183
+ maxLength={4000}
184
+ value={t.prompt}
185
+ onChange={(v) => patchTask(i, { prompt: v })}
173
186
  placeholder="Instructions for this task…"
174
- className="mb-1 w-full rounded border border-base-200 bg-base px-2 py-1 text-sm" />
187
+ className="mb-1"
188
+ />
175
189
  <AudienceChips audiences={audiences} selected={t.access} onToggle={(n) => patchTask(i, { access: toggleName(t.access, n) })} />
176
190
  </div>
177
191
  ))}
178
192
  </div>
179
193
  <div className="mt-2 flex gap-2">
180
- <input aria-label="New task label" value={newTaskLabel} maxLength={60}
181
- onChange={(e) => setNewTaskLabel(e.target.value)}
194
+ <Input
195
+ label="New task label"
196
+ hideLabel
197
+ value={newTaskLabel}
198
+ maxLength={60}
199
+ onChange={setNewTaskLabel}
182
200
  placeholder="e.g. Draft a social post"
183
- className="min-w-0 flex-1 rounded border border-base-200 bg-base px-2 py-1 text-sm" />
201
+ className="min-w-0 flex-1"
202
+ />
184
203
  <Button type="button" onClick={addTask}>Add task</Button>
185
204
  </div>
186
205
  </div>