@formicoidea/labre-core 0.42.0 → 0.43.1

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 (124) hide show
  1. package/dist/_pkgs/affine-block-data-view/configs/tooltips.js +1 -1
  2. package/dist/_pkgs/affine-block-database/configs/tooltips.js +1 -1
  3. package/dist/_pkgs/affine-block-edgeless-text/edgeless-text-block.js +4 -2
  4. package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.d.ts +39 -0
  5. package/dist/_pkgs/affine-block-embed/common/iframe-sandbox.js +39 -0
  6. package/dist/_pkgs/affine-block-embed/embed-figma-block/embed-figma-block.js +2 -0
  7. package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.d.ts +14 -1
  8. package/dist/_pkgs/affine-block-embed/embed-iframe-block/components/embed-iframe-error-card.js +21 -2
  9. package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.d.ts +0 -2
  10. package/dist/_pkgs/affine-block-embed/embed-iframe-block/consts.js +2 -5
  11. package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.d.ts +1 -1
  12. package/dist/_pkgs/affine-block-embed/embed-iframe-block/embed-iframe-block.js +14 -6
  13. package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.d.ts +16 -0
  14. package/dist/_pkgs/affine-block-embed/embed-iframe-block/types.js +17 -1
  15. package/dist/_pkgs/affine-block-embed/embed-loom-block/embed-loom-block.js +2 -0
  16. package/dist/_pkgs/affine-block-embed/embed-youtube-block/embed-youtube-block.js +2 -0
  17. package/dist/_pkgs/affine-block-embed/index.d.ts +1 -0
  18. package/dist/_pkgs/affine-block-embed/index.js +1 -0
  19. package/dist/_pkgs/affine-block-embed/translations.d.ts +8 -0
  20. package/dist/_pkgs/affine-block-embed/translations.js +28 -0
  21. package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/embed-linked-doc-block.js +4 -2
  22. package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/embed-synced-doc-block.js +2 -2
  23. package/dist/_pkgs/affine-block-frame/frame-manager.js +5 -2
  24. package/dist/_pkgs/affine-block-list/utils/get-list-icon.js +3 -1
  25. package/dist/_pkgs/affine-block-note/configs/tooltips.js +1 -1
  26. package/dist/_pkgs/affine-block-root/adapters/html.js +2 -2
  27. package/dist/_pkgs/affine-block-root/commands/copy-link-commands.d.ts +2 -0
  28. package/dist/_pkgs/affine-block-root/commands/copy-link-commands.js +155 -0
  29. package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
  30. package/dist/_pkgs/affine-block-root/index.js +1 -0
  31. package/dist/_pkgs/affine-block-root/view.js +2 -0
  32. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +13 -1
  33. package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +8 -0
  34. package/dist/_pkgs/affine-block-surface/extensions/legend.js +59 -3
  35. package/dist/_pkgs/affine-block-surface/extensions/morph-toolbar.js +4 -0
  36. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.d.ts +3 -0
  37. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.js +23 -0
  38. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +1 -1
  39. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +12 -4
  40. package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +1 -1
  41. package/dist/_pkgs/affine-block-surface/framework-background/fit.d.ts +36 -0
  42. package/dist/_pkgs/affine-block-surface/framework-background/fit.js +30 -0
  43. package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +1 -0
  44. package/dist/_pkgs/affine-block-surface/framework-background/index.js +1 -0
  45. package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +2 -7
  46. package/dist/_pkgs/affine-block-surface-ref/configs/tooltips.js +2 -2
  47. package/dist/_pkgs/affine-components/color-picker/palette-carousel.js +5 -0
  48. package/dist/_pkgs/affine-components/color-picker/styles.js +1 -1
  49. package/dist/_pkgs/affine-components/context-menu/button.js +3 -1
  50. package/dist/_pkgs/affine-components/icons/ai.js +3 -3
  51. package/dist/_pkgs/affine-components/icons/list.js +7 -1
  52. package/dist/_pkgs/affine-components/size-dropdown-menu/dropdown-menu.js +6 -1
  53. package/dist/_pkgs/affine-components/toolbar/index.d.ts +1 -1
  54. package/dist/_pkgs/affine-components/toolbar/index.js +1 -1
  55. package/dist/_pkgs/affine-components/toolbar/menu-button.d.ts +7 -0
  56. package/dist/_pkgs/affine-components/toolbar/menu-button.js +30 -0
  57. package/dist/_pkgs/affine-components/toolbar/picker-menu.d.ts +16 -1
  58. package/dist/_pkgs/affine-components/toolbar/picker-menu.js +2 -2
  59. package/dist/_pkgs/affine-components/toolbar/toolbar.d.ts +1 -0
  60. package/dist/_pkgs/affine-components/toolbar/toolbar.js +67 -0
  61. package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card-title-editor.js +1 -1
  62. package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +1 -1
  63. package/dist/_pkgs/affine-gfx-brush/toolbar/components/eraser/icons.js +1 -1
  64. package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.d.ts +11 -2
  65. package/dist/_pkgs/affine-gfx-connector/direction/direction-reveal.js +11 -2
  66. package/dist/_pkgs/affine-gfx-connector/text/edgeless-connector-label-editor.js +3 -2
  67. package/dist/_pkgs/affine-gfx-connector/toolbar/config.js +23 -7
  68. package/dist/_pkgs/affine-gfx-connector/translations.d.ts +3 -0
  69. package/dist/_pkgs/affine-gfx-connector/translations.js +23 -0
  70. package/dist/_pkgs/affine-gfx-mindmap/indicator-overlay/index.js +6 -2
  71. package/dist/_pkgs/affine-gfx-mindmap/toolbar/config.js +4 -2
  72. package/dist/_pkgs/affine-gfx-mindmap/translations.d.ts +6 -0
  73. package/dist/_pkgs/affine-gfx-mindmap/translations.js +10 -0
  74. package/dist/_pkgs/affine-gfx-shape/toolbar/config.js +4 -2
  75. package/dist/_pkgs/affine-gfx-shape/translations.d.ts +7 -0
  76. package/dist/_pkgs/affine-gfx-shape/translations.js +11 -0
  77. package/dist/_pkgs/affine-gfx-template/builtin/other.js +13 -7
  78. package/dist/_pkgs/affine-gfx-template/toolbar/template-loading.js +1 -1
  79. package/dist/_pkgs/affine-gfx-template/translations.d.ts +5 -0
  80. package/dist/_pkgs/affine-gfx-template/translations.js +38 -0
  81. package/dist/_pkgs/affine-gfx-text/edgeless-text-editor.js +3 -2
  82. package/dist/_pkgs/affine-gfx-text/toolbar/actions.js +3 -1
  83. package/dist/_pkgs/affine-gfx-text/translations.d.ts +8 -0
  84. package/dist/_pkgs/affine-gfx-text/translations.js +12 -0
  85. package/dist/_pkgs/affine-inline-latex/latex-node/latex-editor-menu.js +2 -1
  86. package/dist/_pkgs/affine-model/consts/text.d.ts +15 -2
  87. package/dist/_pkgs/affine-model/consts/text.js +25 -1
  88. package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +13 -2
  89. package/dist/_pkgs/affine-shared/services/font-loader/config.js +43 -54
  90. package/dist/_pkgs/affine-shared/services/theme-service.d.ts +19 -0
  91. package/dist/_pkgs/affine-shared/services/theme-service.js +24 -0
  92. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +20 -0
  93. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +81 -0
  94. package/dist/_pkgs/affine-widget-edgeless-dragging-area/edgeless-dragging-area-rect.js +2 -2
  95. package/dist/_pkgs/affine-widget-edgeless-selected-rect/utils.js +5 -1
  96. package/dist/_pkgs/affine-widget-edgeless-toolbar/config/types.d.ts +15 -0
  97. package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.d.ts +1 -1
  98. package/dist/_pkgs/affine-widget-edgeless-toolbar/config/utils.js +7 -2
  99. package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.d.ts +18 -0
  100. package/dist/_pkgs/affine-widget-edgeless-toolbar/panel/font-family-panel.js +52 -6
  101. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.d.ts +6 -0
  102. package/dist/_pkgs/affine-widget-edgeless-toolbar/translations.js +10 -0
  103. package/dist/_pkgs/affine-widget-frame-title/edgeless-frame-title-editor.js +2 -1
  104. package/dist/_pkgs/affine-widget-slash-menu/translations.d.ts +16 -0
  105. package/dist/_pkgs/affine-widget-slash-menu/translations.js +23 -1
  106. package/dist/_pkgs/affine-widget-toolbar/utils.js +57 -14
  107. package/dist/_pkgs/data-view/core/detail/field.js +2 -1
  108. package/dist/_pkgs/data-view/core/filter/literal/define.js +3 -1
  109. package/dist/_pkgs/data-view/core/group-by/renderer/boolean-group.js +1 -1
  110. package/dist/_pkgs/data-view/property-presets/checkbox/cell-renderer.js +8 -2
  111. package/dist/_pkgs/data-view/view-presets/kanban/pc/cell.js +1 -1
  112. package/dist/_pkgs/data-view/view-presets/kanban/pc/controller/drag.js +2 -1
  113. package/dist/_pkgs/data-view/view-presets/table/pc/controller/drag.js +2 -1
  114. package/dist/_pkgs/data-view/view-presets/table/pc/controller/selection.js +1 -1
  115. package/dist/_pkgs/data-view/view-presets/table/pc/header/vertical-indicator.js +2 -1
  116. package/dist/_pkgs/data-view/view-presets/table/pc/row/row-select-checkbox.js +3 -1
  117. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/drag.js +2 -1
  118. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/selection.js +1 -1
  119. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/header/vertical-indicator.js +2 -1
  120. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/row-header.js +3 -1
  121. package/dist/_pkgs/std/gfx/model/surface/role.d.ts +10 -5
  122. package/dist/commands.js +2 -1
  123. package/dist/translations.js +5 -0
  124. package/package.json +5 -1
