@panphora/clayjs 1.23.0 → 1.24.1

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 (471) hide show
  1. package/dist/all.js +1 -1
  2. package/dist/blockeditor/themes/light-1.css +431 -0
  3. package/dist/clay-dom.js +1 -1
  4. package/dist/clay-events.js +1 -1
  5. package/dist/clay-internals.js +1 -1
  6. package/dist/clay-options.js +1 -1
  7. package/dist/clay-router.js +1 -1
  8. package/dist/clay-ui.js +1 -1
  9. package/dist/clay-utils.js +1 -1
  10. package/dist/clay.js +1 -1
  11. package/dist/clay.standalone.js +30285 -26613
  12. package/dist/m/c-277QP5ET.js +1 -0
  13. package/dist/m/c-2BLVA6IN.js +5 -0
  14. package/dist/m/c-2OJMOUPC.js +1 -0
  15. package/dist/m/c-2PVGJFI5.js +1 -0
  16. package/dist/m/{c-AYVGD6A6.js → c-3UW5EJ77.js} +1 -1
  17. package/dist/m/{c-T5NK2TVY.js → c-42ZNV7LI.js} +1 -1
  18. package/dist/m/{c-3TLG3OLG.js → c-46LJAZZJ.js} +1 -1
  19. package/dist/m/c-47IBJGPQ.js +1 -0
  20. package/dist/m/c-5FXEKU4Y.js +1 -0
  21. package/dist/m/c-5KXDKC5G.js +1 -0
  22. package/dist/m/{c-EUGJVHDD.js → c-5RZNFTWD.js} +1 -1
  23. package/dist/m/c-65LJU2H2.js +72 -0
  24. package/dist/m/{c-NQJRVJ56.js → c-6IJEVE6B.js} +1 -1
  25. package/dist/m/{c-NW54NHKE.js → c-6LEYVQJK.js} +1 -1
  26. package/dist/m/{c-GSRLXYWL.js → c-6Q6RGFBF.js} +1 -1
  27. package/dist/m/c-6RGEQNVV.js +1 -0
  28. package/dist/m/c-7CM4GMTS.js +6 -0
  29. package/dist/m/c-7NCWENHV.js +1 -0
  30. package/dist/m/c-7V6MGMX2.js +1 -0
  31. package/dist/m/{c-LKSL4AUJ.js → c-7WZSUTYP.js} +1 -1
  32. package/dist/m/c-A4L7APIU.js +1 -0
  33. package/dist/m/c-APGHGDZM.js +1 -0
  34. package/dist/m/c-AT7GLQGV.js +34 -0
  35. package/dist/m/{c-ZRXJD4G6.js → c-B7GOFGQR.js} +1 -1
  36. package/dist/m/{c-KDXIJEEF.js → c-BGN7RCTJ.js} +1 -1
  37. package/dist/m/c-BKM46LUJ.js +1 -0
  38. package/dist/m/c-BOMQIQ3V.js +1 -0
  39. package/dist/m/{c-62HZW5DH.js → c-C5AKJVRH.js} +1 -1
  40. package/dist/m/{c-BXYSDKAN.js → c-CJ7QYEWI.js} +1 -1
  41. package/dist/m/c-CTGRDT6E.js +1 -0
  42. package/dist/m/c-CV4T65JE.js +6 -0
  43. package/dist/m/c-CVSWLX3X.js +1 -0
  44. package/dist/m/c-CZHTXGJS.js +1 -0
  45. package/dist/m/c-D7NT5S4F.js +1 -0
  46. package/dist/m/c-DD26VXAP.js +1 -0
  47. package/dist/m/{c-ANNFZFLN.js → c-DDS23EY6.js} +1 -1
  48. package/dist/m/{c-ALDVFPWL.js → c-DFKBGSN2.js} +1 -1
  49. package/dist/m/c-DIKR7H57.js +147 -0
  50. package/dist/m/c-DXPOFLEJ.js +1 -0
  51. package/dist/m/c-EDE45NM7.js +1 -0
  52. package/dist/m/c-EILLN2H2.js +1 -0
  53. package/dist/m/c-EODTTNVA.js +1 -0
  54. package/dist/m/{c-G6COVIZB.js → c-ESK4S67I.js} +1 -1
  55. package/dist/m/c-FDWR3FL7.js +1 -0
  56. package/dist/m/{c-WQZTI5P2.js → c-FEC6LGFF.js} +1 -1
  57. package/dist/m/c-FLEIU6CG.js +1 -0
  58. package/dist/m/c-FQAQRXGK.js +1 -0
  59. package/dist/m/{c-W4JCVLAB.js → c-FSQXFG5T.js} +1 -1
  60. package/dist/m/c-FVPNX2GO.js +135 -0
  61. package/dist/m/c-FYDKYW6E.js +1 -0
  62. package/dist/m/c-GNI7WHKF.js +32 -0
  63. package/dist/m/c-GO635CRU.js +3 -0
  64. package/dist/m/c-H3FNLBHN.js +2 -0
  65. package/dist/m/c-HDVH3MVC.js +72 -0
  66. package/dist/m/c-HIX5H5L7.js +1 -0
  67. package/dist/m/c-HKSLOVU4.js +1 -0
  68. package/dist/m/{c-SGRIYOAJ.js → c-HL6BLJNA.js} +1 -1
  69. package/dist/m/c-HTLYXCUH.js +1 -0
  70. package/dist/m/{c-QIR5CAKM.js → c-IUL7PU4P.js} +1 -1
  71. package/dist/m/c-IXO7EI2Q.js +1 -0
  72. package/dist/m/{c-W5E5P2TZ.js → c-JQF2EUCG.js} +1 -1
  73. package/dist/m/{c-NEL7HQW3.js → c-JWDCQL6J.js} +1 -1
  74. package/dist/m/c-KQKKIVLW.js +20 -0
  75. package/dist/m/c-LATNQ6Q5.js +1 -0
  76. package/dist/m/c-LD6UVV5R.js +1 -0
  77. package/dist/m/c-LS7IVQVW.js +1 -0
  78. package/dist/m/{c-JCOQVZYS.js → c-LSVN3OLG.js} +1 -1
  79. package/dist/m/{c-JDZDF2QM.js → c-LTSPHVAK.js} +1 -1
  80. package/dist/m/c-MFOSMAVM.js +3 -0
  81. package/dist/m/c-MJ7GVE46.js +1 -0
  82. package/dist/m/c-MP6S4AZU.js +6 -0
  83. package/dist/m/c-MQKSKQHG.js +2 -0
  84. package/dist/m/{c-UHUNXWKN.js → c-MQYEDF3Q.js} +1 -1
  85. package/dist/m/{c-IHUWUKIU.js → c-MR75YPRT.js} +1 -1
  86. package/dist/m/c-ND3Q2G2I.js +1 -0
  87. package/dist/m/c-NEQRFC4O.js +1 -0
  88. package/dist/m/{c-5FKRZNJV.js → c-NFQFV7OP.js} +1 -1
  89. package/dist/m/c-NHXOBD6A.js +1 -0
  90. package/dist/m/{c-QIKT6SKM.js → c-NICICT4P.js} +1 -1
  91. package/dist/m/c-NQAPWM7O.js +1 -0
  92. package/dist/m/{c-QUGCKMWF.js → c-NVU3DORS.js} +1 -1
  93. package/dist/m/{c-LWIDDWAR.js → c-OCYG4NBQ.js} +22 -22
  94. package/dist/m/c-OH2FPYSY.js +19 -0
  95. package/dist/m/c-OYHI67B6.js +1 -0
  96. package/dist/m/{c-R2XUODVY.js → c-OYW5MFPZ.js} +1 -1
  97. package/dist/m/{c-5B4YBZXC.js → c-P2HKMJAW.js} +1 -1
  98. package/dist/m/{c-TSBVMWAH.js → c-PCNJETUA.js} +1 -1
  99. package/dist/m/c-PDBNCJCT.js +1 -0
  100. package/dist/m/c-PGSBXHUE.js +1 -0
  101. package/dist/m/{c-5TIZ2I64.js → c-PYG2NGWU.js} +1 -1
  102. package/dist/m/c-Q26XHBLQ.js +1 -0
  103. package/dist/m/c-Q6BG3ZLO.js +1 -0
  104. package/dist/m/c-QENKN7QI.js +1 -0
  105. package/dist/m/c-QQFHEODI.js +1 -0
  106. package/dist/m/c-QTEUO2K6.js +1 -0
  107. package/dist/m/c-R23UHMXG.js +1 -0
  108. package/dist/m/c-RETTCOWO.js +10 -0
  109. package/dist/m/c-SE3SIY7Y.js +7 -0
  110. package/dist/m/{c-XX75FFNL.js → c-SGGGCIVD.js} +1 -1
  111. package/dist/m/c-SGH3UTF3.js +1 -0
  112. package/dist/m/c-SIM7Z3U7.js +1 -0
  113. package/dist/m/{c-X5LNHET5.js → c-SKMIR5HQ.js} +1 -1
  114. package/dist/m/{c-R27DWQKX.js → c-STRI73GQ.js} +1 -1
  115. package/dist/m/c-SUXHUL7U.js +1 -0
  116. package/dist/m/c-SXGEWPFC.js +10 -0
  117. package/dist/m/c-SXNSSHPP.js +1 -0
  118. package/dist/m/c-T3P3AXEW.js +1 -0
  119. package/dist/m/{c-PXLTUYZC.js → c-TFLRT5JX.js} +1 -1
  120. package/dist/m/{c-YCLU4UNT.js → c-TGIMBAWE.js} +1 -1
  121. package/dist/m/c-TGSHHFO6.js +1 -0
  122. package/dist/m/c-U4NTUVDZ.js +1 -0
  123. package/dist/m/c-UOOIF2AL.js +1 -0
  124. package/dist/m/{c-6TYGD5AB.js → c-UOUUI265.js} +1 -1
  125. package/dist/m/c-V2U3F4QX.js +1 -0
  126. package/dist/m/c-V2V5FKXX.js +1 -0
  127. package/dist/m/c-VBXRXTVS.js +26 -0
  128. package/dist/m/c-VHSMPITY.js +1 -0
  129. package/dist/m/c-VPXCXBDT.js +1 -0
  130. package/dist/m/c-WCG6AKA7.js +1 -0
  131. package/dist/m/c-WNOLMHI2.js +1 -0
  132. package/dist/m/{c-CRPIDGXC.js → c-X6MOYATI.js} +1 -1
  133. package/dist/m/{c-FQGHR32O.js → c-X75G43SZ.js} +1 -1
  134. package/dist/m/c-XB6EAIAR.js +13 -0
  135. package/dist/m/c-XMIDHEKF.js +1 -0
  136. package/dist/m/c-XUZMRQ7O.js +4 -0
  137. package/dist/m/{c-2Z22FCFK.js → c-XW5TIYYB.js} +1 -1
  138. package/dist/m/c-YDW4VCHP.js +1 -0
  139. package/dist/m/{c-QGAPG7OM.js → c-YLHTD3KX.js} +1 -1
  140. package/dist/m/c-YNIEIPBS.js +1 -0
  141. package/dist/m/c-Z4G2UK6T.js +4 -0
  142. package/dist/m/c-Z6MROEQ4.js +1 -0
  143. package/dist/m/c-ZFO5RW6G.js +2 -0
  144. package/dist/m/c-ZGCO4J3H.js +8 -0
  145. package/dist/m/c-ZKKAF4UT.js +3 -0
  146. package/dist/m/c-ZRGEN6QQ.js +4 -0
  147. package/dist/m/core/{admin-attrs-U7IJNYBG.js → admin-attrs-ONRWVXPK.js} +1 -1
  148. package/dist/m/core/{autosave-F5YQCKVL.js → autosave-TBKAAAFB.js} +1 -1
  149. package/dist/m/core/conflict-notice-FOEE6I7E.js +1 -0
  150. package/dist/m/core/draft-mode-4MCL3LYI.js +1 -0
  151. package/dist/m/core/{host-permission-6EVJGNPL.js → host-permission-X4BENZEU.js} +1 -1
  152. package/dist/m/core/{is-edit-mode-GCX6767E.js → is-edit-mode-FFHCQ5DR.js} +1 -1
  153. package/dist/m/core/{persist-CJXIL7D4.js → persist-6ILUR34S.js} +1 -1
  154. package/dist/m/core/{recovery-DRFZRJED.js → recovery-APWADU4K.js} +1 -1
  155. package/dist/m/core/save-6HT2LABE.js +1 -0
  156. package/dist/m/core/save-core-EVMNZQ4V.js +1 -0
  157. package/dist/m/core/site-edits-G4BOZMV4.js +1 -0
  158. package/dist/m/core/{unsaved-warning-HNQVTA2D.js → unsaved-warning-ITZDIZ2I.js} +1 -1
  159. package/dist/m/internals/{index-NRPNDTSA.js → index-HS3CQDFW.js} +1 -1
  160. package/dist/m/loader-GLLVDUZA.js +1 -0
  161. package/dist/m/manifest-50FF1C45.js +1 -0
  162. package/dist/m/manifest-edit-BE1A621D.js +1 -0
  163. package/dist/m/manifest.json +2072 -1811
  164. package/dist/m/page/editor-KAZDJNND.js +307 -0
  165. package/dist/m/plugins/ai-edit-LABECCSN.js +6 -0
  166. package/dist/m/plugins/{cms-H7DTMUQX.js → cms-T2HLI7JG.js} +16 -16
  167. package/dist/m/plugins/{demo-42BSYQ7T.js → demo-T7B4RIKL.js} +1 -1
  168. package/dist/m/plugins/{derive-QVI3LI3A.js → derive-6LPJOCAV.js} +1 -1
  169. package/dist/m/plugins/indicator-J4ABFARX.js +1 -0
  170. package/dist/m/plugins/{live-DCUBKXY4.js → live-PGBIEMGB.js} +1 -1
  171. package/dist/m/plugins/menu-YZL3X2AJ.js +1 -0
  172. package/dist/m/plugins/page-WOCNX2IN.js +2 -0
  173. package/dist/m/plugins/page-view-SJODOOGE.js +1 -0
  174. package/dist/m/plugins/{people-5XRNRP5U.js → people-C4TCWFOQ.js} +1 -1
  175. package/dist/m/plugins/{quickcrop-WWF5I422.js → quickcrop-X5MRIBAP.js} +2 -2
  176. package/dist/m/plugins/richclay-Y2NV44NA.js +549 -0
  177. package/dist/m/plugins/sortable-XCHQG65Z.js +1 -0
  178. package/dist/m/plugins/{source-6BKMK4PO.js → source-YK7MO23W.js} +1 -1
  179. package/dist/m/plugins/{undo-3JEYK5QY.js → undo-VLRBQNPN.js} +1 -1
  180. package/dist/m/plugins/upgrade-NNTJBSK2.js +1 -0
  181. package/dist/m/plugins/{upload-TTCQRIM5.js → upload-ZKKJV76X.js} +1 -1
  182. package/dist/m/plugins/visitor-drafts-RTZNONHT.js +20 -0
  183. package/dist/m/plugins/{visitor-drafts-owner-Z5B2OQBR.js → visitor-drafts-owner-LHUHFU3L.js} +1 -1
  184. package/dist/m/plugins/{visitor-menu-4LQMKLPP.js → visitor-menu-FY4KM2SW.js} +1 -1
  185. package/dist/m/plugins/wire-M2NR354P.js +1 -0
  186. package/dist/m/{reader-core-POFQCKRV.js → reader-core-T2S3JC4E.js} +2 -2
  187. package/dist/m/sync/live-sync-Z64YREWQ.js +1 -0
  188. package/dist/m/ui/index-MGTWOW2C.js +1 -0
  189. package/dist/m/vendor/{sap-core.vendor-OA5SKL7Q.js → sap-core.vendor-QAEPMETX.js} +1 -1
  190. package/dist/offline-manifest.json +1250 -1082
  191. package/dist/server/core.cjs +132 -109
  192. package/dist/server/page-compaction-worker.cjs +5 -5
  193. package/dist/server/rooms.mjs +3 -1
  194. package/docs/guide.md +89 -44
  195. package/entries/clay-data.js +1 -1
  196. package/entries/sap.js +1 -1
  197. package/package.json +5 -3
  198. package/src/blockeditor/themes/content.css +70 -0
  199. package/src/blockeditor/themes/light-1.css +431 -0
  200. package/src/blockeditor/themes/light-1.source.css +270 -0
  201. package/src/blockeditor/themes/light-2.css +211 -0
  202. package/src/blockeditor/themes/light-3.css +130 -0
  203. package/src/blockeditor/themes/light-4.css +299 -0
  204. package/src/core/conflict-notice.js +28 -0
  205. package/src/core/draft-mode.js +6 -0
  206. package/src/core/host-meta.js +6 -6
  207. package/src/core/is-edit-mode.js +9 -3
  208. package/src/core/mode-support.js +3 -0
  209. package/src/core/mode-switch.js +4 -4
  210. package/src/core/mode-transition.js +3 -1
  211. package/src/core/page-format-wire.js +1 -1
  212. package/src/core/page-format.js +8 -8
  213. package/src/core/save-accepted.js +6 -7
  214. package/src/core/save-core.js +52 -23
  215. package/src/core/save-failure-notice.js +37 -0
  216. package/src/core/save-feedback.js +6 -0
  217. package/src/core/save-replace.js +1 -1
  218. package/src/core/save-size.js +2 -2
  219. package/src/core/save.js +78 -15
  220. package/src/core/site-edits.js +166 -0
  221. package/src/core/unsaved-warning.js +2 -2
  222. package/src/core/upgrade-run.js +4 -4
  223. package/src/lib/ai-comment.js +23 -0
  224. package/src/lib/effect.js +8 -0
  225. package/src/lib/idb-error-code.js +20 -0
  226. package/src/live/fast-lane.js +10 -10
  227. package/src/live/local-lane.js +10 -10
  228. package/src/live/page-compaction.js +8 -8
  229. package/src/live/server-lane.js +1 -1
  230. package/src/loader-logic.js +48 -18
  231. package/src/loader.js +11 -6
  232. package/src/page/adopt-boot.js +1 -1
  233. package/src/page/adopt.js +2 -2
  234. package/src/page/ai-area.js +182 -0
  235. package/src/page/ai-preview.js +80 -0
  236. package/src/page/ai-surface.js +257 -0
  237. package/src/page/ai-tool.js +308 -145
  238. package/src/page/announce.js +2 -2
  239. package/src/page/awareness.js +18 -18
  240. package/src/page/blocks.js +35 -34
  241. package/src/page/blocksel.js +2 -2
  242. package/src/page/board-drag.js +11 -11
  243. package/src/page/board-face.js +1 -1
  244. package/src/page/board-panel.js +26 -26
  245. package/src/page/board-style.js +127 -127
  246. package/src/page/board-view.js +48 -48
  247. package/src/page/chart.js +29 -29
  248. package/src/page/checkpoint-proof.js +19 -19
  249. package/src/page/chrome.js +74 -65
  250. package/src/page/clipboard-shape.js +1 -1
  251. package/src/page/csv-import.js +4 -4
  252. package/src/page/drag.js +5 -5
  253. package/src/page/editor.js +301 -296
  254. package/src/page/export-html.js +8 -8
  255. package/src/page/features/checklist.js +36 -36
  256. package/src/page/features/export-html.js +19 -19
  257. package/src/page/features/export-markdown.js +10 -10
  258. package/src/page/features/import-markdown.js +13 -13
  259. package/src/page/features/media.js +50 -50
  260. package/src/page/features/table.js +17 -17
  261. package/src/page/features/title-cover.js +17 -17
  262. package/src/page/features/title-icon.js +7 -7
  263. package/src/page/features/toc.js +1 -1
  264. package/src/page/features/tool.js +42 -18
  265. package/src/page/format-command.js +4 -4
  266. package/src/page/format-gate.js +6 -6
  267. package/src/page/format-host.js +6 -6
  268. package/src/page/format-level.js +3 -3
  269. package/src/page/format-native-commands.js +2 -2
  270. package/src/page/highlight-slot.js +1 -1
  271. package/src/page/highlight.js +4 -4
  272. package/src/page/history-intent.js +2 -2
  273. package/src/page/image-actions.js +4 -4
  274. package/src/page/link.js +10 -10
  275. package/src/page/media.js +3 -3
  276. package/src/page/mention-picker.js +7 -7
  277. package/src/page/merge.js +1 -1
  278. package/src/page/placeholder.js +3 -3
  279. package/src/page/projection.js +11 -11
  280. package/src/page/reader-patch.js +2 -2
  281. package/src/page/recover.js +26 -26
  282. package/src/page/recovery-ui.js +28 -28
  283. package/src/page/rich/chart.js +1 -1
  284. package/src/page/rich/page-tool.js +21 -6
  285. package/src/page/rich/tool-runtime.js +3 -2
  286. package/src/page/save-projection.js +2 -2
  287. package/src/page/save-states.js +9 -9
  288. package/src/page/schema.js +9 -9
  289. package/src/page/table-style.js +21 -21
  290. package/src/page/toc-link.js +1 -1
  291. package/src/page/tool-capability.js +8 -3
  292. package/src/page/tool-transport.js +52 -0
  293. package/src/page/tool-views.js +4 -0
  294. package/src/page/tools.js +6 -1
  295. package/src/page/view.js +6 -6
  296. package/src/page/ybind/binding.js +1 -1
  297. package/src/page/ybind/conversion.js +1 -1
  298. package/src/page/ybind/layout.js +4 -4
  299. package/src/page/ybind/migrate.js +1 -1
  300. package/src/page/ybind/origins.js +2 -2
  301. package/src/page/ybind/provider.js +2 -2
  302. package/src/page/ybind/recovery-proof.js +3 -3
  303. package/src/page/ybind/recovery-replay.js +2 -2
  304. package/src/plugins/ai-edit/picker.js +235 -0
  305. package/src/plugins/ai-edit.js +220 -34
  306. package/src/plugins/indicator-chip.js +39 -34
  307. package/src/plugins/indicator.js +13 -4
  308. package/src/plugins/live.js +21 -13
  309. package/src/plugins/menu/actions.js +89 -17
  310. package/src/plugins/menu/seo.js +32 -6
  311. package/src/plugins/menu/shell-style.js +26 -7
  312. package/src/plugins/menu/shell.js +12 -7
  313. package/src/plugins/menu/variants.js +6 -10
  314. package/src/plugins/menu/visitor.js +44 -34
  315. package/src/plugins/menu.js +3 -2
  316. package/src/plugins/page-view.js +2 -2
  317. package/src/plugins/page.js +257 -98
  318. package/src/plugins/sortable.js +7 -0
  319. package/src/plugins/upgrade.js +2 -1
  320. package/src/plugins/visitor-drafts/commit.js +303 -0
  321. package/src/plugins/visitor-drafts/idb.js +221 -0
  322. package/src/plugins/visitor-drafts/intro-style.js +1 -1
  323. package/src/plugins/visitor-drafts/intro.js +8 -25
  324. package/src/plugins/visitor-drafts/prompt.js +30 -4
  325. package/src/plugins/visitor-drafts/session.js +345 -0
  326. package/src/plugins/visitor-drafts/store.js +351 -32
  327. package/src/plugins/visitor-drafts.js +158 -27
  328. package/src/server/checkpoint/index.js +8 -8
  329. package/src/server/rooms/index.js +2 -2
  330. package/src/server/rooms/live-data-rooms.js +35 -35
  331. package/src/server/rooms/live-page-history.js +2 -2
  332. package/src/server/rooms/page-admission.js +34 -6
  333. package/src/server/rooms/page-conversion.js +1 -1
  334. package/src/server/rooms/page-lineage.js +4 -4
  335. package/src/server/rooms/page-rebase.js +4 -4
  336. package/src/server/rooms/page-room-conformance.js +14 -14
  337. package/src/server/rooms/page-state.js +2 -2
  338. package/src/server/rooms/page-write-admission.js +7 -7
  339. package/src/server/rooms/page-write-guard.js +3 -3
  340. package/src/sync/data-guard-notice.js +265 -0
  341. package/src/sync/live-sync.js +54 -11
  342. package/src/sync/page-relay.js +4 -4
  343. package/src/sync/presence-store.js +1 -1
  344. package/src/sync/presence-target.js +3 -3
  345. package/src/sync/presence.js +1 -1
  346. package/src/sync/stream.js +54 -13
  347. package/src/sync/wire-profile.js +8 -3
  348. package/src/ui/bevel.js +1 -1
  349. package/src/ui/index.js +9 -10
  350. package/src/ui/skins/cms.js +1 -1
  351. package/src/ui/skins/quickcrop.js +1 -1
  352. package/src/ui/skins/richclay.js +2 -2
  353. package/src/ui/toast-lazy.js +12 -3
  354. package/src/ui/toast.js +9 -3
  355. package/src/vendor/hyper-html-api-data.vendor.js +1 -1
  356. package/src/vendor/hyper-html-api-upgrade.vendor.js +2 -2
  357. package/src/vendor/hypercms.vendor.js +16 -16
  358. package/src/vendor/richclay.vendor.js +48 -20
  359. package/src/vendor/sap-core.vendor.js +1 -1
  360. package/tool-generation/context.md +44 -0
  361. package/tool-generation/system.md +23 -0
  362. package/dist/m/c-24PMUJIV.js +0 -2
  363. package/dist/m/c-2AYVYEI4.js +0 -1
  364. package/dist/m/c-2AZDZWCK.js +0 -1
  365. package/dist/m/c-2L6O5PDS.js +0 -6
  366. package/dist/m/c-2RYOGUQM.js +0 -2
  367. package/dist/m/c-2ZVOEU4M.js +0 -1
  368. package/dist/m/c-37NAONZA.js +0 -1
  369. package/dist/m/c-3GJ4SDE2.js +0 -1
  370. package/dist/m/c-3O7OBDCM.js +0 -1
  371. package/dist/m/c-5OJ7YF2N.js +0 -1
  372. package/dist/m/c-5WMXEKFH.js +0 -135
  373. package/dist/m/c-6RDOKLN7.js +0 -1
  374. package/dist/m/c-A4IP6MBC.js +0 -1
  375. package/dist/m/c-A6L3FMUS.js +0 -1
  376. package/dist/m/c-ATKAOH23.js +0 -1
  377. package/dist/m/c-B6O7AJYG.js +0 -32
  378. package/dist/m/c-BCGWJYXW.js +0 -1
  379. package/dist/m/c-BGKAT2FL.js +0 -7
  380. package/dist/m/c-BYTKL6UX.js +0 -1
  381. package/dist/m/c-DHBRA6DL.js +0 -1
  382. package/dist/m/c-DTMZ3ZHI.js +0 -1
  383. package/dist/m/c-E3ZXARWA.js +0 -1
  384. package/dist/m/c-EK63G3CG.js +0 -1
  385. package/dist/m/c-ELYIIYRS.js +0 -1
  386. package/dist/m/c-EXKHPOVC.js +0 -3
  387. package/dist/m/c-FCSZ3DC5.js +0 -20
  388. package/dist/m/c-FTWGYI5E.js +0 -1
  389. package/dist/m/c-G4PWUDD5.js +0 -1
  390. package/dist/m/c-GBKB5WDL.js +0 -2
  391. package/dist/m/c-GBTVCJXC.js +0 -1
  392. package/dist/m/c-GC2HICFJ.js +0 -1
  393. package/dist/m/c-GRWMD6O5.js +0 -1
  394. package/dist/m/c-HCNWJE4A.js +0 -4
  395. package/dist/m/c-HG2C77BM.js +0 -4
  396. package/dist/m/c-JGHEACGK.js +0 -1
  397. package/dist/m/c-JGLX6TBK.js +0 -1
  398. package/dist/m/c-JNRKHYWO.js +0 -1
  399. package/dist/m/c-KBS3UV6B.js +0 -1
  400. package/dist/m/c-KQ7E3PYY.js +0 -1
  401. package/dist/m/c-L3F5ZLIV.js +0 -1
  402. package/dist/m/c-L4KMT7FO.js +0 -6
  403. package/dist/m/c-L5VFATT6.js +0 -1
  404. package/dist/m/c-LCYPMULG.js +0 -1
  405. package/dist/m/c-LIGQYZ7M.js +0 -6
  406. package/dist/m/c-LKIWEPAV.js +0 -1
  407. package/dist/m/c-MPSKIU2I.js +0 -1
  408. package/dist/m/c-N7JPUPGC.js +0 -1
  409. package/dist/m/c-NK33MMYF.js +0 -1
  410. package/dist/m/c-NQLWOHLH.js +0 -10
  411. package/dist/m/c-NTHUTABN.js +0 -1
  412. package/dist/m/c-NWX3MFT4.js +0 -1
  413. package/dist/m/c-OKXI52N7.js +0 -1
  414. package/dist/m/c-OPONJ2UK.js +0 -128
  415. package/dist/m/c-OWQWOGYI.js +0 -1
  416. package/dist/m/c-P6Q2ZTFQ.js +0 -1
  417. package/dist/m/c-QEN6HZCA.js +0 -1
  418. package/dist/m/c-QIXT3Q7C.js +0 -28
  419. package/dist/m/c-QM5LXRDT.js +0 -9
  420. package/dist/m/c-QYYUVLVG.js +0 -1
  421. package/dist/m/c-RQRMPZXD.js +0 -1
  422. package/dist/m/c-SBCBXKOZ.js +0 -26
  423. package/dist/m/c-SKF5HL4I.js +0 -4
  424. package/dist/m/c-SRPC3VBE.js +0 -1
  425. package/dist/m/c-TANBH7FI.js +0 -1
  426. package/dist/m/c-THGQQDYY.js +0 -1
  427. package/dist/m/c-UD5JZTDL.js +0 -1
  428. package/dist/m/c-UDGEFWNU.js +0 -1
  429. package/dist/m/c-UGNV5MFB.js +0 -1
  430. package/dist/m/c-VIRFF5HG.js +0 -8
  431. package/dist/m/c-VJYEVRYK.js +0 -1
  432. package/dist/m/c-VQCEOGKH.js +0 -13
  433. package/dist/m/c-VYJ7O4RI.js +0 -34
  434. package/dist/m/c-W7IPVCAA.js +0 -1
  435. package/dist/m/c-WBGWGOM7.js +0 -1
  436. package/dist/m/c-WJ5DRBHT.js +0 -72
  437. package/dist/m/c-X5WC4PX5.js +0 -1
  438. package/dist/m/c-XCFQEWW6.js +0 -3
  439. package/dist/m/c-XGH4GS2T.js +0 -1
  440. package/dist/m/c-XLQ3BDMM.js +0 -1
  441. package/dist/m/c-ZQXNHZZT.js +0 -72
  442. package/dist/m/core/conflict-notice-42H4ASLA.js +0 -1
  443. package/dist/m/core/draft-mode-WSQAT67S.js +0 -1
  444. package/dist/m/core/save-ESPSQPLV.js +0 -1
  445. package/dist/m/core/save-core-6SQHOR6W.js +0 -1
  446. package/dist/m/loader-FBDE2UAB.js +0 -1
  447. package/dist/m/manifest-1D2F5CA5.js +0 -1
  448. package/dist/m/manifest-edit-F7CC5CFD.js +0 -1
  449. package/dist/m/page/editor-OSKOW6RS.js +0 -304
  450. package/dist/m/plugins/ai-edit-VV4QTINH.js +0 -6
  451. package/dist/m/plugins/indicator-WVPGMOZ7.js +0 -1
  452. package/dist/m/plugins/menu-Q4MFFQ6E.js +0 -1
  453. package/dist/m/plugins/page-OAWUJQEL.js +0 -2
  454. package/dist/m/plugins/page-view-DZ26ZDDQ.js +0 -1
  455. package/dist/m/plugins/richclay-PGOOJ4OK.js +0 -517
  456. package/dist/m/plugins/sortable-266HY6TR.js +0 -1
  457. package/dist/m/plugins/upgrade-BNZVFHMZ.js +0 -1
  458. package/dist/m/plugins/visitor-drafts-2AUYKAIJ.js +0 -20
  459. package/dist/m/plugins/wire-W2EV36KZ.js +0 -1
  460. package/dist/m/sync/live-sync-XGUPHI3I.js +0 -1
  461. package/dist/m/ui/index-VGYAKAKI.js +0 -1
  462. package/dist/page/themes/light-1.css +0 -431
  463. package/src/page/themes/content.css +0 -70
  464. package/src/page/themes/light-1.css +0 -431
  465. package/src/page/themes/light-1.source.css +0 -270
  466. package/src/page/themes/light-2.css +0 -211
  467. package/src/page/themes/light-3.css +0 -130
  468. package/src/page/themes/light-4.css +0 -299
  469. /package/dist/m/{c-FILLTJA7.js → c-QTTJYJMA.js} +0 -0
  470. /package/dist/m/plugins/{quickcrop-WWF5I422.js.LEGAL.txt → quickcrop-X5MRIBAP.js.LEGAL.txt} +0 -0
  471. /package/dist/m/plugins/{richclay-PGOOJ4OK.js.LEGAL.txt → richclay-Y2NV44NA.js.LEGAL.txt} +0 -0
