@aglyn/besigner-ui 1.0.0-beta.143

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 (486) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +73 -0
  4. package/src/besigner.d.ts +88 -0
  5. package/src/besigner.js +89 -0
  6. package/src/besigner.js.map +1 -0
  7. package/src/index.d.ts +17 -0
  8. package/src/index.js +18 -0
  9. package/src/index.js.map +1 -0
  10. package/src/lib/box-styler/box-styler.d.ts +57 -0
  11. package/src/lib/box-styler/box-styler.js +240 -0
  12. package/src/lib/box-styler/box-styler.js.map +1 -0
  13. package/src/lib/box-styler/components/box-diagram.d.ts +89 -0
  14. package/src/lib/box-styler/components/box-diagram.js +661 -0
  15. package/src/lib/box-styler/components/box-diagram.js.map +1 -0
  16. package/src/lib/box-styler/components/legend.d.ts +56 -0
  17. package/src/lib/box-styler/components/legend.js +130 -0
  18. package/src/lib/box-styler/components/legend.js.map +1 -0
  19. package/src/lib/box-styler/components/spacing-editor.d.ts +55 -0
  20. package/src/lib/box-styler/components/spacing-editor.js +347 -0
  21. package/src/lib/box-styler/components/spacing-editor.js.map +1 -0
  22. package/src/lib/box-styler/constants.d.ts +17 -0
  23. package/src/lib/box-styler/constants.js +30 -0
  24. package/src/lib/box-styler/constants.js.map +1 -0
  25. package/src/lib/box-styler/index.d.ts +2 -0
  26. package/src/lib/box-styler/index.js +4 -0
  27. package/src/lib/box-styler/index.js.map +1 -0
  28. package/src/lib/box-styler/region-fills.d.ts +107 -0
  29. package/src/lib/box-styler/region-fills.js +139 -0
  30. package/src/lib/box-styler/region-fills.js.map +1 -0
  31. package/src/lib/box-styler/spacing-value.d.ts +104 -0
  32. package/src/lib/box-styler/spacing-value.js +223 -0
  33. package/src/lib/box-styler/spacing-value.js.map +1 -0
  34. package/src/lib/box-styler/types.d.ts +29 -0
  35. package/src/lib/box-styler/types.js +18 -0
  36. package/src/lib/box-styler/types.js.map +1 -0
  37. package/src/lib/components/accordion-list.component.d.ts +50 -0
  38. package/src/lib/components/accordion-list.component.js +228 -0
  39. package/src/lib/components/accordion-list.component.js.map +1 -0
  40. package/src/lib/components/add-controls.component.d.ts +22 -0
  41. package/src/lib/components/add-controls.component.js +50 -0
  42. package/src/lib/components/add-controls.component.js.map +1 -0
  43. package/src/lib/components/app-bar-breadcrumbs.component.d.ts +29 -0
  44. package/src/lib/components/app-bar-breadcrumbs.component.js +279 -0
  45. package/src/lib/components/app-bar-breadcrumbs.component.js.map +1 -0
  46. package/src/lib/components/app-bar-primary.component.d.ts +21 -0
  47. package/src/lib/components/app-bar-primary.component.js +108 -0
  48. package/src/lib/components/app-bar-primary.component.js.map +1 -0
  49. package/src/lib/components/app-bar-secondary.component.d.ts +21 -0
  50. package/src/lib/components/app-bar-secondary.component.js +94 -0
  51. package/src/lib/components/app-bar-secondary.component.js.map +1 -0
  52. package/src/lib/components/aside-panel.component.d.ts +23 -0
  53. package/src/lib/components/aside-panel.component.js +505 -0
  54. package/src/lib/components/aside-panel.component.js.map +1 -0
  55. package/src/lib/components/besigner-conflict-alert.component.d.ts +36 -0
  56. package/src/lib/components/besigner-conflict-alert.component.js +51 -0
  57. package/src/lib/components/besigner-conflict-alert.component.js.map +1 -0
  58. package/src/lib/components/besigner-dnd-context.component.d.ts +32 -0
  59. package/src/lib/components/besigner-dnd-context.component.js +75 -0
  60. package/src/lib/components/besigner-dnd-context.component.js.map +1 -0
  61. package/src/lib/components/besigner-draft-alert.component.d.ts +70 -0
  62. package/src/lib/components/besigner-draft-alert.component.js +155 -0
  63. package/src/lib/components/besigner-draft-alert.component.js.map +1 -0
  64. package/src/lib/components/besigner-root-provider.component.d.ts +33 -0
  65. package/src/lib/components/besigner-root-provider.component.js +68 -0
  66. package/src/lib/components/besigner-root-provider.component.js.map +1 -0
  67. package/src/lib/components/binding-preview-controls.component.d.ts +28 -0
  68. package/src/lib/components/binding-preview-controls.component.js +63 -0
  69. package/src/lib/components/binding-preview-controls.component.js.map +1 -0
  70. package/src/lib/components/closeable-drawer.component.d.ts +32 -0
  71. package/src/lib/components/closeable-drawer.component.js +134 -0
  72. package/src/lib/components/closeable-drawer.component.js.map +1 -0
  73. package/src/lib/components/component-accordion-list.d.ts +28 -0
  74. package/src/lib/components/component-accordion-list.js +205 -0
  75. package/src/lib/components/component-accordion-list.js.map +1 -0
  76. package/src/lib/components/component-icon.component.d.ts +32 -0
  77. package/src/lib/components/component-icon.component.js +51 -0
  78. package/src/lib/components/component-icon.component.js.map +1 -0
  79. package/src/lib/components/component-picker.d.ts +27 -0
  80. package/src/lib/components/component-picker.js +368 -0
  81. package/src/lib/components/component-picker.js.map +1 -0
  82. package/src/lib/components/components-grid-list.component.d.ts +31 -0
  83. package/src/lib/components/components-grid-list.component.js +162 -0
  84. package/src/lib/components/components-grid-list.component.js.map +1 -0
  85. package/src/lib/components/custom-css-form.component.d.ts +115 -0
  86. package/src/lib/components/custom-css-form.component.js +699 -0
  87. package/src/lib/components/custom-css-form.component.js.map +1 -0
  88. package/src/lib/components/device-preview-controls.component.d.ts +22 -0
  89. package/src/lib/components/device-preview-controls.component.js +150 -0
  90. package/src/lib/components/device-preview-controls.component.js.map +1 -0
  91. package/src/lib/components/dnd/canvas-drop-indicator.d.ts +20 -0
  92. package/src/lib/components/dnd/canvas-drop-indicator.js +61 -0
  93. package/src/lib/components/dnd/canvas-drop-indicator.js.map +1 -0
  94. package/src/lib/components/dnd/draggable-droppable.d.ts +31 -0
  95. package/src/lib/components/dnd/draggable-droppable.js +383 -0
  96. package/src/lib/components/dnd/draggable-droppable.js.map +1 -0
  97. package/src/lib/components/dnd/draggable.d.ts +42 -0
  98. package/src/lib/components/dnd/draggable.js +66 -0
  99. package/src/lib/components/dnd/draggable.js.map +1 -0
  100. package/src/lib/components/dnd/drop-indicator.d.ts +31 -0
  101. package/src/lib/components/dnd/drop-indicator.js +139 -0
  102. package/src/lib/components/dnd/drop-indicator.js.map +1 -0
  103. package/src/lib/components/dnd/droppable.d.ts +43 -0
  104. package/src/lib/components/dnd/droppable.js +63 -0
  105. package/src/lib/components/dnd/droppable.js.map +1 -0
  106. package/src/lib/components/element-card.component.d.ts +23 -0
  107. package/src/lib/components/element-card.component.js +49 -0
  108. package/src/lib/components/element-card.component.js.map +1 -0
  109. package/src/lib/components/element-classes-field.component.d.ts +41 -0
  110. package/src/lib/components/element-classes-field.component.js +140 -0
  111. package/src/lib/components/element-classes-field.component.js.map +1 -0
  112. package/src/lib/components/element-detail-overlay.component.d.ts +55 -0
  113. package/src/lib/components/element-detail-overlay.component.js +157 -0
  114. package/src/lib/components/element-detail-overlay.component.js.map +1 -0
  115. package/src/lib/components/element-detail.component.d.ts +56 -0
  116. package/src/lib/components/element-detail.component.js +171 -0
  117. package/src/lib/components/element-detail.component.js.map +1 -0
  118. package/src/lib/components/element-info-details.component.d.ts +18 -0
  119. package/src/lib/components/element-info-details.component.js +169 -0
  120. package/src/lib/components/element-info-details.component.js.map +1 -0
  121. package/src/lib/components/element-interactions-form.component.d.ts +21 -0
  122. package/src/lib/components/element-interactions-form.component.js +199 -0
  123. package/src/lib/components/element-interactions-form.component.js.map +1 -0
  124. package/src/lib/components/element-preview.component.d.ts +75 -0
  125. package/src/lib/components/element-preview.component.js +346 -0
  126. package/src/lib/components/element-preview.component.js.map +1 -0
  127. package/src/lib/components/element-props-form.component.d.ts +565 -0
  128. package/src/lib/components/element-props-form.component.js +2392 -0
  129. package/src/lib/components/element-props-form.component.js.map +1 -0
  130. package/src/lib/components/element-styles-form-template.component.d.ts +27 -0
  131. package/src/lib/components/element-styles-form-template.component.js +89 -0
  132. package/src/lib/components/element-styles-form-template.component.js.map +1 -0
  133. package/src/lib/components/element-styles-form.component.d.ts +52 -0
  134. package/src/lib/components/element-styles-form.component.js +1350 -0
  135. package/src/lib/components/element-styles-form.component.js.map +1 -0
  136. package/src/lib/components/empty-document-slot.d.ts +39 -0
  137. package/src/lib/components/empty-document-slot.js +121 -0
  138. package/src/lib/components/empty-document-slot.js.map +1 -0
  139. package/src/lib/components/empty-results.d.ts +22 -0
  140. package/src/lib/components/empty-results.js +131 -0
  141. package/src/lib/components/empty-results.js.map +1 -0
  142. package/src/lib/components/history-controls.component.d.ts +21 -0
  143. package/src/lib/components/history-controls.component.js +67 -0
  144. package/src/lib/components/history-controls.component.js.map +1 -0
  145. package/src/lib/components/inline-markdown-editor.component.d.ts +17 -0
  146. package/src/lib/components/inline-markdown-editor.component.js +220 -0
  147. package/src/lib/components/inline-markdown-editor.component.js.map +1 -0
  148. package/src/lib/components/inline-text-editor.component.d.ts +48 -0
  149. package/src/lib/components/inline-text-editor.component.js +905 -0
  150. package/src/lib/components/inline-text-editor.component.js.map +1 -0
  151. package/src/lib/components/insert-token-menu.component.d.ts +86 -0
  152. package/src/lib/components/insert-token-menu.component.js +232 -0
  153. package/src/lib/components/insert-token-menu.component.js.map +1 -0
  154. package/src/lib/components/instance-attr-overrides.component.d.ts +50 -0
  155. package/src/lib/components/instance-attr-overrides.component.js +298 -0
  156. package/src/lib/components/instance-attr-overrides.component.js.map +1 -0
  157. package/src/lib/components/interact-controls.component.d.ts +22 -0
  158. package/src/lib/components/interact-controls.component.js +74 -0
  159. package/src/lib/components/interact-controls.component.js.map +1 -0
  160. package/src/lib/components/markdown-attribute-field.component.d.ts +40 -0
  161. package/src/lib/components/markdown-attribute-field.component.js +103 -0
  162. package/src/lib/components/markdown-attribute-field.component.js.map +1 -0
  163. package/src/lib/components/node-card.d.ts +24 -0
  164. package/src/lib/components/node-card.js +86 -0
  165. package/src/lib/components/node-card.js.map +1 -0
  166. package/src/lib/components/node-context-menu.d.ts +25 -0
  167. package/src/lib/components/node-context-menu.js +558 -0
  168. package/src/lib/components/node-context-menu.js.map +1 -0
  169. package/src/lib/components/node-leaf.d.ts +39 -0
  170. package/src/lib/components/node-leaf.js +628 -0
  171. package/src/lib/components/node-leaf.js.map +1 -0
  172. package/src/lib/components/node-outline.d.ts +24 -0
  173. package/src/lib/components/node-outline.js +156 -0
  174. package/src/lib/components/node-outline.js.map +1 -0
  175. package/src/lib/components/node-overlay.d.ts +23 -0
  176. package/src/lib/components/node-overlay.js +299 -0
  177. package/src/lib/components/node-overlay.js.map +1 -0
  178. package/src/lib/components/node-quick-actions.d.ts +24 -0
  179. package/src/lib/components/node-quick-actions.js +284 -0
  180. package/src/lib/components/node-quick-actions.js.map +1 -0
  181. package/src/lib/components/node-tree-view.d.ts +106 -0
  182. package/src/lib/components/node-tree-view.js +820 -0
  183. package/src/lib/components/node-tree-view.js.map +1 -0
  184. package/src/lib/components/panel-controls.component.d.ts +22 -0
  185. package/src/lib/components/panel-controls.component.js +76 -0
  186. package/src/lib/components/panel-controls.component.js.map +1 -0
  187. package/src/lib/components/picker-search-field.d.ts +38 -0
  188. package/src/lib/components/picker-search-field.js +79 -0
  189. package/src/lib/components/picker-search-field.js.map +1 -0
  190. package/src/lib/components/plugin-settings-field.component.d.ts +38 -0
  191. package/src/lib/components/plugin-settings-field.component.js +264 -0
  192. package/src/lib/components/plugin-settings-field.component.js.map +1 -0
  193. package/src/lib/components/properties-dialog.component.d.ts +22 -0
  194. package/src/lib/components/properties-dialog.component.js +40 -0
  195. package/src/lib/components/properties-dialog.component.js.map +1 -0
  196. package/src/lib/components/property-binding-field.component.d.ts +142 -0
  197. package/src/lib/components/property-binding-field.component.js +325 -0
  198. package/src/lib/components/property-binding-field.component.js.map +1 -0
  199. package/src/lib/components/property-values-form.component.d.ts +43 -0
  200. package/src/lib/components/property-values-form.component.js +223 -0
  201. package/src/lib/components/property-values-form.component.js.map +1 -0
  202. package/src/lib/components/scheme-preview-controls.component.d.ts +26 -0
  203. package/src/lib/components/scheme-preview-controls.component.js +56 -0
  204. package/src/lib/components/scheme-preview-controls.component.js.map +1 -0
  205. package/src/lib/components/screen-link-field.component.d.ts +118 -0
  206. package/src/lib/components/screen-link-field.component.js +282 -0
  207. package/src/lib/components/screen-link-field.component.js.map +1 -0
  208. package/src/lib/components/site-theme-color-tokens-provider.component.d.ts +33 -0
  209. package/src/lib/components/site-theme-color-tokens-provider.component.js +53 -0
  210. package/src/lib/components/site-theme-color-tokens-provider.component.js.map +1 -0
  211. package/src/lib/components/subtree-json-dialog.component.d.ts +46 -0
  212. package/src/lib/components/subtree-json-dialog.component.js +125 -0
  213. package/src/lib/components/subtree-json-dialog.component.js.map +1 -0
  214. package/src/lib/components/token-pill.component.d.ts +51 -0
  215. package/src/lib/components/token-pill.component.js +164 -0
  216. package/src/lib/components/token-pill.component.js.map +1 -0
  217. package/src/lib/components/token-text-field.component.d.ts +146 -0
  218. package/src/lib/components/token-text-field.component.js +603 -0
  219. package/src/lib/components/token-text-field.component.js.map +1 -0
  220. package/src/lib/components/tree/tree-list.d.ts +6 -0
  221. package/src/lib/components/tree/tree-list.js +108 -0
  222. package/src/lib/components/tree/tree-list.js.map +1 -0
  223. package/src/lib/components/viewport-canvas.component.d.ts +23 -0
  224. package/src/lib/components/viewport-canvas.component.js +128 -0
  225. package/src/lib/components/viewport-canvas.component.js.map +1 -0
  226. package/src/lib/components/viewport-frame.component.d.ts +47 -0
  227. package/src/lib/components/viewport-frame.component.js +332 -0
  228. package/src/lib/components/viewport-frame.component.js.map +1 -0
  229. package/src/lib/components/viewport-root.component.d.ts +22 -0
  230. package/src/lib/components/viewport-root.component.js +112 -0
  231. package/src/lib/components/viewport-root.component.js.map +1 -0
  232. package/src/lib/components/viewport-zoom-controls.d.ts +29 -0
  233. package/src/lib/components/viewport-zoom-controls.js +147 -0
  234. package/src/lib/components/viewport-zoom-controls.js.map +1 -0
  235. package/src/lib/components/workspace-editor.component.d.ts +23 -0
  236. package/src/lib/components/workspace-editor.component.js +191 -0
  237. package/src/lib/components/workspace-editor.component.js.map +1 -0
  238. package/src/lib/components/workspace-panel.component.d.ts +28 -0
  239. package/src/lib/components/workspace-panel.component.js +147 -0
  240. package/src/lib/components/workspace-panel.component.js.map +1 -0
  241. package/src/lib/constants/sample-data.d.ts +18 -0
  242. package/src/lib/constants/sample-data.js +106 -0
  243. package/src/lib/constants/sample-data.js.map +1 -0
  244. package/src/lib/constants/shared.d.ts +17 -0
  245. package/src/lib/constants/shared.js +18 -0
  246. package/src/lib/constants/shared.js.map +1 -0
  247. package/src/lib/contexts/besigner-app-context.d.ts +30 -0
  248. package/src/lib/contexts/besigner-app-context.js +41 -0
  249. package/src/lib/contexts/besigner-app-context.js.map +1 -0
  250. package/src/lib/contexts/binding-picker-context.d.ts +78 -0
  251. package/src/lib/contexts/binding-picker-context.js +21 -0
  252. package/src/lib/contexts/binding-picker-context.js.map +1 -0
  253. package/src/lib/contexts/canvas-host-tokens-context.d.ts +49 -0
  254. package/src/lib/contexts/canvas-host-tokens-context.js +63 -0
  255. package/src/lib/contexts/canvas-host-tokens-context.js.map +1 -0
  256. package/src/lib/contexts/canvas-reveal-context.d.ts +32 -0
  257. package/src/lib/contexts/canvas-reveal-context.js +34 -0
  258. package/src/lib/contexts/canvas-reveal-context.js.map +1 -0
  259. package/src/lib/contexts/component-promotion-context.d.ts +89 -0
  260. package/src/lib/contexts/component-promotion-context.js +21 -0
  261. package/src/lib/contexts/component-promotion-context.js.map +1 -0
  262. package/src/lib/contexts/components-drawer-context.provider.d.ts +32 -0
  263. package/src/lib/contexts/components-drawer-context.provider.js +80 -0
  264. package/src/lib/contexts/components-drawer-context.provider.js.map +1 -0
  265. package/src/lib/contexts/element-drawer-context.d.ts +1005 -0
  266. package/src/lib/contexts/element-drawer-context.js +45 -0
  267. package/src/lib/contexts/element-drawer-context.js.map +1 -0
  268. package/src/lib/contexts/inspected-selection.d.ts +32 -0
  269. package/src/lib/contexts/inspected-selection.js +38 -0
  270. package/src/lib/contexts/inspected-selection.js.map +1 -0
  271. package/src/lib/contexts/inspector-extras-context.d.ts +56 -0
  272. package/src/lib/contexts/inspector-extras-context.js +35 -0
  273. package/src/lib/contexts/inspector-extras-context.js.map +1 -0
  274. package/src/lib/contexts/interactions-context.d.ts +99 -0
  275. package/src/lib/contexts/interactions-context.js +22 -0
  276. package/src/lib/contexts/interactions-context.js.map +1 -0
  277. package/src/lib/contexts/layout-chrome-context.d.ts +37 -0
  278. package/src/lib/contexts/layout-chrome-context.js +75 -0
  279. package/src/lib/contexts/layout-chrome-context.js.map +1 -0
  280. package/src/lib/contexts/media-asset-facts-context.d.ts +74 -0
  281. package/src/lib/contexts/media-asset-facts-context.js +27 -0
  282. package/src/lib/contexts/media-asset-facts-context.js.map +1 -0
  283. package/src/lib/contexts/media-picker-context.d.ts +88 -0
  284. package/src/lib/contexts/media-picker-context.js +21 -0
  285. package/src/lib/contexts/media-picker-context.js.map +1 -0
  286. package/src/lib/contexts/rendered-canvas-elements.d.ts +42 -0
  287. package/src/lib/contexts/rendered-canvas-elements.js +79 -0
  288. package/src/lib/contexts/rendered-canvas-elements.js.map +1 -0
  289. package/src/lib/contexts/repeat-record-context.d.ts +38 -0
  290. package/src/lib/contexts/repeat-record-context.js +21 -0
  291. package/src/lib/contexts/repeat-record-context.js.map +1 -0
  292. package/src/lib/contexts/repeat-rows-context.d.ts +53 -0
  293. package/src/lib/contexts/repeat-rows-context.js +38 -0
  294. package/src/lib/contexts/repeat-rows-context.js.map +1 -0
  295. package/src/lib/contexts/toolbar-extras-context.d.ts +31 -0
  296. package/src/lib/contexts/toolbar-extras-context.js +33 -0
  297. package/src/lib/contexts/toolbar-extras-context.js.map +1 -0
  298. package/src/lib/drafts/besigner-draft-store.d.ts +110 -0
  299. package/src/lib/drafts/besigner-draft-store.js +125 -0
  300. package/src/lib/drafts/besigner-draft-store.js.map +1 -0
  301. package/src/lib/drafts/besigner-server-draft.d.ts +130 -0
  302. package/src/lib/drafts/besigner-server-draft.js +211 -0
  303. package/src/lib/drafts/besigner-server-draft.js.map +1 -0
  304. package/src/lib/form-fields/components/shared/inline-form-control.d.ts +32 -0
  305. package/src/lib/form-fields/components/shared/inline-form-control.js +85 -0
  306. package/src/lib/form-fields/components/shared/inline-form-control.js.map +1 -0
  307. package/src/lib/form-fields/components/shared/toggle-button-form-control.d.ts +33 -0
  308. package/src/lib/form-fields/components/shared/toggle-button-form-control.js +83 -0
  309. package/src/lib/form-fields/components/shared/toggle-button-form-control.js.map +1 -0
  310. package/src/lib/form-fields/form-fields.d.ts +20 -0
  311. package/src/lib/form-fields/form-fields.js +21 -0
  312. package/src/lib/form-fields/form-fields.js.map +1 -0
  313. package/src/lib/form-fields/index.d.ts +1 -0
  314. package/src/lib/form-fields/index.js +3 -0
  315. package/src/lib/form-fields/index.js.map +1 -0
  316. package/src/lib/hooks/use-add-element-drawer-callback.d.ts +28 -0
  317. package/src/lib/hooks/use-add-element-drawer-callback.js +112 -0
  318. package/src/lib/hooks/use-add-element-drawer-callback.js.map +1 -0
  319. package/src/lib/hooks/use-aglyn-besigner-flag.d.ts +23 -0
  320. package/src/lib/hooks/use-aglyn-besigner-flag.js +47 -0
  321. package/src/lib/hooks/use-aglyn-besigner-flag.js.map +1 -0
  322. package/src/lib/hooks/use-aglyn-besigner-panel-value.d.ts +23 -0
  323. package/src/lib/hooks/use-aglyn-besigner-panel-value.js +54 -0
  324. package/src/lib/hooks/use-aglyn-besigner-panel-value.js.map +1 -0
  325. package/src/lib/hooks/use-aglyn-besigner-panel.d.ts +23 -0
  326. package/src/lib/hooks/use-aglyn-besigner-panel.js +47 -0
  327. package/src/lib/hooks/use-aglyn-besigner-panel.js.map +1 -0
  328. package/src/lib/hooks/use-anchored-rect.d.ts +68 -0
  329. package/src/lib/hooks/use-anchored-rect.js +131 -0
  330. package/src/lib/hooks/use-anchored-rect.js.map +1 -0
  331. package/src/lib/hooks/use-besigner-app-context.d.ts +18 -0
  332. package/src/lib/hooks/use-besigner-app-context.js +19 -0
  333. package/src/lib/hooks/use-besigner-app-context.js.map +1 -0
  334. package/src/lib/hooks/use-besigner-document.d.ts +309 -0
  335. package/src/lib/hooks/use-besigner-document.js +500 -0
  336. package/src/lib/hooks/use-besigner-document.js.map +1 -0
  337. package/src/lib/hooks/use-besigner-draft.d.ts +209 -0
  338. package/src/lib/hooks/use-besigner-draft.js +429 -0
  339. package/src/lib/hooks/use-besigner-draft.js.map +1 -0
  340. package/src/lib/hooks/use-clipboard-callbacks.d.ts +29 -0
  341. package/src/lib/hooks/use-clipboard-callbacks.js +82 -0
  342. package/src/lib/hooks/use-clipboard-callbacks.js.map +1 -0
  343. package/src/lib/hooks/use-clipboard-shortcuts.d.ts +52 -0
  344. package/src/lib/hooks/use-clipboard-shortcuts.js +102 -0
  345. package/src/lib/hooks/use-clipboard-shortcuts.js.map +1 -0
  346. package/src/lib/hooks/use-component-propagation-notice.d.ts +96 -0
  347. package/src/lib/hooks/use-component-propagation-notice.js +177 -0
  348. package/src/lib/hooks/use-component-propagation-notice.js.map +1 -0
  349. package/src/lib/hooks/use-debounced-commit.d.ts +43 -0
  350. package/src/lib/hooks/use-debounced-commit.js +88 -0
  351. package/src/lib/hooks/use-debounced-commit.js.map +1 -0
  352. package/src/lib/hooks/use-delete-element-callback.d.ts +24 -0
  353. package/src/lib/hooks/use-delete-element-callback.js +82 -0
  354. package/src/lib/hooks/use-delete-element-callback.js.map +1 -0
  355. package/src/lib/hooks/use-detail-hover-intent.d.ts +76 -0
  356. package/src/lib/hooks/use-detail-hover-intent.js +123 -0
  357. package/src/lib/hooks/use-detail-hover-intent.js.map +1 -0
  358. package/src/lib/hooks/use-document-repair-callbacks.d.ts +50 -0
  359. package/src/lib/hooks/use-document-repair-callbacks.js +237 -0
  360. package/src/lib/hooks/use-document-repair-callbacks.js.map +1 -0
  361. package/src/lib/hooks/use-insert-token-options.d.ts +52 -0
  362. package/src/lib/hooks/use-insert-token-options.js +230 -0
  363. package/src/lib/hooks/use-insert-token-options.js.map +1 -0
  364. package/src/lib/hooks/use-leaf-drag.d.ts +24 -0
  365. package/src/lib/hooks/use-leaf-drag.js +28 -0
  366. package/src/lib/hooks/use-leaf-drag.js.map +1 -0
  367. package/src/lib/hooks/use-leaf-drop.d.ts +31 -0
  368. package/src/lib/hooks/use-leaf-drop.js +43 -0
  369. package/src/lib/hooks/use-leaf-drop.js.map +1 -0
  370. package/src/lib/hooks/use-markdown-media-picker.d.ts +63 -0
  371. package/src/lib/hooks/use-markdown-media-picker.js +110 -0
  372. package/src/lib/hooks/use-markdown-media-picker.js.map +1 -0
  373. package/src/lib/hooks/use-media-asset-facts-overlay.d.ts +43 -0
  374. package/src/lib/hooks/use-media-asset-facts-overlay.js +133 -0
  375. package/src/lib/hooks/use-media-asset-facts-overlay.js.map +1 -0
  376. package/src/lib/hooks/use-move-node-callbacks.d.ts +22 -0
  377. package/src/lib/hooks/use-move-node-callbacks.js +57 -0
  378. package/src/lib/hooks/use-move-node-callbacks.js.map +1 -0
  379. package/src/lib/hooks/use-node-with-host-tokens.d.ts +42 -0
  380. package/src/lib/hooks/use-node-with-host-tokens.js +59 -0
  381. package/src/lib/hooks/use-node-with-host-tokens.js.map +1 -0
  382. package/src/lib/hooks/use-picker-filter.d.ts +61 -0
  383. package/src/lib/hooks/use-picker-filter.js +122 -0
  384. package/src/lib/hooks/use-picker-filter.js.map +1 -0
  385. package/src/lib/hooks/use-repeat-preview.d.ts +64 -0
  386. package/src/lib/hooks/use-repeat-preview.js +214 -0
  387. package/src/lib/hooks/use-repeat-preview.js.map +1 -0
  388. package/src/lib/hooks/use-repeat-sources.d.ts +17 -0
  389. package/src/lib/hooks/use-repeat-sources.js +41 -0
  390. package/src/lib/hooks/use-repeat-sources.js.map +1 -0
  391. package/src/lib/hooks/use-visible-component-categories.d.ts +37 -0
  392. package/src/lib/hooks/use-visible-component-categories.js +79 -0
  393. package/src/lib/hooks/use-visible-component-categories.js.map +1 -0
  394. package/src/lib/utils/active-host-theme.d.ts +28 -0
  395. package/src/lib/utils/active-host-theme.js +77 -0
  396. package/src/lib/utils/active-host-theme.js.map +1 -0
  397. package/src/lib/utils/attr-target.d.ts +170 -0
  398. package/src/lib/utils/attr-target.js +229 -0
  399. package/src/lib/utils/attr-target.js.map +1 -0
  400. package/src/lib/utils/attribute-field-value.d.ts +21 -0
  401. package/src/lib/utils/attribute-field-value.js +28 -0
  402. package/src/lib/utils/attribute-field-value.js.map +1 -0
  403. package/src/lib/utils/canvas-context-menu.d.ts +28 -0
  404. package/src/lib/utils/canvas-context-menu.js +56 -0
  405. package/src/lib/utils/canvas-context-menu.js.map +1 -0
  406. package/src/lib/utils/canvas-reveal.d.ts +115 -0
  407. package/src/lib/utils/canvas-reveal.js +165 -0
  408. package/src/lib/utils/canvas-reveal.js.map +1 -0
  409. package/src/lib/utils/describe-element.d.ts +72 -0
  410. package/src/lib/utils/describe-element.js +159 -0
  411. package/src/lib/utils/describe-element.js.map +1 -0
  412. package/src/lib/utils/device-preview-styles.d.ts +89 -0
  413. package/src/lib/utils/device-preview-styles.js +228 -0
  414. package/src/lib/utils/device-preview-styles.js.map +1 -0
  415. package/src/lib/utils/docs-help.d.ts +22 -0
  416. package/src/lib/utils/docs-help.generated.d.ts +47 -0
  417. package/src/lib/utils/docs-help.generated.js +229 -0
  418. package/src/lib/utils/docs-help.generated.js.map +1 -0
  419. package/src/lib/utils/docs-help.js +37 -0
  420. package/src/lib/utils/docs-help.js.map +1 -0
  421. package/src/lib/utils/held-answers-store.d.ts +59 -0
  422. package/src/lib/utils/held-answers-store.js +94 -0
  423. package/src/lib/utils/held-answers-store.js.map +1 -0
  424. package/src/lib/utils/in-place-edit-surface.d.ts +118 -0
  425. package/src/lib/utils/in-place-edit-surface.js +164 -0
  426. package/src/lib/utils/in-place-edit-surface.js.map +1 -0
  427. package/src/lib/utils/inline-markdown-edit.store.d.ts +71 -0
  428. package/src/lib/utils/inline-markdown-edit.store.js +90 -0
  429. package/src/lib/utils/inline-markdown-edit.store.js.map +1 -0
  430. package/src/lib/utils/inline-text-edit.store.d.ts +85 -0
  431. package/src/lib/utils/inline-text-edit.store.js +78 -0
  432. package/src/lib/utils/inline-text-edit.store.js.map +1 -0
  433. package/src/lib/utils/instance-leaf-hit.d.ts +39 -0
  434. package/src/lib/utils/instance-leaf-hit.js +56 -0
  435. package/src/lib/utils/instance-leaf-hit.js.map +1 -0
  436. package/src/lib/utils/muted-classes.d.ts +76 -0
  437. package/src/lib/utils/muted-classes.js +108 -0
  438. package/src/lib/utils/muted-classes.js.map +1 -0
  439. package/src/lib/utils/muted-styles.d.ts +125 -0
  440. package/src/lib/utils/muted-styles.js +193 -0
  441. package/src/lib/utils/muted-styles.js.map +1 -0
  442. package/src/lib/utils/numeric-text-value.d.ts +42 -0
  443. package/src/lib/utils/numeric-text-value.js +47 -0
  444. package/src/lib/utils/numeric-text-value.js.map +1 -0
  445. package/src/lib/utils/preset-interactions.d.ts +37 -0
  446. package/src/lib/utils/preset-interactions.js +87 -0
  447. package/src/lib/utils/preset-interactions.js.map +1 -0
  448. package/src/lib/utils/publish-failure-message.d.ts +35 -0
  449. package/src/lib/utils/publish-failure-message.js +51 -0
  450. package/src/lib/utils/publish-failure-message.js.map +1 -0
  451. package/src/lib/utils/rank-picker-results.d.ts +45 -0
  452. package/src/lib/utils/rank-picker-results.js +136 -0
  453. package/src/lib/utils/rank-picker-results.js.map +1 -0
  454. package/src/lib/utils/responsive-sx.d.ts +65 -0
  455. package/src/lib/utils/responsive-sx.js +129 -0
  456. package/src/lib/utils/responsive-sx.js.map +1 -0
  457. package/src/lib/utils/rich-text-commands.d.ts +28 -0
  458. package/src/lib/utils/rich-text-commands.js +43 -0
  459. package/src/lib/utils/rich-text-commands.js.map +1 -0
  460. package/src/lib/utils/sanitize-rich-text.d.ts +52 -0
  461. package/src/lib/utils/sanitize-rich-text.js +173 -0
  462. package/src/lib/utils/sanitize-rich-text.js.map +1 -0
  463. package/src/lib/utils/state-sx.d.ts +255 -0
  464. package/src/lib/utils/state-sx.js +338 -0
  465. package/src/lib/utils/state-sx.js.map +1 -0
  466. package/src/lib/utils/style-field-groups.d.ts +136 -0
  467. package/src/lib/utils/style-field-groups.js +874 -0
  468. package/src/lib/utils/style-field-groups.js.map +1 -0
  469. package/src/lib/utils/style-field-search.d.ts +84 -0
  470. package/src/lib/utils/style-field-search.js +505 -0
  471. package/src/lib/utils/style-field-search.js.map +1 -0
  472. package/src/lib/utils/style-target.d.ts +69 -0
  473. package/src/lib/utils/style-target.js +203 -0
  474. package/src/lib/utils/style-target.js.map +1 -0
  475. package/src/lib/utils/theme-scale-options.d.ts +169 -0
  476. package/src/lib/utils/theme-scale-options.js +702 -0
  477. package/src/lib/utils/theme-scale-options.js.map +1 -0
  478. package/src/lib/utils/token-editable-dom.d.ts +82 -0
  479. package/src/lib/utils/token-editable-dom.js +280 -0
  480. package/src/lib/utils/token-editable-dom.js.map +1 -0
  481. package/src/lib/utils/token-segments.d.ts +111 -0
  482. package/src/lib/utils/token-segments.js +246 -0
  483. package/src/lib/utils/token-segments.js.map +1 -0
  484. package/src/lib/utils/visibility-styles.d.ts +38 -0
  485. package/src/lib/utils/visibility-styles.js +54 -0
  486. package/src/lib/utils/visibility-styles.js.map +1 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { Firestore } from 'firebase/firestore';
