@drawnagency/primitives 0.1.109 → 0.1.111

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 (208) hide show
  1. package/dist/auth/cookies.d.ts +8 -0
  2. package/dist/auth/cookies.d.ts.map +1 -1
  3. package/dist/auth/index.d.ts +1 -1
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +3 -1
  6. package/dist/auth/types.d.ts +11 -4
  7. package/dist/auth/types.d.ts.map +1 -1
  8. package/dist/{chunk-WXBHP4JY.js → chunk-3GAG6ZXB.js} +55 -46
  9. package/dist/{chunk-FM4M4Q2W.js → chunk-4TZJZU2T.js} +23 -3
  10. package/dist/{chunk-5PVRACZY.js → chunk-7MI3HCOF.js} +60 -23
  11. package/dist/{chunk-WBDPDGFA.js → chunk-7WQJ57XG.js} +6 -31
  12. package/dist/{chunk-LQHYVPBS.js → chunk-ALMEC3XN.js} +11 -12
  13. package/dist/{chunk-TZQPOR5A.js → chunk-DMCGN5AS.js} +10 -3
  14. package/dist/{chunk-ZKVKNUJC.js → chunk-ELQ4C677.js} +1 -1
  15. package/dist/{chunk-5BM2Y3NJ.js → chunk-FRVO75DK.js} +14 -2
  16. package/dist/{chunk-VKAGMEKE.js → chunk-FTPETWXE.js} +1 -0
  17. package/dist/{chunk-3TO4RRHY.js → chunk-GPPVYLEI.js} +7 -0
  18. package/dist/{chunk-NLQ5F3RQ.js → chunk-HBULBDGP.js} +1 -1
  19. package/dist/{chunk-67ZOQCUD.js → chunk-NXGIHSL5.js} +67 -50
  20. package/dist/{chunk-CPTFFLK2.js → chunk-OTDA6KWL.js} +10 -3
  21. package/dist/{chunk-XIDE4TDF.js → chunk-OUYB2GCW.js} +1 -1
  22. package/dist/{chunk-72CG6AA2.js → chunk-RA5IOFPY.js} +10 -2
  23. package/dist/{chunk-GEENI3OC.js → chunk-SW6PCQQD.js} +4 -0
  24. package/dist/{chunk-BOZUEKWL.js → chunk-UVIYI4J6.js} +1 -1
  25. package/dist/{chunk-AB3XVXI3.js → chunk-VCCNKTFD.js} +37 -29
  26. package/dist/{chunk-XBYJQ5RS.js → chunk-XQMDWXD6.js} +21 -6
  27. package/dist/collab/rebase.d.ts +6 -0
  28. package/dist/collab/rebase.d.ts.map +1 -1
  29. package/dist/collab/rebase.js +12 -3
  30. package/dist/collab/recovery.d.ts +0 -20
  31. package/dist/collab/recovery.d.ts.map +1 -1
  32. package/dist/components/brandguide/ColorSwatchSettings.d.ts.map +1 -1
  33. package/dist/components/brandguide/ColorsView.d.ts.map +1 -1
  34. package/dist/components/brandguide/colors-shared.d.ts +10 -1
  35. package/dist/components/brandguide/colors-shared.d.ts.map +1 -1
  36. package/dist/components/chat/ChatPanel.d.ts.map +1 -1
  37. package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
  38. package/dist/components/docfile/PdfCanvasViewer.d.ts.map +1 -1
  39. package/dist/components/docfile/doc-file-state.d.ts.map +1 -1
  40. package/dist/components/editor/IndicatorPill.d.ts.map +1 -1
  41. package/dist/components/editor/NavGroupRow.d.ts +7 -2
  42. package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
  43. package/dist/components/editor/PagesModal.d.ts.map +1 -1
  44. package/dist/components/editor/index.js +13 -12
  45. package/dist/components/primitives/EditableRichText.d.ts.map +1 -1
  46. package/dist/components/primitives/LinkPopover.d.ts.map +1 -1
  47. package/dist/components/primitives/index.js +14 -12
  48. package/dist/components/primitives/useEditableCollection.d.ts.map +1 -1
  49. package/dist/components/primitives/useEditablePlainText.d.ts.map +1 -1
  50. package/dist/components/sections/IconList/index.d.ts.map +1 -1
  51. package/dist/components/sections/Prose/Prose.d.ts.map +1 -1
  52. package/dist/components/sections/brand-guide.js +8 -8
  53. package/dist/components/sections/register-schemas.js +14 -14
  54. package/dist/components/sections/register.js +14 -14
  55. package/dist/components/shared/FontPicker.d.ts.map +1 -1
  56. package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
  57. package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
  58. package/dist/components/shared/Navigation.d.ts.map +1 -1
  59. package/dist/components/shared/Popover.d.ts.map +1 -1
  60. package/dist/components/shell/AudienceAddForm.d.ts +1 -5
  61. package/dist/components/shell/AudienceAddForm.d.ts.map +1 -1
  62. package/dist/components/shell/AudienceRow.d.ts +2 -3
  63. package/dist/components/shell/AudienceRow.d.ts.map +1 -1
  64. package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
  65. package/dist/components/shell/EditorShell.d.ts.map +1 -1
  66. package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
  67. package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
  68. package/dist/components/shell/SiteSettingsViewerAccess.d.ts.map +1 -1
  69. package/dist/components/shell/view-branch.d.ts.map +1 -1
  70. package/dist/document/components/DocRail.d.ts.map +1 -1
  71. package/dist/document/components/DocViewer.d.ts.map +1 -1
  72. package/dist/document/components/measure.d.ts.map +1 -1
  73. package/dist/document/components/useDocPages.d.ts.map +1 -1
  74. package/dist/document/engine/blocks.d.ts.map +1 -1
  75. package/dist/document/engine/masonry.d.ts.map +1 -1
  76. package/dist/document/engine/paginate.d.ts.map +1 -1
  77. package/dist/document/engine/settings.d.ts +3 -0
  78. package/dist/document/engine/settings.d.ts.map +1 -1
  79. package/dist/document/index.js +79 -28
  80. package/dist/hooks/useBuildStatus.d.ts.map +1 -1
  81. package/dist/hooks/useDocumentUploads.d.ts +1 -0
  82. package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
  83. package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
  84. package/dist/hooks/useEditorPublish.d.ts.map +1 -1
  85. package/dist/hooks/useFocusTrap.d.ts +6 -0
  86. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  87. package/dist/hooks/useMediaPipeline.d.ts +3 -2
  88. package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
  89. package/dist/hooks/useSanitizedHtml.d.ts +12 -0
  90. package/dist/hooks/useSanitizedHtml.d.ts.map +1 -0
  91. package/dist/index.js +19 -13
  92. package/dist/lib/block-move.d.ts.map +1 -1
  93. package/dist/lib/contrast.d.ts.map +1 -1
  94. package/dist/lib/dexie.d.ts +2 -8
  95. package/dist/lib/dexie.d.ts.map +1 -1
  96. package/dist/lib/dexie.js +21 -49
  97. package/dist/lib/index-ops.d.ts.map +1 -1
  98. package/dist/lib/index-ops.js +43 -23
  99. package/dist/lib/index.js +8 -8
  100. package/dist/lib/loader.d.ts.map +1 -1
  101. package/dist/lib/media-folders.d.ts +12 -4
  102. package/dist/lib/media-folders.d.ts.map +1 -1
  103. package/dist/lib/media-folders.js +12 -2
  104. package/dist/lib/migrate-sections-transform.js +1 -1
  105. package/dist/lib/nav-progress.d.ts +14 -0
  106. package/dist/lib/nav-progress.d.ts.map +1 -0
  107. package/dist/lib/nav-tree.d.ts.map +1 -1
  108. package/dist/lib/nav.d.ts.map +1 -1
  109. package/dist/lib/pages.d.ts.map +1 -1
  110. package/dist/lib/registry.d.ts.map +1 -1
  111. package/dist/lib/registry.js +1 -1
  112. package/dist/lib/sanitize.d.ts +6 -0
  113. package/dist/lib/sanitize.d.ts.map +1 -1
  114. package/dist/lib/timestamp.d.ts.map +1 -1
  115. package/dist/media/index.js +4 -4
  116. package/dist/media/queue.d.ts.map +1 -1
  117. package/dist/media/resolve.d.ts.map +1 -1
  118. package/dist/media/utils.d.ts.map +1 -1
  119. package/dist/media/videoPoster.d.ts.map +1 -1
  120. package/dist/schemas/audience.d.ts +5 -1
  121. package/dist/schemas/audience.d.ts.map +1 -1
  122. package/dist/schemas/audience.js +1 -1
  123. package/dist/schemas/index.js +8 -6
  124. package/dist/schemas/sections.d.ts +12 -0
  125. package/dist/schemas/sections.d.ts.map +1 -1
  126. package/dist/storage/index.d.ts +1 -1
  127. package/dist/storage/index.d.ts.map +1 -1
  128. package/dist/storage/index.js +3 -1
  129. package/dist/storage/types.d.ts +9 -0
  130. package/dist/storage/types.d.ts.map +1 -1
  131. package/dist/types/database.d.ts +0 -3
  132. package/dist/types/database.d.ts.map +1 -1
  133. package/package.json +1 -1
  134. package/src/auth/cookies.ts +11 -0
  135. package/src/auth/index.ts +1 -1
  136. package/src/auth/types.ts +18 -4
  137. package/src/collab/rebase.ts +26 -1
  138. package/src/collab/recovery.ts +29 -3
  139. package/src/components/brandguide/ColorSwatchSettings.tsx +40 -13
  140. package/src/components/brandguide/ColorsEditable.tsx +7 -9
  141. package/src/components/brandguide/ColorsView.tsx +12 -11
  142. package/src/components/brandguide/colors-shared.ts +17 -1
  143. package/src/components/chat/ChatPanel.tsx +19 -0
  144. package/src/components/docfile/DocFilePane.tsx +11 -0
  145. package/src/components/docfile/PdfCanvasViewer.tsx +46 -5
  146. package/src/components/docfile/doc-file-state.ts +7 -0
  147. package/src/components/editor/IndicatorPill.tsx +5 -1
  148. package/src/components/editor/NavGroupRow.tsx +8 -3
  149. package/src/components/editor/PagesModal.tsx +10 -2
  150. package/src/components/primitives/EditableList.tsx +10 -2
  151. package/src/components/primitives/EditableRichText.tsx +4 -3
  152. package/src/components/primitives/LinkPopover.tsx +23 -1
  153. package/src/components/primitives/useEditableCollection.ts +61 -41
  154. package/src/components/primitives/useEditablePlainText.ts +24 -3
  155. package/src/components/sections/IconList/index.tsx +8 -1
  156. package/src/components/sections/Prose/Prose.tsx +4 -2
  157. package/src/components/shared/FontPicker.tsx +16 -4
  158. package/src/components/shared/HistoryChangesModal.tsx +12 -1
  159. package/src/components/shared/HistoryPopover.tsx +18 -4
  160. package/src/components/shared/Navigation.tsx +20 -2
  161. package/src/components/shared/Popover.tsx +9 -5
  162. package/src/components/shell/AudienceAddForm.tsx +6 -26
  163. package/src/components/shell/AudienceRow.tsx +29 -39
  164. package/src/components/shell/BugReportFAB.tsx +20 -2
  165. package/src/components/shell/EditorShell.tsx +200 -50
  166. package/src/components/shell/MediaLibraryModal.tsx +52 -10
  167. package/src/components/shell/SiteSettingsUsers.tsx +3 -0
  168. package/src/components/shell/SiteSettingsViewerAccess.tsx +21 -16
  169. package/src/components/shell/view-branch.ts +4 -1
  170. package/src/document/components/DocRail.tsx +27 -2
  171. package/src/document/components/DocViewer.tsx +5 -1
  172. package/src/document/components/measure.tsx +22 -6
  173. package/src/document/components/useDocPages.ts +13 -3
  174. package/src/document/engine/blocks.ts +33 -4
  175. package/src/document/engine/masonry.ts +8 -2
  176. package/src/document/engine/paginate.ts +4 -1
  177. package/src/document/engine/settings.ts +40 -3
  178. package/src/hooks/useBuildStatus.ts +6 -0
  179. package/src/hooks/useDocumentUploads.ts +46 -3
  180. package/src/hooks/useEditorPersistence.ts +33 -19
  181. package/src/hooks/useEditorPublish.ts +83 -34
  182. package/src/hooks/useFocusTrap.ts +18 -0
  183. package/src/hooks/useMediaPipeline.ts +111 -38
  184. package/src/hooks/useSanitizedHtml.ts +29 -0
  185. package/src/lib/audience-secret.ts +1 -0
  186. package/src/lib/block-move.ts +13 -2
  187. package/src/lib/contrast.ts +14 -14
  188. package/src/lib/dexie.ts +46 -49
  189. package/src/lib/index-ops.ts +63 -20
  190. package/src/lib/loader.ts +41 -12
  191. package/src/lib/media-folders.ts +31 -5
  192. package/src/lib/migrate-sections-transform.ts +22 -2
  193. package/src/lib/nav-progress.ts +108 -0
  194. package/src/lib/nav-tree.ts +16 -2
  195. package/src/lib/nav.ts +10 -1
  196. package/src/lib/pages.ts +24 -6
  197. package/src/lib/registry.ts +3 -0
  198. package/src/lib/sanitize.ts +9 -0
  199. package/src/lib/timestamp.ts +5 -0
  200. package/src/media/queue.ts +4 -0
  201. package/src/media/resolve.ts +14 -1
  202. package/src/media/utils.ts +3 -1
  203. package/src/media/videoPoster.ts +14 -3
  204. package/src/schemas/audience.ts +10 -2
  205. package/src/schemas/sections.ts +23 -1
  206. package/src/storage/index.ts +1 -1
  207. package/src/storage/types.ts +13 -0
  208. package/src/types/database.ts +0 -3
