@formicoidea/labre-core 0.33.0 → 0.34.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/_pkgs/affine-block-attachment/attachment-block.js +2 -2
  2. package/dist/_pkgs/affine-block-attachment/configs/toolbar.d.ts +2 -2
  3. package/dist/_pkgs/affine-block-attachment/configs/toolbar.js +9 -7
  4. package/dist/_pkgs/affine-block-bookmark/configs/toolbar.js +12 -12
  5. package/dist/_pkgs/affine-block-code/code-block.js +2 -2
  6. package/dist/_pkgs/affine-block-code/code-toolbar/config.js +6 -0
  7. package/dist/_pkgs/affine-block-database/database-block.js +2 -2
  8. package/dist/_pkgs/affine-block-embed/common/render-linked-doc.js +3 -3
  9. package/dist/_pkgs/affine-block-embed/configs/toolbar.js +11 -11
  10. package/dist/_pkgs/affine-block-embed/embed-html-block/configs/toolbar.js +5 -5
  11. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.d.ts +7 -7
  12. package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +12 -12
  13. package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +2 -2
  14. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.js +9 -9
  15. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +4 -4
  16. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/components/embed-synced-doc-card.js +5 -4
  17. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +9 -9
  18. package/dist/_pkgs/affine-block-frame/frame-toolbar.js +2 -2
  19. package/dist/_pkgs/affine-block-image/configs/toolbar.js +4 -4
  20. package/dist/_pkgs/affine-block-note/configs/toolbar.js +2 -2
  21. package/dist/_pkgs/affine-block-root/configs/toolbar.d.ts +6 -4
  22. package/dist/_pkgs/affine-block-root/configs/toolbar.js +6 -6
  23. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/misc.d.ts +10 -10
  24. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/misc.js +4 -4
  25. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.d.ts +7 -7
  26. package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.js +8 -8
  27. package/dist/_pkgs/affine-block-root/edgeless/edgeless-root-block.js +3 -1
  28. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +15 -4
  29. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +17 -0
  30. package/dist/_pkgs/affine-block-surface/extensions/spotlight.d.ts +21 -0
  31. package/dist/_pkgs/affine-block-surface/extensions/spotlight.js +17 -3
  32. package/dist/_pkgs/affine-block-surface/index.d.ts +1 -0
  33. package/dist/_pkgs/affine-block-surface/index.js +1 -0
  34. package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.d.ts +17 -0
  35. package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +66 -0
  36. package/dist/_pkgs/affine-block-surface/view.js +5 -0
  37. package/dist/_pkgs/affine-block-surface-ref/configs/toolbar.js +4 -4
  38. package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
  39. package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
  40. package/dist/_pkgs/affine-components/icons/text.js +426 -426
  41. package/dist/_pkgs/affine-components/open-doc-dropdown-menu/dropdown-menu.d.ts +2 -0
  42. package/dist/_pkgs/affine-components/resource/resource.js +2 -0
  43. package/dist/_pkgs/affine-components/view-dropdown-menu/dropdown-menu.js +27 -14
  44. package/dist/_pkgs/affine-inline-link/link-node/configs/toolbar.d.ts +4 -4
  45. package/dist/_pkgs/affine-inline-link/link-node/configs/toolbar.js +6 -6
  46. package/dist/_pkgs/affine-inline-reference/reference-node/configs/toolbar.d.ts +4 -4
  47. package/dist/_pkgs/affine-inline-reference/reference-node/configs/toolbar.js +6 -6
  48. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +61 -0
  49. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +93 -0
  50. package/dist/_pkgs/affine-model/elements/cynefin/cynefin.d.ts +7 -2
  51. package/dist/_pkgs/affine-model/elements/cynefin/cynefin.js +9 -4
  52. package/dist/_pkgs/affine-model/elements/edgy/board.d.ts +7 -2
  53. package/dist/_pkgs/affine-model/elements/edgy/board.js +9 -4
  54. package/dist/_pkgs/affine-model/elements/edgy/facets.d.ts +20 -3
  55. package/dist/_pkgs/affine-model/elements/edgy/facets.js +13 -4
  56. package/dist/_pkgs/affine-model/elements/estuarine/estuarine.d.ts +7 -2
  57. package/dist/_pkgs/affine-model/elements/estuarine/estuarine.js +9 -4
  58. package/dist/_pkgs/affine-model/elements/framework-background/background.d.ts +7 -2
  59. package/dist/_pkgs/affine-model/elements/framework-background/background.js +9 -4
  60. package/dist/_pkgs/affine-model/elements/framework-background/hit-test.d.ts +48 -0
  61. package/dist/_pkgs/affine-model/elements/framework-background/hit-test.js +55 -0
  62. package/dist/_pkgs/affine-model/elements/framework-background/index.d.ts +1 -0
  63. package/dist/_pkgs/affine-model/elements/framework-background/index.js +1 -0
  64. package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +11 -0
  65. package/dist/_pkgs/affine-shared/services/edit-props-store.js +15 -0
  66. package/dist/_pkgs/affine-shared/services/toolbar-service/action.d.ts +32 -0
  67. package/dist/_pkgs/affine-shared/services/toolbar-service/action.js +16 -0
  68. package/dist/_pkgs/affine-shared/services/toolbar-service/flags.d.ts +10 -0
  69. package/dist/_pkgs/affine-shared/services/toolbar-service/flags.js +32 -1
  70. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +106 -0
  71. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +201 -0
  72. package/dist/_pkgs/affine-shared/services/translation-service/index.d.ts +1 -0
  73. package/dist/_pkgs/affine-shared/services/translation-service/index.js +1 -0
  74. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.d.ts +11 -16
  75. package/dist/_pkgs/affine-widget-edgeless-toolbar/catalogue/catalogue-groups.js +11 -28
  76. package/dist/_pkgs/affine-widget-keyboard-toolbar/config.js +2 -1
  77. package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
  78. package/dist/_pkgs/affine-widget-slash-menu/config.js +2 -1
  79. package/dist/_pkgs/affine-widget-toolbar/toolbar.js +5 -0
  80. package/dist/_pkgs/affine-widget-toolbar/utils.d.ts +19 -2
  81. package/dist/_pkgs/affine-widget-toolbar/utils.js +22 -7
  82. package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +11 -11
  83. package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
  84. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-title.js +18 -18
  85. package/dist/_pkgs/std/extension/command-registry.d.ts +36 -0
  86. package/dist/_pkgs/std/extension/command-registry.js +16 -0
  87. package/dist/_pkgs/std/extension/translation-manifest.d.ts +46 -1
  88. package/dist/_pkgs/std/extension/translation-manifest.js +58 -0
  89. package/dist/_pkgs/std/gfx/highlight.d.ts +84 -0
  90. package/dist/_pkgs/std/gfx/highlight.js +112 -0
  91. package/dist/_pkgs/std/gfx/index.d.ts +1 -0
  92. package/dist/_pkgs/std/gfx/index.js +1 -0
  93. package/dist/_pkgs/std/gfx/interactivity/gfx-view-event-handler.js +17 -3
  94. package/dist/_pkgs/std/scope/std-scope.d.ts +2 -1
  95. package/dist/_pkgs/std/scope/std-scope.js +2 -0
  96. package/dist/_pkgs/std/utils/gfx.js +2 -0
  97. package/dist/shortcuts.d.ts +20 -6
  98. package/dist/shortcuts.js +7 -9
  99. package/dist/translations.js +25 -18
  100. package/package.json +13 -1
