@drawnagency/primitives 0.1.112 → 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 (491) 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/auth/types.d.ts +1 -0
  6. package/dist/auth/types.d.ts.map +1 -1
  7. package/dist/{chunk-GPPVYLEI.js → chunk-45FA7Z55.js} +1 -1
  8. package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
  9. package/dist/chunk-5GFACGSN.js +6 -0
  10. package/dist/chunk-5KSAS4VY.js +275 -0
  11. package/dist/{chunk-5KNXTMUC.js → chunk-7SAAJVDE.js} +408 -28
  12. package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
  13. package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
  14. package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
  15. package/dist/chunk-DIMDRBFK.js +11 -0
  16. package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
  17. package/dist/{chunk-VLPELTPI.js → chunk-IP2SEBAJ.js} +5 -1
  18. package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
  19. package/dist/chunk-JR24U7FJ.js +120 -0
  20. package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
  21. package/dist/{chunk-Z2LO4PSQ.js → chunk-N3G7DOU3.js} +609 -61
  22. package/dist/chunk-OAGJBCSH.js +67 -0
  23. package/dist/{chunk-VT3PYGVW.js → chunk-PLANHXS7.js} +191 -61
  24. package/dist/{chunk-OGGZ5AXT.js → chunk-PNSCDBU7.js} +38 -56
  25. package/dist/{chunk-HSXMOS5Q.js → chunk-PTY2RG2K.js} +5 -2
  26. package/dist/{chunk-EPWBPIV6.js → chunk-PZPGJZRG.js} +9 -8
  27. package/dist/{chunk-P3ZNCHW7.js → chunk-QHMKIODQ.js} +19 -5
  28. package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
  29. package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
  30. package/dist/chunk-VUYCRBJK.js +174 -0
  31. package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
  32. package/dist/{chunk-3SZNUCXI.js → chunk-Y5QECJX7.js} +223 -16
  33. package/dist/collab/rebase.d.ts +2 -1
  34. package/dist/collab/rebase.d.ts.map +1 -1
  35. package/dist/collab/rebase.js +20 -5
  36. package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
  37. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  38. package/dist/components/chat/ChatWidget.d.ts.map +1 -1
  39. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  40. package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
  41. package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
  42. package/dist/components/editor/DragHandle.d.ts +12 -2
  43. package/dist/components/editor/DragHandle.d.ts.map +1 -1
  44. package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
  45. package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
  46. package/dist/components/editor/NavGroupRow.d.ts +4 -1
  47. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  48. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  49. package/dist/components/editor/SectionWrapper.d.ts +1 -1
  50. package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
  51. package/dist/components/editor/SettingsForm.d.ts.map +1 -1
  52. package/dist/components/editor/TagIndicator.d.ts +15 -0
  53. package/dist/components/editor/TagIndicator.d.ts.map +1 -0
  54. package/dist/components/editor/index.js +148 -77
  55. package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
  56. package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
  57. package/dist/components/primitives/EditableList.d.ts.map +1 -1
  58. package/dist/components/primitives/HeadingSection.d.ts +4 -1
  59. package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
  60. package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
  61. package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
  62. package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
  63. package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
  64. package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
  65. package/dist/components/primitives/grid-drop.d.ts.map +1 -0
  66. package/dist/components/primitives/index.d.ts +1 -1
  67. package/dist/components/primitives/index.d.ts.map +1 -1
  68. package/dist/components/primitives/index.js +17 -154
  69. package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
  70. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
  71. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
  72. package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
  73. package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
  74. package/dist/components/sections/IconList/IconList.d.ts +2 -1
  75. package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
  76. package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
  77. package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
  78. package/dist/components/sections/IconList/index.d.ts +1 -0
  79. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  80. package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
  81. package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
  82. package/dist/components/sections/Media/index.d.ts +8 -0
  83. package/dist/components/sections/Media/index.d.ts.map +1 -1
  84. package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
  85. package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
  86. package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
  87. package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
  88. package/dist/components/sections/Reference/index.d.ts +9 -0
  89. package/dist/components/sections/Reference/index.d.ts.map +1 -0
  90. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
  91. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
  92. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
  93. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
  94. package/dist/components/sections/SectionSummary/index.d.ts +33 -0
  95. package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
  96. package/dist/components/sections/all-sections.d.ts +53 -0
  97. package/dist/components/sections/all-sections.d.ts.map +1 -1
  98. package/dist/components/sections/brand-guide.d.ts +41 -2
  99. package/dist/components/sections/brand-guide.d.ts.map +1 -1
  100. package/dist/components/sections/brand-guide.js +12 -10
  101. package/dist/components/sections/core-sections.d.ts +14 -0
  102. package/dist/components/sections/core-sections.d.ts.map +1 -1
  103. package/dist/components/sections/register-schemas.js +19 -17
  104. package/dist/components/sections/register.js +19 -17
  105. package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
  106. package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
  107. package/dist/components/shared/Button.d.ts +11 -3
  108. package/dist/components/shared/Button.d.ts.map +1 -1
  109. package/dist/components/shared/Checkbox.d.ts +6 -0
  110. package/dist/components/shared/Checkbox.d.ts.map +1 -1
  111. package/dist/components/shared/ConfirmDialog.d.ts +25 -0
  112. package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
  113. package/dist/components/shared/ConfirmInline.d.ts +25 -0
  114. package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
  115. package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
  116. package/dist/components/shared/Fab.d.ts +11 -2
  117. package/dist/components/shared/Fab.d.ts.map +1 -1
  118. package/dist/components/shared/FabStack.d.ts +22 -0
  119. package/dist/components/shared/FabStack.d.ts.map +1 -0
  120. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  121. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  122. package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
  123. package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
  124. package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
  125. package/dist/components/shared/InlineAlert.d.ts.map +1 -0
  126. package/dist/components/shared/Input.d.ts +10 -0
  127. package/dist/components/shared/Input.d.ts.map +1 -1
  128. package/dist/components/shared/Navigation.d.ts +1 -0
  129. package/dist/components/shared/Navigation.d.ts.map +1 -1
  130. package/dist/components/shared/Notice.d.ts +10 -0
  131. package/dist/components/shared/Notice.d.ts.map +1 -0
  132. package/dist/components/shared/Popover.d.ts.map +1 -1
  133. package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
  134. package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
  135. package/dist/components/shared/Select.d.ts +3 -2
  136. package/dist/components/shared/Select.d.ts.map +1 -1
  137. package/dist/components/shared/SplitButton.d.ts.map +1 -1
  138. package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
  139. package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
  140. package/dist/components/shared/Textarea.d.ts +7 -0
  141. package/dist/components/shared/Textarea.d.ts.map +1 -1
  142. package/dist/components/shared/ToolbarFrame.d.ts +17 -0
  143. package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
  144. package/dist/components/shared/copy.d.ts +13 -0
  145. package/dist/components/shared/copy.d.ts.map +1 -0
  146. package/dist/components/shared/icons.d.ts +0 -12
  147. package/dist/components/shared/icons.d.ts.map +1 -1
  148. package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
  149. package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
  150. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  151. package/dist/components/shell/BugReportFAB.d.ts +7 -1
  152. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  153. package/dist/components/shell/CredentialList.d.ts.map +1 -1
  154. package/dist/components/shell/DocInspector.d.ts.map +1 -1
  155. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
  156. package/dist/components/shell/EditorContext.d.ts +4 -0
  157. package/dist/components/shell/EditorContext.d.ts.map +1 -1
  158. package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
  159. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  160. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  161. package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
  162. package/dist/components/shell/MediaFolderTile.d.ts +4 -1
  163. package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
  164. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  165. package/dist/components/shell/RestoreModal.d.ts.map +1 -1
  166. package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
  167. package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
  168. package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
  169. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  170. package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
  171. package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
  172. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  173. package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
  174. package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
  175. package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
  176. package/dist/components/shell/reference-sources.d.ts +22 -0
  177. package/dist/components/shell/reference-sources.d.ts.map +1 -0
  178. package/dist/deck/index.d.ts +2 -2
  179. package/dist/deck/index.d.ts.map +1 -1
  180. package/dist/deck/index.js +1 -3
  181. package/dist/deck-builder/index.js +11 -18
  182. package/dist/document/index.d.ts +2 -2
  183. package/dist/document/index.d.ts.map +1 -1
  184. package/dist/hooks/useBlockDnd.d.ts +11 -0
  185. package/dist/hooks/useBlockDnd.d.ts.map +1 -1
  186. package/dist/hooks/useBuildStatus.d.ts +1 -1
  187. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  188. package/dist/hooks/useDocumentUploads.d.ts +1 -1
  189. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  190. package/dist/hooks/useEditorPersistence.d.ts +5 -1
  191. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  192. package/dist/hooks/useEditorPublish.d.ts +2 -2
  193. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  194. package/dist/hooks/useNotice.d.ts +19 -0
  195. package/dist/hooks/useNotice.d.ts.map +1 -0
  196. package/dist/hooks/useSortableNavRow.d.ts +11 -0
  197. package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
  198. package/dist/hooks/useSortableRow.d.ts +11 -0
  199. package/dist/hooks/useSortableRow.d.ts.map +1 -1
  200. package/dist/hooks/useStackedEscape.d.ts +32 -0
  201. package/dist/hooks/useStackedEscape.d.ts.map +1 -0
  202. package/dist/index.js +67 -49
  203. package/dist/lib/audience-secret.js +2 -2
  204. package/dist/lib/block-dnd.d.ts +5 -0
  205. package/dist/lib/block-dnd.d.ts.map +1 -1
  206. package/dist/lib/block-move.d.ts.map +1 -1
  207. package/dist/lib/brand-swatches.d.ts +12 -0
  208. package/dist/lib/brand-swatches.d.ts.map +1 -0
  209. package/dist/lib/container-ops.d.ts +3 -2
  210. package/dist/lib/container-ops.d.ts.map +1 -1
  211. package/dist/lib/dexie.d.ts.map +1 -1
  212. package/dist/lib/dexie.js +9 -1
  213. package/dist/lib/env.d.ts +4 -0
  214. package/dist/lib/env.d.ts.map +1 -1
  215. package/dist/lib/env.js +5 -3
  216. package/dist/lib/events.d.ts +1 -2
  217. package/dist/lib/events.d.ts.map +1 -1
  218. package/dist/lib/image-background.d.ts +8 -0
  219. package/dist/lib/image-background.d.ts.map +1 -0
  220. package/dist/lib/index-ops.js +3 -3
  221. package/dist/lib/index.d.ts +6 -4
  222. package/dist/lib/index.d.ts.map +1 -1
  223. package/dist/lib/index.js +29 -21
  224. package/dist/lib/loader.d.ts +21 -7
  225. package/dist/lib/loader.d.ts.map +1 -1
  226. package/dist/lib/nav-tree.d.ts +1 -0
  227. package/dist/lib/nav-tree.d.ts.map +1 -1
  228. package/dist/lib/nav.d.ts +38 -0
  229. package/dist/lib/nav.d.ts.map +1 -1
  230. package/dist/lib/platform-broker.d.ts +4 -2
  231. package/dist/lib/platform-broker.d.ts.map +1 -1
  232. package/dist/lib/platform-broker.js +21 -13
  233. package/dist/lib/reference-type.d.ts +2 -0
  234. package/dist/lib/reference-type.d.ts.map +1 -0
  235. package/dist/lib/reference-validation.d.ts +31 -0
  236. package/dist/lib/reference-validation.d.ts.map +1 -0
  237. package/dist/lib/reference-validation.js +39 -0
  238. package/dist/lib/references.d.ts +74 -0
  239. package/dist/lib/references.d.ts.map +1 -0
  240. package/dist/lib/registry.d.ts +35 -0
  241. package/dist/lib/registry.d.ts.map +1 -1
  242. package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
  243. package/dist/lib/safe-redirect.d.ts.map +1 -0
  244. package/dist/lib/tags.d.ts +58 -0
  245. package/dist/lib/tags.d.ts.map +1 -0
  246. package/dist/lib/theme-vars.d.ts +9 -0
  247. package/dist/lib/theme-vars.d.ts.map +1 -1
  248. package/dist/media/index.d.ts +1 -1
  249. package/dist/media/index.d.ts.map +1 -1
  250. package/dist/media/index.js +8 -4
  251. package/dist/media/resolve.d.ts +2 -0
  252. package/dist/media/resolve.d.ts.map +1 -1
  253. package/dist/media/utils.d.ts +2 -0
  254. package/dist/media/utils.d.ts.map +1 -1
  255. package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
  256. package/dist/media/video-poster.d.ts.map +1 -0
  257. package/dist/schemas/audience.js +2 -2
  258. package/dist/schemas/index.d.ts +1 -0
  259. package/dist/schemas/index.d.ts.map +1 -1
  260. package/dist/schemas/index.js +14 -8
  261. package/dist/schemas/shared.d.ts +26 -0
  262. package/dist/schemas/shared.d.ts.map +1 -1
  263. package/dist/schemas/site-config.d.ts +7 -0
  264. package/dist/schemas/site-config.d.ts.map +1 -1
  265. package/dist/schemas/tags.d.ts +27 -0
  266. package/dist/schemas/tags.d.ts.map +1 -0
  267. package/dist/storage/index.js +1 -1
  268. package/dist/types/database.d.ts +8 -0
  269. package/dist/types/database.d.ts.map +1 -1
  270. package/package.json +6 -1
  271. package/src/auth/cookies.ts +111 -0
  272. package/src/auth/types.ts +1 -0
  273. package/src/collab/rebase.ts +26 -2
  274. package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
  275. package/src/components/brandguide/ColorsEditable.tsx +1 -0
  276. package/src/components/chat/ChatPanel.tsx +2 -3
  277. package/src/components/chat/ChatWidget.tsx +7 -7
  278. package/src/components/docfile/DocFilePane.tsx +4 -12
  279. package/src/components/editor/ChildBlockWrapper.tsx +13 -19
  280. package/src/components/editor/ConflictDialog.tsx +27 -35
  281. package/src/components/editor/DeleteButton.tsx +2 -2
  282. package/src/components/editor/DragHandle.tsx +16 -3
  283. package/src/components/editor/DropEdgeIndicator.tsx +36 -10
  284. package/src/components/editor/InsertButton.tsx +2 -2
  285. package/src/components/editor/NavGroupRow.tsx +43 -14
  286. package/src/components/editor/PagesModal.tsx +99 -26
  287. package/src/components/editor/SectionWrapper.tsx +64 -23
  288. package/src/components/editor/SettingsButton.tsx +2 -2
  289. package/src/components/editor/SettingsForm.tsx +19 -2
  290. package/src/components/editor/StatusIndicator.tsx +4 -4
  291. package/src/components/editor/TagIndicator.tsx +80 -0
  292. package/src/components/primitives/DocumentDropZone.tsx +1 -1
  293. package/src/components/primitives/EditableGrid.tsx +15 -14
  294. package/src/components/primitives/EditableList.tsx +27 -74
  295. package/src/components/primitives/HeadingSection.tsx +5 -2
  296. package/src/components/primitives/ResolvedMedia.tsx +13 -0
  297. package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
  298. package/src/components/primitives/index.ts +1 -1
  299. package/src/components/primitives/useEditablePlainText.ts +5 -5
  300. package/src/components/sections/Button/CTAButton.tsx +3 -1
  301. package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
  302. package/src/components/sections/DoDontMedia/index.tsx +12 -3
  303. package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
  304. package/src/components/sections/IconList/IconList.tsx +70 -37
  305. package/src/components/sections/IconList/IconListSettings.tsx +55 -17
  306. package/src/components/sections/IconList/index.tsx +10 -3
  307. package/src/components/sections/LinkHeading/index.tsx +1 -1
  308. package/src/components/sections/Media/MediaBlock.tsx +13 -2
  309. package/src/components/sections/Media/index.tsx +12 -4
  310. package/src/components/sections/Reference/ReferenceList.tsx +214 -0
  311. package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
  312. package/src/components/sections/Reference/index.tsx +47 -0
  313. package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
  314. package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
  315. package/src/components/sections/SectionSummary/index.tsx +149 -0
  316. package/src/components/sections/SubHeading/index.tsx +1 -1
  317. package/src/components/sections/SubSubHeading/index.tsx +1 -1
  318. package/src/components/sections/brand-guide.ts +4 -3
  319. package/src/components/sections/core-sections.ts +2 -0
  320. package/src/components/shared/BrandSwatchesContext.ts +13 -0
  321. package/src/components/shared/Button.tsx +47 -34
  322. package/src/components/shared/Checkbox.tsx +21 -12
  323. package/src/components/shared/ConfirmDialog.tsx +87 -0
  324. package/src/components/shared/ConfirmInline.tsx +90 -0
  325. package/src/components/shared/ErrorBoundary.tsx +6 -18
  326. package/src/components/shared/Fab.tsx +15 -5
  327. package/src/components/shared/FabStack.tsx +28 -0
  328. package/src/components/shared/HistoryChangesModal.tsx +43 -41
  329. package/src/components/shared/HistoryPopover.tsx +7 -20
  330. package/src/components/shared/ImageBackgroundField.tsx +92 -0
  331. package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
  332. package/src/components/shared/Input.tsx +23 -7
  333. package/src/components/shared/Navigation.tsx +48 -35
  334. package/src/components/shared/Notice.tsx +59 -0
  335. package/src/components/shared/Popover.tsx +7 -11
  336. package/src/components/shared/ReferenceSourcesContext.ts +27 -0
  337. package/src/components/shared/Select.tsx +5 -2
  338. package/src/components/shared/SplitButton.tsx +11 -17
  339. package/src/components/shared/SummaryAnchorsContext.ts +11 -0
  340. package/src/components/shared/Textarea.tsx +17 -2
  341. package/src/components/shared/ToolbarFrame.tsx +28 -0
  342. package/src/components/shared/VideoSourceField.tsx +1 -1
  343. package/src/components/shared/copy.ts +18 -0
  344. package/src/components/shared/icons.tsx +1 -17
  345. package/src/components/shell/AudienceAddForm.tsx +2 -2
  346. package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
  347. package/src/components/shell/AudienceRow.tsx +22 -15
  348. package/src/components/shell/BugReportFAB.tsx +50 -40
  349. package/src/components/shell/CredentialList.tsx +33 -13
  350. package/src/components/shell/DocInspector.tsx +3 -12
  351. package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
  352. package/src/components/shell/EditorContext.tsx +7 -0
  353. package/src/components/shell/EditorLoginForm.tsx +26 -36
  354. package/src/components/shell/EditorModal.tsx +8 -10
  355. package/src/components/shell/EditorShell.tsx +499 -339
  356. package/src/components/shell/HistoryToolbar.tsx +24 -26
  357. package/src/components/shell/MediaFolderTile.tsx +8 -3
  358. package/src/components/shell/MediaLibraryModal.tsx +59 -60
  359. package/src/components/shell/ProcessingIndicator.tsx +2 -2
  360. package/src/components/shell/RestoreModal.tsx +17 -16
  361. package/src/components/shell/SetPasswordForm.tsx +3 -3
  362. package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
  363. package/src/components/shell/SiteSettingsDisplay.tsx +20 -21
  364. package/src/components/shell/SiteSettingsModal.tsx +24 -2
  365. package/src/components/shell/SiteSettingsTags.tsx +143 -0
  366. package/src/components/shell/SiteSettingsUsers.tsx +85 -28
  367. package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
  368. package/src/components/shell/ViewerLoginForm.tsx +5 -4
  369. package/src/components/shell/reference-sources.ts +36 -0
  370. package/src/deck/index.ts +2 -2
  371. package/src/document/index.ts +2 -2
  372. package/src/hooks/useBlockDnd.ts +11 -0
  373. package/src/hooks/useBuildStatus.ts +53 -6
  374. package/src/hooks/useDocumentUploads.ts +1 -1
  375. package/src/hooks/useEditorPersistence.ts +141 -35
  376. package/src/hooks/useEditorPublish.ts +18 -27
  377. package/src/hooks/useMediaPipeline.ts +1 -1
  378. package/src/hooks/useNotice.ts +45 -0
  379. package/src/hooks/useSortableNavRow.ts +11 -0
  380. package/src/hooks/useSortableRow.ts +22 -2
  381. package/src/hooks/useStackedEscape.ts +62 -0
  382. package/src/lib/block-dnd.ts +6 -1
  383. package/src/lib/block-move.ts +3 -0
  384. package/src/lib/brand-swatches.ts +32 -0
  385. package/src/lib/container-ops.ts +5 -3
  386. package/src/lib/dexie.ts +15 -1
  387. package/src/lib/env.ts +9 -0
  388. package/src/lib/events.ts +1 -2
  389. package/src/lib/image-background.ts +31 -0
  390. package/src/lib/index.ts +5 -4
  391. package/src/lib/loader.ts +54 -55
  392. package/src/lib/nav-tree.ts +71 -0
  393. package/src/lib/nav.ts +196 -36
  394. package/src/lib/platform-broker.ts +32 -14
  395. package/src/lib/reference-type.ts +3 -0
  396. package/src/lib/reference-validation.ts +69 -0
  397. package/src/lib/references.ts +130 -0
  398. package/src/lib/registry.ts +37 -0
  399. package/src/lib/tags.ts +148 -0
  400. package/src/lib/theme-vars.ts +23 -0
  401. package/src/media/index.ts +1 -1
  402. package/src/media/resolve.ts +3 -1
  403. package/src/media/utils.ts +18 -0
  404. package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
  405. package/src/schemas/index.ts +1 -0
  406. package/src/schemas/shared.ts +24 -1
  407. package/src/schemas/site-config.ts +9 -1
  408. package/src/schemas/tags.ts +33 -0
  409. package/src/storage/types.ts +1 -1
  410. package/src/types/database.ts +6 -0
  411. package/dist/chunk-BR4MIPTM.js +0 -138
  412. package/dist/chunk-DNY72JZN.js +0 -86
  413. package/dist/chunk-F2LYQPXV.js +0 -77
  414. package/dist/chunk-TALRVOGO.js +0 -128
  415. package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
  416. package/dist/components/primitives/gridDrop.d.ts.map +0 -1
  417. package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
  418. package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
  419. package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
  420. package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
  421. package/dist/hooks/index.d.ts +0 -9
  422. package/dist/hooks/index.d.ts.map +0 -1
  423. package/dist/lib/grid.d.ts +0 -2
  424. package/dist/lib/grid.d.ts.map +0 -1
  425. package/dist/lib/safeRedirect.d.ts.map +0 -1
  426. package/dist/media/videoPoster.d.ts.map +0 -1
  427. package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
  428. package/src/components/brandguide/Colors.d.ts.map +0 -1
  429. package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
  430. package/src/components/primitives/EditableGrid.d.ts.map +0 -1
  431. package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
  432. package/src/components/primitives/EditableRichText.d.ts.map +0 -1
  433. package/src/components/primitives/HeadingSection.d.ts.map +0 -1
  434. package/src/components/primitives/IconPicker.d.ts.map +0 -1
  435. package/src/components/primitives/LinkPopover.d.ts.map +0 -1
  436. package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
  437. package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
  438. package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
  439. package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
  440. package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
  441. package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
  442. package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
  443. package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
  444. package/src/components/sections/Button/index.d.ts.map +0 -1
  445. package/src/components/sections/Colors/index.d.ts.map +0 -1
  446. package/src/components/sections/IconList/IconList.d.ts.map +0 -1
  447. package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
  448. package/src/components/sections/IconList/index.d.ts.map +0 -1
  449. package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
  450. package/src/components/sections/Prose/Prose.d.ts.map +0 -1
  451. package/src/components/sections/Prose/index.d.ts.map +0 -1
  452. package/src/components/sections/SubHeading/index.d.ts.map +0 -1
  453. package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
  454. package/src/components/sections/register-schemas.d.ts.map +0 -1
  455. package/src/components/shared/Button.d.ts.map +0 -1
  456. package/src/components/shared/Checkbox.d.ts.map +0 -1
  457. package/src/components/shared/FormLabel.d.ts.map +0 -1
  458. package/src/components/shared/IconButton.d.ts.map +0 -1
  459. package/src/components/shared/Input.d.ts.map +0 -1
  460. package/src/components/shared/Select.d.ts.map +0 -1
  461. package/src/components/shared/icons.d.ts.map +0 -1
  462. package/src/components/shell/BuildStatusIndicator.tsx +0 -59
  463. package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
  464. package/src/hooks/index.ts +0 -8
  465. package/src/hooks/useResolvedMedia.d.ts.map +0 -1
  466. package/src/lib/cn.d.ts.map +0 -1
  467. package/src/lib/grid.d.ts.map +0 -1
  468. package/src/lib/grid.ts +0 -7
  469. package/src/lib/icons.d.ts.map +0 -1
  470. package/src/lib/loader.d.ts.map +0 -1
  471. package/src/lib/nav.d.ts.map +0 -1
  472. package/src/lib/registry.d.ts.map +0 -1
  473. package/src/lib/sanitize.d.ts.map +0 -1
  474. package/src/media/github.d.ts.map +0 -1
  475. package/src/media/index.d.ts.map +0 -1
  476. package/src/media/queue.d.ts.map +0 -1
  477. package/src/media/resolve.d.ts.map +0 -1
  478. package/src/media/types.d.ts.map +0 -1
  479. package/src/media/utils.d.ts.map +0 -1
  480. package/src/media/videoPoster.d.ts.map +0 -1
  481. package/src/schemas/auth.d.ts.map +0 -1
  482. package/src/schemas/media-grid-options.d.ts.map +0 -1
  483. package/src/schemas/media.d.ts.map +0 -1
  484. package/src/schemas/sections.d.ts.map +0 -1
  485. package/src/schemas/shared.d.ts.map +0 -1
  486. package/src/schemas/site-config.d.ts.map +0 -1
  487. /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
  488. /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
  489. /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
  490. /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
  491. /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
