@formicoidea/labre-core 0.41.0 → 0.42.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 (252) hide show
  1. package/LICENSE +384 -0
  2. package/dist/_pkgs/affine-block-bookmark/bookmark-block.js +2 -2
  3. package/dist/_pkgs/affine-block-edgeless-text/edgeless-toolbar/config.js +7 -1
  4. package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.js +2 -1
  5. package/dist/_pkgs/affine-block-embed/embed-github-block/embed-github-block.js +2 -1
  6. package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.d.ts +2 -0
  7. package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.js +5 -0
  8. package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.d.ts +1 -0
  9. package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +30 -8
  10. package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.d.ts +8 -0
  11. package/dist/_pkgs/affine-block-embed/embed-iframe-block/utils.js +19 -0
  12. package/dist/_pkgs/affine-block-embed/embed-loom-block/embed-loom-block.js +2 -1
  13. package/dist/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.js +2 -1
  14. package/dist/_pkgs/affine-block-frame/frame-manager.js +1 -1
  15. package/dist/_pkgs/affine-block-frame/frame-tool.js +1 -1
  16. package/dist/_pkgs/affine-block-frame/frame-toolbar.js +6 -1
  17. package/dist/_pkgs/affine-block-list/list-keymap.js +7 -0
  18. package/dist/_pkgs/affine-block-note/note-keymap.js +7 -1
  19. package/dist/_pkgs/affine-block-paragraph/paragraph-keymap.js +7 -1
  20. package/dist/_pkgs/affine-block-root/commands/pivot-commands.js +1 -8
  21. package/dist/_pkgs/affine-block-root/commands/tag-commands.js +1 -8
  22. package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.d.ts +9 -0
  23. package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +51 -0
  24. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.d.ts +22 -0
  25. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +46 -0
  26. package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.d.ts +21 -0
  27. package/dist/_pkgs/affine-block-root/edgeless/utils/pinch-zoom.js +24 -0
  28. package/dist/_pkgs/affine-block-root/edgeless/utils/query.js +8 -0
  29. package/dist/_pkgs/affine-block-root/keyboard/keymap.js +1 -16
  30. package/dist/_pkgs/affine-block-surface/element-model/index.d.ts +21 -3
  31. package/dist/_pkgs/affine-block-surface/element-model/index.js +14 -2
  32. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +23 -0
  33. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +89 -0
  34. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +7 -0
  35. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +5 -0
  36. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +41 -0
  37. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +70 -0
  38. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +49 -0
  39. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +257 -0
  40. package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.d.ts +16 -0
  41. package/dist/_pkgs/affine-block-surface/extensions/export-svg/tagged-path.js +24 -0
  42. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.d.ts +24 -0
  43. package/dist/_pkgs/affine-block-surface/extensions/export-svg/toolbar.js +66 -0
  44. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +4 -0
  45. package/dist/_pkgs/affine-block-surface/extensions/index.js +4 -0
  46. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.d.ts +66 -4
  47. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +241 -11
  48. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +18 -0
  49. package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.d.ts +81 -0
  50. package/dist/_pkgs/affine-block-surface/extensions/legend-toolbar.js +81 -0
  51. package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +136 -0
  52. package/dist/_pkgs/affine-block-surface/extensions/legend.js +439 -0
  53. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.d.ts +17 -3
  54. package/dist/_pkgs/affine-block-surface/extensions/reading-widget.js +35 -13
  55. package/dist/_pkgs/affine-block-surface/extensions/reading.d.ts +61 -1
  56. package/dist/_pkgs/affine-block-surface/extensions/reading.js +85 -39
  57. package/dist/_pkgs/affine-block-surface/extensions/record-action.d.ts +66 -0
  58. package/dist/_pkgs/affine-block-surface/extensions/record-action.js +145 -0
  59. package/dist/_pkgs/affine-block-surface/extensions/validation.d.ts +253 -28
  60. package/dist/_pkgs/affine-block-surface/extensions/validation.js +489 -41
  61. package/dist/_pkgs/affine-block-surface/framework-background/background-view.d.ts +115 -0
  62. package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +185 -0
  63. package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +1 -0
  64. package/dist/_pkgs/affine-block-surface/framework-background/index.js +1 -0
  65. package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +16 -1
  66. package/dist/_pkgs/affine-block-surface/framework-background/labels.js +31 -21
  67. package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +29 -5
  68. package/dist/_pkgs/affine-block-surface/framework-background/stacking.d.ts +6 -4
  69. package/dist/_pkgs/affine-block-surface/framework-background/stacking.js +56 -8
  70. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.d.ts +12 -0
  71. package/dist/_pkgs/affine-block-surface/renderer/canvas-renderer.js +15 -0
  72. package/dist/_pkgs/affine-block-surface/view.js +8 -1
  73. package/dist/_pkgs/affine-block-surface-ref/configs/slash-menu.js +1 -1
  74. package/dist/_pkgs/affine-components/color-picker/button.d.ts +56 -1
  75. package/dist/_pkgs/affine-components/color-picker/button.js +168 -23
  76. package/dist/_pkgs/affine-components/color-picker/framework-palette.d.ts +106 -0
  77. package/dist/_pkgs/affine-components/color-picker/framework-palette.js +177 -0
  78. package/dist/_pkgs/affine-components/color-picker/index.d.ts +2 -0
  79. package/dist/_pkgs/affine-components/color-picker/index.js +2 -0
  80. package/dist/_pkgs/affine-components/color-picker/palette-carousel.d.ts +85 -0
  81. package/dist/_pkgs/affine-components/color-picker/palette-carousel.js +440 -0
  82. package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.d.ts +31 -1
  83. package/dist/_pkgs/affine-components/edgeless-shape-color-picker/color-picker.js +189 -63
  84. package/dist/_pkgs/affine-components/resource/resource.js +29 -16
  85. package/dist/_pkgs/affine-components/translations.d.ts +8 -0
  86. package/dist/_pkgs/affine-components/translations.js +17 -0
  87. package/dist/_pkgs/affine-foundation/view.js +2 -1
  88. package/dist/_pkgs/affine-gfx-brush/element-renderer.js +2 -2
  89. package/dist/_pkgs/affine-gfx-brush/toolbar/configs/brush.js +6 -1
  90. package/dist/_pkgs/affine-gfx-brush/toolbar/configs/highlighter.js +6 -1
  91. package/dist/_pkgs/affine-gfx-connector/connector-manager.d.ts +9 -1
  92. package/dist/_pkgs/affine-gfx-connector/connector-manager.js +61 -0
  93. package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.d.ts +7 -1
  94. package/dist/_pkgs/affine-gfx-connector/element-renderer/connector-dom/index.js +87 -17
  95. package/dist/_pkgs/affine-gfx-connector/element-renderer/index.js +78 -17
  96. package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.d.ts +24 -2
  97. package/dist/_pkgs/affine-gfx-connector/element-renderer/utils.js +31 -8
  98. package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.d.ts +124 -3
  99. package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +216 -54
  100. package/dist/_pkgs/affine-gfx-connector/text/text.d.ts +13 -4
  101. package/dist/_pkgs/affine-gfx-connector/text/text.js +13 -44
  102. package/dist/_pkgs/affine-gfx-connector/toolbar/config.d.ts +56 -0
  103. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +72 -4
  104. package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.d.ts +8 -0
  105. package/dist/_pkgs/affine-gfx-connector/toolbar/hollow-endpoint-icons.js +118 -0
  106. package/dist/_pkgs/affine-gfx-connector/view/view.d.ts +37 -1
  107. package/dist/_pkgs/affine-gfx-connector/view/view.js +97 -8
  108. package/dist/_pkgs/affine-gfx-group/command/group-api.js +1 -1
  109. package/dist/_pkgs/affine-gfx-group/store.js +0 -2
  110. package/dist/_pkgs/affine-gfx-group/translations.d.ts +9 -10
  111. package/dist/_pkgs/affine-gfx-group/translations.js +9 -13
  112. package/dist/_pkgs/affine-gfx-mindmap/templates/index.js +1 -1
  113. package/dist/_pkgs/affine-gfx-mindmap/toolbar/basket-elements.js +1 -1
  114. package/dist/_pkgs/affine-gfx-mindmap/toolbar/utils/import-mindmap.js +2 -2
  115. package/dist/_pkgs/affine-gfx-mindmap/translations.d.ts +1 -1
  116. package/dist/_pkgs/affine-gfx-mindmap/translations.js +1 -1
  117. package/dist/_pkgs/affine-gfx-shape/element-renderer/highlighter.js +2 -2
  118. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.d.ts +6 -0
  119. package/dist/_pkgs/affine-gfx-shape/overlay/polygon-drawing-overlay.js +30 -1
  120. package/dist/_pkgs/affine-gfx-shape/polygon-tool.d.ts +20 -1
  121. package/dist/_pkgs/affine-gfx-shape/polygon-tool.js +9 -1
  122. package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +6 -1
  123. package/dist/_pkgs/affine-gfx-shape/toolbar/palette-color-action.js +11 -1
  124. package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
  125. package/dist/_pkgs/affine-gfx-template/snapshot-from-action.js +32 -119
  126. package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +1 -1
  127. package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.d.ts +13 -1
  128. package/dist/_pkgs/affine-gfx-text/dblclick-add-edgeless-text.js +19 -4
  129. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.d.ts +41 -0
  130. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +57 -2
  131. package/dist/_pkgs/affine-gfx-text/toolbar/actions.d.ts +8 -1
  132. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +12 -2
  133. package/dist/_pkgs/affine-gfx-text/translations.d.ts +1 -0
  134. package/dist/_pkgs/affine-gfx-text/translations.js +2 -1
  135. package/dist/_pkgs/affine-inline-preset/markdown.js +5 -1
  136. package/dist/_pkgs/affine-model/consts/connector.d.ts +28 -2
  137. package/dist/_pkgs/affine-model/consts/connector.js +26 -0
  138. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +1 -1
  139. package/dist/_pkgs/affine-model/elements/brush/brush.js +1 -1
  140. package/dist/_pkgs/affine-model/elements/c4/board.js +1 -1
  141. package/dist/_pkgs/affine-model/elements/c4/boundary.js +1 -1
  142. package/dist/_pkgs/affine-model/elements/connector/connector.d.ts +135 -0
  143. package/dist/_pkgs/affine-model/elements/connector/connector.js +246 -5
  144. package/dist/_pkgs/affine-model/elements/connector/end-label.d.ts +83 -0
  145. package/dist/_pkgs/affine-model/elements/connector/end-label.js +119 -0
  146. package/dist/_pkgs/affine-model/elements/connector/index.d.ts +1 -0
  147. package/dist/_pkgs/affine-model/elements/connector/index.js +1 -0
  148. package/dist/_pkgs/affine-model/elements/context-map/context-map.js +1 -1
  149. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.d.ts +28 -0
  150. package/dist/_pkgs/affine-model/elements/core-domain/core-domain.js +129 -2
  151. package/dist/_pkgs/affine-model/elements/cynefin/cynefin.d.ts +8 -0
  152. package/dist/_pkgs/affine-model/elements/cynefin/cynefin.js +45 -2
  153. package/dist/_pkgs/affine-model/elements/edgy/board.js +1 -1
  154. package/dist/_pkgs/affine-model/elements/edgy/facets.js +1 -1
  155. package/dist/_pkgs/affine-model/elements/estuarine/estuarine.d.ts +6 -0
  156. package/dist/_pkgs/affine-model/elements/estuarine/estuarine.js +36 -2
  157. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.d.ts +18 -7
  158. package/dist/_pkgs/affine-model/elements/event-storming/event-storming.js +23 -8
  159. package/dist/_pkgs/affine-model/elements/framework-background/background.d.ts +16 -0
  160. package/dist/_pkgs/affine-model/elements/framework-background/background.js +18 -0
  161. package/dist/_pkgs/affine-model/elements/highlighter/highlighter.js +1 -1
  162. package/dist/_pkgs/affine-model/elements/index.d.ts +8 -0
  163. package/dist/_pkgs/affine-model/elements/index.js +1 -0
  164. package/dist/_pkgs/affine-model/elements/shape/shape.js +1 -1
  165. package/dist/_pkgs/affine-model/elements/text/text.js +1 -1
  166. package/dist/_pkgs/affine-model/elements/uml/band.d.ts +39 -0
  167. package/dist/_pkgs/affine-model/elements/uml/band.js +31 -0
  168. package/dist/_pkgs/affine-model/elements/uml/diagram.d.ts +158 -0
  169. package/dist/_pkgs/affine-model/elements/uml/diagram.js +229 -0
  170. package/dist/_pkgs/affine-model/elements/uml/fragment.d.ts +161 -0
  171. package/dist/_pkgs/affine-model/elements/uml/fragment.js +205 -0
  172. package/dist/_pkgs/affine-model/elements/uml/index.d.ts +8 -0
  173. package/dist/_pkgs/affine-model/elements/uml/index.js +8 -0
  174. package/dist/_pkgs/affine-model/elements/uml/lifeline.d.ts +77 -0
  175. package/dist/_pkgs/affine-model/elements/uml/lifeline.js +89 -0
  176. package/dist/_pkgs/affine-model/elements/uml/node.d.ts +142 -0
  177. package/dist/_pkgs/affine-model/elements/uml/node.js +190 -0
  178. package/dist/_pkgs/affine-model/elements/uml/partition.d.ts +106 -0
  179. package/dist/_pkgs/affine-model/elements/uml/partition.js +172 -0
  180. package/dist/_pkgs/affine-model/elements/uml/region.d.ts +75 -0
  181. package/dist/_pkgs/affine-model/elements/uml/region.js +150 -0
  182. package/dist/_pkgs/affine-model/elements/uml/subject.d.ts +37 -0
  183. package/dist/_pkgs/affine-model/elements/uml/subject.js +108 -0
  184. package/dist/_pkgs/affine-model/elements/wardley/wardley.js +1 -1
  185. package/dist/_pkgs/affine-shared/services/embed-iframe/embed-iframe-config.d.ts +1 -0
  186. package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +7 -0
  187. package/dist/_pkgs/affine-shared/services/font-loader/config.js +43 -0
  188. package/dist/_pkgs/affine-shared/services/pivot-materiality-publisher.js +1 -9
  189. package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.d.ts +53 -0
  190. package/dist/_pkgs/affine-shared/services/telemetry-service/document-damage-watcher.js +95 -0
  191. package/dist/_pkgs/affine-shared/services/telemetry-service/index.d.ts +1 -0
  192. package/dist/_pkgs/affine-shared/services/telemetry-service/index.js +1 -0
  193. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -1
  194. package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +2 -2
  195. package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.d.ts +34 -0
  196. package/dist/_pkgs/affine-shared/services/toolbar-service/command-action.js +63 -0
  197. package/dist/_pkgs/affine-shared/services/toolbar-service/index.d.ts +1 -0
  198. package/dist/_pkgs/affine-shared/services/toolbar-service/index.js +1 -0
  199. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +77 -7
  200. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +97 -7
  201. package/dist/_pkgs/affine-shared/styles/index.d.ts +1 -0
  202. package/dist/_pkgs/affine-shared/styles/index.js +1 -0
  203. package/dist/_pkgs/affine-shared/styles/motion.d.ts +14 -0
  204. package/dist/_pkgs/affine-shared/styles/motion.js +38 -0
  205. package/dist/_pkgs/affine-shared/utils/event.d.ts +10 -0
  206. package/dist/_pkgs/affine-shared/utils/event.js +20 -0
  207. package/dist/_pkgs/affine-shared/utils/file/filesys.d.ts +16 -0
  208. package/dist/_pkgs/affine-shared/utils/file/filesys.js +25 -0
  209. package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
  210. package/dist/_pkgs/affine-shared/utils/index.js +1 -0
  211. package/dist/_pkgs/affine-shared/utils/link-preview-refresh.d.ts +12 -0
  212. package/dist/_pkgs/affine-shared/utils/link-preview-refresh.js +13 -0
  213. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.d.ts +12 -4
  214. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/artefact-catalogue-widget.js +27 -4
  215. package/dist/_pkgs/affine-widget-edgeless-toolbar/create-popper.js +13 -0
  216. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.d.ts +2 -0
  217. package/dist/_pkgs/affine-widget-edgeless-toolbar/index.js +2 -0
  218. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.d.ts +80 -0
  219. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/command-menu.js +270 -81
  220. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.d.ts +15 -0
  221. package/dist/_pkgs/affine-widget-edgeless-toolbar/menu/senior-menu-selection.js +15 -0
  222. package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-weight-and-style-panel.js +8 -1
  223. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.d.ts +42 -0
  224. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-ghost-overlay.js +100 -0
  225. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.d.ts +100 -0
  226. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/artefact-placement-tool.js +274 -0
  227. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.d.ts +3 -0
  228. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/index.js +3 -0
  229. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.d.ts +25 -0
  230. package/dist/_pkgs/affine-widget-edgeless-toolbar/placement/translate-created.js +67 -0
  231. package/dist/_pkgs/affine-widget-edgeless-toolbar/view.js +5 -0
  232. package/dist/_pkgs/global/gfx/xywh.js +7 -0
  233. package/dist/_pkgs/std/extension/command-registry.d.ts +158 -1
  234. package/dist/_pkgs/std/extension/command-registry.js +22 -0
  235. package/dist/_pkgs/std/gfx/index.d.ts +1 -1
  236. package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.d.ts +12 -0
  237. package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.js +20 -1
  238. package/dist/_pkgs/std/gfx/interactivity/manager.d.ts +10 -0
  239. package/dist/_pkgs/std/gfx/interactivity/manager.js +12 -0
  240. package/dist/_pkgs/std/gfx/model/surface/element-model.js +12 -7
  241. package/dist/_pkgs/std/gfx/model/surface/surface-model.d.ts +56 -0
  242. package/dist/_pkgs/std/gfx/model/surface/surface-model.js +84 -3
  243. package/dist/_pkgs/std/gfx/view/view.d.ts +11 -2
  244. package/dist/_pkgs/std/gfx/view/view.js +16 -2
  245. package/dist/commands.d.ts +6 -0
  246. package/dist/commands.js +8 -1
  247. package/dist/frameworks.d.ts +9 -0
  248. package/dist/frameworks.js +19 -0
  249. package/dist/translations.js +16 -0
  250. package/package.json +9 -4
  251. package/dist/_pkgs/affine-gfx-group/group-watcher.d.ts +0 -1
  252. package/dist/_pkgs/affine-gfx-group/group-watcher.js +0 -20
