@drawnagency/primitives 0.1.113 → 0.1.115

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 (534) 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-4WQ36ZP7.js +83 -0
  6. package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
  7. package/dist/chunk-5GFACGSN.js +6 -0
  8. package/dist/{chunk-AHALSCQH.js → chunk-67P34WNW.js} +76 -131
  9. package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
  10. package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
  11. package/dist/chunk-APIJPTFG.js +64 -0
  12. package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
  13. package/dist/chunk-CDBURDPX.js +90 -0
  14. package/dist/chunk-DFKTF3CH.js +0 -0
  15. package/dist/chunk-DIMDRBFK.js +11 -0
  16. package/dist/chunk-DJABADOO.js +131 -0
  17. package/dist/{chunk-NHN2LSIU.js → chunk-DJOGPSRU.js} +31 -68
  18. package/dist/{chunk-KR2MHTNJ.js → chunk-FHTKSELX.js} +610 -62
  19. package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
  20. package/dist/chunk-GNF6KFQ7.js +18 -0
  21. package/dist/{chunk-FRE2CCLV.js → chunk-HHNPSKPT.js} +5 -79
  22. package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
  23. package/dist/chunk-JR24U7FJ.js +120 -0
  24. package/dist/{chunk-BDFTMGCL.js → chunk-JXATNKLV.js} +11 -10
  25. package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
  26. package/dist/{chunk-6BZ2KNTP.js → chunk-NX7TFHA4.js} +195 -65
  27. package/dist/{chunk-VWWY5TL5.js → chunk-O37AV27P.js} +14 -75
  28. package/dist/chunk-RIITGTV3.js +275 -0
  29. package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
  30. package/dist/chunk-S7QRHUWO.js +8 -0
  31. package/dist/{chunk-Z7W3DQTR.js → chunk-T26HAKW3.js} +424 -42
  32. package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
  33. package/dist/{chunk-GPPVYLEI.js → chunk-UUUSJDIG.js} +1 -1
  34. package/dist/chunk-VY3IFGE3.js +70 -0
  35. package/dist/chunk-WYOFQHKI.js +176 -0
  36. package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
  37. package/dist/{chunk-DS4GCYV2.js → chunk-YV3YSZEB.js} +223 -16
  38. package/dist/collab/rebase.d.ts +2 -1
  39. package/dist/collab/rebase.d.ts.map +1 -1
  40. package/dist/collab/rebase.js +24 -9
  41. package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
  42. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  43. package/dist/components/chat/ChatWidget.d.ts.map +1 -1
  44. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  45. package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
  46. package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
  47. package/dist/components/editor/DragHandle.d.ts +12 -2
  48. package/dist/components/editor/DragHandle.d.ts.map +1 -1
  49. package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
  50. package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
  51. package/dist/components/editor/NavGroupRow.d.ts +4 -1
  52. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  53. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  54. package/dist/components/editor/SectionWrapper.d.ts +1 -1
  55. package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
  56. package/dist/components/editor/SettingsForm.d.ts.map +1 -1
  57. package/dist/components/editor/TagIndicator.d.ts +15 -0
  58. package/dist/components/editor/TagIndicator.d.ts.map +1 -0
  59. package/dist/components/editor/index.js +150 -79
  60. package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
  61. package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
  62. package/dist/components/primitives/EditableList.d.ts.map +1 -1
  63. package/dist/components/primitives/HeadingSection.d.ts +4 -1
  64. package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
  65. package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
  66. package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
  67. package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
  68. package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
  69. package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
  70. package/dist/components/primitives/grid-drop.d.ts.map +1 -0
  71. package/dist/components/primitives/index.d.ts +1 -1
  72. package/dist/components/primitives/index.d.ts.map +1 -1
  73. package/dist/components/primitives/index.js +22 -154
  74. package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
  75. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
  76. package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
  77. package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
  78. package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
  79. package/dist/components/sections/IconList/IconList.d.ts +2 -1
  80. package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
  81. package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
  82. package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
  83. package/dist/components/sections/IconList/index.d.ts +1 -0
  84. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  85. package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
  86. package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
  87. package/dist/components/sections/Media/index.d.ts +8 -0
  88. package/dist/components/sections/Media/index.d.ts.map +1 -1
  89. package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
  90. package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
  91. package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
  92. package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
  93. package/dist/components/sections/Reference/index.d.ts +9 -0
  94. package/dist/components/sections/Reference/index.d.ts.map +1 -0
  95. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
  96. package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
  97. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
  98. package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
  99. package/dist/components/sections/SectionSummary/index.d.ts +33 -0
  100. package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
  101. package/dist/components/sections/all-sections.d.ts +53 -0
  102. package/dist/components/sections/all-sections.d.ts.map +1 -1
  103. package/dist/components/sections/brand-guide.d.ts +41 -2
  104. package/dist/components/sections/brand-guide.d.ts.map +1 -1
  105. package/dist/components/sections/brand-guide.js +17 -10
  106. package/dist/components/sections/core-sections.d.ts +14 -0
  107. package/dist/components/sections/core-sections.d.ts.map +1 -1
  108. package/dist/components/sections/register-schemas.js +25 -18
  109. package/dist/components/sections/register.js +25 -18
  110. package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
  111. package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
  112. package/dist/components/shared/Button.d.ts +11 -3
  113. package/dist/components/shared/Button.d.ts.map +1 -1
  114. package/dist/components/shared/Checkbox.d.ts +6 -0
  115. package/dist/components/shared/Checkbox.d.ts.map +1 -1
  116. package/dist/components/shared/ConfirmDialog.d.ts +25 -0
  117. package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
  118. package/dist/components/shared/ConfirmInline.d.ts +25 -0
  119. package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
  120. package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
  121. package/dist/components/shared/Fab.d.ts +11 -2
  122. package/dist/components/shared/Fab.d.ts.map +1 -1
  123. package/dist/components/shared/FabStack.d.ts +22 -0
  124. package/dist/components/shared/FabStack.d.ts.map +1 -0
  125. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  126. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  127. package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
  128. package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
  129. package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
  130. package/dist/components/shared/InlineAlert.d.ts.map +1 -0
  131. package/dist/components/shared/Input.d.ts +10 -0
  132. package/dist/components/shared/Input.d.ts.map +1 -1
  133. package/dist/components/shared/Navigation.d.ts.map +1 -1
  134. package/dist/components/shared/Notice.d.ts +10 -0
  135. package/dist/components/shared/Notice.d.ts.map +1 -0
  136. package/dist/components/shared/Popover.d.ts.map +1 -1
  137. package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
  138. package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
  139. package/dist/components/shared/Select.d.ts +3 -2
  140. package/dist/components/shared/Select.d.ts.map +1 -1
  141. package/dist/components/shared/SplitButton.d.ts.map +1 -1
  142. package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
  143. package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
  144. package/dist/components/shared/Textarea.d.ts +7 -0
  145. package/dist/components/shared/Textarea.d.ts.map +1 -1
  146. package/dist/components/shared/ToolbarFrame.d.ts +17 -0
  147. package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
  148. package/dist/components/shared/copy.d.ts +13 -0
  149. package/dist/components/shared/copy.d.ts.map +1 -0
  150. package/dist/components/shared/icons.d.ts +0 -12
  151. package/dist/components/shared/icons.d.ts.map +1 -1
  152. package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
  153. package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
  154. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  155. package/dist/components/shell/BugReportFAB.d.ts +7 -1
  156. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  157. package/dist/components/shell/CredentialList.d.ts.map +1 -1
  158. package/dist/components/shell/DocInspector.d.ts.map +1 -1
  159. package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
  160. package/dist/components/shell/EditorContext.d.ts +4 -0
  161. package/dist/components/shell/EditorContext.d.ts.map +1 -1
  162. package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
  163. package/dist/components/shell/EditorModal.d.ts.map +1 -1
  164. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  165. package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
  166. package/dist/components/shell/MediaFolderTile.d.ts +4 -1
  167. package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
  168. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  169. package/dist/components/shell/RestoreModal.d.ts.map +1 -1
  170. package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
  171. package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
  172. package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
  173. package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
  174. package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
  175. package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
  176. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  177. package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
  178. package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
  179. package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
  180. package/dist/components/shell/reference-sources.d.ts +22 -0
  181. package/dist/components/shell/reference-sources.d.ts.map +1 -0
  182. package/dist/deck/index.d.ts +2 -2
  183. package/dist/deck/index.d.ts.map +1 -1
  184. package/dist/deck/index.js +1 -3
  185. package/dist/deck-builder/index.js +10 -17
  186. package/dist/document/index.d.ts +2 -2
  187. package/dist/document/index.d.ts.map +1 -1
  188. package/dist/hooks/useBlockDnd.d.ts +11 -0
  189. package/dist/hooks/useBlockDnd.d.ts.map +1 -1
  190. package/dist/hooks/useBuildStatus.d.ts +1 -1
  191. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  192. package/dist/hooks/useDocumentUploads.d.ts +1 -1
  193. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  194. package/dist/hooks/useEditorPersistence.d.ts +5 -1
  195. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  196. package/dist/hooks/useEditorPublish.d.ts +6 -3
  197. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  198. package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
  199. package/dist/hooks/useNotice.d.ts +19 -0
  200. package/dist/hooks/useNotice.d.ts.map +1 -0
  201. package/dist/hooks/useSortableNavRow.d.ts +11 -0
  202. package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
  203. package/dist/hooks/useSortableRow.d.ts +11 -0
  204. package/dist/hooks/useSortableRow.d.ts.map +1 -1
  205. package/dist/hooks/useStackedEscape.d.ts +32 -0
  206. package/dist/hooks/useStackedEscape.d.ts.map +1 -0
  207. package/dist/index.js +95 -48
  208. package/dist/lib/audience-secret.js +2 -2
  209. package/dist/lib/block-dnd.d.ts +5 -0
  210. package/dist/lib/block-dnd.d.ts.map +1 -1
  211. package/dist/lib/block-move.d.ts.map +1 -1
  212. package/dist/lib/brand-swatches.d.ts +12 -0
  213. package/dist/lib/brand-swatches.d.ts.map +1 -0
  214. package/dist/lib/container-ops.d.ts +3 -2
  215. package/dist/lib/container-ops.d.ts.map +1 -1
  216. package/dist/lib/dexie.d.ts +7 -1
  217. package/dist/lib/dexie.d.ts.map +1 -1
  218. package/dist/lib/dexie.js +12 -3
  219. package/dist/lib/env.d.ts +4 -0
  220. package/dist/lib/env.d.ts.map +1 -1
  221. package/dist/lib/env.js +5 -3
  222. package/dist/lib/events.d.ts +1 -2
  223. package/dist/lib/events.d.ts.map +1 -1
  224. package/dist/lib/image-background.d.ts +8 -0
  225. package/dist/lib/image-background.d.ts.map +1 -0
  226. package/dist/lib/image-variant-plan.d.ts +42 -0
  227. package/dist/lib/image-variant-plan.d.ts.map +1 -0
  228. package/dist/lib/image-variant-plan.js +53 -0
  229. package/dist/lib/index-ops.d.ts.map +1 -1
  230. package/dist/lib/index-ops.js +21 -17
  231. package/dist/lib/index.d.ts +7 -4
  232. package/dist/lib/index.d.ts.map +1 -1
  233. package/dist/lib/index.js +55 -26
  234. package/dist/lib/loader.d.ts +25 -12
  235. package/dist/lib/loader.d.ts.map +1 -1
  236. package/dist/lib/media-ops.d.ts +73 -0
  237. package/dist/lib/media-ops.d.ts.map +1 -0
  238. package/dist/lib/media-ops.js +60 -0
  239. package/dist/lib/nav-tree.d.ts +7 -0
  240. package/dist/lib/nav-tree.d.ts.map +1 -1
  241. package/dist/lib/nav.d.ts +38 -0
  242. package/dist/lib/nav.d.ts.map +1 -1
  243. package/dist/lib/pages.d.ts +2 -1
  244. package/dist/lib/pages.d.ts.map +1 -1
  245. package/dist/lib/platform-broker.d.ts +4 -2
  246. package/dist/lib/platform-broker.d.ts.map +1 -1
  247. package/dist/lib/platform-broker.js +21 -13
  248. package/dist/lib/reference-type.d.ts +2 -0
  249. package/dist/lib/reference-type.d.ts.map +1 -0
  250. package/dist/lib/reference-validation.d.ts +31 -0
  251. package/dist/lib/reference-validation.d.ts.map +1 -0
  252. package/dist/lib/reference-validation.js +39 -0
  253. package/dist/lib/references.d.ts +74 -0
  254. package/dist/lib/references.d.ts.map +1 -0
  255. package/dist/lib/registry.d.ts +35 -0
  256. package/dist/lib/registry.d.ts.map +1 -1
  257. package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
  258. package/dist/lib/safe-redirect.d.ts.map +1 -0
  259. package/dist/lib/sidecar-diagnostics.d.ts +20 -0
  260. package/dist/lib/sidecar-diagnostics.d.ts.map +1 -0
  261. package/dist/lib/sidecars.d.ts +118 -0
  262. package/dist/lib/sidecars.d.ts.map +1 -0
  263. package/dist/lib/sidecars.js +23 -0
  264. package/dist/lib/slug.d.ts +2 -0
  265. package/dist/lib/slug.d.ts.map +1 -0
  266. package/dist/lib/storage-tier.d.ts +17 -0
  267. package/dist/lib/storage-tier.d.ts.map +1 -0
  268. package/dist/lib/storage-tier.js +29 -0
  269. package/dist/lib/tags.d.ts +64 -0
  270. package/dist/lib/tags.d.ts.map +1 -0
  271. package/dist/lib/theme-vars.d.ts +9 -0
  272. package/dist/lib/theme-vars.d.ts.map +1 -1
  273. package/dist/media/index.d.ts +1 -1
  274. package/dist/media/index.d.ts.map +1 -1
  275. package/dist/media/index.js +18 -14
  276. package/dist/media/queue.d.ts +2 -0
  277. package/dist/media/queue.d.ts.map +1 -1
  278. package/dist/media/utils.d.ts +2 -0
  279. package/dist/media/utils.d.ts.map +1 -1
  280. package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
  281. package/dist/media/video-poster.d.ts.map +1 -0
  282. package/dist/media/worker.d.ts +1 -35
  283. package/dist/media/worker.d.ts.map +1 -1
  284. package/dist/schemas/audience.js +2 -2
  285. package/dist/schemas/index.d.ts +1 -0
  286. package/dist/schemas/index.d.ts.map +1 -1
  287. package/dist/schemas/index.js +25 -13
  288. package/dist/schemas/media.d.ts +4 -0
  289. package/dist/schemas/media.d.ts.map +1 -1
  290. package/dist/schemas/shared.d.ts +26 -0
  291. package/dist/schemas/shared.d.ts.map +1 -1
  292. package/dist/schemas/site-config.d.ts +6 -0
  293. package/dist/schemas/site-config.d.ts.map +1 -1
  294. package/dist/schemas/tags.d.ts +27 -0
  295. package/dist/schemas/tags.d.ts.map +1 -0
  296. package/dist/storage/index.js +2 -1
  297. package/dist/storage/memory.d.ts +21 -0
  298. package/dist/storage/memory.d.ts.map +1 -0
  299. package/dist/storage/memory.js +129 -0
  300. package/dist/storage/types.d.ts +9 -0
  301. package/dist/storage/types.d.ts.map +1 -1
  302. package/dist/types/database.d.ts.map +1 -1
  303. package/package.json +26 -1
  304. package/src/auth/cookies.ts +111 -0
  305. package/src/collab/rebase.ts +29 -9
  306. package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
  307. package/src/components/brandguide/ColorsEditable.tsx +1 -0
  308. package/src/components/chat/ChatPanel.tsx +2 -3
  309. package/src/components/chat/ChatWidget.tsx +2 -3
  310. package/src/components/docfile/DocFilePane.tsx +4 -12
  311. package/src/components/editor/ChildBlockWrapper.tsx +13 -19
  312. package/src/components/editor/ConflictDialog.tsx +27 -35
  313. package/src/components/editor/DeleteButton.tsx +2 -2
  314. package/src/components/editor/DragHandle.tsx +16 -3
  315. package/src/components/editor/DropEdgeIndicator.tsx +36 -10
  316. package/src/components/editor/InsertButton.tsx +2 -2
  317. package/src/components/editor/NavGroupRow.tsx +43 -14
  318. package/src/components/editor/PagesModal.tsx +99 -26
  319. package/src/components/editor/SectionWrapper.tsx +64 -23
  320. package/src/components/editor/SettingsButton.tsx +2 -2
  321. package/src/components/editor/SettingsForm.tsx +19 -2
  322. package/src/components/editor/StatusIndicator.tsx +4 -4
  323. package/src/components/editor/TagIndicator.tsx +80 -0
  324. package/src/components/primitives/DocumentDropZone.tsx +1 -1
  325. package/src/components/primitives/EditableGrid.tsx +15 -14
  326. package/src/components/primitives/EditableList.tsx +27 -74
  327. package/src/components/primitives/HeadingSection.tsx +5 -2
  328. package/src/components/primitives/ResolvedMedia.tsx +13 -0
  329. package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
  330. package/src/components/primitives/index.ts +1 -1
  331. package/src/components/primitives/useEditablePlainText.ts +5 -5
  332. package/src/components/sections/Button/CTAButton.tsx +3 -1
  333. package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
  334. package/src/components/sections/DoDontMedia/index.tsx +12 -3
  335. package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
  336. package/src/components/sections/IconList/IconList.tsx +70 -37
  337. package/src/components/sections/IconList/IconListSettings.tsx +55 -17
  338. package/src/components/sections/IconList/index.tsx +10 -3
  339. package/src/components/sections/LinkHeading/index.tsx +1 -1
  340. package/src/components/sections/Media/MediaBlock.tsx +13 -2
  341. package/src/components/sections/Media/index.tsx +12 -4
  342. package/src/components/sections/Reference/ReferenceList.tsx +214 -0
  343. package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
  344. package/src/components/sections/Reference/index.tsx +47 -0
  345. package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
  346. package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
  347. package/src/components/sections/SectionSummary/index.tsx +149 -0
  348. package/src/components/sections/SubHeading/index.tsx +1 -1
  349. package/src/components/sections/SubSubHeading/index.tsx +1 -1
  350. package/src/components/sections/brand-guide.ts +4 -3
  351. package/src/components/sections/core-sections.ts +2 -0
  352. package/src/components/shared/BrandSwatchesContext.ts +13 -0
  353. package/src/components/shared/Button.tsx +47 -34
  354. package/src/components/shared/Checkbox.tsx +21 -12
  355. package/src/components/shared/ConfirmDialog.tsx +87 -0
  356. package/src/components/shared/ConfirmInline.tsx +90 -0
  357. package/src/components/shared/ErrorBoundary.tsx +6 -18
  358. package/src/components/shared/Fab.tsx +15 -5
  359. package/src/components/shared/FabStack.tsx +28 -0
  360. package/src/components/shared/HistoryChangesModal.tsx +43 -41
  361. package/src/components/shared/HistoryPopover.tsx +7 -20
  362. package/src/components/shared/ImageBackgroundField.tsx +92 -0
  363. package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
  364. package/src/components/shared/Input.tsx +23 -7
  365. package/src/components/shared/Navigation.tsx +22 -17
  366. package/src/components/shared/Notice.tsx +59 -0
  367. package/src/components/shared/Popover.tsx +7 -11
  368. package/src/components/shared/ReferenceSourcesContext.ts +27 -0
  369. package/src/components/shared/Select.tsx +5 -2
  370. package/src/components/shared/SplitButton.tsx +11 -17
  371. package/src/components/shared/SummaryAnchorsContext.ts +11 -0
  372. package/src/components/shared/Textarea.tsx +17 -2
  373. package/src/components/shared/ToolbarFrame.tsx +28 -0
  374. package/src/components/shared/VideoSourceField.tsx +1 -1
  375. package/src/components/shared/copy.ts +18 -0
  376. package/src/components/shared/icons.tsx +1 -17
  377. package/src/components/shell/AudienceAddForm.tsx +2 -2
  378. package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
  379. package/src/components/shell/AudienceRow.tsx +22 -15
  380. package/src/components/shell/BugReportFAB.tsx +50 -40
  381. package/src/components/shell/CredentialList.tsx +33 -13
  382. package/src/components/shell/DocInspector.tsx +3 -12
  383. package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
  384. package/src/components/shell/EditorContext.tsx +7 -0
  385. package/src/components/shell/EditorLoginForm.tsx +26 -36
  386. package/src/components/shell/EditorModal.tsx +8 -10
  387. package/src/components/shell/EditorShell.tsx +501 -338
  388. package/src/components/shell/HistoryToolbar.tsx +24 -26
  389. package/src/components/shell/MediaFolderTile.tsx +8 -3
  390. package/src/components/shell/MediaLibraryModal.tsx +59 -60
  391. package/src/components/shell/ProcessingIndicator.tsx +2 -2
  392. package/src/components/shell/RestoreModal.tsx +17 -16
  393. package/src/components/shell/SetPasswordForm.tsx +3 -3
  394. package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
  395. package/src/components/shell/SiteSettingsDisplay.tsx +10 -20
  396. package/src/components/shell/SiteSettingsModal.tsx +24 -2
  397. package/src/components/shell/SiteSettingsTags.tsx +143 -0
  398. package/src/components/shell/SiteSettingsUsers.tsx +36 -26
  399. package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
  400. package/src/components/shell/ViewerLoginForm.tsx +5 -4
  401. package/src/components/shell/reference-sources.ts +36 -0
  402. package/src/deck/index.ts +2 -2
  403. package/src/document/index.ts +2 -2
  404. package/src/hooks/useBlockDnd.ts +11 -0
  405. package/src/hooks/useBuildStatus.ts +53 -6
  406. package/src/hooks/useDocumentUploads.ts +1 -1
  407. package/src/hooks/useEditorPersistence.ts +141 -35
  408. package/src/hooks/useEditorPublish.ts +27 -31
  409. package/src/hooks/useMediaPipeline.ts +30 -24
  410. package/src/hooks/useNotice.ts +45 -0
  411. package/src/hooks/useSortableNavRow.ts +11 -0
  412. package/src/hooks/useSortableRow.ts +22 -2
  413. package/src/hooks/useStackedEscape.ts +62 -0
  414. package/src/lib/block-dnd.ts +6 -1
  415. package/src/lib/block-move.ts +3 -0
  416. package/src/lib/brand-swatches.ts +32 -0
  417. package/src/lib/container-ops.ts +5 -3
  418. package/src/lib/dexie.ts +24 -2
  419. package/src/lib/env.ts +9 -0
  420. package/src/lib/events.ts +1 -2
  421. package/src/lib/image-background.ts +31 -0
  422. package/src/lib/image-variant-plan.ts +92 -0
  423. package/src/lib/index-ops.ts +9 -18
  424. package/src/lib/index.ts +20 -4
  425. package/src/lib/loader.ts +28 -88
  426. package/src/lib/media-ops.ts +112 -0
  427. package/src/lib/nav-tree.ts +104 -4
  428. package/src/lib/nav.ts +196 -36
  429. package/src/lib/pages.ts +2 -3
  430. package/src/lib/platform-broker.ts +32 -14
  431. package/src/lib/reference-type.ts +3 -0
  432. package/src/lib/reference-validation.ts +69 -0
  433. package/src/lib/references.ts +130 -0
  434. package/src/lib/registry.ts +37 -0
  435. package/src/lib/sidecar-diagnostics.ts +29 -0
  436. package/src/lib/sidecars.ts +221 -0
  437. package/src/lib/slug.ts +6 -0
  438. package/src/lib/storage-tier.ts +38 -0
  439. package/src/lib/tags.ts +165 -0
  440. package/src/lib/theme-vars.ts +23 -0
  441. package/src/media/index.ts +1 -1
  442. package/src/media/queue.ts +3 -0
  443. package/src/media/utils.ts +19 -1
  444. package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
  445. package/src/media/worker.ts +17 -8
  446. package/src/schemas/index.ts +1 -0
  447. package/src/schemas/media.ts +7 -2
  448. package/src/schemas/shared.ts +24 -1
  449. package/src/schemas/site-config.ts +6 -1
  450. package/src/schemas/tags.ts +33 -0
  451. package/src/storage/memory.ts +178 -0
  452. package/src/storage/types.ts +16 -3
  453. package/src/types/database.ts +2 -0
  454. package/dist/chunk-DNY72JZN.js +0 -86
  455. package/dist/chunk-F2LYQPXV.js +0 -77
  456. package/dist/chunk-JH762VUH.js +0 -128
  457. package/dist/chunk-K7DYZXVU.js +0 -138
  458. package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
  459. package/dist/components/primitives/gridDrop.d.ts.map +0 -1
  460. package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
  461. package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
  462. package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
  463. package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
  464. package/dist/hooks/index.d.ts +0 -9
  465. package/dist/hooks/index.d.ts.map +0 -1
  466. package/dist/lib/grid.d.ts +0 -2
  467. package/dist/lib/grid.d.ts.map +0 -1
  468. package/dist/lib/safeRedirect.d.ts.map +0 -1
  469. package/dist/media/videoPoster.d.ts.map +0 -1
  470. package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
  471. package/src/components/brandguide/Colors.d.ts.map +0 -1
  472. package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
  473. package/src/components/primitives/EditableGrid.d.ts.map +0 -1
  474. package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
  475. package/src/components/primitives/EditableRichText.d.ts.map +0 -1
  476. package/src/components/primitives/HeadingSection.d.ts.map +0 -1
  477. package/src/components/primitives/IconPicker.d.ts.map +0 -1
  478. package/src/components/primitives/LinkPopover.d.ts.map +0 -1
  479. package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
  480. package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
  481. package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
  482. package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
  483. package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
  484. package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
  485. package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
  486. package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
  487. package/src/components/sections/Button/index.d.ts.map +0 -1
  488. package/src/components/sections/Colors/index.d.ts.map +0 -1
  489. package/src/components/sections/IconList/IconList.d.ts.map +0 -1
  490. package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
  491. package/src/components/sections/IconList/index.d.ts.map +0 -1
  492. package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
  493. package/src/components/sections/Prose/Prose.d.ts.map +0 -1
  494. package/src/components/sections/Prose/index.d.ts.map +0 -1
  495. package/src/components/sections/SubHeading/index.d.ts.map +0 -1
  496. package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
  497. package/src/components/sections/register-schemas.d.ts.map +0 -1
  498. package/src/components/shared/Button.d.ts.map +0 -1
  499. package/src/components/shared/Checkbox.d.ts.map +0 -1
  500. package/src/components/shared/FormLabel.d.ts.map +0 -1
  501. package/src/components/shared/IconButton.d.ts.map +0 -1
  502. package/src/components/shared/Input.d.ts.map +0 -1
  503. package/src/components/shared/Select.d.ts.map +0 -1
  504. package/src/components/shared/icons.d.ts.map +0 -1
  505. package/src/components/shell/BuildStatusIndicator.tsx +0 -59
  506. package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
  507. package/src/hooks/index.ts +0 -8
  508. package/src/hooks/useResolvedMedia.d.ts.map +0 -1
  509. package/src/lib/cn.d.ts.map +0 -1
  510. package/src/lib/grid.d.ts.map +0 -1
  511. package/src/lib/grid.ts +0 -7
  512. package/src/lib/icons.d.ts.map +0 -1
  513. package/src/lib/loader.d.ts.map +0 -1
  514. package/src/lib/nav.d.ts.map +0 -1
  515. package/src/lib/registry.d.ts.map +0 -1
  516. package/src/lib/sanitize.d.ts.map +0 -1
  517. package/src/media/github.d.ts.map +0 -1
  518. package/src/media/index.d.ts.map +0 -1
  519. package/src/media/queue.d.ts.map +0 -1
  520. package/src/media/resolve.d.ts.map +0 -1
  521. package/src/media/types.d.ts.map +0 -1
  522. package/src/media/utils.d.ts.map +0 -1
  523. package/src/media/videoPoster.d.ts.map +0 -1
  524. package/src/schemas/auth.d.ts.map +0 -1
  525. package/src/schemas/media-grid-options.d.ts.map +0 -1
  526. package/src/schemas/media.d.ts.map +0 -1
  527. package/src/schemas/sections.d.ts.map +0 -1
  528. package/src/schemas/shared.d.ts.map +0 -1
  529. package/src/schemas/site-config.d.ts.map +0 -1
  530. /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
  531. /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
  532. /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
  533. /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
  534. /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