@@ -0,0 +1,148 @@
1
+ import type { TagEntry } from "../schemas/tags";
2
+ import type { SiteIndex } from "../schemas/site-config";
3
+
4
+ /**
5
+ * Repair the tag sidecar against the current section set.
6
+ *
7
+ * Total, pure, and idempotent — the same contract as reconcileNav, for the same
8
+ * reason: tags.json survives writers that do not know it exists, so it can name
9
+ * sections an older writer (or an agent) has since deleted, and the repair has
10
+ * to happen on read rather than by rejecting content. It is deliberately NOT a
11
+ * schema refinement: parse-rejecting content would leave the editor unable to
12
+ * load the site it needs to repair it.
13
+ *
14
+ * Drops assignments to sections absent from `sections`, duplicate section ids
15
+ * within a tag, duplicate tag ids (first wins), and tags with no usable id. A
16
+ * tag with no assignments left is KEPT — the registry outlives its sections.
17
+ * Every entry is rebuilt key by key, so the output always parses as a
18
+ * TagsFile and never shares structure with the input (the editor holds this in
19
+ * React state, where a shared array would let a later edit mutate prior state).
20
+ */
21
+ export function reconcileTags(entries: TagEntry[], sections: SiteIndex["sections"]): TagEntry[] {
22
+ const entryList = Array.isArray(entries) ? entries : [];
23
+ const validIds = new Set(sections && typeof sections === "object" ? Object.keys(sections) : []);
24
+
25
+ const seenTagIds = new Set<string>();
26
+ const result: TagEntry[] = [];
27
+ for (const entry of entryList) {
28
+ if (!entry || typeof entry !== "object") continue;
29
+ if (typeof entry.id !== "string" || entry.id === "" || seenTagIds.has(entry.id)) continue;
30
+ seenTagIds.add(entry.id);
31
+
32
+ const claimed = Array.isArray(entry.sectionIds) ? entry.sectionIds : [];
33
+ const sectionIds: string[] = [];
34
+ for (const id of claimed) {
35
+ if (typeof id === "string" && validIds.has(id) && !sectionIds.includes(id)) sectionIds.push(id);
36
+ }
37
+ result.push({ id: entry.id, label: typeof entry.label === "string" ? entry.label : "", sectionIds });
38
+ }
39
+ return result;
40
+ }
41
+
42
+ /**
43
+ * The ONLY sanctioned way to read the tags. Always reconciles, so callers never
44
+ * reason about whether index.tags is present, stale, or names deleted sections.
45
+ */
46
+ export function siteTags(index: SiteIndex): TagEntry[] {
47
+ return reconcileTags(index.tags ?? [], index.sections);
48
+ }
49
+
50
+ /** Display fallback for blank tag labels — mirrors groupDisplayLabel. */
51
+ export function tagDisplayLabel(label: string): string {
52
+ return label || "Untitled tag";
53
+ }
54
+
55
+ /** The tag already using this name (case- and whitespace-insensitive) — what
56
+ * an inline create reuses, and what the registry refuses to duplicate. */
57
+ export function findTagByLabel(tags: TagEntry[], label: string): TagEntry | null {
58
+ const wanted = label.trim().toLowerCase();
59
+ if (!wanted) return null;
60
+ return tags.find((t) => t.label.trim().toLowerCase() === wanted) ?? null;
61
+ }
62
+
63
+ export function addTag(index: SiteIndex, id: string, label: string, sectionId?: string): SiteIndex {
64
+ const tags = siteTags(index);
65
+ if (tags.some((t) => t.id === id)) return { ...index, tags };
66
+ return { ...index, tags: reconcileTags([...tags, { id, label, sectionIds: sectionId ? [sectionId] : [] }], index.sections) };
67
+ }
68
+
69
+ export function renameTag(index: SiteIndex, id: string, label: string): SiteIndex {
70
+ return { ...index, tags: siteTags(index).map((t) => (t.id === id ? { ...t, label } : t)) };
71
+ }
72
+
73
+ export function deleteTag(index: SiteIndex, id: string): SiteIndex {
74
+ return { ...index, tags: siteTags(index).filter((t) => t.id !== id) };
75
+ }
76
+
77
+ export function setSectionTagged(index: SiteIndex, sectionId: string, tagId: string, tagged: boolean): SiteIndex {
78
+ return {
79
+ ...index,
80
+ tags: siteTags(index).map((t) => {
81
+ if (t.id !== tagId) return t;
82
+ const without = t.sectionIds.filter((id) => id !== sectionId);
83
+ return { ...t, sectionIds: tagged ? [...without, sectionId] : without };
84
+ }),
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Three-way merge of the tag sidecar for the collab rebase.
90
+ *
91
+ * Nav's rebase rule is "the remote's persisted tree wins", which is safe there
92
+ * because grouping is edited rarely. Tags are edited from every section's
93
+ * chrome, so the same rule would silently drop unsaved tagging whenever a peer
94
+ * saved anything at all. Instead, local edits are diffed against the clean
95
+ * baseline (`base`) and replayed onto the remote:
96
+ * - a tag created locally is appended; one deleted locally is dropped;
97
+ * - a local rename wins, otherwise the remote label stands;
98
+ * - per (tag, section) pair, a local add or remove is replayed;
99
+ * - a tag the REMOTE deleted stays deleted, local assignments included —
100
+ * persisted state beats unsaved edits to a tag that no longer exists.
101
+ * With no baseline to diff against, the remote wins (nav's rule). A remote with
102
+ * no tags at all (an older server that does not attach the sidecar) leaves the
103
+ * local tags intact rather than wiping them. Inputs are never mutated; the
104
+ * result is not reconciled — readers do that through siteTags.
105
+ */
106
+ export function mergeTags(args: {
107
+ base: TagEntry[] | undefined;
108
+ local: TagEntry[] | undefined;
109
+ remote: TagEntry[] | undefined;
110
+ }): TagEntry[] | undefined {
111
+ const { base, local, remote } = args;
112
+ if (remote === undefined) return local?.map((t) => ({ ...t, sectionIds: [...t.sectionIds] }));
113
+ if (base === undefined || local === undefined) return remote.map((t) => ({ ...t, sectionIds: [...t.sectionIds] }));
114
+
115
+ // First occurrence wins, matching reconcileTags — `base` is an unreconciled
116
+ // server read, and a last-wins map would invent a diff against a duplicate.
117
+ const firstById = (tags: TagEntry[]) => {
118
+ const byId = new Map<string, TagEntry>();
119
+ for (const t of tags) if (!byId.has(t.id)) byId.set(t.id, t);
120
+ return byId;
121
+ };
122
+ const baseById = firstById(base);
123
+ const localById = firstById(local);
124
+ const remoteIds = new Set(remote.map((t) => t.id));
125
+
126
+ const result: TagEntry[] = [];
127
+ for (const r of remote) {
128
+ const b = baseById.get(r.id);
129
+ const l = localById.get(r.id);
130
+ if (b && !l) continue; // deleted locally
131
+ const members = [...r.sectionIds];
132
+ let label = r.label;
133
+ if (b && l) {
134
+ if (l.label !== b.label) label = l.label;
135
+ for (const id of l.sectionIds) if (!b.sectionIds.includes(id) && !members.includes(id)) members.push(id);
136
+ for (const id of b.sectionIds) {
137
+ if (l.sectionIds.includes(id)) continue;
138
+ const at = members.indexOf(id);
139
+ if (at !== -1) members.splice(at, 1);
140
+ }
141
+ }
142
+ result.push({ id: r.id, label, sectionIds: members });
143
+ }
144
+ for (const l of local) {
145
+ if (!remoteIds.has(l.id) && !baseById.has(l.id)) result.push({ ...l, sectionIds: [...l.sectionIds] });
146
+ }
147
+ return result;
148
+ }
@@ -1,5 +1,6 @@
1
1
  import type { SiteConfig } from "../schemas/site-config";
2
2
  import { suggestAccessibleOn } from "./contrast";
3
+ import { cornerRadiusValue } from "./corner-radius";
3
4
 
4
5
  /**
5
6
  * Computes the CSS value for the brand `--color-primary` / `--color-primary-contrast`
@@ -50,3 +51,25 @@ export function onPrimaryVarValue(c?: Partial<ThemeColorConfig> | null): string
50
51
  const dark = c?.primaryColorDark ? suggestAccessibleOn(c.primaryColorDark) : null;
51
52
  return lightDark(light, dark, c?.darkMode === "optional");
52
53
  }
54
+
55
+ /**
56
+ * The full inline `<html style>` string both `Layout.astro` and
57
+ * `LoginLayout.astro` set at SSR time — one assembly point for the 9 custom
58
+ * properties instead of the same template literal copied into both files.
59
+ * Byte-for-byte identical to what those files built inline before this
60
+ * existed; changing the property order or defaults here is a client-facing
61
+ * change to every site's `<html>` tag, not a refactor.
62
+ */
63
+ export function themeStyle(siteConfig?: SiteConfig | null): string {
64
+ return (
65
+ `--color-primary: ${primaryVarValue(siteConfig)}; ` +
66
+ `--color-primary-contrast: ${accentVarValue(siteConfig)}; ` +
67
+ `--color-on-primary: ${onPrimaryVarValue(siteConfig)}; ` +
68
+ `--font-heading: ${siteConfig?.headingFont ?? "system-ui"}, system-ui, sans-serif; ` +
69
+ `--font-body: ${siteConfig?.bodyFont ?? "system-ui"}, system-ui, sans-serif; ` +
70
+ `--heading-text-transform: ${siteConfig?.uppercaseHeadings !== false ? "uppercase" : "none"}; ` +
71
+ `--subheading-text-transform: ${siteConfig?.uppercaseSubheadings !== false ? "uppercase" : "none"}; ` +
72
+ `--nav-text-transform: ${siteConfig?.uppercaseNavHeadings !== false ? "uppercase" : "none"}; ` +
73
+ `--radius-outer: ${cornerRadiusValue(siteConfig?.cornerRadius)};`
74
+ );
75
+ }
@@ -5,7 +5,7 @@ export * from "./provider";
5
5
  export * from "./utils";
6
6
  export * from "./queue";
7
7
  export * from "./resolve";
8
- export { generateVideoPoster } from "./videoPoster";
8
+ export { generateVideoPoster } from "./video-poster";
9
9
  export { composePreviewImage, type PreviewImageInputs } from "./compose-preview";
10
10
 
11
11
  const MEDIA_KEY = Symbol.for("@drawnagency/primitives/media");
@@ -105,6 +105,7 @@ export interface ResolvedLogo {
105
105
  darkUrl: string | null;
106
106
  invertInDark: boolean;
107
107
  showInNav: boolean;
108
+ hideTitle: boolean;
108
109
  }
109
110
 
110
111
  /**
@@ -117,7 +118,7 @@ export interface ResolvedLogo {
117
118
  * both those tags resolve to `tag: "img"`.
118
119
  */
119
120
  export function resolveLogo(
120
- logo: { light: { imageId: string }; dark: { imageId: string } | null; invertInDark: boolean; showInNav: boolean } | null,
121
+ logo: { light: { imageId: string }; dark: { imageId: string } | null; invertInDark: boolean; showInNav: boolean; hideTitle: boolean } | null,
121
122
  manifest: MediaManifest,
122
123
  provider: MediaProvider,
123
124
  ): ResolvedLogo | null {
@@ -131,5 +132,6 @@ export function resolveLogo(
131
132
  darkUrl,
132
133
  invertInDark: logo.invertInDark,
133
134
  showInNav: logo.showInNav,
135
+ hideTitle: logo.hideTitle,
134
136
  };
135
137
  }
@@ -48,6 +48,24 @@ export function mimeToExt(mime: string): string {
48
48
  return MIME_TO_EXT[mime] ?? "bin";
49
49
  }
50
50
 
51
+ // Editor preview URL for a library item, matching what /api/media/[id] serves:
52
+ // SVGs carry kind "image" but have no webp variants, only original.svg; rasters
53
+ // get their smallest variant; animated and video items get their playable
54
+ // original (a <video> src, not a still). Null for a raster with no variants.
55
+ export function mediaThumbnailUrl(item: MediaItem): string | null {
56
+ if (item.mimeType === "image/svg+xml" || item.kind !== "image") {
57
+ return `/api/media/${item.id}/original.${mimeToExt(item.mimeType)}`;
58
+ }
59
+ if (item.variants.length === 0) return null;
60
+ const smallest = item.variants.reduce((a, b) => (a.width < b.width ? a : b));
61
+ return `/api/media/${item.id}/${smallest.width}.webp`;
62
+ }
63
+
64
+ // For <img>-only previews (cover, logo): null unless the item is a still image.
65
+ export function imageThumbnailUrl(item: MediaItem | undefined): string | null {
66
+ return item?.kind === "image" ? mediaThumbnailUrl(item) : null;
67
+ }
68
+
51
69
  export function displayFilenameExt(mime: string): string {
52
70
  const ext = MIME_TO_EXT[mime];
53
71
  return ext ? `.${ext}` : "";
@@ -26,7 +26,7 @@ export function generateVideoPoster(
26
26
  }, 10_000);
27
27
 
28
28
  video.addEventListener("error", () => {
29
- safeReject(new Error("Failed to load video for poster generation"));
29
+ safeReject(new Error("Couldn't load video for poster generation"));
30
30
  }, { once: true });
31
31
 
32
32
  video.muted = true;
@@ -56,7 +56,7 @@ export function generateVideoPoster(
56
56
  settled = true;
57
57
  cleanup();
58
58
  if (!posterBlob) {
59
- reject(new Error("Failed to create poster blob"));
59
+ reject(new Error("Couldn't create poster blob"));
60
60
  return;
61
61
  }
62
62
  resolve({ posterBlob, width: w, height: h, duration: video.duration });
@@ -2,6 +2,7 @@ export * from "./shared";
2
2
  export * from "./sections";
3
3
  export * from "./site-config";
4
4
  export * from "./nav";
5
+ export * from "./tags";
5
6
  export * from "./media";
6
7
  export * from "./audience";
7
8
  export * from "./media-grid-options";
@@ -38,7 +38,7 @@ const BaseMediaRef = z.object({
38
38
  .union([z.string(), z.array(z.string())])
39
39
  .optional()
40
40
  .describe("Optional caption: a single string, or multiple lines as an array of strings."),
41
- background: z.string().optional().describe("Optional CSS background color/value shown behind a transparent image."),
41
+ background: z.string().optional().describe("Legacy; not rendered. For a backdrop behind a media section's image, use the section's options.background."),
42
42
  invertFrom: z
43
43
  .string()
44
44
  .optional()
@@ -91,6 +91,29 @@ export const HexColorSchema = z
91
91
  .string()
92
92
  .regex(/^#[0-9a-fA-F]{6}$/, "must be a 6-digit hex color");
93
93
 
94
+ const ImageBackgroundSurfaceSchema = z.enum(["none", "light", "dark"]);
95
+ export type ImageBackgroundSurface = z.infer<typeof ImageBackgroundSurfaceSchema>;
96
+
97
+ /** Per-placement backdrop painted behind an image (e.g. a dark plate under a
98
+ * white transparent logo). Absent = no backdrop. */
99
+ export const ImageBackgroundSchema = z.discriminatedUnion("mode", [
100
+ z.object({
101
+ mode: z.literal("theme").describe("Pick a site surface separately for light and dark mode."),
102
+ light: ImageBackgroundSurfaceSchema.describe(
103
+ "Backdrop in light mode: 'none', the site's light surface, or its dark surface.",
104
+ ),
105
+ dark: ImageBackgroundSurfaceSchema.describe(
106
+ "Backdrop in dark mode: 'none', the site's light surface, or its dark surface.",
107
+ ),
108
+ }),
109
+ z.object({
110
+ mode: z.literal("custom").describe("Use one custom color in both modes."),
111
+ color: HexColorSchema.describe("One backdrop color for both light and dark mode, as a 6-digit hex."),
112
+ }),
113
+ ]);
114
+
115
+ export type ImageBackground = z.infer<typeof ImageBackgroundSchema>;
116
+
94
117
  // Font-family names are interpolated raw into the `style` attribute on <html>
95
118
  // (`--font-heading: ${headingFont}, ...`). Astro HTML-escapes the attribute, so
96
119
  // the residual risk is CSS-declaration injection via `;`/`{}`. Allow only the
@@ -7,6 +7,7 @@ import { CORNER_RADIUS_OPTIONS } from "../lib/corner-radius";
7
7
  // document options block onto PageSchema.
8
8
  import { documentOptionsSchema } from "../document/engine/settings";
9
9
  import type { NavEntry } from "./nav";
10
+ import type { TagEntry } from "./tags";
10
11
 
11
12
  export const StatusSchema = z.enum(["draft", "live", "archived", "published"]).transform(
12
13
  (val) => val === "published" ? "live" as const : val,
@@ -176,8 +177,12 @@ export const IndexSchema = RawIndexSchema.transform(normalizeRawIndex).pipe(Cano
176
177
  * index.json. It is optional because most SiteIndex values (tests, legacy
177
178
  * content, partial writes) have no nav — reads go through navEntries(), which
178
179
  * reconciles a missing nav into a flat one.
180
+ *
181
+ * `tags` follows the same rules for the src/content/tags.json sidecar; read it
182
+ * only through siteTags() (lib/tags.ts). Absent means "not loaded", which every
183
+ * writer treats as "leave tags.json alone" — not as "no tags".
179
184
  */
180
- export type SiteIndex = z.infer<typeof CanonicalIndexSchema> & { nav?: NavEntry[] };
185
+ export type SiteIndex = z.infer<typeof CanonicalIndexSchema> & { nav?: NavEntry[]; tags?: TagEntry[] };
181
186
 
182
187
  /** Parse + normalize any raw index (legacy or canonical) to the canonical shape. */
183
188
  export function normalizeSiteIndex(raw: unknown): SiteIndex {
@@ -292,6 +297,9 @@ export const SiteConfigSchema = z.object({
292
297
  dark: z.object({ imageId: z.string() }).nullable().default(null),
293
298
  invertInDark: z.boolean().default(false),
294
299
  showInNav: z.boolean().default(true),
300
+ // A nav logo stands in for the site name by default; the toggle is for
301
+ // wordmark-less logos that still need the name spelled out.
302
+ hideTitle: z.boolean().default(true),
295
303
  })
296
304
  .nullable()
297
305
  .default(null),
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * The site's section tags, persisted to `src/content/tags.json`.
5
+ *
6
+ * A sidecar for the same reason nav.json is (see schemas/nav.ts): an older
7
+ * writer re-serializes the Zod-parsed index and silently deletes any key it
8
+ * does not know, so tags must never be a key on index.json or a section file.
9
+ *
10
+ * Each tag owns its assignments (`sectionIds`), so deleting a tag removes it
11
+ * from every section by construction; a deleted section is pruned by
12
+ * `reconcileTags` (lib/tags.ts). Array order is the registry's display order.
13
+ */
14
+ export const TagEntrySchema = z.object({
15
+ id: z.string().min(1),
16
+ /** May be blank — agent-authored files can omit it; UI falls back to "Untitled tag". */
17
+ label: z.string().catch(""),
18
+ // Everything but `id` repairs rather than rejects. A rejected entry marks the
19
+ // read degraded, and a degraded tags.json refuses EVERY tags write until
20
+ // someone fixes the file by hand — far too heavy a price for one blank id in
21
+ // one tag's list, which reconcileTags would drop anyway.
22
+ sectionIds: z
23
+ .array(z.unknown())
24
+ .catch([])
25
+ .transform((ids) => ids.filter((id): id is string => typeof id === "string" && id !== "")),
26
+ });
27
+
28
+ export const TagsFileSchema = z.object({
29
+ tags: z.array(TagEntrySchema),
30
+ });
31
+
32
+ export type TagEntry = z.infer<typeof TagEntrySchema>;
33
+ export type TagsFile = z.infer<typeof TagsFileSchema>;
@@ -86,7 +86,7 @@ export interface StorageProvider {
86
86
  */
87
87
  export class IdempotencyLookupUnavailableError extends Error {
88
88
  constructor(override readonly cause?: unknown) {
89
- super("Could not search draft history for the idempotency key");
89
+ super("Couldn't search draft history for the idempotency key");
90
90
  this.name = "IdempotencyLookupUnavailableError";
91
91
  }
92
92
  }
@@ -1,3 +1,5 @@
1
+ // GENERATED by Supabase CLI — do not edit by hand.
2
+ // Regenerate with `pnpm generate-types` after every migration.
1
3
  export type Json =
2
4
  | string
3
5
  | number
@@ -847,6 +849,10 @@ export type Database = {
847
849
  Args: { p_site_id: string; p_user_id: string }
848
850
  Returns: undefined
849
851
  }
852
+ set_site_user_role: {
853
+ Args: { p_role: string; p_site_id: string; p_user_id: string }
854
+ Returns: undefined
855
+ }
850
856
  }
851
857
  Enums: {
852
858
  [_ in never]: never
@@ -1,138 +0,0 @@
1
- import {
2
- FormLabel,
3
- Input
4
- } from "./chunk-TALRVOGO.js";
5
- import {
6
- cn
7
- } from "./chunk-7EOSDFS3.js";
8
-
9
- // src/components/shared/PagesContext.tsx
10
- import { createContext, useContext } from "react";
11
- var PagesContext = createContext({ pages: [], getPageHeadings: () => [] });
12
- function usePages() {
13
- return useContext(PagesContext);
14
- }
15
-
16
- // src/components/shared/Select.tsx
17
- import { useId } from "react";
18
- import { ChevronDown } from "lucide-react";
19
- import { jsx, jsxs } from "react/jsx-runtime";
20
- function Select({
21
- label,
22
- value,
23
- onChange,
24
- options,
25
- disabled,
26
- className,
27
- selectClassName
28
- }) {
29
- const id = useId();
30
- return /* @__PURE__ */ jsxs("div", { className, children: [
31
- label && /* @__PURE__ */ jsx(FormLabel, { htmlFor: id, children: label }),
32
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
33
- /* @__PURE__ */ jsx(
34
- "select",
35
- {
36
- id,
37
- value,
38
- onChange: (e) => onChange(e.target.value),
39
- disabled,
40
- className: cn(
41
- "w-full appearance-none rounded border border-base-200 bg-base py-2 pr-8 pl-3 text-sm text-base-contrast",
42
- "focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast",
43
- disabled && "cursor-not-allowed opacity-50",
44
- selectClassName
45
- ),
46
- children: options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
47
- }
48
- ),
49
- /* @__PURE__ */ jsx(
50
- ChevronDown,
51
- {
52
- size: 14,
53
- className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 text-base-contrast-light"
54
- }
55
- )
56
- ] })
57
- ] });
58
- }
59
-
60
- // src/components/shared/LinkField.tsx
61
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
62
- var TARGET_OPTIONS = [
63
- { label: "Same tab (_self)", value: "_self" },
64
- { label: "New tab (_blank)", value: "_blank" }
65
- ];
66
- function LinkField({ label, value, onChange }) {
67
- const { pages, getPageHeadings } = usePages();
68
- const isInternal = value.kind === "internal";
69
- function setMode(kind) {
70
- if (kind === value.kind) return;
71
- onChange(kind === "external" ? { kind: "external", href: "", target: value.target } : { kind: "internal", pageId: "", anchorSectionId: null, target: "_self" });
72
- }
73
- const pageId = isInternal ? value.pageId : "";
74
- const headings = pageId ? getPageHeadings(pageId) : [];
75
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
76
- /* @__PURE__ */ jsx2(FormLabel, { children: label }),
77
- /* @__PURE__ */ jsx2("div", { className: "flex gap-2", role: "tablist", children: ["internal", "external"].map((kind) => /* @__PURE__ */ jsx2(
78
- "button",
79
- {
80
- type: "button",
81
- role: "tab",
82
- "aria-selected": value.kind === kind,
83
- onClick: () => setMode(kind),
84
- className: cn(
85
- "cursor-pointer rounded border px-3 py-1 text-sm capitalize",
86
- value.kind === kind ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
87
- ),
88
- children: kind === "external" ? "External URL" : "Internal page"
89
- },
90
- kind
91
- )) }),
92
- value.kind === "external" ? /* @__PURE__ */ jsx2(
93
- Input,
94
- {
95
- label: "URL",
96
- value: value.href,
97
- placeholder: "https://...",
98
- onChange: (href) => onChange({ kind: "external", href, target: value.target })
99
- }
100
- ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
101
- /* @__PURE__ */ jsx2(
102
- Select,
103
- {
104
- label: "Page",
105
- value: value.pageId,
106
- options: [{ label: "Select a page\u2026", value: "" }, ...pages.map((p) => ({ label: p.title, value: p.id }))],
107
- onChange: (pid) => onChange({ kind: "internal", pageId: pid, anchorSectionId: null, target: value.target })
108
- }
109
- ),
110
- /* @__PURE__ */ jsx2(
111
- Select,
112
- {
113
- label: "Section",
114
- value: value.anchorSectionId ?? "",
115
- disabled: !pageId,
116
- options: [{ label: "None (top of page)", value: "" }, ...headings.map((h) => ({ label: h.label, value: h.id }))],
117
- onChange: (anchor) => onChange({ kind: "internal", pageId, anchorSectionId: anchor || null, target: value.target })
118
- }
119
- )
120
- ] }),
121
- value.kind === "external" && /* @__PURE__ */ jsx2(
122
- Select,
123
- {
124
- label: "Opens in",
125
- value: value.target,
126
- options: TARGET_OPTIONS,
127
- onChange: (t) => onChange({ ...value, target: t })
128
- }
129
- )
130
- ] });
131
- }
132
-
133
- export {
134
- PagesContext,
135
- usePages,
136
- Select,
137
- LinkField
138
- };
@@ -1,86 +0,0 @@
1
- import {
2
- getContainerChildren
3
- } from "./chunk-CXZ5YJG4.js";
4
- import {
5
- getSection
6
- } from "./chunk-FTPETWXE.js";
7
-
8
- // src/lib/nav.ts
9
- function toSectionId(text) {
10
- const slug = text.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/^-+|-+$/g, "");
11
- if (slug) return slug;
12
- let hash = 0;
13
- for (let i = 0; i < text.length; i++) {
14
- hash = (hash << 5) - hash + text.charCodeAt(i) | 0;
15
- }
16
- return `section-${Math.abs(hash).toString(36)}`;
17
- }
18
- function flattenForNav(sections) {
19
- const flat = [];
20
- const walk = (loaded) => {
21
- flat.push(loaded);
22
- for (const child of getContainerChildren(loaded.section)) {
23
- walk({ section: child, meta: loaded.meta });
24
- }
25
- };
26
- sections.forEach(walk);
27
- return flat;
28
- }
29
- function generateNavLinks(sections, registry) {
30
- const nav = [];
31
- let currentParent = null;
32
- let currentChild = null;
33
- const lookupRole = (type) => {
34
- const def = registry ? registry.getSection(type) : getSection(type);
35
- return def?.navRole;
36
- };
37
- for (const { section, meta } of flattenForNav(sections)) {
38
- const content = section.content;
39
- if (!content.heading) continue;
40
- const role = lookupRole(section.type);
41
- if (!role) continue;
42
- if (role === "h1") {
43
- if (content.excludeFromNav) {
44
- currentParent = null;
45
- currentChild = null;
46
- continue;
47
- }
48
- currentParent = {
49
- href: `#${toSectionId(content.heading)}`,
50
- label: content.heading,
51
- status: meta.status,
52
- children: []
53
- };
54
- currentChild = null;
55
- nav.push(currentParent);
56
- } else if (role === "h2") {
57
- if (content.excludeFromNav) {
58
- currentChild = null;
59
- continue;
60
- }
61
- if (!currentParent) continue;
62
- currentChild = {
63
- href: `#${toSectionId(content.heading)}`,
64
- label: content.heading,
65
- status: meta.status,
66
- children: []
67
- };
68
- currentParent.children.push(currentChild);
69
- } else if (role === "h3") {
70
- if (content.excludeFromNav) continue;
71
- if (!currentChild) continue;
72
- currentChild.children.push({
73
- href: `#${toSectionId(content.heading)}`,
74
- label: content.heading,
75
- status: meta.status,
76
- children: []
77
- });
78
- }
79
- }
80
- return nav;
81
- }
82
-
83
- export {
84
- toSectionId,
85
- generateNavLinks
86
- };