@@ -37,6 +37,7 @@ import { derive, field, GfxPrimitiveElementModel, local } from '../../../std/gfx
37
37
  import * as Y from 'yjs';
38
38
  import { CONNECTOR_LABEL_MAX_WIDTH, ConnectorLabelOffsetAnchor, ConnectorMode, DEFAULT_CONNECTOR_MODE, DEFAULT_ROUGHNESS, FontFamily, FontStyle, FontWeight, StrokeStyle, TextAlign, } from '../../consts/index.js';
39
39
  import { DefaultTheme } from '../../themes/index.js';
40
+ import { connectorEndNear } from './end-label.js';
40
41
  export const getConnectorModeName = (mode) => {
41
42
  return {
42
43
  [ConnectorMode.Straight]: 'Straight',
@@ -73,6 +74,9 @@ let ConnectorElementModel = (() => {
73
74
  let _labelEditing_decorators;
74
75
  let _labelEditing_initializers = [];
75
76
  let _labelEditing_extraInitializers = [];
77
+ let _endLabelEditing_decorators;
78
+ let _endLabelEditing_initializers = [];
79
+ let _endLabelEditing_extraInitializers = [];
76
80
  let _mode_decorators;
77
81
  let _mode_initializers = [];
78
82
  let _mode_extraInitializers = [];
@@ -94,6 +98,12 @@ let ConnectorElementModel = (() => {
94
98
  let _source_decorators;
95
99
  let _source_initializers = [];
96
100
  let _source_extraInitializers = [];
101
+ let _sourceLabel_decorators;
102
+ let _sourceLabel_initializers = [];
103
+ let _sourceLabel_extraInitializers = [];
104
+ let _sourceLabelXYWH_decorators;
105
+ let _sourceLabelXYWH_initializers = [];
106
+ let _sourceLabelXYWH_extraInitializers = [];
97
107
  let _stroke_decorators;
98
108
  let _stroke_initializers = [];
99
109
  let _stroke_extraInitializers = [];
@@ -106,6 +116,12 @@ let ConnectorElementModel = (() => {
106
116
  let _target_decorators;
107
117
  let _target_initializers = [];
108
118
  let _target_extraInitializers = [];
119
+ let _targetLabel_decorators;
120
+ let _targetLabel_initializers = [];
121
+ let _targetLabel_extraInitializers = [];
122
+ let _targetLabelXYWH_decorators;
123
+ let _targetLabelXYWH_initializers = [];
124
+ let _targetLabelXYWH_extraInitializers = [];
109
125
  let _text_decorators;
110
126
  let _text_initializers = [];
111
127
  let _text_extraInitializers = [];
@@ -137,6 +153,7 @@ let ConnectorElementModel = (() => {
137
153
  })];
138
154
  _labelXYWH_decorators = [field()];
139
155
  _labelEditing_decorators = [local()];
156
+ _endLabelEditing_decorators = [local()];
140
157
  _mode_decorators = [field()];
141
158
  _path_decorators = [derive((path, instance) => {
142
159
  const { x, y } = instance;
@@ -149,10 +166,14 @@ let ConnectorElementModel = (() => {
149
166
  _rough_decorators = [field()];
150
167
  _roughness_decorators = [field()];
151
168
  _source_decorators = [field()];
169
+ _sourceLabel_decorators = [field()];
170
+ _sourceLabelXYWH_decorators = [field()];
152
171
  _stroke_decorators = [field()];
153
172
  _strokeStyle_decorators = [field()];
154
173
  _strokeWidth_decorators = [field()];
155
174
  _target_decorators = [field()];
175
+ _targetLabel_decorators = [field()];
176
+ _targetLabelXYWH_decorators = [field()];
156
177
  _text_decorators = [field()];
157
178
  _xywh_decorators = [local()];
158
179
  __esDecorate(this, null, _absolutePath_decorators, { kind: "accessor", name: "absolutePath", static: false, private: false, access: { has: obj => "absolutePath" in obj, get: obj => obj.absolutePath, set: (obj, value) => { obj.absolutePath = value; } }, metadata: _metadata }, _absolutePath_initializers, _absolutePath_extraInitializers);
@@ -164,6 +185,7 @@ let ConnectorElementModel = (() => {
164
185
  __esDecorate(this, null, _labelStyle_decorators, { kind: "accessor", name: "labelStyle", static: false, private: false, access: { has: obj => "labelStyle" in obj, get: obj => obj.labelStyle, set: (obj, value) => { obj.labelStyle = value; } }, metadata: _metadata }, _labelStyle_initializers, _labelStyle_extraInitializers);
165
186
  __esDecorate(this, null, _labelXYWH_decorators, { kind: "accessor", name: "labelXYWH", static: false, private: false, access: { has: obj => "labelXYWH" in obj, get: obj => obj.labelXYWH, set: (obj, value) => { obj.labelXYWH = value; } }, metadata: _metadata }, _labelXYWH_initializers, _labelXYWH_extraInitializers);
166
187
  __esDecorate(this, null, _labelEditing_decorators, { kind: "accessor", name: "labelEditing", static: false, private: false, access: { has: obj => "labelEditing" in obj, get: obj => obj.labelEditing, set: (obj, value) => { obj.labelEditing = value; } }, metadata: _metadata }, _labelEditing_initializers, _labelEditing_extraInitializers);
188
+ __esDecorate(this, null, _endLabelEditing_decorators, { kind: "accessor", name: "endLabelEditing", static: false, private: false, access: { has: obj => "endLabelEditing" in obj, get: obj => obj.endLabelEditing, set: (obj, value) => { obj.endLabelEditing = value; } }, metadata: _metadata }, _endLabelEditing_initializers, _endLabelEditing_extraInitializers);
167
189
  __esDecorate(this, null, _mode_decorators, { kind: "accessor", name: "mode", static: false, private: false, access: { has: obj => "mode" in obj, get: obj => obj.mode, set: (obj, value) => { obj.mode = value; } }, metadata: _metadata }, _mode_initializers, _mode_extraInitializers);
168
190
  __esDecorate(this, null, _path_decorators, { kind: "accessor", name: "path", static: false, private: false, access: { has: obj => "path" in obj, get: obj => obj.path, set: (obj, value) => { obj.path = value; } }, metadata: _metadata }, _path_initializers, _path_extraInitializers);
169
191
  __esDecorate(this, null, _rearEndpointStyle_decorators, { kind: "accessor", name: "rearEndpointStyle", static: false, private: false, access: { has: obj => "rearEndpointStyle" in obj, get: obj => obj.rearEndpointStyle, set: (obj, value) => { obj.rearEndpointStyle = value; } }, metadata: _metadata }, _rearEndpointStyle_initializers, _rearEndpointStyle_extraInitializers);
@@ -171,10 +193,14 @@ let ConnectorElementModel = (() => {
171
193
  __esDecorate(this, null, _rough_decorators, { kind: "accessor", name: "rough", static: false, private: false, access: { has: obj => "rough" in obj, get: obj => obj.rough, set: (obj, value) => { obj.rough = value; } }, metadata: _metadata }, _rough_initializers, _rough_extraInitializers);
172
194
  __esDecorate(this, null, _roughness_decorators, { kind: "accessor", name: "roughness", static: false, private: false, access: { has: obj => "roughness" in obj, get: obj => obj.roughness, set: (obj, value) => { obj.roughness = value; } }, metadata: _metadata }, _roughness_initializers, _roughness_extraInitializers);
173
195
  __esDecorate(this, null, _source_decorators, { kind: "accessor", name: "source", static: false, private: false, access: { has: obj => "source" in obj, get: obj => obj.source, set: (obj, value) => { obj.source = value; } }, metadata: _metadata }, _source_initializers, _source_extraInitializers);
196
+ __esDecorate(this, null, _sourceLabel_decorators, { kind: "accessor", name: "sourceLabel", static: false, private: false, access: { has: obj => "sourceLabel" in obj, get: obj => obj.sourceLabel, set: (obj, value) => { obj.sourceLabel = value; } }, metadata: _metadata }, _sourceLabel_initializers, _sourceLabel_extraInitializers);
197
+ __esDecorate(this, null, _sourceLabelXYWH_decorators, { kind: "accessor", name: "sourceLabelXYWH", static: false, private: false, access: { has: obj => "sourceLabelXYWH" in obj, get: obj => obj.sourceLabelXYWH, set: (obj, value) => { obj.sourceLabelXYWH = value; } }, metadata: _metadata }, _sourceLabelXYWH_initializers, _sourceLabelXYWH_extraInitializers);
174
198
  __esDecorate(this, null, _stroke_decorators, { kind: "accessor", name: "stroke", static: false, private: false, access: { has: obj => "stroke" in obj, get: obj => obj.stroke, set: (obj, value) => { obj.stroke = value; } }, metadata: _metadata }, _stroke_initializers, _stroke_extraInitializers);
175
199
  __esDecorate(this, null, _strokeStyle_decorators, { kind: "accessor", name: "strokeStyle", static: false, private: false, access: { has: obj => "strokeStyle" in obj, get: obj => obj.strokeStyle, set: (obj, value) => { obj.strokeStyle = value; } }, metadata: _metadata }, _strokeStyle_initializers, _strokeStyle_extraInitializers);
176
200
  __esDecorate(this, null, _strokeWidth_decorators, { kind: "accessor", name: "strokeWidth", static: false, private: false, access: { has: obj => "strokeWidth" in obj, get: obj => obj.strokeWidth, set: (obj, value) => { obj.strokeWidth = value; } }, metadata: _metadata }, _strokeWidth_initializers, _strokeWidth_extraInitializers);
177
201
  __esDecorate(this, null, _target_decorators, { kind: "accessor", name: "target", static: false, private: false, access: { has: obj => "target" in obj, get: obj => obj.target, set: (obj, value) => { obj.target = value; } }, metadata: _metadata }, _target_initializers, _target_extraInitializers);
202
+ __esDecorate(this, null, _targetLabel_decorators, { kind: "accessor", name: "targetLabel", static: false, private: false, access: { has: obj => "targetLabel" in obj, get: obj => obj.targetLabel, set: (obj, value) => { obj.targetLabel = value; } }, metadata: _metadata }, _targetLabel_initializers, _targetLabel_extraInitializers);
203
+ __esDecorate(this, null, _targetLabelXYWH_decorators, { kind: "accessor", name: "targetLabelXYWH", static: false, private: false, access: { has: obj => "targetLabelXYWH" in obj, get: obj => obj.targetLabelXYWH, set: (obj, value) => { obj.targetLabelXYWH = value; } }, metadata: _metadata }, _targetLabelXYWH_initializers, _targetLabelXYWH_extraInitializers);
178
204
  __esDecorate(this, null, _text_decorators, { kind: "accessor", name: "text", static: false, private: false, access: { has: obj => "text" in obj, get: obj => obj.text, set: (obj, value) => { obj.text = value; } }, metadata: _metadata }, _text_initializers, _text_extraInitializers);
179
205
  __esDecorate(this, null, _xywh_decorators, { kind: "accessor", name: "xywh", static: false, private: false, access: { has: obj => "xywh" in obj, get: obj => obj.xywh, set: (obj, value) => { obj.xywh = value; } }, metadata: _metadata }, _xywh_initializers, _xywh_extraInitializers);
180
206
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -190,6 +216,9 @@ let ConnectorElementModel = (() => {
190
216
  if (this.hasLabel()) {
191
217
  bounds = bounds.unite(Bound.fromXYWH(this.labelXYWH));
192
218
  }
219
+ for (const box of this.endLabelBoxes()) {
220
+ bounds = bounds.unite(Bound.fromXYWH(box));
221
+ }
193
222
  return bounds;
194
223
  }
195
224
  get type() {
@@ -199,12 +228,21 @@ let ConnectorElementModel = (() => {
199
228
  if (typeof props.text === 'string') {
200
229
  props.text = new Y.Text(props.text);
201
230
  }
231
+ // The two end labels take the same courtesy the centre one does: a caller
232
+ // may hand a plain string and get a `Y.Text` on the element.
233
+ if (typeof props.sourceLabel === 'string') {
234
+ props.sourceLabel = new Y.Text(props.sourceLabel);
235
+ }
236
+ if (typeof props.targetLabel === 'string') {
237
+ props.targetLabel = new Y.Text(props.targetLabel);
238
+ }
202
239
  return props;
203
240
  }
204
241
  containsBound(bounds) {
205
242
  return (this.absolutePath.some(point => bounds.containsPoint(point)) ||
206
243
  (this.hasLabel() &&
207
- Bound.fromXYWH(this.labelXYWH).points.some(p => bounds.containsPoint(p))));
244
+ Bound.fromXYWH(this.labelXYWH).points.some(p => bounds.containsPoint(p))) ||
245
+ this.endLabelBoxes().some(box => Bound.fromXYWH(box).points.some(p => bounds.containsPoint(p))));
208
246
  }
209
247
  getLineIntersections(start, end) {
210
248
  const { mode, absolutePath: path } = this;
@@ -218,6 +256,13 @@ let ConnectorElementModel = (() => {
218
256
  if (!intersected && this.hasLabel()) {
219
257
  intersected = linePolylineIntersects(start, end, Bound.fromXYWH(this.labelXYWH).points);
220
258
  }
259
+ if (!intersected) {
260
+ for (const box of this.endLabelBoxes()) {
261
+ intersected = linePolylineIntersects(start, end, Bound.fromXYWH(box).points);
262
+ if (intersected)
263
+ break;
264
+ }
265
+ }
221
266
  return intersected;
222
267
  }
223
268
  /**
@@ -336,9 +381,120 @@ let ConnectorElementModel = (() => {
336
381
  this.text &&
337
382
  this.text.length);
338
383
  }
384
+ /** The content of one end's label, or `undefined` when it has none. */
385
+ endLabelText(end) {
386
+ return end === 'source' ? this.sourceLabel : this.targetLabel;
387
+ }
388
+ /** The box of one end's label, or `undefined` when nothing placed it yet. */
389
+ endLabelXYWH(end) {
390
+ return end === 'source' ? this.sourceLabelXYWH : this.targetLabelXYWH;
391
+ }
392
+ /**
393
+ * Whether one end carries a label that should be PAINTED — the end-label
394
+ * twin of `hasLabel()`, gated on the same `labelDisplay` (one switch hides
395
+ * every caption on a connector, which is what the toolbar's toggle means)
396
+ * and on `endLabelEditing` instead of `labelEditing`, so mounting the editor
397
+ * on one end does not blank the other two labels.
398
+ */
399
+ hasEndLabel(end) {
400
+ const text = this.endLabelText(end);
401
+ return Boolean(this.endLabelEditing !== end &&
402
+ this.labelDisplay &&
403
+ this.endLabelXYWH(end) &&
404
+ text &&
405
+ text.length);
406
+ }
407
+ hasSourceLabel() {
408
+ return this.hasEndLabel('source');
409
+ }
410
+ hasTargetLabel() {
411
+ return this.hasEndLabel('target');
412
+ }
413
+ /** The boxes of the end labels that are currently painted, in end order. */
414
+ endLabelBoxes() {
415
+ const boxes = [];
416
+ if (this.hasSourceLabel())
417
+ boxes.push(this.sourceLabelXYWH);
418
+ if (this.hasTargetLabel())
419
+ boxes.push(this.targetLabelXYWH);
420
+ return boxes;
421
+ }
422
+ endLabelIncludesPoint(end, point) {
423
+ return (this.hasEndLabel(end) &&
424
+ Bound.fromXYWH(this.endLabelXYWH(end)).isPointInBound(point));
425
+ }
426
+ sourceLabelIncludesPoint(point) {
427
+ return this.endLabelIncludesPoint('source', point);
428
+ }
429
+ targetLabelIncludesPoint(point) {
430
+ return this.endLabelIncludesPoint('target', point);
431
+ }
432
+ /**
433
+ * Whether a point is reaching for one of the ENDS — the arrowhead, and the
434
+ * label that belongs beside it whether or not it exists yet.
435
+ *
436
+ * ## Why a hairline has to claim more than itself
437
+ *
438
+ * A connector is a stroke a few units wide, so its hit test is the line and
439
+ * nothing else — and an end label is the one thing on a connector that a user
440
+ * aims at BEFORE it exists (`docs/adr/0018`: they aim at the arrowhead). The
441
+ * picker that turns a double-click into "the source label" was written
442
+ * generously for exactly that, and it never got the chance: past `8` units off
443
+ * the stroke (plus half its width when the caller asks for a threshold —
444
+ * {@link includesPoint}'s own tolerance) nothing answered here, so the event
445
+ * reached no view at all and the editor's double-click-on-empty-canvas handler
446
+ * dropped a text block at the arrowhead instead. A text box appears, it is not
447
+ * the label, and the contextual menu's own entry works — which is precisely
448
+ * what the PO reported on 14/09/2026.
449
+ *
450
+ * ## …and why only a connector a FRAMEWORK typed claims it
451
+ *
452
+ * A `CONNECTOR_END_LABEL_GRAB` disc around each endpoint is a large
453
+ * thing to take out of the canvas, and the only gesture that needs it is the
454
+ * one that opens an END label — which is a notation's caption, never a plain
455
+ * arrow's. A connector carrying a `role` is exactly a connector some framework
456
+ * wrote (`uml:association`, `bpmn:sequenceFlow`); a generalist one keeps the
457
+ * hairline it has always had, so a double-click beside a whiteboard arrow
458
+ * still means "add text here" and a click there still reaches whatever is
459
+ * under it.
460
+ *
461
+ * ## …and why it gives the bound element right of way
462
+ *
463
+ * An endpoint sits ON the border of the node it is attached to, so half of
464
+ * every grab disc is INSIDE that node — and a node's body is the target of its
465
+ * own gestures (a UML classifier opens its name compartment there). Claiming
466
+ * that half would take the gesture away from the artefact and give it to the
467
+ * line touching it. So the disc stops at the bound element's own box, and what
468
+ * is left is the half the notation writes a multiplicity in: outside the box,
469
+ * beside the arrowhead.
470
+ *
471
+ * Resolved through the surface rather than remembered, and BOTH ways: a
472
+ * canvas element by id, and a BLOCK — a note, an image, an embed, a frame —
473
+ * through the store, because those are ends a framework binds too and the
474
+ * element resolver alone answers `undefined` for every one of them. It did,
475
+ * and the whole disc was then claimed inside the note. `null` is for an end
476
+ * bound to NOTHING: an unattached end is a free arrowhead in open canvas, and
477
+ * the whole disc around it is the author's target.
478
+ */
479
+ endGrabIncludesPoint(point) {
480
+ if (this.role === undefined)
481
+ return false;
482
+ const end = connectorEndNear(this.absolutePath, point);
483
+ if (!end)
484
+ return false;
485
+ const id = this[end].id;
486
+ const boundTo = id
487
+ ? (this.surface?.getElementById(id) ??
488
+ this.surface?.store.getBlock(id)?.model)
489
+ : null;
490
+ return !boundTo?.elementBound?.isPointInBound(point);
491
+ }
339
492
  includesPoint(x, y, options) {
340
493
  const currentPoint = [x, y];
341
- if (this.labelIncludesPoint(currentPoint)) {
494
+ if (this.labelIncludesPoint(currentPoint) ||
495
+ this.sourceLabelIncludesPoint(currentPoint) ||
496
+ this.targetLabelIncludesPoint(currentPoint) ||
497
+ this.endGrabIncludesPoint(currentPoint)) {
342
498
  return true;
343
499
  }
344
500
  const { mode, strokeWidth, absolutePath: path } = this;
@@ -382,6 +538,19 @@ let ConnectorElementModel = (() => {
382
538
  const [x, y, w, h] = this.labelXYWH;
383
539
  this.labelXYWH = [x + offset[0], y + offset[1], w, h];
384
540
  }
541
+ // The end labels ride along. Dragging the whole connector moves BOTH of
542
+ // its endpoints by the same offset, so "an end label follows its endpoint"
543
+ // and "translate by the connector's offset" are the same movement here;
544
+ // they part company only when a single endpoint moves, which is the path
545
+ // generator's business, not this one's.
546
+ if (this.hasSourceLabel()) {
547
+ const [x, y, w, h] = this.sourceLabelXYWH;
548
+ this.sourceLabelXYWH = [x + offset[0], y + offset[1], w, h];
549
+ }
550
+ if (this.hasTargetLabel()) {
551
+ const [x, y, w, h] = this.targetLabelXYWH;
552
+ this.targetLabelXYWH = [x + offset[0], y + offset[1], w, h];
553
+ }
385
554
  }
386
555
  resize(originalPath, matrix) {
387
556
  this.updatingPath = false;
@@ -489,6 +658,18 @@ let ConnectorElementModel = (() => {
489
658
  */
490
659
  get labelEditing() { return this.#labelEditing_accessor_storage; }
491
660
  set labelEditing(value) { this.#labelEditing_accessor_storage = value; }
661
+ #endLabelEditing_accessor_storage;
662
+ /**
663
+ * The end whose label is currently open in the DOM editor, if any — the
664
+ * end-label twin of `labelEditing`, and `@local()` for the same reason: it
665
+ * is a property of this client's editing session, not of the document.
666
+ *
667
+ * One selector rather than two booleans because only one label can be edited
668
+ * at a time, and because it is the same `'source' | 'target'` the editor's
669
+ * `which` argument carries.
670
+ */
671
+ get endLabelEditing() { return this.#endLabelEditing_accessor_storage; }
672
+ set endLabelEditing(value) { this.#endLabelEditing_accessor_storage = value; }
492
673
  #mode_accessor_storage;
493
674
  get mode() { return this.#mode_accessor_storage; }
494
675
  set mode(value) { this.#mode_accessor_storage = value; }
@@ -510,6 +691,46 @@ let ConnectorElementModel = (() => {
510
691
  #source_accessor_storage;
511
692
  get source() { return this.#source_accessor_storage; }
512
693
  set source(value) { this.#source_accessor_storage = value; }
694
+ #sourceLabel_accessor_storage;
695
+ /**
696
+ * The content of the label beside the SOURCE end — a multiplicity, a role
697
+ * name, a qualifier. `undefined` on every connector that has none, which is
698
+ * almost all of them.
699
+ *
700
+ * ### Why four flat fields and not two records
701
+ *
702
+ * A `Y.Text` nested inside a `Y.Map` inside the element's map would not be
703
+ * observed. The bridge that republishes a text edit as an element update is
704
+ * `watchText` in `syncElementFromY`
705
+ * (`packages/framework/std/src/gfx/model/surface/element-model.ts`): it walks
706
+ * the element's OWN `Y.Map`, and subscribes to every top-level value that is
707
+ * `instanceof Y.Text` — the centre `text` gets its observation from there and
708
+ * from nowhere else, which is why `text` carries no `@observe` decorator.
709
+ *
710
+ * Keeping the two end texts as top-level keys therefore buys the exact same
711
+ * observation, for free, on the exact same code path: type into an end label
712
+ * and the connector repaints, on this client and on every peer. A nested
713
+ * record would have needed an `@observe` bridge of its own, a second way of
714
+ * doing the one thing the centre label already does. ADR 0020.
715
+ *
716
+ * ### Absent by default
717
+ *
718
+ * `undefined` means the key is never written into the Y.Map at all (see the
719
+ * `@field()` `init`), so a connector that has no end label serialises
720
+ * byte-identically to one created before these fields existed: no migration,
721
+ * and an older build opens the document as a connector with two keys it does
722
+ * not read.
723
+ */
724
+ get sourceLabel() { return this.#sourceLabel_accessor_storage; }
725
+ set sourceLabel(value) { this.#sourceLabel_accessor_storage = value; }
726
+ #sourceLabelXYWH_accessor_storage;
727
+ /**
728
+ * The box of the source-end label, in the same absolute coordinates as
729
+ * `labelXYWH`. Absent until something places it — the pure default is
730
+ * `connectorEndLabelBox(path, 'source', size)`.
731
+ */
732
+ get sourceLabelXYWH() { return this.#sourceLabelXYWH_accessor_storage; }
733
+ set sourceLabelXYWH(value) { this.#sourceLabelXYWH_accessor_storage = value; }
513
734
  #stroke_accessor_storage;
514
735
  get stroke() { return this.#stroke_accessor_storage; }
515
736
  set stroke(value) { this.#stroke_accessor_storage = value; }
@@ -522,6 +743,21 @@ let ConnectorElementModel = (() => {
522
743
  #target_accessor_storage;
523
744
  get target() { return this.#target_accessor_storage; }
524
745
  set target(value) { this.#target_accessor_storage = value; }
746
+ #targetLabel_accessor_storage;
747
+ /**
748
+ * The content of the label beside the TARGET end. See `sourceLabel` for why
749
+ * this is a flat `Y.Text` and what its absence guarantees.
750
+ */
751
+ get targetLabel() { return this.#targetLabel_accessor_storage; }
752
+ set targetLabel(value) { this.#targetLabel_accessor_storage = value; }
753
+ #targetLabelXYWH_accessor_storage;
754
+ /**
755
+ * The box of the target-end label, in the same absolute coordinates as
756
+ * `labelXYWH`. Absent until something places it — the pure default is
757
+ * `connectorEndLabelBox(path, 'target', size)`.
758
+ */
759
+ get targetLabelXYWH() { return this.#targetLabelXYWH_accessor_storage; }
760
+ set targetLabelXYWH(value) { this.#targetLabelXYWH_accessor_storage = value; }
525
761
  #text_accessor_storage;
526
762
  /**
527
763
  * The content of the label.
@@ -547,7 +783,8 @@ let ConnectorElementModel = (() => {
547
783
  this.#labelStyle_accessor_storage = (__runInitializers(this, _labelOffset_extraInitializers), __runInitializers(this, _labelStyle_initializers, void 0));
548
784
  this.#labelXYWH_accessor_storage = (__runInitializers(this, _labelStyle_extraInitializers), __runInitializers(this, _labelXYWH_initializers, undefined));
549
785
  this.#labelEditing_accessor_storage = (__runInitializers(this, _labelXYWH_extraInitializers), __runInitializers(this, _labelEditing_initializers, false));
550
- this.#mode_accessor_storage = (__runInitializers(this, _labelEditing_extraInitializers), __runInitializers(this, _mode_initializers, DEFAULT_CONNECTOR_MODE));
786
+ this.#endLabelEditing_accessor_storage = (__runInitializers(this, _labelEditing_extraInitializers), __runInitializers(this, _endLabelEditing_initializers, null));
787
+ this.#mode_accessor_storage = (__runInitializers(this, _endLabelEditing_extraInitializers), __runInitializers(this, _mode_initializers, DEFAULT_CONNECTOR_MODE));
551
788
  this.#path_accessor_storage = (__runInitializers(this, _mode_extraInitializers), __runInitializers(this, _path_initializers, []));
552
789
  this.#rearEndpointStyle_accessor_storage = (__runInitializers(this, _path_extraInitializers), __runInitializers(this, _rearEndpointStyle_initializers, void 0));
553
790
  this.#rotate_accessor_storage = (__runInitializers(this, _rearEndpointStyle_extraInitializers), __runInitializers(this, _rotate_initializers, 0));
@@ -556,13 +793,17 @@ let ConnectorElementModel = (() => {
556
793
  this.#source_accessor_storage = (__runInitializers(this, _roughness_extraInitializers), __runInitializers(this, _source_initializers, {
557
794
  position: [0, 0],
558
795
  }));
559
- this.#stroke_accessor_storage = (__runInitializers(this, _source_extraInitializers), __runInitializers(this, _stroke_initializers, DefaultTheme.connectorColor));
796
+ this.#sourceLabel_accessor_storage = (__runInitializers(this, _source_extraInitializers), __runInitializers(this, _sourceLabel_initializers, undefined));
797
+ this.#sourceLabelXYWH_accessor_storage = (__runInitializers(this, _sourceLabel_extraInitializers), __runInitializers(this, _sourceLabelXYWH_initializers, undefined));
798
+ this.#stroke_accessor_storage = (__runInitializers(this, _sourceLabelXYWH_extraInitializers), __runInitializers(this, _stroke_initializers, DefaultTheme.connectorColor));
560
799
  this.#strokeStyle_accessor_storage = (__runInitializers(this, _stroke_extraInitializers), __runInitializers(this, _strokeStyle_initializers, StrokeStyle.Solid));
561
800
  this.#strokeWidth_accessor_storage = (__runInitializers(this, _strokeStyle_extraInitializers), __runInitializers(this, _strokeWidth_initializers, 4));
562
801
  this.#target_accessor_storage = (__runInitializers(this, _strokeWidth_extraInitializers), __runInitializers(this, _target_initializers, {
563
802
  position: [0, 0],
564
803
  }));
565
- this.#text_accessor_storage = (__runInitializers(this, _target_extraInitializers), __runInitializers(this, _text_initializers, undefined));
804
+ this.#targetLabel_accessor_storage = (__runInitializers(this, _target_extraInitializers), __runInitializers(this, _targetLabel_initializers, undefined));
805
+ this.#targetLabelXYWH_accessor_storage = (__runInitializers(this, _targetLabel_extraInitializers), __runInitializers(this, _targetLabelXYWH_initializers, undefined));
806
+ this.#text_accessor_storage = (__runInitializers(this, _targetLabelXYWH_extraInitializers), __runInitializers(this, _text_initializers, undefined));
566
807
  this.#xywh_accessor_storage = (__runInitializers(this, _text_extraInitializers), __runInitializers(this, _xywh_initializers, '[0,0,0,0]'));
567
808
  __runInitializers(this, _xywh_extraInitializers);
568
809
  }
@@ -0,0 +1,83 @@
1
+ import type { IVec, XYWH } from '../../../global/gfx/index.js';
2
+ /**
3
+ * Which of a connector's two ends a label belongs to.
4
+ *
5
+ * `source` and `target` are the names the connector already uses for its two
6
+ * `Connection`s, so an end label's identity is the identity of the endpoint it
7
+ * follows — never a left/right or a first/last, which flip when the author
8
+ * reverses the edge.
9
+ */
10
+ export type ConnectorLabelEnd = 'source' | 'target';
11
+ /**
12
+ * How far along the path, from its endpoint, an end label is anchored by
13
+ * default — in model units, i.e. board units at zoom 1.
14
+ *
15
+ * Far enough to clear the endpoint head (a `DEFAULT_ARROW_SIZE` head on a
16
+ * 4-unit stroke is about 10 units long), close enough that the reader attaches
17
+ * the text to that end rather than to the middle of the line.
18
+ */
19
+ export declare const DEFAULT_CONNECTOR_END_LABEL_DISTANCE = 12;
20
+ /**
21
+ * How close to an endpoint a gesture has to land to mean "that end" — in model
22
+ * units, so it is a constant on the board and not on the screen (zooming out
23
+ * does not widen the target).
24
+ *
25
+ * `docs/adr/0018` phase 2. Deliberately generous, and for a reason a hairline
26
+ * makes plain: the end label a user is reaching for is usually not there yet, so
27
+ * there is no box to aim at, and the thing they aim at instead is the ARROWHEAD.
28
+ *
29
+ * It lives here, beside the box the same clause places, because it is one fact
30
+ * about the same notation and because BOTH the hit test that delivers the
31
+ * gesture ({@link connectorEndNear}) and the picker that decides what it meant
32
+ * (`pickConnectorLabelWhich`, in the gfx pack) have to agree about it. They did
33
+ * not until the PO's recette of 14/09/2026: the picker was generous and the hit
34
+ * test was the line itself — `8` units off the stroke, plus half the stroke's
35
+ * width when the caller asks for a threshold — so anywhere past that the
36
+ * double-click reached nobody and the editor's own "add text here" answered it
37
+ * instead.
38
+ */
39
+ export declare const CONNECTOR_END_LABEL_GRAB = 24;
40
+ /**
41
+ * Which END of a path a point is reaching for, or `null` for none.
42
+ *
43
+ * The nearer end wins a tie-free comparison; a point within reach of both ends
44
+ * of a very short connector gets the nearer one, which is the same rule
45
+ * `pickConnectorLabelWhich` applies and the only one that stays stable as the
46
+ * author drags the line.
47
+ *
48
+ * Pure, and exported, because it is the whole of a gesture's reach and a spec
49
+ * should be able to ask it without driving a pointer.
50
+ */
51
+ export declare function connectorEndNear(path: readonly IVec[], point: IVec, grab?: number): ConnectorLabelEnd | null;
52
+ /**
53
+ * The default box for a connector end label — where it sits when nothing has
54
+ * placed it yet.
55
+ *
56
+ * Pure geometry, deliberately: the editor seeding a new end label
57
+ * (`mountConnectorLabelEditor`), the canvas renderer painting one that has no
58
+ * stored box, and the path generator re-anchoring one after a re-route all
59
+ * need the SAME answer, and none of them should have to reimplement it. No DOM,
60
+ * no model, no measurement — the caller brings the text's measured size.
61
+ *
62
+ * The box is anchored `distance` units along the path from that end's endpoint
63
+ * and pushed off the line by half its own height, so it sits BESIDE the stroke
64
+ * instead of on it. The push uses the path's tangent taken in the **source →
65
+ * target** orientation for both ends, which is what keeps the two labels on the
66
+ * same side of the line: a `0..*` above one end and a `1` below the other reads
67
+ * as two unrelated notes.
68
+ *
69
+ * @param path the connector's path in the coordinate space the returned box
70
+ * belongs to — `absolutePath` for a persisted `labelXYWH`-style box. Accepts
71
+ * `PointLocation[]`; only the coordinates are read, never the tangents.
72
+ * @param end which endpoint the label belongs to.
73
+ * @param size the label's measured size.
74
+ * @param distance how far along the path to anchor it. A path shorter than
75
+ * `distance` anchors the box at its FAR endpoint rather than off the line —
76
+ * a two-unit-long connector puts both labels in the same place, which is
77
+ * honest about there being no room, and is the only way the box stays on the
78
+ * stroke it annotates.
79
+ */
80
+ export declare function connectorEndLabelBox(path: readonly IVec[], end: ConnectorLabelEnd, size: {
81
+ w: number;
82
+ h: number;
83
+ }, distance?: number): XYWH;
@@ -0,0 +1,119 @@
1
+ import { Vec } from '../../../global/gfx/index.js';
2
+ /**
3
+ * How far along the path, from its endpoint, an end label is anchored by
4
+ * default — in model units, i.e. board units at zoom 1.
5
+ *
6
+ * Far enough to clear the endpoint head (a `DEFAULT_ARROW_SIZE` head on a
7
+ * 4-unit stroke is about 10 units long), close enough that the reader attaches
8
+ * the text to that end rather than to the middle of the line.
9
+ */
10
+ export const DEFAULT_CONNECTOR_END_LABEL_DISTANCE = 12;
11
+ /**
12
+ * How close to an endpoint a gesture has to land to mean "that end" — in model
13
+ * units, so it is a constant on the board and not on the screen (zooming out
14
+ * does not widen the target).
15
+ *
16
+ * `docs/adr/0018` phase 2. Deliberately generous, and for a reason a hairline
17
+ * makes plain: the end label a user is reaching for is usually not there yet, so
18
+ * there is no box to aim at, and the thing they aim at instead is the ARROWHEAD.
19
+ *
20
+ * It lives here, beside the box the same clause places, because it is one fact
21
+ * about the same notation and because BOTH the hit test that delivers the
22
+ * gesture ({@link connectorEndNear}) and the picker that decides what it meant
23
+ * (`pickConnectorLabelWhich`, in the gfx pack) have to agree about it. They did
24
+ * not until the PO's recette of 14/09/2026: the picker was generous and the hit
25
+ * test was the line itself — `8` units off the stroke, plus half the stroke's
26
+ * width when the caller asks for a threshold — so anywhere past that the
27
+ * double-click reached nobody and the editor's own "add text here" answered it
28
+ * instead.
29
+ */
30
+ export const CONNECTOR_END_LABEL_GRAB = 24;
31
+ /**
32
+ * Which END of a path a point is reaching for, or `null` for none.
33
+ *
34
+ * The nearer end wins a tie-free comparison; a point within reach of both ends
35
+ * of a very short connector gets the nearer one, which is the same rule
36
+ * `pickConnectorLabelWhich` applies and the only one that stays stable as the
37
+ * author drags the line.
38
+ *
39
+ * Pure, and exported, because it is the whole of a gesture's reach and a spec
40
+ * should be able to ask it without driving a pointer.
41
+ */
42
+ export function connectorEndNear(path, point, grab = CONNECTOR_END_LABEL_GRAB) {
43
+ if (!path.length)
44
+ return null;
45
+ const first = path[0];
46
+ const last = path[path.length - 1];
47
+ const toSource = Vec.dist(point, [first[0], first[1]]);
48
+ const toTarget = Vec.dist(point, [last[0], last[1]]);
49
+ if (Math.min(toSource, toTarget) > grab)
50
+ return null;
51
+ return toSource <= toTarget ? 'source' : 'target';
52
+ }
53
+ /**
54
+ * The default box for a connector end label — where it sits when nothing has
55
+ * placed it yet.
56
+ *
57
+ * Pure geometry, deliberately: the editor seeding a new end label
58
+ * (`mountConnectorLabelEditor`), the canvas renderer painting one that has no
59
+ * stored box, and the path generator re-anchoring one after a re-route all
60
+ * need the SAME answer, and none of them should have to reimplement it. No DOM,
61
+ * no model, no measurement — the caller brings the text's measured size.
62
+ *
63
+ * The box is anchored `distance` units along the path from that end's endpoint
64
+ * and pushed off the line by half its own height, so it sits BESIDE the stroke
65
+ * instead of on it. The push uses the path's tangent taken in the **source →
66
+ * target** orientation for both ends, which is what keeps the two labels on the
67
+ * same side of the line: a `0..*` above one end and a `1` below the other reads
68
+ * as two unrelated notes.
69
+ *
70
+ * @param path the connector's path in the coordinate space the returned box
71
+ * belongs to — `absolutePath` for a persisted `labelXYWH`-style box. Accepts
72
+ * `PointLocation[]`; only the coordinates are read, never the tangents.
73
+ * @param end which endpoint the label belongs to.
74
+ * @param size the label's measured size.
75
+ * @param distance how far along the path to anchor it. A path shorter than
76
+ * `distance` anchors the box at its FAR endpoint rather than off the line —
77
+ * a two-unit-long connector puts both labels in the same place, which is
78
+ * honest about there being no room, and is the only way the box stays on the
79
+ * stroke it annotates.
80
+ */
81
+ export function connectorEndLabelBox(path, end, size, distance = DEFAULT_CONNECTOR_END_LABEL_DISTANCE) {
82
+ const { w, h } = size;
83
+ const forward = end === 'source';
84
+ const count = path.length;
85
+ if (count === 0) {
86
+ return [-w / 2, -h / 2, w, h];
87
+ }
88
+ const endpoint = path[forward ? 0 : count - 1];
89
+ let anchor = [endpoint[0], endpoint[1]];
90
+ // A degenerate path (one point, or every point coincident) has no direction
91
+ // to be beside; `[1, 0]` puts the label above the anchor, the same place a
92
+ // left-to-right connector would.
93
+ let tangent = [1, 0];
94
+ let remaining = Math.max(0, distance);
95
+ for (let step = 0; step < count - 1; step++) {
96
+ const from = path[forward ? step : count - 1 - step];
97
+ const to = path[forward ? step + 1 : count - 2 - step];
98
+ const segment = Vec.dist(from, to);
99
+ if (segment > 0) {
100
+ // Always source → target, whichever end we walk from.
101
+ tangent = Vec.uni(forward
102
+ ? [to[0] - from[0], to[1] - from[1]]
103
+ : [from[0] - to[0], from[1] - to[1]]);
104
+ }
105
+ if (segment >= remaining) {
106
+ const t = segment === 0 ? 0 : remaining / segment;
107
+ anchor = [
108
+ from[0] + (to[0] - from[0]) * t,
109
+ from[1] + (to[1] - from[1]) * t,
110
+ ];
111
+ remaining = 0;
112
+ break;
113
+ }
114
+ remaining -= segment;
115
+ anchor = [to[0], to[1]];
116
+ }
117
+ const center = Vec.add(anchor, Vec.mul(Vec.per(tangent), h / 2));
118
+ return [center[0] - w / 2, center[1] - h / 2, w, h];
119
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './connector.js';
2
+ export * from './end-label.js';
2
3
  export * from './local-connector.js';
@@ -1,2 +1,3 @@
1
1
  export * from './connector.js';
2
+ export * from './end-label.js';
2
3
  export * from './local-connector.js';
@@ -67,7 +67,7 @@ let ContextMapBoardElementModel = (() => {
67
67
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
68
68
  _resizeEnabled_decorators = [field(true)];
69
69
  _rotate_decorators = [field(0)];
70
- _xywh_decorators = [field()];
70
+ _xywh_decorators = [field('[0,0,0,0]')];
71
71
  __esDecorate(this, null, _resizeEnabled_decorators, { kind: "accessor", name: "resizeEnabled", static: false, private: false, access: { has: obj => "resizeEnabled" in obj, get: obj => obj.resizeEnabled, set: (obj, value) => { obj.resizeEnabled = value; } }, metadata: _metadata }, _resizeEnabled_initializers, _resizeEnabled_extraInitializers);
72
72
  __esDecorate(this, null, _rotate_decorators, { kind: "accessor", name: "rotate", static: false, private: false, access: { has: obj => "rotate" in obj, get: obj => obj.rotate, set: (obj, value) => { obj.rotate = value; } }, metadata: _metadata }, _rotate_initializers, _rotate_extraInitializers);
73
73
  __esDecorate(this, null, _xywh_decorators, { kind: "accessor", name: "xywh", static: false, private: false, access: { has: obj => "xywh" in obj, get: obj => obj.xywh, set: (obj, value) => { obj.xywh = value; } }, metadata: _metadata }, _xywh_initializers, _xywh_extraInitializers);