@@ -1,3 +1,9 @@
1
+ /**
2
+ * The chrome accent, reached through its token rather than written as a hex:
3
+ * the six-dot burst is chrome, so it has to follow the host's theme (DESIGN.md,
4
+ * The Borrowed Blue Rule).
5
+ */
6
+ const ACCENT = 'var(--affine-primary-color)';
1
7
  export const playCheckAnimation = async (refElement, { left = 0, size = 20 } = {}) => {
2
8
  const sparkingEl = document.createElement('div');
3
9
  sparkingEl.classList.add('affine-check-animation');
@@ -14,7 +20,7 @@ export const playCheckAnimation = async (refElement, { left = 0, size = 20 } = {
14
20
  refElement.append(sparkingEl);
15
21
  await sparkingEl.animate([
16
22
  {
17
- boxShadow: '0 -18px 0 -8px #1e96eb, 16px -8px 0 -8px #1e96eb, 16px 8px 0 -8px #1e96eb, 0 18px 0 -8px #1e96eb, -16px 8px 0 -8px #1e96eb, -16px -8px 0 -8px #1e96eb',
23
+ boxShadow: `0 -18px 0 -8px ${ACCENT}, 16px -8px 0 -8px ${ACCENT}, 16px 8px 0 -8px ${ACCENT}, 0 18px 0 -8px ${ACCENT}, -16px 8px 0 -8px ${ACCENT}, -16px -8px 0 -8px ${ACCENT}`,
18
24
  },
19
25
  ], { duration: 240, easing: 'ease', fill: 'forwards' }).finished;
20
26
  await sparkingEl.animate([
@@ -218,9 +218,14 @@ let SizeDropdownMenu = (() => {
218
218
  const { sizes, format, type, icon, resolvedLabel: label, size$: { value: size }, } = this;
219
219
  const isCheckType = type === 'check';
220
220
  const placeholder = format?.(Math.trunc(size)) ?? Math.trunc(size);
221
+ // `class` is STATIC. It used to be `${label.toLowerCase()}-menu`, which
222
+ // made a CSS class depend on the host's language the day `label` joined
223
+ // the translation seam (#390) — `échelle-menu` in French. Nothing in the
224
+ // repo selects it (checked across the styles and both test suites): it is
225
+ // the stable identifier it was always meant to be.
221
226
  return html `
222
227
  <editor-menu-button
223
- class="${`${label.toLowerCase()}-menu`}"
228
+ class="size-menu"
224
229
  .contentPadding="${'8px'}"
225
230
  .button=${html `
226
231
  <editor-icon-button
@@ -1,7 +1,7 @@
1
1
  export { EditorChevronDown } from './chevron-down.js';
2
2
  export { ToolbarMoreMenuConfigExtension } from './config.js';
3
3
  export { EditorIconButton } from './icon-button.js';
4
- export { EditorMenuAction, EditorMenuButton, EditorMenuContent, } from './menu-button.js';
4
+ export { EDITOR_MENU_TOGGLE, EditorMenuAction, EditorMenuButton, EditorMenuContent, } from './menu-button.js';
5
5
  export { MenuContext } from './menu-context.js';
6
6
  export { type PickerMenu, type PickerMenuItem, renderCurrentPickerItemWith, renderPickerMenu, renderPickerMenuItems, } from './picker-menu.js';
7
7
  export { EditorToolbarSeparator } from './separator.js';
@@ -6,7 +6,7 @@ import { Tooltip } from './tooltip.js';
6
6
  export { EditorChevronDown } from './chevron-down.js';
7
7
  export { ToolbarMoreMenuConfigExtension } from './config.js';
8
8
  export { EditorIconButton } from './icon-button.js';
9
- export { EditorMenuAction, EditorMenuButton, EditorMenuContent, } from './menu-button.js';
9
+ export { EDITOR_MENU_TOGGLE, EditorMenuAction, EditorMenuButton, EditorMenuContent, } from './menu-button.js';
10
10
  export { MenuContext } from './menu-context.js';
11
11
  export { renderCurrentPickerItemWith, renderPickerMenu, renderPickerMenuItems, } from './picker-menu.js';
12
12
  export { EditorToolbarSeparator } from './separator.js';
@@ -1,5 +1,12 @@
1
1
  import { type ButtonPopperOptions } from '../../affine-shared/utils/index.js';
2
2
  import { LitElement, type PropertyValues, type TemplateResult } from 'lit';
3
+ /**
4
+ * A panel in a toolbar opened or closed, announced across shadow boundaries.
5
+ *
6
+ * `detail` is whether it is now open, and the deepest element of
7
+ * `composedPath()` is the button it belongs to.
8
+ */
9
+ export declare const EDITOR_MENU_TOGGLE = "editor-menu-toggle";
3
10
  declare const EditorMenuButton_base: typeof LitElement & import("../../global/utils/types.js").Constructor<import("../../global/lit/with-disposable.js").DisposableClass>;
4
11
  export declare class EditorMenuButton extends EditorMenuButton_base {
5
12
  static styles: import("lit").CSSResult;
@@ -37,6 +37,13 @@ import { createButtonPopper, } from '../../affine-shared/utils/index.js';
37
37
  import { WithDisposable } from '../../global/lit/index.js';
38
38
  import { css, html, LitElement, } from 'lit';
39
39
  import { property, query } from 'lit/decorators.js';
40
+ /**
41
+ * A panel in a toolbar opened or closed, announced across shadow boundaries.
42
+ *
43
+ * `detail` is whether it is now open, and the deepest element of
44
+ * `composedPath()` is the button it belongs to.
45
+ */
46
+ export const EDITOR_MENU_TOGGLE = 'editor-menu-toggle';
40
47
  let EditorMenuButton = (() => {
41
48
  let _classSuper = WithDisposable(LitElement);
42
49
  let __content_decorators;
@@ -97,6 +104,20 @@ let EditorMenuButton = (() => {
97
104
  else {
98
105
  delete this.dataset.open;
99
106
  }
107
+ // Said again, out loud, for whoever is holding this button — the row
108
+ // it sits on has to know, and `data-open` alone cannot tell it: a
109
+ // picker keeps its menu button inside its OWN shadow root, where no
110
+ // `querySelector` and no `MutationObserver` of the row's reaches. This
111
+ // one bubbles AND is composed, so it crosses every boundary between
112
+ // here and the row. See `EditorToolbar`, which stops clipping while a
113
+ // panel is open. The `toggle` event above is deliberately left as it
114
+ // is: it does not bubble, and things listen for it by that name.
115
+ this.dispatchEvent(new CustomEvent(EDITOR_MENU_TOGGLE, {
116
+ detail: opened,
117
+ bubbles: true,
118
+ cancelable: false,
119
+ composed: true,
120
+ }));
100
121
  },
101
122
  mainAxis: 0,
102
123
  offsetHeight: 6 * 4,
@@ -184,6 +205,15 @@ export class EditorMenuContent extends LitElement {
184
205
  .content-wrapper {
185
206
  overscroll-behavior: contain;
186
207
  overflow-y: auto;
208
+ /* Spelled out because CSS Overflow computes a visible axis to auto as
209
+ * soon as the other one is not visible: the overflow-y above would
210
+ * silently make this popup scrollable SIDEWAYS too. Anything animated by
211
+ * a positive translateX inside it — the palette carousel's incoming page,
212
+ * see color-picker/palette-carousel.ts — then grows the scrollable
213
+ * region for the length of the animation and flashes a horizontal
214
+ * scrollbar (issue #392). Not clip: combined with overflow-y: auto the
215
+ * spec falls it back to hidden anyway. */
216
+ overflow-x: hidden;
187
217
  padding: var(--content-padding, 0 6px);
188
218
  }
189
219
 
@@ -38,6 +38,21 @@ export type PickerMenu<T> = {
38
38
  label: string;
39
39
  icon?: TemplateResult;
40
40
  tooltip?: string;
41
+ /**
42
+ * The accessible name of the MENU shell (`aria-label` on
43
+ * `editor-menu-button`), which the caller supplies whole (#390).
44
+ *
45
+ * It used to be sewn together here as `` `${label.toLowerCase()}-menu` ``.
46
+ * That was a stable identifier while {@link label} was an English literal;
47
+ * once the caller started handing over a TRANSLATED label it became half a
48
+ * sentence in each language ("changer le type de forme-menu"). A menu's
49
+ * accessible name is its own wording, never a composition — the precedent
50
+ * is `ROOT_ALIGNMENT_MENU_ARIA` in `blocks/root`.
51
+ *
52
+ * Left out, the name is composed from {@link label} as before, so a caller
53
+ * that still passes an English literal is unaffected.
54
+ */
55
+ menuAria?: string;
41
56
  items: PickerMenuItem<T>[];
42
57
  currentValue: T;
43
58
  onPick: (value: T) => void;
@@ -51,5 +66,5 @@ export type PickerMenu<T> = {
51
66
  };
52
67
  /** The field of the item that currently matches — its icon, usually. */
53
68
  export declare function renderCurrentPickerItemWith<T, F extends keyof PickerMenuItem<T>>(items: PickerMenuItem<T>[], currentValue: T, field: F): PickerMenuItem<T>[F] | undefined;
54
- export declare function renderPickerMenu<T>({ label, tooltip, icon, items, currentValue, onPick, testId, }: PickerMenu<T>): TemplateResult<1>;
69
+ export declare function renderPickerMenu<T>({ label, tooltip, menuAria, icon, items, currentValue, onPick, testId, }: PickerMenu<T>): TemplateResult<1>;
55
70
  export declare function renderPickerMenuItems<T>(items: PickerMenuItem<T>[], currentValue: T, onPick: (value: T) => void, testId?: string): unknown;
@@ -6,11 +6,11 @@ import { EditorChevronDown } from './chevron-down.js';
6
6
  export function renderCurrentPickerItemWith(items, currentValue, field) {
7
7
  return items.find(({ value }) => value === currentValue)?.[field];
8
8
  }
9
- export function renderPickerMenu({ label, tooltip, icon, items, currentValue, onPick, testId, }) {
9
+ export function renderPickerMenu({ label, tooltip, menuAria, icon, items, currentValue, onPick, testId, }) {
10
10
  return html `
11
11
  <editor-menu-button
12
12
  data-testid=${ifDefined(testId)}
13
- aria-label="${`${label.toLowerCase()}-menu`}"
13
+ aria-label="${menuAria ?? `${label.toLowerCase()}-menu`}"
14
14
  .button=${html `
15
15
  <editor-icon-button
16
16
  data-testid=${ifDefined(testId ? `${testId}-button` : undefined)}
@@ -1,6 +1,7 @@
1
1
  import { LitElement } from 'lit';
2
2
  declare const EditorToolbar_base: typeof LitElement & import("../../global/utils/types.js").Constructor<import("../../global/lit/with-disposable.js").DisposableClass>;
3
3
  export declare class EditorToolbar extends EditorToolbar_base {
4
+ #private;
4
5
  static styles: import("lit").CSSResult;
5
6
  connectedCallback(): void;
6
7
  render(): import("lit-html").TemplateResult<1>;
@@ -2,6 +2,7 @@ import { panelBaseStyle } from '../../affine-shared/styles/index.js';
2
2
  import { stopPropagation } from '../../affine-shared/utils/index.js';
3
3
  import { WithDisposable } from '../../global/lit/index.js';
4
4
  import { css, html, LitElement } from 'lit';
5
+ import { EDITOR_MENU_TOGGLE } from './menu-button.js';
5
6
  export class EditorToolbar extends WithDisposable(LitElement) {
6
7
  static { this.styles = css `
7
8
  ${panelBaseStyle(':host')}
@@ -13,6 +14,27 @@ export class EditorToolbar extends WithDisposable(LitElement) {
13
14
  height: 36px;
14
15
  box-sizing: content-box;
15
16
  flex-wrap: nowrap;
17
+ /* And never outside its own background. The row's width is a max-width
18
+ the positioner writes; entries keep their natural width (below), so a
19
+ row that has nothing left to give up would otherwise paint its last
20
+ icons over the document, past the border and the shadow — which is
21
+ what a 420px window used to show.
22
+
23
+ Clipped on the X axis alone: overflow-x hidden would make the row a
24
+ scroll container on BOTH axes (a visible paired with a hidden computes
25
+ to auto) and swallow the dropdown panels, which are positioned inside
26
+ the row and hang above and below it. */
27
+ overflow-x: clip;
28
+ overflow-y: visible;
29
+ }
30
+
31
+ /* ...except while one of those panels is open. A clipping box is also what
32
+ floating-ui fits a panel into, so left in place the rule above would
33
+ squeeze a 176px menu into the width of the row that opened it — or, for
34
+ a dropdown at one end of the row, cut half of it off. See
35
+ syncOpenMenus below, which is what raises this attribute. */
36
+ :host([data-menu-open]) {
37
+ overflow: visible;
16
38
  }
17
39
 
18
40
  :host([data-without-bg]) {
@@ -35,6 +57,38 @@ export class EditorToolbar extends WithDisposable(LitElement) {
35
57
  fill: currentColor;
36
58
  }
37
59
  `; }
60
+ /** The panels open in this row right now, whatever opened them. */
61
+ #openMenus = new Set();
62
+ /**
63
+ * Says, on the row itself, whether one of its panels is open.
64
+ *
65
+ * Why an attribute at all: the row cannot ask the question in CSS. `:host()`
66
+ * takes a COMPOUND selector and `:has()` is not one, so
67
+ * `:host(:has([data-open]))` is not a rule browsers honour (Chromium
68
+ * 2026-09: it matches from the document, never from inside the shadow root).
69
+ *
70
+ * Why not a `querySelector` for `data-open`, which the buttons do raise:
71
+ * because it answers only for the buttons the row holds DIRECTLY. A colour
72
+ * picker keeps its menu button inside its own shadow root, where neither a
73
+ * `querySelector` nor a `MutationObserver` of this row can see it — and that
74
+ * is the row whose panel the clip was cutting in half
75
+ * (`framework-palette-carousel.spec.ts`). {@link EDITOR_MENU_TOGGLE} is
76
+ * composed, so it crosses every boundary, and it is raised before the panel
77
+ * is ever positioned.
78
+ *
79
+ * A panel whose button is taken off the row by a re-render never says it
80
+ * closed, so the set is swept of anything no longer in a document.
81
+ */
82
+ #syncOpenMenus() {
83
+ for (const menu of this.#openMenus) {
84
+ if (!menu.isConnected)
85
+ this.#openMenus.delete(menu);
86
+ }
87
+ if (this.#openMenus.size > 0)
88
+ this.dataset.menuOpen = 'true';
89
+ else
90
+ delete this.dataset.menuOpen;
91
+ }
38
92
  connectedCallback() {
39
93
  super.connectedCallback();
40
94
  this._disposables.addFromEvent(this, 'pointerdown', (e) => {
@@ -44,6 +98,19 @@ export class EditorToolbar extends WithDisposable(LitElement) {
44
98
  this._disposables.addFromEvent(this, 'wheel', stopPropagation, {
45
99
  passive: false,
46
100
  });
101
+ this._disposables.addFromEvent(this, EDITOR_MENU_TOGGLE, (e) => {
102
+ // The deepest element of the path, not `target`: a composed event that
103
+ // crosses a shadow boundary is retargeted to the host it came out of,
104
+ // and one host may hold more than one panel.
105
+ const menu = e.composedPath()[0];
106
+ if (!(menu instanceof Element))
107
+ return;
108
+ if (e.detail)
109
+ this.#openMenus.add(menu);
110
+ else
111
+ this.#openMenus.delete(menu);
112
+ this.#syncOpenMenus();
113
+ });
47
114
  }
48
115
  render() {
49
116
  return html `<slot></slot>`;
@@ -138,7 +138,7 @@ let FrameCardTitleEditor = (() => {
138
138
  background: 'var(--affine-background-primary-color)',
139
139
  border: '1px solid var(--affine-primary-color)',
140
140
  color: 'var(--affine-text-primary-color)',
141
- boxShadow: '0px 0px 0px 2px rgba(30, 150, 235, 0.30)',
141
+ boxShadow: '0px 0px 0px 2px color-mix(in srgb, var(--affine-primary-color) 30%, transparent)',
142
142
  zIndex: '1',
143
143
  display: 'block',
144
144
  });
@@ -69,7 +69,7 @@ const styles = css `
69
69
  }
70
70
 
71
71
  .frame-card-container.selected .frame-card-body {
72
- border: 2px solid var(--light-brand-color, #1e96eb);
72
+ border: 2px solid var(--affine-primary-color);
73
73
  }
74
74
 
75
75
  .frame-card-container.dragging {
@@ -45,7 +45,7 @@ export const EdgelessEraserLightIcon = html `<svg
45
45
  />
46
46
  <path
47
47
  d="M27.5 16.5H33H34.6295C35.2048 16.5 35.706 16.8921 35.8443 17.4505L35.8583 17.5067C36.0615 18.3269 36.7242 18.9534 37.5545 19.1105C38.1029 19.2142 38.5 19.6934 38.5 20.2516V21.75V27.5V39V61.5H27.5V16.5Z"
48
- fill="#1E96EB"
48
+ fill="var(--affine-primary-color)"
49
49
  />
50
50
  <path
51
51
  d="M27.5 16.5H33H34.6295C35.2048 16.5 35.706 16.8921 35.8443 17.4505L35.8583 17.5067C36.0615 18.3269 36.7242 18.9534 37.5545 19.1105C38.1029 19.2142 38.5 19.6934 38.5 20.2516V21.75V27.5V39V61.5H27.5V16.5Z"
@@ -41,11 +41,20 @@ import { type TypedEdge } from './typed-edge.js';
41
41
  * a `@local()` field. The reveal is session state and leaves with the pointer.
42
42
  */
43
43
  /**
44
- * The one colour the reveal is drawn in — the house primary, i.e. the colour of
44
+ * The one colour the reveal is drawn in — the chrome accent, i.e. the colour of
45
45
  * an affordance rather than of ink. Deliberately NOT the framework's palette:
46
46
  * the label is the tool talking about the drawing, not part of the drawing.
47
+ *
48
+ * A TOKEN, not a hex: the chip is rendered in the DOM (`direction-widget.ts`),
49
+ * so it follows whatever the host sets `--affine-primary-color` to. The accent
50
+ * is AFFiNE's and due to be replaced — DESIGN.md, The Borrowed Blue Rule.
51
+ *
52
+ * It is the colour of EVERY typed edge of every framework: no role declares a
53
+ * `chipColor` any more (PO recette of 23/09/2026, after one that did produced
54
+ * two blues on one map). `affine/all/src/__tests__/direction-chip-accent.unit.spec.ts`
55
+ * reads the mounted vocabularies and keeps it that way.
47
56
  */
48
- export declare const EDGE_DIRECTION_COLOR = "#1e96eb";
57
+ export declare const EDGE_DIRECTION_COLOR = "var(--affine-primary-color)";
49
58
  /**
50
59
  * Where the label sits on a typed edge, and how it is turned.
51
60
  *
@@ -40,11 +40,20 @@ import { asTypedEdge, edgeIsBound, roleVocabularies, } from './typed-edge.js';
40
40
  * a `@local()` field. The reveal is session state and leaves with the pointer.
41
41
  */
42
42
  /**
43
- * The one colour the reveal is drawn in — the house primary, i.e. the colour of
43
+ * The one colour the reveal is drawn in — the chrome accent, i.e. the colour of
44
44
  * an affordance rather than of ink. Deliberately NOT the framework's palette:
45
45
  * the label is the tool talking about the drawing, not part of the drawing.
46
+ *
47
+ * A TOKEN, not a hex: the chip is rendered in the DOM (`direction-widget.ts`),
48
+ * so it follows whatever the host sets `--affine-primary-color` to. The accent
49
+ * is AFFiNE's and due to be replaced — DESIGN.md, The Borrowed Blue Rule.
50
+ *
51
+ * It is the colour of EVERY typed edge of every framework: no role declares a
52
+ * `chipColor` any more (PO recette of 23/09/2026, after one that did produced
53
+ * two blues on one map). `affine/all/src/__tests__/direction-chip-accent.unit.spec.ts`
54
+ * reads the mounted vocabularies and keeps it that way.
46
55
  */
47
- export const EDGE_DIRECTION_COLOR = '#1e96eb';
56
+ export const EDGE_DIRECTION_COLOR = 'var(--affine-primary-color)';
48
57
  const pathOf = (model) => {
49
58
  const path = model.absolutePath;
50
59
  return Array.isArray(path) && path.length >= 2 ? path : null;
@@ -245,10 +245,11 @@ let EdgelessConnectorLabelEditor = (() => {
245
245
  transform-origin: center;
246
246
  z-index: 10;
247
247
  padding: ${VERTICAL_PADDING}px ${HORIZONTAL_PADDING}px;
248
- border: ${BORDER_WIDTH}px solid var(--affine-primary-color, #1e96eb);
248
+ border: ${BORDER_WIDTH}px solid var(--affine-primary-color);
249
249
  background: var(--affine-background-primary-color, #fff);
250
250
  border-radius: 2px;
251
- box-shadow: 0px 0px 0px 2px rgba(30, 150, 235, 0.3);
251
+ box-shadow: 0px 0px 0px 2px
252
+ color-mix(in srgb, var(--affine-primary-color) 30%, transparent);
252
253
  box-sizing: border-box;
253
254
  overflow: visible;
254
255
 
@@ -2,7 +2,7 @@ import { EdgelessCRUDIdentifier } from '../../affine-block-surface/index.js';
2
2
  import { frameworkPaletteGroups, packColor, } from '../../affine-components/color-picker/index.js';
3
3
  import { createTextActions, normalizeTextBound } from '../../affine-gfx-text/index.js';
4
4
  import { ConnectorElementModel, ConnectorMode, DEFAULT_FRONT_ENDPOINT_STYLE, DEFAULT_REAR_ENDPOINT_STYLE, DefaultTheme, LineWidth, PointStyle, resolveColor, StrokeStyle, } from '../../affine-model/index.js';
5
- import { CONNECTOR_SOURCE_LABEL, CONNECTOR_TARGET_LABEL, ToolbarModuleExtension, translateKey, } from '../../affine-shared/services/index.js';
5
+ import { CONNECTOR_SOURCE_LABEL, CONNECTOR_TARGET_LABEL, MENU_ARIA_STYLE, ToolbarModuleExtension, translateKey, } from '../../affine-shared/services/index.js';
6
6
  import { getMostCommonResolvedValue, getMostCommonValue, } from '../../affine-shared/utils/index.js';
7
7
  import { getRootBlock, LINE_STYLE_LIST, renderMenu, } from '../../affine-widget-edgeless-toolbar/index.js';
8
8
  import { Bound } from '../../global/gfx/index.js';
@@ -15,7 +15,7 @@ import { INVERT_EDGE_DIRECTION, invertEdgeDirection, } from '../direction/invert
15
15
  import { asTypedEdge, edgeIsBound, roleVocabularies, } from '../direction/typed-edge.js';
16
16
  import { mountConnectorLabelEditor } from '../text/index.js';
17
17
  import { EndPointDiamondHollowIcon, EndPointTriangleHollowIcon, StartPointDiamondHollowIcon, StartPointTriangleHollowIcon, } from './hollow-endpoint-icons.js';
18
- import { CONNECTOR_ADD_TEXT, CONNECTOR_LABEL_END_POINT_STYLE, CONNECTOR_LABEL_SHAPE, CONNECTOR_LABEL_START_POINT_STYLE, CONNECTOR_LABEL_STROKE_STYLE, CONNECTOR_LABEL_STYLE, CONNECTOR_MODE_WORDING, CONNECTOR_TOOLTIP_CONNECTOR_SHAPE, CONNECTOR_TOOLTIP_FLIP_DIRECTION, } from '../translations.js';
18
+ import { CONNECTOR_ADD_TEXT, CONNECTOR_END_POINT_STYLE_MENU_ARIA, CONNECTOR_LABEL_END_POINT_STYLE, CONNECTOR_LABEL_SHAPE, CONNECTOR_LABEL_START_POINT_STYLE, CONNECTOR_LABEL_STROKE_STYLE, CONNECTOR_LABEL_STYLE, CONNECTOR_MODE_WORDING, CONNECTOR_SHAPE_MENU_ARIA, CONNECTOR_START_POINT_STYLE_MENU_ARIA, CONNECTOR_TOOLTIP_CONNECTOR_SHAPE, CONNECTOR_TOOLTIP_FLIP_DIRECTION, } from '../translations.js';
19
19
  /**
20
20
  * Every `PointStyle` must appear in BOTH lists.
21
21
  *
@@ -204,10 +204,16 @@ export const connectorToolbarConfig = {
204
204
  updateModelsWith(ctx, models, field, value);
205
205
  };
206
206
  return renderMenu({
207
- label: translateKey(ctx.std, ...CONNECTOR_LABEL_STYLE),
207
+ // `label` stays the ENGLISH literal and `labelWording` carries the
208
+ // key: `renderMenu` resolves it, and the menu shell's accessible
209
+ // name no longer has to be sewn onto a translated word (#390).
210
+ label: CONNECTOR_LABEL_STYLE[1],
211
+ labelWording: CONNECTOR_LABEL_STYLE,
212
+ menuAriaWording: MENU_ARIA_STYLE,
208
213
  items: LINE_STYLE_LIST,
209
214
  currentValue: rough,
210
215
  onPick,
216
+ std: ctx.std,
211
217
  });
212
218
  },
213
219
  },
@@ -226,10 +232,13 @@ export const connectorToolbarConfig = {
226
232
  updateModelsWith(ctx, models, field, value);
227
233
  };
228
234
  return renderMenu({
229
- label: translateKey(ctx.std, ...CONNECTOR_LABEL_START_POINT_STYLE),
235
+ label: CONNECTOR_LABEL_START_POINT_STYLE[1],
236
+ labelWording: CONNECTOR_LABEL_START_POINT_STYLE,
237
+ menuAriaWording: CONNECTOR_START_POINT_STYLE_MENU_ARIA,
230
238
  items: FRONT_ENDPOINT_STYLE_LIST,
231
239
  currentValue: pointStyle,
232
240
  onPick,
241
+ std: ctx.std,
233
242
  });
234
243
  },
235
244
  },
@@ -293,10 +302,13 @@ export const connectorToolbarConfig = {
293
302
  updateModelsWith(ctx, models, field, value);
294
303
  };
295
304
  return renderMenu({
296
- label: translateKey(ctx.std, ...CONNECTOR_LABEL_END_POINT_STYLE),
305
+ label: CONNECTOR_LABEL_END_POINT_STYLE[1],
306
+ labelWording: CONNECTOR_LABEL_END_POINT_STYLE,
307
+ menuAriaWording: CONNECTOR_END_POINT_STYLE_MENU_ARIA,
297
308
  items: REAR_ENDPOINT_STYLE_LIST,
298
309
  currentValue: pointStyle,
299
310
  onPick,
311
+ std: ctx.std,
300
312
  });
301
313
  },
302
314
  },
@@ -361,11 +373,15 @@ export const connectorToolbarConfig = {
361
373
  key: translateKey(ctx.std, ...CONNECTOR_MODE_WORDING[item.value]),
362
374
  }));
363
375
  return renderMenu({
364
- label: translateKey(ctx.std, ...CONNECTOR_LABEL_SHAPE),
365
- tooltip: translateKey(ctx.std, ...CONNECTOR_TOOLTIP_CONNECTOR_SHAPE),
376
+ label: CONNECTOR_LABEL_SHAPE[1],
377
+ labelWording: CONNECTOR_LABEL_SHAPE,
378
+ menuAriaWording: CONNECTOR_SHAPE_MENU_ARIA,
379
+ tooltip: CONNECTOR_TOOLTIP_CONNECTOR_SHAPE[1],
380
+ tooltipWording: CONNECTOR_TOOLTIP_CONNECTOR_SHAPE,
366
381
  items,
367
382
  currentValue: mode,
368
383
  onPick,
384
+ std: ctx.std,
369
385
  });
370
386
  },
371
387
  },
@@ -20,9 +20,12 @@ export declare const CONNECTOR_LABEL_CONNECTOR: ChromeWording;
20
20
  export declare const CONNECTOR_LABEL_STROKE_STYLE: ChromeWording;
21
21
  export declare const CONNECTOR_LABEL_STYLE: ChromeWording;
22
22
  export declare const CONNECTOR_LABEL_START_POINT_STYLE: ChromeWording;
23
+ export declare const CONNECTOR_START_POINT_STYLE_MENU_ARIA: ChromeWording;
23
24
  export declare const CONNECTOR_TOOLTIP_FLIP_DIRECTION: ChromeWording;
24
25
  export declare const CONNECTOR_LABEL_END_POINT_STYLE: ChromeWording;
26
+ export declare const CONNECTOR_END_POINT_STYLE_MENU_ARIA: ChromeWording;
25
27
  export declare const CONNECTOR_LABEL_SHAPE: ChromeWording;
28
+ export declare const CONNECTOR_SHAPE_MENU_ARIA: ChromeWording;
26
29
  export declare const CONNECTOR_TOOLTIP_CONNECTOR_SHAPE: ChromeWording;
27
30
  /**
28
31
  * "Add text" — the contextual-toolbar action AND the label editor's own
@@ -44,6 +44,18 @@ export const CONNECTOR_LABEL_START_POINT_STYLE = [
44
44
  'com.labre.connector.toolbar.start-point-style',
45
45
  'Start point style',
46
46
  ];
47
+ /* ── The menu shells' accessible names (#390) ─────────────────────────────
48
+ *
49
+ * Each `aria-label` is its own wording rather than `` `${label}-menu` ``: the
50
+ * four labels above go through the seam, so the composition read "style de
51
+ * point de départ-menu" on a French host. Fallbacks are the exact identifiers
52
+ * the composition produced in English. The plain "Style" menu reuses the
53
+ * shared `MENU_ARIA_STYLE` — three toolbars draw that same menu.
54
+ */
55
+ export const CONNECTOR_START_POINT_STYLE_MENU_ARIA = [
56
+ 'com.labre.connector.toolbar.start-point-style-menu',
57
+ 'start point style-menu',
58
+ ];
47
59
  export const CONNECTOR_TOOLTIP_FLIP_DIRECTION = [
48
60
  'com.labre.connector.toolbar.flip-direction',
49
61
  'Flip direction',
@@ -52,10 +64,18 @@ export const CONNECTOR_LABEL_END_POINT_STYLE = [
52
64
  'com.labre.connector.toolbar.end-point-style',
53
65
  'End point style',
54
66
  ];
67
+ export const CONNECTOR_END_POINT_STYLE_MENU_ARIA = [
68
+ 'com.labre.connector.toolbar.end-point-style-menu',
69
+ 'end point style-menu',
70
+ ];
55
71
  export const CONNECTOR_LABEL_SHAPE = [
56
72
  'com.labre.connector.toolbar.shape',
57
73
  'Shape',
58
74
  ];
75
+ export const CONNECTOR_SHAPE_MENU_ARIA = [
76
+ 'com.labre.connector.toolbar.shape-menu',
77
+ 'shape-menu',
78
+ ];
59
79
  export const CONNECTOR_TOOLTIP_CONNECTOR_SHAPE = [
60
80
  'com.labre.connector.toolbar.connector-shape',
61
81
  'Connector shape',
@@ -72,8 +92,11 @@ export const CONNECTOR_WORDINGS = [
72
92
  CONNECTOR_LABEL_CONNECTOR,
73
93
  CONNECTOR_LABEL_STROKE_STYLE,
74
94
  CONNECTOR_LABEL_START_POINT_STYLE,
95
+ CONNECTOR_START_POINT_STYLE_MENU_ARIA,
75
96
  CONNECTOR_TOOLTIP_FLIP_DIRECTION,
76
97
  CONNECTOR_LABEL_END_POINT_STYLE,
98
+ CONNECTOR_END_POINT_STYLE_MENU_ARIA,
77
99
  CONNECTOR_LABEL_SHAPE,
100
+ CONNECTOR_SHAPE_MENU_ARIA,
78
101
  CONNECTOR_TOOLTIP_CONNECTOR_SHAPE,
79
102
  ];
@@ -1,7 +1,7 @@
1
1
  import { Overlay } from '../../affine-block-surface/index.js';
2
2
  import { PathGenerator } from '../../affine-gfx-connector/index.js';
3
3
  import { ConnectorMode, LayoutType, } from '../../affine-model/index.js';
4
- import { ThemeProvider } from '../../affine-shared/services/index.js';
4
+ import { CHROME_ACCENT_CSS_VARIABLE, ThemeProvider, } from '../../affine-shared/services/index.js';
5
5
  import { isVecZero, PointLocation, toRadian, Vec, } from '../../global/gfx/index.js';
6
6
  import last from 'lodash-es/last.js';
7
7
  import { NODE_HORIZONTAL_SPACING, NODE_VERTICAL_SPACING } from '../view/layout.js';
@@ -101,7 +101,11 @@ export class MindMapIndicatorOverlay extends Overlay {
101
101
  }
102
102
  const targetPos = this.targetBound;
103
103
  const points = this._generatePath();
104
- const color = this.themeService.getColorValue('--affine-primary-color', '#1E96EB', true);
104
+ // The accent read from the theme, not a literal: a canvas context cannot
105
+ // take a `var(…)`, so the token is resolved here (DESIGN.md, The Borrowed
106
+ // Blue Rule). The hex used to sit here as a `getColorValue` fallback that
107
+ // could never fire — the variable name always resolves.
108
+ const color = this.themeService.getCssVariableColor(CHROME_ACCENT_CSS_VARIABLE);
105
109
  ctx.strokeStyle = color;
106
110
  ctx.fillStyle = color;
107
111
  ctx.lineWidth = 3;
@@ -1,9 +1,9 @@
1
1
  import { hasGrouped } from '../../affine-gfx-shape/index.js';
2
2
  import { LayoutType, MindmapElementModel, MindmapStyle, ShapeElementModel, } from '../../affine-model/index.js';
3
- import { STYLE_MENU_LABEL, ToolbarModuleExtension, } from '../../affine-shared/services/index.js';
3
+ import { MENU_ARIA_STYLE, STYLE_MENU_LABEL, ToolbarModuleExtension, } from '../../affine-shared/services/index.js';
4
4
  import { getMostCommonValue } from '../../affine-shared/utils/index.js';
5
5
  import { renderMenu, } from '../../affine-widget-edgeless-toolbar/index.js';
6
- import { MINDMAP_LAYOUT_LABEL, MINDMAP_LAYOUT_LEFT, MINDMAP_LAYOUT_RADIAL, MINDMAP_LAYOUT_RIGHT, } from '../translations.js';
6
+ import { MINDMAP_LAYOUT_LABEL, MINDMAP_LAYOUT_MENU_ARIA, MINDMAP_LAYOUT_LEFT, MINDMAP_LAYOUT_RADIAL, MINDMAP_LAYOUT_RIGHT, } from '../translations.js';
7
7
  import { RadiantIcon, RightLayoutIcon, StyleIcon } from '@blocksuite/icons/lit';
8
8
  import { BlockFlavourIdentifier } from '../../std/index.js';
9
9
  import { MindmapStyleFour, MindmapStyleOne, MindmapStyleThree, MindmapStyleTwo, } from '../view/index.js';
@@ -58,6 +58,7 @@ export const createMindmapStyleActionMenu = (ctx, models) => {
58
58
  return renderMenu({
59
59
  label: 'Style',
60
60
  labelWording: STYLE_MENU_LABEL,
61
+ menuAriaWording: MENU_ARIA_STYLE,
61
62
  icon: StyleIcon(),
62
63
  items: MINDMAP_STYLE_LIST,
63
64
  currentValue: style,
@@ -77,6 +78,7 @@ export const createMindmapLayoutActionMenu = (ctx, models) => {
77
78
  return renderMenu({
78
79
  label: 'Layout',
79
80
  labelWording: MINDMAP_LAYOUT_LABEL,
81
+ menuAriaWording: MINDMAP_LAYOUT_MENU_ARIA,
80
82
  items: MINDMAP_LAYOUT_LIST,
81
83
  currentValue: layoutType,
82
84
  onPick,
@@ -57,6 +57,12 @@ export declare const MINDMAP_TEMPLATE_NAME_STYLE_2: ChromeWording;
57
57
  export declare const MINDMAP_TEMPLATE_NAME_STYLE_3: ChromeWording;
58
58
  export declare const MINDMAP_TEMPLATE_NAME_STYLE_4: ChromeWording;
59
59
  export declare const MINDMAP_LAYOUT_LABEL: ChromeWording;
60
+ /**
61
+ * The accessible name of the layout menu SHELL (#390) — its own wording, not
62
+ * `` `${MINDMAP_LAYOUT_LABEL}-menu` ``, which read "disposition-menu" in
63
+ * French. The fallback is the exact identifier that composition produced.
64
+ */
65
+ export declare const MINDMAP_LAYOUT_MENU_ARIA: ChromeWording;
60
66
  /**
61
67
  * The three layout directions — a different concept from `gfx/text`'s own
62
68
  * "Left" / "Right" text alignment (`TEXT_ALIGN_LEFT`/`RIGHT`), so kept as
@@ -102,6 +102,15 @@ export const MINDMAP_LAYOUT_LABEL = [
102
102
  'com.labre.mindmap.toolbar.layout',
103
103
  'Layout',
104
104
  ];
105
+ /**
106
+ * The accessible name of the layout menu SHELL (#390) — its own wording, not
107
+ * `` `${MINDMAP_LAYOUT_LABEL}-menu` ``, which read "disposition-menu" in
108
+ * French. The fallback is the exact identifier that composition produced.
109
+ */
110
+ export const MINDMAP_LAYOUT_MENU_ARIA = [
111
+ 'com.labre.mindmap.toolbar.layout-menu',
112
+ 'layout-menu',
113
+ ];
105
114
  /**
106
115
  * The three layout directions — a different concept from `gfx/text`'s own
107
116
  * "Left" / "Right" text alignment (`TEXT_ALIGN_LEFT`/`RIGHT`), so kept as
@@ -159,6 +168,7 @@ export const MINDMAP_CHROME_WORDINGS = [
159
168
  MINDMAP_TEMPLATE_NAME_STYLE_3,
160
169
  MINDMAP_TEMPLATE_NAME_STYLE_4,
161
170
  MINDMAP_LAYOUT_LABEL,
171
+ MINDMAP_LAYOUT_MENU_ARIA,
162
172
  MINDMAP_LAYOUT_LEFT,
163
173
  MINDMAP_LAYOUT_RADIAL,
164
174
  MINDMAP_LAYOUT_RIGHT,
@@ -2,7 +2,7 @@ import { EdgelessCRUDIdentifier } from '../../affine-block-surface/index.js';
2
2
  import { frameworkPaletteGroups, packColor, } from '../../affine-components/color-picker/index.js';
3
3
  import { createTextActions } from '../../affine-gfx-text/index.js';
4
4
  import { DefaultTheme, FontFamily, getShapeName, getShapeRadius, getShapeType, isTransparent, LineWidth, MindmapElementModel, resolveColor, ShapeElementModel, ShapeStyle, ShapeType, StrokeStyle, TextFitMode, } from '../../affine-model/index.js';
5
- import { STYLE_MENU_LABEL, ToolbarModuleExtension, translateKey, } from '../../affine-shared/services/index.js';
5
+ import { MENU_ARIA_STYLE, STYLE_MENU_LABEL, ToolbarModuleExtension, translateKey, } from '../../affine-shared/services/index.js';
6
6
  import { getMostCommonValue } from '../../affine-shared/utils/index.js';
7
7
  import { getRootBlock, LINE_STYLE_LIST, renderMenu, } from '../../affine-widget-edgeless-toolbar/index.js';
8
8
  import { Bound } from '../../global/gfx/index.js';
@@ -15,7 +15,7 @@ import { ShapeElementView } from '../element-view.js';
15
15
  import { applyTextFitMode, nextTextFitMode } from '../text-fit.js';
16
16
  import { mountShapeTextEditor } from '../text/edgeless-shape-text-editor.js';
17
17
  import { ShapeComponentConfig } from './shape-menu-config.js';
18
- import { SHAPE_ADD_TEXT_TOOLTIP, SHAPE_EDIT_VERTICES_TOOLTIP, SHAPE_SWITCH_TYPE_LABEL, SHAPE_TEXT_FIT_ARIA, SHAPE_TEXT_FIT_CONTAINED, SHAPE_TEXT_FIT_GROW, SHAPE_TEXT_FIT_OVERFLOW, SHAPE_TEXT_FIT_TOOLTIP, } from '../translations.js';
18
+ import { SHAPE_ADD_TEXT_TOOLTIP, SHAPE_EDIT_VERTICES_TOOLTIP, SHAPE_SWITCH_TYPE_LABEL, SHAPE_SWITCH_TYPE_MENU_ARIA, SHAPE_TEXT_FIT_ARIA, SHAPE_TEXT_FIT_CONTAINED, SHAPE_TEXT_FIT_GROW, SHAPE_TEXT_FIT_OVERFLOW, SHAPE_TEXT_FIT_TOOLTIP, } from '../translations.js';
19
19
  /** Icon + wording per text fit mode for the cycling toolbar button. */
20
20
  const TEXT_FIT_UI = {
21
21
  [TextFitMode.Grow]: { icon: AutoHeightIcon(), wording: SHAPE_TEXT_FIT_GROW },
@@ -60,6 +60,7 @@ export const shapeToolbarConfig = {
60
60
  icon: ShapeIcon(),
61
61
  label: 'Switch shape type',
62
62
  labelWording: SHAPE_SWITCH_TYPE_LABEL,
63
+ menuAriaWording: SHAPE_SWITCH_TYPE_MENU_ARIA,
63
64
  items: ShapeComponentConfig.map(item => ({
64
65
  key: item.tooltip,
65
66
  keyWording: item.tooltipWording,
@@ -96,6 +97,7 @@ export const shapeToolbarConfig = {
96
97
  return renderMenu({
97
98
  label: 'Style',
98
99
  labelWording: STYLE_MENU_LABEL,
100
+ menuAriaWording: MENU_ARIA_STYLE,
99
101
  items: LINE_STYLE_LIST,
100
102
  currentValue: shapeStyle === ShapeStyle.Scribbled,
101
103
  onPick,