@formicoidea/labre-core 0.43.1 → 0.46.0

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 (300) hide show
  1. package/dist/_pkgs/affine-block-attachment/utils.js +4 -0
  2. package/dist/_pkgs/affine-block-bookmark/configs/toolbar.js +17 -4
  3. package/dist/_pkgs/affine-block-callout/commands/turn-callout-into.d.ts +43 -0
  4. package/dist/_pkgs/affine-block-callout/commands/turn-callout-into.js +109 -0
  5. package/dist/_pkgs/affine-block-callout/commands/turn-into-callout.d.ts +29 -0
  6. package/dist/_pkgs/affine-block-callout/commands/turn-into-callout.js +81 -0
  7. package/dist/_pkgs/affine-block-callout/configs/slash-menu.js +6 -4
  8. package/dist/_pkgs/affine-block-callout/configs/toolbar.d.ts +65 -0
  9. package/dist/_pkgs/affine-block-callout/configs/toolbar.js +178 -0
  10. package/dist/_pkgs/affine-block-callout/configs/turn-into.d.ts +8 -0
  11. package/dist/_pkgs/affine-block-callout/configs/turn-into.js +19 -0
  12. package/dist/_pkgs/affine-block-callout/translations.d.ts +4 -2
  13. package/dist/_pkgs/affine-block-callout/translations.js +4 -2
  14. package/dist/_pkgs/affine-block-callout/view.js +10 -1
  15. package/dist/_pkgs/affine-block-code/code-block-service.d.ts +13 -0
  16. package/dist/_pkgs/affine-block-code/code-block-service.js +26 -0
  17. package/dist/_pkgs/affine-block-code/code-block.d.ts +6 -0
  18. package/dist/_pkgs/affine-block-code/code-block.js +11 -2
  19. package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +31 -8
  20. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.d.ts +11 -0
  21. package/dist/_pkgs/affine-block-edgeless-text/svg-painter.d.ts +20 -0
  22. package/dist/_pkgs/affine-block-edgeless-text/svg-painter.js +76 -0
  23. package/dist/_pkgs/affine-block-edgeless-text/view.js +2 -0
  24. package/dist/_pkgs/affine-block-embed/configs/toolbar.js +11 -2
  25. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +11 -2
  26. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-edgeless-linked-doc-block.js +3 -1
  27. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +7 -2
  28. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-edgeless-synced-doc-block.js +3 -1
  29. package/dist/_pkgs/affine-block-frame/commands.d.ts +27 -0
  30. package/dist/_pkgs/affine-block-frame/commands.js +49 -0
  31. package/dist/_pkgs/affine-block-frame/frame-manager.d.ts +16 -6
  32. package/dist/_pkgs/affine-block-frame/frame-manager.js +58 -22
  33. package/dist/_pkgs/affine-block-frame/frame-order.d.ts +43 -0
  34. package/dist/_pkgs/affine-block-frame/frame-order.js +93 -0
  35. package/dist/_pkgs/affine-block-frame/frame-tool.js +3 -1
  36. package/dist/_pkgs/affine-block-frame/index.d.ts +2 -0
  37. package/dist/_pkgs/affine-block-frame/index.js +2 -0
  38. package/dist/_pkgs/affine-block-frame/present/frame-order-menu.d.ts +10 -2
  39. package/dist/_pkgs/affine-block-frame/present/frame-order-menu.js +32 -18
  40. package/dist/_pkgs/affine-block-frame/view.js +6 -0
  41. package/dist/_pkgs/affine-block-image/utils.js +4 -1
  42. package/dist/_pkgs/affine-block-latex/adapters/markdown/preprocessor.d.ts +8 -0
  43. package/dist/_pkgs/affine-block-latex/adapters/markdown/preprocessor.js +9 -5
  44. package/dist/_pkgs/affine-block-note/configs/toolbar.d.ts +19 -0
  45. package/dist/_pkgs/affine-block-note/configs/toolbar.js +38 -23
  46. package/dist/_pkgs/affine-block-note/translations.d.ts +2 -1
  47. package/dist/_pkgs/affine-block-note/translations.js +14 -6
  48. package/dist/_pkgs/affine-block-root/configs/toolbar.js +48 -3
  49. package/dist/_pkgs/affine-block-root/edgeless/clipboard/clipboard.js +2 -1
  50. package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +161 -83
  51. package/dist/_pkgs/affine-block-root/edgeless/clipboard/paste-order.d.ts +21 -0
  52. package/dist/_pkgs/affine-block-root/edgeless/clipboard/paste-order.js +85 -0
  53. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.d.ts +6 -0
  54. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +18 -1
  55. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.d.ts +9 -0
  56. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.js +28 -0
  57. package/dist/_pkgs/affine-block-root/keyboard/commands.js +9 -6
  58. package/dist/_pkgs/affine-block-root/preview/edgeless-root-preview-block.js +15 -2
  59. package/dist/_pkgs/affine-block-root/translations.d.ts +7 -2
  60. package/dist/_pkgs/affine-block-root/translations.js +10 -13
  61. package/dist/_pkgs/affine-block-surface/adapters/markdown/element-adapter/type.d.ts +1 -1
  62. package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +1 -1
  63. package/dist/_pkgs/affine-block-surface/element-model/index.js +1 -1
  64. package/dist/_pkgs/affine-block-surface/extensions/audit.js +13 -61
  65. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.d.ts +2 -0
  66. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.js +71 -0
  67. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/index.d.ts +1 -0
  68. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/index.js +1 -0
  69. package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +4 -0
  70. package/dist/_pkgs/affine-block-surface/extensions/crud-extension.js +4 -0
  71. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.d.ts +12 -0
  72. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +27 -7
  73. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +2 -1
  74. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +22 -3
  75. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +6 -3
  76. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +4 -2
  77. package/dist/_pkgs/affine-block-surface/extensions/export-svg/parts.d.ts +63 -0
  78. package/dist/_pkgs/affine-block-surface/extensions/export-svg/parts.js +67 -0
  79. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +62 -5
  80. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +98 -18
  81. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +14 -0
  82. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +82 -1
  83. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.d.ts +2 -2
  84. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.js +112 -10
  85. package/dist/_pkgs/affine-block-surface/extensions/export-svg/translations.d.ts +13 -0
  86. package/dist/_pkgs/affine-block-surface/extensions/export-svg/translations.js +33 -0
  87. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +3 -0
  88. package/dist/_pkgs/affine-block-surface/extensions/index.js +3 -0
  89. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +13 -6
  90. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +26 -10
  91. package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +82 -6
  92. package/dist/_pkgs/affine-block-surface/extensions/reading.js +99 -21
  93. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.d.ts +91 -0
  94. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.js +285 -0
  95. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.d.ts +80 -0
  96. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.js +355 -0
  97. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.d.ts +3 -0
  98. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.js +3 -0
  99. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/tree.d.ts +137 -0
  100. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/tree.js +323 -0
  101. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +112 -4
  102. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +86 -15
  103. package/dist/_pkgs/affine-block-surface/extensions/user-layers/actions.d.ts +76 -0
  104. package/dist/_pkgs/affine-block-surface/extensions/user-layers/actions.js +299 -0
  105. package/dist/_pkgs/affine-block-surface/extensions/user-layers/active-layer.d.ts +20 -0
  106. package/dist/_pkgs/affine-block-surface/extensions/user-layers/active-layer.js +34 -0
  107. package/dist/_pkgs/affine-block-surface/extensions/user-layers/commands.d.ts +67 -0
  108. package/dist/_pkgs/affine-block-surface/extensions/user-layers/commands.js +172 -0
  109. package/dist/_pkgs/affine-block-surface/extensions/user-layers/creation.d.ts +40 -0
  110. package/dist/_pkgs/affine-block-surface/extensions/user-layers/creation.js +69 -0
  111. package/dist/_pkgs/affine-block-surface/extensions/user-layers/index.d.ts +5 -0
  112. package/dist/_pkgs/affine-block-surface/extensions/user-layers/index.js +5 -0
  113. package/dist/_pkgs/affine-block-surface/extensions/user-layers/translations.d.ts +10 -0
  114. package/dist/_pkgs/affine-block-surface/extensions/user-layers/translations.js +14 -0
  115. package/dist/_pkgs/affine-block-surface/framework-background/facts.d.ts +55 -2
  116. package/dist/_pkgs/affine-block-surface/framework-background/facts.js +63 -1
  117. package/dist/_pkgs/affine-block-surface/framework-background/stacking.d.ts +16 -8
  118. package/dist/_pkgs/affine-block-surface/framework-background/stacking.js +26 -14
  119. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +17 -3
  120. package/dist/_pkgs/affine-block-surface/renderer/dom-renderer.d.ts +3 -1
  121. package/dist/_pkgs/affine-block-surface/renderer/dom-renderer.js +22 -2
  122. package/dist/_pkgs/affine-block-surface/renderer/paint-predicate.d.ts +30 -0
  123. package/dist/_pkgs/affine-block-surface/renderer/paint-predicate.js +29 -0
  124. package/dist/_pkgs/affine-block-surface/surface-block.js +6 -0
  125. package/dist/_pkgs/affine-block-surface/surface-model.js +5 -0
  126. package/dist/_pkgs/affine-block-surface/surface-transformer.js +5 -0
  127. package/dist/_pkgs/affine-block-surface/tool/default-tool.js +28 -5
  128. package/dist/_pkgs/affine-block-surface/view.js +23 -1
  129. package/dist/_pkgs/affine-block-surface-ref/surface-ref-block.js +12 -2
  130. package/dist/_pkgs/affine-components/context-menu/button.js +14 -0
  131. package/dist/_pkgs/affine-components/filterable-list/index.js +30 -9
  132. package/dist/_pkgs/affine-components/icons/index.d.ts +0 -1
  133. package/dist/_pkgs/affine-components/icons/index.js +0 -1
  134. package/dist/_pkgs/affine-components/icons/text.d.ts +1 -0
  135. package/dist/_pkgs/affine-components/icons/text.js +11 -0
  136. package/dist/_pkgs/affine-components/portal/portal.d.ts +1 -1
  137. package/dist/_pkgs/affine-foundation/view.d.ts +8 -8
  138. package/dist/_pkgs/affine-fragment-adapter-panel/adapter-panel.d.ts +2 -2
  139. package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.d.ts +34 -2
  140. package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.js +194 -81
  141. package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.d.ts +7 -4
  142. package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +9 -24
  143. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.d.ts +1 -1
  144. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.js +8 -27
  145. package/dist/_pkgs/affine-fragment-frame-panel/index.d.ts +2 -0
  146. package/dist/_pkgs/affine-fragment-frame-panel/index.js +2 -0
  147. package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +3 -1
  148. package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +21 -4
  149. package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +3 -2
  150. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +1 -1
  151. package/dist/_pkgs/affine-gfx-group/command/group-api.js +52 -1
  152. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/index.js +21 -3
  153. package/dist/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.js +2 -0
  154. package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +1 -1
  155. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +9 -0
  156. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +23 -1
  157. package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
  158. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +2 -1
  159. package/dist/_pkgs/affine-gfx-text/element-renderer/index.js +20 -3
  160. package/dist/_pkgs/affine-gfx-text/element-renderer/utils.d.ts +67 -1
  161. package/dist/_pkgs/affine-gfx-text/element-renderer/utils.js +101 -0
  162. package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +11 -0
  163. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +53 -2
  164. package/dist/_pkgs/affine-gfx-text/toolbar/config.d.ts +11 -0
  165. package/dist/_pkgs/affine-gfx-text/toolbar/config.js +1 -1
  166. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.d.ts +3 -0
  167. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.js +31 -0
  168. package/dist/_pkgs/affine-inline-preset/adapters/html/inline-delta.d.ts +4 -0
  169. package/dist/_pkgs/affine-inline-preset/adapters/html/inline-delta.js +14 -0
  170. package/dist/_pkgs/affine-inline-preset/command/config.js +21 -3
  171. package/dist/_pkgs/affine-inline-preset/command/index.d.ts +1 -1
  172. package/dist/_pkgs/affine-inline-preset/command/index.js +1 -1
  173. package/dist/_pkgs/affine-inline-preset/command/text-style.d.ts +2 -1
  174. package/dist/_pkgs/affine-inline-preset/command/text-style.js +1 -0
  175. package/dist/_pkgs/affine-inline-preset/default-inline-manager.js +2 -1
  176. package/dist/_pkgs/affine-inline-preset/inline-spec.d.ts +4 -0
  177. package/dist/_pkgs/affine-inline-preset/inline-spec.js +14 -0
  178. package/dist/_pkgs/affine-inline-preset/translations.d.ts +2 -2
  179. package/dist/_pkgs/affine-inline-preset/translations.js +2 -2
  180. package/dist/_pkgs/affine-model/blocks/attachment/attachment-model.js +2 -0
  181. package/dist/_pkgs/affine-model/blocks/bookmark/bookmark-model.js +2 -0
  182. package/dist/_pkgs/affine-model/blocks/edgeless-text/edgeless-text-model.d.ts +1 -1
  183. package/dist/_pkgs/affine-model/blocks/edgeless-text/edgeless-text-model.js +2 -0
  184. package/dist/_pkgs/affine-model/blocks/embed/iframe/iframe-model.js +2 -0
  185. package/dist/_pkgs/affine-model/blocks/frame/frame-model.js +2 -0
  186. package/dist/_pkgs/affine-model/blocks/image/image-model.js +2 -0
  187. package/dist/_pkgs/affine-model/blocks/latex/latex-model.js +2 -0
  188. package/dist/_pkgs/affine-model/blocks/note/note-model.js +2 -0
  189. package/dist/_pkgs/affine-model/consts/text.d.ts +26 -0
  190. package/dist/_pkgs/affine-model/consts/text.js +25 -0
  191. package/dist/_pkgs/affine-model/elements/shape/shape.d.ts +6 -1
  192. package/dist/_pkgs/affine-model/elements/shape/shape.js +14 -1
  193. package/dist/_pkgs/affine-model/elements/text/text.d.ts +6 -1
  194. package/dist/_pkgs/affine-model/elements/text/text.js +13 -1
  195. package/dist/_pkgs/affine-model/utils/helper.js +2 -0
  196. package/dist/_pkgs/affine-model/utils/types.d.ts +2 -2
  197. package/dist/_pkgs/affine-rich-text/conversion.d.ts +25 -0
  198. package/dist/_pkgs/affine-rich-text/conversion.js +9 -0
  199. package/dist/_pkgs/affine-rich-text/index.d.ts +1 -1
  200. package/dist/_pkgs/affine-rich-text/index.js +1 -1
  201. package/dist/_pkgs/affine-shared/commands/model-crud/replace-selected-text-with-blocks.d.ts +1 -1
  202. package/dist/_pkgs/affine-shared/services/canvas-grid.d.ts +63 -0
  203. package/dist/_pkgs/affine-shared/services/canvas-grid.js +109 -0
  204. package/dist/_pkgs/affine-shared/services/canvas-local-visibility.d.ts +64 -0
  205. package/dist/_pkgs/affine-shared/services/canvas-local-visibility.js +192 -0
  206. package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +31 -4
  207. package/dist/_pkgs/affine-shared/services/edit-props-store.js +34 -0
  208. package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
  209. package/dist/_pkgs/affine-shared/services/editor-setting-service.js +7 -0
  210. package/dist/_pkgs/affine-shared/services/feature-flag-service.d.ts +4 -0
  211. package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +2 -2
  212. package/dist/_pkgs/affine-shared/services/font-loader/font-loader-service.d.ts +3 -3
  213. package/dist/_pkgs/affine-shared/services/index.d.ts +4 -1
  214. package/dist/_pkgs/affine-shared/services/index.js +4 -1
  215. package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-storage.d.ts +4 -4
  216. package/dist/_pkgs/affine-shared/services/outline-panel-service.d.ts +31 -0
  217. package/dist/_pkgs/affine-shared/services/outline-panel-service.js +17 -0
  218. package/dist/_pkgs/affine-shared/services/selection-pane-service.d.ts +44 -0
  219. package/dist/_pkgs/affine-shared/services/selection-pane-service.js +28 -0
  220. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +69 -0
  221. package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
  222. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +16 -0
  223. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +28 -0
  224. package/dist/_pkgs/affine-shared/styles/index.d.ts +1 -0
  225. package/dist/_pkgs/affine-shared/styles/index.js +1 -0
  226. package/dist/_pkgs/affine-shared/styles/panel-header.d.ts +31 -0
  227. package/dist/_pkgs/affine-shared/styles/panel-header.js +61 -0
  228. package/dist/_pkgs/affine-shared/styles/text.js +7 -7
  229. package/dist/_pkgs/affine-shared/types/index.d.ts +6 -0
  230. package/dist/_pkgs/affine-shared/utils/canvas-export-colors.d.ts +26 -0
  231. package/dist/_pkgs/affine-shared/utils/canvas-export-colors.js +127 -0
  232. package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +8 -11
  233. package/dist/_pkgs/affine-shared/utils/file/filesys.js +8 -11
  234. package/dist/_pkgs/affine-shared/utils/index.d.ts +3 -0
  235. package/dist/_pkgs/affine-shared/utils/index.js +3 -0
  236. package/dist/_pkgs/affine-shared/utils/label-mode.d.ts +47 -0
  237. package/dist/_pkgs/affine-shared/utils/label-mode.js +55 -0
  238. package/dist/_pkgs/affine-shared/utils/model/merge-to-code-model.js +7 -1
  239. package/dist/_pkgs/affine-shared/utils/model/transform-model.js +5 -0
  240. package/dist/_pkgs/affine-shared/utils/panel-reorder-drag.d.ts +85 -0
  241. package/dist/_pkgs/affine-shared/utils/panel-reorder-drag.js +162 -0
  242. package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +10 -3
  243. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +25 -49
  244. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.d.ts +4 -0
  245. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.js +4 -0
  246. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +4 -0
  247. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +4 -0
  248. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.d.ts +62 -0
  249. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.js +94 -0
  250. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/labels.d.ts +17 -0
  251. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/labels.js +95 -0
  252. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-default.d.ts +10 -0
  253. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-default.js +31 -0
  254. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-tool.d.ts +26 -0
  255. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-tool.js +82 -0
  256. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.d.ts +186 -0
  257. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.js +1417 -0
  258. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.d.ts +52 -0
  259. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.js +161 -1
  260. package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +10 -0
  261. package/dist/_pkgs/affine-widget-note-slicer/note-slicer.js +7 -3
  262. package/dist/_pkgs/std/gfx/controller.d.ts +13 -0
  263. package/dist/_pkgs/std/gfx/controller.js +22 -2
  264. package/dist/_pkgs/std/gfx/grid.d.ts +31 -2
  265. package/dist/_pkgs/std/gfx/index.d.ts +3 -1
  266. package/dist/_pkgs/std/gfx/index.js +3 -1
  267. package/dist/_pkgs/std/gfx/interactivity/manager.js +7 -0
  268. package/dist/_pkgs/std/gfx/layer.js +73 -5
  269. package/dist/_pkgs/std/gfx/local-visibility.d.ts +88 -0
  270. package/dist/_pkgs/std/gfx/local-visibility.js +217 -0
  271. package/dist/_pkgs/std/gfx/model/gfx-block-model.d.ts +13 -0
  272. package/dist/_pkgs/std/gfx/model/surface/element-model.d.ts +34 -0
  273. package/dist/_pkgs/std/gfx/model/surface/element-model.js +65 -1
  274. package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +27 -0
  275. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +43 -0
  276. package/dist/_pkgs/std/gfx/model/surface/user-layers.d.ts +68 -0
  277. package/dist/_pkgs/std/gfx/model/surface/user-layers.js +127 -0
  278. package/dist/_pkgs/std/scope/std-scope.d.ts +1 -1
  279. package/dist/_pkgs/std/utils/layer.d.ts +10 -0
  280. package/dist/_pkgs/std/utils/layer.js +64 -13
  281. package/dist/_pkgs/std/view/element/gfx-block-component.js +10 -2
  282. package/dist/commands.js +6 -1
  283. package/dist/host-panels.d.ts +90 -0
  284. package/dist/host-panels.js +111 -0
  285. package/dist/translations.js +10 -6
  286. package/package.json +13 -2
  287. package/dist/_pkgs/affine-components/icons/file-icons-rc.d.ts +0 -1
  288. package/dist/_pkgs/affine-components/icons/file-icons-rc.js +0 -130
  289. package/dist/_pkgs/affine-fragment-frame-panel/utils/drag.d.ts +0 -27
  290. package/dist/_pkgs/affine-fragment-frame-panel/utils/drag.js +0 -96
  291. package/dist/_pkgs/affine-shared/services/sidebar-service.d.ts +0 -8
  292. package/dist/_pkgs/affine-shared/services/sidebar-service.js +0 -7
  293. package/dist/_pkgs/affine-shared/test-utils/affine-template.d.ts +0 -6
  294. package/dist/_pkgs/affine-shared/test-utils/affine-template.js +0 -258
  295. package/dist/_pkgs/affine-shared/test-utils/affine-test-utils.d.ts +0 -8
  296. package/dist/_pkgs/affine-shared/test-utils/affine-test-utils.js +0 -81
  297. package/dist/_pkgs/affine-shared/test-utils/create-test-host.d.ts +0 -23
  298. package/dist/_pkgs/affine-shared/test-utils/create-test-host.js +0 -187
  299. package/dist/_pkgs/affine-shared/test-utils/index.d.ts +0 -3
  300. package/dist/_pkgs/affine-shared/test-utils/index.js +0 -3
