@drawnagency/primitives 0.1.113 → 0.1.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/cookies.d.ts +39 -0
  3. package/dist/auth/cookies.d.ts.map +1 -1
  4. package/dist/auth/index.js +3 -3
  5. package/dist/{chunk-GPPVYLEI.js → chunk-45FA7Z55.js} +1 -1
  6. package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
  7. package/dist/chunk-5GFACGSN.js +6 -0
  8. package/dist/chunk-5KSAS4VY.js +275 -0
  9. package/dist/{chunk-Z7W3DQTR.js → chunk-7SAAJVDE.js} +408 -28
  10. package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
  11. package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
  12. package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
  13. package/dist/chunk-DIMDRBFK.js +11 -0
  14. package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
  15. package/dist/{chunk-NHN2LSIU.js → chunk-IP2SEBAJ.js} +5 -1
  16. package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
  17. package/dist/chunk-JR24U7FJ.js +120 -0
  18. package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
  19. package/dist/{chunk-KR2MHTNJ.js → chunk-N3G7DOU3.js} +609 -61
  20. package/dist/chunk-OAGJBCSH.js +67 -0
  21. package/dist/{chunk-6BZ2KNTP.js → chunk-PLANHXS7.js} +191 -61
  22. package/dist/{chunk-VWWY5TL5.js → chunk-PNSCDBU7.js} +38 -56
  23. package/dist/{chunk-AHALSCQH.js → chunk-PTY2RG2K.js} +1 -1
  24. package/dist/{chunk-BDFTMGCL.js → chunk-PZPGJZRG.js} +9 -8
  25. package/dist/{chunk-FRE2CCLV.js → chunk-QHMKIODQ.js} +17 -4
  26. package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
  27. package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
  28. package/dist/chunk-VUYCRBJK.js +174 -0
  29. package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
  30. package/dist/{chunk-DS4GCYV2.js → chunk-Y5QECJX7.js} +223 -16
  31. package/dist/collab/rebase.d.ts +2 -1
  32. package/dist/collab/rebase.d.ts.map +1 -1
  33. package/dist/collab/rebase.js +20 -5
  34. package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
  35. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  36. package/dist/components/chat/ChatWidget.d.ts.map +1 -1
  37. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  38. package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
  39. package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
  40. package/dist/components/editor/DragHandle.d.ts +12 -2
  41. package/dist/components/editor/DragHandle.d.ts.map +1 -1
  42. package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
  43. package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
  44. package/dist/components/editor/NavGroupRow.d.ts +4 -1
  45. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  46. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  47. package/dist/components/editor/SectionWrapper.d.ts +1 -1
  48. package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
  49. package/dist/components/editor/SettingsForm.d.ts.map +1 -1
  50. package/dist/components/editor/TagIndicator.d.ts +15 -0
  51. package/dist/components/editor/TagIndicator.d.ts.map +1 -0
  52. package/dist/components/editor/index.js +148 -77
  53. package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
  54. package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
  55. package/dist/components/primitives/EditableList.d.ts.map +1 -1
  56. package/dist/components/primitives/HeadingSection.d.ts +4 -1
  57. package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
  58. package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
  59. package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
  60. package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
  61. package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
  62. package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
  63. package/dist/components/primitives/grid-drop.d.ts.map +1 -0
  64. package/dist/components/primitives/index.d.ts +1 -1
  65. package/dist/components/primitives/index.d.ts.map +1 -1
  66. package/dist/components/primitives/index.js +17 -154
  67. package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
  68. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
  69. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
  70. package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
  71. package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
  72. package/dist/components/sections/IconList/IconList.d.ts +2 -1
  73. package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
  74. package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
  75. package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
  76. package/dist/components/sections/IconList/index.d.ts +1 -0
  77. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  78. package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
  79. package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
  80. package/dist/components/sections/Media/index.d.ts +8 -0
  81. package/dist/components/sections/Media/index.d.ts.map +1 -1
  82. package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
  83. package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
  84. package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
  85. package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
  86. package/dist/components/sections/Reference/index.d.ts +9 -0
  87. package/dist/components/sections/Reference/index.d.ts.map +1 -0
  88. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
  89. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
  90. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
  91. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
  92. package/dist/components/sections/SectionSummary/index.d.ts +33 -0
  93. package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
  94. package/dist/components/sections/all-sections.d.ts +53 -0
  95. package/dist/components/sections/all-sections.d.ts.map +1 -1
  96. package/dist/components/sections/brand-guide.d.ts +41 -2
  97. package/dist/components/sections/brand-guide.d.ts.map +1 -1
  98. package/dist/components/sections/brand-guide.js +12 -10
  99. package/dist/components/sections/core-sections.d.ts +14 -0
  100. package/dist/components/sections/core-sections.d.ts.map +1 -1
  101. package/dist/components/sections/register-schemas.js +19 -17
  102. package/dist/components/sections/register.js +19 -17
  103. package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
  104. package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
  105. package/dist/components/shared/Button.d.ts +11 -3
  106. package/dist/components/shared/Button.d.ts.map +1 -1
  107. package/dist/components/shared/Checkbox.d.ts +6 -0
  108. package/dist/components/shared/Checkbox.d.ts.map +1 -1
  109. package/dist/components/shared/ConfirmDialog.d.ts +25 -0
  110. package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
  111. package/dist/components/shared/ConfirmInline.d.ts +25 -0
  112. package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
  113. package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
  114. package/dist/components/shared/Fab.d.ts +11 -2
  115. package/dist/components/shared/Fab.d.ts.map +1 -1
  116. package/dist/components/shared/FabStack.d.ts +22 -0
  117. package/dist/components/shared/FabStack.d.ts.map +1 -0
  118. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  119. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  120. package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
  121. package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
  122. package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
  123. package/dist/components/shared/InlineAlert.d.ts.map +1 -0
  124. package/dist/components/shared/Input.d.ts +10 -0
  125. package/dist/components/shared/Input.d.ts.map +1 -1
  126. package/dist/components/shared/Navigation.d.ts.map +1 -1
  127. package/dist/components/shared/Notice.d.ts +10 -0
  128. package/dist/components/shared/Notice.d.ts.map +1 -0
  129. package/dist/components/shared/Popover.d.ts.map +1 -1
  130. package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
  131. package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
  132. package/dist/components/shared/Select.d.ts +3 -2
  133. package/dist/components/shared/Select.d.ts.map +1 -1
  134. package/dist/components/shared/SplitButton.d.ts.map +1 -1
  135. package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
  136. package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
  137. package/dist/components/shared/Textarea.d.ts +7 -0
  138. package/dist/components/shared/Textarea.d.ts.map +1 -1
  139. package/dist/components/shared/ToolbarFrame.d.ts +17 -0
  140. package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
  141. package/dist/components/shared/copy.d.ts +13 -0
  142. package/dist/components/shared/copy.d.ts.map +1 -0
  143. package/dist/components/shared/icons.d.ts +0 -12
  144. package/dist/components/shared/icons.d.ts.map +1 -1
  145. package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
  146. package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
  147. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  148. package/dist/components/shell/BugReportFAB.d.ts +7 -1
  149. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  150. package/dist/components/shell/CredentialList.d.ts.map +1 -1
  151. package/dist/components/shell/DocInspector.d.ts.map +1 -1
  152. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
  153. package/dist/components/shell/EditorContext.d.ts +4 -0
  154. package/dist/components/shell/EditorContext.d.ts.map +1 -1
  155. package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
  156. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  157. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  158. package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
  159. package/dist/components/shell/MediaFolderTile.d.ts +4 -1
  160. package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
  161. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  162. package/dist/components/shell/RestoreModal.d.ts.map +1 -1
  163. package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
  164. package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
  165. package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
  166. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  167. package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
  168. package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
  169. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  170. package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
  171. package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
  172. package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
  173. package/dist/components/shell/reference-sources.d.ts +22 -0
  174. package/dist/components/shell/reference-sources.d.ts.map +1 -0
  175. package/dist/deck/index.d.ts +2 -2
  176. package/dist/deck/index.d.ts.map +1 -1
  177. package/dist/deck/index.js +1 -3
  178. package/dist/deck-builder/index.js +11 -18
  179. package/dist/document/index.d.ts +2 -2
  180. package/dist/document/index.d.ts.map +1 -1
  181. package/dist/hooks/useBlockDnd.d.ts +11 -0
  182. package/dist/hooks/useBlockDnd.d.ts.map +1 -1
  183. package/dist/hooks/useBuildStatus.d.ts +1 -1
  184. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  185. package/dist/hooks/useDocumentUploads.d.ts +1 -1
  186. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  187. package/dist/hooks/useEditorPersistence.d.ts +5 -1
  188. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  189. package/dist/hooks/useEditorPublish.d.ts +2 -2
  190. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  191. package/dist/hooks/useNotice.d.ts +19 -0
  192. package/dist/hooks/useNotice.d.ts.map +1 -0
  193. package/dist/hooks/useSortableNavRow.d.ts +11 -0
  194. package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
  195. package/dist/hooks/useSortableRow.d.ts +11 -0
  196. package/dist/hooks/useSortableRow.d.ts.map +1 -1
  197. package/dist/hooks/useStackedEscape.d.ts +32 -0
  198. package/dist/hooks/useStackedEscape.d.ts.map +1 -0
  199. package/dist/index.js +67 -49
  200. package/dist/lib/audience-secret.js +2 -2
  201. package/dist/lib/block-dnd.d.ts +5 -0
  202. package/dist/lib/block-dnd.d.ts.map +1 -1
  203. package/dist/lib/block-move.d.ts.map +1 -1
  204. package/dist/lib/brand-swatches.d.ts +12 -0
  205. package/dist/lib/brand-swatches.d.ts.map +1 -0
  206. package/dist/lib/container-ops.d.ts +3 -2
  207. package/dist/lib/container-ops.d.ts.map +1 -1
  208. package/dist/lib/dexie.d.ts.map +1 -1
  209. package/dist/lib/dexie.js +9 -1
  210. package/dist/lib/env.d.ts +4 -0
  211. package/dist/lib/env.d.ts.map +1 -1
  212. package/dist/lib/env.js +5 -3
  213. package/dist/lib/events.d.ts +1 -2
  214. package/dist/lib/events.d.ts.map +1 -1
  215. package/dist/lib/image-background.d.ts +8 -0
  216. package/dist/lib/image-background.d.ts.map +1 -0
  217. package/dist/lib/index-ops.js +3 -3
  218. package/dist/lib/index.d.ts +6 -4
  219. package/dist/lib/index.d.ts.map +1 -1
  220. package/dist/lib/index.js +29 -21
  221. package/dist/lib/loader.d.ts +21 -7
  222. package/dist/lib/loader.d.ts.map +1 -1
  223. package/dist/lib/nav-tree.d.ts +1 -0
  224. package/dist/lib/nav-tree.d.ts.map +1 -1
  225. package/dist/lib/nav.d.ts +38 -0
  226. package/dist/lib/nav.d.ts.map +1 -1
  227. package/dist/lib/platform-broker.d.ts +4 -2
  228. package/dist/lib/platform-broker.d.ts.map +1 -1
  229. package/dist/lib/platform-broker.js +21 -13
  230. package/dist/lib/reference-type.d.ts +2 -0
  231. package/dist/lib/reference-type.d.ts.map +1 -0
  232. package/dist/lib/reference-validation.d.ts +31 -0
  233. package/dist/lib/reference-validation.d.ts.map +1 -0
  234. package/dist/lib/reference-validation.js +39 -0
  235. package/dist/lib/references.d.ts +74 -0
  236. package/dist/lib/references.d.ts.map +1 -0
  237. package/dist/lib/registry.d.ts +35 -0
  238. package/dist/lib/registry.d.ts.map +1 -1
  239. package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
  240. package/dist/lib/safe-redirect.d.ts.map +1 -0
  241. package/dist/lib/tags.d.ts +58 -0
  242. package/dist/lib/tags.d.ts.map +1 -0
  243. package/dist/lib/theme-vars.d.ts +9 -0
  244. package/dist/lib/theme-vars.d.ts.map +1 -1
  245. package/dist/media/index.d.ts +1 -1
  246. package/dist/media/index.d.ts.map +1 -1
  247. package/dist/media/index.js +8 -4
  248. package/dist/media/utils.d.ts +2 -0
  249. package/dist/media/utils.d.ts.map +1 -1
  250. package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
  251. package/dist/media/video-poster.d.ts.map +1 -0
  252. package/dist/schemas/audience.js +2 -2
  253. package/dist/schemas/index.d.ts +1 -0
  254. package/dist/schemas/index.d.ts.map +1 -1
  255. package/dist/schemas/index.js +14 -8
  256. package/dist/schemas/shared.d.ts +26 -0
  257. package/dist/schemas/shared.d.ts.map +1 -1
  258. package/dist/schemas/site-config.d.ts +6 -0
  259. package/dist/schemas/site-config.d.ts.map +1 -1
  260. package/dist/schemas/tags.d.ts +27 -0
  261. package/dist/schemas/tags.d.ts.map +1 -0
  262. package/dist/storage/index.js +1 -1
  263. package/dist/types/database.d.ts.map +1 -1
  264. package/package.json +6 -1
  265. package/src/auth/cookies.ts +111 -0
  266. package/src/collab/rebase.ts +26 -2
  267. package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
  268. package/src/components/brandguide/ColorsEditable.tsx +1 -0
  269. package/src/components/chat/ChatPanel.tsx +2 -3
  270. package/src/components/chat/ChatWidget.tsx +2 -3
  271. package/src/components/docfile/DocFilePane.tsx +4 -12
  272. package/src/components/editor/ChildBlockWrapper.tsx +13 -19
  273. package/src/components/editor/ConflictDialog.tsx +27 -35
  274. package/src/components/editor/DeleteButton.tsx +2 -2
  275. package/src/components/editor/DragHandle.tsx +16 -3
  276. package/src/components/editor/DropEdgeIndicator.tsx +36 -10
  277. package/src/components/editor/InsertButton.tsx +2 -2
  278. package/src/components/editor/NavGroupRow.tsx +43 -14
  279. package/src/components/editor/PagesModal.tsx +99 -26
  280. package/src/components/editor/SectionWrapper.tsx +64 -23
  281. package/src/components/editor/SettingsButton.tsx +2 -2
  282. package/src/components/editor/SettingsForm.tsx +19 -2
  283. package/src/components/editor/StatusIndicator.tsx +4 -4
  284. package/src/components/editor/TagIndicator.tsx +80 -0
  285. package/src/components/primitives/DocumentDropZone.tsx +1 -1
  286. package/src/components/primitives/EditableGrid.tsx +15 -14
  287. package/src/components/primitives/EditableList.tsx +27 -74
  288. package/src/components/primitives/HeadingSection.tsx +5 -2
  289. package/src/components/primitives/ResolvedMedia.tsx +13 -0
  290. package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
  291. package/src/components/primitives/index.ts +1 -1
  292. package/src/components/primitives/useEditablePlainText.ts +5 -5
  293. package/src/components/sections/Button/CTAButton.tsx +3 -1
  294. package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
  295. package/src/components/sections/DoDontMedia/index.tsx +12 -3
  296. package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
  297. package/src/components/sections/IconList/IconList.tsx +70 -37
  298. package/src/components/sections/IconList/IconListSettings.tsx +55 -17
  299. package/src/components/sections/IconList/index.tsx +10 -3
  300. package/src/components/sections/LinkHeading/index.tsx +1 -1
  301. package/src/components/sections/Media/MediaBlock.tsx +13 -2
  302. package/src/components/sections/Media/index.tsx +12 -4
  303. package/src/components/sections/Reference/ReferenceList.tsx +214 -0
  304. package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
  305. package/src/components/sections/Reference/index.tsx +47 -0
  306. package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
  307. package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
  308. package/src/components/sections/SectionSummary/index.tsx +149 -0
  309. package/src/components/sections/SubHeading/index.tsx +1 -1
  310. package/src/components/sections/SubSubHeading/index.tsx +1 -1
  311. package/src/components/sections/brand-guide.ts +4 -3
  312. package/src/components/sections/core-sections.ts +2 -0
  313. package/src/components/shared/BrandSwatchesContext.ts +13 -0
  314. package/src/components/shared/Button.tsx +47 -34
  315. package/src/components/shared/Checkbox.tsx +21 -12
  316. package/src/components/shared/ConfirmDialog.tsx +87 -0
  317. package/src/components/shared/ConfirmInline.tsx +90 -0
  318. package/src/components/shared/ErrorBoundary.tsx +6 -18
  319. package/src/components/shared/Fab.tsx +15 -5
  320. package/src/components/shared/FabStack.tsx +28 -0
  321. package/src/components/shared/HistoryChangesModal.tsx +43 -41
  322. package/src/components/shared/HistoryPopover.tsx +7 -20
  323. package/src/components/shared/ImageBackgroundField.tsx +92 -0
  324. package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
  325. package/src/components/shared/Input.tsx +23 -7
  326. package/src/components/shared/Navigation.tsx +22 -17
  327. package/src/components/shared/Notice.tsx +59 -0
  328. package/src/components/shared/Popover.tsx +7 -11
  329. package/src/components/shared/ReferenceSourcesContext.ts +27 -0
  330. package/src/components/shared/Select.tsx +5 -2
  331. package/src/components/shared/SplitButton.tsx +11 -17
  332. package/src/components/shared/SummaryAnchorsContext.ts +11 -0
  333. package/src/components/shared/Textarea.tsx +17 -2
  334. package/src/components/shared/ToolbarFrame.tsx +28 -0
  335. package/src/components/shared/VideoSourceField.tsx +1 -1
  336. package/src/components/shared/copy.ts +18 -0
  337. package/src/components/shared/icons.tsx +1 -17
  338. package/src/components/shell/AudienceAddForm.tsx +2 -2
  339. package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
  340. package/src/components/shell/AudienceRow.tsx +22 -15
  341. package/src/components/shell/BugReportFAB.tsx +50 -40
  342. package/src/components/shell/CredentialList.tsx +33 -13
  343. package/src/components/shell/DocInspector.tsx +3 -12
  344. package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
  345. package/src/components/shell/EditorContext.tsx +7 -0
  346. package/src/components/shell/EditorLoginForm.tsx +26 -36
  347. package/src/components/shell/EditorModal.tsx +8 -10
  348. package/src/components/shell/EditorShell.tsx +499 -339
  349. package/src/components/shell/HistoryToolbar.tsx +24 -26
  350. package/src/components/shell/MediaFolderTile.tsx +8 -3
  351. package/src/components/shell/MediaLibraryModal.tsx +59 -60
  352. package/src/components/shell/ProcessingIndicator.tsx +2 -2
  353. package/src/components/shell/RestoreModal.tsx +17 -16
  354. package/src/components/shell/SetPasswordForm.tsx +3 -3
  355. package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
  356. package/src/components/shell/SiteSettingsDisplay.tsx +10 -20
  357. package/src/components/shell/SiteSettingsModal.tsx +24 -2
  358. package/src/components/shell/SiteSettingsTags.tsx +143 -0
  359. package/src/components/shell/SiteSettingsUsers.tsx +36 -26
  360. package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
  361. package/src/components/shell/ViewerLoginForm.tsx +5 -4
  362. package/src/components/shell/reference-sources.ts +36 -0
  363. package/src/deck/index.ts +2 -2
  364. package/src/document/index.ts +2 -2
  365. package/src/hooks/useBlockDnd.ts +11 -0
  366. package/src/hooks/useBuildStatus.ts +53 -6
  367. package/src/hooks/useDocumentUploads.ts +1 -1
  368. package/src/hooks/useEditorPersistence.ts +141 -35
  369. package/src/hooks/useEditorPublish.ts +18 -27
  370. package/src/hooks/useMediaPipeline.ts +1 -1
  371. package/src/hooks/useNotice.ts +45 -0
  372. package/src/hooks/useSortableNavRow.ts +11 -0
  373. package/src/hooks/useSortableRow.ts +22 -2
  374. package/src/hooks/useStackedEscape.ts +62 -0
  375. package/src/lib/block-dnd.ts +6 -1
  376. package/src/lib/block-move.ts +3 -0
  377. package/src/lib/brand-swatches.ts +32 -0
  378. package/src/lib/container-ops.ts +5 -3
  379. package/src/lib/dexie.ts +15 -1
  380. package/src/lib/env.ts +9 -0
  381. package/src/lib/events.ts +1 -2
  382. package/src/lib/image-background.ts +31 -0
  383. package/src/lib/index.ts +5 -4
  384. package/src/lib/loader.ts +54 -55
  385. package/src/lib/nav-tree.ts +71 -0
  386. package/src/lib/nav.ts +196 -36
  387. package/src/lib/platform-broker.ts +32 -14
  388. package/src/lib/reference-type.ts +3 -0
  389. package/src/lib/reference-validation.ts +69 -0
  390. package/src/lib/references.ts +130 -0
  391. package/src/lib/registry.ts +37 -0
  392. package/src/lib/tags.ts +148 -0
  393. package/src/lib/theme-vars.ts +23 -0
  394. package/src/media/index.ts +1 -1
  395. package/src/media/utils.ts +18 -0
  396. package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
  397. package/src/schemas/index.ts +1 -0
  398. package/src/schemas/shared.ts +24 -1
  399. package/src/schemas/site-config.ts +6 -1
  400. package/src/schemas/tags.ts +33 -0
  401. package/src/storage/types.ts +1 -1
  402. package/src/types/database.ts +2 -0
  403. package/dist/chunk-DNY72JZN.js +0 -86
  404. package/dist/chunk-F2LYQPXV.js +0 -77
  405. package/dist/chunk-JH762VUH.js +0 -128
  406. package/dist/chunk-K7DYZXVU.js +0 -138
  407. package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
  408. package/dist/components/primitives/gridDrop.d.ts.map +0 -1
  409. package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
  410. package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
  411. package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
  412. package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
  413. package/dist/hooks/index.d.ts +0 -9
  414. package/dist/hooks/index.d.ts.map +0 -1
  415. package/dist/lib/grid.d.ts +0 -2
  416. package/dist/lib/grid.d.ts.map +0 -1
  417. package/dist/lib/safeRedirect.d.ts.map +0 -1
  418. package/dist/media/videoPoster.d.ts.map +0 -1
  419. package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
  420. package/src/components/brandguide/Colors.d.ts.map +0 -1
  421. package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
  422. package/src/components/primitives/EditableGrid.d.ts.map +0 -1
  423. package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
  424. package/src/components/primitives/EditableRichText.d.ts.map +0 -1
  425. package/src/components/primitives/HeadingSection.d.ts.map +0 -1
  426. package/src/components/primitives/IconPicker.d.ts.map +0 -1
  427. package/src/components/primitives/LinkPopover.d.ts.map +0 -1
  428. package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
  429. package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
  430. package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
  431. package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
  432. package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
  433. package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
  434. package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
  435. package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
  436. package/src/components/sections/Button/index.d.ts.map +0 -1
  437. package/src/components/sections/Colors/index.d.ts.map +0 -1
  438. package/src/components/sections/IconList/IconList.d.ts.map +0 -1
  439. package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
  440. package/src/components/sections/IconList/index.d.ts.map +0 -1
  441. package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
  442. package/src/components/sections/Prose/Prose.d.ts.map +0 -1
  443. package/src/components/sections/Prose/index.d.ts.map +0 -1
  444. package/src/components/sections/SubHeading/index.d.ts.map +0 -1
  445. package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
  446. package/src/components/sections/register-schemas.d.ts.map +0 -1
  447. package/src/components/shared/Button.d.ts.map +0 -1
  448. package/src/components/shared/Checkbox.d.ts.map +0 -1
  449. package/src/components/shared/FormLabel.d.ts.map +0 -1
  450. package/src/components/shared/IconButton.d.ts.map +0 -1
  451. package/src/components/shared/Input.d.ts.map +0 -1
  452. package/src/components/shared/Select.d.ts.map +0 -1
  453. package/src/components/shared/icons.d.ts.map +0 -1
  454. package/src/components/shell/BuildStatusIndicator.tsx +0 -59
  455. package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
  456. package/src/hooks/index.ts +0 -8
  457. package/src/hooks/useResolvedMedia.d.ts.map +0 -1
  458. package/src/lib/cn.d.ts.map +0 -1
  459. package/src/lib/grid.d.ts.map +0 -1
  460. package/src/lib/grid.ts +0 -7
  461. package/src/lib/icons.d.ts.map +0 -1
  462. package/src/lib/loader.d.ts.map +0 -1
  463. package/src/lib/nav.d.ts.map +0 -1
  464. package/src/lib/registry.d.ts.map +0 -1
  465. package/src/lib/sanitize.d.ts.map +0 -1
  466. package/src/media/github.d.ts.map +0 -1
  467. package/src/media/index.d.ts.map +0 -1
  468. package/src/media/queue.d.ts.map +0 -1
  469. package/src/media/resolve.d.ts.map +0 -1
  470. package/src/media/types.d.ts.map +0 -1
  471. package/src/media/utils.d.ts.map +0 -1
  472. package/src/media/videoPoster.d.ts.map +0 -1
  473. package/src/schemas/auth.d.ts.map +0 -1
  474. package/src/schemas/media-grid-options.d.ts.map +0 -1
  475. package/src/schemas/media.d.ts.map +0 -1
  476. package/src/schemas/sections.d.ts.map +0 -1
  477. package/src/schemas/shared.d.ts.map +0 -1
  478. package/src/schemas/site-config.d.ts.map +0 -1
  479. /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
  480. /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
  481. /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
  482. /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
  483. /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