18
+ import { type BesignerDraftIds } from '../drafts/besigner-draft-store';
19
+ /**
20
+ * Trailing debounce on the snapshot. Longer than the AGL-567 attribute
21
+ * debounce because this is disk work, not model work, and nobody is waiting
22
+ * on it: a snapshot one second behind the canvas is still a snapshot.
23
+ */
24
+ export declare const DRAFT_WRITE_DEBOUNCE_MS = 1000;
25
+ /**
26
+ * …and an upper bound, because a trailing debounce alone never fires during
27
+ * sustained activity. Dragging a section around for two minutes without a
28
+ * one-second pause must not mean two minutes of unprotected work.
29
+ */
30
+ export declare const DRAFT_WRITE_MAX_WAIT_MS = 15000;
31
+ /**
32
+ * Why a recovered draft may not be put back on the canvas (AGL-2486). Null
33
+ * when restoring is a private act and safe to offer.
34
+ */
35
+ export type BesignerDraftRestoreBlock =
36
+ /**
37
+ * Someone else SAVED this document after the draft was taken, so the draft
38
+ * predates work that is now in the stored document.
39
+ *
40
+ * The only remaining verdict, and it applies only when this editor is
41
+ * ALONE in the room: every shared case now withholds the whole prompt
42
+ * rather than a button (see `roomIsShared`). A `'live-session'` member
43
+ * used to sit beside this one and became unreachable the moment the
44
+ * signal that produced it also suppressed the offer — so it is gone
45
+ * rather than left as a branch nothing can enter.
46
+ */
47
+ 'saved-since';
48
+ /** Which store an offered draft came from. See `BesignerDraftState.origin`. */
49
+ export type BesignerDraftOrigin = 'browser' | 'shared';
50
+ export interface BesignerDraftState {
51
+ /**
52
+ * Unsaved work from a previous session is on hand and the author has not
53
+ * decided about it yet. Undefined ids (no draft support wired) or no draft
54
+ * both read as false.
55
+ */
56
+ available: boolean;
57
+ /**
58
+ * When the offered draft was written, per its own store; null when there is
59
+ * no offer, or when the store recorded no time.
60
+ */
61
+ takenAt: number | null;
62
+ /**
63
+ * The stored document has moved on since the draft was taken — someone
64
+ * else saved while it was stranded (AGL-674).
65
+ */
66
+ staleAgainstDocument: boolean;
67
+ /**
68
+ * WHERE the offered draft came from, which is the difference between two
69
+ * things the banner used to describe in one voice (AGL-2508).
70
+ *
71
+ * * `browser` — the local crash net. Work that was never saved, held in
72
+ * this browser only, offered back after a reload or a crash.
73
+ * * `shared` — the WORKING DRAFT on the server. The author pressed Save
74
+ * draft, was told it saved, and it did: this is that document coming
75
+ * back, from any browser, for anyone with access.
76
+ *
77
+ * Telling an author their deliberately saved draft was "recovered from
78
+ * this browser" reads as a save that failed and a browser that rescued
79
+ * them. It is the opposite on both counts.
80
+ */
81
+ origin: BesignerDraftOrigin;
82
+ /**
83
+ * Why {@link restore} is withheld, or null when it is safe to offer
84
+ * (AGL-2486). A blocked restore is a no-op, not merely an unrendered
85
+ * button: the offer and the action have to agree.
86
+ */
87
+ restoreBlockedBy: BesignerDraftRestoreBlock | null;
88
+ /**
89
+ * A SAVED draft exists that this session has neither opened nor discarded
90
+ * (AGL-2874).
91
+ *
92
+ * True even while the offer is withheld from a shared room, which is why it
93
+ * is not folded into {@link available}: what it protects is the draft, not
94
+ * the prompt. A save or publish from a canvas that never took the draft in
95
+ * must not delete it on the way past.
96
+ */
97
+ sharedDraftUnopened: boolean;
98
+ /** Puts the draft into the canvas as an undoable, unsaved change. */
99
+ restore: () => void;
100
+ /** Drops the offer and the stored draft. */
101
+ discard: () => void;
102
+ }
103
+ /**
104
+ * How many OTHER editing sessions are in this room, from the point of view
105
+ * of the recovery prompt — or null while that is not yet known (AGL-2486).
106
+ *
107
+ * Presence is the input, but its statuses do not map onto "am I alone" one
108
+ * for one, and the difference decides whether a person who crashed gets
109
+ * their work back:
110
+ *
111
+ * * `live` — the room is known. However many sessions it holds is the
112
+ * answer, zero included.
113
+ * * `idle` / `connecting` — NOT known yet. Null, so the prompt waits rather
114
+ * than offering a Discard for the second before presence lands.
115
+ * * `unauthorized` / `error` / `unconfigured` — presence cannot answer and
116
+ * never will on this load. Zero, deliberately: a deployment with no
117
+ * Realtime Database has no co-edit mirror either, so there is nothing to
118
+ * have already restored the work, and withholding recovery there would
119
+ * break the crash net for every self-host that never configured presence
120
+ * (`project_self_host_docker_byo_firebase`).
121
+ */
122
+ export declare function recoverableRoomSessions(status: string, otherSessions: number): number | null;
123
+ export interface UseBesignerDraftOptions {
124
+ /** Omit to disable drafts for this document. */
125
+ ids?: BesignerDraftIds;
126
+ /**
127
+ * Omit to use the local crash net alone (AGL-1152).
128
+ *
129
+ * Given one, the SHARED working draft is consulted too and PREFERRED when
130
+ * both exist. That ordering is the point rather than a tie-break: a local
131
+ * draft is residue from a browser that stopped, while a server draft is work
132
+ * somebody deliberately saved — possibly a colleague, possibly this person
133
+ * on another machine. Offering the crash residue over it would hand back the
134
+ * older of the two and look like data loss.
135
+ */
136
+ firestore?: Firestore;
137
+ /**
138
+ * True once the stored document has been pushed into the canvas. Nothing
139
+ * is read or written before this: writing earlier would snapshot an empty
140
+ * canvas over a real draft, and reading earlier could not tell "no draft"
141
+ * from "not loaded yet".
142
+ */
143
+ loaded: boolean;
144
+ /** The canvas differs from the last agreed state. */
145
+ dirty: boolean;
146
+ /** Current stored-document stamp, in `Aglyn.versionStamp` form. */
147
+ storedStamp: string | null;
148
+ /**
149
+ * The stored document's node map, in stored shape (AGL-2874).
150
+ *
151
+ * Lets a draft tell a write that moved the TREE from one that only moved
152
+ * the stamp — a component's declared properties, a version's layout
153
+ * binding. Only the first makes restoring a draft a rollback. Omitted, every
154
+ * stamp change counts, which is the conservative answer.
155
+ */
156
+ storedNodes?: unknown;
157
+ /**
158
+ * Other live editing sessions in this room, or null while unknown — see
159
+ * {@link recoverableRoomSessions}, which is how a caller with a presence
160
+ * state derives it (AGL-2486).
161
+ *
162
+ * Omitted means ZERO, not unknown: an editor with no presence at all (the
163
+ * system-email besigner has no honest orgId for a room) is a single-player
164
+ * session by construction, and must keep its crash net.
165
+ */
166
+ roomSessions?: number | null;
167
+ }
168
+ /**
169
+ * Keeps a single local snapshot of unsaved canvas work per document, and
170
+ * offers it back after a crash (AGL-1256).
171
+ *
172
+ * See `besigner-draft-store` for why this is a crash net and not version
173
+ * history — in particular why the draft is destroyed the instant a save
174
+ * succeeds, which is the property that keeps it from being a free stand-in
175
+ * for the paid versioning feature.
176
+ *
177
+ * **Two tabs on one document write one draft key, last writer wins.** That
178
+ * is deliberate: both tabs are editing the same version and the newest
179
+ * unsaved state is the one worth recovering. Nothing here tries to merge
180
+ * them; merging whole node maps is AGL-677's problem, not a crash net's.
181
+ *
182
+ * ## Where this sits next to live co-editing (AGL-2486)
183
+ *
184
+ * There are two "unsaved" states in a besigner editor and they have
185
+ * different scopes, which is why the prompt says "from this browser" out
186
+ * loud:
187
+ *
188
+ * * The **co-edit mirror** (AGL-677) is the SHARED one. It carries unsaved
189
+ * work per node between sessions and replays it to whoever joins, so
190
+ * opening a document someone else is editing already shows their
191
+ * in-progress state — and shows you your own again after a crash, before
192
+ * this prompt is read.
193
+ * * This draft is the PRIVATE one: one snapshot, in one browser, for the
194
+ * case where nothing else survived.
195
+ *
196
+ * They are not merged and this one is not made shareable — the mirror
197
+ * already is that, per node, without a merge of two whole maps.
198
+ *
199
+ * The private snapshot is not OFFERED at all while the room is shared
200
+ * (AGL-2486). Withholding only Restore is not enough: that leaves a prompt
201
+ * whose one remaining button is Discard, standing over work several people
202
+ * are still doing. Recovery is a crash story, a crash means nothing else
203
+ * survived, and a live room is proof that something did. See
204
+ * `roomIsShared` in the body for the two signals that decide it, and
205
+ * {@link BesignerDraftState.restoreBlockedBy} for the narrower verdicts that
206
+ * still apply when this editor is alone.
207
+ */
208
+ export declare function useBesignerDraft(options: UseBesignerDraftOptions): BesignerDraftState;
209
+ export default useBesignerDraft;
@@ -0,0 +1,429 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { _ as _extends } from "@swc/helpers/_/_extends";
17
+ import { canvas, hasConcurrentWrite } from "@aglyn/aglyn";
18
+ import isEqual from "lodash-es/isEqual.js";
19
+ import { autorun } from "mobx";
20
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
21
+ import { besignerDraftKey, clearBesignerDraft, pruneBesignerDrafts, readBesignerDraft, writeBesignerDraft } from "../drafts/besigner-draft-store.js";
22
+ import { clearServerDraft, readServerDraft } from "../drafts/besigner-server-draft.js";
23
+ import { useDebouncedCommit } from "./use-debounced-commit.js";
24
+ /**
25
+ * Trailing debounce on the snapshot. Longer than the AGL-567 attribute
26
+ * debounce because this is disk work, not model work, and nobody is waiting
27
+ * on it: a snapshot one second behind the canvas is still a snapshot.
28
+ */ export const DRAFT_WRITE_DEBOUNCE_MS = 1000;
29
+ /**
30
+ * …and an upper bound, because a trailing debounce alone never fires during
31
+ * sustained activity. Dragging a section around for two minutes without a
32
+ * one-second pause must not mean two minutes of unprotected work.
33
+ */ export const DRAFT_WRITE_MAX_WAIT_MS = 15000;
34
+ const EMPTY_STATE = {
35
+ available: false,
36
+ takenAt: null,
37
+ staleAgainstDocument: false,
38
+ origin: 'browser',
39
+ restoreBlockedBy: null,
40
+ sharedDraftUnopened: false,
41
+ restore: ()=>undefined,
42
+ discard: ()=>undefined
43
+ };
44
+ /**
45
+ * How many OTHER editing sessions are in this room, from the point of view
46
+ * of the recovery prompt — or null while that is not yet known (AGL-2486).
47
+ *
48
+ * Presence is the input, but its statuses do not map onto "am I alone" one
49
+ * for one, and the difference decides whether a person who crashed gets
50
+ * their work back:
51
+ *
52
+ * * `live` — the room is known. However many sessions it holds is the
53
+ * answer, zero included.
54
+ * * `idle` / `connecting` — NOT known yet. Null, so the prompt waits rather
55
+ * than offering a Discard for the second before presence lands.
56
+ * * `unauthorized` / `error` / `unconfigured` — presence cannot answer and
57
+ * never will on this load. Zero, deliberately: a deployment with no
58
+ * Realtime Database has no co-edit mirror either, so there is nothing to
59
+ * have already restored the work, and withholding recovery there would
60
+ * break the crash net for every self-host that never configured presence
61
+ * (`project_self_host_docker_byo_firebase`).
62
+ */ export function recoverableRoomSessions(status, otherSessions) {
63
+ if (status === 'live') return otherSessions;
64
+ if (status === 'idle' || status === 'connecting') return null;
65
+ return 0;
66
+ }
67
+ /**
68
+ * Keeps a single local snapshot of unsaved canvas work per document, and
69
+ * offers it back after a crash (AGL-1256).
70
+ *
71
+ * See `besigner-draft-store` for why this is a crash net and not version
72
+ * history — in particular why the draft is destroyed the instant a save
73
+ * succeeds, which is the property that keeps it from being a free stand-in
74
+ * for the paid versioning feature.
75
+ *
76
+ * **Two tabs on one document write one draft key, last writer wins.** That
77
+ * is deliberate: both tabs are editing the same version and the newest
78
+ * unsaved state is the one worth recovering. Nothing here tries to merge
79
+ * them; merging whole node maps is AGL-677's problem, not a crash net's.
80
+ *
81
+ * ## Where this sits next to live co-editing (AGL-2486)
82
+ *
83
+ * There are two "unsaved" states in a besigner editor and they have
84
+ * different scopes, which is why the prompt says "from this browser" out
85
+ * loud:
86
+ *
87
+ * * The **co-edit mirror** (AGL-677) is the SHARED one. It carries unsaved
88
+ * work per node between sessions and replays it to whoever joins, so
89
+ * opening a document someone else is editing already shows their
90
+ * in-progress state — and shows you your own again after a crash, before
91
+ * this prompt is read.
92
+ * * This draft is the PRIVATE one: one snapshot, in one browser, for the
93
+ * case where nothing else survived.
94
+ *
95
+ * They are not merged and this one is not made shareable — the mirror
96
+ * already is that, per node, without a merge of two whole maps.
97
+ *
98
+ * The private snapshot is not OFFERED at all while the room is shared
99
+ * (AGL-2486). Withholding only Restore is not enough: that leaves a prompt
100
+ * whose one remaining button is Discard, standing over work several people
101
+ * are still doing. Recovery is a crash story, a crash means nothing else
102
+ * survived, and a live room is proof that something did. See
103
+ * `roomIsShared` in the body for the two signals that decide it, and
104
+ * {@link BesignerDraftState.restoreBlockedBy} for the narrower verdicts that
105
+ * still apply when this editor is alone.
106
+ */ export function useBesignerDraft(options) {
107
+ var _sameTreeStampsRef_current;
108
+ const { ids, loaded, dirty, storedStamp, storedNodes, firestore } = options;
109
+ // `??` would fold null into 0 and lose the distinction the whole rule
110
+ // rests on: null is "presence has not answered yet", 0 is "it answered,
111
+ // and you are alone".
112
+ const roomSessions = options.roomSessions === undefined ? 0 : options.roomSessions;
113
+ const key = ids ? besignerDraftKey(ids) : null;
114
+ /** The draft being offered, held in memory for the life of the offer. */ const [offer, setOffer] = useState(null);
115
+ /**
116
+ * Which store {@link offer} came from (AGL-2508). Tracked beside the offer
117
+ * rather than folded into `BesignerDraft`, because the stored shape is what
118
+ * both stores persist and neither one records where it ended up being read
119
+ * from — that is a fact about this load, not about the document.
120
+ */ const [offerOrigin, setOfferOrigin] = useState('browser');
121
+ /** Guards the read so it happens exactly once per document, before writes. */ const readKeyRef = useRef(null);
122
+ /**
123
+ * The same guard for the SHARED draft, kept apart from the local one
124
+ * because the two become readable at different moments (AGL-2874).
125
+ *
126
+ * An editor passes `firestore` only once its PARENT document has said that
127
+ * this is the live version, and the version document can reach the canvas
128
+ * before that. With one latch for both, the local read takes it and the
129
+ * shared draft is never read that session — no offer, and nothing standing
130
+ * between the draft and a save that overwrites it.
131
+ */ const serverReadKeyRef = useRef(null);
132
+ const idsRef = useRef(ids);
133
+ idsRef.current = ids;
134
+ const storedStampRef = useRef(storedStamp);
135
+ storedStampRef.current = storedStamp;
136
+ /**
137
+ * Whether this session has ever written the draft slot. Without it the
138
+ * clean-canvas cleanup below would delete the draft it was just offered:
139
+ * a freshly loaded document is clean by definition, so "clean" only means
140
+ * "nothing left to protect" once we have actually put something there.
141
+ */ const wroteRef = useRef(false);
142
+ const writeDraft = useCallback(()=>{
143
+ const currentIds = idsRef.current;
144
+ if (!currentIds) return;
145
+ wroteRef.current = true;
146
+ // Serialising here rather than in the autorun is the whole point of the
147
+ // debounce: the tracking read is cheap to repeat, `JSON.stringify` of a
148
+ // 200-node map plus a synchronous `setItem` is not (AGL-567).
149
+ const nodes = canvas.toJSON().nodes;
150
+ writeBesignerDraft(currentIds, {
151
+ nodes,
152
+ baseStamp: storedStampRef.current
153
+ });
154
+ }, []);
155
+ const { schedule, flush } = useDebouncedCommit(writeDraft, DRAFT_WRITE_DEBOUNCE_MS, {
156
+ maxWait: DRAFT_WRITE_MAX_WAIT_MS
157
+ });
158
+ // Read the existing draft once the document is in the canvas, and before
159
+ // anything can overwrite it.
160
+ // Keyed on the storage key rather than the ids object: callers build that
161
+ // object inline, so a dependency on it would re-run this on every render.
162
+ useEffect(()=>{
163
+ const currentIds = idsRef.current;
164
+ if (!key || !currentIds || !loaded) return undefined;
165
+ if (readKeyRef.current !== key) {
166
+ var _local_updatedAt;
167
+ readKeyRef.current = key;
168
+ pruneBesignerDrafts();
169
+ const local = readBesignerDraft(currentIds);
170
+ setOffer(local ? {
171
+ nodes: local.nodes,
172
+ baseStamp: local.baseStamp,
173
+ takenAt: (_local_updatedAt = local.updatedAt) != null ? _local_updatedAt : null
174
+ } : null);
175
+ setOfferOrigin('browser');
176
+ }
177
+ // The shared draft answers late, and wins when it answers. It is read at
178
+ // most once per document too, so a slow reply cannot re-offer a draft
179
+ // the author has meanwhile restored or discarded.
180
+ if (!firestore || serverReadKeyRef.current === key) return undefined;
181
+ serverReadKeyRef.current = key;
182
+ let live = true;
183
+ let answered = false;
184
+ void readServerDraft(firestore, currentIds).then((server)=>{
185
+ answered = true;
186
+ if (!live || !server) return;
187
+ setOfferOrigin('shared');
188
+ setOffer({
189
+ nodes: server.nodes,
190
+ baseStamp: server.baseStamp,
191
+ // The server's stamp, so the banner tells the draft's real age.
192
+ // Expiry never reads it: `DRAFT_MAX_AGE_MS` belongs to the crash
193
+ // net, and a saved draft lives until it is published or discarded.
194
+ takenAt: server.updatedAt
195
+ });
196
+ }).catch(()=>{
197
+ answered = true;
198
+ });
199
+ return ()=>{
200
+ live = false;
201
+ // A read torn down before it answered never happened, so the next run
202
+ // asks again rather than finding the latch already taken.
203
+ if (!answered) serverReadKeyRef.current = null;
204
+ };
205
+ }, [
206
+ key,
207
+ loaded,
208
+ firestore
209
+ ]);
210
+ // Snapshot on canvas change. `autorun` re-runs whenever anything the
211
+ // tracked read touched changes, and `toJSON()` touches every node — which
212
+ // is the same depth of read the existing `isInitialSame` computed already
213
+ // performs on every change, so this adds a constant factor to a path that
214
+ // is already O(nodes), not a new order of cost.
215
+ useEffect(()=>{
216
+ if (!key || !loaded) return undefined;
217
+ return autorun(()=>{
218
+ canvas.toJSON();
219
+ if (canvas.isInitialSame) return;
220
+ schedule();
221
+ });
222
+ }, [
223
+ key,
224
+ loaded,
225
+ schedule
226
+ ]);
227
+ // Returning to the saved state (an undo back to it, or a save landing)
228
+ // means there is no unsaved work left IN THIS BROWSER to protect. Dropping
229
+ // the crash net here is what stops it lingering as a restore point for a
230
+ // document that has moved past it.
231
+ //
232
+ // The SHARED draft is not this effect's to drop (AGL-2874). It is work
233
+ // somebody deliberately saved, and a canvas back at the stored document says
234
+ // nothing about it: edit anything and undo it, and this runs with the shared
235
+ // draft still unopened. Deciding about it belongs to Discard, and to a save
236
+ // or publish of a canvas that took the draft in.
237
+ useEffect(()=>{
238
+ const currentIds = idsRef.current;
239
+ if (!key || !currentIds || !loaded || dirty) return;
240
+ if (!wroteRef.current) return;
241
+ // Flush before clearing, not after: a timer left pending would land
242
+ // *after* the delete and re-create a draft whose content is identical to
243
+ // the saved document — offered on the next load as unsaved work that
244
+ // never existed.
245
+ flush();
246
+ clearBesignerDraft(currentIds);
247
+ wroteRef.current = false;
248
+ }, [
249
+ key,
250
+ loaded,
251
+ dirty,
252
+ flush
253
+ ]);
254
+ // A crash is not the only way a tab dies; closing it is the common one,
255
+ // and `pagehide` is the last reliable moment to get the pending snapshot
256
+ // onto disk. `visibilitychange` covers the mobile/background case where
257
+ // `pagehide` may never fire.
258
+ useEffect(()=>{
259
+ if (!key || !loaded) return undefined;
260
+ const flushNow = ()=>{
261
+ if (!canvas.isInitialSame) flush();
262
+ };
263
+ const onVisibility = ()=>{
264
+ if (document.visibilityState === 'hidden') flushNow();
265
+ };
266
+ window.addEventListener('pagehide', flushNow);
267
+ document.addEventListener('visibilitychange', onVisibility);
268
+ return ()=>{
269
+ window.removeEventListener('pagehide', flushNow);
270
+ document.removeEventListener('visibilitychange', onVisibility);
271
+ };
272
+ }, [
273
+ key,
274
+ loaded,
275
+ flush
276
+ ]);
277
+ /**
278
+ * A peer's live change is on this canvas. Read OUTSIDE the memo below so
279
+ * the observer that renders the prompt re-runs it when the first remote
280
+ * change lands — a mobx read inside a `useMemo` whose deps never mention
281
+ * it would keep serving the verdict from mount.
282
+ */ const canvasHasRemoteEdits = canvas.hasRemoteEdits;
283
+ /**
284
+ * Every stamp the stored document has carried this session while its tree
285
+ * stayed exactly as it is now (AGL-2874).
286
+ *
287
+ * A write that leaves `nodes` alone still moves `updatedAt` — declaring a
288
+ * component's properties is one — and a draft judged on the stamp alone
289
+ * becomes unrestorable the moment an author does that, though putting it
290
+ * back could roll nothing back. A draft taken against any stamp in this set
291
+ * is a draft of this very tree. Reset whenever the tree itself changes, so
292
+ * someone else's saved nodes still block it.
293
+ *
294
+ * Kept in a ref and brought up to date during render: the answer has to be
295
+ * right in the same render the new stamp arrives in, or the banner shows a
296
+ * blocked draft for a frame. Adding a stamp twice changes nothing, so a
297
+ * repeated render lands in the same place.
298
+ */ const sameTreeStampsRef = useRef(undefined);
299
+ if (storedNodes !== undefined && storedStamp) {
300
+ const current = sameTreeStampsRef.current;
301
+ if (!current || current.nodes !== storedNodes && !isEqual(current.nodes, storedNodes)) {
302
+ sameTreeStampsRef.current = {
303
+ nodes: storedNodes,
304
+ stamps: new Set([
305
+ storedStamp
306
+ ])
307
+ };
308
+ } else {
309
+ current.nodes = storedNodes;
310
+ current.stamps.add(storedStamp);
311
+ }
312
+ }
313
+ const draftOfThisTree = Boolean((offer == null ? void 0 : offer.baseStamp) && ((_sameTreeStampsRef_current = sameTreeStampsRef.current) == null ? void 0 : _sameTreeStampsRef_current.stamps.has(offer.baseStamp)));
314
+ const staleAgainstDocument = Boolean(offer && hasConcurrentWrite(offer.baseStamp, storedStamp) && !draftOfThisTree);
315
+ /**
316
+ * Restoring is a WHOLE-MAP replace, and in a shared session that is not a
317
+ * private act (AGL-2486). Measured on the running editor: a peer created a
318
+ * node, the other session pressed Restore, and the node was deleted on the
319
+ * peer's own screen; with a stale draft the same click reverted a
320
+ * colleague's SAVED work and survived the reload the conflict banner asks
321
+ * for, with Save re-enabled and no warning left on screen.
322
+ *
323
+ * So the offer is withheld rather than merely re-worded. What the author
324
+ * loses by that is small and the mirror mostly covers it: unsaved work in a
325
+ * co-edited room is republished to whoever rejoins, which is how their own
326
+ * changes are already back on the canvas before this prompt is even read.
327
+ * What they would lose by the other choice is someone else's work.
328
+ */ const restoreBlockedBy = staleAgainstDocument ? 'saved-since' : null;
329
+ /**
330
+ * Whether this room is somebody else's too, i.e. whether the mirror
331
+ * already has the work this prompt is about (AGL-2486).
332
+ *
333
+ * The recovery prompt exists for a CRASH, and a crash is the case where
334
+ * nothing else survived. When something else demonstrably did — a third tab
335
+ * opening onto a document two other tabs are editing unsaved — there is no
336
+ * recovery to offer, and both buttons can only do harm to work that is
337
+ * still in progress.
338
+ *
339
+ * TWO signals, OR'd, because they cover different halves of "the mirror
340
+ * already has this" and neither implies the other:
341
+ *
342
+ * * **Presence membership.** Another session is in the room right now. It
343
+ * may not have published anything since this tab joined — a colleague
344
+ * who is reading rather than typing publishes nothing — but the mirror
345
+ * is live and their unsaved work is in it, so a whole-map replace from
346
+ * an older private snapshot would still be a replace of shared state.
347
+ * * **Mirror-entry presence** (`canvas.hasRemoteEdits`). The mirror has
348
+ * already replayed another session's unsaved work ONTO this canvas.
349
+ * This is the half that catches the room whose other sessions have since
350
+ * closed: their work came back on join, and it is on screen now.
351
+ *
352
+ * Presence alone misses the second; `hasRemoteEdits` alone misses the
353
+ * first, which is any tab that joins a live room before anyone in it types
354
+ * again. Unknown (null) counts as shared until presence says otherwise —
355
+ * the cost of waiting a second is a delayed offer, the cost of guessing
356
+ * wrong is a Discard button over other people's work.
357
+ *
358
+ * What is NOT withheld: a person alone in the room after a browser quit
359
+ * gets the full offer, Restore included. That case is the entire reason
360
+ * the feature exists, and nothing here narrows it.
361
+ */ const roomIsShared = roomSessions === null || roomSessions > 0 || canvasHasRemoteEdits;
362
+ const restore = useCallback(()=>{
363
+ const draft = offer;
364
+ if (!draft) return;
365
+ // The action agrees with the offer. A component that renders Restore
366
+ // without consulting `restoreBlockedBy` still cannot roll a colleague
367
+ // back through this path.
368
+ if (restoreBlockedBy || roomIsShared) return;
369
+ // `applyNodes` snapshots history first, so restoring is undoable and
370
+ // leaves the canvas dirty. Dirty matters beyond the save button: it is
371
+ // what keeps "Save the canvas before creating a version" firing, so a
372
+ // restored draft can never be swept into a version snapshot.
373
+ canvas.applyNodes(draft.nodes);
374
+ setOffer(null);
375
+ }, [
376
+ offer,
377
+ restoreBlockedBy,
378
+ roomIsShared
379
+ ]);
380
+ const discard = useCallback(()=>{
381
+ const currentIds = idsRef.current;
382
+ setOffer(null);
383
+ if (!currentIds) return;
384
+ clearBesignerDraft(currentIds);
385
+ // Whichever store the offer came from. The shared draft is PREFERRED over
386
+ // the local one when both exist, so declining an offer that clearing only
387
+ // localStorage cannot reach leaves the author declining the same thing on
388
+ // every reload, with no way to stop being asked.
389
+ if (firestore) void clearServerDraft(firestore, currentIds);
390
+ }, [
391
+ firestore
392
+ ]);
393
+ const sharedDraftUnopened = Boolean(offer && offerOrigin === 'shared');
394
+ return useMemo(()=>{
395
+ if (!key || !offer) return EMPTY_STATE;
396
+ // No prompt at all in a shared room — not a re-worded one. The draft is
397
+ // deliberately LEFT ON DISK: nothing about the room makes this browser's
398
+ // snapshot wrong, only unofferable, and reaping it here would take away
399
+ // the crash net of the very tab that is still holding the work.
400
+ if (roomIsShared) {
401
+ return sharedDraftUnopened ? _extends({}, EMPTY_STATE, {
402
+ sharedDraftUnopened
403
+ }) : EMPTY_STATE;
404
+ }
405
+ return {
406
+ available: true,
407
+ takenAt: offer.takenAt,
408
+ staleAgainstDocument,
409
+ origin: offerOrigin,
410
+ restoreBlockedBy,
411
+ sharedDraftUnopened,
412
+ restore,
413
+ discard
414
+ };
415
+ }, [
416
+ key,
417
+ offer,
418
+ offerOrigin,
419
+ roomIsShared,
420
+ staleAgainstDocument,
421
+ restoreBlockedBy,
422
+ sharedDraftUnopened,
423
+ restore,
424
+ discard
425
+ ]);
426
+ }
427
+ export default useBesignerDraft;
428
+
429
+ //# sourceMappingURL=use-besigner-draft.js.map