@@ -33,7 +33,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
33
33
  return useValue ? value : void 0;
34
34
  };
35
35
  import { DefaultTool, EdgelessCRUDIdentifier, } from '../../affine-block-surface/index.js';
36
- import { getLineHeight } from '../../affine-gfx-text/index.js';
36
+ import { getLineHeight, textDecorationLine } from '../../affine-gfx-text/index.js';
37
37
  import { connectorEndLabelBox, } from '../../affine-model/index.js';
38
38
  import { ThemeProvider, translateKey } from '../../affine-shared/services/index.js';
39
39
  import { almostEqual } from '../../affine-shared/utils/index.js';
@@ -423,7 +423,7 @@ let EdgelessConnectorLabelEditor = (() => {
423
423
  }
424
424
  render() {
425
425
  const { connector } = this;
426
- const { labelStyle: { fontFamily, fontSize, fontStyle, fontWeight, textAlign, color: labelColor, }, labelConstraints: { hasMaxWidth, maxWidth }, } = connector;
426
+ const { labelStyle: { fontFamily, fontSize, fontStyle, fontWeight, textAlign, textDecoration, color: labelColor, }, labelConstraints: { hasMaxWidth, maxWidth }, } = connector;
427
427
  const lineHeight = getLineHeight(fontFamily, fontSize, fontWeight);
428
428
  const { translateX, translateY, zoom } = this.gfx.viewport;
429
429
  const [x, y] = Vec.mul(this._labelCenter, zoom);
@@ -447,6 +447,7 @@ let EdgelessConnectorLabelEditor = (() => {
447
447
  fontStyle,
448
448
  fontWeight,
449
449
  textAlign,
450
+ textDecorationLine: textDecorationLine(textDecoration),
450
451
  lineHeight: `${lineHeight}px`,
451
452
  maxWidth: hasMaxWidth
452
453
  ? `${maxWidth + BORDER_WIDTH * 2 + HORIZONTAL_PADDING * 2}px`
@@ -450,7 +450,7 @@ export const connectorToolbarConfig = {
450
450
  return;
451
451
  const labelStyle = { ...model.labelStyle, ...props };
452
452
  // No need to adjust element bounds
453
- if (props['textAlign']) {
453
+ if (props['textAlign'] || props['textDecoration']) {
454
454
  ctx.std
455
455
  .get(EdgelessCRUDIdentifier)
456
456
  .updateElement(model.id, { labelStyle });
@@ -1,7 +1,7 @@
1
1
  import { EdgelessCRUDIdentifier } from '../../affine-block-surface/index.js';
2
2
  import { MindmapElementModel, } from '../../affine-model/index.js';
3
3
  import { translateKey } from '../../affine-shared/services/index.js';
4
- import { batchAddChildren, batchRemoveChildren, generateKeyBetween, generateNKeysBetween, GfxControllerIdentifier, measureOperation, } from '../../std/gfx/index.js';
4
+ import { batchAddChildren, batchRemoveChildren, generateKeyBetween, generateNKeysBetween, GfxControllerIdentifier, GfxPrimitiveElementModel, measureOperation, } from '../../std/gfx/index.js';
5
5
  import { GROUP_SEED_NAME } from '../translations.js';
6
6
  /**
7
7
  * Every element that sits at the root of the board, in painting order.
@@ -65,12 +65,60 @@ const buildUngroupIndexes = (orderedElements, afterIndex, beforeIndex, fallbackA
65
65
  tryGenerateOneByOne(null, null) ??
66
66
  []);
67
67
  };
68
+ /**
69
+ * The layer a new group is stored in (ADR 0031 §5): the effective layer of
70
+ * its HIGHEST member, so grouping never sinks what was on top. `'@default'`
71
+ * is passed explicitly — the creation middleware then writes no key, rather
72
+ * than reading "absent" as "the viewer's active layer". Nothing at all while
73
+ * the surface has no user layer.
74
+ */
75
+ function groupLayerProps(gfx, elements) {
76
+ const userLayers = gfx.surface?.userLayers;
77
+ if (!userLayers?.ranks)
78
+ return {};
79
+ const models = elements
80
+ .map(el => (typeof el === 'string' ? gfx.getElementById(el) : el))
81
+ .filter((model) => !!model && 'index' in model)
82
+ .sort((a, b) => gfx.layer.compare(a, b));
83
+ const highest = models.at(-1);
84
+ return highest ? { layer: userLayers.effectiveLayerOf(highest) } : {};
85
+ }
86
+ /**
87
+ * Ungrouping a top-level group hands its layer to each released child, in
88
+ * the ungroup's own transaction (ADR 0031 §5): a member's own `layer` was
89
+ * ignored while it was inside, and may be stale.
90
+ */
91
+ function releaseChildrenToGroupLayer(gfx, group, children) {
92
+ const userLayers = gfx.surface?.userLayers;
93
+ if (!userLayers?.ranks)
94
+ return;
95
+ const layer = group.layer;
96
+ for (const child of children) {
97
+ const own = child instanceof GfxPrimitiveElementModel
98
+ ? child.layer
99
+ : child.props.layer;
100
+ if (own === layer)
101
+ continue;
102
+ if (layer === undefined) {
103
+ if (child instanceof GfxPrimitiveElementModel) {
104
+ child.clearField('layer');
105
+ }
106
+ else {
107
+ delete child.props.layer;
108
+ }
109
+ }
110
+ else {
111
+ gfx.updateElement(child, { layer });
112
+ }
113
+ }
114
+ }
68
115
  export const createGroupCommand = (ctx, next) => {
69
116
  const { std, elements } = ctx;
70
117
  const gfx = std.get(GfxControllerIdentifier);
71
118
  const crud = std.get(EdgelessCRUDIdentifier);
72
119
  const groups = gfx.layer.canvasElements.filter(el => el.type === 'group');
73
120
  const groupId = crud.addElement('group', {
121
+ ...groupLayerProps(gfx, elements),
74
122
  children: elements.reduce((pre, el) => {
75
123
  const id = typeof el === 'string' ? el : el.id;
76
124
  pre[id] = true;
@@ -175,6 +223,9 @@ export const ungroupCommand = (ctx, next) => {
175
223
  if (parent !== null) {
176
224
  batchAddChildren(parent, orderedElements);
177
225
  }
226
+ else {
227
+ releaseChildrenToGroupLayer(gfx, group, orderedElements);
228
+ }
178
229
  });
179
230
  selection.set({
180
231
  editing: false,
@@ -1,5 +1,5 @@
1
1
  import { ElementRendererExtension, } from '../../../affine-block-surface/index.js';
2
- import { getFontMetrics, getFontString, getLineWidth, isRTL, measureTextInDOM, wrapTextDeltas, } from '../../../affine-gfx-text/index.js';
2
+ import { getFontMetrics, getFontString, getLineWidth, isRTL, measureTextInDOM, paintTextDecoration, wrapTextDeltas, } from '../../../affine-gfx-text/index.js';
3
3
  import { DefaultTheme, TextAlign } from '../../../affine-model/index.js';
4
4
  import { Bound } from '../../../global/gfx/index.js';
5
5
  import { deltaInsertsToChunks } from '../../../std/inline/index.js';
@@ -33,6 +33,8 @@ function renderText(model, ctx, { color }) {
33
33
  const { x, y, text, fontFamily, fontWeight, textAlign, w, h, textVerticalAlign, padding, } = model;
34
34
  if (!text)
35
35
  return;
36
+ // A local preview shape has no stored decoration.
37
+ const textDecoration = 'textDecoration' in model ? model.textDecoration : undefined;
36
38
  // Contained mode shrinks the layout font size so the text fits the bounds.
37
39
  const fontSize = effectiveShapeFontSize(model);
38
40
  const [verticalPadding, horPadding] = padding;
@@ -69,9 +71,25 @@ function renderText(model, ctx, { color }) {
69
71
  if (ctx.canvas.dir !== (rtl ? 'rtl' : 'ltr')) {
70
72
  ctx.canvas.setAttribute('dir', rtl ? 'rtl' : 'ltr');
71
73
  }
72
- ctx.fillText(str,
73
74
  // 0.5 is the dom editor padding to make the text align with the DOM text
74
- horOffset + 0.5, lineIndex * lineHeight + vertOffset);
75
+ const textX = horOffset + 0.5;
76
+ const baselineY = lineIndex * lineHeight + vertOffset;
77
+ ctx.fillText(str, textX, baselineY);
78
+ if (textDecoration) {
79
+ // Already on the alphabetic baseline, at the size Contained mode
80
+ // shrank the text to.
81
+ paintTextDecoration(ctx, {
82
+ decoration: textDecoration,
83
+ lineText: str,
84
+ font,
85
+ x: textX,
86
+ baselineY,
87
+ fontFamily,
88
+ fontSize,
89
+ fontWeight,
90
+ color,
91
+ });
92
+ }
75
93
  maxLineWidth = Math.max(maxLineWidth, getLineWidth(str, font));
76
94
  if (shouldTemporarilyAttach) {
77
95
  ctx.canvas.remove();
@@ -33,6 +33,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
33
33
  return useValue ? value : void 0;
34
34
  };
35
35
  import { DefaultTool, EdgelessCRUDIdentifier, TextUtils, } from '../../affine-block-surface/index.js';
36
+ import { textDecorationLine } from '../../affine-gfx-text/index.js';
36
37
  import { MindmapElementModel, ShapeElementModel, TextFitMode, TextResizing, } from '../../affine-model/index.js';
37
38
  import { ThemeProvider } from '../../affine-shared/services/index.js';
38
39
  import { getSelectedRect, overlayScale, toOverlayCoord, } from '../../affine-shared/utils/index.js';
@@ -427,6 +428,7 @@ let EdgelessShapeTextEditor = (() => {
427
428
  color,
428
429
  padding: `${verticalPadding}px ${horiPadding}px`,
429
430
  textAlign: this.element.textAlign,
431
+ textDecorationLine: textDecorationLine(this.element.textDecoration),
430
432
  display: 'grid',
431
433
  gridTemplateColumns: '100%',
432
434
  alignItems: this.element.textVerticalAlign === 'center'
@@ -294,7 +294,7 @@ export const shapeToolbarConfig = {
294
294
  // id: `g.text`
295
295
  ...createTextActions(ShapeElementModel, 'shape', (ctx, model, props) => {
296
296
  // No need to adjust element bounds
297
- if (props['textAlign']) {
297
+ if (props['textAlign'] || props['textDecoration']) {
298
298
  ctx.std.get(EdgelessCRUDIdentifier).updateElement(model.id, props);
299
299
  return;
300
300
  }
@@ -1,5 +1,14 @@
1
1
  import { Bound } from '../../global/gfx/index.js';
2
+ import type { BlockStdScope } from '../../std/index.js';
2
3
  import type { TemplateJob } from './template.js';
4
+ /**
5
+ * Everything a template inserts lands in the viewer's active layer (ADR 0031
6
+ * §6). The insertion bypasses both stamped paths — its elements are merged
7
+ * straight into the surface's elements map, its blocks go through
8
+ * `store.addBlock` — so the layer is stamped on the snapshot before it is
9
+ * written, with the same rule as every other creation.
10
+ */
11
+ export declare const createActiveLayerMiddleware: (std: BlockStdScope) => (job: TemplateJob) => void;
3
12
  export declare const replaceIdMiddleware: (job: TemplateJob) => void;
4
13
  export declare const createInsertPlaceMiddleware: (targetPlace: Bound) => (job: TemplateJob) => void;
5
14
  export declare const createStickerMiddleware: (center: {
@@ -1,6 +1,28 @@
1
- import { generateElementId, sortIndex } from '../../affine-block-surface/index.js';
1
+ import { applyCreationLayer, generateElementId, sortIndex, } from '../../affine-block-surface/index.js';
2
2
  import { Bound } from '../../global/gfx/index.js';
3
3
  import { assertType } from '../../global/utils/index.js';
4
+ /**
5
+ * Everything a template inserts lands in the viewer's active layer (ADR 0031
6
+ * §6). The insertion bypasses both stamped paths — its elements are merged
7
+ * straight into the surface's elements map, its blocks go through
8
+ * `store.addBlock` — so the layer is stamped on the snapshot before it is
9
+ * written, with the same rule as every other creation.
10
+ */
11
+ export const createActiveLayerMiddleware = (std) => {
12
+ return (job) => {
13
+ job.slots.beforeInsert.subscribe(payload => {
14
+ if (payload.type !== 'block')
15
+ return;
16
+ const { props, flavour } = payload.data.blockJson;
17
+ if (flavour === 'affine:surface') {
18
+ Object.values(props.elements).forEach(element => applyCreationLayer(std, element));
19
+ return;
20
+ }
21
+ if (typeof props.xywh === 'string')
22
+ applyCreationLayer(std, props);
23
+ });
24
+ };
25
+ };
4
26
  export const replaceIdMiddleware = (job) => {
5
27
  const regeneratedIdMap = new Map();
6
28
  job.slots.beforeInsert.subscribe(payload => {
@@ -5,7 +5,7 @@ import { assertType } from '../../global/utils/index.js';
5
5
  import { GfxControllerIdentifier } from '../../std/gfx/index.js';
6
6
  import { DocSnapshotSchema, } from '../../store/index.js';
7
7
  import { Subject } from 'rxjs';
8
- import { createInsertPlaceMiddleware, createRegenerateIndexMiddleware, createStickerMiddleware, replaceIdMiddleware, } from './template-middlewares.js';
8
+ import { createActiveLayerMiddleware, createInsertPlaceMiddleware, createRegenerateIndexMiddleware, createStickerMiddleware, replaceIdMiddleware, } from './template-middlewares.js';
9
9
  /**
10
10
  * Those block contains other block's id
11
11
  * should defer the loading
@@ -243,6 +243,7 @@ export function createTemplateJob(std, type, center) {
243
243
  middlewares.push(createStickerMiddleware(center || viewport.center, () => layer.generateIndex()));
244
244
  }
245
245
  middlewares.push(replaceIdMiddleware);
246
+ middlewares.push(createActiveLayerMiddleware(std));
246
247
  return TemplateJob.create({
247
248
  model: surface,
248
249
  type,
@@ -46,7 +46,7 @@ import { css, html, nothing } from 'lit';
46
46
  import { property, query } from 'lit/decorators.js';
47
47
  import { styleMap } from 'lit/directives/style-map.js';
48
48
  import * as Y from 'yjs';
49
- import { getCursorByCoord, getLineHeight } from './element-renderer/utils.js';
49
+ import { getCursorByCoord, getLineHeight, textDecorationLine, } from './element-renderer/utils.js';
50
50
  import { TEXT_EDITOR_PLACEHOLDER } from './translations.js';
51
51
  export function mountTextElementEditor(textElement, edgeless, focusCoord) {
52
52
  let cursorIndex = textElement.text.length;
@@ -366,6 +366,7 @@ let EdgelessTextEditor = (() => {
366
366
  fontStyle,
367
367
  color,
368
368
  textAlign,
369
+ textDecorationLine: textDecorationLine(this.element.textDecoration),
369
370
  lineHeight: `${lineHeight}px`,
370
371
  boxSizing: 'content-box',
371
372
  })}
@@ -1,9 +1,9 @@
1
1
  import { ElementRendererExtension, } from '../../affine-block-surface/index.js';
2
2
  import { DefaultTheme } from '../../affine-model/index.js';
3
3
  import { deltaInsertsToChunks } from '../../std/inline/index.js';
4
- import { getFontString, getLineHeight, getTextWidth, isRTL, wrapTextDeltas, } from './utils.js';
4
+ import { alphabeticBaselineOffset, getFontString, getLineHeight, getTextWidth, isRTL, paintTextDecoration, wrapTextDeltas, } from './utils.js';
5
5
  export const text = (model, ctx, matrix, renderer) => {
6
- const { fontSize, fontWeight, fontStyle, fontFamily, textAlign, rotate } = model;
6
+ const { fontSize, fontWeight, fontStyle, fontFamily, textAlign, textDecoration, rotate, } = model;
7
7
  const [, , w, h] = model.deserializedXYWH;
8
8
  const cx = w / 2;
9
9
  const cy = h / 2;
@@ -38,7 +38,24 @@ export const text = (model, ctx, matrix, renderer) => {
38
38
  ctx.canvas.setAttribute('dir', rtl ? 'rtl' : 'ltr');
39
39
  // 0.5 comes from v-line padding
40
40
  const offset = textAlign === 'center' ? 0 : textAlign === 'right' ? -0.5 : 0.5;
41
- ctx.fillText(str, horizontalOffset + beforeTextWidth + offset, (lineIndex + 1) * lineHeightPx);
41
+ const x = horizontalOffset + beforeTextWidth + offset;
42
+ const y = (lineIndex + 1) * lineHeightPx;
43
+ ctx.fillText(str, x, y);
44
+ if (textDecoration) {
45
+ paintTextDecoration(ctx, {
46
+ decoration: textDecoration,
47
+ lineText: str,
48
+ font,
49
+ x,
50
+ // Painted on the ideographic baseline (the bottom of the font box);
51
+ // the line hangs off the alphabetic one, a descent above it.
52
+ baselineY: y + alphabeticBaselineOffset(font, 'ideographic'),
53
+ fontFamily,
54
+ fontSize,
55
+ fontWeight,
56
+ color,
57
+ });
58
+ }
42
59
  beforeTextWidth += getTextWidth(str, font);
43
60
  if (shouldTemporarilyAttach) {
44
61
  ctx.canvas.remove();
@@ -1,4 +1,4 @@
1
- import type { FontFamily, FontStyle, FontWeight, TextElementModel } from '../../affine-model/index.js';
1
+ import { type FontFamily, type FontStyle, type FontWeight, TextDecoration, type TextElementModel } from '../../affine-model/index.js';
2
2
  import type { Bound } from '../../global/gfx/index.js';
3
3
  import type * as Y from 'yjs';
4
4
  export type TextDelta = {
@@ -21,6 +21,71 @@ export declare function isRTL(text: string): boolean;
21
21
  export declare function splitIntoLines(text: string): string[];
22
22
  export declare function getLineWidth(text: string, font: string): number;
23
23
  export declare function getTextWidth(text: string, font: string): number;
24
+ /**
25
+ * How far BELOW a `textBaseline` line the alphabetic baseline sits, measured
26
+ * rather than derived: Chromium puts `middle` at half the x-height, not half
27
+ * the font box, so no ratio of the font metrics gets it right. Negative when
28
+ * the alphabetic baseline is above the line (`ideographic`, the font box's
29
+ * bottom).
30
+ */
31
+ export declare function alphabeticBaselineOffset(font: string, baseline: CanvasTextBaseline): number;
32
+ /** The decoration tokens this build paints; any other token is skipped. */
33
+ type KnownTextDecorationToken = 'underline' | 'overline';
34
+ /**
35
+ * The tokens of a stored `textDecoration` this build knows (ADR 0030).
36
+ *
37
+ * Token by token on purpose: the stored value is an append-only CSS token
38
+ * list, so a token a newer client adds is dropped here one at a time and
39
+ * `'underline line-through'` still reads as underlined. Never a `switch` on the
40
+ * whole string, which would lose the underline with the unknown token.
41
+ */
42
+ export declare function parseTextDecoration(value: string | undefined): {
43
+ underline: boolean;
44
+ overline: boolean;
45
+ };
46
+ /**
47
+ * The CSS `text-decoration-line` the DOM twins of a canvas text use — the
48
+ * known tokens only, so an unknown one cannot invalidate the declaration.
49
+ */
50
+ export declare function textDecorationLine(value: string | undefined): string;
51
+ /**
52
+ * The stored value after one toggle: `token` turned on or off, every other
53
+ * token kept — an unknown one included, so a toggle in this build never erases
54
+ * what a newer client wrote. Nothing left writes `None`, never `undefined`
55
+ * (ADR 0030 §2).
56
+ */
57
+ export declare function toggleTextDecoration(value: string | undefined, token: KnownTextDecorationToken, on: boolean): TextDecoration;
58
+ /**
59
+ * Strokes the underline and the overline of ONE painted run of a canvas text
60
+ * (ADR 0030 §3) — shared by the text, shape and connector-label renderers, and
61
+ * replayed as is by the SVG export, which runs those renderers on svgcanvas.
62
+ *
63
+ * - Width is the run's measured advance, never the element's box, with the
64
+ * same measurement the wrap uses, offset by the `ctx.textAlign` the run was
65
+ * painted with.
66
+ * - Offsets are ratios of the size the renderer paints with: canvas
67
+ * `TextMetrics` exposes no underline position.
68
+ * - `fillRect`, not `stroke`: a rectangle ignores whatever `lineDash`,
69
+ * `lineCap` or `lineWidth` a shape left on the context, and svgcanvas writes
70
+ * it as one `<rect>`.
71
+ *
72
+ * Paints nothing at all — not even a `fillStyle` write — when the value holds
73
+ * no known token, so an undecorated text draws exactly the calls it drew
74
+ * before the field existed.
75
+ */
76
+ export declare function paintTextDecoration(ctx: CanvasRenderingContext2D, { decoration, lineText, font, x, baselineY, fontFamily, fontSize, fontWeight, color, }: {
77
+ decoration: string | undefined;
78
+ lineText: string;
79
+ font: string;
80
+ /** The x passed to `fillText`, read with the context's `textAlign`. */
81
+ x: number;
82
+ /** The ALPHABETIC baseline of the run, whatever `textBaseline` painted it. */
83
+ baselineY: number;
84
+ fontFamily: string;
85
+ fontSize: number;
86
+ fontWeight: string;
87
+ color: string;
88
+ }): void;
24
89
  export declare function wrapTextDeltas(text: Y.Text, font: string, w: number): TextDelta[];
25
90
  export declare const truncateTextByWidth: (text: string, font: string, width: number) => string;
26
91
  export declare function getTextCursorPosition(model: TextElementModel, coord: {
@@ -50,3 +115,4 @@ export declare const charWidth: {
50
115
  getCache: (font: string) => number[] | undefined;
51
116
  };
52
117
  export declare function wrapText(text: string, font: string, maxWidth: number): string;
118
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { TextUtils } from '../../affine-block-surface/index.js';
2
+ import { TextDecoration, } from '../../affine-model/index.js';
2
3
  import { getPointsFromBoundWithRotation, rotatePoints, } from '../../global/gfx/index.js';
3
4
  import { deltaInsertsToChunks } from '../../std/inline/index.js';
4
5
  const { getFontFacesByFontFamily, wrapFontFamily } = TextUtils;
@@ -107,6 +108,106 @@ export function getTextWidth(text, font) {
107
108
  });
108
109
  return width;
109
110
  }
111
+ /**
112
+ * How far BELOW a `textBaseline` line the alphabetic baseline sits, measured
113
+ * rather than derived: Chromium puts `middle` at half the x-height, not half
114
+ * the font box, so no ratio of the font metrics gets it right. Negative when
115
+ * the alphabetic baseline is above the line (`ideographic`, the font box's
116
+ * bottom).
117
+ */
118
+ export function alphabeticBaselineOffset(font, baseline) {
119
+ const ctx = getMeasureCtx();
120
+ if (font !== ctx.font)
121
+ ctx.font = font;
122
+ const previous = ctx.textBaseline;
123
+ ctx.textBaseline = baseline;
124
+ const { alphabeticBaseline } = ctx.measureText('x');
125
+ ctx.textBaseline = previous;
126
+ return -(alphabeticBaseline ?? 0) || 0;
127
+ }
128
+ /**
129
+ * The tokens of a stored `textDecoration` this build knows (ADR 0030).
130
+ *
131
+ * Token by token on purpose: the stored value is an append-only CSS token
132
+ * list, so a token a newer client adds is dropped here one at a time and
133
+ * `'underline line-through'` still reads as underlined. Never a `switch` on the
134
+ * whole string, which would lose the underline with the unknown token.
135
+ */
136
+ export function parseTextDecoration(value) {
137
+ const tokens = value ? value.split(/\s+/) : [];
138
+ return {
139
+ underline: tokens.includes('underline'),
140
+ overline: tokens.includes('overline'),
141
+ };
142
+ }
143
+ /**
144
+ * The CSS `text-decoration-line` the DOM twins of a canvas text use — the
145
+ * known tokens only, so an unknown one cannot invalidate the declaration.
146
+ */
147
+ export function textDecorationLine(value) {
148
+ const { underline, overline } = parseTextDecoration(value);
149
+ const line = [underline && 'underline', overline && 'overline']
150
+ .filter(Boolean)
151
+ .join(' ');
152
+ return line || 'none';
153
+ }
154
+ /**
155
+ * The stored value after one toggle: `token` turned on or off, every other
156
+ * token kept — an unknown one included, so a toggle in this build never erases
157
+ * what a newer client wrote. Nothing left writes `None`, never `undefined`
158
+ * (ADR 0030 §2).
159
+ */
160
+ export function toggleTextDecoration(value, token, on) {
161
+ const tokens = new Set((value ?? '')
162
+ .split(/\s+/)
163
+ .filter(t => t && t !== TextDecoration.None && t !== token));
164
+ if (on)
165
+ tokens.add(token);
166
+ const known = ['underline', 'overline'].filter(t => tokens.has(t));
167
+ const unknown = [...tokens].filter(t => t !== 'underline' && t !== 'overline');
168
+ const next = [...known, ...unknown].join(' ');
169
+ return (next || TextDecoration.None);
170
+ }
171
+ /**
172
+ * Strokes the underline and the overline of ONE painted run of a canvas text
173
+ * (ADR 0030 §3) — shared by the text, shape and connector-label renderers, and
174
+ * replayed as is by the SVG export, which runs those renderers on svgcanvas.
175
+ *
176
+ * - Width is the run's measured advance, never the element's box, with the
177
+ * same measurement the wrap uses, offset by the `ctx.textAlign` the run was
178
+ * painted with.
179
+ * - Offsets are ratios of the size the renderer paints with: canvas
180
+ * `TextMetrics` exposes no underline position.
181
+ * - `fillRect`, not `stroke`: a rectangle ignores whatever `lineDash`,
182
+ * `lineCap` or `lineWidth` a shape left on the context, and svgcanvas writes
183
+ * it as one `<rect>`.
184
+ *
185
+ * Paints nothing at all — not even a `fillStyle` write — when the value holds
186
+ * no known token, so an undecorated text draws exactly the calls it drew
187
+ * before the field existed.
188
+ */
189
+ export function paintTextDecoration(ctx, { decoration, lineText, font, x, baselineY, fontFamily, fontSize, fontWeight, color, }) {
190
+ const { underline, overline } = parseTextDecoration(decoration);
191
+ if (!underline && !overline)
192
+ return;
193
+ const width = getLineWidth(lineText, font);
194
+ if (!(width > 0))
195
+ return;
196
+ const left = ctx.textAlign === 'center'
197
+ ? x - width / 2
198
+ : ctx.textAlign === 'right'
199
+ ? x - width
200
+ : x;
201
+ const thickness = Math.max(1, fontSize / 16);
202
+ ctx.fillStyle = color;
203
+ if (underline) {
204
+ ctx.fillRect(left, baselineY + Math.max(1, fontSize * 0.08), width, thickness);
205
+ }
206
+ if (overline) {
207
+ const { fontBoundingBoxAscent } = getFontMetrics(fontFamily, fontSize, fontWeight);
208
+ ctx.fillRect(left, baselineY - fontBoundingBoxAscent, width, thickness);
209
+ }
210
+ }
110
211
  export function wrapTextDeltas(text, font, w) {
111
212
  if (!text)
112
213
  return [];
@@ -15,6 +15,17 @@ export declare function createTextActions<K extends abstract new (...args: any)
15
15
  }, {
16
16
  readonly id: "c.font-style";
17
17
  readonly content: (ctx: ToolbarContext) => import("lit-html").TemplateResult<1> | null;
18
+ }, {
19
+ readonly id: "c.text-decoration";
20
+ readonly when: boolean;
21
+ readonly actions: {
22
+ id: "a.underline" | "b.overline";
23
+ icon: import("lit-html").TemplateResult<1>;
24
+ tooltipWording: import("../../affine-shared/services/index.js").ChromeWording;
25
+ when: (ctx: ToolbarContext) => boolean;
26
+ active: (ctx: ToolbarContext) => boolean;
27
+ run: (ctx: ToolbarContext) => void;
28
+ }[];
18
29
  }, {
19
30
  readonly id: "d.font-size";
20
31
  readonly when: boolean;
@@ -1,15 +1,16 @@
1
1
  import { EdgelessCRUDIdentifier, TextUtils } from '../../affine-block-surface/index.js';
2
2
  import { frameworkPaletteGroups, packColor, } from '../../affine-components/color-picker/index.js';
3
+ import { OverlineIcon, UnderlineIcon } from '../../affine-components/icons/index.js';
3
4
  import { EditorChevronDown } from '../../affine-components/toolbar/index.js';
4
5
  import { DefaultTheme, FontFamily, FontStyle, FontWeight, resolveColor, TextAlign, } from '../../affine-model/index.js';
5
- import { translateKey, } from '../../affine-shared/services/index.js';
6
+ import { TEXT_FORMAT_OVERLINE, TEXT_FORMAT_UNDERLINE, translateKey, } from '../../affine-shared/services/index.js';
6
7
  import { getMostCommonResolvedValue, getMostCommonValue, } from '../../affine-shared/utils/index.js';
7
8
  import { renderMenu, resolveMenuItemLabel, } from '../../affine-widget-edgeless-toolbar/index.js';
8
9
  import { TextAlignCenterIcon, TextAlignLeftIcon, TextAlignRightIcon, } from '@blocksuite/icons/lit';
9
10
  import { signal } from '@preact/signals-core';
10
11
  import { html } from 'lit';
11
12
  import { styleMap } from 'lit/directives/style-map.js';
12
- import { isFontStyleSupported, isFontWeightSupported, } from '../element-renderer/utils.js';
13
+ import { isFontStyleSupported, isFontWeightSupported, parseTextDecoration, toggleTextDecoration, } from '../element-renderer/utils.js';
13
14
  import { TEXT_ALIGN_CENTER, TEXT_ALIGN_LEFT, TEXT_ALIGN_RIGHT, TEXT_TOOLBAR_ALIGNMENT, TEXT_TOOLBAR_ALIGNMENT_MENU_ARIA, TEXT_TOOLBAR_FONT, TEXT_TOOLBAR_FONT_STYLE, TEXT_TOOLBAR_FONT_STYLE_ITALIC, TEXT_TOOLBAR_FONT_WEIGHT_BOLD, TEXT_TOOLBAR_FONT_WEIGHT_LIGHT, TEXT_TOOLBAR_FONT_WEIGHT_REGULAR, TEXT_TOOLBAR_FONT_WEIGHT_SEMIBOLD, TEXT_TOOLBAR_FONT_SIZE, TEXT_TOOLBAR_TEXT_COLOR, } from '../translations.js';
14
15
  const FONT_WEIGHT_LIST = [
15
16
  {
@@ -71,6 +72,24 @@ const TEXT_ALIGN_LIST = [
71
72
  icon: TextAlignRightIcon(),
72
73
  },
73
74
  ];
75
+ /**
76
+ * The decoration toggles, in the order they sit on the row (the toolbar orders
77
+ * a group's children by id).
78
+ */
79
+ const TEXT_DECORATION_TOGGLES = [
80
+ {
81
+ id: 'a.underline',
82
+ token: 'underline',
83
+ icon: UnderlineIcon,
84
+ wording: TEXT_FORMAT_UNDERLINE,
85
+ },
86
+ {
87
+ id: 'b.overline',
88
+ token: 'overline',
89
+ icon: OverlineIcon,
90
+ wording: TEXT_FORMAT_OVERLINE,
91
+ },
92
+ ];
74
93
  export function createTextActions(klass, type, update = (ctx, model, props) => ctx.std.get(EdgelessCRUDIdentifier).updateElement(model.id, props), mapInto = model => model, stash = (model, type, field) => model[type](field)) {
75
94
  return [
76
95
  {
@@ -250,6 +269,38 @@ export function createTextActions(klass, type, update = (ctx, model, props) => c
250
269
  `;
251
270
  },
252
271
  },
272
+ {
273
+ // Two element-level toggles, drawn like the format bar's underline:
274
+ // the decoration applies to the whole text, never to one run (ADR 0030
275
+ // §1, §6). `affine:edgeless-text` decorates its paragraphs per run
276
+ // through the inline schema instead, so it has no such field.
277
+ id: 'c.text-decoration',
278
+ when: type !== 'edgeless-text',
279
+ actions: TEXT_DECORATION_TOGGLES.map(({ id, token, icon, wording }) => ({
280
+ id,
281
+ icon,
282
+ tooltipWording: wording,
283
+ when: (ctx) => {
284
+ const models = ctx.getSurfaceModelsByType(klass);
285
+ return (models.length > 0 &&
286
+ models.every(model => isSurfaceTextModel(model, klass, type)));
287
+ },
288
+ active: (ctx) => ctx
289
+ .getSurfaceModelsByType(klass)
290
+ .every(model => parseTextDecoration(mapInto(model).textDecoration)[token]),
291
+ run: (ctx) => {
292
+ const models = ctx.getSurfaceModelsByType(klass);
293
+ const on = !models.every(model => parseTextDecoration(mapInto(model).textDecoration)[token]);
294
+ // One click, one undo step, whatever the selection holds.
295
+ ctx.store.captureSync();
296
+ for (const model of models) {
297
+ update(ctx, model, {
298
+ textDecoration: toggleTextDecoration(mapInto(model).textDecoration, token, on),
299
+ });
300
+ }
301
+ },
302
+ })),
303
+ },
253
304
  {
254
305
  id: 'd.font-size',
255
306
  when: type !== 'edgeless-text',
@@ -8,6 +8,17 @@ export declare const textToolbarConfig: {
8
8
  }, {
9
9
  readonly id: "c.font-style";
10
10
  readonly content: (ctx: import("../../affine-shared/services/index.js").ToolbarContext) => import("lit-html").TemplateResult<1> | null;
11
+ }, {
12
+ readonly id: "c.text-decoration";
13
+ readonly when: boolean;
14
+ readonly actions: {
15
+ id: "a.underline" | "b.overline";
16
+ icon: import("lit-html").TemplateResult<1>;
17
+ tooltipWording: import("../../affine-shared/services/index.js").ChromeWording;
18
+ when: (ctx: import("../../affine-shared/services/index.js").ToolbarContext) => boolean;
19
+ active: (ctx: import("../../affine-shared/services/index.js").ToolbarContext) => boolean;
20
+ run: (ctx: import("../../affine-shared/services/index.js").ToolbarContext) => void;
21
+ }[];
11
22
  }, {
12
23
  readonly id: "d.font-size";
13
24
  readonly when: boolean;
@@ -8,7 +8,7 @@ import { createTextActions } from './actions.js';
8
8
  export const textToolbarConfig = {
9
9
  actions: createTextActions(TextElementModel, 'text', (ctx, model, props) => {
10
10
  // No need to adjust element bounds
11
- if (props['textAlign']) {
11
+ if (props['textAlign'] || props['textDecoration']) {
12
12
  ctx.std.get(EdgelessCRUDIdentifier).updateElement(model.id, props);
13
13
  return;
14
14
  }
@@ -25,6 +25,9 @@ export declare const htmlDelElementToDeltaMatcher: import("../../../store/index.
25
25
  export declare const htmlUnderlineElementToDeltaMatcher: import("../../../store/index.js").ExtensionType & {
26
26
  identifier: import("../../../global/di/types.js").ServiceIdentifier<import("../../../affine-shared/adapters/index.js").HtmlASTToDeltaMatcher>;
27
27
  };
28
+ export declare const htmlOverlineElementToDeltaMatcher: import("../../../store/index.js").ExtensionType & {
29
+ identifier: import("../../../global/di/types.js").ServiceIdentifier<import("../../../affine-shared/adapters/index.js").HtmlASTToDeltaMatcher>;
30
+ };
28
31
  export declare const htmlMarkElementToDeltaMatcher: import("../../../store/index.js").ExtensionType & {
29
32
  identifier: import("../../../global/di/types.js").ServiceIdentifier<import("../../../affine-shared/adapters/index.js").HtmlASTToDeltaMatcher>;
30
33
  };