@formicoidea/labre-core 0.43.1 → 0.45.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 (263) 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-into-callout.d.ts +29 -0
  4. package/dist/_pkgs/affine-block-callout/commands/turn-into-callout.js +81 -0
  5. package/dist/_pkgs/affine-block-callout/configs/slash-menu.js +6 -4
  6. package/dist/_pkgs/affine-block-callout/configs/turn-into.d.ts +8 -0
  7. package/dist/_pkgs/affine-block-callout/configs/turn-into.js +19 -0
  8. package/dist/_pkgs/affine-block-callout/translations.d.ts +4 -2
  9. package/dist/_pkgs/affine-block-callout/translations.js +4 -2
  10. package/dist/_pkgs/affine-block-callout/view.js +3 -0
  11. package/dist/_pkgs/affine-block-code/code-block-service.d.ts +13 -0
  12. package/dist/_pkgs/affine-block-code/code-block-service.js +26 -0
  13. package/dist/_pkgs/affine-block-code/code-block.d.ts +6 -0
  14. package/dist/_pkgs/affine-block-code/code-block.js +11 -2
  15. package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +31 -8
  16. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.d.ts +11 -0
  17. package/dist/_pkgs/affine-block-edgeless-text/svg-painter.d.ts +20 -0
  18. package/dist/_pkgs/affine-block-edgeless-text/svg-painter.js +76 -0
  19. package/dist/_pkgs/affine-block-edgeless-text/view.js +2 -0
  20. package/dist/_pkgs/affine-block-embed/configs/toolbar.js +11 -2
  21. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +11 -2
  22. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-edgeless-linked-doc-block.js +3 -1
  23. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +7 -2
  24. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-edgeless-synced-doc-block.js +3 -1
  25. package/dist/_pkgs/affine-block-frame/frame-manager.d.ts +5 -0
  26. package/dist/_pkgs/affine-block-frame/frame-manager.js +48 -17
  27. package/dist/_pkgs/affine-block-frame/frame-tool.js +3 -1
  28. package/dist/_pkgs/affine-block-image/utils.js +4 -1
  29. package/dist/_pkgs/affine-block-latex/adapters/markdown/preprocessor.d.ts +8 -0
  30. package/dist/_pkgs/affine-block-latex/adapters/markdown/preprocessor.js +9 -5
  31. package/dist/_pkgs/affine-block-note/translations.d.ts +0 -1
  32. package/dist/_pkgs/affine-block-note/translations.js +0 -5
  33. package/dist/_pkgs/affine-block-root/configs/toolbar.js +17 -1
  34. package/dist/_pkgs/affine-block-root/edgeless/clipboard/clipboard.js +2 -1
  35. package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +161 -83
  36. package/dist/_pkgs/affine-block-root/edgeless/clipboard/paste-order.d.ts +21 -0
  37. package/dist/_pkgs/affine-block-root/edgeless/clipboard/paste-order.js +85 -0
  38. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.d.ts +6 -0
  39. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +18 -1
  40. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.d.ts +9 -0
  41. package/dist/_pkgs/affine-block-root/edgeless/utils/clone-utils.js +28 -0
  42. package/dist/_pkgs/affine-block-root/keyboard/commands.js +9 -6
  43. package/dist/_pkgs/affine-block-root/preview/edgeless-root-preview-block.js +15 -2
  44. package/dist/_pkgs/affine-block-surface/adapters/markdown/element-adapter/type.d.ts +1 -1
  45. package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +1 -1
  46. package/dist/_pkgs/affine-block-surface/element-model/index.js +1 -1
  47. package/dist/_pkgs/affine-block-surface/extensions/audit.js +13 -61
  48. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.d.ts +2 -0
  49. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.js +71 -0
  50. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/index.d.ts +1 -0
  51. package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/index.js +1 -0
  52. package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +4 -0
  53. package/dist/_pkgs/affine-block-surface/extensions/crud-extension.js +4 -0
  54. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.d.ts +12 -0
  55. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +27 -7
  56. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +2 -1
  57. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +22 -3
  58. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +6 -3
  59. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +4 -2
  60. package/dist/_pkgs/affine-block-surface/extensions/export-svg/parts.d.ts +63 -0
  61. package/dist/_pkgs/affine-block-surface/extensions/export-svg/parts.js +67 -0
  62. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +62 -5
  63. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +98 -18
  64. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +14 -0
  65. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +82 -1
  66. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.d.ts +2 -2
  67. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.js +112 -10
  68. package/dist/_pkgs/affine-block-surface/extensions/export-svg/translations.d.ts +13 -0
  69. package/dist/_pkgs/affine-block-surface/extensions/export-svg/translations.js +33 -0
  70. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +3 -0
  71. package/dist/_pkgs/affine-block-surface/extensions/index.js +3 -0
  72. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +13 -6
  73. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +26 -10
  74. package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +82 -6
  75. package/dist/_pkgs/affine-block-surface/extensions/reading.js +99 -21
  76. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.d.ts +80 -0
  77. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.js +248 -0
  78. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.d.ts +82 -0
  79. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.js +342 -0
  80. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.d.ts +3 -0
  81. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.js +3 -0
  82. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/tree.d.ts +137 -0
  83. package/dist/_pkgs/affine-block-surface/extensions/selection-pane/tree.js +323 -0
  84. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +112 -4
  85. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +86 -15
  86. package/dist/_pkgs/affine-block-surface/extensions/user-layers/actions.d.ts +76 -0
  87. package/dist/_pkgs/affine-block-surface/extensions/user-layers/actions.js +299 -0
  88. package/dist/_pkgs/affine-block-surface/extensions/user-layers/active-layer.d.ts +20 -0
  89. package/dist/_pkgs/affine-block-surface/extensions/user-layers/active-layer.js +34 -0
  90. package/dist/_pkgs/affine-block-surface/extensions/user-layers/commands.d.ts +67 -0
  91. package/dist/_pkgs/affine-block-surface/extensions/user-layers/commands.js +172 -0
  92. package/dist/_pkgs/affine-block-surface/extensions/user-layers/creation.d.ts +40 -0
  93. package/dist/_pkgs/affine-block-surface/extensions/user-layers/creation.js +69 -0
  94. package/dist/_pkgs/affine-block-surface/extensions/user-layers/index.d.ts +5 -0
  95. package/dist/_pkgs/affine-block-surface/extensions/user-layers/index.js +5 -0
  96. package/dist/_pkgs/affine-block-surface/extensions/user-layers/translations.d.ts +10 -0
  97. package/dist/_pkgs/affine-block-surface/extensions/user-layers/translations.js +14 -0
  98. package/dist/_pkgs/affine-block-surface/framework-background/facts.d.ts +55 -2
  99. package/dist/_pkgs/affine-block-surface/framework-background/facts.js +63 -1
  100. package/dist/_pkgs/affine-block-surface/framework-background/stacking.d.ts +16 -8
  101. package/dist/_pkgs/affine-block-surface/framework-background/stacking.js +26 -14
  102. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +17 -3
  103. package/dist/_pkgs/affine-block-surface/renderer/dom-renderer.d.ts +3 -1
  104. package/dist/_pkgs/affine-block-surface/renderer/dom-renderer.js +22 -2
  105. package/dist/_pkgs/affine-block-surface/renderer/paint-predicate.d.ts +30 -0
  106. package/dist/_pkgs/affine-block-surface/renderer/paint-predicate.js +29 -0
  107. package/dist/_pkgs/affine-block-surface/surface-block.js +6 -0
  108. package/dist/_pkgs/affine-block-surface/surface-model.js +5 -0
  109. package/dist/_pkgs/affine-block-surface/surface-transformer.js +5 -0
  110. package/dist/_pkgs/affine-block-surface/tool/default-tool.js +28 -5
  111. package/dist/_pkgs/affine-block-surface/view.js +23 -1
  112. package/dist/_pkgs/affine-block-surface-ref/surface-ref-block.js +12 -2
  113. package/dist/_pkgs/affine-components/context-menu/button.js +14 -0
  114. package/dist/_pkgs/affine-components/filterable-list/index.js +30 -9
  115. package/dist/_pkgs/affine-components/icons/index.d.ts +0 -1
  116. package/dist/_pkgs/affine-components/icons/index.js +0 -1
  117. package/dist/_pkgs/affine-components/icons/text.d.ts +1 -0
  118. package/dist/_pkgs/affine-components/icons/text.js +11 -0
  119. package/dist/_pkgs/affine-fragment-adapter-panel/adapter-panel.d.ts +2 -2
  120. package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +2 -2
  121. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.d.ts +1 -1
  122. package/dist/_pkgs/affine-fragment-frame-panel/header/frame-panel-header.js +8 -27
  123. package/dist/_pkgs/affine-fragment-frame-panel/index.d.ts +1 -0
  124. package/dist/_pkgs/affine-fragment-frame-panel/index.js +1 -0
  125. package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +3 -1
  126. package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +21 -4
  127. package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +3 -2
  128. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +1 -1
  129. package/dist/_pkgs/affine-gfx-group/command/group-api.js +52 -1
  130. package/dist/_pkgs/affine-gfx-shape/element-renderer/shape/index.js +21 -3
  131. package/dist/_pkgs/affine-gfx-shape/text/edgeless-shape-text-editor.js +2 -0
  132. package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +1 -1
  133. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +9 -0
  134. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +23 -1
  135. package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
  136. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +2 -1
  137. package/dist/_pkgs/affine-gfx-text/element-renderer/index.js +20 -3
  138. package/dist/_pkgs/affine-gfx-text/element-renderer/utils.d.ts +67 -1
  139. package/dist/_pkgs/affine-gfx-text/element-renderer/utils.js +101 -0
  140. package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +11 -0
  141. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +53 -2
  142. package/dist/_pkgs/affine-gfx-text/toolbar/config.d.ts +11 -0
  143. package/dist/_pkgs/affine-gfx-text/toolbar/config.js +1 -1
  144. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.d.ts +3 -0
  145. package/dist/_pkgs/affine-inline-preset/adapters/html/html-inline.js +31 -0
  146. package/dist/_pkgs/affine-inline-preset/adapters/html/inline-delta.d.ts +4 -0
  147. package/dist/_pkgs/affine-inline-preset/adapters/html/inline-delta.js +14 -0
  148. package/dist/_pkgs/affine-inline-preset/command/config.js +21 -3
  149. package/dist/_pkgs/affine-inline-preset/command/index.d.ts +1 -1
  150. package/dist/_pkgs/affine-inline-preset/command/index.js +1 -1
  151. package/dist/_pkgs/affine-inline-preset/command/text-style.d.ts +2 -1
  152. package/dist/_pkgs/affine-inline-preset/command/text-style.js +1 -0
  153. package/dist/_pkgs/affine-inline-preset/default-inline-manager.js +2 -1
  154. package/dist/_pkgs/affine-inline-preset/inline-spec.d.ts +4 -0
  155. package/dist/_pkgs/affine-inline-preset/inline-spec.js +14 -0
  156. package/dist/_pkgs/affine-inline-preset/translations.d.ts +2 -2
  157. package/dist/_pkgs/affine-inline-preset/translations.js +2 -2
  158. package/dist/_pkgs/affine-model/blocks/attachment/attachment-model.js +2 -0
  159. package/dist/_pkgs/affine-model/blocks/bookmark/bookmark-model.js +2 -0
  160. package/dist/_pkgs/affine-model/blocks/edgeless-text/edgeless-text-model.d.ts +1 -1
  161. package/dist/_pkgs/affine-model/blocks/edgeless-text/edgeless-text-model.js +2 -0
  162. package/dist/_pkgs/affine-model/blocks/embed/iframe/iframe-model.js +2 -0
  163. package/dist/_pkgs/affine-model/blocks/frame/frame-model.js +2 -0
  164. package/dist/_pkgs/affine-model/blocks/image/image-model.js +2 -0
  165. package/dist/_pkgs/affine-model/blocks/latex/latex-model.js +2 -0
  166. package/dist/_pkgs/affine-model/blocks/note/note-model.js +2 -0
  167. package/dist/_pkgs/affine-model/consts/text.d.ts +26 -0
  168. package/dist/_pkgs/affine-model/consts/text.js +25 -0
  169. package/dist/_pkgs/affine-model/elements/shape/shape.d.ts +6 -1
  170. package/dist/_pkgs/affine-model/elements/shape/shape.js +14 -1
  171. package/dist/_pkgs/affine-model/elements/text/text.d.ts +6 -1
  172. package/dist/_pkgs/affine-model/elements/text/text.js +13 -1
  173. package/dist/_pkgs/affine-model/utils/helper.js +2 -0
  174. package/dist/_pkgs/affine-rich-text/conversion.d.ts +25 -0
  175. package/dist/_pkgs/affine-rich-text/conversion.js +9 -0
  176. package/dist/_pkgs/affine-rich-text/index.d.ts +1 -1
  177. package/dist/_pkgs/affine-rich-text/index.js +1 -1
  178. package/dist/_pkgs/affine-shared/commands/model-crud/replace-selected-text-with-blocks.d.ts +1 -1
  179. package/dist/_pkgs/affine-shared/services/canvas-grid.d.ts +63 -0
  180. package/dist/_pkgs/affine-shared/services/canvas-grid.js +109 -0
  181. package/dist/_pkgs/affine-shared/services/canvas-local-visibility.d.ts +64 -0
  182. package/dist/_pkgs/affine-shared/services/canvas-local-visibility.js +192 -0
  183. package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +27 -0
  184. package/dist/_pkgs/affine-shared/services/edit-props-store.js +34 -0
  185. package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
  186. package/dist/_pkgs/affine-shared/services/editor-setting-service.js +7 -0
  187. package/dist/_pkgs/affine-shared/services/feature-flag-service.d.ts +4 -0
  188. package/dist/_pkgs/affine-shared/services/index.d.ts +3 -0
  189. package/dist/_pkgs/affine-shared/services/index.js +3 -0
  190. package/dist/_pkgs/affine-shared/services/selection-pane-service.d.ts +44 -0
  191. package/dist/_pkgs/affine-shared/services/selection-pane-service.js +28 -0
  192. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +69 -0
  193. package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
  194. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +5 -0
  195. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +9 -0
  196. package/dist/_pkgs/affine-shared/styles/index.d.ts +1 -0
  197. package/dist/_pkgs/affine-shared/styles/index.js +1 -0
  198. package/dist/_pkgs/affine-shared/styles/panel-header.d.ts +31 -0
  199. package/dist/_pkgs/affine-shared/styles/panel-header.js +61 -0
  200. package/dist/_pkgs/affine-shared/styles/text.js +7 -7
  201. package/dist/_pkgs/affine-shared/types/index.d.ts +6 -0
  202. package/dist/_pkgs/affine-shared/utils/canvas-export-colors.d.ts +26 -0
  203. package/dist/_pkgs/affine-shared/utils/canvas-export-colors.js +127 -0
  204. package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +8 -11
  205. package/dist/_pkgs/affine-shared/utils/file/filesys.js +8 -11
  206. package/dist/_pkgs/affine-shared/utils/index.d.ts +2 -0
  207. package/dist/_pkgs/affine-shared/utils/index.js +2 -0
  208. package/dist/_pkgs/affine-shared/utils/label-mode.d.ts +47 -0
  209. package/dist/_pkgs/affine-shared/utils/label-mode.js +55 -0
  210. package/dist/_pkgs/affine-shared/utils/model/merge-to-code-model.js +7 -1
  211. package/dist/_pkgs/affine-shared/utils/model/transform-model.js +5 -0
  212. package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +10 -3
  213. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +25 -49
  214. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.d.ts +4 -0
  215. package/dist/_pkgs/affine-widget-edgeless-toolbar/effects.js +4 -0
  216. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +4 -0
  217. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +4 -0
  218. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.d.ts +61 -0
  219. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.js +91 -0
  220. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/labels.d.ts +17 -0
  221. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/labels.js +95 -0
  222. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-default.d.ts +10 -0
  223. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-default.js +31 -0
  224. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-tool.d.ts +26 -0
  225. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-tool.js +82 -0
  226. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.d.ts +170 -0
  227. package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.js +1381 -0
  228. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.d.ts +52 -0
  229. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.js +161 -1
  230. package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +10 -0
  231. package/dist/_pkgs/affine-widget-note-slicer/note-slicer.js +7 -3
  232. package/dist/_pkgs/std/gfx/controller.d.ts +13 -0
  233. package/dist/_pkgs/std/gfx/controller.js +22 -2
  234. package/dist/_pkgs/std/gfx/grid.d.ts +31 -2
  235. package/dist/_pkgs/std/gfx/index.d.ts +3 -1
  236. package/dist/_pkgs/std/gfx/index.js +3 -1
  237. package/dist/_pkgs/std/gfx/interactivity/manager.js +7 -0
  238. package/dist/_pkgs/std/gfx/layer.js +73 -5
  239. package/dist/_pkgs/std/gfx/local-visibility.d.ts +88 -0
  240. package/dist/_pkgs/std/gfx/local-visibility.js +217 -0
  241. package/dist/_pkgs/std/gfx/model/gfx-block-model.d.ts +13 -0
  242. package/dist/_pkgs/std/gfx/model/surface/element-model.d.ts +34 -0
  243. package/dist/_pkgs/std/gfx/model/surface/element-model.js +65 -1
  244. package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +27 -0
  245. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +43 -0
  246. package/dist/_pkgs/std/gfx/model/surface/user-layers.d.ts +68 -0
  247. package/dist/_pkgs/std/gfx/model/surface/user-layers.js +127 -0
  248. package/dist/_pkgs/std/utils/layer.d.ts +10 -0
  249. package/dist/_pkgs/std/utils/layer.js +64 -13
  250. package/dist/_pkgs/std/view/element/gfx-block-component.js +10 -2
  251. package/dist/commands.js +4 -1
  252. package/dist/translations.js +10 -6
  253. package/package.json +9 -2
  254. package/dist/_pkgs/affine-components/icons/file-icons-rc.d.ts +0 -1
  255. package/dist/_pkgs/affine-components/icons/file-icons-rc.js +0 -130
  256. package/dist/_pkgs/affine-shared/test-utils/affine-template.d.ts +0 -6
  257. package/dist/_pkgs/affine-shared/test-utils/affine-template.js +0 -258
  258. package/dist/_pkgs/affine-shared/test-utils/affine-test-utils.d.ts +0 -8
  259. package/dist/_pkgs/affine-shared/test-utils/affine-test-utils.js +0 -81
  260. package/dist/_pkgs/affine-shared/test-utils/create-test-host.d.ts +0 -23
  261. package/dist/_pkgs/affine-shared/test-utils/create-test-host.js +0 -187
  262. package/dist/_pkgs/affine-shared/test-utils/index.d.ts +0 -3
  263. package/dist/_pkgs/affine-shared/test-utils/index.js +0 -3
