@formicoidea/labre-core 0.23.0 → 0.23.2

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 (1624) hide show
  1. package/package.json +1 -1
  2. package/src/_pkgs/affine-block-attachment/adapters/extension.ts +9 -9
  3. package/src/_pkgs/affine-block-attachment/adapters/markdown.ts +85 -85
  4. package/src/_pkgs/affine-block-attachment/adapters/notion-html.ts +115 -115
  5. package/src/_pkgs/affine-block-attachment/attachment-block.ts +533 -533
  6. package/src/_pkgs/affine-block-attachment/attachment-edgeless-block.ts +72 -72
  7. package/src/_pkgs/affine-block-attachment/attachment-service.ts +51 -51
  8. package/src/_pkgs/affine-block-attachment/components/rename-model.ts +95 -95
  9. package/src/_pkgs/affine-block-attachment/components/styles.ts +64 -64
  10. package/src/_pkgs/affine-block-attachment/configs/slash-menu.ts +58 -58
  11. package/src/_pkgs/affine-block-attachment/configs/toolbar.ts +411 -411
  12. package/src/_pkgs/affine-block-attachment/edgeless-clipboard-config.ts +34 -34
  13. package/src/_pkgs/affine-block-attachment/embed.ts +305 -305
  14. package/src/_pkgs/affine-block-attachment/store.ts +17 -17
  15. package/src/_pkgs/affine-block-attachment/styles.ts +160 -160
  16. package/src/_pkgs/affine-block-attachment/utils.ts +216 -216
  17. package/src/_pkgs/affine-block-attachment/view.ts +51 -51
  18. package/src/_pkgs/affine-block-bookmark/adapters/extension.ts +13 -13
  19. package/src/_pkgs/affine-block-bookmark/adapters/html.ts +10 -10
  20. package/src/_pkgs/affine-block-bookmark/adapters/markdown/index.ts +12 -12
  21. package/src/_pkgs/affine-block-bookmark/adapters/markdown/markdown.ts +93 -93
  22. package/src/_pkgs/affine-block-bookmark/adapters/markdown/preprocessor.ts +263 -263
  23. package/src/_pkgs/affine-block-bookmark/adapters/notion-html.ts +71 -71
  24. package/src/_pkgs/affine-block-bookmark/adapters/plain-text.ts +9 -9
  25. package/src/_pkgs/affine-block-bookmark/bookmark-block.ts +291 -291
  26. package/src/_pkgs/affine-block-bookmark/bookmark-edgeless-block.ts +88 -88
  27. package/src/_pkgs/affine-block-bookmark/commands/insert-bookmark.ts +23 -23
  28. package/src/_pkgs/affine-block-bookmark/commands/insert-link-by-quick-search.ts +79 -79
  29. package/src/_pkgs/affine-block-bookmark/components/bookmark-card.ts +131 -131
  30. package/src/_pkgs/affine-block-bookmark/configs/slash-menu.ts +65 -65
  31. package/src/_pkgs/affine-block-bookmark/configs/toolbar.ts +625 -625
  32. package/src/_pkgs/affine-block-bookmark/edgeless-clipboard-config.ts +29 -29
  33. package/src/_pkgs/affine-block-bookmark/store.ts +17 -17
  34. package/src/_pkgs/affine-block-bookmark/styles.ts +282 -282
  35. package/src/_pkgs/affine-block-bookmark/utils.ts +47 -47
  36. package/src/_pkgs/affine-block-bookmark/view.ts +43 -43
  37. package/src/_pkgs/affine-block-callout/adapters/markdown.ts +207 -207
  38. package/src/_pkgs/affine-block-callout/callout-block.ts +132 -132
  39. package/src/_pkgs/affine-block-callout/callout-keymap.ts +34 -34
  40. package/src/_pkgs/affine-block-callout/configs/slash-menu.ts +67 -67
  41. package/src/_pkgs/affine-block-callout/emoji-menu.ts +34 -34
  42. package/src/_pkgs/affine-block-callout/store.ts +17 -17
  43. package/src/_pkgs/affine-block-callout/view.ts +30 -30
  44. package/src/_pkgs/affine-block-code/adapters/extension.ts +13 -13
  45. package/src/_pkgs/affine-block-code/adapters/html.ts +109 -109
  46. package/src/_pkgs/affine-block-code/adapters/markdown/index.ts +12 -12
  47. package/src/_pkgs/affine-block-code/adapters/markdown/markdown.ts +99 -99
  48. package/src/_pkgs/affine-block-code/adapters/markdown/preprocessor.ts +76 -76
  49. package/src/_pkgs/affine-block-code/adapters/notion-html.ts +59 -59
  50. package/src/_pkgs/affine-block-code/adapters/plain-text.ts +26 -26
  51. package/src/_pkgs/affine-block-code/clipboard/index.ts +173 -173
  52. package/src/_pkgs/affine-block-code/code-block-config.ts +19 -19
  53. package/src/_pkgs/affine-block-code/code-block-inline.ts +50 -50
  54. package/src/_pkgs/affine-block-code/code-block-service.ts +69 -69
  55. package/src/_pkgs/affine-block-code/code-block.ts +498 -498
  56. package/src/_pkgs/affine-block-code/code-keymap.ts +7 -7
  57. package/src/_pkgs/affine-block-code/code-preview-extension.ts +27 -27
  58. package/src/_pkgs/affine-block-code/code-toolbar/components/code-toolbar.ts +159 -159
  59. package/src/_pkgs/affine-block-code/code-toolbar/components/lang-button.ts +168 -168
  60. package/src/_pkgs/affine-block-code/code-toolbar/components/preview-button.ts +112 -112
  61. package/src/_pkgs/affine-block-code/code-toolbar/config.ts +284 -284
  62. package/src/_pkgs/affine-block-code/code-toolbar/context.ts +46 -46
  63. package/src/_pkgs/affine-block-code/code-toolbar/index.ts +173 -173
  64. package/src/_pkgs/affine-block-code/code-toolbar/utils.ts +16 -16
  65. package/src/_pkgs/affine-block-code/configs/slash-menu.ts +8 -8
  66. package/src/_pkgs/affine-block-code/highlight/affine-code-unit.ts +122 -122
  67. package/src/_pkgs/affine-block-code/markdown.ts +61 -61
  68. package/src/_pkgs/affine-block-code/store.ts +19 -19
  69. package/src/_pkgs/affine-block-code/styles.ts +73 -73
  70. package/src/_pkgs/affine-block-code/turbo/code-layout-handler.ts +73 -73
  71. package/src/_pkgs/affine-block-code/turbo/code-painter.worker.ts +53 -53
  72. package/src/_pkgs/affine-block-code/view.ts +65 -65
  73. package/src/_pkgs/affine-block-data-view/block-meta/base.ts +37 -37
  74. package/src/_pkgs/affine-block-data-view/block-meta/todo.ts +13 -13
  75. package/src/_pkgs/affine-block-data-view/columns/index.ts +22 -22
  76. package/src/_pkgs/affine-block-data-view/configs/slash-menu.ts +51 -51
  77. package/src/_pkgs/affine-block-data-view/data-source.ts +326 -326
  78. package/src/_pkgs/affine-block-data-view/data-view-block.ts +318 -318
  79. package/src/_pkgs/affine-block-data-view/data-view-model.ts +102 -102
  80. package/src/_pkgs/affine-block-data-view/data-view-spec.ts +8 -8
  81. package/src/_pkgs/affine-block-data-view/store.ts +15 -15
  82. package/src/_pkgs/affine-block-data-view/view.ts +28 -28
  83. package/src/_pkgs/affine-block-data-view/views/index.ts +11 -11
  84. package/src/_pkgs/affine-block-database/adapters/extension.ts +13 -13
  85. package/src/_pkgs/affine-block-database/adapters/html.ts +105 -105
  86. package/src/_pkgs/affine-block-database/adapters/markdown.ts +67 -67
  87. package/src/_pkgs/affine-block-database/adapters/notion-html.ts +358 -358
  88. package/src/_pkgs/affine-block-database/adapters/plain-text.ts +48 -48
  89. package/src/_pkgs/affine-block-database/adapters/utils.ts +109 -109
  90. package/src/_pkgs/affine-block-database/block-icons.ts +45 -45
  91. package/src/_pkgs/affine-block-database/commands.ts +69 -69
  92. package/src/_pkgs/affine-block-database/components/layout.ts +69 -69
  93. package/src/_pkgs/affine-block-database/components/title/index.ts +199 -199
  94. package/src/_pkgs/affine-block-database/config.ts +6 -6
  95. package/src/_pkgs/affine-block-database/configs/slash-menu.ts +83 -83
  96. package/src/_pkgs/affine-block-database/context/host-context.ts +4 -4
  97. package/src/_pkgs/affine-block-database/data-source.ts +667 -667
  98. package/src/_pkgs/affine-block-database/database-block.ts +468 -468
  99. package/src/_pkgs/affine-block-database/database-dnd-preview-block.ts +58 -58
  100. package/src/_pkgs/affine-block-database/detail-panel/block-renderer.ts +158 -158
  101. package/src/_pkgs/affine-block-database/detail-panel/note-renderer.ts +129 -129
  102. package/src/_pkgs/affine-block-database/index.ts +14 -14
  103. package/src/_pkgs/affine-block-database/properties/converts.ts +176 -176
  104. package/src/_pkgs/affine-block-database/properties/created-time/cell-renderer.ts +54 -54
  105. package/src/_pkgs/affine-block-database/properties/created-time/define.ts +30 -30
  106. package/src/_pkgs/affine-block-database/properties/index.ts +29 -29
  107. package/src/_pkgs/affine-block-database/properties/link/cell-renderer-css.ts +99 -99
  108. package/src/_pkgs/affine-block-database/properties/link/cell-renderer.ts +186 -186
  109. package/src/_pkgs/affine-block-database/properties/link/define.ts +25 -25
  110. package/src/_pkgs/affine-block-database/properties/model.ts +20 -20
  111. package/src/_pkgs/affine-block-database/properties/rich-text/cell-renderer.ts +430 -430
  112. package/src/_pkgs/affine-block-database/properties/rich-text/define.ts +77 -77
  113. package/src/_pkgs/affine-block-database/properties/title/cell-renderer-css.ts +31 -31
  114. package/src/_pkgs/affine-block-database/properties/title/cell-renderer.ts +23 -23
  115. package/src/_pkgs/affine-block-database/properties/title/define.ts +83 -83
  116. package/src/_pkgs/affine-block-database/properties/title/icon.ts +21 -21
  117. package/src/_pkgs/affine-block-database/properties/title/text.ts +319 -319
  118. package/src/_pkgs/affine-block-database/selection.ts +68 -68
  119. package/src/_pkgs/affine-block-database/service/index.ts +11 -11
  120. package/src/_pkgs/affine-block-database/store.ts +19 -19
  121. package/src/_pkgs/affine-block-database/utils/block-utils.ts +240 -240
  122. package/src/_pkgs/affine-block-database/utils/title-doc.ts +30 -30
  123. package/src/_pkgs/affine-block-database/view.ts +51 -51
  124. package/src/_pkgs/affine-block-database/views/index.ts +12 -12
  125. package/src/_pkgs/affine-block-divider/adapters/extension.ts +13 -13
  126. package/src/_pkgs/affine-block-divider/adapters/html.ts +53 -53
  127. package/src/_pkgs/affine-block-divider/adapters/markdown.ts +50 -50
  128. package/src/_pkgs/affine-block-divider/adapters/notion-html.ts +38 -38
  129. package/src/_pkgs/affine-block-divider/adapters/plain-text.ts +21 -21
  130. package/src/_pkgs/affine-block-divider/divider-block.ts +50 -50
  131. package/src/_pkgs/affine-block-divider/markdown.ts +63 -63
  132. package/src/_pkgs/affine-block-divider/store.ts +17 -17
  133. package/src/_pkgs/affine-block-divider/view.ts +26 -26
  134. package/src/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.ts +33 -33
  135. package/src/_pkgs/affine-block-edgeless-text/edgeless-text-block.ts +512 -512
  136. package/src/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.ts +19 -19
  137. package/src/_pkgs/affine-block-edgeless-text/store.ts +14 -14
  138. package/src/_pkgs/affine-block-edgeless-text/view.ts +37 -37
  139. package/src/_pkgs/affine-block-embed/common/adapters/html.ts +66 -66
  140. package/src/_pkgs/affine-block-embed/common/adapters/markdown.ts +58 -58
  141. package/src/_pkgs/affine-block-embed/common/adapters/notion-html.ts +89 -89
  142. package/src/_pkgs/affine-block-embed/common/adapters/plain-text.ts +40 -40
  143. package/src/_pkgs/affine-block-embed/common/embed-block-element.ts +207 -207
  144. package/src/_pkgs/affine-block-embed/common/insert-embed-card.ts +94 -94
  145. package/src/_pkgs/affine-block-embed/common/render-linked-doc.ts +205 -205
  146. package/src/_pkgs/affine-block-embed/common/to-edgeless-embed-block.ts +78 -78
  147. package/src/_pkgs/affine-block-embed/common/utils.ts +49 -49
  148. package/src/_pkgs/affine-block-embed/configs/toolbar.ts +686 -686
  149. package/src/_pkgs/affine-block-embed/embed-figma-block/adapters/extension.ts +13 -13
  150. package/src/_pkgs/affine-block-embed/embed-figma-block/adapters/html.ts +11 -11
  151. package/src/_pkgs/affine-block-embed/embed-figma-block/adapters/markdown.ts +11 -11
  152. package/src/_pkgs/affine-block-embed/embed-figma-block/adapters/notion-html.ts +14 -14
  153. package/src/_pkgs/affine-block-embed/embed-figma-block/adapters/plain-text.ts +10 -10
  154. package/src/_pkgs/affine-block-embed/embed-figma-block/configs/slash-menu.ts +47 -47
  155. package/src/_pkgs/affine-block-embed/embed-figma-block/edgeless-clipboard-config.ts +25 -25
  156. package/src/_pkgs/affine-block-embed/embed-figma-block/embed-edgeless-figma-block.ts +13 -13
  157. package/src/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.ts +126 -126
  158. package/src/_pkgs/affine-block-embed/embed-figma-block/embed-figma-service.ts +14 -14
  159. package/src/_pkgs/affine-block-embed/embed-figma-block/embed-figma-spec.ts +26 -26
  160. package/src/_pkgs/affine-block-embed/embed-figma-block/styles.ts +218 -218
  161. package/src/_pkgs/affine-block-embed/embed-github-block/adapters/extension.ts +13 -13
  162. package/src/_pkgs/affine-block-embed/embed-github-block/adapters/html.ts +11 -11
  163. package/src/_pkgs/affine-block-embed/embed-github-block/adapters/markdown.ts +10 -10
  164. package/src/_pkgs/affine-block-embed/embed-github-block/adapters/notion-html.ts +14 -14
  165. package/src/_pkgs/affine-block-embed/embed-github-block/adapters/plain-text.ts +10 -10
  166. package/src/_pkgs/affine-block-embed/embed-github-block/configs/slash-menu.ts +47 -47
  167. package/src/_pkgs/affine-block-embed/embed-github-block/edgeless-clipboard-config.ts +51 -51
  168. package/src/_pkgs/affine-block-embed/embed-github-block/embed-edgeless-github-block.ts +13 -13
  169. package/src/_pkgs/affine-block-embed/embed-github-block/embed-github-block.ts +271 -271
  170. package/src/_pkgs/affine-block-embed/embed-github-block/embed-github-service.ts +36 -36
  171. package/src/_pkgs/affine-block-embed/embed-github-block/embed-github-spec.ts +30 -30
  172. package/src/_pkgs/affine-block-embed/embed-github-block/utils.ts +182 -182
  173. package/src/_pkgs/affine-block-embed/embed-html-block/components/fullscreen-toolbar.ts +171 -171
  174. package/src/_pkgs/affine-block-embed/embed-html-block/configs/toolbar.ts +193 -193
  175. package/src/_pkgs/affine-block-embed/embed-html-block/edgeless-clipboard-config.ts +24 -24
  176. package/src/_pkgs/affine-block-embed/embed-html-block/embed-edgeless-html-block.ts +19 -19
  177. package/src/_pkgs/affine-block-embed/embed-html-block/embed-html-block.ts +114 -114
  178. package/src/_pkgs/affine-block-embed/embed-html-block/embed-html-spec.ts +19 -19
  179. package/src/_pkgs/affine-block-embed/embed-iframe-block/adapters/html.ts +55 -55
  180. package/src/_pkgs/affine-block-embed/embed-iframe-block/adapters/index.ts +15 -15
  181. package/src/_pkgs/affine-block-embed/embed-iframe-block/adapters/markdown.ts +46 -46
  182. package/src/_pkgs/affine-block-embed/embed-iframe-block/adapters/plain-text.ts +31 -31
  183. package/src/_pkgs/affine-block-embed/embed-iframe-block/commands/insert-embed-iframe-with-url.ts +107 -107
  184. package/src/_pkgs/affine-block-embed/embed-iframe-block/commands/insert-empty-embed-iframe.ts +55 -55
  185. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.ts +343 -343
  186. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-idle-card.ts +132 -132
  187. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-link-edit-popup.ts +122 -122
  188. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-link-input-base.ts +160 -160
  189. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-link-input-popup.ts +292 -292
  190. package/src/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-loading-card.ts +193 -193
  191. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/excalidraw.ts +42 -42
  192. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/generic.ts +75 -75
  193. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/google-docs.ts +81 -81
  194. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/google-drive.ts +197 -197
  195. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/miro.ts +46 -46
  196. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/providers/spotify.ts +47 -47
  197. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/slash-menu/slash-menu.ts +37 -37
  198. package/src/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.ts +492 -492
  199. package/src/_pkgs/affine-block-embed/embed-iframe-block/edgeless-clipboard-config.ts +37 -37
  200. package/src/_pkgs/affine-block-embed/embed-iframe-block/embed-edgeless-iframe-block.ts +119 -119
  201. package/src/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.ts +470 -470
  202. package/src/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-spec.ts +23 -23
  203. package/src/_pkgs/affine-block-embed/embed-iframe-block/utils.ts +75 -75
  204. package/src/_pkgs/affine-block-embed/embed-loom-block/adapters/extension.ts +13 -13
  205. package/src/_pkgs/affine-block-embed/embed-loom-block/adapters/html.ts +11 -11
  206. package/src/_pkgs/affine-block-embed/embed-loom-block/adapters/markdown.ts +11 -11
  207. package/src/_pkgs/affine-block-embed/embed-loom-block/adapters/notion-html.ts +14 -14
  208. package/src/_pkgs/affine-block-embed/embed-loom-block/adapters/plain-text.ts +10 -10
  209. package/src/_pkgs/affine-block-embed/embed-loom-block/configs/slash-menu.ts +47 -47
  210. package/src/_pkgs/affine-block-embed/embed-loom-block/edgeless-clipboard-config.ts +28 -28
  211. package/src/_pkgs/affine-block-embed/embed-loom-block/embed-edgeless-loom-bock.ts +13 -13
  212. package/src/_pkgs/affine-block-embed/embed-loom-block/embed-loom-block.ts +171 -171
  213. package/src/_pkgs/affine-block-embed/embed-loom-block/embed-loom-service.ts +25 -25
  214. package/src/_pkgs/affine-block-embed/embed-loom-block/embed-loom-spec.ts +30 -30
  215. package/src/_pkgs/affine-block-embed/embed-loom-block/utils.ts +75 -75
  216. package/src/_pkgs/affine-block-embed/embed-youtube-block/adapters/extension.ts +13 -13
  217. package/src/_pkgs/affine-block-embed/embed-youtube-block/adapters/html.ts +51 -51
  218. package/src/_pkgs/affine-block-embed/embed-youtube-block/adapters/markdown.ts +10 -10
  219. package/src/_pkgs/affine-block-embed/embed-youtube-block/adapters/notion-html.ts +14 -14
  220. package/src/_pkgs/affine-block-embed/embed-youtube-block/adapters/plain-text.ts +12 -12
  221. package/src/_pkgs/affine-block-embed/embed-youtube-block/configs/slash-menu.ts +47 -47
  222. package/src/_pkgs/affine-block-embed/embed-youtube-block/edgeless-clipboard-config.ts +42 -42
  223. package/src/_pkgs/affine-block-embed/embed-youtube-block/embed-edgeless-youtube-block.ts +13 -13
  224. package/src/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.ts +225 -225
  225. package/src/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-service.ts +35 -35
  226. package/src/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-spec.ts +30 -30
  227. package/src/_pkgs/affine-block-embed/embed-youtube-block/styles.ts +241 -241
  228. package/src/_pkgs/affine-block-embed/embed-youtube-block/utils.ts +114 -114
  229. package/src/_pkgs/affine-block-embed/store.ts +48 -48
  230. package/src/_pkgs/affine-block-embed/types.ts +23 -23
  231. package/src/_pkgs/affine-block-embed/view.ts +72 -72
  232. package/src/_pkgs/affine-block-embed-doc/common/render-linked-doc.ts +213 -213
  233. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/adapters/extension.ts +11 -11
  234. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/adapters/html.ts +63 -63
  235. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/adapters/markdown.ts +122 -122
  236. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/adapters/plain-text.ts +33 -33
  237. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/commands/insert-embed-linked-doc.ts +34 -34
  238. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/slash-menu.ts +84 -84
  239. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.ts +513 -513
  240. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/edgeless-clipboard-config.ts +31 -31
  241. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-edgeless-linked-doc-block.ts +71 -71
  242. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.ts +628 -628
  243. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-spec.ts +21 -21
  244. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/styles.ts +2232 -2232
  245. package/src/_pkgs/affine-block-embed-doc/embed-linked-doc-block/utils.ts +102 -102
  246. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/adapters/extension.ts +11 -11
  247. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/adapters/html.ts +88 -88
  248. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/adapters/markdown.ts +64 -64
  249. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/adapters/plain-text.ts +62 -62
  250. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/commands/insert-embed-synced-doc.ts +20 -20
  251. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/components/embed-synced-doc-card.ts +262 -262
  252. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/edgeless-interaction.ts +87 -87
  253. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/index.ts +18 -18
  254. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.ts +500 -500
  255. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/edgeless-clipboard-config.ts +27 -27
  256. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts +196 -196
  257. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.ts +627 -627
  258. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-spec.ts +20 -20
  259. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/index.ts +8 -8
  260. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/init-height-extension.ts +65 -65
  261. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/styles.ts +1122 -1122
  262. package/src/_pkgs/affine-block-embed-doc/embed-synced-doc-block/utils.ts +74 -74
  263. package/src/_pkgs/affine-block-embed-doc/store.ts +25 -25
  264. package/src/_pkgs/affine-block-embed-doc/view.ts +40 -40
  265. package/src/_pkgs/affine-block-frame/edgeless-clipboard-config.ts +43 -43
  266. package/src/_pkgs/affine-block-frame/edgeless-toolbar/frame-dense-menu.ts +34 -34
  267. package/src/_pkgs/affine-block-frame/edgeless-toolbar/frame-menu.ts +104 -104
  268. package/src/_pkgs/affine-block-frame/edgeless-toolbar/frame-tool-button.ts +49 -49
  269. package/src/_pkgs/affine-block-frame/edgeless-toolbar/presentation-toolbar.ts +560 -560
  270. package/src/_pkgs/affine-block-frame/edgeless-toolbar/quick-tool.ts +16 -16
  271. package/src/_pkgs/affine-block-frame/frame-block.ts +208 -208
  272. package/src/_pkgs/affine-block-frame/frame-highlight-manager.ts +96 -96
  273. package/src/_pkgs/affine-block-frame/frame-manager.ts +503 -503
  274. package/src/_pkgs/affine-block-frame/frame-spec.ts +16 -16
  275. package/src/_pkgs/affine-block-frame/frame-tool.ts +108 -108
  276. package/src/_pkgs/affine-block-frame/frame-toolbar.ts +218 -218
  277. package/src/_pkgs/affine-block-frame/present/frame-order-button.ts +82 -82
  278. package/src/_pkgs/affine-block-frame/present/frame-order-menu.ts +265 -265
  279. package/src/_pkgs/affine-block-frame/present/navigator-bg-widget.ts +126 -126
  280. package/src/_pkgs/affine-block-frame/present/navigator-setting-button.ts +195 -195
  281. package/src/_pkgs/affine-block-frame/present/present-button.ts +40 -40
  282. package/src/_pkgs/affine-block-frame/present-tool.ts +12 -12
  283. package/src/_pkgs/affine-block-frame/store.ts +14 -14
  284. package/src/_pkgs/affine-block-frame/view.ts +39 -39
  285. package/src/_pkgs/affine-block-image/adapters/extension.ts +11 -11
  286. package/src/_pkgs/affine-block-image/adapters/html.ts +90 -90
  287. package/src/_pkgs/affine-block-image/adapters/markdown.ts +66 -66
  288. package/src/_pkgs/affine-block-image/adapters/notion-html.ts +82 -82
  289. package/src/_pkgs/affine-block-image/adapters/utils.ts +89 -89
  290. package/src/_pkgs/affine-block-image/commands/insert-images.ts +40 -40
  291. package/src/_pkgs/affine-block-image/components/image-block-fallback.ts +126 -126
  292. package/src/_pkgs/affine-block-image/components/page-image-block.ts +422 -422
  293. package/src/_pkgs/affine-block-image/configs/slash-menu.ts +32 -32
  294. package/src/_pkgs/affine-block-image/configs/toolbar.ts +174 -174
  295. package/src/_pkgs/affine-block-image/edgeless-clipboard-config.ts +30 -30
  296. package/src/_pkgs/affine-block-image/image-block.ts +194 -194
  297. package/src/_pkgs/affine-block-image/image-edgeless-block.ts +205 -205
  298. package/src/_pkgs/affine-block-image/image-resize-manager.ts +105 -105
  299. package/src/_pkgs/affine-block-image/image-service.ts +46 -46
  300. package/src/_pkgs/affine-block-image/image-spec.ts +29 -29
  301. package/src/_pkgs/affine-block-image/index.ts +11 -11
  302. package/src/_pkgs/affine-block-image/preview-image/edgeless.ts +25 -25
  303. package/src/_pkgs/affine-block-image/preview-image/page.ts +58 -58
  304. package/src/_pkgs/affine-block-image/store.ts +18 -18
  305. package/src/_pkgs/affine-block-image/turbo/image-layout-handler.ts +71 -71
  306. package/src/_pkgs/affine-block-image/turbo/image-painter.worker.ts +56 -56
  307. package/src/_pkgs/affine-block-image/utils.ts +433 -433
  308. package/src/_pkgs/affine-block-image/view.ts +27 -27
  309. package/src/_pkgs/affine-block-latex/adapters/extension.ts +11 -11
  310. package/src/_pkgs/affine-block-latex/adapters/markdown/index.ts +12 -12
  311. package/src/_pkgs/affine-block-latex/adapters/markdown/markdown.ts +55 -55
  312. package/src/_pkgs/affine-block-latex/adapters/markdown/preprocessor.ts +88 -88
  313. package/src/_pkgs/affine-block-latex/adapters/notion-html.ts +50 -50
  314. package/src/_pkgs/affine-block-latex/adapters/plain-text.ts +29 -29
  315. package/src/_pkgs/affine-block-latex/commands.ts +75 -75
  316. package/src/_pkgs/affine-block-latex/configs/slash-menu.ts +62 -62
  317. package/src/_pkgs/affine-block-latex/configs/tooltips.ts +41 -41
  318. package/src/_pkgs/affine-block-latex/latex-block.ts +158 -158
  319. package/src/_pkgs/affine-block-latex/store.ts +19 -19
  320. package/src/_pkgs/affine-block-latex/styles.ts +40 -40
  321. package/src/_pkgs/affine-block-latex/view.ts +27 -27
  322. package/src/_pkgs/affine-block-list/adapters/extension.ts +13 -13
  323. package/src/_pkgs/affine-block-list/adapters/html.ts +203 -203
  324. package/src/_pkgs/affine-block-list/adapters/markdown.ts +156 -156
  325. package/src/_pkgs/affine-block-list/adapters/notion-html.ts +116 -116
  326. package/src/_pkgs/affine-block-list/adapters/plain-text.ts +27 -27
  327. package/src/_pkgs/affine-block-list/commands/convert-to-numbered-list.ts +28 -28
  328. package/src/_pkgs/affine-block-list/commands/dedent-list.ts +165 -165
  329. package/src/_pkgs/affine-block-list/commands/indent-list.ts +147 -147
  330. package/src/_pkgs/affine-block-list/commands/list-to-paragraph.ts +44 -44
  331. package/src/_pkgs/affine-block-list/commands/split-list.ts +250 -250
  332. package/src/_pkgs/affine-block-list/commands/utils.ts +70 -70
  333. package/src/_pkgs/affine-block-list/list-block.ts +216 -216
  334. package/src/_pkgs/affine-block-list/list-keymap.ts +136 -136
  335. package/src/_pkgs/affine-block-list/markdown.ts +91 -91
  336. package/src/_pkgs/affine-block-list/store.ts +17 -17
  337. package/src/_pkgs/affine-block-list/turbo/list-layout-handler.ts +151 -151
  338. package/src/_pkgs/affine-block-list/turbo/list-painter.worker.ts +119 -119
  339. package/src/_pkgs/affine-block-list/utils/forward-delete.ts +75 -75
  340. package/src/_pkgs/affine-block-list/utils/get-list-icon.ts +78 -78
  341. package/src/_pkgs/affine-block-list/view.ts +30 -30
  342. package/src/_pkgs/affine-block-note/adapters/html.ts +44 -44
  343. package/src/_pkgs/affine-block-note/adapters/index.ts +30 -30
  344. package/src/_pkgs/affine-block-note/adapters/markdown.ts +131 -131
  345. package/src/_pkgs/affine-block-note/adapters/plain-text.ts +41 -41
  346. package/src/_pkgs/affine-block-note/commands/block-type.ts +247 -247
  347. package/src/_pkgs/affine-block-note/commands/change-note-display-mode.ts +60 -60
  348. package/src/_pkgs/affine-block-note/commands/dedent-block-to-root.ts +38 -38
  349. package/src/_pkgs/affine-block-note/commands/dedent-block.ts +67 -67
  350. package/src/_pkgs/affine-block-note/commands/dedent-blocks-to-root.ts +43 -43
  351. package/src/_pkgs/affine-block-note/commands/dedent-blocks.ts +87 -87
  352. package/src/_pkgs/affine-block-note/commands/indent-block.ts +74 -74
  353. package/src/_pkgs/affine-block-note/commands/indent-blocks.ts +125 -125
  354. package/src/_pkgs/affine-block-note/commands/select-block.ts +22 -22
  355. package/src/_pkgs/affine-block-note/commands/select-blocks-between.ts +53 -53
  356. package/src/_pkgs/affine-block-note/components/edgeless-note-background.ts +182 -182
  357. package/src/_pkgs/affine-block-note/components/edgeless-note-border-dropdown-menu.ts +42 -42
  358. package/src/_pkgs/affine-block-note/components/edgeless-note-display-mode-dropdown-menu.ts +58 -58
  359. package/src/_pkgs/affine-block-note/components/edgeless-note-mask.ts +84 -84
  360. package/src/_pkgs/affine-block-note/components/edgeless-note-shadow-menu.ts +206 -206
  361. package/src/_pkgs/affine-block-note/components/edgeless-note-style-panel.ts +434 -434
  362. package/src/_pkgs/affine-block-note/components/edgeless-page-block-title.ts +46 -46
  363. package/src/_pkgs/affine-block-note/config.ts +20 -20
  364. package/src/_pkgs/affine-block-note/configs/slash-menu.ts +125 -125
  365. package/src/_pkgs/affine-block-note/configs/toolbar.ts +350 -350
  366. package/src/_pkgs/affine-block-note/configs/tooltips.ts +330 -330
  367. package/src/_pkgs/affine-block-note/edgeless-clipboard-config.ts +28 -28
  368. package/src/_pkgs/affine-block-note/move-block.ts +129 -129
  369. package/src/_pkgs/affine-block-note/note-block.ts +34 -34
  370. package/src/_pkgs/affine-block-note/note-edgeless-block.css.ts +74 -74
  371. package/src/_pkgs/affine-block-note/note-edgeless-block.ts +499 -499
  372. package/src/_pkgs/affine-block-note/note-keymap.ts +611 -611
  373. package/src/_pkgs/affine-block-note/quick-action.ts +66 -66
  374. package/src/_pkgs/affine-block-note/store.ts +36 -36
  375. package/src/_pkgs/affine-block-note/turbo/note-layout-handler.ts +83 -83
  376. package/src/_pkgs/affine-block-note/turbo/note-painter.worker.ts +49 -49
  377. package/src/_pkgs/affine-block-note/view.ts +47 -47
  378. package/src/_pkgs/affine-block-paragraph/adapters/extension.ts +13 -13
  379. package/src/_pkgs/affine-block-paragraph/adapters/html.ts +359 -359
  380. package/src/_pkgs/affine-block-paragraph/adapters/markdown.ts +200 -200
  381. package/src/_pkgs/affine-block-paragraph/adapters/notion-html.ts +239 -239
  382. package/src/_pkgs/affine-block-paragraph/adapters/plain-text.ts +28 -28
  383. package/src/_pkgs/affine-block-paragraph/commands/add-paragraph.ts +56 -56
  384. package/src/_pkgs/affine-block-paragraph/commands/append-paragraph.ts +30 -30
  385. package/src/_pkgs/affine-block-paragraph/commands/dedent-paragraph.ts +114 -114
  386. package/src/_pkgs/affine-block-paragraph/commands/indent-paragraph.ts +156 -156
  387. package/src/_pkgs/affine-block-paragraph/commands/split-paragraph.ts +81 -81
  388. package/src/_pkgs/affine-block-paragraph/heading-icon.ts +92 -92
  389. package/src/_pkgs/affine-block-paragraph/markdown.ts +74 -74
  390. package/src/_pkgs/affine-block-paragraph/paragraph-block-config.ts +9 -9
  391. package/src/_pkgs/affine-block-paragraph/paragraph-block.ts +369 -369
  392. package/src/_pkgs/affine-block-paragraph/paragraph-keymap.ts +230 -230
  393. package/src/_pkgs/affine-block-paragraph/store.ts +17 -17
  394. package/src/_pkgs/affine-block-paragraph/styles.ts +158 -158
  395. package/src/_pkgs/affine-block-paragraph/turbo/paragraph-layout-handler.ts +106 -106
  396. package/src/_pkgs/affine-block-paragraph/turbo/paragraph-painter.worker.ts +115 -115
  397. package/src/_pkgs/affine-block-paragraph/utils/forward-delete.ts +94 -94
  398. package/src/_pkgs/affine-block-paragraph/utils/merge-with-prev.ts +184 -184
  399. package/src/_pkgs/affine-block-paragraph/view.ts +66 -66
  400. package/src/_pkgs/affine-block-root/adapters/extension.ts +11 -11
  401. package/src/_pkgs/affine-block-root/adapters/html.ts +135 -135
  402. package/src/_pkgs/affine-block-root/adapters/markdown.ts +36 -36
  403. package/src/_pkgs/affine-block-root/adapters/notion-html.ts +28 -28
  404. package/src/_pkgs/affine-block-root/clipboard/page-clipboard.ts +176 -176
  405. package/src/_pkgs/affine-block-root/clipboard/readonly-clipboard.ts +71 -71
  406. package/src/_pkgs/affine-block-root/configs/toolbar.ts +398 -398
  407. package/src/_pkgs/affine-block-root/edgeless/clipboard/canvas.ts +117 -117
  408. package/src/_pkgs/affine-block-root/edgeless/clipboard/clipboard.ts +715 -715
  409. package/src/_pkgs/affine-block-root/edgeless/clipboard/command.ts +218 -218
  410. package/src/_pkgs/affine-block-root/edgeless/clipboard/utils.ts +140 -140
  411. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/alignment.ts +293 -293
  412. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/index.ts +19 -19
  413. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/misc.ts +369 -369
  414. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/more.ts +435 -435
  415. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/render-linked-doc.ts +103 -96
  416. package/src/_pkgs/affine-block-root/edgeless/configs/toolbar/utils.ts +17 -17
  417. package/src/_pkgs/affine-block-root/edgeless/edgeless-keyboard.ts +753 -753
  418. package/src/_pkgs/affine-block-root/edgeless/edgeless-root-block.ts +524 -524
  419. package/src/_pkgs/affine-block-root/edgeless/edgeless-root-service.ts +231 -231
  420. package/src/_pkgs/affine-block-root/edgeless/edgeless-root-spec.ts +11 -11
  421. package/src/_pkgs/affine-block-root/edgeless/index.ts +9 -9
  422. package/src/_pkgs/affine-block-root/edgeless/interact-extensions/clone-ext.ts +32 -32
  423. package/src/_pkgs/affine-block-root/edgeless/utils/clipboard-utils.ts +97 -97
  424. package/src/_pkgs/affine-block-root/edgeless/utils/clone-utils.ts +237 -237
  425. package/src/_pkgs/affine-block-root/edgeless/utils/connector.ts +34 -34
  426. package/src/_pkgs/affine-block-root/edgeless/utils/crud.ts +37 -37
  427. package/src/_pkgs/affine-block-root/edgeless/utils/query.ts +104 -104
  428. package/src/_pkgs/affine-block-root/keyboard/keyboard-manager.ts +163 -163
  429. package/src/_pkgs/affine-block-root/keyboard/keymap.ts +16 -16
  430. package/src/_pkgs/affine-block-root/page/page-root-block.ts +422 -422
  431. package/src/_pkgs/affine-block-root/preview/edgeless-root-preview-block.ts +262 -262
  432. package/src/_pkgs/affine-block-root/preview/preview-root-block.ts +41 -41
  433. package/src/_pkgs/affine-block-root/store.ts +17 -17
  434. package/src/_pkgs/affine-block-root/view.ts +93 -93
  435. package/src/_pkgs/affine-block-surface/adapters/html-adapter/html.ts +20 -20
  436. package/src/_pkgs/affine-block-surface/adapters/markdown/element-adapter/index.ts +33 -33
  437. package/src/_pkgs/affine-block-surface/adapters/markdown/element-adapter/type.ts +29 -29
  438. package/src/_pkgs/affine-block-surface/adapters/markdown/markdown.ts +76 -76
  439. package/src/_pkgs/affine-block-surface/adapters/plain-text/element-adapter/index.ts +32 -32
  440. package/src/_pkgs/affine-block-surface/adapters/plain-text/element-adapter/type.ts +29 -29
  441. package/src/_pkgs/affine-block-surface/adapters/plain-text/plain-text.ts +77 -77
  442. package/src/_pkgs/affine-block-surface/adapters/type.ts +30 -30
  443. package/src/_pkgs/affine-block-surface/commands/auto-align.ts +157 -157
  444. package/src/_pkgs/affine-block-surface/commands/reassociate-connectors.ts +46 -46
  445. package/src/_pkgs/affine-block-surface/element-model/base.ts +4 -4
  446. package/src/_pkgs/affine-block-surface/element-model/index.ts +96 -96
  447. package/src/_pkgs/affine-block-surface/extensions/clipboard-config.ts +80 -80
  448. package/src/_pkgs/affine-block-surface/extensions/crud-extension.ts +181 -181
  449. package/src/_pkgs/affine-block-surface/extensions/dom-element-renderer.ts +30 -30
  450. package/src/_pkgs/affine-block-surface/extensions/edit-props-middleware-builder.ts +26 -26
  451. package/src/_pkgs/affine-block-surface/extensions/element-renderer.ts +31 -31
  452. package/src/_pkgs/affine-block-surface/extensions/export-manager/export-manager.ts +559 -559
  453. package/src/_pkgs/affine-block-surface/extensions/legacy-slot-extension.ts +39 -39
  454. package/src/_pkgs/affine-block-surface/extensions/query.ts +15 -15
  455. package/src/_pkgs/affine-block-surface/extensions/surface-middleware.ts +23 -23
  456. package/src/_pkgs/affine-block-surface/renderer/canvas-renderer.ts +472 -472
  457. package/src/_pkgs/affine-block-surface/renderer/dom-elements/index.ts +31 -31
  458. package/src/_pkgs/affine-block-surface/renderer/dom-renderer.ts +710 -710
  459. package/src/_pkgs/affine-block-surface/renderer/elements/index.ts +23 -23
  460. package/src/_pkgs/affine-block-surface/renderer/elements/type.ts +6 -6
  461. package/src/_pkgs/affine-block-surface/renderer/overlay.ts +57 -57
  462. package/src/_pkgs/affine-block-surface/renderer/tool-overlay.ts +44 -44
  463. package/src/_pkgs/affine-block-surface/store.ts +17 -17
  464. package/src/_pkgs/affine-block-surface/surface-block-void.ts +16 -16
  465. package/src/_pkgs/affine-block-surface/surface-block.ts +255 -255
  466. package/src/_pkgs/affine-block-surface/surface-model.ts +69 -69
  467. package/src/_pkgs/affine-block-surface/surface-transformer.ts +115 -115
  468. package/src/_pkgs/affine-block-surface/tool/default-tool.ts +374 -374
  469. package/src/_pkgs/affine-block-surface/tool/panning-utils.ts +46 -46
  470. package/src/_pkgs/affine-block-surface/utils/a-star.ts +299 -299
  471. package/src/_pkgs/affine-block-surface/utils/font.ts +47 -47
  472. package/src/_pkgs/affine-block-surface/utils/get-bg-grip-gap.ts +10 -10
  473. package/src/_pkgs/affine-block-surface/utils/get-last-props-key.ts +29 -29
  474. package/src/_pkgs/affine-block-surface/utils/get-surface-block.ts +16 -16
  475. package/src/_pkgs/affine-block-surface/utils/graph.ts +151 -151
  476. package/src/_pkgs/affine-block-surface/utils/update-xywh.ts +82 -82
  477. package/src/_pkgs/affine-block-surface/view.ts +45 -45
  478. package/src/_pkgs/affine-block-surface-ref/commands.ts +60 -60
  479. package/src/_pkgs/affine-block-surface-ref/components/placeholder.ts +131 -131
  480. package/src/_pkgs/affine-block-surface-ref/components/surface-ref-toolbar-title.ts +76 -76
  481. package/src/_pkgs/affine-block-surface-ref/configs/slash-menu.ts +164 -164
  482. package/src/_pkgs/affine-block-surface-ref/configs/toolbar.ts +100 -100
  483. package/src/_pkgs/affine-block-surface-ref/portal/generic-block.ts +82 -82
  484. package/src/_pkgs/affine-block-surface-ref/portal/note.ts +169 -169
  485. package/src/_pkgs/affine-block-surface-ref/store.ts +14 -14
  486. package/src/_pkgs/affine-block-surface-ref/surface-ref-block-edgeless.ts +80 -80
  487. package/src/_pkgs/affine-block-surface-ref/surface-ref-block.ts +511 -511
  488. package/src/_pkgs/affine-block-surface-ref/utils.ts +152 -152
  489. package/src/_pkgs/affine-block-surface-ref/view.ts +49 -49
  490. package/src/_pkgs/affine-block-table/adapters/extension.ts +13 -13
  491. package/src/_pkgs/affine-block-table/adapters/html.ts +129 -129
  492. package/src/_pkgs/affine-block-table/adapters/markdown.ts +82 -82
  493. package/src/_pkgs/affine-block-table/adapters/notion-html.ts +21 -21
  494. package/src/_pkgs/affine-block-table/adapters/plain-text.ts +79 -79
  495. package/src/_pkgs/affine-block-table/adapters/utils.ts +212 -212
  496. package/src/_pkgs/affine-block-table/add-button-css.ts +99 -99
  497. package/src/_pkgs/affine-block-table/add-button.ts +330 -330
  498. package/src/_pkgs/affine-block-table/color.ts +45 -45
  499. package/src/_pkgs/affine-block-table/commands.ts +52 -52
  500. package/src/_pkgs/affine-block-table/configs/slash-menu.ts +44 -44
  501. package/src/_pkgs/affine-block-table/selection-controller.ts +527 -527
  502. package/src/_pkgs/affine-block-table/selection-layer.ts +112 -112
  503. package/src/_pkgs/affine-block-table/selection-schema.ts +112 -112
  504. package/src/_pkgs/affine-block-table/store.ts +19 -19
  505. package/src/_pkgs/affine-block-table/table-block.ts +209 -209
  506. package/src/_pkgs/affine-block-table/table-cell-css.ts +154 -154
  507. package/src/_pkgs/affine-block-table/table-cell.ts +866 -866
  508. package/src/_pkgs/affine-block-table/table-data-manager.ts +382 -382
  509. package/src/_pkgs/affine-block-table/view.ts +29 -29
  510. package/src/_pkgs/affine-components/block-selection/index.ts +69 -69
  511. package/src/_pkgs/affine-components/block-zero-width/index.ts +59 -59
  512. package/src/_pkgs/affine-components/caption/block-caption.ts +188 -188
  513. package/src/_pkgs/affine-components/caption/captioned-block-component.ts +82 -82
  514. package/src/_pkgs/affine-components/card-style-dropdown-menu/dropdown-menu.ts +118 -118
  515. package/src/_pkgs/affine-components/citation/citation.ts +167 -167
  516. package/src/_pkgs/affine-components/color-picker/button.ts +207 -207
  517. package/src/_pkgs/affine-components/color-picker/color-panel.ts +260 -260
  518. package/src/_pkgs/affine-components/color-picker/color-picker.ts +677 -677
  519. package/src/_pkgs/affine-components/color-picker/icons.ts +71 -71
  520. package/src/_pkgs/affine-components/color-picker/styles.ts +308 -308
  521. package/src/_pkgs/affine-components/color-picker/types.ts +53 -53
  522. package/src/_pkgs/affine-components/color-picker/utils.ts +368 -368
  523. package/src/_pkgs/affine-components/context-menu/button.ts +302 -302
  524. package/src/_pkgs/affine-components/context-menu/group.ts +35 -35
  525. package/src/_pkgs/affine-components/context-menu/input.ts +254 -254
  526. package/src/_pkgs/affine-components/context-menu/item.ts +12 -12
  527. package/src/_pkgs/affine-components/context-menu/menu-renderer.ts +574 -574
  528. package/src/_pkgs/affine-components/context-menu/menu.ts +170 -170
  529. package/src/_pkgs/affine-components/context-menu/sub-menu.ts +194 -194
  530. package/src/_pkgs/affine-components/date-picker/date-picker.ts +626 -626
  531. package/src/_pkgs/affine-components/drop-indicator/drop-indicator.ts +51 -51
  532. package/src/_pkgs/affine-components/drop-indicator/file-drop-manager.ts +300 -300
  533. package/src/_pkgs/affine-components/edgeless-line-styles-panel/line-styles-panel.ts +113 -113
  534. package/src/_pkgs/affine-components/edgeless-line-width-panel/line-width-panel.ts +50 -50
  535. package/src/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.ts +318 -318
  536. package/src/_pkgs/affine-components/embed-card-modal/embed-card-create-modal.ts +218 -218
  537. package/src/_pkgs/affine-components/embed-card-modal/embed-card-edit-modal.ts +468 -468
  538. package/src/_pkgs/affine-components/embed-card-modal/styles.ts +131 -131
  539. package/src/_pkgs/affine-components/filterable-list/index.ts +259 -259
  540. package/src/_pkgs/affine-components/filterable-list/styles.ts +109 -109
  541. package/src/_pkgs/affine-components/highlight-dropdown-menu/dropdown-menu.ts +123 -123
  542. package/src/_pkgs/affine-components/hover/controller.ts +201 -201
  543. package/src/_pkgs/affine-components/hover/middlewares/basic.ts +79 -79
  544. package/src/_pkgs/affine-components/link-preview/link.ts +65 -65
  545. package/src/_pkgs/affine-components/linked-doc-title/doc-title.ts +61 -61
  546. package/src/_pkgs/affine-components/notification/linked-doc.ts +45 -45
  547. package/src/_pkgs/affine-components/open-doc-dropdown-menu/dropdown-menu.ts +131 -131
  548. package/src/_pkgs/affine-components/peek/commands.ts +47 -47
  549. package/src/_pkgs/affine-components/peek/peekable.ts +137 -137
  550. package/src/_pkgs/affine-components/peek/service.ts +16 -16
  551. package/src/_pkgs/affine-components/peek/type.ts +70 -70
  552. package/src/_pkgs/affine-components/portal/helper.ts +225 -225
  553. package/src/_pkgs/affine-components/resource/resource.ts +230 -230
  554. package/src/_pkgs/affine-components/resource/status.ts +165 -165
  555. package/src/_pkgs/affine-components/size-dropdown-menu/dropdown-menu.ts +211 -211
  556. package/src/_pkgs/affine-components/slider/slider.ts +159 -159
  557. package/src/_pkgs/affine-components/slider/styles.ts +79 -79
  558. package/src/_pkgs/affine-components/smooth-corner/index.ts +184 -184
  559. package/src/_pkgs/affine-components/toast/create.ts +39 -39
  560. package/src/_pkgs/affine-components/toast/toast.ts +80 -80
  561. package/src/_pkgs/affine-components/toggle-button/toggle-button.ts +97 -97
  562. package/src/_pkgs/affine-components/toggle-switch/index.ts +88 -88
  563. package/src/_pkgs/affine-components/toolbar/config.ts +7 -7
  564. package/src/_pkgs/affine-components/toolbar/icon-button.ts +220 -220
  565. package/src/_pkgs/affine-components/toolbar/menu-button.ts +242 -242
  566. package/src/_pkgs/affine-components/toolbar/menu-context.ts +30 -30
  567. package/src/_pkgs/affine-components/toolbar/toolbar.ts +52 -52
  568. package/src/_pkgs/affine-components/toolbar/tooltip.ts +328 -328
  569. package/src/_pkgs/affine-components/toolbar/utils.ts +120 -120
  570. package/src/_pkgs/affine-components/view-dropdown-menu/dropdown-menu.ts +86 -86
  571. package/src/_pkgs/affine-ext-loader/base-provider.ts +69 -69
  572. package/src/_pkgs/affine-ext-loader/manager.ts +146 -146
  573. package/src/_pkgs/affine-ext-loader/store-manager.ts +47 -47
  574. package/src/_pkgs/affine-ext-loader/view-manager.ts +49 -49
  575. package/src/_pkgs/affine-foundation/clipboard.ts +65 -65
  576. package/src/_pkgs/affine-foundation/effects.ts +70 -70
  577. package/src/_pkgs/affine-foundation/store.ts +54 -54
  578. package/src/_pkgs/affine-foundation/view.ts +108 -108
  579. package/src/_pkgs/affine-fragment-adapter-panel/adapter-panel.ts +177 -177
  580. package/src/_pkgs/affine-fragment-adapter-panel/body/adapter-panel-body.ts +216 -216
  581. package/src/_pkgs/affine-fragment-adapter-panel/config.ts +28 -28
  582. package/src/_pkgs/affine-fragment-adapter-panel/header/adapter-menu.ts +86 -86
  583. package/src/_pkgs/affine-fragment-adapter-panel/header/adapter-panel-header.ts +119 -119
  584. package/src/_pkgs/affine-fragment-adapter-panel/view.ts +12 -12
  585. package/src/_pkgs/affine-fragment-doc-title/doc-title.ts +241 -241
  586. package/src/_pkgs/affine-fragment-doc-title/utils.ts +11 -11
  587. package/src/_pkgs/affine-fragment-doc-title/view.ts +12 -12
  588. package/src/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.ts +436 -436
  589. package/src/_pkgs/affine-fragment-frame-panel/card/frame-card-title-editor.ts +126 -126
  590. package/src/_pkgs/affine-fragment-frame-panel/card/frame-card-title.ts +151 -151
  591. package/src/_pkgs/affine-fragment-frame-panel/card/frame-card.ts +254 -254
  592. package/src/_pkgs/affine-fragment-frame-panel/card/frame-preview.ts +263 -263
  593. package/src/_pkgs/affine-fragment-frame-panel/frame-panel.ts +92 -92
  594. package/src/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.ts +248 -248
  595. package/src/_pkgs/affine-fragment-frame-panel/header/frames-setting-menu.ts +219 -219
  596. package/src/_pkgs/affine-fragment-frame-panel/utils/drag.ts +156 -156
  597. package/src/_pkgs/affine-fragment-frame-panel/view.ts +12 -12
  598. package/src/_pkgs/affine-fragment-outline/body/outline-notice.ts +94 -94
  599. package/src/_pkgs/affine-fragment-outline/body/outline-panel-body.ts +481 -481
  600. package/src/_pkgs/affine-fragment-outline/card/outline-card.ts +278 -278
  601. package/src/_pkgs/affine-fragment-outline/card/outline-preview.ts +228 -228
  602. package/src/_pkgs/affine-fragment-outline/config.ts +97 -97
  603. package/src/_pkgs/affine-fragment-outline/header/outline-panel-header.ts +90 -90
  604. package/src/_pkgs/affine-fragment-outline/header/outline-setting-menu.ts +47 -47
  605. package/src/_pkgs/affine-fragment-outline/mobile-outline-panel.ts +197 -197
  606. package/src/_pkgs/affine-fragment-outline/outline-panel.ts +118 -118
  607. package/src/_pkgs/affine-fragment-outline/outline-viewer.ts +325 -325
  608. package/src/_pkgs/affine-fragment-outline/utils/custom-events.ts +27 -27
  609. package/src/_pkgs/affine-fragment-outline/utils/query.ts +72 -72
  610. package/src/_pkgs/affine-fragment-outline/utils/scroll.ts +201 -201
  611. package/src/_pkgs/affine-fragment-outline/view.ts +12 -12
  612. package/src/_pkgs/affine-gfx-brush/adapter/markdown/index.ts +18 -18
  613. package/src/_pkgs/affine-gfx-brush/adapter/plain-text/index.ts +11 -11
  614. package/src/_pkgs/affine-gfx-brush/brush-tool.ts +200 -200
  615. package/src/_pkgs/affine-gfx-brush/element-renderer.ts +32 -32
  616. package/src/_pkgs/affine-gfx-brush/eraser-tool.ts +158 -158
  617. package/src/_pkgs/affine-gfx-brush/highlighter-tool.ts +179 -179
  618. package/src/_pkgs/affine-gfx-brush/store.ts +19 -19
  619. package/src/_pkgs/affine-gfx-brush/toolbar/components/eraser/eraser-tool-button.ts +75 -75
  620. package/src/_pkgs/affine-gfx-brush/toolbar/components/pen/pen-menu.ts +215 -215
  621. package/src/_pkgs/affine-gfx-brush/toolbar/components/pen/pen-tool-button.ts +195 -195
  622. package/src/_pkgs/affine-gfx-brush/toolbar/configs/brush.ts +120 -120
  623. package/src/_pkgs/affine-gfx-brush/toolbar/configs/highlighter.ts +139 -139
  624. package/src/_pkgs/affine-gfx-brush/toolbar/senior-tool.ts +15 -15
  625. package/src/_pkgs/affine-gfx-brush/view.ts +39 -39
  626. package/src/_pkgs/affine-gfx-connector/adapter/markdown/index.ts +26 -26
  627. package/src/_pkgs/affine-gfx-connector/adapter/plain-text/index.ts +14 -14
  628. package/src/_pkgs/affine-gfx-connector/adapter/text.ts +23 -23
  629. package/src/_pkgs/affine-gfx-connector/components/connector-handle.ts +263 -263
  630. package/src/_pkgs/affine-gfx-connector/connector-manager.ts +1858 -1858
  631. package/src/_pkgs/affine-gfx-connector/connector-tool.ts +279 -279
  632. package/src/_pkgs/affine-gfx-connector/connector-watcher.ts +190 -190
  633. package/src/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.ts +367 -367
  634. package/src/_pkgs/affine-gfx-connector/element-renderer/connector-dom.ts +11 -11
  635. package/src/_pkgs/affine-gfx-connector/element-renderer/index.ts +315 -315
  636. package/src/_pkgs/affine-gfx-connector/element-renderer/utils.ts +327 -327
  637. package/src/_pkgs/affine-gfx-connector/element-transform/connector-filter.ts +44 -44
  638. package/src/_pkgs/affine-gfx-connector/store.ts +21 -21
  639. package/src/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.ts +394 -394
  640. package/src/_pkgs/affine-gfx-connector/text/text.ts +66 -66
  641. package/src/_pkgs/affine-gfx-connector/toolbar/config.ts +436 -436
  642. package/src/_pkgs/affine-gfx-connector/toolbar/connector-dense-menu.ts +58 -58
  643. package/src/_pkgs/affine-gfx-connector/toolbar/connector-menu.ts +153 -153
  644. package/src/_pkgs/affine-gfx-connector/toolbar/connector-tool-button.ts +79 -79
  645. package/src/_pkgs/affine-gfx-connector/toolbar/quick-tool.ts +15 -15
  646. package/src/_pkgs/affine-gfx-connector/view/view.ts +256 -256
  647. package/src/_pkgs/affine-gfx-connector/view.ts +38 -38
  648. package/src/_pkgs/affine-gfx-group/adapter/markdown/index.ts +25 -25
  649. package/src/_pkgs/affine-gfx-group/adapter/plain-text/index.ts +14 -14
  650. package/src/_pkgs/affine-gfx-group/adapter/text.ts +21 -21
  651. package/src/_pkgs/affine-gfx-group/command/group-api.ts +134 -134
  652. package/src/_pkgs/affine-gfx-group/element-renderer/consts.ts +6 -6
  653. package/src/_pkgs/affine-gfx-group/element-renderer/index.ts +67 -67
  654. package/src/_pkgs/affine-gfx-group/element-renderer/utils.ts +77 -77
  655. package/src/_pkgs/affine-gfx-group/element-view.ts +57 -57
  656. package/src/_pkgs/affine-gfx-group/group-watcher.ts +36 -36
  657. package/src/_pkgs/affine-gfx-group/interaction-ext.ts +45 -45
  658. package/src/_pkgs/affine-gfx-group/store.ts +21 -21
  659. package/src/_pkgs/affine-gfx-group/text/edgeless-group-title-editor.ts +189 -189
  660. package/src/_pkgs/affine-gfx-group/text/text.ts +33 -33
  661. package/src/_pkgs/affine-gfx-group/toolbar/config.ts +106 -106
  662. package/src/_pkgs/affine-gfx-group/view.ts +30 -30
  663. package/src/_pkgs/affine-gfx-link/link-tool.ts +13 -13
  664. package/src/_pkgs/affine-gfx-link/toolbar/link-dense-menu.ts +32 -32
  665. package/src/_pkgs/affine-gfx-link/toolbar/link-tool-button.ts +96 -96
  666. package/src/_pkgs/affine-gfx-link/view.ts +23 -23
  667. package/src/_pkgs/affine-gfx-mindmap/adapter/markdown/index.ts +69 -69
  668. package/src/_pkgs/affine-gfx-mindmap/adapter/plain-text/index.ts +13 -13
  669. package/src/_pkgs/affine-gfx-mindmap/adapter/utils.ts +65 -65
  670. package/src/_pkgs/affine-gfx-mindmap/element-renderer.ts +81 -81
  671. package/src/_pkgs/affine-gfx-mindmap/indicator-overlay/index.ts +301 -301
  672. package/src/_pkgs/affine-gfx-mindmap/interactivity/drag-utils.ts +190 -190
  673. package/src/_pkgs/affine-gfx-mindmap/interactivity/mind-map-drag.ts +465 -465
  674. package/src/_pkgs/affine-gfx-mindmap/store.ts +19 -19
  675. package/src/_pkgs/affine-gfx-mindmap/toolbar/assets.ts +46 -46
  676. package/src/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.ts +206 -206
  677. package/src/_pkgs/affine-gfx-mindmap/toolbar/config.ts +199 -199
  678. package/src/_pkgs/affine-gfx-mindmap/toolbar/mindmap-importing-placeholder.ts +54 -54
  679. package/src/_pkgs/affine-gfx-mindmap/toolbar/mindmap-menu.ts +415 -415
  680. package/src/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.ts +466 -466
  681. package/src/_pkgs/affine-gfx-mindmap/toolbar/senior-tool.ts +15 -15
  682. package/src/_pkgs/affine-gfx-mindmap/toolbar/utils/import-mindmap.ts +143 -143
  683. package/src/_pkgs/affine-gfx-mindmap/utils/index.ts +70 -70
  684. package/src/_pkgs/affine-gfx-mindmap/view/layout.ts +201 -201
  685. package/src/_pkgs/affine-gfx-mindmap/view/utils.ts +692 -692
  686. package/src/_pkgs/affine-gfx-mindmap/view/view.ts +378 -378
  687. package/src/_pkgs/affine-gfx-mindmap/view.ts +36 -36
  688. package/src/_pkgs/affine-gfx-note/components/note-display-mode-panel.ts +104 -104
  689. package/src/_pkgs/affine-gfx-note/components/note-shadow-panel.ts +144 -144
  690. package/src/_pkgs/affine-gfx-note/note-tool.ts +330 -330
  691. package/src/_pkgs/affine-gfx-note/overlay/overlay.ts +161 -161
  692. package/src/_pkgs/affine-gfx-note/toolbar/note-menu-config.ts +151 -151
  693. package/src/_pkgs/affine-gfx-note/toolbar/note-menu.ts +210 -210
  694. package/src/_pkgs/affine-gfx-note/toolbar/note-senior-button.ts +218 -218
  695. package/src/_pkgs/affine-gfx-note/toolbar/note-tool-button.ts +120 -120
  696. package/src/_pkgs/affine-gfx-note/toolbar/senior-tool.ts +11 -11
  697. package/src/_pkgs/affine-gfx-note/view.ts +23 -23
  698. package/src/_pkgs/affine-gfx-pointer/quick-tool/default-tool-button.ts +105 -105
  699. package/src/_pkgs/affine-gfx-pointer/quick-tool/quick-tool.ts +12 -12
  700. package/src/_pkgs/affine-gfx-pointer/snap/snap-manager.ts +139 -139
  701. package/src/_pkgs/affine-gfx-pointer/snap/snap-overlay.ts +816 -816
  702. package/src/_pkgs/affine-gfx-pointer/tools/empty-tool.ts +8 -8
  703. package/src/_pkgs/affine-gfx-pointer/tools/pan-tool.ts +110 -110
  704. package/src/_pkgs/affine-gfx-pointer/view.ts +30 -30
  705. package/src/_pkgs/affine-gfx-shape/adapter/markdown/index.ts +46 -46
  706. package/src/_pkgs/affine-gfx-shape/adapter/plain-text/index.ts +35 -35
  707. package/src/_pkgs/affine-gfx-shape/adapter/utils.ts +36 -36
  708. package/src/_pkgs/affine-gfx-shape/components/shape-panel.ts +65 -65
  709. package/src/_pkgs/affine-gfx-shape/components/shape-style-panel.ts +59 -59
  710. package/src/_pkgs/affine-gfx-shape/consts.ts +19 -19
  711. package/src/_pkgs/affine-gfx-shape/draggable/shape-draggable.ts +367 -367
  712. package/src/_pkgs/affine-gfx-shape/draggable/shape-menu.ts +212 -212
  713. package/src/_pkgs/affine-gfx-shape/draggable/shape-tool-button.ts +99 -99
  714. package/src/_pkgs/affine-gfx-shape/draggable/shape-tool-element.ts +326 -326
  715. package/src/_pkgs/affine-gfx-shape/draggable/utils.ts +150 -150
  716. package/src/_pkgs/affine-gfx-shape/element-renderer/highlighter.ts +41 -41
  717. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/diamond.ts +66 -66
  718. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/ellipse.ts +59 -59
  719. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/index.ts +185 -185
  720. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/polygon.ts +134 -134
  721. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/rect.ts +98 -98
  722. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/triangle.ts +65 -65
  723. package/src/_pkgs/affine-gfx-shape/element-renderer/shape/utils.ts +362 -362
  724. package/src/_pkgs/affine-gfx-shape/element-renderer/shape-dom/index.ts +228 -228
  725. package/src/_pkgs/affine-gfx-shape/element-renderer/shape-dom/utils.ts +59 -59
  726. package/src/_pkgs/affine-gfx-shape/element-renderer/shape-dom.ts +11 -11
  727. package/src/_pkgs/affine-gfx-shape/element-view.ts +612 -612
  728. package/src/_pkgs/affine-gfx-shape/overlay/diamond.ts +23 -23
  729. package/src/_pkgs/affine-gfx-shape/overlay/ellipse.ts +15 -15
  730. package/src/_pkgs/affine-gfx-shape/overlay/factory.ts +37 -37
  731. package/src/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.ts +195 -195
  732. package/src/_pkgs/affine-gfx-shape/overlay/polygon-vertex-editing-overlay.ts +1213 -1213
  733. package/src/_pkgs/affine-gfx-shape/overlay/polygon.ts +28 -28
  734. package/src/_pkgs/affine-gfx-shape/overlay/rect.ts +15 -15
  735. package/src/_pkgs/affine-gfx-shape/overlay/rounded-rect.ts +32 -32
  736. package/src/_pkgs/affine-gfx-shape/overlay/shape-overlay.ts +110 -110
  737. package/src/_pkgs/affine-gfx-shape/overlay/shape.ts +27 -27
  738. package/src/_pkgs/affine-gfx-shape/overlay/triangle.ts +22 -22
  739. package/src/_pkgs/affine-gfx-shape/overlay/utils.ts +59 -59
  740. package/src/_pkgs/affine-gfx-shape/polygon-tool.ts +430 -430
  741. package/src/_pkgs/affine-gfx-shape/shape-tool.ts +368 -368
  742. package/src/_pkgs/affine-gfx-shape/store.ts +19 -19
  743. package/src/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.ts +411 -411
  744. package/src/_pkgs/affine-gfx-shape/toolbar/config.ts +361 -361
  745. package/src/_pkgs/affine-gfx-shape/toolbar/senior-tool.ts +15 -15
  746. package/src/_pkgs/affine-gfx-shape/toolbar/shape-menu-config.ts +81 -81
  747. package/src/_pkgs/affine-gfx-shape/view.ts +39 -39
  748. package/src/_pkgs/affine-gfx-template/services/template-middlewares.ts +344 -344
  749. package/src/_pkgs/affine-gfx-template/services/template.ts +432 -432
  750. package/src/_pkgs/affine-gfx-template/template-tool.ts +5 -5
  751. package/src/_pkgs/affine-gfx-template/toolbar/overlay-scrollbar.ts +174 -174
  752. package/src/_pkgs/affine-gfx-template/toolbar/template-panel.ts +517 -517
  753. package/src/_pkgs/affine-gfx-template/toolbar/template-tool-button.ts +225 -225
  754. package/src/_pkgs/affine-gfx-template/toolbar/utils.ts +33 -33
  755. package/src/_pkgs/affine-gfx-template/view.ts +25 -25
  756. package/src/_pkgs/affine-gfx-text/adapter/markdown/index.ts +24 -24
  757. package/src/_pkgs/affine-gfx-text/adapter/plain-text/index.ts +14 -14
  758. package/src/_pkgs/affine-gfx-text/adapter/text.ts +22 -22
  759. package/src/_pkgs/affine-gfx-text/commands/insert-edgeless-text.ts +114 -114
  760. package/src/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.ts +52 -52
  761. package/src/_pkgs/affine-gfx-text/edgeless-text-editor.ts +487 -487
  762. package/src/_pkgs/affine-gfx-text/element-renderer/index.ts +94 -94
  763. package/src/_pkgs/affine-gfx-text/element-renderer/utils.ts +559 -559
  764. package/src/_pkgs/affine-gfx-text/element-view.ts +95 -95
  765. package/src/_pkgs/affine-gfx-text/store.ts +19 -19
  766. package/src/_pkgs/affine-gfx-text/tool.ts +66 -66
  767. package/src/_pkgs/affine-gfx-text/toolbar/actions.ts +396 -396
  768. package/src/_pkgs/affine-gfx-text/toolbar/config.ts +56 -56
  769. package/src/_pkgs/affine-gfx-text/toolbar/text-menu.ts +49 -49
  770. package/src/_pkgs/affine-gfx-text/view.ts +32 -32
  771. package/src/_pkgs/affine-gfx-turbo-renderer/layout/block-layout-provider.ts +29 -29
  772. package/src/_pkgs/affine-gfx-turbo-renderer/painter/painter.worker.ts +129 -129
  773. package/src/_pkgs/affine-gfx-turbo-renderer/renderer-utils.ts +222 -222
  774. package/src/_pkgs/affine-gfx-turbo-renderer/turbo-renderer.ts +431 -431
  775. package/src/_pkgs/affine-inline-comment/inline-comment-manager.ts +218 -218
  776. package/src/_pkgs/affine-inline-comment/inline-comment.ts +97 -97
  777. package/src/_pkgs/affine-inline-comment/inline-spec.ts +38 -38
  778. package/src/_pkgs/affine-inline-comment/utils.ts +64 -64
  779. package/src/_pkgs/affine-inline-comment/view.ts +22 -22
  780. package/src/_pkgs/affine-inline-footnote/adapters/markdown/inline-delta.ts +50 -50
  781. package/src/_pkgs/affine-inline-footnote/adapters/markdown/markdown-inline.ts +57 -57
  782. package/src/_pkgs/affine-inline-footnote/adapters/markdown/preprocessor.ts +54 -54
  783. package/src/_pkgs/affine-inline-footnote/footnote-node/footnote-config.ts +120 -120
  784. package/src/_pkgs/affine-inline-footnote/footnote-node/footnote-node.ts +279 -279
  785. package/src/_pkgs/affine-inline-footnote/footnote-node/footnote-popup-chip.ts +74 -74
  786. package/src/_pkgs/affine-inline-footnote/footnote-node/footnote-popup.ts +223 -223
  787. package/src/_pkgs/affine-inline-footnote/inline-spec.ts +32 -32
  788. package/src/_pkgs/affine-inline-footnote/store.ts +21 -21
  789. package/src/_pkgs/affine-inline-footnote/view.ts +21 -21
  790. package/src/_pkgs/affine-inline-latex/adapters/markdown/inline-delta.ts +21 -21
  791. package/src/_pkgs/affine-inline-latex/adapters/markdown/markdown-inline.ts +12 -12
  792. package/src/_pkgs/affine-inline-latex/adapters/plain-text/inline-delta.ts +21 -21
  793. package/src/_pkgs/affine-inline-latex/command.ts +74 -74
  794. package/src/_pkgs/affine-inline-latex/index.ts +9 -9
  795. package/src/_pkgs/affine-inline-latex/inline-spec.ts +40 -40
  796. package/src/_pkgs/affine-inline-latex/latex-node/latex-editor-menu.ts +210 -210
  797. package/src/_pkgs/affine-inline-latex/latex-node/latex-editor-unit.ts +55 -55
  798. package/src/_pkgs/affine-inline-latex/latex-node/latex-node.ts +265 -265
  799. package/src/_pkgs/affine-inline-latex/markdown.ts +180 -180
  800. package/src/_pkgs/affine-inline-latex/store.ts +21 -21
  801. package/src/_pkgs/affine-inline-latex/view.ts +29 -29
  802. package/src/_pkgs/affine-inline-link/adapters/html/html-inline.ts +70 -70
  803. package/src/_pkgs/affine-inline-link/adapters/html/inline-delta.ts +25 -25
  804. package/src/_pkgs/affine-inline-link/adapters/markdown/inline-delta.ts +36 -36
  805. package/src/_pkgs/affine-inline-link/adapters/markdown/markdown-inline.ts +52 -52
  806. package/src/_pkgs/affine-inline-link/adapters/notion-html/html-inline.ts +52 -52
  807. package/src/_pkgs/affine-inline-link/adapters/plain-text/inline-delta.ts +25 -25
  808. package/src/_pkgs/affine-inline-link/command.ts +42 -42
  809. package/src/_pkgs/affine-inline-link/inline-spec.ts +22 -22
  810. package/src/_pkgs/affine-inline-link/link-node/affine-link.ts +188 -188
  811. package/src/_pkgs/affine-inline-link/link-node/configs/toolbar.ts +365 -365
  812. package/src/_pkgs/affine-inline-link/link-node/link-popup/link-popup.ts +335 -335
  813. package/src/_pkgs/affine-inline-link/link-node/link-popup/styles.ts +162 -162
  814. package/src/_pkgs/affine-inline-link/link-node/link-popup/toggle-link-popup.ts +27 -27
  815. package/src/_pkgs/affine-inline-link/markdown.ts +53 -53
  816. package/src/_pkgs/affine-inline-link/store.ts +27 -27
  817. package/src/_pkgs/affine-inline-link/toolbar.ts +9 -9
  818. package/src/_pkgs/affine-inline-link/view.ts +23 -23
  819. package/src/_pkgs/affine-inline-mention/affine-mention.ts +150 -150
  820. package/src/_pkgs/affine-inline-mention/inline-spec.ts +34 -34
  821. package/src/_pkgs/affine-inline-mention/view.ts +21 -21
  822. package/src/_pkgs/affine-inline-preset/adapters/extensions.ts +21 -21
  823. package/src/_pkgs/affine-inline-preset/adapters/html/html-inline.ts +311 -311
  824. package/src/_pkgs/affine-inline-preset/adapters/html/inline-delta.ts +154 -154
  825. package/src/_pkgs/affine-inline-preset/adapters/markdown/inline-delta.ts +57 -57
  826. package/src/_pkgs/affine-inline-preset/adapters/markdown/markdown-inline.ts +98 -98
  827. package/src/_pkgs/affine-inline-preset/adapters/notion-html/html-inline.ts +256 -256
  828. package/src/_pkgs/affine-inline-preset/command/config.ts +138 -138
  829. package/src/_pkgs/affine-inline-preset/command/consts.ts +19 -19
  830. package/src/_pkgs/affine-inline-preset/command/delete-text.ts +81 -81
  831. package/src/_pkgs/affine-inline-preset/command/format-block.ts +75 -75
  832. package/src/_pkgs/affine-inline-preset/command/format-native.ts +53 -53
  833. package/src/_pkgs/affine-inline-preset/command/format-text.ts +94 -94
  834. package/src/_pkgs/affine-inline-preset/command/text-style.ts +110 -110
  835. package/src/_pkgs/affine-inline-preset/command/utils.ts +226 -226
  836. package/src/_pkgs/affine-inline-preset/default-inline-manager.ts +38 -38
  837. package/src/_pkgs/affine-inline-preset/index.ts +10 -10
  838. package/src/_pkgs/affine-inline-preset/inline-spec.ts +118 -118
  839. package/src/_pkgs/affine-inline-preset/keymap/basic.ts +78 -78
  840. package/src/_pkgs/affine-inline-preset/keymap/bracket.ts +162 -162
  841. package/src/_pkgs/affine-inline-preset/keymap/format.ts +36 -36
  842. package/src/_pkgs/affine-inline-preset/keymap/index.ts +15 -15
  843. package/src/_pkgs/affine-inline-preset/markdown.ts +284 -284
  844. package/src/_pkgs/affine-inline-preset/nodes/affine-text.ts +35 -35
  845. package/src/_pkgs/affine-inline-preset/store.ts +15 -15
  846. package/src/_pkgs/affine-inline-preset/view.ts +25 -25
  847. package/src/_pkgs/affine-inline-reference/adapters/html/inline-delta.ts +42 -42
  848. package/src/_pkgs/affine-inline-reference/adapters/markdown/inline-delta.ts +42 -42
  849. package/src/_pkgs/affine-inline-reference/adapters/plain-text/inline-delta.ts +33 -33
  850. package/src/_pkgs/affine-inline-reference/inline-spec.ts +57 -57
  851. package/src/_pkgs/affine-inline-reference/reference-node/configs/toolbar.ts +247 -247
  852. package/src/_pkgs/affine-inline-reference/reference-node/reference-config.ts +53 -53
  853. package/src/_pkgs/affine-inline-reference/reference-node/reference-node-slots.ts +30 -30
  854. package/src/_pkgs/affine-inline-reference/reference-node/reference-node.ts +318 -318
  855. package/src/_pkgs/affine-inline-reference/reference-node/reference-popup/reference-popup.ts +282 -282
  856. package/src/_pkgs/affine-inline-reference/reference-node/reference-popup/toggle-reference-popup.ts +27 -27
  857. package/src/_pkgs/affine-inline-reference/reference-node/types.ts +15 -15
  858. package/src/_pkgs/affine-inline-reference/store.ts +21 -21
  859. package/src/_pkgs/affine-inline-reference/toolbar.ts +9 -9
  860. package/src/_pkgs/affine-inline-reference/utils.ts +21 -21
  861. package/src/_pkgs/affine-inline-reference/view.ts +25 -25
  862. package/src/_pkgs/affine-model/blocks/attachment/attachment-model.ts +112 -112
  863. package/src/_pkgs/affine-model/blocks/attachment/attachment-transformer.ts +34 -34
  864. package/src/_pkgs/affine-model/blocks/bookmark/bookmark-model.ts +81 -81
  865. package/src/_pkgs/affine-model/blocks/callout/callout-model.ts +44 -44
  866. package/src/_pkgs/affine-model/blocks/code/code-model.ts +52 -52
  867. package/src/_pkgs/affine-model/blocks/database/database-model.ts +43 -43
  868. package/src/_pkgs/affine-model/blocks/divider/divider-model.ts +24 -24
  869. package/src/_pkgs/affine-model/blocks/edgeless-text/edgeless-text-model.ts +94 -94
  870. package/src/_pkgs/affine-model/blocks/embed/figma/figma-model.ts +21 -21
  871. package/src/_pkgs/affine-model/blocks/embed/figma/figma-schema.ts +28 -28
  872. package/src/_pkgs/affine-model/blocks/embed/github/github-model.ts +35 -35
  873. package/src/_pkgs/affine-model/blocks/embed/github/github-schema.ts +37 -37
  874. package/src/_pkgs/affine-model/blocks/embed/html/html-model.ts +17 -17
  875. package/src/_pkgs/affine-model/blocks/embed/html/html-schema.ts +25 -25
  876. package/src/_pkgs/affine-model/blocks/embed/iframe/iframe-model.ts +38 -38
  877. package/src/_pkgs/affine-model/blocks/embed/iframe/iframe-schema.ts +17 -17
  878. package/src/_pkgs/affine-model/blocks/embed/linked-doc/linked-doc-model.ts +24 -24
  879. package/src/_pkgs/affine-model/blocks/embed/linked-doc/linked-doc-schema.ts +30 -30
  880. package/src/_pkgs/affine-model/blocks/embed/loom/loom-model.ts +23 -23
  881. package/src/_pkgs/affine-model/blocks/embed/loom/loom-schema.ts +29 -29
  882. package/src/_pkgs/affine-model/blocks/embed/synced-doc/synced-doc-model.ts +30 -30
  883. package/src/_pkgs/affine-model/blocks/embed/synced-doc/synced-doc-schema.ts +39 -39
  884. package/src/_pkgs/affine-model/blocks/embed/types.ts +58 -58
  885. package/src/_pkgs/affine-model/blocks/embed/youtube/youtube-model.ts +26 -26
  886. package/src/_pkgs/affine-model/blocks/embed/youtube/youtube-schema.ts +33 -33
  887. package/src/_pkgs/affine-model/blocks/frame/frame-model.ts +163 -163
  888. package/src/_pkgs/affine-model/blocks/image/image-model.ts +59 -59
  889. package/src/_pkgs/affine-model/blocks/image/image-transformer.ts +34 -34
  890. package/src/_pkgs/affine-model/blocks/latex/latex-model.ts +47 -47
  891. package/src/_pkgs/affine-model/blocks/list/list-model.ts +56 -56
  892. package/src/_pkgs/affine-model/blocks/note/note-model.ts +167 -167
  893. package/src/_pkgs/affine-model/blocks/paragraph/paragraph-model.ts +62 -62
  894. package/src/_pkgs/affine-model/blocks/root/root-block-model.ts +65 -65
  895. package/src/_pkgs/affine-model/blocks/surface-ref/surface-ref-model.ts +34 -34
  896. package/src/_pkgs/affine-model/blocks/table/table-model.ts +71 -71
  897. package/src/_pkgs/affine-model/consts/doc.ts +94 -94
  898. package/src/_pkgs/affine-model/elements/bpmn/index.ts +2 -2
  899. package/src/_pkgs/affine-model/elements/bpmn/node.ts +42 -42
  900. package/src/_pkgs/affine-model/elements/bpmn/pool.ts +66 -66
  901. package/src/_pkgs/affine-model/elements/brush/brush.ts +219 -219
  902. package/src/_pkgs/affine-model/elements/connector/connector.ts +539 -539
  903. package/src/_pkgs/affine-model/elements/connector/local-connector.ts +58 -58
  904. package/src/_pkgs/affine-model/elements/cynefin/cynefin.ts +78 -78
  905. package/src/_pkgs/affine-model/elements/edgy/facets.ts +87 -87
  906. package/src/_pkgs/affine-model/elements/edgy/node.ts +37 -37
  907. package/src/_pkgs/affine-model/elements/estuarine/estuarine.ts +79 -79
  908. package/src/_pkgs/affine-model/elements/group/group.ts +121 -121
  909. package/src/_pkgs/affine-model/elements/highlighter/highlighter.ts +220 -220
  910. package/src/_pkgs/affine-model/elements/mindmap/mindmap.ts +974 -974
  911. package/src/_pkgs/affine-model/elements/shape/api/diamond.ts +120 -120
  912. package/src/_pkgs/affine-model/elements/shape/api/ellipse.ts +202 -202
  913. package/src/_pkgs/affine-model/elements/shape/api/polygon.ts +424 -424
  914. package/src/_pkgs/affine-model/elements/shape/api/rect.ts +119 -119
  915. package/src/_pkgs/affine-model/elements/shape/api/triangle.ts +116 -116
  916. package/src/_pkgs/affine-model/elements/shape/shape.ts +367 -367
  917. package/src/_pkgs/affine-model/elements/text/text.ts +92 -92
  918. package/src/_pkgs/affine-model/elements/wardley/node.ts +52 -52
  919. package/src/_pkgs/affine-model/elements/wardley/wardley.ts +160 -160
  920. package/src/_pkgs/affine-model/utils/helper.ts +74 -74
  921. package/src/_pkgs/affine-model/utils/types.ts +43 -43
  922. package/src/_pkgs/affine-rich-text/conversion.ts +136 -136
  923. package/src/_pkgs/affine-rich-text/dom.ts +172 -172
  924. package/src/_pkgs/affine-rich-text/hooks.ts +116 -116
  925. package/src/_pkgs/affine-rich-text/rich-text.ts +480 -480
  926. package/src/_pkgs/affine-rich-text/utils.ts +68 -68
  927. package/src/_pkgs/affine-shared/adapters/attachment.ts +147 -147
  928. package/src/_pkgs/affine-shared/adapters/clipboard/clipboard.ts +107 -107
  929. package/src/_pkgs/affine-shared/adapters/html/block-adapter.ts +31 -31
  930. package/src/_pkgs/affine-shared/adapters/html/delta-converter.ts +135 -135
  931. package/src/_pkgs/affine-shared/adapters/html/html.ts +400 -400
  932. package/src/_pkgs/affine-shared/adapters/image.ts +137 -137
  933. package/src/_pkgs/affine-shared/adapters/markdown/block-adapter.ts +31 -31
  934. package/src/_pkgs/affine-shared/adapters/markdown/delta-converter.ts +124 -124
  935. package/src/_pkgs/affine-shared/adapters/markdown/markdown.ts +414 -414
  936. package/src/_pkgs/affine-shared/adapters/markdown/preprocessor.ts +40 -40
  937. package/src/_pkgs/affine-shared/adapters/middlewares/callout-export-options.ts +45 -45
  938. package/src/_pkgs/affine-shared/adapters/middlewares/code.ts +11 -11
  939. package/src/_pkgs/affine-shared/adapters/middlewares/copy.ts +66 -66
  940. package/src/_pkgs/affine-shared/adapters/middlewares/doc-link.ts +44 -44
  941. package/src/_pkgs/affine-shared/adapters/middlewares/file-name.ts +27 -27
  942. package/src/_pkgs/affine-shared/adapters/middlewares/file-path.ts +14 -14
  943. package/src/_pkgs/affine-shared/adapters/middlewares/paste.ts +596 -596
  944. package/src/_pkgs/affine-shared/adapters/middlewares/proxy.ts +53 -53
  945. package/src/_pkgs/affine-shared/adapters/middlewares/replace-id.ts +256 -256
  946. package/src/_pkgs/affine-shared/adapters/middlewares/surface-ref-to-embed.ts +46 -46
  947. package/src/_pkgs/affine-shared/adapters/middlewares/title.ts +15 -15
  948. package/src/_pkgs/affine-shared/adapters/middlewares/upload.ts +118 -118
  949. package/src/_pkgs/affine-shared/adapters/mix-text.ts +360 -360
  950. package/src/_pkgs/affine-shared/adapters/notion-html/block-adapter.ts +33 -33
  951. package/src/_pkgs/affine-shared/adapters/notion-html/delta-converter.ts +105 -105
  952. package/src/_pkgs/affine-shared/adapters/notion-html/notion-html.ts +300 -300
  953. package/src/_pkgs/affine-shared/adapters/notion-text.ts +191 -191
  954. package/src/_pkgs/affine-shared/adapters/plain-text/block-adapter.ts +28 -28
  955. package/src/_pkgs/affine-shared/adapters/plain-text/delta-converter.ts +81 -81
  956. package/src/_pkgs/affine-shared/adapters/plain-text/plain-text.ts +324 -324
  957. package/src/_pkgs/affine-shared/adapters/types/adapter.ts +124 -124
  958. package/src/_pkgs/affine-shared/adapters/types/delta-converter.ts +61 -61
  959. package/src/_pkgs/affine-shared/adapters/types/preprocessor.ts +88 -88
  960. package/src/_pkgs/affine-shared/adapters/utils/text.ts +96 -96
  961. package/src/_pkgs/affine-shared/commands/block-crud/get-block-index.ts +33 -33
  962. package/src/_pkgs/affine-shared/commands/block-crud/get-first-content-block.ts +65 -65
  963. package/src/_pkgs/affine-shared/commands/block-crud/get-last-content-block.ts +67 -67
  964. package/src/_pkgs/affine-shared/commands/block-crud/get-next-block.ts +36 -36
  965. package/src/_pkgs/affine-shared/commands/block-crud/get-prev-block.ts +37 -37
  966. package/src/_pkgs/affine-shared/commands/block-crud/get-selected-blocks.ts +164 -164
  967. package/src/_pkgs/affine-shared/commands/model-crud/clear-and-select-first-model.ts +33 -33
  968. package/src/_pkgs/affine-shared/commands/model-crud/copy-selected-models.ts +25 -25
  969. package/src/_pkgs/affine-shared/commands/model-crud/delete-selected-models.ts +21 -21
  970. package/src/_pkgs/affine-shared/commands/model-crud/draft-selected-models.ts +50 -50
  971. package/src/_pkgs/affine-shared/commands/model-crud/duplicate-selected-model.ts +55 -55
  972. package/src/_pkgs/affine-shared/commands/model-crud/get-selected-models.ts +67 -67
  973. package/src/_pkgs/affine-shared/commands/model-crud/replace-selected-text-with-blocks.ts +399 -399
  974. package/src/_pkgs/affine-shared/commands/model-crud/retain-first-model.ts +19 -19
  975. package/src/_pkgs/affine-shared/commands/selection/focus-block-end.ts +37 -37
  976. package/src/_pkgs/affine-shared/commands/selection/focus-block-start.ts +23 -23
  977. package/src/_pkgs/affine-shared/commands/selection/get-block-selections.ts +10 -10
  978. package/src/_pkgs/affine-shared/commands/selection/get-selection-rects.ts +184 -184
  979. package/src/_pkgs/affine-shared/commands/selection/get-surface-selection.ts +10 -10
  980. package/src/_pkgs/affine-shared/commands/selection/get-text-selection.ts +10 -10
  981. package/src/_pkgs/affine-shared/commands/selection/is-nothing-selected.ts +24 -24
  982. package/src/_pkgs/affine-shared/commands/selection/types.ts +18 -18
  983. package/src/_pkgs/affine-shared/consts/index.ts +90 -90
  984. package/src/_pkgs/affine-shared/selection/hightlight.ts +66 -66
  985. package/src/_pkgs/affine-shared/selection/image.ts +33 -33
  986. package/src/_pkgs/affine-shared/services/auto-clear-selection-service.ts +12 -12
  987. package/src/_pkgs/affine-shared/services/block-meta-service.ts +104 -104
  988. package/src/_pkgs/affine-shared/services/citation-service/citation-service.ts +84 -84
  989. package/src/_pkgs/affine-shared/services/comment-service/block-comment-manager.ts +118 -118
  990. package/src/_pkgs/affine-shared/services/comment-service/comment-provider.ts +44 -44
  991. package/src/_pkgs/affine-shared/services/comment-service/utils.ts +50 -50
  992. package/src/_pkgs/affine-shared/services/doc-display-meta-service.ts +197 -197
  993. package/src/_pkgs/affine-shared/services/doc-mode-service.ts +109 -109
  994. package/src/_pkgs/affine-shared/services/drag-handle-config.ts +65 -65
  995. package/src/_pkgs/affine-shared/services/edit-props-store.ts +217 -217
  996. package/src/_pkgs/affine-shared/services/editor-setting-service.ts +41 -41
  997. package/src/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.ts +93 -93
  998. package/src/_pkgs/affine-shared/services/embed-iframe/embed-iframe-service.ts +152 -152
  999. package/src/_pkgs/affine-shared/services/embed-option-service.ts +65 -65
  1000. package/src/_pkgs/affine-shared/services/feature-flag-service.ts +65 -65
  1001. package/src/_pkgs/affine-shared/services/file-size-limit-service.ts +23 -23
  1002. package/src/_pkgs/affine-shared/services/font-loader/config.ts +379 -379
  1003. package/src/_pkgs/affine-shared/services/font-loader/font-loader-service.ts +62 -62
  1004. package/src/_pkgs/affine-shared/services/generate-url-service.ts +21 -21
  1005. package/src/_pkgs/affine-shared/services/index.ts +1 -0
  1006. package/src/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.ts +240 -240
  1007. package/src/_pkgs/affine-shared/services/link-preview-service/link-preview-service.ts +210 -210
  1008. package/src/_pkgs/affine-shared/services/link-preview-service/link-preview-storage.ts +81 -81
  1009. package/src/_pkgs/affine-shared/services/linked-doc-creation-service.ts +34 -0
  1010. package/src/_pkgs/affine-shared/services/native-clipboard-service.ts +23 -23
  1011. package/src/_pkgs/affine-shared/services/notification-service.ts +123 -123
  1012. package/src/_pkgs/affine-shared/services/open-doc-config.ts +59 -59
  1013. package/src/_pkgs/affine-shared/services/page-viewport-service.ts +15 -15
  1014. package/src/_pkgs/affine-shared/services/parse-url-service.ts +22 -22
  1015. package/src/_pkgs/affine-shared/services/quick-search-service.ts +31 -31
  1016. package/src/_pkgs/affine-shared/services/sidebar-service.ts +18 -18
  1017. package/src/_pkgs/affine-shared/services/telemetry-service/block-lifecycle-watcher.ts +148 -148
  1018. package/src/_pkgs/affine-shared/services/telemetry-service/noop.ts +20 -20
  1019. package/src/_pkgs/affine-shared/services/telemetry-service/telemetry-service.ts +78 -78
  1020. package/src/_pkgs/affine-shared/services/theme-service.ts +195 -195
  1021. package/src/_pkgs/affine-shared/services/toolbar-service/context.ts +297 -297
  1022. package/src/_pkgs/affine-shared/services/toolbar-service/module.ts +9 -9
  1023. package/src/_pkgs/affine-shared/services/toolbar-service/registry.ts +64 -64
  1024. package/src/_pkgs/affine-shared/services/user-service/user-list-service.ts +28 -28
  1025. package/src/_pkgs/affine-shared/services/user-service/user-service.ts +24 -24
  1026. package/src/_pkgs/affine-shared/services/user-service/writer-info-service.ts +22 -22
  1027. package/src/_pkgs/affine-shared/services/viewport-element-service.ts +62 -62
  1028. package/src/_pkgs/affine-shared/services/virtual-keyboard-service.ts +23 -23
  1029. package/src/_pkgs/affine-shared/test-utils/affine-template.ts +316 -316
  1030. package/src/_pkgs/affine-shared/test-utils/affine-test-utils.ts +113 -113
  1031. package/src/_pkgs/affine-shared/test-utils/create-test-host.ts +248 -248
  1032. package/src/_pkgs/affine-shared/theme/css-variables.ts +132 -132
  1033. package/src/_pkgs/affine-shared/types/index.ts +74 -74
  1034. package/src/_pkgs/affine-shared/utils/button-popper.ts +161 -161
  1035. package/src/_pkgs/affine-shared/utils/collapsed/paragraph.ts +57 -57
  1036. package/src/_pkgs/affine-shared/utils/dnd/calc-drop-target.ts +208 -208
  1037. package/src/_pkgs/affine-shared/utils/dnd/get-drop-rect-by-point.ts +160 -160
  1038. package/src/_pkgs/affine-shared/utils/dnd/types.ts +29 -29
  1039. package/src/_pkgs/affine-shared/utils/dom/checker.ts +18 -18
  1040. package/src/_pkgs/affine-shared/utils/dom/point-to-block.ts +334 -334
  1041. package/src/_pkgs/affine-shared/utils/dom/point-to-range.ts +98 -98
  1042. package/src/_pkgs/affine-shared/utils/dom/query.ts +39 -39
  1043. package/src/_pkgs/affine-shared/utils/dom/viewport.ts +19 -19
  1044. package/src/_pkgs/affine-shared/utils/edgeless.ts +79 -79
  1045. package/src/_pkgs/affine-shared/utils/event.ts +362 -362
  1046. package/src/_pkgs/affine-shared/utils/file/filesys.ts +293 -293
  1047. package/src/_pkgs/affine-shared/utils/model/block-props.ts +6 -6
  1048. package/src/_pkgs/affine-shared/utils/model/checker.ts +34 -34
  1049. package/src/_pkgs/affine-shared/utils/model/doc.ts +38 -38
  1050. package/src/_pkgs/affine-shared/utils/model/get-content-block.ts +140 -140
  1051. package/src/_pkgs/affine-shared/utils/model/getter.ts +75 -75
  1052. package/src/_pkgs/affine-shared/utils/model/list.ts +103 -103
  1053. package/src/_pkgs/affine-shared/utils/model/merge-to-code-model.ts +33 -33
  1054. package/src/_pkgs/affine-shared/utils/model/transform-model.ts +31 -31
  1055. package/src/_pkgs/affine-shared/utils/reference.ts +44 -44
  1056. package/src/_pkgs/affine-shared/utils/title.ts +32 -32
  1057. package/src/_pkgs/affine-shared/utils/virtual-padding.ts +35 -35
  1058. package/src/_pkgs/affine-shared/utils/zod-schema.ts +219 -219
  1059. package/src/_pkgs/affine-widget-drag-handle/components/edgeless-preview/preview.ts +133 -133
  1060. package/src/_pkgs/affine-widget-drag-handle/drag-handle.ts +252 -252
  1061. package/src/_pkgs/affine-widget-drag-handle/helpers/preview-helper.ts +207 -207
  1062. package/src/_pkgs/affine-widget-drag-handle/helpers/rect-helper.ts +95 -95
  1063. package/src/_pkgs/affine-widget-drag-handle/helpers/selection-helper.ts +67 -67
  1064. package/src/_pkgs/affine-widget-drag-handle/index.ts +15 -15
  1065. package/src/_pkgs/affine-widget-drag-handle/middleware/blocks-filter.ts +119 -119
  1066. package/src/_pkgs/affine-widget-drag-handle/middleware/card-style-updater.ts +56 -56
  1067. package/src/_pkgs/affine-widget-drag-handle/middleware/new-id-cross-doc.ts +53 -53
  1068. package/src/_pkgs/affine-widget-drag-handle/middleware/reorder-list.ts +31 -31
  1069. package/src/_pkgs/affine-widget-drag-handle/styles.ts +86 -86
  1070. package/src/_pkgs/affine-widget-drag-handle/utils.ts +346 -346
  1071. package/src/_pkgs/affine-widget-drag-handle/view.ts +21 -21
  1072. package/src/_pkgs/affine-widget-drag-handle/watchers/drag-event-watcher.ts +1742 -1742
  1073. package/src/_pkgs/affine-widget-drag-handle/watchers/edgeless-watcher.ts +235 -235
  1074. package/src/_pkgs/affine-widget-drag-handle/watchers/keyboard-event-watcher.ts +24 -24
  1075. package/src/_pkgs/affine-widget-drag-handle/watchers/page-watcher.ts +21 -21
  1076. package/src/_pkgs/affine-widget-drag-handle/watchers/pointer-event-watcher.ts +366 -366
  1077. package/src/_pkgs/affine-widget-edgeless-auto-connect/index.ts +634 -634
  1078. package/src/_pkgs/affine-widget-edgeless-auto-connect/view.ts +23 -23
  1079. package/src/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.ts +68 -68
  1080. package/src/_pkgs/affine-widget-edgeless-dragging-area/view.ts +23 -23
  1081. package/src/_pkgs/affine-widget-edgeless-selected-rect/auto-complete-panel.ts +680 -680
  1082. package/src/_pkgs/affine-widget-edgeless-selected-rect/edgeless-auto-complete.ts +787 -787
  1083. package/src/_pkgs/affine-widget-edgeless-selected-rect/edgeless-selected-rect.ts +844 -844
  1084. package/src/_pkgs/affine-widget-edgeless-selected-rect/resize-handles.ts +94 -94
  1085. package/src/_pkgs/affine-widget-edgeless-selected-rect/spec.ts +10 -10
  1086. package/src/_pkgs/affine-widget-edgeless-selected-rect/utils.ts +416 -416
  1087. package/src/_pkgs/affine-widget-edgeless-selected-rect/view.ts +23 -23
  1088. package/src/_pkgs/affine-widget-edgeless-toolbar/config/types.ts +28 -28
  1089. package/src/_pkgs/affine-widget-edgeless-toolbar/config/utils.ts +72 -72
  1090. package/src/_pkgs/affine-widget-edgeless-toolbar/context.ts +21 -21
  1091. package/src/_pkgs/affine-widget-edgeless-toolbar/create-popper.ts +103 -103
  1092. package/src/_pkgs/affine-widget-edgeless-toolbar/draggable/draggable-element.controller.ts +477 -477
  1093. package/src/_pkgs/affine-widget-edgeless-toolbar/draggable/types.ts +97 -97
  1094. package/src/_pkgs/affine-widget-edgeless-toolbar/menu/slide-menu.ts +184 -184
  1095. package/src/_pkgs/affine-widget-edgeless-toolbar/menu/toolbar-arrow-up-icon.ts +17 -17
  1096. package/src/_pkgs/affine-widget-edgeless-toolbar/mixins/quick-tool.mixin.ts +21 -21
  1097. package/src/_pkgs/affine-widget-edgeless-toolbar/mixins/tool.mixin.ts +171 -171
  1098. package/src/_pkgs/affine-widget-edgeless-toolbar/mixins/toolbar-button-with-menu.mixin.ts +20 -20
  1099. package/src/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.ts +57 -57
  1100. package/src/_pkgs/affine-widget-edgeless-toolbar/panel/font-weight-and-style-panel.ts +163 -163
  1101. package/src/_pkgs/affine-widget-edgeless-toolbar/view.ts +23 -23
  1102. package/src/_pkgs/affine-widget-edgeless-zoom-toolbar/index.ts +94 -94
  1103. package/src/_pkgs/affine-widget-edgeless-zoom-toolbar/view.ts +23 -23
  1104. package/src/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-bar-toggle-button.ts +113 -113
  1105. package/src/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-toolbar.ts +213 -213
  1106. package/src/_pkgs/affine-widget-frame-title/affine-frame-title-widget.ts +21 -21
  1107. package/src/_pkgs/affine-widget-frame-title/edgeless-frame-title-editor.ts +185 -185
  1108. package/src/_pkgs/affine-widget-frame-title/frame-title.ts +293 -293
  1109. package/src/_pkgs/affine-widget-frame-title/mount-frame-title-editor.ts +34 -34
  1110. package/src/_pkgs/affine-widget-frame-title/styles.ts +35 -35
  1111. package/src/_pkgs/affine-widget-frame-title/view.ts +23 -23
  1112. package/src/_pkgs/affine-widget-keyboard-toolbar/config.ts +1160 -1160
  1113. package/src/_pkgs/affine-widget-keyboard-toolbar/keyboard-tool-panel.ts +100 -100
  1114. package/src/_pkgs/affine-widget-keyboard-toolbar/keyboard-toolbar.ts +350 -350
  1115. package/src/_pkgs/affine-widget-keyboard-toolbar/position-controller.ts +42 -42
  1116. package/src/_pkgs/affine-widget-keyboard-toolbar/styles.ts +145 -145
  1117. package/src/_pkgs/affine-widget-keyboard-toolbar/view.ts +28 -28
  1118. package/src/_pkgs/affine-widget-keyboard-toolbar/widget.ts +148 -148
  1119. package/src/_pkgs/affine-widget-linked-doc/config.ts +230 -230
  1120. package/src/_pkgs/affine-widget-linked-doc/import-doc/import-doc.ts +297 -297
  1121. package/src/_pkgs/affine-widget-linked-doc/import-doc/index.ts +38 -38
  1122. package/src/_pkgs/affine-widget-linked-doc/import-doc/loader.ts +103 -103
  1123. package/src/_pkgs/affine-widget-linked-doc/linked-doc-popover.ts +428 -428
  1124. package/src/_pkgs/affine-widget-linked-doc/mobile-linked-doc-menu.ts +216 -216
  1125. package/src/_pkgs/affine-widget-linked-doc/styles.ts +163 -163
  1126. package/src/_pkgs/affine-widget-linked-doc/transformers/html.ts +218 -218
  1127. package/src/_pkgs/affine-widget-linked-doc/transformers/markdown.ts +283 -283
  1128. package/src/_pkgs/affine-widget-linked-doc/transformers/notion-html.ts +174 -174
  1129. package/src/_pkgs/affine-widget-linked-doc/transformers/utils.ts +115 -115
  1130. package/src/_pkgs/affine-widget-linked-doc/transformers/zip.ts +172 -172
  1131. package/src/_pkgs/affine-widget-linked-doc/view.ts +83 -83
  1132. package/src/_pkgs/affine-widget-linked-doc/widget.ts +344 -344
  1133. package/src/_pkgs/affine-widget-note-slicer/note-slicer.ts +451 -451
  1134. package/src/_pkgs/affine-widget-note-slicer/view.ts +23 -23
  1135. package/src/_pkgs/affine-widget-page-dragging-area/index.ts +331 -331
  1136. package/src/_pkgs/affine-widget-page-dragging-area/utils.ts +146 -146
  1137. package/src/_pkgs/affine-widget-page-dragging-area/view.ts +24 -24
  1138. package/src/_pkgs/affine-widget-remote-selection/doc/config.ts +5 -5
  1139. package/src/_pkgs/affine-widget-remote-selection/doc/doc-remote-selection.ts +398 -398
  1140. package/src/_pkgs/affine-widget-remote-selection/edgeless/index.ts +304 -304
  1141. package/src/_pkgs/affine-widget-remote-selection/index.ts +20 -20
  1142. package/src/_pkgs/affine-widget-remote-selection/manager/remote-color-manager.ts +42 -42
  1143. package/src/_pkgs/affine-widget-remote-selection/view.ts +27 -27
  1144. package/src/_pkgs/affine-widget-scroll-anchoring/index.ts +12 -12
  1145. package/src/_pkgs/affine-widget-scroll-anchoring/scroll-anchoring.ts +267 -267
  1146. package/src/_pkgs/affine-widget-scroll-anchoring/view.ts +21 -21
  1147. package/src/_pkgs/affine-widget-slash-menu/config.ts +189 -189
  1148. package/src/_pkgs/affine-widget-slash-menu/extensions.ts +51 -51
  1149. package/src/_pkgs/affine-widget-slash-menu/slash-menu-popover.ts +668 -668
  1150. package/src/_pkgs/affine-widget-slash-menu/styles.ts +109 -109
  1151. package/src/_pkgs/affine-widget-slash-menu/types.ts +59 -59
  1152. package/src/_pkgs/affine-widget-slash-menu/view.ts +22 -22
  1153. package/src/_pkgs/affine-widget-slash-menu/widget.ts +184 -184
  1154. package/src/_pkgs/affine-widget-toolbar/index.ts +12 -12
  1155. package/src/_pkgs/affine-widget-toolbar/toolbar.ts +705 -705
  1156. package/src/_pkgs/affine-widget-toolbar/utils.ts +432 -432
  1157. package/src/_pkgs/affine-widget-toolbar/view.ts +22 -22
  1158. package/src/_pkgs/affine-widget-viewport-overlay/index.ts +90 -90
  1159. package/src/_pkgs/affine-widget-viewport-overlay/view.ts +21 -21
  1160. package/src/_pkgs/data-view/core/common/properties.ts +283 -283
  1161. package/src/_pkgs/data-view/core/common/property-menu.ts +76 -76
  1162. package/src/_pkgs/data-view/core/component/button/button.ts +89 -89
  1163. package/src/_pkgs/data-view/core/component/overflow/overflow.ts +109 -109
  1164. package/src/_pkgs/data-view/core/component/tags/multi-tag-select.ts +606 -606
  1165. package/src/_pkgs/data-view/core/component/tags/multi-tag-view.ts +88 -88
  1166. package/src/_pkgs/data-view/core/data-source/base.ts +305 -305
  1167. package/src/_pkgs/data-view/core/data-view.ts +211 -211
  1168. package/src/_pkgs/data-view/core/detail/detail.ts +305 -305
  1169. package/src/_pkgs/data-view/core/detail/field.ts +286 -286
  1170. package/src/_pkgs/data-view/core/expression/ref/ref-view.ts +94 -94
  1171. package/src/_pkgs/data-view/core/expression/types.ts +22 -22
  1172. package/src/_pkgs/data-view/core/filter/add-filter.ts +67 -67
  1173. package/src/_pkgs/data-view/core/filter/literal/define.ts +154 -154
  1174. package/src/_pkgs/data-view/core/filter/literal/types.ts +19 -19
  1175. package/src/_pkgs/data-view/core/filter/utils.ts +66 -66
  1176. package/src/_pkgs/data-view/core/group-by/group-title.ts +231 -231
  1177. package/src/_pkgs/data-view/core/group-by/matcher.ts +41 -41
  1178. package/src/_pkgs/data-view/core/group-by/renderer/base.ts +40 -40
  1179. package/src/_pkgs/data-view/core/group-by/renderer/number-group.ts +65 -65
  1180. package/src/_pkgs/data-view/core/group-by/renderer/select-group.ts +119 -119
  1181. package/src/_pkgs/data-view/core/group-by/renderer/string-group.ts +53 -53
  1182. package/src/_pkgs/data-view/core/group-by/setting.ts +322 -322
  1183. package/src/_pkgs/data-view/core/group-by/trait.ts +362 -362
  1184. package/src/_pkgs/data-view/core/group-by/types.ts +41 -41
  1185. package/src/_pkgs/data-view/core/logical/type-presets.ts +67 -67
  1186. package/src/_pkgs/data-view/core/logical/type-variable.ts +76 -76
  1187. package/src/_pkgs/data-view/core/property/base-cell.ts +134 -134
  1188. package/src/_pkgs/data-view/core/property/manager.ts +44 -44
  1189. package/src/_pkgs/data-view/core/property/renderer.ts +25 -25
  1190. package/src/_pkgs/data-view/core/property/types.ts +99 -99
  1191. package/src/_pkgs/data-view/core/sort/add-sort.ts +53 -53
  1192. package/src/_pkgs/data-view/core/sort/utils.ts +108 -108
  1193. package/src/_pkgs/data-view/core/utils/uni-component/operation.ts +16 -16
  1194. package/src/_pkgs/data-view/core/utils/uni-component/render-template.ts +24 -24
  1195. package/src/_pkgs/data-view/core/utils/uni-component/uni-component.ts +156 -156
  1196. package/src/_pkgs/data-view/core/utils/uni-icon.ts +36 -36
  1197. package/src/_pkgs/data-view/core/view/data-view-base.ts +106 -106
  1198. package/src/_pkgs/data-view/core/view/data-view.ts +80 -80
  1199. package/src/_pkgs/data-view/core/view/types.ts +43 -43
  1200. package/src/_pkgs/data-view/core/view-manager/property.ts +270 -270
  1201. package/src/_pkgs/data-view/core/view-manager/row.ts +65 -65
  1202. package/src/_pkgs/data-view/core/view-manager/single-view.ts +286 -286
  1203. package/src/_pkgs/data-view/core/view-manager/view-manager.ts +130 -130
  1204. package/src/_pkgs/data-view/core/widget/types.ts +10 -10
  1205. package/src/_pkgs/data-view/core/widget/widget-base.ts +28 -28
  1206. package/src/_pkgs/data-view/property-presets/checkbox/cell-renderer.ts +121 -121
  1207. package/src/_pkgs/data-view/property-presets/converts.ts +45 -45
  1208. package/src/_pkgs/data-view/property-presets/date/cell-renderer.ts +167 -167
  1209. package/src/_pkgs/data-view/property-presets/multi-select/cell-renderer.ts +89 -89
  1210. package/src/_pkgs/data-view/property-presets/multi-select/define.ts +76 -76
  1211. package/src/_pkgs/data-view/property-presets/number/cell-renderer.ts +133 -133
  1212. package/src/_pkgs/data-view/property-presets/select/cell-renderer.ts +88 -88
  1213. package/src/_pkgs/data-view/property-presets/select/define.ts +73 -73
  1214. package/src/_pkgs/data-view/view-presets/kanban/define.ts +91 -91
  1215. package/src/_pkgs/data-view/view-presets/kanban/kanban-view-manager.ts +328 -328
  1216. package/src/_pkgs/data-view/view-presets/kanban/mobile/card.ts +225 -225
  1217. package/src/_pkgs/data-view/view-presets/kanban/mobile/cell.ts +178 -178
  1218. package/src/_pkgs/data-view/view-presets/kanban/mobile/group.ts +153 -153
  1219. package/src/_pkgs/data-view/view-presets/kanban/mobile/kanban-view-ui-logic.ts +170 -170
  1220. package/src/_pkgs/data-view/view-presets/kanban/mobile/menu.ts +122 -122
  1221. package/src/_pkgs/data-view/view-presets/kanban/pc/card.ts +337 -337
  1222. package/src/_pkgs/data-view/view-presets/kanban/pc/cell.ts +185 -185
  1223. package/src/_pkgs/data-view/view-presets/kanban/pc/controller/clipboard.ts +53 -53
  1224. package/src/_pkgs/data-view/view-presets/kanban/pc/controller/drag.ts +255 -255
  1225. package/src/_pkgs/data-view/view-presets/kanban/pc/controller/selection.ts +801 -801
  1226. package/src/_pkgs/data-view/view-presets/kanban/pc/group.ts +211 -211
  1227. package/src/_pkgs/data-view/view-presets/kanban/pc/header.ts +76 -76
  1228. package/src/_pkgs/data-view/view-presets/kanban/pc/kanban-view-ui-logic.ts +331 -331
  1229. package/src/_pkgs/data-view/view-presets/kanban/pc/menu.ts +114 -114
  1230. package/src/_pkgs/data-view/view-presets/table/mobile/cell.ts +170 -170
  1231. package/src/_pkgs/data-view/view-presets/table/mobile/column-header.ts +272 -272
  1232. package/src/_pkgs/data-view/view-presets/table/mobile/group.ts +166 -166
  1233. package/src/_pkgs/data-view/view-presets/table/mobile/header.ts +90 -90
  1234. package/src/_pkgs/data-view/view-presets/table/mobile/menu.ts +47 -47
  1235. package/src/_pkgs/data-view/view-presets/table/mobile/row.ts +150 -150
  1236. package/src/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.ts +160 -160
  1237. package/src/_pkgs/data-view/view-presets/table/pc/cell.ts +161 -161
  1238. package/src/_pkgs/data-view/view-presets/table/pc/controller/clipboard.ts +323 -323
  1239. package/src/_pkgs/data-view/view-presets/table/pc/controller/drag-to-fill.ts +112 -112
  1240. package/src/_pkgs/data-view/view-presets/table/pc/controller/drag.ts +209 -209
  1241. package/src/_pkgs/data-view/view-presets/table/pc/controller/hotkeys.ts +416 -416
  1242. package/src/_pkgs/data-view/view-presets/table/pc/controller/selection.ts +1180 -1180
  1243. package/src/_pkgs/data-view/view-presets/table/pc/group.ts +311 -311
  1244. package/src/_pkgs/data-view/view-presets/table/pc/header/column-header.ts +143 -143
  1245. package/src/_pkgs/data-view/view-presets/table/pc/header/column-renderer.ts +98 -98
  1246. package/src/_pkgs/data-view/view-presets/table/pc/header/database-header-column.ts +500 -500
  1247. package/src/_pkgs/data-view/view-presets/table/pc/header/number-format-bar.ts +145 -145
  1248. package/src/_pkgs/data-view/view-presets/table/pc/header/styles.ts +349 -349
  1249. package/src/_pkgs/data-view/view-presets/table/pc/header/vertical-indicator.ts +163 -163
  1250. package/src/_pkgs/data-view/view-presets/table/pc/menu.ts +132 -132
  1251. package/src/_pkgs/data-view/view-presets/table/pc/row/row-select-checkbox.ts +80 -80
  1252. package/src/_pkgs/data-view/view-presets/table/pc/row/row.ts +306 -306
  1253. package/src/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.ts +220 -220
  1254. package/src/_pkgs/data-view/view-presets/table/pc-virtual/controller/clipboard.ts +324 -324
  1255. package/src/_pkgs/data-view/view-presets/table/pc-virtual/controller/drag-to-fill.ts +117 -117
  1256. package/src/_pkgs/data-view/view-presets/table/pc-virtual/controller/drag.ts +212 -212
  1257. package/src/_pkgs/data-view/view-presets/table/pc-virtual/controller/hotkeys.ts +418 -418
  1258. package/src/_pkgs/data-view/view-presets/table/pc-virtual/controller/selection.ts +1110 -1110
  1259. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/bottom/group-footer.ts +105 -105
  1260. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/bottom/stats/column-stats-bar.ts +51 -51
  1261. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.ts +246 -246
  1262. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-header.ts +138 -138
  1263. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-title-css.ts +63 -63
  1264. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/column-header.ts +135 -135
  1265. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/column-move-preview.ts +98 -98
  1266. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/number-format-bar.ts +147 -147
  1267. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/single-column-header.ts +497 -497
  1268. package/src/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/vertical-indicator.ts +169 -169
  1269. package/src/_pkgs/data-view/view-presets/table/pc-virtual/row/cell.ts +225 -225
  1270. package/src/_pkgs/data-view/view-presets/table/pc-virtual/row/menu.ts +132 -132
  1271. package/src/_pkgs/data-view/view-presets/table/pc-virtual/row/row-header.ts +128 -128
  1272. package/src/_pkgs/data-view/view-presets/table/pc-virtual/row/row-last.ts +65 -65
  1273. package/src/_pkgs/data-view/view-presets/table/pc-virtual/table-view-ui-logic.ts +321 -321
  1274. package/src/_pkgs/data-view/view-presets/table/pc-virtual/types.ts +41 -41
  1275. package/src/_pkgs/data-view/view-presets/table/pc-virtual/virtual/virtual-cell.ts +60 -60
  1276. package/src/_pkgs/data-view/view-presets/table/stats/column-stats-bar.ts +55 -55
  1277. package/src/_pkgs/data-view/view-presets/table/stats/column-stats-column.ts +246 -246
  1278. package/src/_pkgs/data-view/view-presets/table/table-view-manager.ts +395 -395
  1279. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/context.ts +10 -10
  1280. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/filter/condition-view.ts +311 -311
  1281. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/filter/group-panel-view.ts +480 -480
  1282. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/filter/index.ts +21 -21
  1283. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/filter/list-view.ts +220 -220
  1284. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/filter/root-panel-view.ts +437 -437
  1285. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/index.ts +52 -52
  1286. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/sort/index.ts +32 -32
  1287. package/src/_pkgs/data-view/widget-presets/quick-setting-bar/sort/root-panel.ts +240 -240
  1288. package/src/_pkgs/data-view/widget-presets/tools/presets/filter/filter.ts +122 -122
  1289. package/src/_pkgs/data-view/widget-presets/tools/presets/search/search.ts +189 -189
  1290. package/src/_pkgs/data-view/widget-presets/tools/presets/sort/sort.ts +127 -127
  1291. package/src/_pkgs/data-view/widget-presets/tools/presets/table-add-row/add-row.ts +51 -51
  1292. package/src/_pkgs/data-view/widget-presets/tools/presets/table-add-row/new-record-preview.ts +44 -44
  1293. package/src/_pkgs/data-view/widget-presets/tools/presets/view-options/view-options.ts +384 -384
  1294. package/src/_pkgs/data-view/widget-presets/tools/tools-view.ts +83 -83
  1295. package/src/_pkgs/data-view/widget-presets/views-bar/views-view.ts +319 -319
  1296. package/src/_pkgs/std/clipboard/clipboard-adapter.ts +33 -33
  1297. package/src/_pkgs/std/clipboard/clipboard.ts +323 -323
  1298. package/src/_pkgs/std/event/base.ts +62 -62
  1299. package/src/_pkgs/std/event/control/keyboard.ts +149 -149
  1300. package/src/_pkgs/std/event/control/pointer.ts +626 -626
  1301. package/src/_pkgs/std/event/dispatcher.ts +435 -435
  1302. package/src/_pkgs/std/event/keymap.ts +127 -127
  1303. package/src/_pkgs/std/event/utils.ts +17 -17
  1304. package/src/_pkgs/std/extension/block-view.ts +33 -33
  1305. package/src/_pkgs/std/extension/config.ts +44 -44
  1306. package/src/_pkgs/std/extension/dnd/index.ts +373 -373
  1307. package/src/_pkgs/std/extension/editor-life-cycle.ts +49 -49
  1308. package/src/_pkgs/std/extension/flavour.ts +26 -26
  1309. package/src/_pkgs/std/extension/keymap.ts +49 -49
  1310. package/src/_pkgs/std/extension/lifecycle-watcher.ts +70 -70
  1311. package/src/_pkgs/std/extension/service.ts +113 -113
  1312. package/src/_pkgs/std/extension/widget-view-map.ts +40 -40
  1313. package/src/_pkgs/std/gfx/controller.ts +284 -284
  1314. package/src/_pkgs/std/gfx/extension.ts +53 -53
  1315. package/src/_pkgs/std/gfx/grid.ts +513 -513
  1316. package/src/_pkgs/std/gfx/identifiers.ts +10 -10
  1317. package/src/_pkgs/std/gfx/interactivity/extension/base.ts +211 -211
  1318. package/src/_pkgs/std/gfx/interactivity/extension/view.ts +134 -134
  1319. package/src/_pkgs/std/gfx/interactivity/gfx-view-event-handler.ts +108 -108
  1320. package/src/_pkgs/std/gfx/interactivity/manager.ts +1111 -1111
  1321. package/src/_pkgs/std/gfx/interactivity/resize/manager.ts +657 -657
  1322. package/src/_pkgs/std/gfx/interactivity/types/drag.ts +73 -73
  1323. package/src/_pkgs/std/gfx/interactivity/types/resize.ts +41 -41
  1324. package/src/_pkgs/std/gfx/interactivity/types/view.ts +173 -173
  1325. package/src/_pkgs/std/gfx/keyboard.ts +51 -51
  1326. package/src/_pkgs/std/gfx/layer.ts +909 -909
  1327. package/src/_pkgs/std/gfx/model/base.ts +173 -173
  1328. package/src/_pkgs/std/gfx/model/gfx-block-model.ts +315 -315
  1329. package/src/_pkgs/std/gfx/model/surface/element-model.ts +598 -598
  1330. package/src/_pkgs/std/gfx/model/surface/local-element-model.ts +254 -254
  1331. package/src/_pkgs/std/gfx/model/surface/surface-model.ts +697 -697
  1332. package/src/_pkgs/std/gfx/selection.ts +408 -408
  1333. package/src/_pkgs/std/gfx/surface-middleware.ts +61 -61
  1334. package/src/_pkgs/std/gfx/tool/tool-controller.ts +635 -635
  1335. package/src/_pkgs/std/gfx/tool/tool.ts +125 -125
  1336. package/src/_pkgs/std/gfx/view/view-manager.ts +139 -139
  1337. package/src/_pkgs/std/gfx/view/view.ts +225 -225
  1338. package/src/_pkgs/std/gfx/viewport-element.ts +230 -230
  1339. package/src/_pkgs/std/gfx/viewport.ts +659 -659
  1340. package/src/_pkgs/std/identifier.ts +34 -34
  1341. package/src/_pkgs/std/inline/components/v-element.ts +113 -113
  1342. package/src/_pkgs/std/inline/components/v-line.ts +156 -156
  1343. package/src/_pkgs/std/inline/consts.ts +6 -6
  1344. package/src/_pkgs/std/inline/extensions/inline-manager.ts +124 -124
  1345. package/src/_pkgs/std/inline/extensions/inline-spec.ts +49 -49
  1346. package/src/_pkgs/std/inline/extensions/markdown-matcher.ts +30 -30
  1347. package/src/_pkgs/std/inline/extensions/type.ts +44 -44
  1348. package/src/_pkgs/std/inline/inline-editor.ts +296 -296
  1349. package/src/_pkgs/std/inline/range/inline-range-provider.ts +118 -118
  1350. package/src/_pkgs/std/inline/range/range-binding.ts +392 -392
  1351. package/src/_pkgs/std/inline/services/attribute.ts +106 -106
  1352. package/src/_pkgs/std/inline/services/delta.ts +153 -153
  1353. package/src/_pkgs/std/inline/services/event.ts +382 -382
  1354. package/src/_pkgs/std/inline/services/hook.ts +35 -35
  1355. package/src/_pkgs/std/inline/services/range.ts +394 -394
  1356. package/src/_pkgs/std/inline/services/render.ts +185 -185
  1357. package/src/_pkgs/std/inline/services/text.ts +140 -140
  1358. package/src/_pkgs/std/inline/types.ts +37 -37
  1359. package/src/_pkgs/std/inline/utils/attribute-renderer.ts +49 -49
  1360. package/src/_pkgs/std/inline/utils/delta-convert.ts +63 -63
  1361. package/src/_pkgs/std/inline/utils/embed.ts +47 -47
  1362. package/src/_pkgs/std/inline/utils/point-conversion.ts +191 -191
  1363. package/src/_pkgs/std/inline/utils/range-conversion.ts +368 -368
  1364. package/src/_pkgs/std/inline/utils/renderer.ts +18 -18
  1365. package/src/_pkgs/std/inline/utils/transform-input.ts +78 -78
  1366. package/src/_pkgs/std/scope/std-scope.ts +169 -169
  1367. package/src/_pkgs/std/selection/block.ts +33 -33
  1368. package/src/_pkgs/std/selection/cursor.ts +45 -45
  1369. package/src/_pkgs/std/selection/surface.ts +72 -72
  1370. package/src/_pkgs/std/selection/text.ts +117 -117
  1371. package/src/_pkgs/std/spec/type.ts +5 -5
  1372. package/src/_pkgs/std/utils/gfx.ts +32 -32
  1373. package/src/_pkgs/std/utils/layer.ts +175 -175
  1374. package/src/_pkgs/std/utils/tree.ts +137 -137
  1375. package/src/_pkgs/std/view/decorators/required.ts +58 -58
  1376. package/src/_pkgs/std/view/element/block-component.ts +315 -315
  1377. package/src/_pkgs/std/view/element/consts.ts +10 -10
  1378. package/src/_pkgs/std/view/element/gfx-block-component.ts +303 -303
  1379. package/src/_pkgs/std/view/element/lit-host.ts +197 -197
  1380. package/src/_pkgs/std/view/element/shadowless-element.ts +97 -97
  1381. package/src/_pkgs/std/view/element/widget-component.ts +98 -98
  1382. package/src/_pkgs/store/adapter/assets.ts +159 -159
  1383. package/src/_pkgs/store/adapter/base.ts +324 -324
  1384. package/src/_pkgs/store/extension/extension.ts +134 -134
  1385. package/src/_pkgs/store/extension/schema.ts +20 -20
  1386. package/src/_pkgs/store/extension/selection/base.ts +46 -46
  1387. package/src/_pkgs/store/extension/selection/identifier.ts +17 -17
  1388. package/src/_pkgs/store/extension/selection/selection-extension.ts +189 -189
  1389. package/src/_pkgs/store/extension/store-extension.ts +61 -61
  1390. package/src/_pkgs/store/extension/workspace/doc.ts +38 -38
  1391. package/src/_pkgs/store/extension/workspace/workspace.ts +30 -30
  1392. package/src/_pkgs/store/index.ts +27 -27
  1393. package/src/_pkgs/store/model/block/block-model.ts +158 -158
  1394. package/src/_pkgs/store/model/block/flat-sync-controller.ts +173 -173
  1395. package/src/_pkgs/store/model/block/sync-controller.ts +391 -391
  1396. package/src/_pkgs/store/model/store/crud.ts +397 -397
  1397. package/src/_pkgs/store/model/store/identifier.ts +5 -5
  1398. package/src/_pkgs/store/model/store/store.ts +1298 -1298
  1399. package/src/_pkgs/store/reactive/flat-native-y/initialize.ts +59 -59
  1400. package/src/_pkgs/store/reactive/proxy.ts +390 -390
  1401. package/src/_pkgs/store/reactive/text/text.ts +472 -472
  1402. package/src/_pkgs/store/schema/error.ts +10 -10
  1403. package/src/_pkgs/store/test/test-workspace.ts +231 -231
  1404. package/src/_pkgs/store/transformer/assets.ts +105 -105
  1405. package/src/_pkgs/store/transformer/transformer.ts +660 -660
  1406. package/src/_pkgs/sync/blob/engine.ts +205 -205
  1407. package/src/_pkgs/sync/doc/engine.ts +291 -291
  1408. package/src/_pkgs/sync/doc/peer.ts +451 -451
  1409. package/src/blocks/attachment/index.ts +1 -1
  1410. package/src/blocks/attachment/store.ts +1 -1
  1411. package/src/blocks/attachment/view.ts +1 -1
  1412. package/src/blocks/bookmark/index.ts +1 -1
  1413. package/src/blocks/bookmark/store.ts +1 -1
  1414. package/src/blocks/bookmark/view.ts +1 -1
  1415. package/src/blocks/callout/index.ts +1 -1
  1416. package/src/blocks/callout/store.ts +1 -1
  1417. package/src/blocks/callout/view.ts +1 -1
  1418. package/src/blocks/code/index.ts +1 -1
  1419. package/src/blocks/code/store.ts +1 -1
  1420. package/src/blocks/code/view.ts +1 -1
  1421. package/src/blocks/data-view/index.ts +1 -1
  1422. package/src/blocks/data-view/store.ts +1 -1
  1423. package/src/blocks/data-view/view.ts +1 -1
  1424. package/src/blocks/database/index.ts +1 -1
  1425. package/src/blocks/database/store.ts +1 -1
  1426. package/src/blocks/database/view.ts +1 -1
  1427. package/src/blocks/divider/index.ts +1 -1
  1428. package/src/blocks/divider/store.ts +1 -1
  1429. package/src/blocks/divider/view.ts +1 -1
  1430. package/src/blocks/edgeless-text/index.ts +1 -1
  1431. package/src/blocks/edgeless-text/store.ts +1 -1
  1432. package/src/blocks/edgeless-text/view.ts +1 -1
  1433. package/src/blocks/embed/index.ts +1 -1
  1434. package/src/blocks/embed/store.ts +1 -1
  1435. package/src/blocks/embed/view.ts +1 -1
  1436. package/src/blocks/embed-doc/index.ts +1 -1
  1437. package/src/blocks/embed-doc/store.ts +1 -1
  1438. package/src/blocks/embed-doc/view.ts +1 -1
  1439. package/src/blocks/frame/index.ts +1 -1
  1440. package/src/blocks/frame/store.ts +1 -1
  1441. package/src/blocks/frame/view.ts +1 -1
  1442. package/src/blocks/image/index.ts +1 -1
  1443. package/src/blocks/image/store.ts +1 -1
  1444. package/src/blocks/image/view.ts +1 -1
  1445. package/src/blocks/latex/index.ts +1 -1
  1446. package/src/blocks/latex/store.ts +1 -1
  1447. package/src/blocks/latex/view.ts +1 -1
  1448. package/src/blocks/list/index.ts +1 -1
  1449. package/src/blocks/list/store.ts +1 -1
  1450. package/src/blocks/list/view.ts +1 -1
  1451. package/src/blocks/note/index.ts +1 -1
  1452. package/src/blocks/note/store.ts +1 -1
  1453. package/src/blocks/note/view.ts +1 -1
  1454. package/src/blocks/paragraph/index.ts +1 -1
  1455. package/src/blocks/paragraph/store.ts +1 -1
  1456. package/src/blocks/paragraph/view.ts +1 -1
  1457. package/src/blocks/root/index.ts +1 -1
  1458. package/src/blocks/root/store.ts +1 -1
  1459. package/src/blocks/root/view.ts +1 -1
  1460. package/src/blocks/surface/index.ts +1 -1
  1461. package/src/blocks/surface/store.ts +1 -1
  1462. package/src/blocks/surface/view.ts +1 -1
  1463. package/src/blocks/surface-ref/index.ts +1 -1
  1464. package/src/blocks/surface-ref/store.ts +1 -1
  1465. package/src/blocks/surface-ref/view.ts +1 -1
  1466. package/src/blocks/table/index.ts +1 -1
  1467. package/src/blocks/table/store.ts +1 -1
  1468. package/src/blocks/table/view.ts +1 -1
  1469. package/src/components/block-selection.ts +1 -1
  1470. package/src/components/block-zero-width.ts +1 -1
  1471. package/src/components/caption.ts +1 -1
  1472. package/src/components/card-style-dropdown-menu.ts +1 -1
  1473. package/src/components/citation.ts +1 -1
  1474. package/src/components/color-picker.ts +1 -1
  1475. package/src/components/context-menu.ts +1 -1
  1476. package/src/components/date-picker.ts +1 -1
  1477. package/src/components/drop-indicator.ts +1 -1
  1478. package/src/components/edgeless-line-styles-panel.ts +1 -1
  1479. package/src/components/edgeless-line-width-panel.ts +1 -1
  1480. package/src/components/edgeless-shape-color-picker.ts +1 -1
  1481. package/src/components/embed-card-modal.ts +1 -1
  1482. package/src/components/filterable-list.ts +1 -1
  1483. package/src/components/highlight-dropdown-menu.ts +1 -1
  1484. package/src/components/hover.ts +1 -1
  1485. package/src/components/icon-button.ts +1 -1
  1486. package/src/components/icons.ts +1 -1
  1487. package/src/components/link-preview.ts +1 -1
  1488. package/src/components/linked-doc-title.ts +1 -1
  1489. package/src/components/notification.ts +1 -1
  1490. package/src/components/open-doc-dropdown-menu.ts +1 -1
  1491. package/src/components/peek.ts +1 -1
  1492. package/src/components/portal.ts +1 -1
  1493. package/src/components/resource.ts +1 -1
  1494. package/src/components/size-dropdown-menu.ts +1 -1
  1495. package/src/components/smooth-corner.ts +1 -1
  1496. package/src/components/toast.ts +1 -1
  1497. package/src/components/toggle-button.ts +1 -1
  1498. package/src/components/toggle-switch.ts +1 -1
  1499. package/src/components/toolbar.ts +1 -1
  1500. package/src/components/tooltip-content-with-shortcut.ts +1 -1
  1501. package/src/components/view-dropdown-menu.ts +1 -1
  1502. package/src/data-view/effects.ts +1 -1
  1503. package/src/data-view/index.ts +1 -1
  1504. package/src/effects.ts +34 -34
  1505. package/src/ext-loader/index.ts +1 -1
  1506. package/src/extensions/store.ts +83 -83
  1507. package/src/extensions/view.ts +143 -143
  1508. package/src/foundation/clipboard.ts +1 -1
  1509. package/src/foundation/store.ts +1 -1
  1510. package/src/foundation/view.ts +1 -1
  1511. package/src/fragments/adapter-panel/index.ts +1 -1
  1512. package/src/fragments/adapter-panel/view.ts +1 -1
  1513. package/src/fragments/doc-title/index.ts +1 -1
  1514. package/src/fragments/doc-title/view.ts +1 -1
  1515. package/src/fragments/frame-panel/index.ts +1 -1
  1516. package/src/fragments/frame-panel/view.ts +1 -1
  1517. package/src/fragments/outline/index.ts +1 -1
  1518. package/src/fragments/outline/view.ts +1 -1
  1519. package/src/gfx/brush/index.ts +1 -1
  1520. package/src/gfx/brush/store.ts +1 -1
  1521. package/src/gfx/brush/view.ts +1 -1
  1522. package/src/gfx/connector/index.ts +1 -1
  1523. package/src/gfx/connector/store.ts +1 -1
  1524. package/src/gfx/connector/view.ts +1 -1
  1525. package/src/gfx/group/index.ts +1 -1
  1526. package/src/gfx/group/store.ts +1 -1
  1527. package/src/gfx/group/view.ts +1 -1
  1528. package/src/gfx/link/index.ts +1 -1
  1529. package/src/gfx/link/view.ts +1 -1
  1530. package/src/gfx/mindmap/index.ts +1 -1
  1531. package/src/gfx/mindmap/store.ts +1 -1
  1532. package/src/gfx/mindmap/view.ts +1 -1
  1533. package/src/gfx/note/index.ts +1 -1
  1534. package/src/gfx/note/view.ts +1 -1
  1535. package/src/gfx/pointer/index.ts +1 -1
  1536. package/src/gfx/pointer/view.ts +1 -1
  1537. package/src/gfx/shape/index.ts +1 -1
  1538. package/src/gfx/shape/store.ts +1 -1
  1539. package/src/gfx/shape/view.ts +1 -1
  1540. package/src/gfx/template/index.ts +1 -1
  1541. package/src/gfx/template/view.ts +1 -1
  1542. package/src/gfx/text/index.ts +1 -1
  1543. package/src/gfx/text/store.ts +1 -1
  1544. package/src/gfx/text/view.ts +1 -1
  1545. package/src/gfx/turbo-renderer.ts +1 -1
  1546. package/src/global/di.ts +1 -1
  1547. package/src/global/disposable.ts +1 -1
  1548. package/src/global/env.ts +1 -1
  1549. package/src/global/exceptions.ts +1 -1
  1550. package/src/global/gfx.ts +1 -1
  1551. package/src/global/index.ts +1 -1
  1552. package/src/global/lit.ts +1 -1
  1553. package/src/global/types.ts +1 -1
  1554. package/src/global/utils.ts +1 -1
  1555. package/src/inlines/comment/index.ts +1 -1
  1556. package/src/inlines/footnote/index.ts +1 -1
  1557. package/src/inlines/footnote/store.ts +1 -1
  1558. package/src/inlines/footnote/view.ts +1 -1
  1559. package/src/inlines/latex/index.ts +1 -1
  1560. package/src/inlines/latex/store.ts +1 -1
  1561. package/src/inlines/latex/view.ts +1 -1
  1562. package/src/inlines/link/index.ts +1 -1
  1563. package/src/inlines/link/store.ts +1 -1
  1564. package/src/inlines/link/view.ts +1 -1
  1565. package/src/inlines/mention/index.ts +1 -1
  1566. package/src/inlines/mention/view.ts +1 -1
  1567. package/src/inlines/preset/index.ts +1 -1
  1568. package/src/inlines/preset/store.ts +1 -1
  1569. package/src/inlines/preset/view.ts +1 -1
  1570. package/src/inlines/reference/index.ts +1 -1
  1571. package/src/inlines/reference/store.ts +1 -1
  1572. package/src/inlines/reference/view.ts +1 -1
  1573. package/src/model/index.ts +1 -1
  1574. package/src/rich-text/effects.ts +1 -1
  1575. package/src/rich-text/index.ts +1 -1
  1576. package/src/schemas.ts +78 -78
  1577. package/src/shared/adapters.ts +1 -1
  1578. package/src/shared/commands.ts +1 -1
  1579. package/src/shared/consts.ts +1 -1
  1580. package/src/shared/selection.ts +1 -1
  1581. package/src/shared/services.ts +1 -1
  1582. package/src/shared/styles.ts +1 -1
  1583. package/src/shared/theme.ts +1 -1
  1584. package/src/shared/types.ts +1 -1
  1585. package/src/shared/utils.ts +1 -1
  1586. package/src/std/effects.ts +1 -1
  1587. package/src/std/gfx.ts +1 -1
  1588. package/src/std/index.ts +1 -1
  1589. package/src/std/inline.ts +1 -1
  1590. package/src/store/index.ts +3 -3
  1591. package/src/store/test.ts +1 -1
  1592. package/src/sync/index.ts +1 -1
  1593. package/src/widgets/drag-handle/index.ts +1 -1
  1594. package/src/widgets/drag-handle/view.ts +1 -1
  1595. package/src/widgets/edgeless-auto-connect/index.ts +1 -1
  1596. package/src/widgets/edgeless-auto-connect/view.ts +1 -1
  1597. package/src/widgets/edgeless-dragging-area/index.ts +1 -1
  1598. package/src/widgets/edgeless-dragging-area/view.ts +1 -1
  1599. package/src/widgets/edgeless-selected-rect/index.ts +1 -1
  1600. package/src/widgets/edgeless-selected-rect/view.ts +1 -1
  1601. package/src/widgets/edgeless-toolbar/index.ts +1 -1
  1602. package/src/widgets/edgeless-toolbar/view.ts +1 -1
  1603. package/src/widgets/edgeless-zoom-toolbar/index.ts +1 -1
  1604. package/src/widgets/edgeless-zoom-toolbar/view.ts +1 -1
  1605. package/src/widgets/frame-title/index.ts +1 -1
  1606. package/src/widgets/frame-title/view.ts +1 -1
  1607. package/src/widgets/keyboard-toolbar/index.ts +1 -1
  1608. package/src/widgets/keyboard-toolbar/view.ts +1 -1
  1609. package/src/widgets/linked-doc/index.ts +1 -1
  1610. package/src/widgets/linked-doc/view.ts +1 -1
  1611. package/src/widgets/note-slicer/index.ts +1 -1
  1612. package/src/widgets/note-slicer/view.ts +1 -1
  1613. package/src/widgets/page-dragging-area/index.ts +1 -1
  1614. package/src/widgets/page-dragging-area/view.ts +1 -1
  1615. package/src/widgets/remote-selection/index.ts +1 -1
  1616. package/src/widgets/remote-selection/view.ts +1 -1
  1617. package/src/widgets/scroll-anchoring/index.ts +1 -1
  1618. package/src/widgets/scroll-anchoring/view.ts +1 -1
  1619. package/src/widgets/slash-menu/index.ts +1 -1
  1620. package/src/widgets/slash-menu/view.ts +1 -1
  1621. package/src/widgets/toolbar/index.ts +1 -1
  1622. package/src/widgets/toolbar/view.ts +1 -1
  1623. package/src/widgets/viewport-overlay/index.ts +1 -1
  1624. package/src/widgets/viewport-overlay/view.ts +1 -1