@@ -1,4 +1,4 @@
1
- import { announceBottomUi, bottomBarHeight } from "./bottom-ui.js";
1
+ import { BOTTOM_UI_CHANGED, announceBottomUi, bottomBarHeight } from "./bottom-ui.js";
2
2
  import { mountEditorUI } from "../../ui/editor-ui.js";
3
3
  const ASIDE = `<aside class="hcp" id="hcp" hidden aria-label="Download this app" data-hcp-state="tab" data-hcp-reason="open" sap-ignore clay="editor-ui">
4
4
  <section class="hcp-card" id="hcp-card" role="dialog" aria-modal="false" aria-labelledby="hcp-title">
@@ -21,7 +21,9 @@ const ASIDE = `<aside class="hcp" id="hcp" hidden aria-label="Download this app"
21
21
  </div>
22
22
  </aside>`;
23
23
 
24
- export async function mountPrompt({ memory, appName, link }) {
24
+ // `settle` returns a promise while the page's last changes are not yet where the download
25
+ // page reads them, and null once they are. False requests a download from this page.
26
+ export async function mountPrompt({ memory, appName, link, settle, canDownloadCurrent = () => true }) {
25
27
  const { PROMPT_CSS } = await import("./prompt-style.js");
26
28
  const existing = document.querySelector('clay-editor-ui[data-clay-ui="download-prompt"]');
27
29
  let root = existing?.shadowRoot.getElementById("hcp");
@@ -92,6 +94,7 @@ export async function mountPrompt({ memory, appName, link }) {
92
94
  }
93
95
 
94
96
  let liftFrame = 0;
97
+ let announcing = false;
95
98
  function lift() {
96
99
  if (liftFrame) return;
97
100
  liftFrame = requestAnimationFrame(() => {
@@ -99,7 +102,9 @@ export async function mountPrompt({ memory, appName, link }) {
99
102
  const raise = bottomBarHeight(innerWidth - 24, (el) => root.contains(el) || el.closest("[data-hcp-preview], .clay-owner"));
100
103
  const next = raise + "px";
101
104
  if (root.style.getPropertyValue("--hcp-lift") !== next) root.style.setProperty("--hcp-lift", next);
105
+ announcing = true;
102
106
  announceBottomUi();
107
+ announcing = false;
103
108
  });
104
109
  }
105
110
 
@@ -115,6 +120,7 @@ export async function mountPrompt({ memory, appName, link }) {
115
120
  }
116
121
  }
117
122
 
123
+ let rescueRequested = false;
118
124
  root.addEventListener("click", async (e) => {
119
125
  const t = e.target.closest("[data-hcp]");
120
126
  if (t) {
@@ -128,9 +134,23 @@ export async function mountPrompt({ memory, appName, link }) {
128
134
  return;
129
135
  }
130
136
  if (e.target.closest("[data-hcp-link]")) {
131
- if (root.getAttribute("data-hcp-reason") === "error") {
137
+ if (!canDownloadCurrent()) return;
138
+ let rescue = rescueRequested || root.getAttribute("data-hcp-reason") === "error";
139
+ if (!rescue) {
140
+ const waiting = settle?.();
141
+ if (waiting) {
142
+ e.preventDefault();
143
+ if (await waiting !== false) {
144
+ linkEl.click();
145
+ return;
146
+ }
147
+ rescue = true;
148
+ }
149
+ }
150
+ if (rescue) {
132
151
  e.preventDefault();
133
152
  if (!(await downloadCurrent())) {
153
+ showError();
134
154
  root.querySelector(".hcp-body [data-hcp-for='error']").textContent = "The download could not be made. Keep this page open and try Download free again.";
135
155
  return;
136
156
  }
@@ -149,7 +169,10 @@ export async function mountPrompt({ memory, appName, link }) {
149
169
  function clearError() {
150
170
  if (root.getAttribute("data-hcp-reason") === "error") root.setAttribute("data-hcp-reason", "use");
151
171
  }
152
- const api = { set, root, showError, clearError, download: () => linkEl.click() };
172
+ const api = { set, root, showError, clearError, download: (rescue = false) => {
173
+ rescueRequested = rescue;
174
+ try { linkEl.click(); } finally { rescueRequested = false; }
175
+ } };
153
176
 
154
177
  document.addEventListener("input", onUse, true);
155
178
  document.addEventListener("change", onUse, true);
@@ -157,6 +180,9 @@ export async function mountPrompt({ memory, appName, link }) {
157
180
  document.addEventListener("focusout", onFocusOut);
158
181
  addEventListener("scroll", lift, { passive: true });
159
182
  addEventListener("resize", lift);
183
+ // The intro leaving can bring a page's bottom bar into view with no scroll and no transition, so the
184
+ // prompt measures again when anything else says the bottom of the screen changed. Its own word is skipped.
185
+ document.addEventListener(BOTTOM_UI_CHANGED, () => { if (!announcing) lift(); });
160
186
  document.addEventListener("transitionend", lift, true);
161
187
  // Transition events stop at a shadow root, so the prompt's own slides are heard here.
162
188
  root.addEventListener("transitionend", lift);
@@ -0,0 +1,345 @@
1
+ /**
2
+ * One tab's side of the draft database.
3
+ *
4
+ * The store (`store.js`) turns each save into an operation and keeps it in this tab's
5
+ * journal slot. This module delivers them: `sync()` runs one `transact()` (`commit.js`)
6
+ * carrying this tab's unconfirmed operations and every journal slot `localStorage` holds,
7
+ * a closed tab's included, and `took()` acts on what that transaction stored. An operation
8
+ * is saved once its transaction completed; a failed one stays where it is and goes again
9
+ * with the next `sync()`.
10
+ *
11
+ * After each transaction `localStorage` gets a cache of the record: the record itself with
12
+ * a `w` field `{rev, reset}` while it is at most FULL_COPY_LIMIT characters, beyond that a
13
+ * head (`{v: 2, idb: true, data: the small keys}`). A page boots from the cache, the
14
+ * first-paint look and the download page read it, and a tab on a released ClayJS (1.24.0
15
+ * and earlier) takes it for the record. It is never read back as the record here.
16
+ *
17
+ * Such a tab writes its own record over the cache. That record has no `w`, so the next
18
+ * transaction takes it in (`commit.js`), and the cache is never written over one that has
19
+ * not been taken in.
20
+ */
21
+
22
+ import { openDrafts } from "./idb.js";
23
+ import { emptyMeta, foreignMark, isForeign, markerFor, markerGen, recoveryKey, recoveryMark, rowKey, settled, transact } from "./commit.js";
24
+ import { setDraftStoreFailed } from "../../core/draft-mode.js";
25
+
26
+ export const FULL_COPY_LIMIT = 256 * 1024;
27
+ const HEAD_FIELD_LIMIT = 2 * 1024;
28
+ const HEAD_KEYS = new Set(["v", "savedAt", "id", "ancestry", "reset", "data"]);
29
+ // A settled journal slot younger than this may belong to a tab that is still writing it.
30
+ const SLOT_AGE_MS = 10 * 1000;
31
+ // Start over reloads the page once its transaction completed, or after this long: the
32
+ // marker in `localStorage` then carries it to the next page load's first transaction.
33
+ const START_OVER_WAIT_MS = 1500;
34
+ const FIRST_TRANSACTION_TIMEOUT_MS = 2000;
35
+ const STARTED_OVER = "This draft was started over in another tab.";
36
+ const RESET_KEPT_ASIDE = "This draft was started over in another tab. The earlier draft was kept aside in this browser.";
37
+ const KEPT_ASIDE = "A tab that was open before an update saved another copy of this draft. That copy was kept aside, and this draft was not changed. Reload that tab to go on from this draft.";
38
+
39
+ const parse = (text) => {
40
+ if (text == null) return null;
41
+ try { return JSON.parse(text); } catch { return null; }
42
+ };
43
+
44
+ // Only data fits in a head: a page (`live`, `blockeditor`) or any field a later version adds
45
+ // is held only in the database, so a head of such a record never says it is `full`.
46
+ function headOf(record, w) {
47
+ const data = {};
48
+ let full = Object.keys(record).every((name) => HEAD_KEYS.has(name));
49
+ for (const [name, value] of Object.entries(record.data)) {
50
+ if (JSON.stringify(value).length < HEAD_FIELD_LIMIT) data[name] = value;
51
+ else full = false;
52
+ }
53
+ return JSON.stringify({ v: 2, savedAt: record.savedAt, id: record.id, ancestry: record.ancestry, idb: true, ...(full && { full: true }), data, w });
54
+ }
55
+
56
+ /**
57
+ * Open the database for this tab and run its first transaction, which takes in what closed
58
+ * tabs left in their journal slots. Rejects when the database does not open.
59
+ *
60
+ * @param {Object} options
61
+ * @param {Object} options.store - the tab's store (`createStore`)
62
+ * @param {?Storage} options.storage
63
+ */
64
+ export async function openSession({ store, storage, doc = document, now = () => Date.now(), reload = () => window.location.reload() }) {
65
+ const drafts = await openDrafts();
66
+ const { key } = store;
67
+ const resetKey = key + ":reset";
68
+ const read = (name) => { try { return storage?.getItem(name) ?? null; } catch { return null; } };
69
+ const remove = (name) => { try { storage?.removeItem(name); } catch {} };
70
+
71
+ // A page that loaded again because another tab started over says so once, and keeps
72
+ // saying it until it is closed: the reload happened while the visitor was in the other
73
+ // tab. The flag is per tab and outlives only that reload.
74
+ const noticeKey = key + ":started-over";
75
+ const recoveryNoticeKey = key + ":recovery-notice";
76
+ try {
77
+ if (window.sessionStorage.getItem(noticeKey)) {
78
+ window.sessionStorage.removeItem(noticeKey);
79
+ if (!window.sessionStorage.getItem(recoveryNoticeKey)) import("../../ui/toast.js").then((m) => m.toastPersistent(STARTED_OVER, "info")).catch(() => {});
80
+ }
81
+ } catch {}
82
+
83
+ // The stored revision this page last matched, and the marker the transaction in flight read.
84
+ let rev = null;
85
+ let marker = "";
86
+ // The number of the generation this page shows, once a transaction has said it.
87
+ let gen = null;
88
+ // This tab's own Start over: the generation it ends, until a transaction has carried it
89
+ // (`sent` is what the transaction in flight carries).
90
+ let ending = null;
91
+ let sent = null;
92
+ let carried = 0;
93
+ let retiring = false;
94
+ let shownId = store.held()?.id;
95
+ // The latest full cache copy this tab saw at the key, and the text of another writer's
96
+ // record a storage event says replaced it: such a record merges from that copy.
97
+ let lastCache = null;
98
+ let replacedBy = null;
99
+ const told = new Set();
100
+ try {
101
+ const notice = window.sessionStorage.getItem(recoveryNoticeKey);
102
+ if (notice) {
103
+ window.sessionStorage.removeItem(recoveryNoticeKey);
104
+ const saved = parse(notice);
105
+ keptAside({ id: saved?.mark ?? notice }, Boolean(saved?.reset));
106
+ }
107
+ } catch {}
108
+
109
+ function rememberRecovery(mark) {
110
+ try { window.sessionStorage.setItem(recoveryNoticeKey, JSON.stringify({ mark, reset: true })); } catch {}
111
+ }
112
+
113
+ function rememberGeneration(reset) {
114
+ try { window.sessionStorage.setItem(key + ":generation", JSON.stringify({ marker, reset })); } catch {}
115
+ }
116
+
117
+ function input() {
118
+ const held = read(resetKey);
119
+ marker = held ?? "";
120
+ const others = store.journalSlots().filter((name) => name !== store.slotKey).map((name) => parse(read(name)));
121
+ sent = store.stopped() ? null : ending;
122
+ carried = store.chain().ops.at(-1)?.seq ?? 0;
123
+ const local = store.held();
124
+ if (local?.v === 1 && local.w !== undefined) lastCache = local;
125
+ const resets = sent ? [sent] : [];
126
+ return {
127
+ seed: store.seed(),
128
+ newId: store.newId,
129
+ merge3: store.merge3,
130
+ unitMark: store.unitMark,
131
+ now: now(),
132
+ marker: held,
133
+ resets,
134
+ local,
135
+ seen: lastCache,
136
+ direct: replacedBy !== null && read(key) === replacedBy,
137
+ chains: store.pending() ? [...others, store.chain()] : others,
138
+ };
139
+ }
140
+
141
+ // Another tab's slot is removed once nothing more can come of it and its tab has gone quiet.
142
+ function sweep(meta) {
143
+ const at = now();
144
+ for (const name of store.journalSlots()) {
145
+ if (name === store.slotKey) continue;
146
+ const chain = parse(read(name));
147
+ if (settled(chain, meta) && at - (chain?.at ?? 0) > SLOT_AGE_MS) remove(name);
148
+ }
149
+ }
150
+
151
+ function cache({ meta, record }) {
152
+ const held = store.held();
153
+ // Another writer's record stays until the database has taken it in: one written since
154
+ // this transaction read `localStorage` goes with the next.
155
+ if (isForeign(held) && foreignMark(held) !== meta.foreign) return void setTimeout(quietly, 0);
156
+ if ((read(resetKey) ?? "") !== meta.reset) return;
157
+ if (!record) return void (held && remove(key));
158
+ if (held?.w && held.w.reset === meta.reset && held.w.rev >= meta.rev) return;
159
+ const w = { rev: meta.rev, reset: meta.reset };
160
+ const full = JSON.stringify({ ...record, w });
161
+ try {
162
+ if (full.length <= FULL_COPY_LIMIT) {
163
+ storage.setItem(key, full);
164
+ lastCache = { ...record, w };
165
+ return;
166
+ }
167
+ } catch {}
168
+ // No room for the full copy: a head still says a draft exists.
169
+ try { storage.setItem(key, headOf(record, w)); } catch {}
170
+ }
171
+
172
+ // Operations captured after the transaction read stay journaled for the next load.
173
+ async function ended(result) {
174
+ retiring = true;
175
+ const chain = store.chain();
176
+ const mark = recoveryMark(chain);
177
+ const kept = chain.ops.some((op) => op.seq > carried) || result.meta.recovery?.includes(mark)
178
+ ? mark : result.meta.recovery?.includes(shownId) ? shownId : null;
179
+ store.acknowledge(carried);
180
+ store.stop({ keepPending: true });
181
+ if (store.unsafe()) {
182
+ try { await drafts.putRow(rowKey(key, store.tab), JSON.stringify(store.chain())); }
183
+ catch (error) { throw store.failed(error); }
184
+ store.acknowledge(store.chain().ops.at(-1)?.seq ?? 0);
185
+ }
186
+ cache(result);
187
+ if (kept) rememberRecovery(kept);
188
+ const held = store.held();
189
+ if (held?.w && held.w.reset !== result.meta.reset) remove(key);
190
+ try { window.sessionStorage.setItem(noticeKey, "1"); } catch {}
191
+ rememberGeneration(result.meta.reset);
192
+ retiring = false;
193
+ reload();
194
+ return result;
195
+ }
196
+
197
+ // Start over ends the generation this page shows, and only that one: when another Start
198
+ // over has ended it since this page loaded, what was saved after that one stays. A page
199
+ // that does not know its generation's number yet waits for the first transaction.
200
+ async function startOver() {
201
+ const shown = store.generation();
202
+ const stop = () => { store.stop(); setDraftStoreFailed(false); };
203
+ const stale = () => (read(resetKey) ?? "") !== shown && (gen === null || (read(resetKey) ?? "") !== marker);
204
+ if (stale()) return stop();
205
+ let known = gen ?? markerGen(shown);
206
+ if (known === null) {
207
+ const result = await first.catch(() => drafts.change(key, ({ meta }) => ({
208
+ puts: [],
209
+ deletes: [],
210
+ result: { meta: parse(meta) ?? emptyMeta(shown) },
211
+ }), { timeout: FIRST_TRANSACTION_TIMEOUT_MS }));
212
+ if (stale()) return stop();
213
+ known = result.meta.gen;
214
+ if (result.meta.reset !== shown) {
215
+ ending = { ends: null, marker: shown };
216
+ const applied = await sync();
217
+ if (store.stopped()) return stop();
218
+ known = applied.meta.gen;
219
+ }
220
+ }
221
+ const next = markerFor(known + 1, store.newId());
222
+ ending = { ends: known, marker: next };
223
+ const before = read(key);
224
+ if (store.held()?.w) remove(key);
225
+ try { storage.setItem(resetKey, next); } catch {}
226
+ let timer;
227
+ try {
228
+ const committed = sync();
229
+ if (read(resetKey) !== next) await committed;
230
+ else await Promise.race([committed.catch(() => {}), new Promise((resolve) => { timer = setTimeout(resolve, START_OVER_WAIT_MS); })]);
231
+ stop();
232
+ } catch (error) {
233
+ ending = null;
234
+ if (before !== null && read(key) === null && (read(resetKey) ?? "") === shown) {
235
+ try { storage.setItem(key, before); } catch {}
236
+ }
237
+ throw error;
238
+ } finally { clearTimeout(timer); }
239
+ }
240
+
241
+ // Each kind of recovery notice is shown once per page load.
242
+ function keptAside(copy, reset = false) {
243
+ console.warn(reset
244
+ ? "visitor-drafts: the draft was started over; the earlier draft was kept in this browser's draft database under"
245
+ : "visitor-drafts: a tab on an earlier ClayJS saved a copy that could not be merged exactly; it was kept in this browser's draft database under", recoveryKey(key, recoveryMark(copy)));
246
+ if (told.has(reset)) return;
247
+ told.add(reset);
248
+ import("../../ui/toast.js").then((m) => m.toastPersistent(reset ? RESET_KEPT_ASIDE : KEPT_ASIDE, "warning")).catch(() => {});
249
+ }
250
+
251
+ function took(result) {
252
+ const { meta, record } = result;
253
+ // A marker the transaction did not take named a generation that had already ended.
254
+ if (marker !== meta.reset && (read(resetKey) ?? "") === marker) {
255
+ try { storage.setItem(resetKey, meta.reset); } catch {}
256
+ }
257
+ if (sent && sent === ending && meta.reset !== store.generation()) {
258
+ if (sent.marker === meta.reset) rememberGeneration(meta.reset);
259
+ store.stop();
260
+ setDraftStoreFailed(false);
261
+ }
262
+ if (sent === ending) ending = null;
263
+ // A stopped page is on its way out, after its own Start over or another tab's: it only
264
+ // keeps the cache in step, for the page load that follows.
265
+ if (store.stopped()) {
266
+ if (retiring) return ended(result);
267
+ cache(result);
268
+ return result;
269
+ }
270
+ if (result.conflicts.length) console.warn("visitor-drafts: another tab changed the same thing; its copy was kept in this browser's draft database under", key + ":conflict");
271
+ if (result.stale.includes(store.tab)) return ended(result);
272
+ if (meta.reset !== store.generation()) {
273
+ if (!store.fresh()) return ended(result);
274
+ store.enter(meta.reset);
275
+ }
276
+ if (result.released.length) keptAside(result.released[0]);
277
+ gen = meta.gen;
278
+ rememberGeneration(meta.reset);
279
+ const saved = store.acknowledge(meta.tabs[store.tab]?.seq ?? 0);
280
+ sweep(meta);
281
+ cache(result);
282
+ if (store.pending()) return result;
283
+ if (saved) {
284
+ setDraftStoreFailed(false);
285
+ doc.dispatchEvent(new CustomEvent("clay:drafts-saved", { detail: { data: record.data } }));
286
+ }
287
+ if (!store.shown()) {
288
+ rev = meta.rev;
289
+ return result;
290
+ }
291
+ // A page with unsaved changes is never rewritten: its next operation merges instead.
292
+ if (!store.changed()) {
293
+ if (record && meta.rev !== rev) store.take(record.data);
294
+ shownId = record?.id;
295
+ rev = meta.rev;
296
+ }
297
+ const unit = store.externalUnit(record);
298
+ if (unit) doc.dispatchEvent(new CustomEvent("clay:drafts-blockeditor-external", { detail: { live: unit.live, adopted: () => store.adoptedUnit(unit) } }));
299
+ return result;
300
+ }
301
+
302
+ // One transaction at a time, and at most one waiting: it reads the chain when it starts,
303
+ // so it carries every operation made before then.
304
+ let active = null;
305
+ let waiting = null;
306
+ function run(options) {
307
+ active = transact(drafts, key, input, options).then(took, (error) => {
308
+ throw store.pending() ? store.failed(error) : error;
309
+ }).finally(() => { active = null; });
310
+ return active;
311
+ }
312
+ function sync() {
313
+ if (waiting) return waiting;
314
+ if (!active) return run();
315
+ waiting = active.then(() => {}, () => {}).then(() => {
316
+ waiting = null;
317
+ return run();
318
+ });
319
+ return waiting;
320
+ }
321
+ const quietly = () => { sync().catch(() => {}); };
322
+
323
+ // At a hide, an operation too large for the journal slot goes into the database blind, with
324
+ // no read and no callback, so it can land while the page is going away.
325
+ function hide() {
326
+ if (store.unsafe()) drafts.putRow(rowKey(key, store.tab), JSON.stringify(store.chain())).catch(() => {});
327
+ if (store.pending()) quietly();
328
+ }
329
+
330
+ window.addEventListener("storage", (event) => {
331
+ if (event.key === key) {
332
+ const [was, is] = [parse(event.oldValue), parse(event.newValue)];
333
+ if (is?.v === 1 && is.w !== undefined) lastCache = is;
334
+ else if (isForeign(is) && was?.v === 1 && was.w !== undefined) [lastCache, replacedBy] = [was, event.newValue];
335
+ }
336
+ if (event.key === null || event.key === key || event.key === resetKey) quietly();
337
+ });
338
+ window.addEventListener("pageshow", (event) => { if (event.persisted) quietly(); });
339
+ // The page editor missed a page another tab stored before it listened.
340
+ doc.addEventListener("clay:drafts-blockeditor-listening", quietly);
341
+
342
+ const first = run({ timeout: FIRST_TRANSACTION_TIMEOUT_MS });
343
+ first.catch(() => {});
344
+ return { first, sync, hide, startOver };
345
+ }