@@ -0,0 +1,1381 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { CanvasActiveLayer, EDITOR_ANCHORED_PANEL_Z_INDEX, filterSelectionPaneTree, SelectionPaneModel, selectionPaneCommands, selectionPaneFilterMembers, selectionPaneFilterTargets, selectionPaneTree, userLayerCommands, userLayerName, } from '../../affine-block-surface/index.js';
36
+ import { menu, popMenu, popupTargetFromElement, } from '../../affine-components/context-menu/index.js';
37
+ import { FrameBlockModel, MindmapElementModel, } from '../../affine-model/index.js';
38
+ import { TOOLBAR_LOCK, TOOLBAR_RENAME, translateKey, } from '../../affine-shared/services/index.js';
39
+ import { panelDragStarted, panelHeaderStyles, } from '../../affine-shared/styles/index.js';
40
+ import { runCommand, WidgetComponent, WidgetViewExtension, } from '../../std/index.js';
41
+ import { DEFAULT_LAYER_ID, GfxBlockElementModel, GfxControllerIdentifier, } from '../../std/gfx/index.js';
42
+ import { ArrowDownSmallIcon, ArrowRightSmallIcon, CloseIcon, DeleteIcon, FilterIcon, InvisibleIcon, LayerIcon, LockIcon, MoreHorizontalIcon, PlusIcon, UnlockIcon, ViewIcon, } from '@blocksuite/icons/lit';
43
+ import { css, html, nothing, unsafeCSS } from 'lit';
44
+ import { state } from 'lit/decorators.js';
45
+ import { repeat } from 'lit/directives/repeat.js';
46
+ import { styleMap } from 'lit/directives/style-map.js';
47
+ import { literal, unsafeStatic } from 'lit/static-html.js';
48
+ import { SELECTION_PANE_ACTIVE_LAYER, SELECTION_PANE_CLOSE, SELECTION_PANE_COLLAPSE, SELECTION_PANE_DELETE_LAYER, SELECTION_PANE_EMPTY, SELECTION_PANE_EXPAND, SELECTION_PANE_FILTER, SELECTION_PANE_FILTER_ALL, SELECTION_PANE_FILTER_FRAME, SELECTION_PANE_LAYER_FILTERED, SELECTION_PANE_TITLE, SELECTION_PANE_HIDE, SELECTION_PANE_HIDE_FOR_EVERYONE, SELECTION_PANE_NEW_LAYER, SELECTION_PANE_ROW_MENU, SELECTION_PANE_SHOW, SELECTION_PANE_SHOW_FOR_EVERYONE, SELECTION_PANE_UNLOCK, } from '../translations.js';
49
+ import { paneDropAbove, paneLists, paneSlotAtGap, } from './drop.js';
50
+ import { selectionPaneRowIcon, selectionPaneRowLabel } from './labels.js';
51
+ export const EDGELESS_SELECTION_PANE_WIDGET = 'edgeless-selection-pane-widget';
52
+ /** The catalogue's measure: an icon, a label and a toggle, never most of a phone. */
53
+ const PANEL_WIDTH = 'min(320px, 85vw)';
54
+ /** Indent per nesting level, in px. */
55
+ const INDENT_PX = 16;
56
+ /**
57
+ * How the pane invokes the registry. The pane is not one of the registry's
58
+ * surfaces (a designed panel, not an enumeration of commands): like the
59
+ * contextual toolbar it acts on ONE element, the row's, and `source` says it
60
+ * came from the editor's chrome.
61
+ */
62
+ const PANE_INVOCATION = {
63
+ surface: 'contextual-toolbar',
64
+ source: 'toolbar:general',
65
+ };
66
+ function paneCommand(id) {
67
+ const command = [...selectionPaneCommands, ...userLayerCommands].find(c => c.id === id);
68
+ if (!command)
69
+ throw new Error(`selection pane: no command ${id}`);
70
+ return command;
71
+ }
72
+ /** `model.group`, or `null` where the getter throws (no surface holds it). */
73
+ function rawGroupOf(model) {
74
+ try {
75
+ return model.group ?? null;
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ /**
82
+ * The **selection pane** (ADR 0031, stage 2): the canvas elements by z-order,
83
+ * top first, the library's own panel behind `SelectionPaneProvider`.
84
+ *
85
+ * ## Docked like the artefact catalogue
86
+ *
87
+ * A full-height column down the left edge of the editor, inside it — the
88
+ * geometry, layer, zero-width host and wheel capture are the catalogue's, for
89
+ * the catalogue's reasons (see `artefact-catalogue-widget.ts`). What differs
90
+ * is the dismissal: the pane is a place you WORK from, its selection mirrors
91
+ * the canvas both ways, so a click on the canvas does not put it away. × and
92
+ * Escape (with the pointer or focus in the pane) do.
93
+ *
94
+ * ## Rows
95
+ *
96
+ * Drawn from `selectionPaneTree(std)` — the same headless tree a host pane
97
+ * would draw — and labelled at render time ({@link selectionPaneRowLabel}).
98
+ * A group or a mindmap is a collapsible row; collapse is this panel's state,
99
+ * never stored. Hover highlights the element on the canvas, click selects it
100
+ * (shift / ctrl / cmd adds or removes it, like on the canvas), the padlock
101
+ * locks that row alone, a double-click renames a group or a frame (a frame is
102
+ * a row at its place in the stack, ADR 0031 amendments), and a drag moves a row
103
+ * among its siblings. Every write goes through `runCommand`, so the read-only
104
+ * refusal and the undo step live in one place.
105
+ */
106
+ let EdgelessSelectionPaneWidget = (() => {
107
+ let _classSuper = WidgetComponent;
108
+ let __open_decorators;
109
+ let __open_initializers = [];
110
+ let __open_extraInitializers = [];
111
+ let __collapsed_decorators;
112
+ let __collapsed_initializers = [];
113
+ let __collapsed_extraInitializers = [];
114
+ let __filter_decorators;
115
+ let __filter_initializers = [];
116
+ let __filter_extraInitializers = [];
117
+ let __renaming_decorators;
118
+ let __renaming_initializers = [];
119
+ let __renaming_extraInitializers = [];
120
+ let __drop_decorators;
121
+ let __drop_initializers = [];
122
+ let __drop_extraInitializers = [];
123
+ let __ghost_decorators;
124
+ let __ghost_initializers = [];
125
+ let __ghost_extraInitializers = [];
126
+ let __selectionRevision_decorators;
127
+ let __selectionRevision_initializers = [];
128
+ let __selectionRevision_extraInitializers = [];
129
+ return class EdgelessSelectionPaneWidget extends _classSuper {
130
+ constructor() {
131
+ super(...arguments);
132
+ this.#_open_accessor_storage = __runInitializers(this, __open_initializers, false);
133
+ this.#_collapsed_accessor_storage = (__runInitializers(this, __open_extraInitializers), __runInitializers(this, __collapsed_initializers, new Set()));
134
+ this.#_filter_accessor_storage = (__runInitializers(this, __collapsed_extraInitializers), __runInitializers(this, __filter_initializers, null));
135
+ this.#_renaming_accessor_storage = (__runInitializers(this, __filter_extraInitializers), __runInitializers(this, __renaming_initializers, null));
136
+ this.#_drop_accessor_storage = (__runInitializers(this, __renaming_extraInitializers), __runInitializers(this, __drop_initializers, null));
137
+ this.#_ghost_accessor_storage = (__runInitializers(this, __drop_extraInitializers), __runInitializers(this, __ghost_initializers, null));
138
+ this.#_selectionRevision_accessor_storage = (__runInitializers(this, __ghost_extraInitializers), __runInitializers(this, __selectionRevision_initializers, 0));
139
+ this._drag = (__runInitializers(this, __selectionRevision_extraInitializers), null);
140
+ /** The rows of the last render, top first: what a drag hit-tests. */
141
+ this._visibleRows = [];
142
+ /** The sibling lists before the filter: what a drop is computed in. */
143
+ this._lists = paneLists([]);
144
+ /** A drag ends with a click on the row it started on; that click is not one. */
145
+ this._swallowNextClick = false;
146
+ /** Put the pane away. Writes nothing but its own state. */
147
+ this.closePanel = () => {
148
+ this._setOpen(false);
149
+ };
150
+ this._swallow = (event) => {
151
+ event.stopPropagation();
152
+ };
153
+ this._onHostKeydown = (event) => {
154
+ if (!this._open || event.key !== 'Escape')
155
+ return;
156
+ if (!event.composedPath().includes(this))
157
+ return;
158
+ if (this._renaming)
159
+ return;
160
+ event.stopPropagation();
161
+ // The frame panel's drag has no cancel: Escape waits for the release.
162
+ if (this._drag?.dragging)
163
+ return;
164
+ this.closePanel();
165
+ };
166
+ /** Same capture as the catalogue: a wheel over the pane scrolls the pane. */
167
+ this._onHostWheel = (event) => {
168
+ if (!this._open)
169
+ return;
170
+ if (!event.composedPath().includes(this))
171
+ return;
172
+ event.stopPropagation();
173
+ };
174
+ this._onRenameKeydown = (event, id) => {
175
+ // The canvas behind binds Backspace, Delete and every letter: a key typed
176
+ // into the title must never reach it.
177
+ event.stopPropagation();
178
+ if (event.isComposing)
179
+ return;
180
+ if (event.key === 'Enter') {
181
+ event.preventDefault();
182
+ this._commitRename(id, event.currentTarget);
183
+ }
184
+ else if (event.key === 'Escape') {
185
+ event.preventDefault();
186
+ this._renaming = null;
187
+ }
188
+ };
189
+ this._onDocumentPointerMove = (event) => {
190
+ const drag = this._drag;
191
+ if (!drag)
192
+ return;
193
+ if (!drag.dragging) {
194
+ if (!panelDragStarted(drag, { x: event.clientX, y: event.clientY })) {
195
+ return;
196
+ }
197
+ drag.dragging = true;
198
+ this._pickUp(drag);
199
+ }
200
+ this._moveGhost(event);
201
+ this._drop = this._dropAt(event.clientX, event.clientY);
202
+ };
203
+ this._onDocumentPointerUp = (event) => {
204
+ const drag = this._drag;
205
+ if (drag?.dragging) {
206
+ this._swallowNextClick = true;
207
+ // A click only follows when the press and the release land on the same
208
+ // row; otherwise nothing would ever clear the flag.
209
+ setTimeout(() => (this._swallowNextClick = false), 0);
210
+ const drop = this._dropAt(event.clientX, event.clientY);
211
+ if (drop)
212
+ this._commitDrop(drag, drop);
213
+ }
214
+ this._endDrag();
215
+ };
216
+ this._openFilterMenu = (event) => {
217
+ const targets = selectionPaneFilterTargets(this.std);
218
+ popMenu(popupTargetFromElement(event.currentTarget), {
219
+ options: {
220
+ items: [
221
+ menu.action({
222
+ name: translateKey(this.std, ...SELECTION_PANE_FILTER_ALL),
223
+ isSelected: this._filter === null,
224
+ select: () => {
225
+ this._filter = null;
226
+ },
227
+ }),
228
+ ...targets.map(target => menu.action({
229
+ name: this._filterWording(target.id),
230
+ isSelected: this._filter === target.id,
231
+ select: () => {
232
+ this._filter = target.id;
233
+ },
234
+ })),
235
+ ],
236
+ },
237
+ });
238
+ };
239
+ /**
240
+ * "New layer": create it, then open its name for editing — the frame
241
+ * panel's inline title editor, as a double-click does — so the creation is
242
+ * unmistakable even under a filter (ADR 0031, amendments).
243
+ */
244
+ this._createLayer = () => {
245
+ const before = new Set(Object.keys(this._gfx.surface?.props.layers ?? {}));
246
+ this._run('canvas.layer.create', {});
247
+ const created = Object.keys(this._gfx.surface?.props.layers ?? {}).find(id => id !== DEFAULT_LAYER_ID && !before.has(id));
248
+ if (created)
249
+ this._renaming = created;
250
+ };
251
+ }
252
+ static {
253
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
254
+ __open_decorators = [state()];
255
+ __collapsed_decorators = [state()];
256
+ __filter_decorators = [state()];
257
+ __renaming_decorators = [state()];
258
+ __drop_decorators = [state()];
259
+ __ghost_decorators = [state()];
260
+ __selectionRevision_decorators = [state()];
261
+ __esDecorate(this, null, __open_decorators, { kind: "accessor", name: "_open", static: false, private: false, access: { has: obj => "_open" in obj, get: obj => obj._open, set: (obj, value) => { obj._open = value; } }, metadata: _metadata }, __open_initializers, __open_extraInitializers);
262
+ __esDecorate(this, null, __collapsed_decorators, { kind: "accessor", name: "_collapsed", static: false, private: false, access: { has: obj => "_collapsed" in obj, get: obj => obj._collapsed, set: (obj, value) => { obj._collapsed = value; } }, metadata: _metadata }, __collapsed_initializers, __collapsed_extraInitializers);
263
+ __esDecorate(this, null, __filter_decorators, { kind: "accessor", name: "_filter", static: false, private: false, access: { has: obj => "_filter" in obj, get: obj => obj._filter, set: (obj, value) => { obj._filter = value; } }, metadata: _metadata }, __filter_initializers, __filter_extraInitializers);
264
+ __esDecorate(this, null, __renaming_decorators, { kind: "accessor", name: "_renaming", static: false, private: false, access: { has: obj => "_renaming" in obj, get: obj => obj._renaming, set: (obj, value) => { obj._renaming = value; } }, metadata: _metadata }, __renaming_initializers, __renaming_extraInitializers);
265
+ __esDecorate(this, null, __drop_decorators, { kind: "accessor", name: "_drop", static: false, private: false, access: { has: obj => "_drop" in obj, get: obj => obj._drop, set: (obj, value) => { obj._drop = value; } }, metadata: _metadata }, __drop_initializers, __drop_extraInitializers);
266
+ __esDecorate(this, null, __ghost_decorators, { kind: "accessor", name: "_ghost", static: false, private: false, access: { has: obj => "_ghost" in obj, get: obj => obj._ghost, set: (obj, value) => { obj._ghost = value; } }, metadata: _metadata }, __ghost_initializers, __ghost_extraInitializers);
267
+ __esDecorate(this, null, __selectionRevision_decorators, { kind: "accessor", name: "_selectionRevision", static: false, private: false, access: { has: obj => "_selectionRevision" in obj, get: obj => obj._selectionRevision, set: (obj, value) => { obj._selectionRevision = value; } }, metadata: _metadata }, __selectionRevision_initializers, __selectionRevision_extraInitializers);
268
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
269
+ }
270
+ static { this.styles = css `
271
+ ${panelHeaderStyles}
272
+
273
+ :host {
274
+ position: absolute;
275
+ left: 0;
276
+ top: 0;
277
+ bottom: 0;
278
+ width: 0;
279
+ z-index: ${unsafeCSS(EDITOR_ANCHORED_PANEL_Z_INDEX)};
280
+ pointer-events: none;
281
+ font-family: var(--affine-font-family);
282
+ }
283
+
284
+ .selection-pane-panel {
285
+ position: absolute;
286
+ left: 0;
287
+ top: 0;
288
+ bottom: 0;
289
+ width: ${unsafeCSS(PANEL_WIDTH)};
290
+ box-sizing: border-box;
291
+ display: flex;
292
+ flex-direction: column;
293
+ background: var(--affine-background-overlay-panel-color, #fff);
294
+ border-right: 1px solid var(--affine-border-color);
295
+ box-shadow: var(--affine-shadow-2);
296
+ color: var(--affine-text-primary-color);
297
+ font-size: 14px;
298
+ line-height: 1.4;
299
+ pointer-events: auto;
300
+ user-select: none;
301
+ }
302
+
303
+ .selection-pane-panel:focus-visible {
304
+ outline: 2px solid var(--affine-primary-color);
305
+ outline-offset: -2px;
306
+ }
307
+
308
+ /* The header row itself is the frame panel's (panelHeaderStyles). */
309
+ .selection-pane-actions {
310
+ flex: none;
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 8px;
314
+ }
315
+
316
+ /* The pane's secondary text: the filter's name, a layer's filtered count. */
317
+ .selection-pane-filter-label,
318
+ .selection-pane-layer-note {
319
+ color: var(--affine-text-secondary-color);
320
+ font-size: 12px;
321
+ overflow: hidden;
322
+ text-overflow: ellipsis;
323
+ white-space: nowrap;
324
+ }
325
+
326
+ .selection-pane-filter-label {
327
+ padding: 6px 16px;
328
+ border-bottom: 1px solid var(--affine-border-color);
329
+ }
330
+
331
+ .selection-pane-layer-note {
332
+ padding-top: 2px;
333
+ padding-bottom: 4px;
334
+ }
335
+
336
+ .selection-pane-body {
337
+ position: relative;
338
+ flex: 1;
339
+ min-height: 0;
340
+ overflow-y: auto;
341
+ overflow-x: hidden;
342
+ overscroll-behavior: contain;
343
+ -webkit-overflow-scrolling: touch;
344
+ padding: 4px 0 16px;
345
+ }
346
+
347
+ .selection-pane-empty {
348
+ padding: 16px;
349
+ color: var(--affine-text-secondary-color);
350
+ }
351
+
352
+ .selection-pane-row {
353
+ display: flex;
354
+ align-items: center;
355
+ gap: 4px;
356
+ min-height: 32px;
357
+ box-sizing: border-box;
358
+ padding-right: 8px;
359
+ border-top: 2px solid transparent;
360
+ border-bottom: 2px solid transparent;
361
+ cursor: pointer;
362
+ }
363
+
364
+ @media (hover: hover) {
365
+ .selection-pane-row:hover {
366
+ background: var(--affine-hover-color);
367
+ }
368
+ }
369
+
370
+ .selection-pane-row[data-selected] {
371
+ background: var(--affine-hover-color);
372
+ color: var(--affine-primary-color);
373
+ }
374
+
375
+ /* The row being dragged stays in place, dimmed, like the frame panel's
376
+ placeholder card; its ghost follows the pointer. */
377
+ .selection-pane-row[data-dragging] {
378
+ opacity: 0.5;
379
+ }
380
+
381
+ /* While dragging, the pane says whether a drop here would land. */
382
+ .selection-pane-panel[data-drag='valid'] {
383
+ cursor: grabbing;
384
+ }
385
+
386
+ .selection-pane-panel[data-drag='invalid'] {
387
+ cursor: not-allowed;
388
+ }
389
+
390
+ .selection-pane-panel[data-drag] * {
391
+ cursor: inherit;
392
+ }
393
+
394
+ /* The frame panel's insert indicator: a line at the gap a drop lands in. */
395
+ .selection-pane-drop-indicator {
396
+ position: absolute;
397
+ right: 8px;
398
+ height: 2px;
399
+ border-radius: 1px;
400
+ background: var(--affine-primary-color);
401
+ transform: translateY(-1px);
402
+ pointer-events: none;
403
+ }
404
+
405
+ /*
406
+ The frame panel's drag mask: over the whole viewport for the length of
407
+ the drag, so the cursor says "grabbing" or "not-allowed" wherever the
408
+ pointer is (the panel's rule above hands it down) and the canvas under
409
+ it takes no hover.
410
+ */
411
+ .selection-pane-drag-mask {
412
+ position: fixed;
413
+ inset: 0;
414
+ z-index: 1;
415
+ }
416
+
417
+ /* The row itself at its own width, like the frame panel's dragged card. */
418
+ .selection-pane-drag-ghost {
419
+ position: absolute;
420
+ top: 0;
421
+ left: 0;
422
+ z-index: 2;
423
+ display: flex;
424
+ align-items: center;
425
+ gap: 4px;
426
+ min-height: 32px;
427
+ box-sizing: border-box;
428
+ padding: 4px 8px;
429
+ border: 1px solid var(--affine-border-color);
430
+ border-radius: 4px;
431
+ background: var(--affine-background-overlay-panel-color);
432
+ box-shadow: var(--affine-shadow-2);
433
+ white-space: nowrap;
434
+ overflow: hidden;
435
+ pointer-events: none;
436
+ }
437
+
438
+ .selection-pane-drag-ghost .selection-pane-label {
439
+ flex: initial;
440
+ }
441
+
442
+ /* A row dragged onto a layer moves into it (ADR 0031 §5). */
443
+ .selection-pane-row[data-drop='into'] {
444
+ outline: 2px solid var(--affine-primary-color);
445
+ outline-offset: -2px;
446
+ }
447
+
448
+ .selection-pane-layer-row {
449
+ font-weight: 600;
450
+ }
451
+
452
+ /* The active layer: where this viewer's new elements land. */
453
+ .selection-pane-layer-row[data-active] .selection-pane-label,
454
+ .selection-pane-layer-row[data-active] .selection-pane-icon {
455
+ color: var(--affine-primary-color);
456
+ }
457
+
458
+ .selection-pane-chevron,
459
+ .selection-pane-eye,
460
+ .selection-pane-lock,
461
+ .selection-pane-more {
462
+ flex: none;
463
+ display: flex;
464
+ align-items: center;
465
+ justify-content: center;
466
+ width: 24px;
467
+ height: 24px;
468
+ padding: 0;
469
+ border: none;
470
+ border-radius: 4px;
471
+ background: transparent;
472
+ color: var(--affine-icon-color);
473
+ cursor: pointer;
474
+ }
475
+
476
+ .selection-pane-chevron svg,
477
+ .selection-pane-eye svg,
478
+ .selection-pane-lock svg,
479
+ .selection-pane-more svg,
480
+ .selection-pane-icon svg {
481
+ width: 16px;
482
+ height: 16px;
483
+ }
484
+
485
+ .selection-pane-chevron:hover,
486
+ .selection-pane-eye:hover,
487
+ .selection-pane-lock:hover,
488
+ .selection-pane-more:hover {
489
+ background: var(--affine-hover-color);
490
+ }
491
+
492
+ .selection-pane-chevron[hidden] {
493
+ visibility: hidden;
494
+ }
495
+
496
+ /*
497
+ Off states show on hover only, like PowerPoint's pane: a column of open
498
+ eyes and open padlocks on every row would be noise. A hidden or locked
499
+ row keeps its mark visible, which is what makes it findable.
500
+ */
501
+ .selection-pane-eye[aria-pressed='false'],
502
+ .selection-pane-lock[aria-pressed='false'],
503
+ .selection-pane-more {
504
+ opacity: 0;
505
+ }
506
+
507
+ .selection-pane-row:hover .selection-pane-eye,
508
+ .selection-pane-row:hover .selection-pane-lock,
509
+ .selection-pane-row:hover .selection-pane-more,
510
+ .selection-pane-eye:focus-visible,
511
+ .selection-pane-lock:focus-visible,
512
+ .selection-pane-more:focus-visible {
513
+ opacity: 1;
514
+ }
515
+
516
+ .selection-pane-row[data-hidden-local] .selection-pane-label,
517
+ .selection-pane-row[data-hidden-local] .selection-pane-icon {
518
+ opacity: 0.5;
519
+ }
520
+
521
+ .selection-pane-row[data-hidden-everyone] .selection-pane-label,
522
+ .selection-pane-layer-row[data-hidden-local] .selection-pane-label {
523
+ opacity: 0.5;
524
+ }
525
+
526
+ /* Hidden for everyone: the theme warning token marks what others cannot see. */
527
+ .selection-pane-row[data-hidden-everyone] .selection-pane-icon {
528
+ color: var(--affine-warning-color);
529
+ }
530
+
531
+ .selection-pane-lock:disabled {
532
+ cursor: default;
533
+ color: var(--affine-text-disable-color);
534
+ }
535
+
536
+ .selection-pane-icon {
537
+ flex: none;
538
+ display: flex;
539
+ align-items: center;
540
+ color: var(--affine-icon-color);
541
+ }
542
+
543
+ .selection-pane-label {
544
+ flex: 1;
545
+ min-width: 0;
546
+ overflow: hidden;
547
+ text-overflow: ellipsis;
548
+ white-space: nowrap;
549
+ }
550
+
551
+ .selection-pane-rename {
552
+ flex: 1;
553
+ min-width: 0;
554
+ padding: 2px 6px;
555
+ border: 1px solid var(--affine-border-color);
556
+ border-radius: 4px;
557
+ background: var(--affine-background-primary-color);
558
+ color: inherit;
559
+ font: inherit;
560
+ outline: none;
561
+ }
562
+
563
+ .selection-pane-rename:focus {
564
+ box-shadow: var(--affine-active-shadow);
565
+ border-color: var(--affine-primary-color);
566
+ }
567
+ `; }
568
+ #_open_accessor_storage;
569
+ get _open() { return this.#_open_accessor_storage; }
570
+ set _open(value) { this.#_open_accessor_storage = value; }
571
+ #_collapsed_accessor_storage;
572
+ /** Group rows the user folded. UI state, never stored. */
573
+ get _collapsed() { return this.#_collapsed_accessor_storage; }
574
+ set _collapsed(value) { this.#_collapsed_accessor_storage = value; }
575
+ #_filter_accessor_storage;
576
+ /** The frame the list is narrowed to, or `null`. */
577
+ get _filter() { return this.#_filter_accessor_storage; }
578
+ set _filter(value) { this.#_filter_accessor_storage = value; }
579
+ #_renaming_accessor_storage;
580
+ /** The group row being renamed, or `null`. */
581
+ get _renaming() { return this.#_renaming_accessor_storage; }
582
+ set _renaming(value) { this.#_renaming_accessor_storage = value; }
583
+ #_drop_accessor_storage;
584
+ /** Where the dragged row would land. */
585
+ get _drop() { return this.#_drop_accessor_storage; }
586
+ set _drop(value) { this.#_drop_accessor_storage = value; }
587
+ #_ghost_accessor_storage;
588
+ /** Where the dragged row's ghost is drawn, in the panel's own box. */
589
+ get _ghost() { return this.#_ghost_accessor_storage; }
590
+ set _ghost(value) { this.#_ghost_accessor_storage = value; }
591
+ #_selectionRevision_accessor_storage;
592
+ /** Bumped when the canvas selection changes, so the rows repaint. */
593
+ get _selectionRevision() { return this.#_selectionRevision_accessor_storage; }
594
+ set _selectionRevision(value) { this.#_selectionRevision_accessor_storage = value; }
595
+ get paneOpen() {
596
+ return this._open;
597
+ }
598
+ get _gfx() {
599
+ return this.std.get(GfxControllerIdentifier);
600
+ }
601
+ _setOpen(open) {
602
+ this._open = open;
603
+ const model = this.std.getOptional(SelectionPaneModel);
604
+ if (model)
605
+ model.open$.value = open;
606
+ if (!open) {
607
+ this._renaming = null;
608
+ this._clearHighlight();
609
+ }
610
+ }
611
+ /** Show the pane. Called through `SelectionPaneProvider` only. */
612
+ openPanel() {
613
+ this._setOpen(true);
614
+ }
615
+ _wire() {
616
+ const host = this.std.host;
617
+ host.addEventListener('keydown', this._onHostKeydown, true);
618
+ host.addEventListener('wheel', this._onHostWheel, true);
619
+ const subscription = this._gfx.selection.slots.updated.subscribe(() => {
620
+ this._selectionRevision++;
621
+ });
622
+ this._disposables.add(() => {
623
+ host.removeEventListener('keydown', this._onHostKeydown, true);
624
+ host.removeEventListener('wheel', this._onHostWheel, true);
625
+ subscription.unsubscribe();
626
+ this._endDrag();
627
+ });
628
+ }
629
+ connectedCallback() {
630
+ super.connectedCallback();
631
+ if (this.hasUpdated)
632
+ this._wire();
633
+ }
634
+ firstUpdated() {
635
+ this._wire();
636
+ }
637
+ disconnectedCallback() {
638
+ super.disconnectedCallback();
639
+ const model = this.std.getOptional(SelectionPaneModel);
640
+ if (model)
641
+ model.open$.value = false;
642
+ }
643
+ /* ── Canvas mirrors ─────────────────────────────────────────────────── */
644
+ _highlight(id) {
645
+ this._gfx.highlightElements([id], { duration: 0 });
646
+ }
647
+ _clearHighlight() {
648
+ this._gfx.highlight.clear();
649
+ }
650
+ _select(event, node) {
651
+ const { selection } = this._gfx;
652
+ if (event.shiftKey || event.metaKey || event.ctrlKey) {
653
+ const ids = new Set(selection.selectedIds);
654
+ if (ids.has(node.id))
655
+ ids.delete(node.id);
656
+ else
657
+ ids.add(node.id);
658
+ selection.set({ elements: [...ids], editing: false });
659
+ return;
660
+ }
661
+ selection.set({ elements: [node.id], editing: false });
662
+ }
663
+ _run(id, params) {
664
+ runCommand(this.std, paneCommand(id), PANE_INVOCATION, params);
665
+ }
666
+ /* ── Rows ───────────────────────────────────────────────────────────── */
667
+ /**
668
+ * The visible rows of `nodes` (the tree as filtered), with `full` the tree
669
+ * before the filter: what tells a layer emptied by the filter from an empty
670
+ * one.
671
+ */
672
+ _rows(nodes, full = nodes) {
673
+ const membersOf = new Map(full
674
+ .filter(node => node.kind === 'layer')
675
+ .map(node => [node.id, node.children?.length ?? 0]));
676
+ const rows = [];
677
+ const walk = (list, depth, parent) => {
678
+ for (const node of list) {
679
+ const row = { node, depth, parent };
680
+ if (node.kind === 'layer' && node.children?.length === 0) {
681
+ const members = membersOf.get(node.id) ?? 0;
682
+ if (members > 0)
683
+ row.hiddenByFilter = members;
684
+ }
685
+ rows.push(row);
686
+ if (node.children && !this._collapsed.has(node.id)) {
687
+ walk(node.children, depth + 1, node.id);
688
+ }
689
+ }
690
+ };
691
+ walk(nodes, 0, '');
692
+ return rows;
693
+ }
694
+ _toggleCollapsed(id) {
695
+ const next = new Set(this._collapsed);
696
+ if (next.has(id))
697
+ next.delete(id);
698
+ else
699
+ next.add(id);
700
+ this._collapsed = next;
701
+ }
702
+ _onRowClick(event, node) {
703
+ if (this._swallowNextClick) {
704
+ this._swallowNextClick = false;
705
+ return;
706
+ }
707
+ // A layer row is not on the canvas: a click makes it the active layer,
708
+ // where this viewer's new elements land (session only, never stored).
709
+ if (node.kind === 'layer') {
710
+ this.std.getOptional(CanvasActiveLayer)?.choose(node.id);
711
+ return;
712
+ }
713
+ this._select(event, node);
714
+ }
715
+ _onRowDblClick(node) {
716
+ if (this.std.store.readonly)
717
+ return;
718
+ if (node.type !== 'group' &&
719
+ node.type !== 'affine:frame' &&
720
+ node.kind !== 'layer') {
721
+ return;
722
+ }
723
+ this._renaming = node.id;
724
+ }
725
+ /** A layer's name — the default layer's seed while it has no record. */
726
+ _layerName(id) {
727
+ return userLayerName(this.std, id);
728
+ }
729
+ _onLockClick(event, node) {
730
+ event.stopPropagation();
731
+ this._run(node.locked ? 'canvas.element.unlock' : 'canvas.element.lock', {
732
+ ids: [node.id],
733
+ });
734
+ }
735
+ /**
736
+ * Hide this row for this viewer, or show it again. Not refused on a
737
+ * read-only document: nothing reaches the document (ADR 0031 §8).
738
+ */
739
+ _onEyeClick(event, node) {
740
+ event.stopPropagation();
741
+ // A layer's eye hides the whole layer for this viewer (stage 7).
742
+ const target = node.kind === 'layer' ? { layerIds: [node.id] } : { ids: [node.id] };
743
+ this._run('canvas.visibility.hideLocal', {
744
+ ...target,
745
+ hidden: !node.hiddenLocal,
746
+ });
747
+ }
748
+ /**
749
+ * The row's menu: the actions that write to the DOCUMENT for every viewer,
750
+ * kept off the row's quick toggles so they are never one stray click away.
751
+ * "Hide for everyone" is painted with the theme warning tokens (ADR 0031,
752
+ * resolved at acceptance). A read-only document offers none of them, so the
753
+ * menu does not open there.
754
+ */
755
+ _openRowMenu(anchor, node) {
756
+ if (this.std.store.readonly)
757
+ return;
758
+ if (node.kind === 'layer') {
759
+ this._openLayerMenu(anchor, node);
760
+ return;
761
+ }
762
+ popMenu(popupTargetFromElement(anchor), {
763
+ options: { items: [this._hideForEveryoneItem(node)] },
764
+ });
765
+ }
766
+ /**
767
+ * "Hide for everyone" (or "Show for everyone"), in a row's or a layer's
768
+ * menu alike: painted with the warning tokens, and written on the element
769
+ * or on the layer's record (`hidden: true`) depending on the row.
770
+ */
771
+ _hideForEveryoneItem(node) {
772
+ const wording = node.hiddenForEveryone
773
+ ? SELECTION_PANE_SHOW_FOR_EVERYONE
774
+ : SELECTION_PANE_HIDE_FOR_EVERYONE;
775
+ const target = node.kind === 'layer' ? { layerIds: [node.id] } : { ids: [node.id] };
776
+ return menu.action({
777
+ name: translateKey(this.std, ...wording),
778
+ prefix: node.hiddenForEveryone ? ViewIcon() : InvisibleIcon(),
779
+ class: { 'warning-item': true },
780
+ testId: 'selection-pane-hide-for-everyone',
781
+ select: () => {
782
+ this._run('canvas.visibility.hideForEveryone', {
783
+ ...target,
784
+ hidden: !node.hiddenForEveryone,
785
+ });
786
+ },
787
+ });
788
+ }
789
+ /**
790
+ * A layer's menu (ADR 0031 stage 7): "Hide for everyone" — `hidden: true`
791
+ * on the record, painted with the warning tokens like the element entry —
792
+ * and "Delete layer", which takes the members with it in one undo step.
793
+ * The default layer cannot be deleted, so its menu has no such entry.
794
+ */
795
+ _openLayerMenu(anchor, node) {
796
+ popMenu(popupTargetFromElement(anchor), {
797
+ options: {
798
+ items: [
799
+ this._hideForEveryoneItem(node),
800
+ menu.action({
801
+ name: translateKey(this.std, ...SELECTION_PANE_DELETE_LAYER),
802
+ prefix: DeleteIcon(),
803
+ class: { 'delete-item': true },
804
+ testId: 'selection-pane-delete-layer',
805
+ hide: () => node.id === DEFAULT_LAYER_ID,
806
+ select: () => {
807
+ this._run('canvas.layer.delete', { id: node.id });
808
+ },
809
+ }),
810
+ ],
811
+ },
812
+ });
813
+ }
814
+ _onRowContextMenu(event, node) {
815
+ event.preventDefault();
816
+ event.stopPropagation();
817
+ this._openRowMenu(event.currentTarget, node);
818
+ }
819
+ _commitRename(id, input) {
820
+ if (this._renaming !== id)
821
+ return;
822
+ this._renaming = null;
823
+ if (this._layerName(id) !== null) {
824
+ this._run('canvas.layer.rename', { id, name: input.value });
825
+ return;
826
+ }
827
+ const frame = this._gfx.getElementById(id) instanceof FrameBlockModel;
828
+ this._run(frame ? 'canvas.frame.rename' : 'canvas.group.rename', {
829
+ id,
830
+ title: input.value,
831
+ });
832
+ }
833
+ /* ── Drag to reorder ────────────────────────────────────────────────── */
834
+ /*
835
+ * The frame panel's model (`fragments/frame-panel`): a press becomes a drag
836
+ * past its threshold and picks the row up, selecting it; the row stays in
837
+ * place, dimmed; a copy of it at its own width follows the pointer; a mask
838
+ * over the viewport carries the cursor; a line marks the gap a release would
839
+ * land in, and a gap the row cannot go to shows no line and a `not-allowed`
840
+ * cursor. Escape does nothing until the release. A read-only document never
841
+ * starts one.
842
+ */
843
+ _onRowPointerDown(event, row) {
844
+ if (event.button !== 0 || this.std.store.readonly)
845
+ return;
846
+ const target = event.target;
847
+ if (target.closest('button, input'))
848
+ return;
849
+ this._drag = {
850
+ id: row.node.id,
851
+ kind: row.node.kind,
852
+ parent: row.parent,
853
+ x: event.clientX,
854
+ y: event.clientY,
855
+ width: event.currentTarget.getBoundingClientRect().width,
856
+ dragging: false,
857
+ };
858
+ document.addEventListener('pointermove', this._onDocumentPointerMove, true);
859
+ document.addEventListener('pointerup', this._onDocumentPointerUp, true);
860
+ }
861
+ /**
862
+ * Which model stands for a row in the dragged row's own stack — the stack
863
+ * `canvas.element.reorder` restacks it in, the models sharing its raw
864
+ * `group` — or `undefined` for a row outside it. A frame's members paint
865
+ * together right above the frame, so for a loose element they stand for
866
+ * their frame. `null` when the dragged row cannot be restacked at all (a
867
+ * mindmap node moves with its mindmap).
868
+ */
869
+ _stackOf(drag) {
870
+ if (drag.kind === 'layer')
871
+ return id => id;
872
+ const gfx = this._gfx;
873
+ const dragged = gfx.getElementById(drag.id);
874
+ if (!dragged)
875
+ return null;
876
+ const stack = rawGroupOf(dragged);
877
+ if (stack instanceof MindmapElementModel)
878
+ return null;
879
+ return id => {
880
+ let model = gfx.getElementById(id);
881
+ for (let hops = 0; model && hops < 32; hops++) {
882
+ const group = rawGroupOf(model);
883
+ if (group === stack)
884
+ return model.id;
885
+ model = group;
886
+ }
887
+ return undefined;
888
+ };
889
+ }
890
+ /** Where a release at `(clientX, clientY)` would land the dragged row. */
891
+ _dropAt(clientX, clientY) {
892
+ const drag = this._drag;
893
+ const body = this.shadowRoot?.querySelector('[data-testid="selection-pane-body"]');
894
+ if (!drag || !body)
895
+ return null;
896
+ const box = body.getBoundingClientRect();
897
+ if (clientX < box.left ||
898
+ clientX > box.right ||
899
+ clientY < box.top ||
900
+ clientY > box.bottom) {
901
+ return { kind: 'refused' };
902
+ }
903
+ const byId = new Map(this._visibleRows.map(row => [row.node.id, row]));
904
+ const shown = Array.from(body.querySelectorAll('[data-testid="selection-pane-row"], [data-testid="selection-pane-layer"]')).flatMap(element => {
905
+ const row = byId.get(element.dataset.id ?? '');
906
+ return row ? [{ element, row }] : [];
907
+ });
908
+ // A canvas row over a layer's header moves INTO that layer (§5).
909
+ if (drag.kind !== 'layer') {
910
+ const header = shown.find(({ element, row }) => {
911
+ if (row.node.kind !== 'layer')
912
+ return false;
913
+ const rect = element.getBoundingClientRect();
914
+ return clientY >= rect.top && clientY <= rect.bottom;
915
+ });
916
+ if (header)
917
+ return { kind: 'into', id: header.row.node.id };
918
+ }
919
+ // The gap: past the middle of a row is below it.
920
+ let gap = 0;
921
+ for (const { element } of shown) {
922
+ const rect = element.getBoundingClientRect();
923
+ if (clientY > rect.top + rect.height / 2)
924
+ gap++;
925
+ }
926
+ const stackOf = this._stackOf(drag);
927
+ const slot = stackOf
928
+ ? paneSlotAtGap(shown.map(({ row }) => row), gap, drag.parent, this._lists)
929
+ : null;
930
+ const list = slot ? this._lists.lists.get(slot.parent) : undefined;
931
+ const landing = slot && list && stackOf
932
+ ? paneDropAbove(list, slot.index, drag.id, stackOf)
933
+ : null;
934
+ if (!slot || !landing)
935
+ return { kind: 'refused' };
936
+ const under = shown[gap]?.element;
937
+ const last = shown[shown.length - 1]?.element;
938
+ const top = under
939
+ ? under.offsetTop
940
+ : last
941
+ ? last.offsetTop + last.offsetHeight
942
+ : 0;
943
+ return {
944
+ kind: 'slot',
945
+ above: landing.above,
946
+ top,
947
+ left: 8 + slot.depth * INDENT_PX,
948
+ };
949
+ }
950
+ _moveGhost(event) {
951
+ const panel = this.shadowRoot?.querySelector('[data-testid="selection-pane-panel"]');
952
+ if (!panel)
953
+ return;
954
+ const box = panel.getBoundingClientRect();
955
+ this._ghost = { x: event.clientX - box.left, y: event.clientY - box.top };
956
+ }
957
+ /** A canvas row picked up is selected, as the frame panel selects a card. */
958
+ _pickUp(drag) {
959
+ if (drag.kind === 'layer')
960
+ return;
961
+ const { selection } = this._gfx;
962
+ if (selection.selectedIds.includes(drag.id))
963
+ return;
964
+ selection.set({ elements: [drag.id], editing: false });
965
+ }
966
+ /**
967
+ * One write per gesture, through the command: `layer` for a drop into a
968
+ * layer, one `index` for a slot. The command writes nothing when the slot
969
+ * is where the row already is, and a refused drop never reaches it.
970
+ */
971
+ _commitDrop(drag, drop) {
972
+ if (drop.kind === 'refused')
973
+ return;
974
+ if (drop.kind === 'into') {
975
+ this._run('canvas.layer.moveElements', {
976
+ ids: [drag.id],
977
+ layerId: drop.id,
978
+ });
979
+ return;
980
+ }
981
+ if (drag.kind === 'layer') {
982
+ this._run('canvas.layer.reorder', { id: drag.id, above: drop.above });
983
+ return;
984
+ }
985
+ this._run('canvas.element.reorder', { id: drag.id, above: drop.above });
986
+ }
987
+ _endDrag() {
988
+ document.removeEventListener('pointermove', this._onDocumentPointerMove, true);
989
+ document.removeEventListener('pointerup', this._onDocumentPointerUp, true);
990
+ const wasDragging = this._drag?.dragging;
991
+ this._drag = null;
992
+ this._drop = null;
993
+ this._ghost = null;
994
+ if (wasDragging)
995
+ this.requestUpdate();
996
+ }
997
+ _renderGhost() {
998
+ const drag = this._drag;
999
+ const at = this._ghost;
1000
+ if (!drag?.dragging || !at)
1001
+ return nothing;
1002
+ const style = styleMap({
1003
+ transform: `translate(${at.x - 16}px, ${at.y - 8}px)`,
1004
+ width: `${drag.width}px`,
1005
+ });
1006
+ if (drag.kind === 'layer') {
1007
+ return html `<div
1008
+ class="selection-pane-drag-ghost"
1009
+ data-testid="selection-pane-drag-ghost"
1010
+ style=${style}
1011
+ >
1012
+ <span class="selection-pane-icon">${LayerIcon()}</span>
1013
+ <span class="selection-pane-label"
1014
+ >${this._layerName(drag.id) ?? ''}</span
1015
+ >
1016
+ </div>`;
1017
+ }
1018
+ const model = this._gfx.getElementById(drag.id);
1019
+ if (!model)
1020
+ return nothing;
1021
+ const type = model instanceof GfxBlockElementModel
1022
+ ? model.flavour
1023
+ : model.type;
1024
+ return html `<div
1025
+ class="selection-pane-drag-ghost"
1026
+ data-testid="selection-pane-drag-ghost"
1027
+ style=${style}
1028
+ >
1029
+ <span class="selection-pane-icon">${selectionPaneRowIcon(type)}</span>
1030
+ <span class="selection-pane-label"
1031
+ >${selectionPaneRowLabel(this.std, model)}</span
1032
+ >
1033
+ </div>`;
1034
+ }
1035
+ _renderDropIndicator() {
1036
+ const drop = this._drop;
1037
+ if (!this._drag?.dragging || drop?.kind !== 'slot')
1038
+ return nothing;
1039
+ return html `<div
1040
+ class="selection-pane-drop-indicator"
1041
+ data-testid="selection-pane-drop-indicator"
1042
+ style=${styleMap({ top: `${drop.top}px`, left: `${drop.left}px` })}
1043
+ ></div>`;
1044
+ }
1045
+ /* ── Filter ─────────────────────────────────────────────────────────── */
1046
+ _filterName(id) {
1047
+ const model = this._gfx.getElementById(id);
1048
+ return model ? selectionPaneRowLabel(this.std, model) : id;
1049
+ }
1050
+ _filterWording(id) {
1051
+ return translateKey(this.std, ...SELECTION_PANE_FILTER_FRAME, {
1052
+ name: this._filterName(id),
1053
+ });
1054
+ }
1055
+ /* ── Render ─────────────────────────────────────────────────────────── */
1056
+ /**
1057
+ * A user layer's row (ADR 0031 §2): its name, renamed in place with a
1058
+ * double-click; a click makes it the active layer; collapsible like a
1059
+ * group (UI state, never stored); dragged among the layers to reorder, and
1060
+ * the drop target of a canvas row dragged onto it. The default layer's row
1061
+ * is drawn the same before it has a record (ADR 0031 amendments): its
1062
+ * rename or "hide for everyone" is what records it.
1063
+ */
1064
+ _renderLayerRow(row) {
1065
+ const { node, depth } = row;
1066
+ const std = this.std;
1067
+ const name = this._layerName(node.id) ?? '';
1068
+ const collapsed = this._collapsed.has(node.id);
1069
+ const active = (std.getOptional(CanvasActiveLayer)?.resolve() ?? null) === node.id;
1070
+ const drop = this._drop?.kind === 'into' && this._drop.id === node.id
1071
+ ? 'into'
1072
+ : undefined;
1073
+ const dragging = this._drag?.dragging && this._drag.id === node.id;
1074
+ return html `<div
1075
+ class="selection-pane-row selection-pane-layer-row"
1076
+ role="treeitem"
1077
+ data-testid="selection-pane-layer"
1078
+ data-id=${node.id}
1079
+ data-kind="layer"
1080
+ aria-level=${depth + 1}
1081
+ aria-expanded=${collapsed ? 'false' : 'true'}
1082
+ title=${active
1083
+ ? translateKey(std, ...SELECTION_PANE_ACTIVE_LAYER)
1084
+ : nothing}
1085
+ ?data-active=${active}
1086
+ ?data-hidden-local=${node.hiddenLocal}
1087
+ ?data-hidden-everyone=${node.hiddenForEveryone}
1088
+ ?data-dragging=${dragging}
1089
+ data-drop=${drop ?? nothing}
1090
+ style=${styleMap({ paddingLeft: `${8 + depth * INDENT_PX}px` })}
1091
+ @click=${(event) => this._onRowClick(event, node)}
1092
+ @dblclick=${() => this._onRowDblClick(node)}
1093
+ @contextmenu=${(event) => this._onRowContextMenu(event, node)}
1094
+ @pointerdown=${(event) => this._onRowPointerDown(event, row)}
1095
+ >
1096
+ <button
1097
+ class="selection-pane-chevron"
1098
+ type="button"
1099
+ data-testid="selection-pane-collapse"
1100
+ aria-label=${translateKey(std, ...(collapsed ? SELECTION_PANE_EXPAND : SELECTION_PANE_COLLAPSE))}
1101
+ @click=${(event) => {
1102
+ event.stopPropagation();
1103
+ this._toggleCollapsed(node.id);
1104
+ }}
1105
+ >
1106
+ ${collapsed ? ArrowRightSmallIcon() : ArrowDownSmallIcon()}
1107
+ </button>
1108
+ <span class="selection-pane-icon">${LayerIcon()}</span>
1109
+ ${this._renderName(node.id, name)} ${this._renderEye(node)}
1110
+ ${std.store.readonly
1111
+ ? nothing
1112
+ : html `<button
1113
+ class="selection-pane-more"
1114
+ type="button"
1115
+ data-testid="selection-pane-more"
1116
+ aria-haspopup="menu"
1117
+ aria-label=${translateKey(std, ...SELECTION_PANE_ROW_MENU)}
1118
+ @click=${(event) => {
1119
+ event.stopPropagation();
1120
+ this._openRowMenu(event.currentTarget, node);
1121
+ }}
1122
+ >
1123
+ ${MoreHorizontalIcon()}
1124
+ </button>`}
1125
+ </div>
1126
+ ${row.hiddenByFilter && !collapsed
1127
+ ? html `<div
1128
+ class="selection-pane-layer-note"
1129
+ data-testid="selection-pane-layer-filtered"
1130
+ data-id=${node.id}
1131
+ style=${styleMap({
1132
+ paddingLeft: `${8 + (depth + 1) * INDENT_PX + 28}px`,
1133
+ })}
1134
+ >
1135
+ ${translateKey(std, ...SELECTION_PANE_LAYER_FILTERED, {
1136
+ count: row.hiddenByFilter,
1137
+ })}
1138
+ </div>`
1139
+ : nothing}`;
1140
+ }
1141
+ /** A row's name, or the field that renames it in place. */
1142
+ _renderName(id, name) {
1143
+ if (this._renaming !== id) {
1144
+ return html `<span class="selection-pane-label" title=${name}
1145
+ >${name}</span
1146
+ >`;
1147
+ }
1148
+ return html `<input
1149
+ class="selection-pane-rename"
1150
+ data-testid="selection-pane-rename"
1151
+ aria-label=${translateKey(this.std, ...TOOLBAR_RENAME)}
1152
+ .value=${name}
1153
+ @click=${this._swallow}
1154
+ @dblclick=${this._swallow}
1155
+ @keydown=${(event) => this._onRenameKeydown(event, id)}
1156
+ @blur=${(event) => this._commitRename(id, event.target)}
1157
+ />`;
1158
+ }
1159
+ /** A row's eye: hide it, or the whole layer, for this viewer only. */
1160
+ _renderEye(node) {
1161
+ return html `<button
1162
+ class="selection-pane-eye"
1163
+ type="button"
1164
+ data-testid="selection-pane-eye"
1165
+ aria-pressed=${node.hiddenLocal ? 'true' : 'false'}
1166
+ aria-label=${translateKey(this.std, ...(node.hiddenLocal ? SELECTION_PANE_SHOW : SELECTION_PANE_HIDE))}
1167
+ @click=${(event) => this._onEyeClick(event, node)}
1168
+ >
1169
+ ${node.hiddenLocal ? InvisibleIcon() : ViewIcon()}
1170
+ </button>`;
1171
+ }
1172
+ _renderRow(row) {
1173
+ const { node, depth } = row;
1174
+ if (node.kind === 'layer')
1175
+ return this._renderLayerRow(row);
1176
+ const std = this.std;
1177
+ const model = this._gfx.getElementById(node.id);
1178
+ if (!model)
1179
+ return nothing;
1180
+ const label = selectionPaneRowLabel(std, model);
1181
+ const selected = this._gfx.selection.has(node.id);
1182
+ const container = node.children !== undefined;
1183
+ const collapsed = this._collapsed.has(node.id);
1184
+ const readonly = std.store.readonly;
1185
+ const drop = this._drop?.kind === 'into' && this._drop.id === node.id
1186
+ ? 'into'
1187
+ : undefined;
1188
+ const dragging = this._drag?.dragging && this._drag.id === node.id;
1189
+ return html `<div
1190
+ class="selection-pane-row"
1191
+ role="treeitem"
1192
+ data-testid="selection-pane-row"
1193
+ data-id=${node.id}
1194
+ data-type=${node.type}
1195
+ data-kind=${node.kind}
1196
+ aria-level=${depth + 1}
1197
+ aria-selected=${selected ? 'true' : 'false'}
1198
+ aria-expanded=${container ? (collapsed ? 'false' : 'true') : nothing}
1199
+ ?data-selected=${selected}
1200
+ ?data-locked=${node.locked}
1201
+ ?data-hidden-local=${node.hiddenLocal}
1202
+ ?data-hidden-everyone=${node.hiddenForEveryone}
1203
+ ?data-dragging=${dragging}
1204
+ data-drop=${drop ?? nothing}
1205
+ style=${styleMap({ paddingLeft: `${8 + depth * INDENT_PX}px` })}
1206
+ @click=${(event) => this._onRowClick(event, node)}
1207
+ @contextmenu=${(event) => this._onRowContextMenu(event, node)}
1208
+ @dblclick=${() => this._onRowDblClick(node)}
1209
+ @pointerenter=${() => this._highlight(node.id)}
1210
+ @pointerdown=${(event) => this._onRowPointerDown(event, row)}
1211
+ >
1212
+ <button
1213
+ class="selection-pane-chevron"
1214
+ type="button"
1215
+ data-testid="selection-pane-collapse"
1216
+ ?hidden=${!container}
1217
+ aria-label=${translateKey(std, ...(collapsed ? SELECTION_PANE_EXPAND : SELECTION_PANE_COLLAPSE))}
1218
+ @click=${(event) => {
1219
+ event.stopPropagation();
1220
+ this._toggleCollapsed(node.id);
1221
+ }}
1222
+ >
1223
+ ${collapsed ? ArrowRightSmallIcon() : ArrowDownSmallIcon()}
1224
+ </button>
1225
+ <span class="selection-pane-icon"
1226
+ >${selectionPaneRowIcon(node.type)}</span
1227
+ >
1228
+ ${this._renderName(node.id, label)} ${this._renderEye(node)}
1229
+ <button
1230
+ class="selection-pane-lock"
1231
+ type="button"
1232
+ data-testid="selection-pane-lock"
1233
+ aria-pressed=${node.locked ? 'true' : 'false'}
1234
+ aria-label=${translateKey(std, ...(node.locked ? SELECTION_PANE_UNLOCK : TOOLBAR_LOCK))}
1235
+ ?disabled=${readonly}
1236
+ @click=${(event) => this._onLockClick(event, node)}
1237
+ >
1238
+ ${node.locked ? LockIcon() : UnlockIcon()}
1239
+ </button>
1240
+ ${readonly
1241
+ ? nothing
1242
+ : html `<button
1243
+ class="selection-pane-more"
1244
+ type="button"
1245
+ data-testid="selection-pane-more"
1246
+ aria-haspopup="menu"
1247
+ aria-label=${translateKey(std, ...SELECTION_PANE_ROW_MENU)}
1248
+ @click=${(event) => {
1249
+ event.stopPropagation();
1250
+ this._openRowMenu(event.currentTarget, node);
1251
+ }}
1252
+ >
1253
+ ${MoreHorizontalIcon()}
1254
+ </button>`}
1255
+ </div>`;
1256
+ }
1257
+ updated() {
1258
+ const input = this.shadowRoot?.querySelector('[data-testid="selection-pane-rename"]');
1259
+ if (input && this.shadowRoot?.activeElement !== input) {
1260
+ input.focus();
1261
+ input.select();
1262
+ // A layer just created may sit above the scrolled-to rows: bring its
1263
+ // field into view, so the creation is seen where it happened.
1264
+ input.scrollIntoView({ block: 'nearest' });
1265
+ }
1266
+ }
1267
+ /**
1268
+ * One header action, in the frame panel's icon button
1269
+ * (`header/frame-panel-header.ts`): a 20px glyph in `edgeless-tool-icon-button`,
1270
+ * secondary until hovered, its tooltip above it, a wash while active.
1271
+ */
1272
+ _renderHeadButton(testId, label, icon, onClick, active = false) {
1273
+ return html `<edgeless-tool-icon-button
1274
+ class="affine-panel-header-button ${active ? 'active' : ''}"
1275
+ data-testid=${testId}
1276
+ aria-label=${label}
1277
+ .tooltip=${label}
1278
+ .tipPosition=${'top'}
1279
+ .active=${active}
1280
+ .activeMode=${'background'}
1281
+ @click=${onClick}
1282
+ >
1283
+ ${icon({ width: '20px', height: '20px' })}
1284
+ </edgeless-tool-icon-button>`;
1285
+ }
1286
+ render() {
1287
+ if (!this._open)
1288
+ return nothing;
1289
+ // Read for its dependency: the rows repaint when the canvas selection does.
1290
+ this._selectionRevision;
1291
+ const full = selectionPaneTree(this.std).value;
1292
+ let tree = full;
1293
+ let filterLabel = null;
1294
+ if (this._filter !== null) {
1295
+ const members = selectionPaneFilterMembers(this.std, this._filter);
1296
+ const target = selectionPaneFilterTargets(this.std).find(candidate => candidate.id === this._filter);
1297
+ if (members && target) {
1298
+ tree = filterSelectionPaneTree(tree, members);
1299
+ filterLabel = this._filterWording(target.id);
1300
+ }
1301
+ }
1302
+ const rows = this._rows(tree, full);
1303
+ this._visibleRows = rows;
1304
+ this._lists = paneLists(full);
1305
+ const title = translateKey(this.std, ...SELECTION_PANE_TITLE);
1306
+ const dragState = this._drag?.dragging
1307
+ ? this._drop && this._drop.kind !== 'refused'
1308
+ ? 'valid'
1309
+ : 'invalid'
1310
+ : undefined;
1311
+ // `pointermove` too: the editor turns every move over the host into a
1312
+ // cursor selection, and a selection with nothing recoverable in it makes
1313
+ // the range binding focus the host — which blurred a layer's rename field
1314
+ // the moment the pointer moved (a group's survived only because its click
1315
+ // had selected it). The pane's own drag listens on the document, in the
1316
+ // capture phase, so it still sees every move.
1317
+ return html `<div
1318
+ class="selection-pane-panel"
1319
+ role="dialog"
1320
+ tabindex="-1"
1321
+ aria-label=${title}
1322
+ data-testid="selection-pane-panel"
1323
+ data-drag=${dragState ?? nothing}
1324
+ @pointerdown=${this._swallow}
1325
+ @pointerup=${this._swallow}
1326
+ @pointermove=${this._swallow}
1327
+ @click=${this._swallow}
1328
+ @dblclick=${this._swallow}
1329
+ >
1330
+ <div
1331
+ class="selection-pane-head affine-panel-header"
1332
+ data-testid="selection-pane-header"
1333
+ >
1334
+ <span
1335
+ class="affine-panel-header-title"
1336
+ data-testid="selection-pane-title"
1337
+ >${title}</span
1338
+ >
1339
+ <div class="selection-pane-actions">
1340
+ ${this.std.store.readonly
1341
+ ? nothing
1342
+ : this._renderHeadButton('selection-pane-new-layer', translateKey(this.std, ...SELECTION_PANE_NEW_LAYER), PlusIcon, this._createLayer)}
1343
+ ${this._renderHeadButton('selection-pane-filter', translateKey(this.std, ...SELECTION_PANE_FILTER), FilterIcon, this._openFilterMenu, filterLabel !== null)}
1344
+ ${this._renderHeadButton('selection-pane-close', translateKey(this.std, ...SELECTION_PANE_CLOSE), CloseIcon, this.closePanel)}
1345
+ </div>
1346
+ </div>
1347
+ ${filterLabel !== null
1348
+ ? html `<div
1349
+ class="selection-pane-filter-label"
1350
+ data-testid="selection-pane-filter-label"
1351
+ >
1352
+ ${filterLabel}
1353
+ </div>`
1354
+ : nothing}
1355
+ <div
1356
+ class="selection-pane-body"
1357
+ role="tree"
1358
+ aria-label=${title}
1359
+ data-testid="selection-pane-body"
1360
+ @pointerleave=${() => this._clearHighlight()}
1361
+ >
1362
+ ${rows.length
1363
+ ? repeat(rows, row => row.node.id, row => this._renderRow(row))
1364
+ : html `<div class="selection-pane-empty">
1365
+ ${translateKey(this.std, ...SELECTION_PANE_EMPTY)}
1366
+ </div>`}
1367
+ ${this._renderDropIndicator()}
1368
+ </div>
1369
+ ${this._drag?.dragging
1370
+ ? html `<div
1371
+ class="selection-pane-drag-mask"
1372
+ data-testid="selection-pane-drag-mask"
1373
+ ></div>`
1374
+ : nothing}
1375
+ ${this._renderGhost()}
1376
+ </div>`;
1377
+ }
1378
+ };
1379
+ })();
1380
+ export { EdgelessSelectionPaneWidget };
1381
+ export const edgelessSelectionPaneWidget = WidgetViewExtension('affine:page', EDGELESS_SELECTION_PANE_WIDGET, literal `${unsafeStatic(EDGELESS_SELECTION_PANE_WIDGET)}`);