@@ -0,0 +1,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");
@@ -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 {
@@ -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
@@ -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
- };
@@ -1,77 +0,0 @@
1
- import {
2
- cn
3
- } from "./chunk-7EOSDFS3.js";
4
-
5
- // src/components/shared/Checkbox.tsx
6
- import { useId } from "react";
7
- import { Check } from "lucide-react";
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
- function Checkbox({
10
- checked,
11
- onChange,
12
- label,
13
- description,
14
- disabled,
15
- className,
16
- startAdornment,
17
- align = "start"
18
- }) {
19
- const id = useId();
20
- return /* @__PURE__ */ jsxs(
21
- "label",
22
- {
23
- htmlFor: id,
24
- className: cn(
25
- "flex cursor-pointer gap-3 select-none hover:opacity-80",
26
- align === "start" ? "items-start" : "items-center",
27
- disabled && "cursor-not-allowed opacity-50",
28
- className
29
- ),
30
- children: [
31
- /* @__PURE__ */ jsxs(
32
- "span",
33
- {
34
- className: cn(
35
- "relative flex h-5 w-5 shrink-0 items-center justify-center",
36
- align === "start" && "mt-0.5"
37
- ),
38
- children: [
39
- /* @__PURE__ */ jsx(
40
- "input",
41
- {
42
- id,
43
- type: "checkbox",
44
- checked,
45
- disabled,
46
- onChange: (e) => onChange(e.target.checked),
47
- className: "sr-only"
48
- }
49
- ),
50
- /* @__PURE__ */ jsx(
51
- "span",
52
- {
53
- "aria-hidden": "true",
54
- className: cn(
55
- "flex h-5 w-5 items-center justify-center rounded border transition-colors",
56
- checked ? "border-primary bg-primary text-primary-contrast" : "border-base-300 bg-base hover:border-primary",
57
- disabled && "pointer-events-none"
58
- ),
59
- children: checked && /* @__PURE__ */ jsx(Check, { size: 14, strokeWidth: 3 })
60
- }
61
- )
62
- ]
63
- }
64
- ),
65
- startAdornment,
66
- /* @__PURE__ */ jsxs("div", { className: "text-sm", children: [
67
- /* @__PURE__ */ jsx("span", { className: "font-medium text-base-contrast", children: label }),
68
- description && /* @__PURE__ */ jsx("span", { className: "block text-base-contrast-light", children: description })
69
- ] })
70
- ]
71
- }
72
- );
73
- }
74
-
75
- export {
76
- Checkbox
77
- };
@@ -1,128 +0,0 @@
1
- import {
2
- getMediaProvider
3
- } from "./chunk-FRE2CCLV.js";
4
- import {
5
- cn
6
- } from "./chunk-7EOSDFS3.js";
7
-
8
- // src/components/shell/MediaLibraryContext.tsx
9
- import { createContext, useContext } from "react";
10
- var MediaLibraryContext = createContext(null);
11
- function useMediaLibrary() {
12
- return useContext(MediaLibraryContext);
13
- }
14
-
15
- // src/hooks/useResolvedMedia.ts
16
- import { useMemo } from "react";
17
- function useResolvedMedia(imageId) {
18
- const ctx = useMediaLibrary();
19
- return useMemo(() => {
20
- if (!imageId || !ctx) {
21
- return { src: void 0, srcset: void 0, poster: void 0, alt: "", kind: "image" };
22
- }
23
- const { manifest, pendingItems, pendingLocalUrls, siteConfig } = ctx;
24
- const sizes = siteConfig?.media?.sizes ?? [640, 1080, 1920];
25
- const manifestItem = manifest.images[imageId];
26
- const pendingItem = pendingItems.find((i) => i.id === imageId);
27
- const item = manifestItem ?? pendingItem;
28
- const alt = item?.alt ?? "";
29
- const kind = item?.kind ?? "image";
30
- const width = item?.width;
31
- const height = item?.height;
32
- const localUrl = pendingLocalUrls[imageId];
33
- if (localUrl) {
34
- return { src: localUrl, srcset: void 0, poster: void 0, alt, kind, width, height };
35
- }
36
- if (manifestItem) {
37
- const provider = getMediaProvider();
38
- const resolved = provider.resolve(manifestItem, sizes);
39
- if (resolved && resolved.tag === "img") {
40
- return {
41
- src: resolved.src,
42
- srcset: "srcSet" in resolved ? resolved.srcSet : void 0,
43
- poster: void 0,
44
- alt,
45
- kind,
46
- width: resolved.width,
47
- height: resolved.height
48
- };
49
- }
50
- if (resolved && resolved.tag === "video") {
51
- return { src: resolved.src, srcset: void 0, poster: resolved.poster, alt, kind, width: resolved.width, height: resolved.height };
52
- }
53
- }
54
- return { src: void 0, srcset: void 0, poster: void 0, alt, kind, width, height };
55
- }, [imageId, ctx]);
56
- }
57
-
58
- // src/components/shared/icons.tsx
59
- import { GripVertical, Plus, Trash2, X, Settings } from "lucide-react";
60
- import { GripVertical as GripVertical2, Plus as Plus2, Trash2 as Trash22, X as X2, Settings as Settings2 } from "lucide-react";
61
- import { jsx } from "react/jsx-runtime";
62
- function DragHandle({ size = 16 }) {
63
- return /* @__PURE__ */ jsx(GripVertical, { size });
64
- }
65
- function AddIcon({ size = 14 }) {
66
- return /* @__PURE__ */ jsx(Plus, { size });
67
- }
68
- function DeleteIcon({ size = 14 }) {
69
- return /* @__PURE__ */ jsx(Trash2, { size });
70
- }
71
- function SettingsIcon({ size = 14 }) {
72
- return /* @__PURE__ */ jsx(Settings, { size });
73
- }
74
-
75
- // src/components/shared/FormLabel.tsx
76
- import { jsx as jsx2 } from "react/jsx-runtime";
77
- function FormLabel({ htmlFor, children, className }) {
78
- return /* @__PURE__ */ jsx2(
79
- "label",
80
- {
81
- htmlFor,
82
- className: cn("mb-1.5 block text-sm font-medium text-base-contrast", className),
83
- children
84
- }
85
- );
86
- }
87
-
88
- // src/components/shared/Input.tsx
89
- import { forwardRef, useId } from "react";
90
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
91
- var Input = forwardRef(function Input2({ label, value, onChange, type = "text", className, disabled, error, ...rest }, ref) {
92
- const id = useId();
93
- const errorId = `${id}-error`;
94
- return /* @__PURE__ */ jsxs("div", { className, children: [
95
- /* @__PURE__ */ jsx3(FormLabel, { htmlFor: id, children: label }),
96
- /* @__PURE__ */ jsx3(
97
- "input",
98
- {
99
- ref,
100
- id,
101
- type,
102
- value,
103
- onChange: (e) => onChange(e.target.value),
104
- disabled,
105
- "aria-invalid": error ? true : void 0,
106
- "aria-describedby": error ? errorId : void 0,
107
- className: cn(
108
- "w-full rounded border bg-base px-3 py-2 text-sm text-base-contrast focus:outline-none focus:ring-1",
109
- error ? "border-red-600 focus:border-red-600 focus:ring-red-600" : "border-base-200 focus:border-base-contrast focus:ring-base-contrast",
110
- disabled && "cursor-not-allowed opacity-50"
111
- ),
112
- ...rest
113
- }
114
- ),
115
- error && /* @__PURE__ */ jsx3("p", { id: errorId, className: "mt-1 text-xs text-red-600", children: error })
116
- ] });
117
- });
118
-
119
- export {
120
- useMediaLibrary,
121
- useResolvedMedia,
122
- DragHandle,
123
- AddIcon,
124
- DeleteIcon,
125
- SettingsIcon,
126
- FormLabel,
127
- Input
128
- };