@@ -11,6 +11,17 @@ interface UseSortableRowOptions {
11
11
  }
12
12
 
13
13
  /**
14
+ * One of three sibling drag-and-drop position hooks, split by location type
15
+ * rather than unified behind a generic `useSortable({ axis })`: this one (flat
16
+ * index — section-ordering lists, `EditableList`), `useSortableNavRow`
17
+ * (NavLocation — the Pages modal's group-aware nav tree), and `useBlockDnd`
18
+ * (block/container id + index — the section canvas, root and nested). A
19
+ * fourth location type earns its own hook on the same shape (rowRef/handleRef,
20
+ * lazy atlaskit import, closest-edge state, a ref for the latest callback)
21
+ * rather than a parameter bag bolted onto an existing one — see
22
+ * docs/superpowers/specs/2026-09-04-editor-ui-primitives-consolidation.md § D6
23
+ * for why a shared `useSortable` was deferred.
24
+ *
14
25
  * Closest-edge drag-to-reorder wiring for a single list row, shared by the
15
26
  * section- and page-ordering modals. Attach `rowRef` to the row element and
16
27
  * `handleRef` to the drag handle, and render
@@ -30,6 +41,15 @@ export function useSortableRow<R extends HTMLElement, H extends HTMLElement>({
30
41
  const [isDragging, setIsDragging] = useState(false);
31
42
  const [closestEdge, setClosestEdge] = useState<"top" | "bottom" | null>(null);
32
43
 
44
+ // Read through a ref so a changed `onReorder` identity doesn't re-register
45
+ // the atlaskit bindings mid-drag (which cancels the drag) — the same class
46
+ // of bug EditableList's `onReorderRef` fixed (2026-08-03). `index` stays a
47
+ // real effect dependency: a stale index would report the wrong
48
+ // `fromIndex`/`toIndex` on drop, the hazard useSortableNavRow's `locationOf`
49
+ // comment warns about for its own (non-re-subscribing) case.
50
+ const onReorderRef = useRef(onReorder);
51
+ onReorderRef.current = onReorder;
52
+
33
53
  useEffect(() => {
34
54
  if (!enabled) return;
35
55
  const row = rowRef.current;
@@ -79,7 +99,7 @@ export function useSortableRow<R extends HTMLElement, H extends HTMLElement>({
79
99
  const rawEdge = extractClosestEdge(self.data);
80
100
  const edge = rawEdge === "top" || rawEdge === "bottom" ? rawEdge : null;
81
101
  const toIndex = computeReorderTarget(fromIndex, index, edge);
82
- if (toIndex !== null) onReorder(fromIndex, toIndex);
102
+ if (toIndex !== null) onReorderRef.current(fromIndex, toIndex);
83
103
  },
84
104
  });
85
105
 
@@ -93,7 +113,7 @@ export function useSortableRow<R extends HTMLElement, H extends HTMLElement>({
93
113
  cancelled = true;
94
114
  cleanup?.();
95
115
  };
96
- }, [index, dragType, onReorder, enabled]);
116
+ }, [index, dragType, enabled]);
97
117
 
98
118
  return { rowRef, handleRef, isDragging, closestEdge };
99
119
  }
@@ -0,0 +1,62 @@
1
+ import { useEffect, useRef, type RefObject } from "react";
2
+
3
+ export interface UseStackedEscapeOptions {
4
+ enabled: boolean;
5
+ /**
6
+ * Runs first, before the layer check would otherwise fall through to
7
+ * `onEscape`; returning `true` swallows the keypress entirely (the document
8
+ * editor overlay's blur-a-focused-field-first step).
9
+ */
10
+ before?: (e: KeyboardEvent) => boolean;
11
+ }
12
+
13
+ /**
14
+ * Shared "a modal above me owns Escape" rule. `EditorModal` marks its
15
+ * outermost layer with `data-modal-layer`; anything that might render BELOW
16
+ * one — a `Popover`, the doc file pane, the document editor overlay, and
17
+ * `EditorModal` itself (relative to another `EditorModal` opened on top of
18
+ * it) — must not react to an Escape meant for that layer instead.
19
+ *
20
+ * Attach the returned ref to your own `data-modal-layer` element (only
21
+ * `EditorModal` does) so the check can exclude it — otherwise it would always
22
+ * find itself and never fire. Callers that aren't a layer themselves (Popover,
23
+ * DocFilePane, the overlay) just ignore the return value: any layer at all
24
+ * then means something is stacked above them.
25
+ *
26
+ * For a tagged caller, "above" means a layer that FOLLOWS its own layer in
27
+ * DOM order (`compareDocumentPosition` + `DOCUMENT_POSITION_FOLLOWING`), not
28
+ * just "any other layer" — modals are appended later in DOM order than the
29
+ * ones already open, so this is what lets two stacked `EditorModal`s (e.g.
30
+ * Site Settings opening the Media Library over itself) resolve Escape to the
31
+ * topmost one only, then the next one down once that one closes.
32
+ */
33
+ export function useStackedEscape<T extends HTMLElement = HTMLElement>(
34
+ onEscape: () => void,
35
+ { enabled, before }: UseStackedEscapeOptions,
36
+ ): RefObject<T | null> {
37
+ const layerRef = useRef<T | null>(null);
38
+
39
+ useEffect(() => {
40
+ if (!enabled) return;
41
+
42
+ const onKeyDown = (e: KeyboardEvent) => {
43
+ if (e.key !== "Escape") return;
44
+ const own = layerRef.current;
45
+ const layers = document.querySelectorAll<HTMLElement>("[data-modal-layer]");
46
+ const above = Array.from(layers).some((el) => {
47
+ if (el === own) return false;
48
+ if (!own) return true;
49
+ return Boolean(own.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
50
+ });
51
+ if (above) return;
52
+ if (before?.(e)) return;
53
+ e.preventDefault();
54
+ onEscape();
55
+ };
56
+
57
+ document.addEventListener("keydown", onKeyDown);
58
+ return () => document.removeEventListener("keydown", onKeyDown);
59
+ }, [enabled, onEscape, before]);
60
+
61
+ return layerRef;
62
+ }
@@ -11,6 +11,8 @@ export interface BlockDragData {
11
11
  index: number;
12
12
  /** True if the dragged block is itself a container (used for the depth guard). */
13
13
  isContainer: boolean;
14
+ /** True if the dragged block is a Reference, which only expands at the page root. */
15
+ isReference?: boolean;
14
16
  [key: string | symbol]: unknown;
15
17
  }
16
18
 
@@ -27,6 +29,7 @@ export function buildBlockDragData(args: {
27
29
  containerId: string;
28
30
  index: number;
29
31
  isContainer: boolean;
32
+ isReference?: boolean;
30
33
  }): BlockDragData {
31
34
  return { dragType: "block", ...args };
32
35
  }
@@ -43,11 +46,13 @@ export function isBlockDragData(data: Record<string | symbol, unknown>): data is
43
46
  * May `source` drop into `dropContainerId`?
44
47
  * - A container block may only land at the page root (v1 one-level nesting → no
45
48
  * container-in-container; MAX_BLOCK_DEPTH=2).
49
+ * - So may a Reference: it is expanded into its sources only at the page root,
50
+ * so inside a container it would render nothing.
46
51
  * - Nothing may drop onto itself.
47
52
  */
48
53
  export function canDropBlock(source: BlockDragData, dropContainerId: string): boolean {
49
54
  if (source.blockId === dropContainerId) return false;
50
- if (source.isContainer && dropContainerId !== ROOT_CONTAINER_ID) return false;
55
+ if ((source.isContainer || source.isReference) && dropContainerId !== ROOT_CONTAINER_ID) return false;
51
56
  return true;
52
57
  }
53
58
 
@@ -2,6 +2,7 @@ import type { LoadedSection } from "./loader";
2
2
  import type { Section } from "../schemas/sections";
3
3
  import type { SiteIndex, SectionMeta } from "../schemas/site-config";
4
4
  import { ROOT_CONTAINER_ID, canDropBlock } from "./block-dnd";
5
+ import { REFERENCE_TYPE } from "./reference-type";
5
6
  import { getContainerChildren, reorderChild, insertChildAt, removeChildAt, placeBlockAtColumn, trimTrailingSpacers } from "./container-ops";
6
7
  import { reorderVisibleSectionInPage, visibleInsertPosition, addSectionToPage, removeSectionFromPages } from "./pages";
7
8
 
@@ -96,6 +97,7 @@ export function applyBlockMove(
96
97
  containerId: fromContainerId,
97
98
  index: fromIndex,
98
99
  isContainer: isContainerSection(draggedSection),
100
+ isReference: draggedSection.type === REFERENCE_TYPE,
99
101
  };
100
102
  if (!canDropBlock(dragData, toContainerId)) return noop(state);
101
103
 
@@ -200,6 +202,7 @@ function applyColumnPlacement(
200
202
  containerId: fromContainerId,
201
203
  index: fromIndex,
202
204
  isContainer: isContainerSection(draggedSection),
205
+ isReference: draggedSection.type === REFERENCE_TYPE,
203
206
  };
204
207
  if (!canDropBlock(dragData, toContainerId)) return noop(state);
205
208
 
@@ -0,0 +1,32 @@
1
+ import type { Section } from "../schemas/sections";
2
+ import type { ColorItem } from "../components/sections/Colors/schema";
3
+
4
+ export interface BrandSwatch {
5
+ hex: string;
6
+ name: string | undefined;
7
+ }
8
+
9
+ type Block = { type?: unknown; content?: unknown };
10
+
11
+ /**
12
+ * Every hex value from every Colors section, walking container children, in
13
+ * page order and deduped case-insensitively. Swatches are offered as plain hex
14
+ * values: color items carry no stable id, so a picked swatch is copied, not linked.
15
+ */
16
+ export function collectBrandSwatches(sections: Section[]): BrandSwatch[] {
17
+ const seen = new Map<string, BrandSwatch>();
18
+ const visit = (block: Block) => {
19
+ const content = (block.content ?? {}) as { colors?: unknown; children?: unknown };
20
+ if (block.type === "colors" && Array.isArray(content.colors)) {
21
+ for (const item of content.colors as ColorItem[]) {
22
+ for (const space of item.spaces) {
23
+ const hex = space.hex?.toLowerCase();
24
+ if (hex && !seen.has(hex)) seen.set(hex, { hex, name: item.name });
25
+ }
26
+ }
27
+ }
28
+ if (Array.isArray(content.children)) (content.children as Block[]).forEach(visit);
29
+ };
30
+ sections.forEach(visit);
31
+ return [...seen.values()];
32
+ }
@@ -2,6 +2,7 @@ import type { ReactNode } from "react";
2
2
  import type { Section } from "../schemas/sections";
3
3
  import { getAllSections } from "./registry";
4
4
  import { sortInsertMenuOptions } from "./insert-menu";
5
+ import { REFERENCE_TYPE } from "./reference-type";
5
6
 
6
7
  interface ContainerContent {
7
8
  columns: number;
@@ -37,13 +38,14 @@ export function reorderChild(container: Section, from: number, to: number): Sect
37
38
 
38
39
  /**
39
40
  * Block types insertable as a container CHILD — excludes `container` itself
40
- * (v1 enforces one level of container nesting). Shared so the depth guard has a
41
- * single, testable source of truth (the container toolbar's "+" picker uses it).
41
+ * (v1 enforces one level of container nesting) and `reference`, which only
42
+ * expands at the top level of a page. Shared so the depth guard has a single,
43
+ * testable source of truth (the container toolbar's "+" picker uses it).
42
44
  */
43
45
  export function childInsertableTypes(): { type: string; label: string; icon: ReactNode }[] {
44
46
  return sortInsertMenuOptions(
45
47
  getAllSections()
46
- .filter((d) => d.type !== "container" && d.type !== "spacer")
48
+ .filter((d) => d.type !== "container" && d.type !== "spacer" && d.type !== REFERENCE_TYPE)
47
49
  .map((d) => ({ type: d.type, label: d.label, icon: d.icon })),
48
50
  );
49
51
  }
package/src/lib/dexie.ts CHANGED
@@ -1,7 +1,13 @@
1
+ // The editor's offline draft store (IndexedDB via Dexie): unsaved section
2
+ // edits, the working index/nav, site config, pending media, and a sha-keyed
3
+ // cache of the last loaded content. Nothing here is authoritative — GitHub is.
4
+ // Schema versions only ever append; an EMPTY `version(N)` bump is intentional
5
+ // (see the per-version notes in the constructor), never a leftover to remove.
1
6
  import Dexie from "dexie";
2
7
  import type { SectionContent } from "../schemas/sections";
3
8
  import type { SiteIndex, SectionMeta, SiteConfig, Page } from "../schemas/site-config";
4
9
  import type { NavEntry } from "../schemas/nav";
10
+ import type { TagEntry } from "../schemas/tags";
5
11
  import type { LoadedSection } from "./loader";
6
12
  import type { MediaManifest, MediaItem } from "../media/types";
7
13
  import type { DocumentManifest, DocumentManifestEntry } from "../schemas/documents";
@@ -19,6 +25,9 @@ interface SiteIndexRow {
19
25
  sections: Record<string, SectionMeta>;
20
26
  /** Optional: rows written before page groups shipped have no nav. */
21
27
  nav?: NavEntry[];
28
+ /** Optional: rows written before section tags shipped have none. Restored
29
+ * as absent (not []), which writers read as "leave tags.json alone". */
30
+ tags?: TagEntry[];
22
31
  deletedSections: string[];
23
32
  updatedAt: string;
24
33
  }
@@ -311,7 +320,10 @@ export async function restoreLocalChanges(): Promise<{
311
320
  const siteId = metaRow?.siteId || getDb().siteId;
312
321
  return {
313
322
  sections,
314
- siteIndex: { siteId, pages: indexRow.pages, sections: indexRow.sections, nav: indexRow.nav },
323
+ siteIndex: {
324
+ siteId, pages: indexRow.pages, sections: indexRow.sections, nav: indexRow.nav,
325
+ ...(indexRow.tags !== undefined ? { tags: indexRow.tags } : {}),
326
+ },
315
327
  siteConfig: configRow?.config,
316
328
  deletedSections: indexRow.deletedSections ?? [],
317
329
  };
@@ -345,6 +357,7 @@ export async function persistSiteIndex(index: SiteIndex, deletedSections: string
345
357
  pages: index.pages,
346
358
  sections: index.sections,
347
359
  nav: index.nav,
360
+ tags: index.tags,
348
361
  deletedSections,
349
362
  updatedAt: now,
350
363
  });
@@ -465,6 +478,7 @@ export async function persistAll(
465
478
  pages: siteIndex.pages,
466
479
  sections: siteIndex.sections,
467
480
  nav: siteIndex.nav,
481
+ tags: siteIndex.tags,
468
482
  // Record the deletion INTENT, not just its effect on the order. The
469
483
  // restore path reads this back; when it was hardcoded `[]` that path
470
484
  // had to re-derive deletions by diffing this snapshot against a fresh
@@ -497,6 +511,12 @@ export async function persistAll(
497
511
  * cache hit then served pre-upload media ("No Image" on images the published site
498
512
  * rendered fine) and an empty document manifest ("File missing" on committed
499
513
  * documents). Passing them positionally makes forgetting a compile error.
514
+ *
515
+ * `tagsDegraded` is required for the same reason. A degraded tags read caches
516
+ * as "not loaded" (the index without `tags`), so a later cache-hit load stays
517
+ * read-only for tags instead of trusting the partial list. Only the cold load
518
+ * used to strip it, so a conflict recovery, remote sync or save re-primed the
519
+ * row with the partial list and the next cache hit re-enabled tag editing.
500
520
  */
501
521
  export async function cacheContent(
502
522
  sha: string,
@@ -504,6 +524,7 @@ export async function cacheContent(
504
524
  index: SiteIndex,
505
525
  siteConfig: Record<string, unknown>,
506
526
  manifests: { media: MediaManifest; documents: DocumentManifest },
527
+ tagsDegraded: boolean,
507
528
  diff?: {
508
529
  savedBranchSha?: string | null;
509
530
  changedSectionIds?: string[];
@@ -512,11 +533,12 @@ export async function cacheContent(
512
533
  },
513
534
  ): Promise<void> {
514
535
  const now = new Date().toISOString();
536
+ const { tags: _partialTags, ...untaggedIndex } = index;
515
537
  await getDb().contentCache.put({
516
538
  key: "current",
517
539
  sha,
518
540
  sections,
519
- index,
541
+ index: tagsDegraded ? untaggedIndex : index,
520
542
  siteConfig,
521
543
  updatedAt: now,
522
544
  savedBranchSha: diff?.savedBranchSha ?? null,
package/src/lib/env.ts CHANGED
@@ -1,3 +1,5 @@
1
+ // env() is a byte-for-byte twin of packages/platform/src/env.ts: platform cannot
2
+ // import primitives without dragging it into apps/admin's bundle, so keep both.
1
3
  declare global {
2
4
  interface ImportMeta {
3
5
  readonly env?: Record<string, string | undefined>;
@@ -11,3 +13,10 @@ export function env(key: string): string {
11
13
  ""
12
14
  );
13
15
  }
16
+
17
+ /** Vite replaces `import.meta.env.PROD` with a boolean literal at build time
18
+ * (packages are `noExternal`, so that covers this file too), which is why the
19
+ * declared string type above is bypassed here. False under Node and vitest. */
20
+ export function isProd(): boolean {
21
+ return (import.meta.env?.PROD as unknown) === true;
22
+ }
package/src/lib/events.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { NavItem, SiteNav } from "./nav";
1
+ import type { SiteNav } from "./nav";
2
2
 
3
3
  export interface TypedEvent<T> {
4
4
  dispatch(detail: T): void;
@@ -19,7 +19,6 @@ export function createEvent<T>(name: string): TypedEvent<T> {
19
19
  }
20
20
 
21
21
  export const editModeEvent = createEvent<{ isEditMode: boolean }>("editmodechange");
22
- export const navChangeEvent = createEvent<NavItem[]>("sitenavchange");
23
22
  export const darkModeEvent = createEvent<string>("sitedarkmode");
24
23
  export const siteNameChangeEvent = createEvent<string>("sitenamechange");
25
24
  export const historySelectEvent = createEvent<{ sha: string; date: string }>("history-select");
@@ -0,0 +1,31 @@
1
+ import type { CSSProperties } from "react";
2
+ import type { ImageBackground, ImageBackgroundSurface } from "../schemas/shared";
3
+
4
+ // Class names are spelled out in full so Tailwind's source scan emits them.
5
+ // The surface-light/-dark tokens deliberately do NOT flip under `.dark`: a dark
6
+ // plate chosen for light mode must stay dark. The per-mode switch comes from the
7
+ // `dark:` variant instead, so it follows the theme toggle with no JS. An unset
8
+ // dark mode clears a light-mode plate rather than inheriting it.
9
+ const LIGHT_MODE: Record<ImageBackgroundSurface, string | undefined> = {
10
+ none: undefined,
11
+ light: "bg-surface-light",
12
+ dark: "bg-surface-dark",
13
+ };
14
+ const DARK_MODE: Record<ImageBackgroundSurface, string | undefined> = {
15
+ none: "dark:bg-transparent",
16
+ light: "dark:bg-surface-light",
17
+ dark: "dark:bg-surface-dark",
18
+ };
19
+
20
+ export interface ImageBackdrop {
21
+ className?: string;
22
+ style?: CSSProperties;
23
+ }
24
+
25
+ export function imageBackdrop(bg: ImageBackground | undefined): ImageBackdrop | undefined {
26
+ if (!bg) return undefined;
27
+ if (bg.mode === "custom") return { style: { backgroundColor: bg.color } };
28
+ const light = LIGHT_MODE[bg.light];
29
+ if (!light && bg.dark === "none") return undefined;
30
+ return { className: [light, DARK_MODE[bg.dark]].filter(Boolean).join(" ") };
31
+ }
@@ -0,0 +1,92 @@
1
+ import { sanitizeMediaName } from "../media/utils";
2
+ import type { MediaConfig, MediaItem, Variant } from "../schemas/media";
3
+
4
+ // The one place an uploaded image's identity, storage folder, variant widths,
5
+ // variant paths and manifest entry are decided. Two pixel adapters sit behind
6
+ // it: the editor's OffscreenCanvas worker (media/worker.ts) and the sharp path
7
+ // (authoring processImageBuffers, which the MCP connector calls). They used to
8
+ // build all of this separately and agree only because a comment said so; the
9
+ // site's media settings and dedup each drifted between them once. Pure and
10
+ // browser-safe — the worker imports it.
11
+
12
+ export interface MediaIdentity {
13
+ id: string;
14
+ hash: string;
15
+ originalName: string;
16
+ /** Storage dir under assets/images/. Never changes once committed. */
17
+ folder: string;
18
+ }
19
+
20
+ /** `hash` is the 16-hex content hash both sides compute (hashFileBuffer / hashBuffer). */
21
+ export function mediaIdentity(hash: string, fileName: string): MediaIdentity {
22
+ const originalName = sanitizeMediaName(fileName);
23
+ return { id: hash, hash, originalName, folder: `${originalName}-${hash}` };
24
+ }
25
+
26
+ /** Repo path of one stored file in a media folder: a variant width, or `poster`. */
27
+ export function imageVariantPath(folder: string, key: number | string): string {
28
+ return `assets/images/${folder}/${key}.webp`;
29
+ }
30
+
31
+ export interface ImageVariantPlan extends MediaIdentity {
32
+ width: number;
33
+ height: number;
34
+ /** WebP quality, 1-100. */
35
+ quality: number;
36
+ /** Ascending by width. */
37
+ variants: { width: number; path: string }[];
38
+ }
39
+
40
+ export function planImageVariants(input: {
41
+ hash: string;
42
+ fileName: string;
43
+ width: number;
44
+ height: number;
45
+ media: Pick<MediaConfig, "sizes" | "quality">;
46
+ }): ImageVariantPlan {
47
+ const identity = mediaIdentity(input.hash, input.fileName);
48
+ // Never upscale; an image narrower than every configured size still gets one
49
+ // variant, at its own width.
50
+ const widths = input.media.sizes.filter((s) => s <= input.width).sort((a, b) => a - b);
51
+ if (widths.length === 0) widths.push(input.width);
52
+ return {
53
+ ...identity,
54
+ width: input.width,
55
+ height: input.height,
56
+ quality: input.media.quality,
57
+ variants: widths.map((width) => ({ width, path: imageVariantPath(identity.folder, width) })),
58
+ };
59
+ }
60
+
61
+ export type ImageManifestEntry = Omit<MediaItem, "kind" | "storage" | "url" | "duration" | "folderId" | "hidden"> & {
62
+ kind: "image";
63
+ storage: "github";
64
+ };
65
+
66
+ /**
67
+ * `rendered` is what the adapter measured for each planned width (heights come
68
+ * from the encoder, not the plan). `size` is the adapter's byte count for the
69
+ * item: the editor records its largest variant, the sharp path the original's
70
+ * length — they differ today and this module does not decide that.
71
+ */
72
+ export function imageManifestEntry(plan: ImageVariantPlan, rendered: Variant[], size: number): ImageManifestEntry {
73
+ const variants = plan.variants.map(({ width }) => {
74
+ const out = rendered.find((r) => r.width === width);
75
+ if (!out) throw new Error(`[image-variant-plan] no rendered variant for planned width ${width}`);
76
+ return { width, height: out.height, size: out.size };
77
+ });
78
+ return {
79
+ id: plan.id,
80
+ hash: plan.hash,
81
+ kind: "image",
82
+ originalName: plan.originalName,
83
+ width: plan.width,
84
+ height: plan.height,
85
+ mimeType: "image/webp",
86
+ size,
87
+ folder: plan.folder,
88
+ variants,
89
+ alt: "",
90
+ storage: "github",
91
+ };
92
+ }
@@ -1,11 +1,12 @@
1
1
  import { z } from "zod";
2
2
  import { IndexSchema, PageStatusSchema, RESERVED_SLUGS, SLUG_RE, type SiteIndex, type SectionMeta } from "../schemas/site-config";
3
- import type { NavEntry, NavGroupEntry } from "../schemas/nav";
3
+ import type { NavGroupEntry } from "../schemas/nav";
4
4
  import type { NavLocation } from "./nav-tree";
5
5
  // Page and nav mutations are shared with the editor rather than reimplemented:
6
6
  // both surfaces must agree on what "delete a page" or "remove a group" means, and
7
7
  // a second implementation here is how they would drift.
8
8
  import { addPage as addPageToIndex, deletePage, slugifyPageSlug, uniquePageSlug } from "./pages";
9
+ import { liftSidecars } from "./sidecars";
9
10
  import {
10
11
  addGroup, deleteGroup, groupOfPage, moveNavEntry, navEntries, reconcileNav,
11
12
  renameGroup, setGroupStartCollapsed,
@@ -254,11 +255,12 @@ export function applyIndexOps(
254
255
  };
255
256
  }
256
257
 
257
- // IndexSchema strips `nav` (that strip is what keeps the sidecar out of
258
- // index.json), so the authored nav has to be lifted off the RAW input to be
259
- // available to the nav ops below. reconcileNav is total, so an unparseable
260
- // shape here degrades to a flat nav rather than failing.
261
- const rawNav = (rawIndex as { nav?: unknown } | null | undefined)?.nav;
258
+ // IndexSchema strips `nav` (that strip is what keeps the Sidecar out of
259
+ // index.json), so the authored nav is lifted off the RAW input to be
260
+ // available to the nav ops below — as fresh entries, so no op can mutate the
261
+ // caller's index. reconcileNav is total, so an unreadable nav degrades to a
262
+ // flat one rather than failing.
263
+ const lifted = liftSidecars(rawIndex);
262
264
 
263
265
  // Own copy: the caller's index is also its knownSiteTypes source and may be
264
266
  // logged, so nothing here mutates it. Reassigned by the page/nav ops, which
@@ -267,18 +269,7 @@ export function applyIndexOps(
267
269
  ...base.data,
268
270
  pages: base.data.pages.map((p) => ({ ...p, order: [...p.order] })),
269
271
  sections: Object.fromEntries(Object.entries(base.data.sections).map(([k, v]) => [k, { ...v }])),
270
- // COPIED, not aliased. Taking the caller's array by reference meant any nav
271
- // op that spliced in place would mutate the caller's index — the one thing
272
- // this function's own comment promises it never does.
273
- ...(Array.isArray(rawNav)
274
- ? {
275
- nav: (rawNav as NavEntry[]).map((entry) =>
276
- entry && typeof entry === "object" && "pageIds" in entry
277
- ? { ...entry, pageIds: [...(entry as { pageIds: string[] }).pageIds] }
278
- : { ...entry },
279
- ),
280
- }
281
- : {}),
272
+ ...(lifted.nav ? { nav: lifted.nav.entries } : {}),
282
273
  };
283
274
 
284
275
  const removed = new Set<string>();
package/src/lib/index.ts CHANGED
@@ -4,6 +4,23 @@ export { audiencePasses } from "./pages";
4
4
  export { resolveChatbotName, resolveThinkingPhrases, DEFAULT_CHATBOT_NAME } from "./chatbot";
5
5
  export { generateNavLinks, toSectionId, type NavItem } from "./nav";
6
6
  export { navEntries, pagesInNavOrder, groupOfPage, groupDisplayLabel, reconcileNav } from "./nav-tree";
7
+ export { siteTags, tagDisplayLabel, reconcileTags } from "./tags";
8
+ export {
9
+ NAV,
10
+ TAGS,
11
+ SIDECARS,
12
+ readSidecar,
13
+ readSidecarText,
14
+ liftSidecars,
15
+ planSidecarWrite,
16
+ type SidecarDefinition,
17
+ type SidecarFileState,
18
+ type SidecarWritePlan,
19
+ type SidecarRead,
20
+ type SidecarDiagnostic,
21
+ } from "./sidecars";
22
+ export { resolveReference, type ReferenceContent } from "./references";
23
+ export { REFERENCE_TYPE } from "./reference-type";
7
24
  export {
8
25
  deriveContrast,
9
26
  contrastColor,
@@ -15,12 +32,11 @@ export {
15
32
  } from "./contrast";
16
33
  export { primaryVarValue, accentVarValue, onPrimaryVarValue } from "./theme-vars";
17
34
  export { sanitizeHtml, ensureSanitizer } from "./sanitize";
18
- export { gridColsClass } from "./grid";
19
35
  export { getIcon, curatedIcons, type IconEntry } from "./icons";
20
36
  export { buildGoogleFontsUrl } from "./google-fonts";
21
37
  export { formatTimestamp } from "./timestamp";
22
- export { safeRedirect } from "./safeRedirect";
23
- export { createEvent, editModeEvent, navChangeEvent, darkModeEvent, type TypedEvent } from "./events";
38
+ export { safeRedirect } from "./safe-redirect";
39
+ export { createEvent, editModeEvent, darkModeEvent, type TypedEvent } from "./events";
24
40
  export {
25
41
  createRegistry,
26
42
  defineSection,
@@ -42,7 +58,7 @@ export {
42
58
  export {
43
59
  mergeSiteContent,
44
60
  loadStaticSiteContent,
45
- loadSiteContent,
46
61
  type LoadedSection,
47
62
  type SiteContent,
63
+ type SidecarReads,
48
64
  } from "./loader";