@@ -1,1213 +1,1213 @@
1
- import {
2
- type RoughCanvas,
3
- ToolOverlay,
4
- } from '../../affine-block-surface/index.js';
5
- import { ShapeElementModel, ShapeType } from '../../affine-model/index.js';
6
- import {
7
- Bound,
8
- type BezierCurveParameters,
9
- getBezierCurveBoundingBox,
10
- } from '../../global/gfx/index.js';
11
- import type { GfxController } from '../../std/gfx/index.js';
12
-
13
- // ─── Visual constants ───────────────────────────────────────────────────────
14
-
15
- /** Radius of a normal vertex handle (screen pixels, divided by zoom). */
16
- const VERTEX_HANDLE_RADIUS = 5;
17
-
18
- /** Radius of a hovered vertex handle (screen pixels, divided by zoom). */
19
- const VERTEX_HANDLE_HOVER_RADIUS = 7;
20
-
21
- /** Radius of a dragged vertex handle (screen pixels, divided by zoom). */
22
- const VERTEX_HANDLE_ACTIVE_RADIUS = 8;
23
-
24
- /** Hit-test distance to consider the cursor "over" a vertex (screen px). */
25
- const VERTEX_HIT_DISTANCE = 10;
26
-
27
- /** Snap distance in model coordinates for coordinate alignment guides. */
28
- const SNAP_GUIDE_DISTANCE = 6;
29
-
30
- /** Color for default vertex handles. */
31
- const HANDLE_FILL_COLOR = '#ffffff';
32
-
33
- /** Color for hovered vertex handles. */
34
- const HANDLE_HOVER_FILL_COLOR = '#d0ebff';
35
-
36
- /** Color for actively dragged vertex handles. */
37
- const HANDLE_ACTIVE_FILL_COLOR = '#339af0';
38
-
39
- /** Snap guide line color. */
40
- const SNAP_GUIDE_COLOR = '#f06595';
41
-
42
- /** Edge midpoint handle radius. */
43
- const MIDPOINT_HANDLE_RADIUS = 3.5;
44
-
45
- /** Hovered edge midpoint handle radius. */
46
- const MIDPOINT_HANDLE_HOVER_RADIUS = 5;
47
-
48
- /** Color for edge midpoint handles. */
49
- const MIDPOINT_FILL_COLOR = '#e9ecef';
50
-
51
- /** Color for hovered edge midpoint handles. */
52
- const MIDPOINT_HOVER_FILL_COLOR = '#d0ebff';
53
-
54
- /** Hit-test distance for edge midpoint handles (screen px). */
55
- const MIDPOINT_HIT_DISTANCE = 10;
56
-
57
- /** Bezier control handle radius. */
58
- const BEZIER_HANDLE_RADIUS = 4;
59
-
60
- /** Bezier control handle color. */
61
- const BEZIER_HANDLE_COLOR = '#e64980';
62
-
63
- /** Bezier control line color. */
64
- const BEZIER_LINE_COLOR = '#e64980';
65
-
66
- // ─── Overlay class ──────────────────────────────────────────────────────────
67
-
68
- /**
69
- * Overlay rendered on top of a selected polygon shape that provides:
70
- *
71
- * - Vertex handle circles at each polygon vertex (with hover/active states)
72
- * - Edge midpoint indicators
73
- * - Coordinate snapping guides while dragging a vertex
74
- * - Real-time polygon path update feedback during vertex drag
75
- *
76
- * This overlay works alongside the standard bounding-box resize handles
77
- * provided by the framework. Vertex editing is activated when the user
78
- * double-clicks a selected polygon (entering editing mode) or when a
79
- * polygon is first selected (non-editing mode shows smaller handles).
80
- */
81
- export class PolygonVertexEditingOverlay extends ToolOverlay {
82
- // ── Linked polygon element ──────────────────────────────────────────
83
-
84
- /** ID of the polygon element this overlay is attached to. */
85
- private _elementId: string | null = null;
86
-
87
- // ── Interaction state ───────────────────────────────────────────────
88
-
89
- /** Index of the currently hovered vertex (-1 = none). */
90
- hoveredVertexIndex = -1;
91
-
92
- /** Index of the currently hovered edge midpoint (-1 = none). */
93
- hoveredMidpointIndex = -1;
94
-
95
- /** Index of the vertex currently being dragged (-1 = none). */
96
- activeVertexIndex = -1;
97
-
98
- /** Whether vertex editing mode is enabled (double-click to enter). */
99
- isEditing = false;
100
-
101
- /** Current cursor position in model coordinates (for hover testing). */
102
- cursorModelPos: [number, number] | null = null;
103
-
104
- /** Index of the vertex whose Bezier control handle is being dragged (-1 = none). */
105
- activeBezierHandleIndex = -1;
106
-
107
- /** Which handle of the active bezier vertex is being dragged (0=cp1, 1=cp2, -1=none). */
108
- activeBezierHandleType: number = -1;
109
-
110
- // ── Snap guide state ────────────────────────────────────────────────
111
-
112
- /** Horizontal snap guide Y coordinate (null = hidden). */
113
- snapGuideY: number | null = null;
114
-
115
- /** Vertical snap guide X coordinate (null = hidden). */
116
- snapGuideX: number | null = null;
117
-
118
- constructor(gfx: GfxController) {
119
- super(gfx);
120
- }
121
-
122
- /** Attach this overlay to a specific polygon element. */
123
- setElement(elementId: string) {
124
- this._elementId = elementId;
125
- }
126
-
127
- /** Get the linked ShapeElementModel if it's a polygon. */
128
- private _getPolygonModel(): ShapeElementModel | null {
129
- if (!this._elementId) return null;
130
- const el = this.gfx.getElementById(this._elementId);
131
- if (
132
- el instanceof ShapeElementModel &&
133
- el.shapeType === ShapeType.Polygon
134
- ) {
135
- return el;
136
- }
137
- return null;
138
- }
139
-
140
- /**
141
- * Convert a normalized [0-1] vertex to absolute model coordinates
142
- * based on the polygon's bounding box.
143
- */
144
- private _toAbsolute(
145
- nv: number[],
146
- bound: Bound
147
- ): [number, number] {
148
- return [bound.x + nv[0] * bound.w, bound.y + nv[1] * bound.h];
149
- }
150
-
151
- /**
152
- * Test if a model-coordinate point is within hit distance of a vertex.
153
- */
154
- hitTestVertex(
155
- modelX: number,
156
- modelY: number
157
- ): number {
158
- const model = this._getPolygonModel();
159
- if (!model || !model.vertices) return -1;
160
-
161
- const bound = Bound.deserialize(model.xywh);
162
- const zoom = this.gfx.viewport.zoom;
163
- const hitDist = VERTEX_HIT_DISTANCE / zoom;
164
-
165
- // Inverse-rotate incoming world coordinates into polygon's local space
166
- let localX = modelX;
167
- let localY = modelY;
168
- const rotate = model.rotate ?? 0;
169
- if (rotate) {
170
- const cx = bound.x + bound.w / 2;
171
- const cy = bound.y + bound.h / 2;
172
- const rad = -(rotate * Math.PI) / 180; // negative for inverse rotation
173
- const cos = Math.cos(rad);
174
- const sin = Math.sin(rad);
175
- const dx = modelX - cx;
176
- const dy = modelY - cy;
177
- localX = cx + dx * cos - dy * sin;
178
- localY = cy + dx * sin + dy * cos;
179
- }
180
-
181
- for (let i = 0; i < model.vertices.length; i++) {
182
- const [ax, ay] = this._toAbsolute(model.vertices[i], bound);
183
- const dx = localX - ax;
184
- const dy = localY - ay;
185
- if (Math.sqrt(dx * dx + dy * dy) < hitDist) {
186
- return i;
187
- }
188
- }
189
- return -1;
190
- }
191
-
192
- /**
193
- * Move a vertex to a new absolute position, computing snap guides
194
- * against other vertices. Updates the model's normalized vertices
195
- * and bounding box.
196
- */
197
- moveVertex(
198
- vertexIndex: number,
199
- modelX: number,
200
- modelY: number
201
- ): void {
202
- const model = this._getPolygonModel();
203
- if (!model || !model.vertices) return;
204
-
205
- const bound = Bound.deserialize(model.xywh);
206
- const zoom = this.gfx.viewport.zoom;
207
- const snapDist = SNAP_GUIDE_DISTANCE / zoom;
208
-
209
- // Inverse-rotate mouse position from world space to local (unrotated) space
210
- const rotate = model.rotate ?? 0;
211
- let localX = modelX;
212
- let localY = modelY;
213
- if (rotate) {
214
- const cx = bound.x + bound.w / 2;
215
- const cy = bound.y + bound.h / 2;
216
- const rad = (-rotate * Math.PI) / 180; // negative for inverse
217
- const dx = modelX - cx;
218
- const dy = modelY - cy;
219
- localX = cx + dx * Math.cos(rad) - dy * Math.sin(rad);
220
- localY = cy + dx * Math.sin(rad) + dy * Math.cos(rad);
221
- }
222
-
223
- // Collect local-space absolute positions of all other vertices for snapping
224
- const otherAbsolute: [number, number][] = [];
225
- for (let i = 0; i < model.vertices.length; i++) {
226
- if (i === vertexIndex) continue;
227
- otherAbsolute.push(this._toAbsolute(model.vertices[i], bound));
228
- }
229
-
230
- // Attempt coordinate snapping in local (unrotated) space
231
- let snappedX = localX;
232
- let snappedY = localY;
233
- this.snapGuideX = null;
234
- this.snapGuideY = null;
235
-
236
- for (const [ox, oy] of otherAbsolute) {
237
- if (Math.abs(localX - ox) < snapDist) {
238
- snappedX = ox;
239
- this.snapGuideX = ox;
240
- }
241
- if (Math.abs(localY - oy) < snapDist) {
242
- snappedY = oy;
243
- this.snapGuideY = oy;
244
- }
245
- }
246
-
247
- // Compute new absolute vertices array
248
- const newAbsVertices: [number, number][] = model.vertices.map(
249
- (v, i) =>
250
- i === vertexIndex
251
- ? ([snappedX, snappedY] as [number, number])
252
- : (this._toAbsolute(v, bound) as [number, number])
253
- );
254
-
255
- // Re-compute bounding box from new absolute positions
256
- let minX = Infinity,
257
- minY = Infinity,
258
- maxX = -Infinity,
259
- maxY = -Infinity;
260
- for (const [vx, vy] of newAbsVertices) {
261
- if (vx < minX) minX = vx;
262
- if (vy < minY) minY = vy;
263
- if (vx > maxX) maxX = vx;
264
- if (vy > maxY) maxY = vy;
265
- }
266
-
267
- // Expand bounds to encompass Bezier geometry (control handles + arc curves)
268
- const smoothFlags = model.smoothFlags;
269
- const controlPoints = model.controlPoints;
270
- const count = model.vertices.length;
271
-
272
- if (smoothFlags) {
273
- for (let i = 0; i < count; i++) {
274
- const next = (i + 1) % count;
275
- const currSmooth = smoothFlags[i] ?? false;
276
- const nextSmooth = smoothFlags[next] ?? false;
277
-
278
- if (!currSmooth && !nextSmooth) continue;
279
-
280
- const [cx, cy] = newAbsVertices[i];
281
- const [nx, ny] = newAbsVertices[next];
282
-
283
- // Outgoing control point of current vertex
284
- let cp1x: number, cp1y: number;
285
- const customCurr = controlPoints?.[i];
286
- if (currSmooth && customCurr) {
287
- cp1x = customCurr[2] * bound.w + bound.x;
288
- cp1y = customCurr[3] * bound.h + bound.y;
289
- } else if (currSmooth) {
290
- cp1x = cx + (nx - cx) / 3;
291
- cp1y = cy + (ny - cy) / 3;
292
- } else {
293
- cp1x = cx;
294
- cp1y = cy;
295
- }
296
-
297
- // Incoming control point of next vertex
298
- let cp2x: number, cp2y: number;
299
- const customNext = controlPoints?.[next];
300
- if (nextSmooth && customNext) {
301
- cp2x = customNext[0] * bound.w + bound.x;
302
- cp2y = customNext[1] * bound.h + bound.y;
303
- } else if (nextSmooth) {
304
- cp2x = nx + (cx - nx) / 3;
305
- cp2y = ny + (cy - ny) / 3;
306
- } else {
307
- cp2x = nx;
308
- cp2y = ny;
309
- }
310
-
311
- // Include control handle positions
312
- if (cp1x < minX) minX = cp1x;
313
- if (cp1y < minY) minY = cp1y;
314
- if (cp1x > maxX) maxX = cp1x;
315
- if (cp1y > maxY) maxY = cp1y;
316
- if (cp2x < minX) minX = cp2x;
317
- if (cp2y < minY) minY = cp2y;
318
- if (cp2x > maxX) maxX = cp2x;
319
- if (cp2y > maxY) maxY = cp2y;
320
-
321
- // Use getBezierCurveBoundingBox for tight arc bounds
322
- const bezierParams: BezierCurveParameters = [
323
- [cx, cy],
324
- [cp1x, cp1y],
325
- [cp2x, cp2y],
326
- [nx, ny],
327
- ];
328
- const arcBound = getBezierCurveBoundingBox(bezierParams);
329
- if (arcBound.x < minX) minX = arcBound.x;
330
- if (arcBound.y < minY) minY = arcBound.y;
331
- if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
332
- if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
333
- }
334
- }
335
-
336
- const w = Math.max(maxX - minX, 1);
337
- const h = Math.max(maxY - minY, 1);
338
-
339
- // Re-normalize vertices to new bounding box
340
- const normalized = newAbsVertices.map(([vx, vy]) => [
341
- (vx - minX) / w,
342
- (vy - minY) / h,
343
- ]);
344
-
345
- const newBound = new Bound(minX, minY, w, h);
346
-
347
- // Update model
348
- model.xywh = newBound.serialize();
349
- model.vertices = normalized;
350
-
351
- // Re-normalize control points to new bounding box
352
- if (controlPoints) {
353
- const normalizedCPs = controlPoints.map(cp => {
354
- if (!cp) return null;
355
- const absCp1x = cp[0] * bound.w + bound.x;
356
- const absCp1y = cp[1] * bound.h + bound.y;
357
- const absCp2x = cp[2] * bound.w + bound.x;
358
- const absCp2y = cp[3] * bound.h + bound.y;
359
- return [
360
- (absCp1x - minX) / w,
361
- (absCp1y - minY) / h,
362
- (absCp2x - minX) / w,
363
- (absCp2y - minY) / h,
364
- ];
365
- });
366
- model.controlPoints = normalizedCPs;
367
- }
368
- }
369
-
370
- /** Clear snap guides (call on drag end). */
371
- clearSnapGuides() {
372
- this.snapGuideX = null;
373
- this.snapGuideY = null;
374
- }
375
-
376
- /**
377
- * Test if a model-coordinate point is within hit distance of an edge midpoint.
378
- * Returns the edge index (i.e., the midpoint between vertex i and vertex i+1),
379
- * or -1 if not near any midpoint.
380
- */
381
- hitTestMidpoint(
382
- modelX: number,
383
- modelY: number
384
- ): number {
385
- const model = this._getPolygonModel();
386
- if (!model || !model.vertices) return -1;
387
-
388
- const bound = Bound.deserialize(model.xywh);
389
- const zoom = this.gfx.viewport.zoom;
390
- const hitDist = MIDPOINT_HIT_DISTANCE / zoom;
391
-
392
- // Inverse-rotate incoming world coordinates into polygon's local space
393
- let localX = modelX;
394
- let localY = modelY;
395
- const rotate = model.rotate ?? 0;
396
- if (rotate) {
397
- const cx = bound.x + bound.w / 2;
398
- const cy = bound.y + bound.h / 2;
399
- const rad = -(rotate * Math.PI) / 180; // negative for inverse rotation
400
- const cos = Math.cos(rad);
401
- const sin = Math.sin(rad);
402
- const dx = modelX - cx;
403
- const dy = modelY - cy;
404
- localX = cx + dx * cos - dy * sin;
405
- localY = cy + dx * sin + dy * cos;
406
- }
407
-
408
- for (let i = 0; i < model.vertices.length; i++) {
409
- const [ax, ay] = this._toAbsolute(model.vertices[i], bound);
410
- const nextIdx = (i + 1) % model.vertices.length;
411
- const [bx, by] = this._toAbsolute(model.vertices[nextIdx], bound);
412
- const mx = (ax + bx) / 2;
413
- const my = (ay + by) / 2;
414
-
415
- const dx = localX - mx;
416
- const dy = localY - my;
417
- if (Math.sqrt(dx * dx + dy * dy) < hitDist) {
418
- return i;
419
- }
420
- }
421
- return -1;
422
- }
423
-
424
- /**
425
- * Test if a model-coordinate point hits a bezier control handle.
426
- * Returns { vertexIndex, handleIndex: 0=cp1, 1=cp2 } or null.
427
- */
428
- hitTestBezierHandle(
429
- modelX: number,
430
- modelY: number
431
- ): { vertexIndex: number; handleIndex: number } | null {
432
- const model = this._getPolygonModel();
433
- if (!model || !model.vertices || !model.smoothFlags) return null;
434
-
435
- const bound = Bound.deserialize(model.xywh);
436
- const zoom = this.gfx.viewport.zoom;
437
- const hitDist = BEZIER_HANDLE_RADIUS * 2 / zoom;
438
-
439
- // Inverse-rotate incoming world coordinates into polygon's local space
440
- let localX = modelX;
441
- let localY = modelY;
442
- const rotate = model.rotate ?? 0;
443
- if (rotate) {
444
- const cx = bound.x + bound.w / 2;
445
- const cy = bound.y + bound.h / 2;
446
- const rad = (-rotate * Math.PI) / 180;
447
- const cos = Math.cos(rad);
448
- const sin = Math.sin(rad);
449
- const dx = modelX - cx;
450
- const dy = modelY - cy;
451
- localX = cx + dx * cos - dy * sin;
452
- localY = cy + dx * sin + dy * cos;
453
- }
454
-
455
- for (let i = 0; i < model.vertices.length; i++) {
456
- if (!model.smoothFlags[i]) continue;
457
- const cp = this.getBezierControlPoints(i);
458
- if (!cp) continue;
459
-
460
- // Check cp1
461
- const dx1 = localX - cp.cp1[0];
462
- const dy1 = localY - cp.cp1[1];
463
- if (Math.sqrt(dx1 * dx1 + dy1 * dy1) < hitDist) {
464
- return { vertexIndex: i, handleIndex: 0 };
465
- }
466
-
467
- // Check cp2
468
- const dx2 = localX - cp.cp2[0];
469
- const dy2 = localY - cp.cp2[1];
470
- if (Math.sqrt(dx2 * dx2 + dy2 * dy2) < hitDist) {
471
- return { vertexIndex: i, handleIndex: 1 };
472
- }
473
- }
474
- return null;
475
- }
476
-
477
- /**
478
- * Move a bezier control handle to an absolute model position.
479
- * Stores the result as normalized coordinates in model.controlPoints.
480
- */
481
- moveBezierHandle(
482
- vertexIndex: number,
483
- handleIndex: number,
484
- modelX: number,
485
- modelY: number
486
- ): void {
487
- const model = this._getPolygonModel();
488
- if (!model || !model.vertices) return;
489
-
490
- const bound = Bound.deserialize(model.xywh);
491
- const count = model.vertices.length;
492
-
493
- // Inverse-rotate mouse position from world space to local (unrotated) space
494
- const rotate = model.rotate ?? 0;
495
- let localX = modelX;
496
- let localY = modelY;
497
- if (rotate) {
498
- const cx = bound.x + bound.w / 2;
499
- const cy = bound.y + bound.h / 2;
500
- const rad = -(rotate * Math.PI) / 180;
501
- const cos = Math.cos(rad);
502
- const sin = Math.sin(rad);
503
- const dx = modelX - cx;
504
- const dy = modelY - cy;
505
- localX = cx + dx * cos - dy * sin;
506
- localY = cy + dx * sin + dy * cos;
507
- }
508
-
509
- // Initialize controlPoints array if null
510
- let controlPoints: (number[] | null)[] = model.controlPoints
511
- ? [...model.controlPoints]
512
- : new Array(count).fill(null);
513
-
514
- // Ensure array is the right length
515
- while (controlPoints.length < count) controlPoints.push(null);
516
-
517
- // Auto-compute current control points for this vertex if not set
518
- if (!controlPoints[vertexIndex]) {
519
- const cp = this.getBezierControlPoints(vertexIndex);
520
- if (!cp) return;
521
- // Store as normalized [cp1x, cp1y, cp2x, cp2y]
522
- controlPoints[vertexIndex] = [
523
- (cp.cp1[0] - bound.x) / bound.w,
524
- (cp.cp1[1] - bound.y) / bound.h,
525
- (cp.cp2[0] - bound.x) / bound.w,
526
- (cp.cp2[1] - bound.y) / bound.h,
527
- ];
528
- }
529
-
530
- // Convert absolute position to normalized coordinates (in current bound)
531
- const normX = (localX - bound.x) / bound.w;
532
- const normY = (localY - bound.y) / bound.h;
533
-
534
- // Update the specific handle
535
- const entry = [...controlPoints[vertexIndex]!];
536
- if (handleIndex === 0) {
537
- entry[0] = normX;
538
- entry[1] = normY;
539
- } else {
540
- entry[2] = normX;
541
- entry[3] = normY;
542
- }
543
- controlPoints[vertexIndex] = entry;
544
-
545
- // ── Re-normalize: expand bounding box to encompass all Bezier geometry ──
546
- // Collect all absolute vertex positions
547
- const absVertices: [number, number][] = model.vertices.map(
548
- v => [bound.x + v[0] * bound.w, bound.y + v[1] * bound.h] as [number, number]
549
- );
550
-
551
- let minX = Infinity,
552
- minY = Infinity,
553
- maxX = -Infinity,
554
- maxY = -Infinity;
555
-
556
- for (const [vx, vy] of absVertices) {
557
- if (vx < minX) minX = vx;
558
- if (vy < minY) minY = vy;
559
- if (vx > maxX) maxX = vx;
560
- if (vy > maxY) maxY = vy;
561
- }
562
-
563
- // Expand bounds using getBezierCurveBoundingBox for each Bezier edge
564
- const smoothFlags = model.smoothFlags;
565
- if (smoothFlags) {
566
- for (let i = 0; i < count; i++) {
567
- const next = (i + 1) % count;
568
- const currSmooth = smoothFlags[i] ?? false;
569
- const nextSmooth = smoothFlags[next] ?? false;
570
-
571
- if (!currSmooth && !nextSmooth) continue;
572
-
573
- const [cx, cy] = absVertices[i];
574
- const [nx, ny] = absVertices[next];
575
-
576
- // Outgoing control point of current vertex
577
- let cp1x: number, cp1y: number;
578
- const customCurr = controlPoints[i];
579
- if (currSmooth && customCurr) {
580
- cp1x = customCurr[2] * bound.w + bound.x;
581
- cp1y = customCurr[3] * bound.h + bound.y;
582
- } else if (currSmooth) {
583
- cp1x = cx + (nx - cx) / 3;
584
- cp1y = cy + (ny - cy) / 3;
585
- } else {
586
- cp1x = cx;
587
- cp1y = cy;
588
- }
589
-
590
- // Incoming control point of next vertex
591
- let cp2x: number, cp2y: number;
592
- const customNext = controlPoints[next];
593
- if (nextSmooth && customNext) {
594
- cp2x = customNext[0] * bound.w + bound.x;
595
- cp2y = customNext[1] * bound.h + bound.y;
596
- } else if (nextSmooth) {
597
- cp2x = nx + (cx - nx) / 3;
598
- cp2y = ny + (cy - ny) / 3;
599
- } else {
600
- cp2x = nx;
601
- cp2y = ny;
602
- }
603
-
604
- // Include control handle positions
605
- if (cp1x < minX) minX = cp1x;
606
- if (cp1y < minY) minY = cp1y;
607
- if (cp1x > maxX) maxX = cp1x;
608
- if (cp1y > maxY) maxY = cp1y;
609
- if (cp2x < minX) minX = cp2x;
610
- if (cp2y < minY) minY = cp2y;
611
- if (cp2x > maxX) maxX = cp2x;
612
- if (cp2y > maxY) maxY = cp2y;
613
-
614
- // Use getBezierCurveBoundingBox for tight arc bounds
615
- const bezierParams: BezierCurveParameters = [
616
- [cx, cy],
617
- [cp1x, cp1y],
618
- [cp2x, cp2y],
619
- [nx, ny],
620
- ];
621
- const arcBound = getBezierCurveBoundingBox(bezierParams);
622
- if (arcBound.x < minX) minX = arcBound.x;
623
- if (arcBound.y < minY) minY = arcBound.y;
624
- if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
625
- if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
626
- }
627
- }
628
-
629
- const newW = Math.max(maxX - minX, 1);
630
- const newH = Math.max(maxY - minY, 1);
631
-
632
- // Re-normalize vertices to new bounding box
633
- const normalizedVerts = absVertices.map(([vx, vy]) => [
634
- (vx - minX) / newW,
635
- (vy - minY) / newH,
636
- ]);
637
-
638
- // Re-normalize control points to new bounding box
639
- const normalizedCPs = controlPoints.map(cp => {
640
- if (!cp) return null;
641
- const absCp1x = cp[0] * bound.w + bound.x;
642
- const absCp1y = cp[1] * bound.h + bound.y;
643
- const absCp2x = cp[2] * bound.w + bound.x;
644
- const absCp2y = cp[3] * bound.h + bound.y;
645
- return [
646
- (absCp1x - minX) / newW,
647
- (absCp1y - minY) / newH,
648
- (absCp2x - minX) / newW,
649
- (absCp2y - minY) / newH,
650
- ];
651
- });
652
-
653
- const newBound = new Bound(minX, minY, newW, newH);
654
- model.xywh = newBound.serialize();
655
- model.vertices = normalizedVerts;
656
- model.controlPoints = normalizedCPs;
657
- }
658
-
659
- /**
660
- * Insert a new vertex at the midpoint of edge `edgeIndex` (between vertex
661
- * edgeIndex and edgeIndex+1). Returns the index of the newly inserted vertex.
662
- */
663
- insertVertexAtMidpoint(edgeIndex: number): number {
664
- const model = this._getPolygonModel();
665
- if (!model || !model.vertices) return -1;
666
-
667
- const vertices = [...model.vertices];
668
- const nextIdx = (edgeIndex + 1) % vertices.length;
669
-
670
- // Compute the midpoint in normalized space
671
- const midNorm = [
672
- (vertices[edgeIndex][0] + vertices[nextIdx][0]) / 2,
673
- (vertices[edgeIndex][1] + vertices[nextIdx][1]) / 2,
674
- ];
675
-
676
- // Insert after edgeIndex
677
- const insertIdx = edgeIndex + 1;
678
- vertices.splice(insertIdx, 0, midNorm);
679
-
680
- // Update smoothFlags if present
681
- if (model.smoothFlags) {
682
- const flags = [...model.smoothFlags];
683
- flags.splice(insertIdx, 0, false);
684
- model.smoothFlags = flags;
685
- }
686
-
687
- // Update controlPoints if present
688
- if (model.controlPoints) {
689
- const cps = [...model.controlPoints];
690
- cps.splice(insertIdx, 0, null);
691
- model.controlPoints = cps;
692
- }
693
-
694
- model.vertices = vertices;
695
- return insertIdx;
696
- }
697
-
698
- /**
699
- * Delete the vertex at the given index. Returns true if successful.
700
- * Requires at least 3 vertices to remain after deletion.
701
- */
702
- deleteVertex(vertexIndex: number): boolean {
703
- const model = this._getPolygonModel();
704
- if (!model || !model.vertices) return false;
705
- if (model.vertices.length <= 3) return false; // minimum polygon is a triangle
706
-
707
- const vertices = [...model.vertices];
708
- vertices.splice(vertexIndex, 1);
709
-
710
- // Update smoothFlags if present
711
- if (model.smoothFlags) {
712
- const flags = [...model.smoothFlags];
713
- flags.splice(vertexIndex, 1);
714
- model.smoothFlags = flags;
715
- }
716
-
717
- // Update controlPoints if present
718
- if (model.controlPoints) {
719
- const cps = [...model.controlPoints];
720
- cps.splice(vertexIndex, 1);
721
- model.controlPoints = cps;
722
- }
723
-
724
- // Re-compute bounding box from remaining vertices
725
- const bound = Bound.deserialize(model.xywh);
726
- const absVertices: [number, number][] = vertices.map(
727
- v => this._toAbsolute(v, bound) as [number, number]
728
- );
729
-
730
- let minX = Infinity,
731
- minY = Infinity,
732
- maxX = -Infinity,
733
- maxY = -Infinity;
734
- for (const [vx, vy] of absVertices) {
735
- if (vx < minX) minX = vx;
736
- if (vy < minY) minY = vy;
737
- if (vx > maxX) maxX = vx;
738
- if (vy > maxY) maxY = vy;
739
- }
740
-
741
- // Expand bounds to encompass Bezier geometry after deletion
742
- const updatedFlags = model.smoothFlags;
743
- const updatedCPs = model.controlPoints;
744
- if (updatedFlags) {
745
- const cnt = vertices.length;
746
- for (let i = 0; i < cnt; i++) {
747
- const next = (i + 1) % cnt;
748
- const currSmooth = updatedFlags[i] ?? false;
749
- const nextSmooth = updatedFlags[next] ?? false;
750
-
751
- if (!currSmooth && !nextSmooth) continue;
752
-
753
- const [cx, cy] = absVertices[i];
754
- const [nx, ny] = absVertices[next];
755
-
756
- let cp1x: number, cp1y: number;
757
- const customCurr = updatedCPs?.[i];
758
- if (currSmooth && customCurr) {
759
- cp1x = customCurr[2] * bound.w + bound.x;
760
- cp1y = customCurr[3] * bound.h + bound.y;
761
- } else if (currSmooth) {
762
- cp1x = cx + (nx - cx) / 3;
763
- cp1y = cy + (ny - cy) / 3;
764
- } else {
765
- cp1x = cx;
766
- cp1y = cy;
767
- }
768
-
769
- let cp2x: number, cp2y: number;
770
- const customNext = updatedCPs?.[next];
771
- if (nextSmooth && customNext) {
772
- cp2x = customNext[0] * bound.w + bound.x;
773
- cp2y = customNext[1] * bound.h + bound.y;
774
- } else if (nextSmooth) {
775
- cp2x = nx + (cx - nx) / 3;
776
- cp2y = ny + (cy - ny) / 3;
777
- } else {
778
- cp2x = nx;
779
- cp2y = ny;
780
- }
781
-
782
- if (cp1x < minX) minX = cp1x;
783
- if (cp1y < minY) minY = cp1y;
784
- if (cp1x > maxX) maxX = cp1x;
785
- if (cp1y > maxY) maxY = cp1y;
786
- if (cp2x < minX) minX = cp2x;
787
- if (cp2y < minY) minY = cp2y;
788
- if (cp2x > maxX) maxX = cp2x;
789
- if (cp2y > maxY) maxY = cp2y;
790
-
791
- const bezierParams: BezierCurveParameters = [
792
- [cx, cy],
793
- [cp1x, cp1y],
794
- [cp2x, cp2y],
795
- [nx, ny],
796
- ];
797
- const arcBound = getBezierCurveBoundingBox(bezierParams);
798
- if (arcBound.x < minX) minX = arcBound.x;
799
- if (arcBound.y < minY) minY = arcBound.y;
800
- if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
801
- if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
802
- }
803
- }
804
-
805
- const w = Math.max(maxX - minX, 1);
806
- const h = Math.max(maxY - minY, 1);
807
-
808
- const normalized = absVertices.map(([vx, vy]) => [
809
- (vx - minX) / w,
810
- (vy - minY) / h,
811
- ]);
812
-
813
- const newBound = new Bound(minX, minY, w, h);
814
- model.xywh = newBound.serialize();
815
- model.vertices = normalized;
816
-
817
- // Re-normalize control points to new bounding box
818
- if (updatedCPs) {
819
- const normalizedCPs = updatedCPs.map(cp => {
820
- if (!cp) return null;
821
- const absCp1x = cp[0] * bound.w + bound.x;
822
- const absCp1y = cp[1] * bound.h + bound.y;
823
- const absCp2x = cp[2] * bound.w + bound.x;
824
- const absCp2y = cp[3] * bound.h + bound.y;
825
- return [
826
- (absCp1x - minX) / w,
827
- (absCp1y - minY) / h,
828
- (absCp2x - minX) / w,
829
- (absCp2y - minY) / h,
830
- ];
831
- });
832
- model.controlPoints = normalizedCPs;
833
- }
834
-
835
- return true;
836
- }
837
-
838
- /**
839
- * Toggle smooth (Bezier) flag for a vertex. When smooth is true, the
840
- * edges adjacent to this vertex are rendered as Bezier curves with
841
- * automatically computed control points.
842
- */
843
- toggleVertexSmooth(vertexIndex: number): void {
844
- const model = this._getPolygonModel();
845
- if (!model || !model.vertices) return;
846
-
847
- const bound = Bound.deserialize(model.xywh);
848
- const count = model.vertices.length;
849
- let flags = model.smoothFlags ? [...model.smoothFlags] : new Array(count).fill(false);
850
-
851
- // Ensure flags array matches vertex count
852
- while (flags.length < count) flags.push(false);
853
- if (flags.length > count) flags = flags.slice(0, count);
854
-
855
- const wasSmooth = flags[vertexIndex];
856
- flags[vertexIndex] = !wasSmooth;
857
- model.smoothFlags = flags;
858
-
859
- // If toggling off, clear custom control points for this vertex
860
- let controlPoints: (number[] | null)[] = model.controlPoints
861
- ? [...model.controlPoints]
862
- : new Array(count).fill(null);
863
- while (controlPoints.length < count) controlPoints.push(null);
864
-
865
- if (wasSmooth) {
866
- controlPoints[vertexIndex] = null;
867
- }
868
-
869
- // ── Re-normalize: expand bounding box to encompass all Bezier geometry ──
870
- // We need to temporarily apply the new flags so getBezierControlPoints uses them
871
- // Instead, compute everything inline using the new flags
872
-
873
- // Collect all absolute vertex positions
874
- const absVertices: [number, number][] = model.vertices.map(
875
- v => [bound.x + v[0] * bound.w, bound.y + v[1] * bound.h] as [number, number]
876
- );
877
-
878
- let minX = Infinity,
879
- minY = Infinity,
880
- maxX = -Infinity,
881
- maxY = -Infinity;
882
-
883
- for (const [vx, vy] of absVertices) {
884
- if (vx < minX) minX = vx;
885
- if (vy < minY) minY = vy;
886
- if (vx > maxX) maxX = vx;
887
- if (vy > maxY) maxY = vy;
888
- }
889
-
890
- // Expand bounds using getBezierCurveBoundingBox for each Bezier edge
891
- for (let i = 0; i < count; i++) {
892
- const next = (i + 1) % count;
893
- const currSmooth = flags[i] ?? false;
894
- const nextSmooth = flags[next] ?? false;
895
-
896
- if (!currSmooth && !nextSmooth) continue;
897
-
898
- const [cx, cy] = absVertices[i];
899
- const [nx, ny] = absVertices[next];
900
-
901
- // Outgoing control point of current vertex (cp2 of its control points)
902
- let cp1x: number, cp1y: number;
903
- const customCurr = controlPoints[i];
904
- if (currSmooth && customCurr) {
905
- cp1x = customCurr[2] * bound.w + bound.x;
906
- cp1y = customCurr[3] * bound.h + bound.y;
907
- } else if (currSmooth) {
908
- cp1x = cx + (nx - cx) / 3;
909
- cp1y = cy + (ny - cy) / 3;
910
- } else {
911
- cp1x = cx;
912
- cp1y = cy;
913
- }
914
-
915
- // Incoming control point of next vertex (cp1 of its control points)
916
- let cp2x: number, cp2y: number;
917
- const customNext = controlPoints[next];
918
- if (nextSmooth && customNext) {
919
- cp2x = customNext[0] * bound.w + bound.x;
920
- cp2y = customNext[1] * bound.h + bound.y;
921
- } else if (nextSmooth) {
922
- cp2x = nx + (cx - nx) / 3;
923
- cp2y = ny + (cy - ny) / 3;
924
- } else {
925
- cp2x = nx;
926
- cp2y = ny;
927
- }
928
-
929
- // Include control handle positions
930
- if (cp1x < minX) minX = cp1x;
931
- if (cp1y < minY) minY = cp1y;
932
- if (cp1x > maxX) maxX = cp1x;
933
- if (cp1y > maxY) maxY = cp1y;
934
- if (cp2x < minX) minX = cp2x;
935
- if (cp2y < minY) minY = cp2y;
936
- if (cp2x > maxX) maxX = cp2x;
937
- if (cp2y > maxY) maxY = cp2y;
938
-
939
- // Use getBezierCurveBoundingBox for tight arc bounds
940
- const bezierParams: BezierCurveParameters = [
941
- [cx, cy],
942
- [cp1x, cp1y],
943
- [cp2x, cp2y],
944
- [nx, ny],
945
- ];
946
- const arcBound = getBezierCurveBoundingBox(bezierParams);
947
- if (arcBound.x < minX) minX = arcBound.x;
948
- if (arcBound.y < minY) minY = arcBound.y;
949
- if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
950
- if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
951
- }
952
-
953
- const newW = Math.max(maxX - minX, 1);
954
- const newH = Math.max(maxY - minY, 1);
955
-
956
- // Re-normalize vertices to new bounding box
957
- const normalizedVerts = absVertices.map(([vx, vy]) => [
958
- (vx - minX) / newW,
959
- (vy - minY) / newH,
960
- ]);
961
-
962
- // Re-normalize control points to new bounding box
963
- const normalizedCPs = controlPoints.map(cp => {
964
- if (!cp) return null;
965
- const absCp1x = cp[0] * bound.w + bound.x;
966
- const absCp1y = cp[1] * bound.h + bound.y;
967
- const absCp2x = cp[2] * bound.w + bound.x;
968
- const absCp2y = cp[3] * bound.h + bound.y;
969
- return [
970
- (absCp1x - minX) / newW,
971
- (absCp1y - minY) / newH,
972
- (absCp2x - minX) / newW,
973
- (absCp2y - minY) / newH,
974
- ];
975
- });
976
-
977
- const newBound = new Bound(minX, minY, newW, newH);
978
- model.xywh = newBound.serialize();
979
- model.vertices = normalizedVerts;
980
- model.controlPoints = normalizedCPs;
981
- }
982
-
983
- /**
984
- * Check if a vertex has Bezier smoothing enabled.
985
- */
986
- isVertexSmooth(vertexIndex: number): boolean {
987
- const model = this._getPolygonModel();
988
- if (!model || !model.smoothFlags) return false;
989
- return !!model.smoothFlags[vertexIndex];
990
- }
991
-
992
- /**
993
- * Get the computed Bezier control points for a smooth vertex.
994
- * Returns [cp1, cp2] where cp1 is the control point for the incoming edge
995
- * and cp2 is for the outgoing edge, both in absolute model coordinates.
996
- * Returns null if the vertex is not smooth.
997
- */
998
- getBezierControlPoints(
999
- vertexIndex: number
1000
- ): { cp1: [number, number]; cp2: [number, number] } | null {
1001
- const model = this._getPolygonModel();
1002
- if (!model || !model.vertices) return null;
1003
- if (!model.smoothFlags || !model.smoothFlags[vertexIndex]) return null;
1004
-
1005
- const bound = Bound.deserialize(model.xywh);
1006
-
1007
- // Check for custom control points first
1008
- const custom = model.controlPoints?.[vertexIndex];
1009
- if (custom) {
1010
- const cp1: [number, number] = [
1011
- custom[0] * bound.w + bound.x,
1012
- custom[1] * bound.h + bound.y,
1013
- ];
1014
- const cp2: [number, number] = [
1015
- custom[2] * bound.w + bound.x,
1016
- custom[3] * bound.h + bound.y,
1017
- ];
1018
- return { cp1, cp2 };
1019
- }
1020
-
1021
- // Fall back to auto-computation
1022
- const vertices = model.vertices;
1023
- const count = vertices.length;
1024
-
1025
- const prev = this._toAbsolute(vertices[(vertexIndex - 1 + count) % count], bound);
1026
- const curr = this._toAbsolute(vertices[vertexIndex], bound);
1027
- const next = this._toAbsolute(vertices[(vertexIndex + 1) % count], bound);
1028
-
1029
- const dx1 = prev[0] - curr[0];
1030
- const dy1 = prev[1] - curr[1];
1031
- const dx2 = next[0] - curr[0];
1032
- const dy2 = next[1] - curr[1];
1033
-
1034
- const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1) || 1;
1035
- const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
1036
-
1037
- const cpDist1 = len1 / 3;
1038
- const cpDist2 = len2 / 3;
1039
-
1040
- const cp1: [number, number] = [
1041
- curr[0] + (dx1 / len1) * cpDist1,
1042
- curr[1] + (dy1 / len1) * cpDist1,
1043
- ];
1044
- const cp2: [number, number] = [
1045
- curr[0] + (dx2 / len2) * cpDist2,
1046
- curr[1] + (dy2 / len2) * cpDist2,
1047
- ];
1048
-
1049
- return { cp1, cp2 };
1050
- }
1051
-
1052
- // ── Rendering ───────────────────────────────────────────────────────
1053
-
1054
- override render(ctx: CanvasRenderingContext2D, _rc: RoughCanvas): void {
1055
- const model = this._getPolygonModel();
1056
- if (!model || !model.vertices) return;
1057
- if (!this.isEditing && this.hoveredVertexIndex < 0) return;
1058
-
1059
- const bound = Bound.deserialize(model.xywh);
1060
- const zoom = this.gfx.viewport.zoom;
1061
- const vertices = model.vertices;
1062
-
1063
- ctx.save();
1064
- ctx.globalAlpha = this.globalAlpha;
1065
-
1066
- // ── Apply rotation around shape center ─────────────────────────
1067
- const rotate = model.rotate ?? 0;
1068
- if (rotate) {
1069
- const cx = bound.x + bound.w / 2;
1070
- const cy = bound.y + bound.h / 2;
1071
- const rad = (rotate * Math.PI) / 180;
1072
- ctx.translate(cx, cy);
1073
- ctx.rotate(rad);
1074
- ctx.translate(-cx, -cy);
1075
- }
1076
-
1077
- // ── Draw snap guides ────────────────────────────────────────────
1078
- if (this.activeVertexIndex >= 0) {
1079
- ctx.setLineDash([4 / zoom, 3 / zoom]);
1080
- ctx.lineWidth = 1 / zoom;
1081
- ctx.strokeStyle = SNAP_GUIDE_COLOR;
1082
-
1083
- if (this.snapGuideX !== null) {
1084
- ctx.beginPath();
1085
- ctx.moveTo(this.snapGuideX, bound.y - 20 / zoom);
1086
- ctx.lineTo(this.snapGuideX, bound.y + bound.h + 20 / zoom);
1087
- ctx.stroke();
1088
- }
1089
- if (this.snapGuideY !== null) {
1090
- ctx.beginPath();
1091
- ctx.moveTo(bound.x - 20 / zoom, this.snapGuideY);
1092
- ctx.lineTo(bound.x + bound.w + 20 / zoom, this.snapGuideY);
1093
- ctx.stroke();
1094
- }
1095
- ctx.setLineDash([]);
1096
- }
1097
-
1098
- // ── Draw Bezier control handles ────────────────────────────────
1099
- if (this.isEditing && model.smoothFlags) {
1100
- for (let i = 0; i < vertices.length; i++) {
1101
- if (!model.smoothFlags[i]) continue;
1102
- const cp = this.getBezierControlPoints(i);
1103
- if (!cp) continue;
1104
-
1105
- const [ax, ay] = this._toAbsolute(vertices[i], bound);
1106
- const cpR = BEZIER_HANDLE_RADIUS / zoom;
1107
-
1108
- // Draw control lines
1109
- ctx.beginPath();
1110
- ctx.moveTo(cp.cp1[0], cp.cp1[1]);
1111
- ctx.lineTo(ax, ay);
1112
- ctx.lineTo(cp.cp2[0], cp.cp2[1]);
1113
- ctx.strokeStyle = BEZIER_LINE_COLOR;
1114
- ctx.lineWidth = 1 / zoom;
1115
- ctx.setLineDash([3 / zoom, 2 / zoom]);
1116
- ctx.stroke();
1117
- ctx.setLineDash([]);
1118
-
1119
- // Draw control point handles
1120
- for (const cp_pt of [cp.cp1, cp.cp2]) {
1121
- ctx.beginPath();
1122
- ctx.arc(cp_pt[0], cp_pt[1], cpR, 0, Math.PI * 2);
1123
- ctx.fillStyle = BEZIER_HANDLE_COLOR;
1124
- ctx.fill();
1125
- ctx.strokeStyle = '#ffffff';
1126
- ctx.lineWidth = 1 / zoom;
1127
- ctx.stroke();
1128
- }
1129
- }
1130
- }
1131
-
1132
- // ── Draw edge midpoint handles ──────────────────────────────────
1133
- if (this.isEditing) {
1134
- for (let i = 0; i < vertices.length; i++) {
1135
- const [ax, ay] = this._toAbsolute(vertices[i], bound);
1136
- const nextIdx = (i + 1) % vertices.length;
1137
- const [bx, by] = this._toAbsolute(vertices[nextIdx], bound);
1138
- const mx = (ax + bx) / 2;
1139
- const my = (ay + by) / 2;
1140
-
1141
- const isHoveredMid = i === this.hoveredMidpointIndex;
1142
- const midR = (isHoveredMid ? MIDPOINT_HANDLE_HOVER_RADIUS : MIDPOINT_HANDLE_RADIUS) / zoom;
1143
- const midFill = isHoveredMid ? MIDPOINT_HOVER_FILL_COLOR : MIDPOINT_FILL_COLOR;
1144
-
1145
- ctx.beginPath();
1146
- ctx.arc(mx, my, midR, 0, Math.PI * 2);
1147
- ctx.fillStyle = midFill;
1148
- ctx.fill();
1149
- ctx.strokeStyle = isHoveredMid ? '#228be6' : '#868e96';
1150
- ctx.lineWidth = (isHoveredMid ? 1.5 : 1) / zoom;
1151
- ctx.stroke();
1152
- }
1153
- }
1154
-
1155
- // ── Draw vertex handles ─────────────────────────────────────────
1156
- for (let i = 0; i < vertices.length; i++) {
1157
- const [ax, ay] = this._toAbsolute(vertices[i], bound);
1158
- const isHovered = i === this.hoveredVertexIndex;
1159
- const isActive = i === this.activeVertexIndex;
1160
-
1161
- let radius: number;
1162
- let fillColor: string;
1163
- let strokeWidth: number;
1164
-
1165
- if (isActive) {
1166
- radius = VERTEX_HANDLE_ACTIVE_RADIUS / zoom;
1167
- fillColor = HANDLE_ACTIVE_FILL_COLOR;
1168
- strokeWidth = 2 / zoom;
1169
- } else if (isHovered) {
1170
- radius = VERTEX_HANDLE_HOVER_RADIUS / zoom;
1171
- fillColor = HANDLE_HOVER_FILL_COLOR;
1172
- strokeWidth = 2 / zoom;
1173
- } else {
1174
- radius = VERTEX_HANDLE_RADIUS / zoom;
1175
- fillColor = HANDLE_FILL_COLOR;
1176
- strokeWidth = 1.5 / zoom;
1177
- }
1178
-
1179
- // Outer stroke
1180
- ctx.beginPath();
1181
- ctx.arc(ax, ay, radius, 0, Math.PI * 2);
1182
- ctx.fillStyle = fillColor;
1183
- ctx.fill();
1184
- ctx.strokeStyle = '#228be6';
1185
- ctx.lineWidth = strokeWidth;
1186
- ctx.stroke();
1187
-
1188
- // Smooth vertex indicator (diamond shape on top of circle)
1189
- if (this.isEditing && model.smoothFlags && model.smoothFlags[i]) {
1190
- const dSize = 3.5 / zoom;
1191
- ctx.beginPath();
1192
- ctx.moveTo(ax, ay - dSize);
1193
- ctx.lineTo(ax + dSize, ay);
1194
- ctx.lineTo(ax, ay + dSize);
1195
- ctx.lineTo(ax - dSize, ay);
1196
- ctx.closePath();
1197
- ctx.fillStyle = BEZIER_HANDLE_COLOR;
1198
- ctx.fill();
1199
- }
1200
-
1201
- // Index label for editing mode (only when editing and zoomed in enough)
1202
- if (this.isEditing && zoom >= 1.5) {
1203
- ctx.font = `${10 / zoom}px sans-serif`;
1204
- ctx.fillStyle = '#228be6';
1205
- ctx.textAlign = 'center';
1206
- ctx.textBaseline = 'bottom';
1207
- ctx.fillText(`${i}`, ax, ay - radius - 2 / zoom);
1208
- }
1209
- }
1210
-
1211
- ctx.restore();
1212
- }
1213
- }
1
+ import {
2
+ type RoughCanvas,
3
+ ToolOverlay,
4
+ } from '../../affine-block-surface/index.js';
5
+ import { ShapeElementModel, ShapeType } from '../../affine-model/index.js';
6
+ import {
7
+ Bound,
8
+ type BezierCurveParameters,
9
+ getBezierCurveBoundingBox,
10
+ } from '../../global/gfx/index.js';
11
+ import type { GfxController } from '../../std/gfx/index.js';
12
+
13
+ // ─── Visual constants ───────────────────────────────────────────────────────
14
+
15
+ /** Radius of a normal vertex handle (screen pixels, divided by zoom). */
16
+ const VERTEX_HANDLE_RADIUS = 5;
17
+
18
+ /** Radius of a hovered vertex handle (screen pixels, divided by zoom). */
19
+ const VERTEX_HANDLE_HOVER_RADIUS = 7;
20
+
21
+ /** Radius of a dragged vertex handle (screen pixels, divided by zoom). */
22
+ const VERTEX_HANDLE_ACTIVE_RADIUS = 8;
23
+
24
+ /** Hit-test distance to consider the cursor "over" a vertex (screen px). */
25
+ const VERTEX_HIT_DISTANCE = 10;
26
+
27
+ /** Snap distance in model coordinates for coordinate alignment guides. */
28
+ const SNAP_GUIDE_DISTANCE = 6;
29
+
30
+ /** Color for default vertex handles. */
31
+ const HANDLE_FILL_COLOR = '#ffffff';
32
+
33
+ /** Color for hovered vertex handles. */
34
+ const HANDLE_HOVER_FILL_COLOR = '#d0ebff';
35
+
36
+ /** Color for actively dragged vertex handles. */
37
+ const HANDLE_ACTIVE_FILL_COLOR = '#339af0';
38
+
39
+ /** Snap guide line color. */
40
+ const SNAP_GUIDE_COLOR = '#f06595';
41
+
42
+ /** Edge midpoint handle radius. */
43
+ const MIDPOINT_HANDLE_RADIUS = 3.5;
44
+
45
+ /** Hovered edge midpoint handle radius. */
46
+ const MIDPOINT_HANDLE_HOVER_RADIUS = 5;
47
+
48
+ /** Color for edge midpoint handles. */
49
+ const MIDPOINT_FILL_COLOR = '#e9ecef';
50
+
51
+ /** Color for hovered edge midpoint handles. */
52
+ const MIDPOINT_HOVER_FILL_COLOR = '#d0ebff';
53
+
54
+ /** Hit-test distance for edge midpoint handles (screen px). */
55
+ const MIDPOINT_HIT_DISTANCE = 10;
56
+
57
+ /** Bezier control handle radius. */
58
+ const BEZIER_HANDLE_RADIUS = 4;
59
+
60
+ /** Bezier control handle color. */
61
+ const BEZIER_HANDLE_COLOR = '#e64980';
62
+
63
+ /** Bezier control line color. */
64
+ const BEZIER_LINE_COLOR = '#e64980';
65
+
66
+ // ─── Overlay class ──────────────────────────────────────────────────────────
67
+
68
+ /**
69
+ * Overlay rendered on top of a selected polygon shape that provides:
70
+ *
71
+ * - Vertex handle circles at each polygon vertex (with hover/active states)
72
+ * - Edge midpoint indicators
73
+ * - Coordinate snapping guides while dragging a vertex
74
+ * - Real-time polygon path update feedback during vertex drag
75
+ *
76
+ * This overlay works alongside the standard bounding-box resize handles
77
+ * provided by the framework. Vertex editing is activated when the user
78
+ * double-clicks a selected polygon (entering editing mode) or when a
79
+ * polygon is first selected (non-editing mode shows smaller handles).
80
+ */
81
+ export class PolygonVertexEditingOverlay extends ToolOverlay {
82
+ // ── Linked polygon element ──────────────────────────────────────────
83
+
84
+ /** ID of the polygon element this overlay is attached to. */
85
+ private _elementId: string | null = null;
86
+
87
+ // ── Interaction state ───────────────────────────────────────────────
88
+
89
+ /** Index of the currently hovered vertex (-1 = none). */
90
+ hoveredVertexIndex = -1;
91
+
92
+ /** Index of the currently hovered edge midpoint (-1 = none). */
93
+ hoveredMidpointIndex = -1;
94
+
95
+ /** Index of the vertex currently being dragged (-1 = none). */
96
+ activeVertexIndex = -1;
97
+
98
+ /** Whether vertex editing mode is enabled (double-click to enter). */
99
+ isEditing = false;
100
+
101
+ /** Current cursor position in model coordinates (for hover testing). */
102
+ cursorModelPos: [number, number] | null = null;
103
+
104
+ /** Index of the vertex whose Bezier control handle is being dragged (-1 = none). */
105
+ activeBezierHandleIndex = -1;
106
+
107
+ /** Which handle of the active bezier vertex is being dragged (0=cp1, 1=cp2, -1=none). */
108
+ activeBezierHandleType: number = -1;
109
+
110
+ // ── Snap guide state ────────────────────────────────────────────────
111
+
112
+ /** Horizontal snap guide Y coordinate (null = hidden). */
113
+ snapGuideY: number | null = null;
114
+
115
+ /** Vertical snap guide X coordinate (null = hidden). */
116
+ snapGuideX: number | null = null;
117
+
118
+ constructor(gfx: GfxController) {
119
+ super(gfx);
120
+ }
121
+
122
+ /** Attach this overlay to a specific polygon element. */
123
+ setElement(elementId: string) {
124
+ this._elementId = elementId;
125
+ }
126
+
127
+ /** Get the linked ShapeElementModel if it's a polygon. */
128
+ private _getPolygonModel(): ShapeElementModel | null {
129
+ if (!this._elementId) return null;
130
+ const el = this.gfx.getElementById(this._elementId);
131
+ if (
132
+ el instanceof ShapeElementModel &&
133
+ el.shapeType === ShapeType.Polygon
134
+ ) {
135
+ return el;
136
+ }
137
+ return null;
138
+ }
139
+
140
+ /**
141
+ * Convert a normalized [0-1] vertex to absolute model coordinates
142
+ * based on the polygon's bounding box.
143
+ */
144
+ private _toAbsolute(
145
+ nv: number[],
146
+ bound: Bound
147
+ ): [number, number] {
148
+ return [bound.x + nv[0] * bound.w, bound.y + nv[1] * bound.h];
149
+ }
150
+
151
+ /**
152
+ * Test if a model-coordinate point is within hit distance of a vertex.
153
+ */
154
+ hitTestVertex(
155
+ modelX: number,
156
+ modelY: number
157
+ ): number {
158
+ const model = this._getPolygonModel();
159
+ if (!model || !model.vertices) return -1;
160
+
161
+ const bound = Bound.deserialize(model.xywh);
162
+ const zoom = this.gfx.viewport.zoom;
163
+ const hitDist = VERTEX_HIT_DISTANCE / zoom;
164
+
165
+ // Inverse-rotate incoming world coordinates into polygon's local space
166
+ let localX = modelX;
167
+ let localY = modelY;
168
+ const rotate = model.rotate ?? 0;
169
+ if (rotate) {
170
+ const cx = bound.x + bound.w / 2;
171
+ const cy = bound.y + bound.h / 2;
172
+ const rad = -(rotate * Math.PI) / 180; // negative for inverse rotation
173
+ const cos = Math.cos(rad);
174
+ const sin = Math.sin(rad);
175
+ const dx = modelX - cx;
176
+ const dy = modelY - cy;
177
+ localX = cx + dx * cos - dy * sin;
178
+ localY = cy + dx * sin + dy * cos;
179
+ }
180
+
181
+ for (let i = 0; i < model.vertices.length; i++) {
182
+ const [ax, ay] = this._toAbsolute(model.vertices[i], bound);
183
+ const dx = localX - ax;
184
+ const dy = localY - ay;
185
+ if (Math.sqrt(dx * dx + dy * dy) < hitDist) {
186
+ return i;
187
+ }
188
+ }
189
+ return -1;
190
+ }
191
+
192
+ /**
193
+ * Move a vertex to a new absolute position, computing snap guides
194
+ * against other vertices. Updates the model's normalized vertices
195
+ * and bounding box.
196
+ */
197
+ moveVertex(
198
+ vertexIndex: number,
199
+ modelX: number,
200
+ modelY: number
201
+ ): void {
202
+ const model = this._getPolygonModel();
203
+ if (!model || !model.vertices) return;
204
+
205
+ const bound = Bound.deserialize(model.xywh);
206
+ const zoom = this.gfx.viewport.zoom;
207
+ const snapDist = SNAP_GUIDE_DISTANCE / zoom;
208
+
209
+ // Inverse-rotate mouse position from world space to local (unrotated) space
210
+ const rotate = model.rotate ?? 0;
211
+ let localX = modelX;
212
+ let localY = modelY;
213
+ if (rotate) {
214
+ const cx = bound.x + bound.w / 2;
215
+ const cy = bound.y + bound.h / 2;
216
+ const rad = (-rotate * Math.PI) / 180; // negative for inverse
217
+ const dx = modelX - cx;
218
+ const dy = modelY - cy;
219
+ localX = cx + dx * Math.cos(rad) - dy * Math.sin(rad);
220
+ localY = cy + dx * Math.sin(rad) + dy * Math.cos(rad);
221
+ }
222
+
223
+ // Collect local-space absolute positions of all other vertices for snapping
224
+ const otherAbsolute: [number, number][] = [];
225
+ for (let i = 0; i < model.vertices.length; i++) {
226
+ if (i === vertexIndex) continue;
227
+ otherAbsolute.push(this._toAbsolute(model.vertices[i], bound));
228
+ }
229
+
230
+ // Attempt coordinate snapping in local (unrotated) space
231
+ let snappedX = localX;
232
+ let snappedY = localY;
233
+ this.snapGuideX = null;
234
+ this.snapGuideY = null;
235
+
236
+ for (const [ox, oy] of otherAbsolute) {
237
+ if (Math.abs(localX - ox) < snapDist) {
238
+ snappedX = ox;
239
+ this.snapGuideX = ox;
240
+ }
241
+ if (Math.abs(localY - oy) < snapDist) {
242
+ snappedY = oy;
243
+ this.snapGuideY = oy;
244
+ }
245
+ }
246
+
247
+ // Compute new absolute vertices array
248
+ const newAbsVertices: [number, number][] = model.vertices.map(
249
+ (v, i) =>
250
+ i === vertexIndex
251
+ ? ([snappedX, snappedY] as [number, number])
252
+ : (this._toAbsolute(v, bound) as [number, number])
253
+ );
254
+
255
+ // Re-compute bounding box from new absolute positions
256
+ let minX = Infinity,
257
+ minY = Infinity,
258
+ maxX = -Infinity,
259
+ maxY = -Infinity;
260
+ for (const [vx, vy] of newAbsVertices) {
261
+ if (vx < minX) minX = vx;
262
+ if (vy < minY) minY = vy;
263
+ if (vx > maxX) maxX = vx;
264
+ if (vy > maxY) maxY = vy;
265
+ }
266
+
267
+ // Expand bounds to encompass Bezier geometry (control handles + arc curves)
268
+ const smoothFlags = model.smoothFlags;
269
+ const controlPoints = model.controlPoints;
270
+ const count = model.vertices.length;
271
+
272
+ if (smoothFlags) {
273
+ for (let i = 0; i < count; i++) {
274
+ const next = (i + 1) % count;
275
+ const currSmooth = smoothFlags[i] ?? false;
276
+ const nextSmooth = smoothFlags[next] ?? false;
277
+
278
+ if (!currSmooth && !nextSmooth) continue;
279
+
280
+ const [cx, cy] = newAbsVertices[i];
281
+ const [nx, ny] = newAbsVertices[next];
282
+
283
+ // Outgoing control point of current vertex
284
+ let cp1x: number, cp1y: number;
285
+ const customCurr = controlPoints?.[i];
286
+ if (currSmooth && customCurr) {
287
+ cp1x = customCurr[2] * bound.w + bound.x;
288
+ cp1y = customCurr[3] * bound.h + bound.y;
289
+ } else if (currSmooth) {
290
+ cp1x = cx + (nx - cx) / 3;
291
+ cp1y = cy + (ny - cy) / 3;
292
+ } else {
293
+ cp1x = cx;
294
+ cp1y = cy;
295
+ }
296
+
297
+ // Incoming control point of next vertex
298
+ let cp2x: number, cp2y: number;
299
+ const customNext = controlPoints?.[next];
300
+ if (nextSmooth && customNext) {
301
+ cp2x = customNext[0] * bound.w + bound.x;
302
+ cp2y = customNext[1] * bound.h + bound.y;
303
+ } else if (nextSmooth) {
304
+ cp2x = nx + (cx - nx) / 3;
305
+ cp2y = ny + (cy - ny) / 3;
306
+ } else {
307
+ cp2x = nx;
308
+ cp2y = ny;
309
+ }
310
+
311
+ // Include control handle positions
312
+ if (cp1x < minX) minX = cp1x;
313
+ if (cp1y < minY) minY = cp1y;
314
+ if (cp1x > maxX) maxX = cp1x;
315
+ if (cp1y > maxY) maxY = cp1y;
316
+ if (cp2x < minX) minX = cp2x;
317
+ if (cp2y < minY) minY = cp2y;
318
+ if (cp2x > maxX) maxX = cp2x;
319
+ if (cp2y > maxY) maxY = cp2y;
320
+
321
+ // Use getBezierCurveBoundingBox for tight arc bounds
322
+ const bezierParams: BezierCurveParameters = [
323
+ [cx, cy],
324
+ [cp1x, cp1y],
325
+ [cp2x, cp2y],
326
+ [nx, ny],
327
+ ];
328
+ const arcBound = getBezierCurveBoundingBox(bezierParams);
329
+ if (arcBound.x < minX) minX = arcBound.x;
330
+ if (arcBound.y < minY) minY = arcBound.y;
331
+ if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
332
+ if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
333
+ }
334
+ }
335
+
336
+ const w = Math.max(maxX - minX, 1);
337
+ const h = Math.max(maxY - minY, 1);
338
+
339
+ // Re-normalize vertices to new bounding box
340
+ const normalized = newAbsVertices.map(([vx, vy]) => [
341
+ (vx - minX) / w,
342
+ (vy - minY) / h,
343
+ ]);
344
+
345
+ const newBound = new Bound(minX, minY, w, h);
346
+
347
+ // Update model
348
+ model.xywh = newBound.serialize();
349
+ model.vertices = normalized;
350
+
351
+ // Re-normalize control points to new bounding box
352
+ if (controlPoints) {
353
+ const normalizedCPs = controlPoints.map(cp => {
354
+ if (!cp) return null;
355
+ const absCp1x = cp[0] * bound.w + bound.x;
356
+ const absCp1y = cp[1] * bound.h + bound.y;
357
+ const absCp2x = cp[2] * bound.w + bound.x;
358
+ const absCp2y = cp[3] * bound.h + bound.y;
359
+ return [
360
+ (absCp1x - minX) / w,
361
+ (absCp1y - minY) / h,
362
+ (absCp2x - minX) / w,
363
+ (absCp2y - minY) / h,
364
+ ];
365
+ });
366
+ model.controlPoints = normalizedCPs;
367
+ }
368
+ }
369
+
370
+ /** Clear snap guides (call on drag end). */
371
+ clearSnapGuides() {
372
+ this.snapGuideX = null;
373
+ this.snapGuideY = null;
374
+ }
375
+
376
+ /**
377
+ * Test if a model-coordinate point is within hit distance of an edge midpoint.
378
+ * Returns the edge index (i.e., the midpoint between vertex i and vertex i+1),
379
+ * or -1 if not near any midpoint.
380
+ */
381
+ hitTestMidpoint(
382
+ modelX: number,
383
+ modelY: number
384
+ ): number {
385
+ const model = this._getPolygonModel();
386
+ if (!model || !model.vertices) return -1;
387
+
388
+ const bound = Bound.deserialize(model.xywh);
389
+ const zoom = this.gfx.viewport.zoom;
390
+ const hitDist = MIDPOINT_HIT_DISTANCE / zoom;
391
+
392
+ // Inverse-rotate incoming world coordinates into polygon's local space
393
+ let localX = modelX;
394
+ let localY = modelY;
395
+ const rotate = model.rotate ?? 0;
396
+ if (rotate) {
397
+ const cx = bound.x + bound.w / 2;
398
+ const cy = bound.y + bound.h / 2;
399
+ const rad = -(rotate * Math.PI) / 180; // negative for inverse rotation
400
+ const cos = Math.cos(rad);
401
+ const sin = Math.sin(rad);
402
+ const dx = modelX - cx;
403
+ const dy = modelY - cy;
404
+ localX = cx + dx * cos - dy * sin;
405
+ localY = cy + dx * sin + dy * cos;
406
+ }
407
+
408
+ for (let i = 0; i < model.vertices.length; i++) {
409
+ const [ax, ay] = this._toAbsolute(model.vertices[i], bound);
410
+ const nextIdx = (i + 1) % model.vertices.length;
411
+ const [bx, by] = this._toAbsolute(model.vertices[nextIdx], bound);
412
+ const mx = (ax + bx) / 2;
413
+ const my = (ay + by) / 2;
414
+
415
+ const dx = localX - mx;
416
+ const dy = localY - my;
417
+ if (Math.sqrt(dx * dx + dy * dy) < hitDist) {
418
+ return i;
419
+ }
420
+ }
421
+ return -1;
422
+ }
423
+
424
+ /**
425
+ * Test if a model-coordinate point hits a bezier control handle.
426
+ * Returns { vertexIndex, handleIndex: 0=cp1, 1=cp2 } or null.
427
+ */
428
+ hitTestBezierHandle(
429
+ modelX: number,
430
+ modelY: number
431
+ ): { vertexIndex: number; handleIndex: number } | null {
432
+ const model = this._getPolygonModel();
433
+ if (!model || !model.vertices || !model.smoothFlags) return null;
434
+
435
+ const bound = Bound.deserialize(model.xywh);
436
+ const zoom = this.gfx.viewport.zoom;
437
+ const hitDist = BEZIER_HANDLE_RADIUS * 2 / zoom;
438
+
439
+ // Inverse-rotate incoming world coordinates into polygon's local space
440
+ let localX = modelX;
441
+ let localY = modelY;
442
+ const rotate = model.rotate ?? 0;
443
+ if (rotate) {
444
+ const cx = bound.x + bound.w / 2;
445
+ const cy = bound.y + bound.h / 2;
446
+ const rad = (-rotate * Math.PI) / 180;
447
+ const cos = Math.cos(rad);
448
+ const sin = Math.sin(rad);
449
+ const dx = modelX - cx;
450
+ const dy = modelY - cy;
451
+ localX = cx + dx * cos - dy * sin;
452
+ localY = cy + dx * sin + dy * cos;
453
+ }
454
+
455
+ for (let i = 0; i < model.vertices.length; i++) {
456
+ if (!model.smoothFlags[i]) continue;
457
+ const cp = this.getBezierControlPoints(i);
458
+ if (!cp) continue;
459
+
460
+ // Check cp1
461
+ const dx1 = localX - cp.cp1[0];
462
+ const dy1 = localY - cp.cp1[1];
463
+ if (Math.sqrt(dx1 * dx1 + dy1 * dy1) < hitDist) {
464
+ return { vertexIndex: i, handleIndex: 0 };
465
+ }
466
+
467
+ // Check cp2
468
+ const dx2 = localX - cp.cp2[0];
469
+ const dy2 = localY - cp.cp2[1];
470
+ if (Math.sqrt(dx2 * dx2 + dy2 * dy2) < hitDist) {
471
+ return { vertexIndex: i, handleIndex: 1 };
472
+ }
473
+ }
474
+ return null;
475
+ }
476
+
477
+ /**
478
+ * Move a bezier control handle to an absolute model position.
479
+ * Stores the result as normalized coordinates in model.controlPoints.
480
+ */
481
+ moveBezierHandle(
482
+ vertexIndex: number,
483
+ handleIndex: number,
484
+ modelX: number,
485
+ modelY: number
486
+ ): void {
487
+ const model = this._getPolygonModel();
488
+ if (!model || !model.vertices) return;
489
+
490
+ const bound = Bound.deserialize(model.xywh);
491
+ const count = model.vertices.length;
492
+
493
+ // Inverse-rotate mouse position from world space to local (unrotated) space
494
+ const rotate = model.rotate ?? 0;
495
+ let localX = modelX;
496
+ let localY = modelY;
497
+ if (rotate) {
498
+ const cx = bound.x + bound.w / 2;
499
+ const cy = bound.y + bound.h / 2;
500
+ const rad = -(rotate * Math.PI) / 180;
501
+ const cos = Math.cos(rad);
502
+ const sin = Math.sin(rad);
503
+ const dx = modelX - cx;
504
+ const dy = modelY - cy;
505
+ localX = cx + dx * cos - dy * sin;
506
+ localY = cy + dx * sin + dy * cos;
507
+ }
508
+
509
+ // Initialize controlPoints array if null
510
+ let controlPoints: (number[] | null)[] = model.controlPoints
511
+ ? [...model.controlPoints]
512
+ : new Array(count).fill(null);
513
+
514
+ // Ensure array is the right length
515
+ while (controlPoints.length < count) controlPoints.push(null);
516
+
517
+ // Auto-compute current control points for this vertex if not set
518
+ if (!controlPoints[vertexIndex]) {
519
+ const cp = this.getBezierControlPoints(vertexIndex);
520
+ if (!cp) return;
521
+ // Store as normalized [cp1x, cp1y, cp2x, cp2y]
522
+ controlPoints[vertexIndex] = [
523
+ (cp.cp1[0] - bound.x) / bound.w,
524
+ (cp.cp1[1] - bound.y) / bound.h,
525
+ (cp.cp2[0] - bound.x) / bound.w,
526
+ (cp.cp2[1] - bound.y) / bound.h,
527
+ ];
528
+ }
529
+
530
+ // Convert absolute position to normalized coordinates (in current bound)
531
+ const normX = (localX - bound.x) / bound.w;
532
+ const normY = (localY - bound.y) / bound.h;
533
+
534
+ // Update the specific handle
535
+ const entry = [...controlPoints[vertexIndex]!];
536
+ if (handleIndex === 0) {
537
+ entry[0] = normX;
538
+ entry[1] = normY;
539
+ } else {
540
+ entry[2] = normX;
541
+ entry[3] = normY;
542
+ }
543
+ controlPoints[vertexIndex] = entry;
544
+
545
+ // ── Re-normalize: expand bounding box to encompass all Bezier geometry ──
546
+ // Collect all absolute vertex positions
547
+ const absVertices: [number, number][] = model.vertices.map(
548
+ v => [bound.x + v[0] * bound.w, bound.y + v[1] * bound.h] as [number, number]
549
+ );
550
+
551
+ let minX = Infinity,
552
+ minY = Infinity,
553
+ maxX = -Infinity,
554
+ maxY = -Infinity;
555
+
556
+ for (const [vx, vy] of absVertices) {
557
+ if (vx < minX) minX = vx;
558
+ if (vy < minY) minY = vy;
559
+ if (vx > maxX) maxX = vx;
560
+ if (vy > maxY) maxY = vy;
561
+ }
562
+
563
+ // Expand bounds using getBezierCurveBoundingBox for each Bezier edge
564
+ const smoothFlags = model.smoothFlags;
565
+ if (smoothFlags) {
566
+ for (let i = 0; i < count; i++) {
567
+ const next = (i + 1) % count;
568
+ const currSmooth = smoothFlags[i] ?? false;
569
+ const nextSmooth = smoothFlags[next] ?? false;
570
+
571
+ if (!currSmooth && !nextSmooth) continue;
572
+
573
+ const [cx, cy] = absVertices[i];
574
+ const [nx, ny] = absVertices[next];
575
+
576
+ // Outgoing control point of current vertex
577
+ let cp1x: number, cp1y: number;
578
+ const customCurr = controlPoints[i];
579
+ if (currSmooth && customCurr) {
580
+ cp1x = customCurr[2] * bound.w + bound.x;
581
+ cp1y = customCurr[3] * bound.h + bound.y;
582
+ } else if (currSmooth) {
583
+ cp1x = cx + (nx - cx) / 3;
584
+ cp1y = cy + (ny - cy) / 3;
585
+ } else {
586
+ cp1x = cx;
587
+ cp1y = cy;
588
+ }
589
+
590
+ // Incoming control point of next vertex
591
+ let cp2x: number, cp2y: number;
592
+ const customNext = controlPoints[next];
593
+ if (nextSmooth && customNext) {
594
+ cp2x = customNext[0] * bound.w + bound.x;
595
+ cp2y = customNext[1] * bound.h + bound.y;
596
+ } else if (nextSmooth) {
597
+ cp2x = nx + (cx - nx) / 3;
598
+ cp2y = ny + (cy - ny) / 3;
599
+ } else {
600
+ cp2x = nx;
601
+ cp2y = ny;
602
+ }
603
+
604
+ // Include control handle positions
605
+ if (cp1x < minX) minX = cp1x;
606
+ if (cp1y < minY) minY = cp1y;
607
+ if (cp1x > maxX) maxX = cp1x;
608
+ if (cp1y > maxY) maxY = cp1y;
609
+ if (cp2x < minX) minX = cp2x;
610
+ if (cp2y < minY) minY = cp2y;
611
+ if (cp2x > maxX) maxX = cp2x;
612
+ if (cp2y > maxY) maxY = cp2y;
613
+
614
+ // Use getBezierCurveBoundingBox for tight arc bounds
615
+ const bezierParams: BezierCurveParameters = [
616
+ [cx, cy],
617
+ [cp1x, cp1y],
618
+ [cp2x, cp2y],
619
+ [nx, ny],
620
+ ];
621
+ const arcBound = getBezierCurveBoundingBox(bezierParams);
622
+ if (arcBound.x < minX) minX = arcBound.x;
623
+ if (arcBound.y < minY) minY = arcBound.y;
624
+ if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
625
+ if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
626
+ }
627
+ }
628
+
629
+ const newW = Math.max(maxX - minX, 1);
630
+ const newH = Math.max(maxY - minY, 1);
631
+
632
+ // Re-normalize vertices to new bounding box
633
+ const normalizedVerts = absVertices.map(([vx, vy]) => [
634
+ (vx - minX) / newW,
635
+ (vy - minY) / newH,
636
+ ]);
637
+
638
+ // Re-normalize control points to new bounding box
639
+ const normalizedCPs = controlPoints.map(cp => {
640
+ if (!cp) return null;
641
+ const absCp1x = cp[0] * bound.w + bound.x;
642
+ const absCp1y = cp[1] * bound.h + bound.y;
643
+ const absCp2x = cp[2] * bound.w + bound.x;
644
+ const absCp2y = cp[3] * bound.h + bound.y;
645
+ return [
646
+ (absCp1x - minX) / newW,
647
+ (absCp1y - minY) / newH,
648
+ (absCp2x - minX) / newW,
649
+ (absCp2y - minY) / newH,
650
+ ];
651
+ });
652
+
653
+ const newBound = new Bound(minX, minY, newW, newH);
654
+ model.xywh = newBound.serialize();
655
+ model.vertices = normalizedVerts;
656
+ model.controlPoints = normalizedCPs;
657
+ }
658
+
659
+ /**
660
+ * Insert a new vertex at the midpoint of edge `edgeIndex` (between vertex
661
+ * edgeIndex and edgeIndex+1). Returns the index of the newly inserted vertex.
662
+ */
663
+ insertVertexAtMidpoint(edgeIndex: number): number {
664
+ const model = this._getPolygonModel();
665
+ if (!model || !model.vertices) return -1;
666
+
667
+ const vertices = [...model.vertices];
668
+ const nextIdx = (edgeIndex + 1) % vertices.length;
669
+
670
+ // Compute the midpoint in normalized space
671
+ const midNorm = [
672
+ (vertices[edgeIndex][0] + vertices[nextIdx][0]) / 2,
673
+ (vertices[edgeIndex][1] + vertices[nextIdx][1]) / 2,
674
+ ];
675
+
676
+ // Insert after edgeIndex
677
+ const insertIdx = edgeIndex + 1;
678
+ vertices.splice(insertIdx, 0, midNorm);
679
+
680
+ // Update smoothFlags if present
681
+ if (model.smoothFlags) {
682
+ const flags = [...model.smoothFlags];
683
+ flags.splice(insertIdx, 0, false);
684
+ model.smoothFlags = flags;
685
+ }
686
+
687
+ // Update controlPoints if present
688
+ if (model.controlPoints) {
689
+ const cps = [...model.controlPoints];
690
+ cps.splice(insertIdx, 0, null);
691
+ model.controlPoints = cps;
692
+ }
693
+
694
+ model.vertices = vertices;
695
+ return insertIdx;
696
+ }
697
+
698
+ /**
699
+ * Delete the vertex at the given index. Returns true if successful.
700
+ * Requires at least 3 vertices to remain after deletion.
701
+ */
702
+ deleteVertex(vertexIndex: number): boolean {
703
+ const model = this._getPolygonModel();
704
+ if (!model || !model.vertices) return false;
705
+ if (model.vertices.length <= 3) return false; // minimum polygon is a triangle
706
+
707
+ const vertices = [...model.vertices];
708
+ vertices.splice(vertexIndex, 1);
709
+
710
+ // Update smoothFlags if present
711
+ if (model.smoothFlags) {
712
+ const flags = [...model.smoothFlags];
713
+ flags.splice(vertexIndex, 1);
714
+ model.smoothFlags = flags;
715
+ }
716
+
717
+ // Update controlPoints if present
718
+ if (model.controlPoints) {
719
+ const cps = [...model.controlPoints];
720
+ cps.splice(vertexIndex, 1);
721
+ model.controlPoints = cps;
722
+ }
723
+
724
+ // Re-compute bounding box from remaining vertices
725
+ const bound = Bound.deserialize(model.xywh);
726
+ const absVertices: [number, number][] = vertices.map(
727
+ v => this._toAbsolute(v, bound) as [number, number]
728
+ );
729
+
730
+ let minX = Infinity,
731
+ minY = Infinity,
732
+ maxX = -Infinity,
733
+ maxY = -Infinity;
734
+ for (const [vx, vy] of absVertices) {
735
+ if (vx < minX) minX = vx;
736
+ if (vy < minY) minY = vy;
737
+ if (vx > maxX) maxX = vx;
738
+ if (vy > maxY) maxY = vy;
739
+ }
740
+
741
+ // Expand bounds to encompass Bezier geometry after deletion
742
+ const updatedFlags = model.smoothFlags;
743
+ const updatedCPs = model.controlPoints;
744
+ if (updatedFlags) {
745
+ const cnt = vertices.length;
746
+ for (let i = 0; i < cnt; i++) {
747
+ const next = (i + 1) % cnt;
748
+ const currSmooth = updatedFlags[i] ?? false;
749
+ const nextSmooth = updatedFlags[next] ?? false;
750
+
751
+ if (!currSmooth && !nextSmooth) continue;
752
+
753
+ const [cx, cy] = absVertices[i];
754
+ const [nx, ny] = absVertices[next];
755
+
756
+ let cp1x: number, cp1y: number;
757
+ const customCurr = updatedCPs?.[i];
758
+ if (currSmooth && customCurr) {
759
+ cp1x = customCurr[2] * bound.w + bound.x;
760
+ cp1y = customCurr[3] * bound.h + bound.y;
761
+ } else if (currSmooth) {
762
+ cp1x = cx + (nx - cx) / 3;
763
+ cp1y = cy + (ny - cy) / 3;
764
+ } else {
765
+ cp1x = cx;
766
+ cp1y = cy;
767
+ }
768
+
769
+ let cp2x: number, cp2y: number;
770
+ const customNext = updatedCPs?.[next];
771
+ if (nextSmooth && customNext) {
772
+ cp2x = customNext[0] * bound.w + bound.x;
773
+ cp2y = customNext[1] * bound.h + bound.y;
774
+ } else if (nextSmooth) {
775
+ cp2x = nx + (cx - nx) / 3;
776
+ cp2y = ny + (cy - ny) / 3;
777
+ } else {
778
+ cp2x = nx;
779
+ cp2y = ny;
780
+ }
781
+
782
+ if (cp1x < minX) minX = cp1x;
783
+ if (cp1y < minY) minY = cp1y;
784
+ if (cp1x > maxX) maxX = cp1x;
785
+ if (cp1y > maxY) maxY = cp1y;
786
+ if (cp2x < minX) minX = cp2x;
787
+ if (cp2y < minY) minY = cp2y;
788
+ if (cp2x > maxX) maxX = cp2x;
789
+ if (cp2y > maxY) maxY = cp2y;
790
+
791
+ const bezierParams: BezierCurveParameters = [
792
+ [cx, cy],
793
+ [cp1x, cp1y],
794
+ [cp2x, cp2y],
795
+ [nx, ny],
796
+ ];
797
+ const arcBound = getBezierCurveBoundingBox(bezierParams);
798
+ if (arcBound.x < minX) minX = arcBound.x;
799
+ if (arcBound.y < minY) minY = arcBound.y;
800
+ if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
801
+ if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
802
+ }
803
+ }
804
+
805
+ const w = Math.max(maxX - minX, 1);
806
+ const h = Math.max(maxY - minY, 1);
807
+
808
+ const normalized = absVertices.map(([vx, vy]) => [
809
+ (vx - minX) / w,
810
+ (vy - minY) / h,
811
+ ]);
812
+
813
+ const newBound = new Bound(minX, minY, w, h);
814
+ model.xywh = newBound.serialize();
815
+ model.vertices = normalized;
816
+
817
+ // Re-normalize control points to new bounding box
818
+ if (updatedCPs) {
819
+ const normalizedCPs = updatedCPs.map(cp => {
820
+ if (!cp) return null;
821
+ const absCp1x = cp[0] * bound.w + bound.x;
822
+ const absCp1y = cp[1] * bound.h + bound.y;
823
+ const absCp2x = cp[2] * bound.w + bound.x;
824
+ const absCp2y = cp[3] * bound.h + bound.y;
825
+ return [
826
+ (absCp1x - minX) / w,
827
+ (absCp1y - minY) / h,
828
+ (absCp2x - minX) / w,
829
+ (absCp2y - minY) / h,
830
+ ];
831
+ });
832
+ model.controlPoints = normalizedCPs;
833
+ }
834
+
835
+ return true;
836
+ }
837
+
838
+ /**
839
+ * Toggle smooth (Bezier) flag for a vertex. When smooth is true, the
840
+ * edges adjacent to this vertex are rendered as Bezier curves with
841
+ * automatically computed control points.
842
+ */
843
+ toggleVertexSmooth(vertexIndex: number): void {
844
+ const model = this._getPolygonModel();
845
+ if (!model || !model.vertices) return;
846
+
847
+ const bound = Bound.deserialize(model.xywh);
848
+ const count = model.vertices.length;
849
+ let flags = model.smoothFlags ? [...model.smoothFlags] : new Array(count).fill(false);
850
+
851
+ // Ensure flags array matches vertex count
852
+ while (flags.length < count) flags.push(false);
853
+ if (flags.length > count) flags = flags.slice(0, count);
854
+
855
+ const wasSmooth = flags[vertexIndex];
856
+ flags[vertexIndex] = !wasSmooth;
857
+ model.smoothFlags = flags;
858
+
859
+ // If toggling off, clear custom control points for this vertex
860
+ let controlPoints: (number[] | null)[] = model.controlPoints
861
+ ? [...model.controlPoints]
862
+ : new Array(count).fill(null);
863
+ while (controlPoints.length < count) controlPoints.push(null);
864
+
865
+ if (wasSmooth) {
866
+ controlPoints[vertexIndex] = null;
867
+ }
868
+
869
+ // ── Re-normalize: expand bounding box to encompass all Bezier geometry ──
870
+ // We need to temporarily apply the new flags so getBezierControlPoints uses them
871
+ // Instead, compute everything inline using the new flags
872
+
873
+ // Collect all absolute vertex positions
874
+ const absVertices: [number, number][] = model.vertices.map(
875
+ v => [bound.x + v[0] * bound.w, bound.y + v[1] * bound.h] as [number, number]
876
+ );
877
+
878
+ let minX = Infinity,
879
+ minY = Infinity,
880
+ maxX = -Infinity,
881
+ maxY = -Infinity;
882
+
883
+ for (const [vx, vy] of absVertices) {
884
+ if (vx < minX) minX = vx;
885
+ if (vy < minY) minY = vy;
886
+ if (vx > maxX) maxX = vx;
887
+ if (vy > maxY) maxY = vy;
888
+ }
889
+
890
+ // Expand bounds using getBezierCurveBoundingBox for each Bezier edge
891
+ for (let i = 0; i < count; i++) {
892
+ const next = (i + 1) % count;
893
+ const currSmooth = flags[i] ?? false;
894
+ const nextSmooth = flags[next] ?? false;
895
+
896
+ if (!currSmooth && !nextSmooth) continue;
897
+
898
+ const [cx, cy] = absVertices[i];
899
+ const [nx, ny] = absVertices[next];
900
+
901
+ // Outgoing control point of current vertex (cp2 of its control points)
902
+ let cp1x: number, cp1y: number;
903
+ const customCurr = controlPoints[i];
904
+ if (currSmooth && customCurr) {
905
+ cp1x = customCurr[2] * bound.w + bound.x;
906
+ cp1y = customCurr[3] * bound.h + bound.y;
907
+ } else if (currSmooth) {
908
+ cp1x = cx + (nx - cx) / 3;
909
+ cp1y = cy + (ny - cy) / 3;
910
+ } else {
911
+ cp1x = cx;
912
+ cp1y = cy;
913
+ }
914
+
915
+ // Incoming control point of next vertex (cp1 of its control points)
916
+ let cp2x: number, cp2y: number;
917
+ const customNext = controlPoints[next];
918
+ if (nextSmooth && customNext) {
919
+ cp2x = customNext[0] * bound.w + bound.x;
920
+ cp2y = customNext[1] * bound.h + bound.y;
921
+ } else if (nextSmooth) {
922
+ cp2x = nx + (cx - nx) / 3;
923
+ cp2y = ny + (cy - ny) / 3;
924
+ } else {
925
+ cp2x = nx;
926
+ cp2y = ny;
927
+ }
928
+
929
+ // Include control handle positions
930
+ if (cp1x < minX) minX = cp1x;
931
+ if (cp1y < minY) minY = cp1y;
932
+ if (cp1x > maxX) maxX = cp1x;
933
+ if (cp1y > maxY) maxY = cp1y;
934
+ if (cp2x < minX) minX = cp2x;
935
+ if (cp2y < minY) minY = cp2y;
936
+ if (cp2x > maxX) maxX = cp2x;
937
+ if (cp2y > maxY) maxY = cp2y;
938
+
939
+ // Use getBezierCurveBoundingBox for tight arc bounds
940
+ const bezierParams: BezierCurveParameters = [
941
+ [cx, cy],
942
+ [cp1x, cp1y],
943
+ [cp2x, cp2y],
944
+ [nx, ny],
945
+ ];
946
+ const arcBound = getBezierCurveBoundingBox(bezierParams);
947
+ if (arcBound.x < minX) minX = arcBound.x;
948
+ if (arcBound.y < minY) minY = arcBound.y;
949
+ if (arcBound.x + arcBound.w > maxX) maxX = arcBound.x + arcBound.w;
950
+ if (arcBound.y + arcBound.h > maxY) maxY = arcBound.y + arcBound.h;
951
+ }
952
+
953
+ const newW = Math.max(maxX - minX, 1);
954
+ const newH = Math.max(maxY - minY, 1);
955
+
956
+ // Re-normalize vertices to new bounding box
957
+ const normalizedVerts = absVertices.map(([vx, vy]) => [
958
+ (vx - minX) / newW,
959
+ (vy - minY) / newH,
960
+ ]);
961
+
962
+ // Re-normalize control points to new bounding box
963
+ const normalizedCPs = controlPoints.map(cp => {
964
+ if (!cp) return null;
965
+ const absCp1x = cp[0] * bound.w + bound.x;
966
+ const absCp1y = cp[1] * bound.h + bound.y;
967
+ const absCp2x = cp[2] * bound.w + bound.x;
968
+ const absCp2y = cp[3] * bound.h + bound.y;
969
+ return [
970
+ (absCp1x - minX) / newW,
971
+ (absCp1y - minY) / newH,
972
+ (absCp2x - minX) / newW,
973
+ (absCp2y - minY) / newH,
974
+ ];
975
+ });
976
+
977
+ const newBound = new Bound(minX, minY, newW, newH);
978
+ model.xywh = newBound.serialize();
979
+ model.vertices = normalizedVerts;
980
+ model.controlPoints = normalizedCPs;
981
+ }
982
+
983
+ /**
984
+ * Check if a vertex has Bezier smoothing enabled.
985
+ */
986
+ isVertexSmooth(vertexIndex: number): boolean {
987
+ const model = this._getPolygonModel();
988
+ if (!model || !model.smoothFlags) return false;
989
+ return !!model.smoothFlags[vertexIndex];
990
+ }
991
+
992
+ /**
993
+ * Get the computed Bezier control points for a smooth vertex.
994
+ * Returns [cp1, cp2] where cp1 is the control point for the incoming edge
995
+ * and cp2 is for the outgoing edge, both in absolute model coordinates.
996
+ * Returns null if the vertex is not smooth.
997
+ */
998
+ getBezierControlPoints(
999
+ vertexIndex: number
1000
+ ): { cp1: [number, number]; cp2: [number, number] } | null {
1001
+ const model = this._getPolygonModel();
1002
+ if (!model || !model.vertices) return null;
1003
+ if (!model.smoothFlags || !model.smoothFlags[vertexIndex]) return null;
1004
+
1005
+ const bound = Bound.deserialize(model.xywh);
1006
+
1007
+ // Check for custom control points first
1008
+ const custom = model.controlPoints?.[vertexIndex];
1009
+ if (custom) {
1010
+ const cp1: [number, number] = [
1011
+ custom[0] * bound.w + bound.x,
1012
+ custom[1] * bound.h + bound.y,
1013
+ ];
1014
+ const cp2: [number, number] = [
1015
+ custom[2] * bound.w + bound.x,
1016
+ custom[3] * bound.h + bound.y,
1017
+ ];
1018
+ return { cp1, cp2 };
1019
+ }
1020
+
1021
+ // Fall back to auto-computation
1022
+ const vertices = model.vertices;
1023
+ const count = vertices.length;
1024
+
1025
+ const prev = this._toAbsolute(vertices[(vertexIndex - 1 + count) % count], bound);
1026
+ const curr = this._toAbsolute(vertices[vertexIndex], bound);
1027
+ const next = this._toAbsolute(vertices[(vertexIndex + 1) % count], bound);
1028
+
1029
+ const dx1 = prev[0] - curr[0];
1030
+ const dy1 = prev[1] - curr[1];
1031
+ const dx2 = next[0] - curr[0];
1032
+ const dy2 = next[1] - curr[1];
1033
+
1034
+ const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1) || 1;
1035
+ const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2) || 1;
1036
+
1037
+ const cpDist1 = len1 / 3;
1038
+ const cpDist2 = len2 / 3;
1039
+
1040
+ const cp1: [number, number] = [
1041
+ curr[0] + (dx1 / len1) * cpDist1,
1042
+ curr[1] + (dy1 / len1) * cpDist1,
1043
+ ];
1044
+ const cp2: [number, number] = [
1045
+ curr[0] + (dx2 / len2) * cpDist2,
1046
+ curr[1] + (dy2 / len2) * cpDist2,
1047
+ ];
1048
+
1049
+ return { cp1, cp2 };
1050
+ }
1051
+
1052
+ // ── Rendering ───────────────────────────────────────────────────────
1053
+
1054
+ override render(ctx: CanvasRenderingContext2D, _rc: RoughCanvas): void {
1055
+ const model = this._getPolygonModel();
1056
+ if (!model || !model.vertices) return;
1057
+ if (!this.isEditing && this.hoveredVertexIndex < 0) return;
1058
+
1059
+ const bound = Bound.deserialize(model.xywh);
1060
+ const zoom = this.gfx.viewport.zoom;
1061
+ const vertices = model.vertices;
1062
+
1063
+ ctx.save();
1064
+ ctx.globalAlpha = this.globalAlpha;
1065
+
1066
+ // ── Apply rotation around shape center ─────────────────────────
1067
+ const rotate = model.rotate ?? 0;
1068
+ if (rotate) {
1069
+ const cx = bound.x + bound.w / 2;
1070
+ const cy = bound.y + bound.h / 2;
1071
+ const rad = (rotate * Math.PI) / 180;
1072
+ ctx.translate(cx, cy);
1073
+ ctx.rotate(rad);
1074
+ ctx.translate(-cx, -cy);
1075
+ }
1076
+
1077
+ // ── Draw snap guides ────────────────────────────────────────────
1078
+ if (this.activeVertexIndex >= 0) {
1079
+ ctx.setLineDash([4 / zoom, 3 / zoom]);
1080
+ ctx.lineWidth = 1 / zoom;
1081
+ ctx.strokeStyle = SNAP_GUIDE_COLOR;
1082
+
1083
+ if (this.snapGuideX !== null) {
1084
+ ctx.beginPath();
1085
+ ctx.moveTo(this.snapGuideX, bound.y - 20 / zoom);
1086
+ ctx.lineTo(this.snapGuideX, bound.y + bound.h + 20 / zoom);
1087
+ ctx.stroke();
1088
+ }
1089
+ if (this.snapGuideY !== null) {
1090
+ ctx.beginPath();
1091
+ ctx.moveTo(bound.x - 20 / zoom, this.snapGuideY);
1092
+ ctx.lineTo(bound.x + bound.w + 20 / zoom, this.snapGuideY);
1093
+ ctx.stroke();
1094
+ }
1095
+ ctx.setLineDash([]);
1096
+ }
1097
+
1098
+ // ── Draw Bezier control handles ────────────────────────────────
1099
+ if (this.isEditing && model.smoothFlags) {
1100
+ for (let i = 0; i < vertices.length; i++) {
1101
+ if (!model.smoothFlags[i]) continue;
1102
+ const cp = this.getBezierControlPoints(i);
1103
+ if (!cp) continue;
1104
+
1105
+ const [ax, ay] = this._toAbsolute(vertices[i], bound);
1106
+ const cpR = BEZIER_HANDLE_RADIUS / zoom;
1107
+
1108
+ // Draw control lines
1109
+ ctx.beginPath();
1110
+ ctx.moveTo(cp.cp1[0], cp.cp1[1]);
1111
+ ctx.lineTo(ax, ay);
1112
+ ctx.lineTo(cp.cp2[0], cp.cp2[1]);
1113
+ ctx.strokeStyle = BEZIER_LINE_COLOR;
1114
+ ctx.lineWidth = 1 / zoom;
1115
+ ctx.setLineDash([3 / zoom, 2 / zoom]);
1116
+ ctx.stroke();
1117
+ ctx.setLineDash([]);
1118
+
1119
+ // Draw control point handles
1120
+ for (const cp_pt of [cp.cp1, cp.cp2]) {
1121
+ ctx.beginPath();
1122
+ ctx.arc(cp_pt[0], cp_pt[1], cpR, 0, Math.PI * 2);
1123
+ ctx.fillStyle = BEZIER_HANDLE_COLOR;
1124
+ ctx.fill();
1125
+ ctx.strokeStyle = '#ffffff';
1126
+ ctx.lineWidth = 1 / zoom;
1127
+ ctx.stroke();
1128
+ }
1129
+ }
1130
+ }
1131
+
1132
+ // ── Draw edge midpoint handles ──────────────────────────────────
1133
+ if (this.isEditing) {
1134
+ for (let i = 0; i < vertices.length; i++) {
1135
+ const [ax, ay] = this._toAbsolute(vertices[i], bound);
1136
+ const nextIdx = (i + 1) % vertices.length;
1137
+ const [bx, by] = this._toAbsolute(vertices[nextIdx], bound);
1138
+ const mx = (ax + bx) / 2;
1139
+ const my = (ay + by) / 2;
1140
+
1141
+ const isHoveredMid = i === this.hoveredMidpointIndex;
1142
+ const midR = (isHoveredMid ? MIDPOINT_HANDLE_HOVER_RADIUS : MIDPOINT_HANDLE_RADIUS) / zoom;
1143
+ const midFill = isHoveredMid ? MIDPOINT_HOVER_FILL_COLOR : MIDPOINT_FILL_COLOR;
1144
+
1145
+ ctx.beginPath();
1146
+ ctx.arc(mx, my, midR, 0, Math.PI * 2);
1147
+ ctx.fillStyle = midFill;
1148
+ ctx.fill();
1149
+ ctx.strokeStyle = isHoveredMid ? '#228be6' : '#868e96';
1150
+ ctx.lineWidth = (isHoveredMid ? 1.5 : 1) / zoom;
1151
+ ctx.stroke();
1152
+ }
1153
+ }
1154
+
1155
+ // ── Draw vertex handles ─────────────────────────────────────────
1156
+ for (let i = 0; i < vertices.length; i++) {
1157
+ const [ax, ay] = this._toAbsolute(vertices[i], bound);
1158
+ const isHovered = i === this.hoveredVertexIndex;
1159
+ const isActive = i === this.activeVertexIndex;
1160
+
1161
+ let radius: number;
1162
+ let fillColor: string;
1163
+ let strokeWidth: number;
1164
+
1165
+ if (isActive) {
1166
+ radius = VERTEX_HANDLE_ACTIVE_RADIUS / zoom;
1167
+ fillColor = HANDLE_ACTIVE_FILL_COLOR;
1168
+ strokeWidth = 2 / zoom;
1169
+ } else if (isHovered) {
1170
+ radius = VERTEX_HANDLE_HOVER_RADIUS / zoom;
1171
+ fillColor = HANDLE_HOVER_FILL_COLOR;
1172
+ strokeWidth = 2 / zoom;
1173
+ } else {
1174
+ radius = VERTEX_HANDLE_RADIUS / zoom;
1175
+ fillColor = HANDLE_FILL_COLOR;
1176
+ strokeWidth = 1.5 / zoom;
1177
+ }
1178
+
1179
+ // Outer stroke
1180
+ ctx.beginPath();
1181
+ ctx.arc(ax, ay, radius, 0, Math.PI * 2);
1182
+ ctx.fillStyle = fillColor;
1183
+ ctx.fill();
1184
+ ctx.strokeStyle = '#228be6';
1185
+ ctx.lineWidth = strokeWidth;
1186
+ ctx.stroke();
1187
+
1188
+ // Smooth vertex indicator (diamond shape on top of circle)
1189
+ if (this.isEditing && model.smoothFlags && model.smoothFlags[i]) {
1190
+ const dSize = 3.5 / zoom;
1191
+ ctx.beginPath();
1192
+ ctx.moveTo(ax, ay - dSize);
1193
+ ctx.lineTo(ax + dSize, ay);
1194
+ ctx.lineTo(ax, ay + dSize);
1195
+ ctx.lineTo(ax - dSize, ay);
1196
+ ctx.closePath();
1197
+ ctx.fillStyle = BEZIER_HANDLE_COLOR;
1198
+ ctx.fill();
1199
+ }
1200
+
1201
+ // Index label for editing mode (only when editing and zoomed in enough)
1202
+ if (this.isEditing && zoom >= 1.5) {
1203
+ ctx.font = `${10 / zoom}px sans-serif`;
1204
+ ctx.fillStyle = '#228be6';
1205
+ ctx.textAlign = 'center';
1206
+ ctx.textBaseline = 'bottom';
1207
+ ctx.fillText(`${i}`, ax, ay - radius - 2 / zoom);
1208
+ }
1209
+ }
1210
+
1211
+ ctx.restore();
1212
+ }
1213
+ }