@@ -28,4 +28,12 @@ export interface AudienceClaims {
28
28
  export declare function verifyAudienceClaims(token: string): Promise<AudienceClaims | null>;
29
29
  export declare function verifyAudienceToken(token: string): Promise<string | null>;
30
30
  export declare function setSessionCookie(cookies: CookieLike, token: string, isProduction: boolean): void;
31
+ /**
32
+ * Clear the editor session cookie. Paired with `setSessionCookie` so the `path`
33
+ * cannot drift: cookies are keyed by name+domain+path, so deleting without the
34
+ * matching `path: "/"` emits a Set-Cookie scoped to the request's own directory
35
+ * (e.g. `/api/auth`) and leaves the real cookie untouched — sign-out appeared
36
+ * to work while the session stayed valid for its full 24h lifetime.
37
+ */
38
+ export declare function clearSessionCookie(cookies: CookieLike): void;
31
39
  //# sourceMappingURL=cookies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/auth/cookies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGnD,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,uBAAuB,QAAe,CAAC;AAMpD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAErD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAWxE;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAe/E;AAMD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,EACjB,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAcxF;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/E;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,OAAO,GACpB,IAAI,CAQN"}
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/auth/cookies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGnD,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,uBAAuB,QAAe,CAAC;AAMpD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAErD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAWxE;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAe/E;AAMD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,SAAS,UAAQ,EACjB,QAAQ,GAAE,MAAM,GAAG,IAAW,GAC7B,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAcxF;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE/E;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,OAAO,GACpB,IAAI,CAQN;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAE5D"}
@@ -2,7 +2,7 @@ export type { Role, Session, SiteUser, Audience, SignInMethod, SignInResult, Tok
2
2
  export type { UiCapabilities } from "./capabilities";
3
3
  export { deriveUiCapabilities } from "./capabilities";
4
4
  export { requireSessionSecret, isSameOriginRequest, safeNextPath } from "./security";
5
- export { signSessionToken, verifySessionToken, signAudienceToken, verifyAudienceToken, verifyAudienceClaims, setSessionCookie, SESSION_COOKIE, AUDIENCE_COOKIE, SESSION_MAX_AGE_SECONDS, AUDIENCE_MAX_AGE_SECONDS } from "./cookies";
5
+ export { signSessionToken, verifySessionToken, signAudienceToken, verifyAudienceToken, verifyAudienceClaims, setSessionCookie, clearSessionCookie, SESSION_COOKIE, AUDIENCE_COOKIE, SESSION_MAX_AGE_SECONDS, AUDIENCE_MAX_AGE_SECONDS } from "./cookies";
6
6
  export type { AudienceClaims } from "./cookies";
7
7
  export { LastOwnerError, SessionExpiredError } from "./errors";
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACrO,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACzP,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
@@ -5,6 +5,7 @@ import {
5
5
  SESSION_COOKIE,
6
6
  SESSION_MAX_AGE_SECONDS,
7
7
  SessionExpiredError,
8
+ clearSessionCookie,
8
9
  deriveUiCapabilities,
9
10
  setSessionCookie,
10
11
  signAudienceToken,
@@ -12,7 +13,7 @@ import {
12
13
  verifyAudienceClaims,
13
14
  verifyAudienceToken,
14
15
  verifySessionToken
15
- } from "../chunk-GEENI3OC.js";
16
+ } from "../chunk-SW6PCQQD.js";
16
17
  import {
17
18
  isSameOriginRequest,
18
19
  requireSessionSecret,
@@ -27,6 +28,7 @@ export {
27
28
  SESSION_COOKIE,
28
29
  SESSION_MAX_AGE_SECONDS,
29
30
  SessionExpiredError,
31
+ clearSessionCookie,
30
32
  deriveUiCapabilities,
31
33
  isSameOriginRequest,
32
34
  requireSessionSecret,
@@ -44,7 +44,15 @@ export interface AuthProvider {
44
44
  };
45
45
  audiences: {
46
46
  list(): Promise<Audience[]>;
47
- verify(name: string, password: string): Promise<boolean>;
47
+ /**
48
+ * Audience mode only: the shared password for a chosen audience, which now
49
+ * exists solely in `.env` mode (`VIEWER_<NAME>_PASSWORD`). Optional because
50
+ * the Supabase provider retired the audience-level password entirely —
51
+ * viewers there sign in through `credentials` below. Presence of this and
52
+ * presence of `credentials` are mutually exclusive in practice; the login
53
+ * route picks the branch from `credentials`, never from the client.
54
+ */
55
+ verify?(name: string, password: string): Promise<boolean>;
48
56
  get?(name: string): Promise<Audience | null>;
49
57
  credentials?: {
50
58
  /** Every credential on the site, each carrying the audience it grants. */
@@ -73,8 +81,7 @@ export interface AuthProvider {
73
81
  delete(username: string): Promise<void>;
74
82
  };
75
83
  manage?: {
76
- create(displayName: string, color: string | null, password: string): Promise<void>;
77
- setPassword(name: string, password: string): Promise<void>;
84
+ create(displayName: string, color: string | null): Promise<void>;
78
85
  setColor(name: string, color: string | null): Promise<void>;
79
86
  setDisplayName(name: string, displayName: string): Promise<void>;
80
87
  delete(name: string): Promise<void>;
@@ -102,7 +109,7 @@ export interface CookieLike {
102
109
  value: string;
103
110
  } | undefined;
104
111
  set(name: string, value: string, options?: Record<string, unknown>): void;
105
- delete(name: string): void;
112
+ delete(name: string, options?: Record<string, unknown>): void;
106
113
  }
107
114
  export interface AuthContext {
108
115
  cookies: CookieLike;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,10 @@ import {
6
6
  SettingsIcon,
7
7
  useMediaLibrary,
8
8
  useResolvedMedia
9
- } from "./chunk-ZKVKNUJC.js";
9
+ } from "./chunk-ELQ4C677.js";
10
10
  import {
11
11
  rebindImageRef
12
- } from "./chunk-XBYJQ5RS.js";
12
+ } from "./chunk-XQMDWXD6.js";
13
13
  import {
14
14
  cn
15
15
  } from "./chunk-7EOSDFS3.js";
@@ -37,15 +37,23 @@ function useEditablePlainText({
37
37
  lastPropValue.current = propValue;
38
38
  }
39
39
  }, [propValue]);
40
+ const onChangeRef = useRef(onChange);
41
+ useEffect(() => {
42
+ onChangeRef.current = onChange;
43
+ }, [onChange]);
40
44
  const handleInput = useCallback((text) => {
41
45
  setValue(text);
46
+ if (text !== lastPropValue.current) {
47
+ lastPropValue.current = text;
48
+ onChangeRef.current(text);
49
+ }
42
50
  }, []);
43
51
  const handleBlur = useCallback(() => {
44
- if (value !== propValue) {
45
- onChange(value);
52
+ if (value !== lastPropValue.current) {
46
53
  lastPropValue.current = value;
54
+ onChangeRef.current(value);
47
55
  }
48
- }, [value, propValue, onChange]);
56
+ }, [value]);
49
57
  return {
50
58
  value,
51
59
  handleInput,
@@ -376,70 +384,71 @@ function useEditableCollection({
376
384
  () => wrapItems(items)
377
385
  );
378
386
  const prevItemsRef = useRef3(items);
387
+ const wrappedRef = useRef3(wrappedItems);
388
+ wrappedRef.current = wrappedItems;
389
+ const commit = useCallback3(
390
+ (next) => {
391
+ wrappedRef.current = next;
392
+ setWrappedItems(next);
393
+ onChange(next.map((w) => w.data));
394
+ },
395
+ [onChange]
396
+ );
379
397
  useEffect3(() => {
380
398
  if (items === prevItemsRef.current) return;
381
399
  prevItemsRef.current = items;
382
400
  setWrappedItems((prev) => {
383
- return items.map((data, i) => {
384
- if (i < prev.length) {
385
- return { id: prev[i].id, data };
386
- }
387
- return { id: uid(), data };
401
+ const taken = new Array(prev.length).fill(false);
402
+ const slotsByData = /* @__PURE__ */ new Map();
403
+ prev.forEach((w, i) => {
404
+ const bucket = slotsByData.get(w.data);
405
+ if (bucket) bucket.push(i);
406
+ else slotsByData.set(w.data, [i]);
388
407
  });
408
+ const matched = items.map((data) => {
409
+ const slot = slotsByData.get(data)?.shift();
410
+ if (slot === void 0) return null;
411
+ taken[slot] = true;
412
+ return prev[slot].id;
413
+ });
414
+ const spare = prev.filter((_, i) => !taken[i]).map((w) => w.id);
415
+ let next = 0;
416
+ return items.map((data, i) => ({ id: matched[i] ?? spare[next++] ?? uid(), data }));
389
417
  });
390
418
  }, [items]);
391
419
  const onReorder = useCallback3(
392
420
  (fromIndex, toIndex) => {
393
- setWrappedItems((prev) => {
394
- const next = [...prev];
395
- const [moved] = next.splice(fromIndex, 1);
396
- next.splice(toIndex, 0, moved);
397
- onChange(next.map((w) => w.data));
398
- return next;
399
- });
421
+ const next = [...wrappedRef.current];
422
+ const [moved] = next.splice(fromIndex, 1);
423
+ next.splice(toIndex, 0, moved);
424
+ commit(next);
400
425
  },
401
- [onChange]
426
+ [commit]
402
427
  );
403
428
  const onAdd = useCallback3(() => {
404
- const newItem = createItem();
405
- setWrappedItems((prev) => {
406
- const next = [...prev, { id: uid(), data: newItem }];
407
- onChange(next.map((w) => w.data));
408
- return next;
409
- });
410
- }, [createItem, onChange]);
429
+ commit([...wrappedRef.current, { id: uid(), data: createItem() }]);
430
+ }, [createItem, commit]);
411
431
  const onInsert = useCallback3(
412
432
  (index) => {
413
- const newItem = createItem();
414
- setWrappedItems((prev) => {
415
- const next = [...prev];
416
- next.splice(index, 0, { id: uid(), data: newItem });
417
- onChange(next.map((w) => w.data));
418
- return next;
419
- });
433
+ const next = [...wrappedRef.current];
434
+ next.splice(index, 0, { id: uid(), data: createItem() });
435
+ commit(next);
420
436
  },
421
- [createItem, onChange]
437
+ [createItem, commit]
422
438
  );
423
439
  const onInsertItem = useCallback3(
424
440
  (index, data) => {
425
- setWrappedItems((prev) => {
426
- const next = [...prev];
427
- next.splice(index, 0, { id: uid(), data });
428
- onChange(next.map((w) => w.data));
429
- return next;
430
- });
441
+ const next = [...wrappedRef.current];
442
+ next.splice(index, 0, { id: uid(), data });
443
+ commit(next);
431
444
  },
432
- [onChange]
445
+ [commit]
433
446
  );
434
447
  const onRemove = useCallback3(
435
448
  (id) => {
436
- setWrappedItems((prev) => {
437
- const next = prev.filter((w) => w.id !== id);
438
- onChange(next.map((w) => w.data));
439
- return next;
440
- });
449
+ commit(wrappedRef.current.filter((w) => w.id !== id));
441
450
  },
442
- [onChange]
451
+ [commit]
443
452
  );
444
453
  return { wrappedItems, onReorder, onAdd, onInsert, onInsertItem, onRemove };
445
454
  }
@@ -32,15 +32,34 @@ var sectionSettingsSchema = z.object({
32
32
  ]).default({ mode: "masonry", flow: "rows", columns: 3, rows: "auto" })
33
33
  });
34
34
  var DEFAULTS = sectionSettingsSchema.parse({});
35
+ function salvage(raw) {
36
+ const fast = sectionSettingsSchema.safeParse(raw ?? {});
37
+ if (fast.success) return { settings: fast.data, rejected: [] };
38
+ if (!raw || typeof raw !== "object") return { settings: DEFAULTS, rejected: [] };
39
+ const src = raw;
40
+ const out = {};
41
+ const rejected = [];
42
+ for (const [key, field] of Object.entries(sectionSettingsSchema.shape)) {
43
+ const parsed = field.safeParse(src[key]);
44
+ if (parsed.success) {
45
+ out[key] = parsed.data;
46
+ } else {
47
+ rejected.push(key);
48
+ out[key] = DEFAULTS[key];
49
+ }
50
+ }
51
+ return { settings: out, rejected };
52
+ }
35
53
  function settingsFor(all, chunkId) {
36
- const raw = all?.[chunkId];
37
- const parsed = sectionSettingsSchema.safeParse(raw ?? {});
38
- const s = parsed.success ? parsed.data : DEFAULTS;
54
+ const s = salvage(all?.[chunkId]).settings;
39
55
  if (s.textPlacement === "top" && s.imagePlacement === "right") {
40
56
  return { ...s, imagePlacement: "fullWidth" };
41
57
  }
42
58
  return s;
43
59
  }
60
+ function settingsIssuesFor(all, chunkId) {
61
+ return salvage(all?.[chunkId]).rejected;
62
+ }
44
63
  var documentMetaSchema = z.object({
45
64
  client: z.string().default(""),
46
65
  project: z.string().default(""),
@@ -68,5 +87,6 @@ var documentOptionsSchema = z.object({
68
87
  export {
69
88
  sectionSettingsSchema,
70
89
  settingsFor,
90
+ settingsIssuesFor,
71
91
  documentOptionsSchema
72
92
  };
@@ -1,20 +1,22 @@
1
1
  import {
2
2
  EditablePlainText
3
- } from "./chunk-WXBHP4JY.js";
3
+ } from "./chunk-3GAG6ZXB.js";
4
4
  import {
5
5
  Button,
6
6
  usePages
7
- } from "./chunk-XIDE4TDF.js";
7
+ } from "./chunk-OUYB2GCW.js";
8
8
  import {
9
+ ensureSanitizer,
10
+ isSanitizerReady,
9
11
  sanitizeHtml,
10
12
  toSectionId
11
- } from "./chunk-72CG6AA2.js";
13
+ } from "./chunk-RA5IOFPY.js";
12
14
  import {
13
15
  cn
14
16
  } from "./chunk-7EOSDFS3.js";
15
17
  import {
16
18
  defineSection
17
- } from "./chunk-VKAGMEKE.js";
19
+ } from "./chunk-FTPETWXE.js";
18
20
 
19
21
  // src/components/primitives/defineHeadingSection.tsx
20
22
  import { z } from "zod";
@@ -77,7 +79,7 @@ function defineHeadingSection(config) {
77
79
  }
78
80
 
79
81
  // src/components/primitives/LinkPopover.tsx
80
- import { useState } from "react";
82
+ import { useEffect, useRef, useState } from "react";
81
83
 
82
84
  // src/lib/links.ts
83
85
  function internalHref(pageId, anchorSectionId) {
@@ -104,6 +106,21 @@ function LinkPopover({ editor, onClose }) {
104
106
  );
105
107
  const hasLink = Boolean(existingAttrs.href);
106
108
  const headings = pageId ? getPageHeadings(pageId) : [];
109
+ const panelRef = useRef(null);
110
+ useEffect(() => {
111
+ function onMouseDown(e) {
112
+ if (panelRef.current && !panelRef.current.contains(e.target)) onClose();
113
+ }
114
+ function onKeyDown(e) {
115
+ if (e.key === "Escape") onClose();
116
+ }
117
+ document.addEventListener("mousedown", onMouseDown);
118
+ document.addEventListener("keydown", onKeyDown);
119
+ return () => {
120
+ document.removeEventListener("mousedown", onMouseDown);
121
+ document.removeEventListener("keydown", onKeyDown);
122
+ };
123
+ }, [onClose]);
107
124
  const handleApply = () => {
108
125
  if (mode === "internal") {
109
126
  if (pageId) {
@@ -130,6 +147,7 @@ function LinkPopover({ editor, onClose }) {
130
147
  return /* @__PURE__ */ jsxs(
131
148
  "div",
132
149
  {
150
+ ref: panelRef,
133
151
  className: "flex w-64 flex-col gap-2 rounded bg-base-accent p-3 shadow-lg",
134
152
  onMouseDown: (e) => e.stopPropagation(),
135
153
  onKeyDown: handleKeyDown,
@@ -250,12 +268,29 @@ function LinkPopover({ editor, onClose }) {
250
268
  }
251
269
 
252
270
  // src/components/primitives/EditableRichText.tsx
253
- import { useRef as useRef2, useCallback as useCallback2, useEffect as useEffect2 } from "react";
271
+ import { useRef as useRef3, useCallback as useCallback2, useEffect as useEffect4 } from "react";
254
272
  import { EditorContent } from "@tiptap/react";
255
273
  import { BubbleMenu } from "@tiptap/react/menus";
256
274
 
275
+ // src/hooks/useSanitizedHtml.ts
276
+ import { useEffect as useEffect2, useState as useState2 } from "react";
277
+ function useSanitizedHtml(html) {
278
+ const [ready, setReady] = useState2(isSanitizerReady);
279
+ useEffect2(() => {
280
+ if (ready) return;
281
+ let alive = true;
282
+ void ensureSanitizer().then(() => {
283
+ if (alive) setReady(true);
284
+ });
285
+ return () => {
286
+ alive = false;
287
+ };
288
+ }, [ready]);
289
+ return ready ? sanitizeHtml(html) : "";
290
+ }
291
+
257
292
  // src/components/primitives/useEditableRichText.ts
258
- import { useState as useState2, useRef, useCallback, useEffect } from "react";
293
+ import { useState as useState3, useRef as useRef2, useCallback, useEffect as useEffect3 } from "react";
259
294
  import { Editor } from "@tiptap/core";
260
295
  import Placeholder from "@tiptap/extension-placeholder";
261
296
 
@@ -390,14 +425,14 @@ function useEditableRichText({
390
425
  preset,
391
426
  placeholder
392
427
  }) {
393
- const editorRef = useRef(null);
394
- const [editor, setEditor] = useState2(null);
395
- const valueRef = useRef(value);
396
- const onChangeRef = useRef(onChange);
397
- useEffect(() => {
428
+ const editorRef = useRef2(null);
429
+ const [editor, setEditor] = useState3(null);
430
+ const valueRef = useRef2(value);
431
+ const onChangeRef = useRef2(onChange);
432
+ useEffect3(() => {
398
433
  valueRef.current = value;
399
434
  }, [value]);
400
- useEffect(() => {
435
+ useEffect3(() => {
401
436
  onChangeRef.current = onChange;
402
437
  }, [onChange]);
403
438
  const activate = useCallback(() => {
@@ -433,7 +468,7 @@ function useEditableRichText({
433
468
  onChangeRef.current(html);
434
469
  }
435
470
  }, []);
436
- useEffect(() => {
471
+ useEffect3(() => {
437
472
  return () => {
438
473
  editorRef.current?.destroy();
439
474
  editorRef.current = null;
@@ -448,7 +483,7 @@ function useEditableRichText({
448
483
  }
449
484
 
450
485
  // src/components/primitives/RichTextToolbar.tsx
451
- import { useState as useState3 } from "react";
486
+ import { useState as useState4 } from "react";
452
487
  import { useEditorState } from "@tiptap/react";
453
488
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
454
489
  function ToolbarButton({ isActive, onClick, title, children }) {
@@ -475,7 +510,7 @@ function Separator() {
475
510
  return /* @__PURE__ */ jsx4("div", { className: "mx-1 h-5 w-px bg-base-contrast/20" });
476
511
  }
477
512
  function RichTextToolbar({ editor, preset }) {
478
- const [showLinkPopover, setShowLinkPopover] = useState3(false);
513
+ const [showLinkPopover, setShowLinkPopover] = useState4(false);
479
514
  const state = useEditorState({
480
515
  editor,
481
516
  selector: ({ editor: ed }) => ({
@@ -628,17 +663,18 @@ function EditableRichText({
628
663
  placeholder = DEFAULT_PLACEHOLDER
629
664
  }) {
630
665
  const { isEditorActive, editor, activate, deactivate } = useEditableRichText({ value, onChange, preset, placeholder });
631
- const wrapperRef = useRef2(null);
632
- const blurTimeoutRef = useRef2(null);
633
- const clickCoordsRef = useRef2(null);
634
- useEffect2(() => {
666
+ const wrapperRef = useRef3(null);
667
+ const safeHtml = useSanitizedHtml(value);
668
+ const blurTimeoutRef = useRef3(null);
669
+ const clickCoordsRef = useRef3(null);
670
+ useEffect4(() => {
635
671
  return () => {
636
672
  if (blurTimeoutRef.current) {
637
673
  clearTimeout(blurTimeoutRef.current);
638
674
  }
639
675
  };
640
676
  }, []);
641
- useEffect2(() => {
677
+ useEffect4(() => {
642
678
  if (!isEditorActive || !editor) return;
643
679
  requestAnimationFrame(() => {
644
680
  if (editor.isDestroyed) return;
@@ -686,7 +722,7 @@ function EditableRichText({
686
722
  "div",
687
723
  {
688
724
  className,
689
- dangerouslySetInnerHTML: { __html: sanitizeHtml(value) }
725
+ dangerouslySetInnerHTML: { __html: safeHtml }
690
726
  }
691
727
  );
692
728
  }
@@ -700,7 +736,7 @@ function EditableRichText({
700
736
  {
701
737
  className,
702
738
  onClick: handleClick,
703
- dangerouslySetInnerHTML: { __html: sanitizeHtml(value) }
739
+ dangerouslySetInnerHTML: { __html: safeHtml }
704
740
  }
705
741
  );
706
742
  }
@@ -732,6 +768,7 @@ function EditableRichText({
732
768
 
733
769
  export {
734
770
  defineHeadingSection,
771
+ useSanitizedHtml,
735
772
  LinkPopover,
736
773
  EditableRichText
737
774
  };
@@ -5,7 +5,7 @@ import {
5
5
  Button,
6
6
  LinkField,
7
7
  Select
8
- } from "./chunk-XIDE4TDF.js";
8
+ } from "./chunk-OUYB2GCW.js";
9
9
  import {
10
10
  DeleteIcon,
11
11
  DragHandle,
@@ -15,10 +15,10 @@ import {
15
15
  SettingsIcon,
16
16
  useMediaLibrary,
17
17
  useResolvedMedia
18
- } from "./chunk-ZKVKNUJC.js";
18
+ } from "./chunk-ELQ4C677.js";
19
19
  import {
20
20
  formatFileSize
21
- } from "./chunk-XBYJQ5RS.js";
21
+ } from "./chunk-XQMDWXD6.js";
22
22
  import {
23
23
  cn
24
24
  } from "./chunk-7EOSDFS3.js";
@@ -500,37 +500,12 @@ var FOCUSABLE_SELECTOR = [
500
500
  "textarea:not([disabled])",
501
501
  '[tabindex]:not([tabindex="-1"])'
502
502
  ].join(", ");
503
- function useFocusTrap(ref, active) {
503
+ function useInitialFocus(ref, active) {
504
504
  useEffect(() => {
505
505
  if (!active || !ref.current) return;
506
- const container = ref.current;
507
506
  const previouslyFocused = document.activeElement;
508
- const getFocusable = () => Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
509
- const focusable = getFocusable();
510
- if (focusable.length > 0) {
511
- focusable[0].focus();
512
- }
513
- const handleKeyDown = (e) => {
514
- if (e.key !== "Tab") return;
515
- const elements = getFocusable();
516
- if (elements.length === 0) return;
517
- const first = elements[0];
518
- const last = elements[elements.length - 1];
519
- if (e.shiftKey) {
520
- if (document.activeElement === first) {
521
- e.preventDefault();
522
- last.focus();
523
- }
524
- } else {
525
- if (document.activeElement === last) {
526
- e.preventDefault();
527
- first.focus();
528
- }
529
- }
530
- };
531
- container.addEventListener("keydown", handleKeyDown);
507
+ ref.current.querySelector(FOCUSABLE_SELECTOR)?.focus();
532
508
  return () => {
533
- container.removeEventListener("keydown", handleKeyDown);
534
509
  if (previouslyFocused && document.body.contains(previouslyFocused)) {
535
510
  previouslyFocused.focus();
536
511
  }
@@ -553,7 +528,7 @@ function Popover({
553
528
  const panelRef = useRef(null);
554
529
  const [resolvedAlign, setResolvedAlign] = useState4("start");
555
530
  const [fixedPos, setFixedPos] = useState4(null);
556
- useFocusTrap(panelRef, isOpen && (!portal || fixedPos !== null));
531
+ useInitialFocus(panelRef, isOpen && (!portal || fixedPos !== null));
557
532
  useLayoutEffect(() => {
558
533
  if (!portal) return;
559
534
  if (!isOpen) {
@@ -9,7 +9,7 @@ import {
9
9
  stripHtmlToPlainText,
10
10
  trimTrailingSpacers,
11
11
  truncate
12
- } from "./chunk-67ZOQCUD.js";
12
+ } from "./chunk-NXGIHSL5.js";
13
13
  import {
14
14
  DeleteButton,
15
15
  DragHandle,
@@ -23,11 +23,12 @@ import {
23
23
  buildBlockDropData,
24
24
  canDropBlock,
25
25
  isBlockDragData
26
- } from "./chunk-WBDPDGFA.js";
26
+ } from "./chunk-7WQJ57XG.js";
27
27
  import {
28
28
  EditableRichText,
29
- defineHeadingSection
30
- } from "./chunk-5PVRACZY.js";
29
+ defineHeadingSection,
30
+ useSanitizedHtml
31
+ } from "./chunk-7MI3HCOF.js";
31
32
  import {
32
33
  EditablePlainText,
33
34
  ImageDropZone,
@@ -37,11 +38,11 @@ import {
37
38
  containerGridClass,
38
39
  masonryColumnsClass,
39
40
  spacerHiddenClass
40
- } from "./chunk-WXBHP4JY.js";
41
+ } from "./chunk-3GAG6ZXB.js";
41
42
  import {
42
43
  useMediaLibrary,
43
44
  useResolvedMedia
44
- } from "./chunk-ZKVKNUJC.js";
45
+ } from "./chunk-ELQ4C677.js";
45
46
  import {
46
47
  embedUrl
47
48
  } from "./chunk-Y4JQGO6G.js";
@@ -49,19 +50,16 @@ import {
49
50
  DEFAULT_LINK,
50
51
  LinkValueSchema
51
52
  } from "./chunk-3ZRQ4G5F.js";
52
- import {
53
- sanitizeHtml
54
- } from "./chunk-72CG6AA2.js";
55
53
  import {
56
54
  cn
57
55
  } from "./chunk-7EOSDFS3.js";
58
56
  import {
59
57
  getSectionSchema
60
- } from "./chunk-TZQPOR5A.js";
58
+ } from "./chunk-DMCGN5AS.js";
61
59
  import {
62
60
  defineSection,
63
61
  getSection
64
- } from "./chunk-VKAGMEKE.js";
62
+ } from "./chunk-FTPETWXE.js";
65
63
  import {
66
64
  SingleMediaReferenceSchema
67
65
  } from "./chunk-GGXZZ77Z.js";
@@ -117,6 +115,7 @@ import { AlignLeft } from "lucide-react";
117
115
  // src/components/sections/Prose/Prose.tsx
118
116
  import { jsx as jsx4 } from "react/jsx-runtime";
119
117
  function Prose({ body, onChange }) {
118
+ const safeHtml = useSanitizedHtml(body);
120
119
  if (onChange) {
121
120
  return /* @__PURE__ */ jsx4("div", { className: "prose-content", children: /* @__PURE__ */ jsx4(
122
121
  EditableRichText,
@@ -133,7 +132,7 @@ function Prose({ body, onChange }) {
133
132
  "div",
134
133
  {
135
134
  className: "prose-content",
136
- dangerouslySetInnerHTML: { __html: sanitizeHtml(body) }
135
+ dangerouslySetInnerHTML: { __html: safeHtml }
137
136
  }
138
137
  );
139
138
  }