@@ -20,9 +20,11 @@ export declare class OpenDocDropdownMenu extends OpenDocDropdownMenu_base {
20
20
  priority?: number;
21
21
  } & {
22
22
  label?: string;
23
+ labelWording?: import("../../affine-shared/services/index.js").ChromeWording;
23
24
  showLabel?: boolean;
24
25
  icon?: import("lit-html").TemplateResult;
25
26
  tooltip?: string | import("lit-html").TemplateResult;
27
+ tooltipWording?: import("../../affine-shared/services/index.js").ChromeWording;
26
28
  variant?: "destructive";
27
29
  disabled?: ((cx: ToolbarContext) => boolean) | boolean;
28
30
  content?: ((cx: ToolbarContext) => import("lit-html").TemplateResult | null) | (import("lit-html").TemplateResult | null);
@@ -63,6 +63,8 @@ export class ResourceController {
63
63
  updateState(state) {
64
64
  this.state$.value = { ...this.state$.value, ...state };
65
65
  }
66
+ // The explicit return type keeps declaration emit off signals-core's
67
+ // `DisposeFn`, whose `[Symbol.dispose]` member tsc cannot serialize.
66
68
  subscribe() {
67
69
  return effect(() => {
68
70
  const blobId = this.blobId$.value;
@@ -32,7 +32,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { ToolbarContext, } from '../../affine-shared/services/index.js';
35
+ import { TOOLBAR_SWITCH_VIEW, toolbarActionLabel, ToolbarContext, translateKey, } from '../../affine-shared/services/index.js';
36
36
  import { SignalWatcher } from '../../global/lit/index.js';
37
37
  import { PropTypes, requiredProperties } from '../../std/index.js';
38
38
  import { LitElement } from 'lit';
@@ -86,13 +86,20 @@ let ViewDropdownMenu = (() => {
86
86
  set viewType$(value) { this.#viewType$_accessor_storage = value; }
87
87
  render() {
88
88
  const { actions, context, viewType$: { value: viewType }, } = this;
89
+ // These entries never went through `combine` — the group that owns them
90
+ // brings its own template and hands them over raw — so the i18n seam is
91
+ // applied here, with the same key the row would have used. `viewType` is
92
+ // resolved by the caller through the very same wordings, which is what
93
+ // keeps the "currently selected" comparison below a comparison of words.
94
+ const wordOf = (action) => toolbarActionLabel(context.std, action);
95
+ const switchView = translateKey(context.std, ...TOOLBAR_SWITCH_VIEW);
89
96
  return html `
90
97
  <editor-menu-button
91
98
  .contentPadding="${'8px'}"
92
99
  .button=${html `
93
100
  <editor-icon-button
94
- aria-label="Switch view"
95
- .tooltip="${'Switch view'}"
101
+ aria-label=${switchView}
102
+ .tooltip="${switchView}"
96
103
  .justify="${'space-between'}"
97
104
  .labelHeight="${'20px'}"
98
105
  .iconContainerWidth="${'110px'}"
@@ -107,17 +114,23 @@ let ViewDropdownMenu = (() => {
107
114
  if (typeof action.when === 'function')
108
115
  return action.when(context);
109
116
  return action.when ?? true;
110
- }), action => action.id, ({ id, label, disabled, run }) => html `
111
- <editor-menu-action
112
- aria-label="${ifDefined(label)}"
113
- data-testid="${`link-to-${id}`}"
114
- ?data-selected="${label === viewType}"
115
- ?disabled="${ifDefined(typeof disabled === 'function' ? disabled(context) : disabled)}"
116
- @click=${() => run?.(context)}
117
- >
118
- ${label}
119
- </editor-menu-action>
120
- `)}
117
+ }), action => action.id, action => {
118
+ const { id, disabled, run } = action;
119
+ const label = wordOf(action);
120
+ return html `
121
+ <editor-menu-action
122
+ aria-label="${ifDefined(label)}"
123
+ data-testid="${`link-to-${id}`}"
124
+ ?data-selected="${label === viewType}"
125
+ ?disabled="${ifDefined(typeof disabled === 'function'
126
+ ? disabled(context)
127
+ : disabled)}"
128
+ @click=${() => run?.(context)}
129
+ >
130
+ ${label}
131
+ </editor-menu-action>
132
+ `;
133
+ })}
121
134
  </div>
122
135
  </editor-menu-button>
123
136
  `;
@@ -20,19 +20,19 @@ export declare const builtinInlineLinkToolbarConfig: {
20
20
  id: string;
21
21
  actions: ({
22
22
  id: string;
23
- label: string;
23
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
24
24
  disabled: true;
25
25
  run?: undefined;
26
26
  when?: undefined;
27
27
  } | {
28
28
  id: string;
29
- label: string;
29
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
30
30
  run(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): void;
31
31
  disabled?: undefined;
32
32
  when?: undefined;
33
33
  } | {
34
34
  id: string;
35
- label: string;
35
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
36
36
  when(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): boolean;
37
37
  run(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): void;
38
38
  disabled?: undefined;
@@ -48,7 +48,7 @@ export declare const builtinInlineLinkToolbarConfig: {
48
48
  }, {
49
49
  readonly placement: ActionPlacement.More;
50
50
  readonly id: "c.delete";
51
- readonly label: "Delete";
51
+ readonly labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
52
52
  readonly icon: import("lit-html").TemplateResult<1>;
53
53
  readonly variant: "destructive";
54
54
  readonly run: (ctx: import("../../../affine-shared/services/index.js").ToolbarContext) => void;
@@ -1,5 +1,5 @@
1
1
  import { toast } from '../../../affine-components/toast/index.js';
2
- import { ActionPlacement, EmbedIframeService, EmbedOptionProvider, } from '../../../affine-shared/services/index.js';
2
+ import { ActionPlacement, EmbedIframeService, EmbedOptionProvider, TOOLBAR_CARD_VIEW, TOOLBAR_DELETE, TOOLBAR_EMBED_VIEW, TOOLBAR_INLINE_VIEW, toolbarActionLabel, } from '../../../affine-shared/services/index.js';
3
3
  import { CopyIcon, DeleteIcon, EditIcon, UnlinkIcon, } from '@blocksuite/icons/lit';
4
4
  import { BlockSelection } from '../../../std/index.js';
5
5
  import { signal } from '@preact/signals-core';
@@ -79,12 +79,12 @@ export const builtinInlineLinkToolbarConfig = {
79
79
  actions: [
80
80
  {
81
81
  id: 'inline',
82
- label: 'Inline view',
82
+ labelWording: TOOLBAR_INLINE_VIEW,
83
83
  disabled: true,
84
84
  },
85
85
  {
86
86
  id: 'card',
87
- label: 'Card view',
87
+ labelWording: TOOLBAR_CARD_VIEW,
88
88
  run(ctx) {
89
89
  const target = ctx.message$.peek()?.element;
90
90
  if (!(target instanceof AffineLink))
@@ -133,7 +133,7 @@ export const builtinInlineLinkToolbarConfig = {
133
133
  },
134
134
  {
135
135
  id: 'embed',
136
- label: 'Embed view',
136
+ labelWording: TOOLBAR_EMBED_VIEW,
137
137
  when(ctx) {
138
138
  const target = ctx.message$.peek()?.element;
139
139
  if (!(target instanceof AffineLink))
@@ -210,7 +210,7 @@ export const builtinInlineLinkToolbarConfig = {
210
210
  if (!(target instanceof AffineLink))
211
211
  return null;
212
212
  const actions = this.actions.map(action => ({ ...action }));
213
- const viewType$ = signal(actions[0].label);
213
+ const viewType$ = signal(toolbarActionLabel(ctx.std, actions[0]));
214
214
  const onToggle = (e) => {
215
215
  const opened = e.detail;
216
216
  if (!opened)
@@ -280,7 +280,7 @@ export const builtinInlineLinkToolbarConfig = {
280
280
  {
281
281
  placement: ActionPlacement.More,
282
282
  id: 'c.delete',
283
- label: 'Delete',
283
+ labelWording: TOOLBAR_DELETE,
284
284
  icon: DeleteIcon(),
285
285
  variant: 'destructive',
286
286
  run(ctx) {
@@ -7,17 +7,17 @@ export declare const builtinInlineReferenceToolbarConfig: {
7
7
  id: string;
8
8
  actions: ({
9
9
  id: string;
10
- label: string;
10
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
11
11
  disabled: true;
12
12
  run?: undefined;
13
13
  } | {
14
14
  id: string;
15
- label: string;
15
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
16
16
  run(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): void;
17
17
  disabled?: undefined;
18
18
  } | {
19
19
  id: string;
20
- label: string;
20
+ labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
21
21
  disabled(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): boolean;
22
22
  run(ctx: import("../../../affine-shared/services/index.js").ToolbarContext): void;
23
23
  })[];
@@ -26,7 +26,7 @@ export declare const builtinInlineReferenceToolbarConfig: {
26
26
  }, {
27
27
  readonly placement: ActionPlacement.More;
28
28
  readonly id: "c.delete";
29
- readonly label: "Delete";
29
+ readonly labelWording: import("../../../affine-shared/services/index.js").ChromeWording;
30
30
  readonly icon: import("lit-html").TemplateResult<1>;
31
31
  readonly variant: "destructive";
32
32
  readonly run: (ctx: import("../../../affine-shared/services/index.js").ToolbarContext) => void;
@@ -1,5 +1,5 @@
1
1
  import { notifyLinkedDocSwitchedToEmbed } from '../../../affine-components/notification/index.js';
2
- import { ActionPlacement, DocDisplayMetaProvider, } from '../../../affine-shared/services/index.js';
2
+ import { ActionPlacement, DocDisplayMetaProvider, TOOLBAR_CARD_VIEW, TOOLBAR_DELETE, TOOLBAR_EMBED_VIEW, TOOLBAR_INLINE_VIEW, toolbarActionLabel, } from '../../../affine-shared/services/index.js';
3
3
  import { cloneReferenceInfoWithoutAliases, isInsideBlockByFlavour, } from '../../../affine-shared/utils/index.js';
4
4
  import { DeleteIcon } from '@blocksuite/icons/lit';
5
5
  import { BlockSelection } from '../../../std/index.js';
@@ -38,12 +38,12 @@ export const builtinInlineReferenceToolbarConfig = {
38
38
  actions: [
39
39
  {
40
40
  id: 'inline',
41
- label: 'Inline view',
41
+ labelWording: TOOLBAR_INLINE_VIEW,
42
42
  disabled: true,
43
43
  },
44
44
  {
45
45
  id: 'card',
46
- label: 'Card view',
46
+ labelWording: TOOLBAR_CARD_VIEW,
47
47
  run(ctx) {
48
48
  const target = ctx.message$.peek()?.element;
49
49
  if (!(target instanceof AffineReference))
@@ -78,7 +78,7 @@ export const builtinInlineReferenceToolbarConfig = {
78
78
  },
79
79
  {
80
80
  id: 'embed',
81
- label: 'Embed view',
81
+ labelWording: TOOLBAR_EMBED_VIEW,
82
82
  disabled(ctx) {
83
83
  const target = ctx.message$.peek()?.element;
84
84
  if (!(target instanceof AffineReference))
@@ -140,7 +140,7 @@ export const builtinInlineReferenceToolbarConfig = {
140
140
  if (!(target instanceof AffineReference))
141
141
  return null;
142
142
  const actions = this.actions.map(action => ({ ...action }));
143
- const viewType$ = signal(actions[0].label);
143
+ const viewType$ = signal(toolbarActionLabel(ctx.std, actions[0]));
144
144
  const onToggle = (e) => {
145
145
  const opened = e.detail;
146
146
  if (!opened)
@@ -174,7 +174,7 @@ export const builtinInlineReferenceToolbarConfig = {
174
174
  {
175
175
  placement: ActionPlacement.More,
176
176
  id: 'c.delete',
177
- label: 'Delete',
177
+ labelWording: TOOLBAR_DELETE,
178
178
  icon: DeleteIcon(),
179
179
  variant: 'destructive',
180
180
  run(ctx) {
@@ -1,6 +1,32 @@
1
1
  import type { SerializedXYWH } from '../../../global/gfx/index.js';
2
+ import type { PointTestOptions } from '../../../std/gfx/index.js';
2
3
  import type { FrameworkBackgroundProps } from '../framework-background/index.js';
3
4
  import { FrameworkBackgroundElementModel } from '../framework-background/index.js';
5
+ /**
6
+ * Width of the participant band — the left margin strip the pool name is
7
+ * written up, in model units.
8
+ *
9
+ * Declared HERE, in the model, and re-exported by `@labre/affine-gfx-bpmn`
10
+ * rather than the other way round. The pool's own hit test needs it (a pool is
11
+ * clickable by its title bands as well as its border, the bpmn.io convention),
12
+ * and `affine-model` cannot reach into `affine-block-surface` where the
13
+ * declaration is resolved. One number, owned by the layer that both the
14
+ * declaration and the hit test can read.
15
+ */
16
+ export declare const POOL_BAND_WIDTH = 28;
17
+ /**
18
+ * Width of a lane's own title band — the strip immediately inside the
19
+ * participant band, with the lane name turned on its side.
20
+ *
21
+ * Four units narrower than {@link POOL_BAND_WIDTH}, and for the same reason the
22
+ * lane font is two points smaller: the two strips sit side by side, so the
23
+ * subordinate one has to say so. Identical widths read as a single 56-unit
24
+ * gutter rather than as a participant containing lanes, which is exactly the
25
+ * relationship the picture has to carry.
26
+ *
27
+ * NO fill, divider only — what bpmn.io, Camunda and Visio all draw.
28
+ */
29
+ export declare const POOL_LANE_BAND_WIDTH = 24;
4
30
  /**
5
31
  * One LANE (couloir) of a pool: a horizontal band the participant's own work is
6
32
  * divided into — "Sales", "Back office", "Automated".
@@ -84,4 +110,39 @@ export declare class BpmnPoolElementModel extends FrameworkBackgroundElementMode
84
110
  * primitive paints the dividers and the names from it.
85
111
  */
86
112
  accessor lanes: BpmnLane[] | undefined;
113
+ /**
114
+ * A pool is picked by its BORDER — and by its TITLE BANDS, which is the one
115
+ * carve-out the recette kept (issue #194).
116
+ *
117
+ * That is the bpmn.io convention, and it is the convention because the bands
118
+ * are the only part of a pool that is the pool rather than the process drawn
119
+ * on it: the participant strip on the left carries the participant's name,
120
+ * the lane strip beside it carries the lane names, and nothing is ever
121
+ * dropped on either. The flow area is where the work goes, so a click there
122
+ * belongs to whatever is under the pointer.
123
+ *
124
+ * ## Where the geometry comes from
125
+ *
126
+ * The two strips run the FULL height of the pool: the participant band is the
127
+ * whole left margin, and the lane bands partition that same height between
128
+ * them with no gap — so their union is one vertical strip
129
+ * `POOL_LANE_BAND_WIDTH` wide, whatever the lanes' individual weights are.
130
+ * Which means this test needs no lane arithmetic at all, only the two widths
131
+ * (declared above, and read from here by the framework declaration) and the
132
+ * answer to "does this pool have a usable lane".
133
+ *
134
+ * The zoom-grown rename targets — the touch-sized boxes a double-click aims
135
+ * at — are the VIEW's business and stay in `pool-hit.ts`; what is painted is
136
+ * what is selectable, which is the promise this test has to keep.
137
+ */
138
+ includesPoint(x: number, y: number, options?: PointTestOptions): boolean;
139
+ /**
140
+ * Whether at least one lane is drawn — the only thing the hit test needs to
141
+ * know about the partition.
142
+ *
143
+ * Mirrors what `backgroundInstanceZones` keeps (a string id, a finite size
144
+ * greater than zero): a malformed row is dropped there and paints no band, so
145
+ * it must not make a band clickable here either.
146
+ */
147
+ private get hasUsableLane();
87
148
  }
@@ -32,8 +32,34 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
+ import { rotatePoint } from '../../../global/gfx/index.js';
35
36
  import { field } from '../../../std/gfx/index.js';
36
37
  import { FrameworkBackgroundElementModel } from '../framework-background/index.js';
38
+ /**
39
+ * Width of the participant band — the left margin strip the pool name is
40
+ * written up, in model units.
41
+ *
42
+ * Declared HERE, in the model, and re-exported by `@labre/affine-gfx-bpmn`
43
+ * rather than the other way round. The pool's own hit test needs it (a pool is
44
+ * clickable by its title bands as well as its border, the bpmn.io convention),
45
+ * and `affine-model` cannot reach into `affine-block-surface` where the
46
+ * declaration is resolved. One number, owned by the layer that both the
47
+ * declaration and the hit test can read.
48
+ */
49
+ export const POOL_BAND_WIDTH = 28;
50
+ /**
51
+ * Width of a lane's own title band — the strip immediately inside the
52
+ * participant band, with the lane name turned on its side.
53
+ *
54
+ * Four units narrower than {@link POOL_BAND_WIDTH}, and for the same reason the
55
+ * lane font is two points smaller: the two strips sit side by side, so the
56
+ * subordinate one has to say so. Identical widths read as a single 56-unit
57
+ * gutter rather than as a participant containing lanes, which is exactly the
58
+ * relationship the picture has to carry.
59
+ *
60
+ * NO fill, divider only — what bpmn.io, Camunda and Visio all draw.
61
+ */
62
+ export const POOL_LANE_BAND_WIDTH = 24;
37
63
  /**
38
64
  * A BPMN "pool": a participant container drawn as a rounded-rect frame with a
39
65
  * vertical name band on the left. It is a framework background like every other
@@ -131,6 +157,73 @@ let BpmnPoolElementModel = (() => {
131
157
  */
132
158
  get lanes() { return this.#lanes_accessor_storage; }
133
159
  set lanes(value) { this.#lanes_accessor_storage = value; }
160
+ /**
161
+ * A pool is picked by its BORDER — and by its TITLE BANDS, which is the one
162
+ * carve-out the recette kept (issue #194).
163
+ *
164
+ * That is the bpmn.io convention, and it is the convention because the bands
165
+ * are the only part of a pool that is the pool rather than the process drawn
166
+ * on it: the participant strip on the left carries the participant's name,
167
+ * the lane strip beside it carries the lane names, and nothing is ever
168
+ * dropped on either. The flow area is where the work goes, so a click there
169
+ * belongs to whatever is under the pointer.
170
+ *
171
+ * ## Where the geometry comes from
172
+ *
173
+ * The two strips run the FULL height of the pool: the participant band is the
174
+ * whole left margin, and the lane bands partition that same height between
175
+ * them with no gap — so their union is one vertical strip
176
+ * `POOL_LANE_BAND_WIDTH` wide, whatever the lanes' individual weights are.
177
+ * Which means this test needs no lane arithmetic at all, only the two widths
178
+ * (declared above, and read from here by the framework declaration) and the
179
+ * answer to "does this pool have a usable lane".
180
+ *
181
+ * The zoom-grown rename targets — the touch-sized boxes a double-click aims
182
+ * at — are the VIEW's business and stay in `pool-hit.ts`; what is painted is
183
+ * what is selectable, which is the promise this test has to keep.
184
+ */
185
+ includesPoint(x, y, options) {
186
+ if (super.includesPoint(x, y, options))
187
+ return true;
188
+ const [ex, ey, w, h] = this.deserializedXYWH;
189
+ // Element-local coordinates, undoing the element rotation about its centre
190
+ // — the bands are axis-aligned inside the pool, not on the canvas.
191
+ let lx = x - ex;
192
+ let ly = y - ey;
193
+ const rotate = this.rotate ?? 0;
194
+ if (rotate) {
195
+ const [ux, uy] = rotatePoint([x, y], [ex + w / 2, ey + h / 2], -rotate);
196
+ lx = ux - ex;
197
+ ly = uy - ey;
198
+ }
199
+ if (ly < 0 || ly > h || lx < 0)
200
+ return false;
201
+ // Clamped to a pool narrower than its own margin — the degenerate case the
202
+ // renderer clamps too.
203
+ const band = Math.min(POOL_BAND_WIDTH, w);
204
+ const lanes = this.hasUsableLane
205
+ ? Math.min(POOL_LANE_BAND_WIDTH, w - band)
206
+ : 0;
207
+ return lx <= band + Math.max(lanes, 0);
208
+ }
209
+ /**
210
+ * Whether at least one lane is drawn — the only thing the hit test needs to
211
+ * know about the partition.
212
+ *
213
+ * Mirrors what `backgroundInstanceZones` keeps (a string id, a finite size
214
+ * greater than zero): a malformed row is dropped there and paints no band, so
215
+ * it must not make a band clickable here either.
216
+ */
217
+ get hasUsableLane() {
218
+ const lanes = this.lanes;
219
+ if (!Array.isArray(lanes))
220
+ return false;
221
+ return lanes.some(lane => typeof lane?.id === 'string' &&
222
+ lane.id !== '' &&
223
+ typeof lane.size === 'number' &&
224
+ Number.isFinite(lane.size) &&
225
+ lane.size > 0);
226
+ }
134
227
  constructor() {
135
228
  super(...arguments);
136
229
  __runInitializers(this, _lanes_extraInitializers);
@@ -1,6 +1,6 @@
1
1
  import type { IVec, SerializedXYWH } from '../../../global/gfx/index.js';
2
2
  import { Bound } from '../../../global/gfx/index.js';
3
- import type { BaseElementProps } from '../../../std/gfx/index.js';
3
+ import type { BaseElementProps, PointTestOptions } from '../../../std/gfx/index.js';
4
4
  import { GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
5
5
  export type CynefinProps = BaseElementProps & {
6
6
  /** When false the resize handles are hidden — toggled from the toolbar. */
@@ -28,7 +28,12 @@ export declare class CynefinElementModel extends GfxPrimitiveElementModel<Cynefi
28
28
  containsBound(bounds: Bound): boolean;
29
29
  getLineIntersections(start: IVec, end: IVec): import("../../../global/gfx/index.js").PointLocation[] | null;
30
30
  getNearestPoint(point: IVec): IVec;
31
- includesPoint(x: number, y: number): boolean;
31
+ /**
32
+ * Picked by its BORDER band — see {@link backgroundIncludesPoint}. The five
33
+ * domains are a picture the user drops elements onto, so the clicks inside
34
+ * the frame belong to those elements.
35
+ */
36
+ includesPoint(x: number, y: number, options?: PointTestOptions): boolean;
32
37
  accessor resizeEnabled: boolean;
33
38
  accessor showTitles: boolean;
34
39
  accessor showDescriptions: boolean;
@@ -32,8 +32,9 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, pointInPolygon, polygonNearestPoint, } from '../../../global/gfx/index.js';
35
+ import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, polygonNearestPoint, } from '../../../global/gfx/index.js';
36
36
  import { field, GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
37
+ import { backgroundIncludesPoint } from '../framework-background/index.js';
37
38
  /**
38
39
  * A static "Liminal Cynefin" framework diagram: the hand-drawn five-domain
39
40
  * boundary (Complex / Complicated / Chaotic / Clear + central Confusion), the
@@ -98,9 +99,13 @@ let CynefinElementModel = (() => {
98
99
  getNearestPoint(point) {
99
100
  return polygonNearestPoint(Bound.deserialize(this.xywh).points, point);
100
101
  }
101
- includesPoint(x, y) {
102
- const points = getPointsFromBoundWithRotation(this);
103
- return pointInPolygon([x, y], points);
102
+ /**
103
+ * Picked by its BORDER band — see {@link backgroundIncludesPoint}. The five
104
+ * domains are a picture the user drops elements onto, so the clicks inside
105
+ * the frame belong to those elements.
106
+ */
107
+ includesPoint(x, y, options) {
108
+ return backgroundIncludesPoint(this, x, y, options);
104
109
  }
105
110
  #resizeEnabled_accessor_storage = __runInitializers(this, _resizeEnabled_initializers, true);
106
111
  get resizeEnabled() { return this.#resizeEnabled_accessor_storage; }
@@ -1,7 +1,7 @@
1
1
  import type { IVec } from '../../../global/gfx/index.js';
2
2
  import { Bound } from '../../../global/gfx/index.js';
3
3
  import type { SerializedXYWH } from '../../../global/gfx/index.js';
4
- import type { BaseElementProps } from '../../../std/gfx/index.js';
4
+ import type { BaseElementProps, PointTestOptions } from '../../../std/gfx/index.js';
5
5
  import { GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
6
6
  export type EdgyBoardProps = BaseElementProps & {
7
7
  /** When false the resize handles are hidden — toggled from the toolbar. */
@@ -24,7 +24,12 @@ export declare class EdgyBoardElementModel extends GfxPrimitiveElementModel<Edgy
24
24
  containsBound(bounds: Bound): boolean;
25
25
  getLineIntersections(start: IVec, end: IVec): import("../../../global/gfx/index.js").PointLocation[] | null;
26
26
  getNearestPoint(point: IVec): IVec;
27
- includesPoint(x: number, y: number): boolean;
27
+ /**
28
+ * Picked by its BORDER band: a board is a passive canvas and the clicks over
29
+ * its area belong to what the user laid on it. Same test every framework
30
+ * background runs — see {@link backgroundIncludesPoint}.
31
+ */
32
+ includesPoint(x: number, y: number, options?: PointTestOptions): boolean;
28
33
  accessor resizeEnabled: boolean;
29
34
  accessor spotlightEnabled: boolean;
30
35
  accessor rotate: number;
@@ -32,8 +32,9 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, pointInPolygon, polygonNearestPoint, } from '../../../global/gfx/index.js';
35
+ import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, polygonNearestPoint, } from '../../../global/gfx/index.js';
36
36
  import { field, GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
37
+ import { backgroundIncludesPoint } from '../framework-background/index.js';
37
38
  /**
38
39
  * A blank white board for free-form EDGY modelling: the user places EDGY base
39
40
  * shapes and connectors on top of it and the board grants them the dependency
@@ -87,9 +88,13 @@ let EdgyBoardElementModel = (() => {
87
88
  getNearestPoint(point) {
88
89
  return polygonNearestPoint(Bound.deserialize(this.xywh).points, point);
89
90
  }
90
- includesPoint(x, y) {
91
- const points = getPointsFromBoundWithRotation(this);
92
- return pointInPolygon([x, y], points);
91
+ /**
92
+ * Picked by its BORDER band: a board is a passive canvas and the clicks over
93
+ * its area belong to what the user laid on it. Same test every framework
94
+ * background runs — see {@link backgroundIncludesPoint}.
95
+ */
96
+ includesPoint(x, y, options) {
97
+ return backgroundIncludesPoint(this, x, y, options);
93
98
  }
94
99
  #resizeEnabled_accessor_storage = __runInitializers(this, _resizeEnabled_initializers, true);
95
100
  get resizeEnabled() { return this.#resizeEnabled_accessor_storage; }
@@ -1,6 +1,6 @@
1
1
  import type { IVec, SerializedXYWH } from '../../../global/gfx/index.js';
2
2
  import { Bound } from '../../../global/gfx/index.js';
3
- import type { BaseElementProps } from '../../../std/gfx/index.js';
3
+ import type { BaseElementProps, PointTestOptions } from '../../../std/gfx/index.js';
4
4
  import { GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
5
5
  export type EdgyFacetsProps = BaseElementProps & {
6
6
  /** When false the resize handles are hidden — toggled from the toolbar. */
@@ -14,7 +14,15 @@ export type EdgyFacetsProps = BaseElementProps & {
14
14
  * margins only exist for the facet name labels — pointless when hidden).
15
15
  */
16
16
  cropToCircles?: boolean;
17
- /** When false the diagram stops granting the hover spotlight. */
17
+ /**
18
+ * INERT since #195 — kept for backward compatibility only.
19
+ *
20
+ * The hover spotlight is board logic: it is granted by the EDGY board
21
+ * (`edgyBoard`), never by this drawing, so nothing reads this field on a
22
+ * facets Venn any more. It stays declared because documents written before
23
+ * the change carry it, and an undeclared property would not survive a load
24
+ * (see the schema red zone in `CLAUDE.md`). Do not read it, do not remove it.
25
+ */
18
26
  spotlightEnabled?: boolean;
19
27
  identityLabel?: string;
20
28
  architectureLabel?: string;
@@ -41,11 +49,20 @@ export declare class EdgyFacetsElementModel extends GfxPrimitiveElementModel<Edg
41
49
  containsBound(bounds: Bound): boolean;
42
50
  getLineIntersections(start: IVec, end: IVec): import("../../../global/gfx/index.js").PointLocation[] | null;
43
51
  getNearestPoint(point: IVec): IVec;
44
- includesPoint(x: number, y: number): boolean;
52
+ /**
53
+ * Picked by its BORDER band — see {@link backgroundIncludesPoint}.
54
+ *
55
+ * The facet LABELS stay double-clickable all the same: their zones are added
56
+ * by `EdgyView.includesPoint`, which is what the pointer router consults, so
57
+ * the rename target lives with the code that draws it and the model layer
58
+ * stays free of it.
59
+ */
60
+ includesPoint(x: number, y: number, options?: PointTestOptions): boolean;
45
61
  accessor resizeEnabled: boolean;
46
62
  accessor showLabels: boolean;
47
63
  accessor showPictos: boolean;
48
64
  accessor cropToCircles: boolean;
65
+ /** Inert — see {@link EdgyFacetsProps.spotlightEnabled} (#195). */
49
66
  accessor spotlightEnabled: boolean;
50
67
  accessor identityLabel: string;
51
68
  accessor architectureLabel: string;
@@ -32,8 +32,9 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
32
32
  }
33
33
  return useValue ? value : void 0;
34
34
  };
35
- import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, pointInPolygon, polygonNearestPoint, } from '../../../global/gfx/index.js';
35
+ import { Bound, getPointsFromBoundWithRotation, linePolygonIntersects, polygonNearestPoint, } from '../../../global/gfx/index.js';
36
36
  import { field, GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
37
+ import { backgroundIncludesPoint } from '../framework-background/index.js';
37
38
  /**
38
39
  * A static "EDGY Enterprise Design Facets" diagram: three overlapping circles
39
40
  * (Identity / Architecture / Experience) with their three pairwise
@@ -123,9 +124,16 @@ let EdgyFacetsElementModel = (() => {
123
124
  getNearestPoint(point) {
124
125
  return polygonNearestPoint(Bound.deserialize(this.xywh).points, point);
125
126
  }
126
- includesPoint(x, y) {
127
- const points = getPointsFromBoundWithRotation(this);
128
- return pointInPolygon([x, y], points);
127
+ /**
128
+ * Picked by its BORDER band — see {@link backgroundIncludesPoint}.
129
+ *
130
+ * The facet LABELS stay double-clickable all the same: their zones are added
131
+ * by `EdgyView.includesPoint`, which is what the pointer router consults, so
132
+ * the rename target lives with the code that draws it and the model layer
133
+ * stays free of it.
134
+ */
135
+ includesPoint(x, y, options) {
136
+ return backgroundIncludesPoint(this, x, y, options);
129
137
  }
130
138
  #resizeEnabled_accessor_storage = __runInitializers(this, _resizeEnabled_initializers, true);
131
139
  get resizeEnabled() { return this.#resizeEnabled_accessor_storage; }
@@ -140,6 +148,7 @@ let EdgyFacetsElementModel = (() => {
140
148
  get cropToCircles() { return this.#cropToCircles_accessor_storage; }
141
149
  set cropToCircles(value) { this.#cropToCircles_accessor_storage = value; }
142
150
  #spotlightEnabled_accessor_storage = (__runInitializers(this, _cropToCircles_extraInitializers), __runInitializers(this, _spotlightEnabled_initializers, true));
151
+ /** Inert — see {@link EdgyFacetsProps.spotlightEnabled} (#195). */
143
152
  get spotlightEnabled() { return this.#spotlightEnabled_accessor_storage; }
144
153
  set spotlightEnabled(value) { this.#spotlightEnabled_accessor_storage = value; }
145
154
  #identityLabel_accessor_storage = (__runInitializers(this, _spotlightEnabled_extraInitializers), __runInitializers(this, _identityLabel_initializers, 'Identity'));
@@ -1,6 +1,6 @@
1
1
  import type { IVec, SerializedXYWH } from '../../../global/gfx/index.js';
2
2
  import { Bound } from '../../../global/gfx/index.js';
3
- import type { BaseElementProps } from '../../../std/gfx/index.js';
3
+ import type { BaseElementProps, PointTestOptions } from '../../../std/gfx/index.js';
4
4
  import { GfxPrimitiveElementModel } from '../../../std/gfx/index.js';
5
5
  export type EstuarineProps = BaseElementProps & {
6
6
  /** When false the resize handles are hidden — toggled from the toolbar. */
@@ -26,7 +26,12 @@ export declare class EstuarineElementModel extends GfxPrimitiveElementModel<Estu
26
26
  containsBound(bounds: Bound): boolean;
27
27
  getLineIntersections(start: IVec, end: IVec): import("../../../global/gfx/index.js").PointLocation[] | null;
28
28
  getNearestPoint(point: IVec): IVec;
29
- includesPoint(x: number, y: number): boolean;
29
+ /**
30
+ * Picked by its BORDER band — see {@link backgroundIncludesPoint}. The map is
31
+ * a space constraint nodes are dropped into, so the clicks inside it are
32
+ * theirs.
33
+ */
34
+ includesPoint(x: number, y: number, options?: PointTestOptions): boolean;
30
35
  accessor resizeEnabled: boolean;
31
36
  accessor showLiminal: boolean;
32
37
  accessor showVolatile: boolean;