blockly 13.0.0-beta.0 → 13.0.0-beta.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 (313) hide show
  1. package/blockly.min.js +2092 -1318
  2. package/blockly.mjs +1 -1
  3. package/blockly_compressed.js +1887 -1190
  4. package/blockly_compressed.js.map +1 -1
  5. package/blocks_compressed.js +71 -71
  6. package/blocks_compressed.js.map +1 -1
  7. package/core/block.d.ts +18 -0
  8. package/core/block_aria_composer.d.ts +119 -0
  9. package/core/block_svg.d.ts +21 -1
  10. package/core/blockly.d.ts +1 -1
  11. package/core/bubbles/bubble.d.ts +39 -0
  12. package/core/bubbles/mini_workspace_bubble.d.ts +4 -1
  13. package/core/bubbles/text_bubble.d.ts +4 -1
  14. package/core/dragging/block_drag_strategy.d.ts +45 -3
  15. package/core/field.d.ts +15 -17
  16. package/core/field_checkbox.d.ts +27 -0
  17. package/core/field_dropdown.d.ts +51 -1
  18. package/core/field_image.d.ts +24 -0
  19. package/core/field_input.d.ts +23 -0
  20. package/core/field_number.d.ts +10 -0
  21. package/core/field_textinput.d.ts +10 -0
  22. package/core/field_variable.d.ts +9 -0
  23. package/core/flyout_base.d.ts +10 -0
  24. package/core/focus_manager.d.ts +47 -2
  25. package/core/inputs/input.d.ts +15 -0
  26. package/core/interfaces/i_flyout_inflater.d.ts +9 -0
  27. package/core/interfaces/i_focusable_node.d.ts +3 -1
  28. package/core/interfaces/i_json_block_definition.d.ts +1 -0
  29. package/core/keyboard_nav/keyboard_mover.d.ts +16 -5
  30. package/core/keyboard_nav/navigation_policies/bubble_navigation_policy.d.ts +63 -0
  31. package/core/keyboard_nav/navigation_policies/icon_navigation_policy.d.ts +2 -2
  32. package/core/keyboard_nav/navigators/flyout_navigator.d.ts +1 -1
  33. package/core/menu.d.ts +3 -0
  34. package/core/menuitem.d.ts +8 -1
  35. package/core/shortcut_items.d.ts +16 -1
  36. package/core/shortcut_registry.d.ts +6 -0
  37. package/core/toolbox/toolbox.d.ts +5 -11
  38. package/core/tooltip.d.ts +10 -0
  39. package/core/trashcan.d.ts +23 -38
  40. package/core/utils/aria.d.ts +16 -62
  41. package/core/utils/dom.d.ts +1 -1
  42. package/core/utils/shortcut_formatting.d.ts +5 -7
  43. package/core/variables.d.ts +1 -1
  44. package/core/workspace.d.ts +5 -1
  45. package/core/workspace_svg.d.ts +8 -0
  46. package/core/zoom_controls.d.ts +43 -50
  47. package/dart_compressed.js +62 -62
  48. package/dart_compressed.js.map +1 -1
  49. package/index.mjs +1 -1
  50. package/javascript_compressed.js +55 -55
  51. package/javascript_compressed.js.map +1 -1
  52. package/lua_compressed.js +50 -50
  53. package/lua_compressed.js.map +1 -1
  54. package/media/drop.mp3 +0 -0
  55. package/msg/ab.js +78 -1
  56. package/msg/ab.mjs +78 -1
  57. package/msg/ace.js +79 -2
  58. package/msg/ace.mjs +78 -1
  59. package/msg/af.js +78 -1
  60. package/msg/af.mjs +78 -1
  61. package/msg/am.js +79 -2
  62. package/msg/am.mjs +78 -1
  63. package/msg/ar.js +101 -24
  64. package/msg/ar.mjs +78 -1
  65. package/msg/ast.js +79 -2
  66. package/msg/ast.mjs +78 -1
  67. package/msg/az.js +79 -2
  68. package/msg/az.mjs +78 -1
  69. package/msg/ba.js +78 -1
  70. package/msg/ba.mjs +78 -1
  71. package/msg/bcc.js +78 -1
  72. package/msg/bcc.mjs +78 -1
  73. package/msg/be-tarask.js +112 -35
  74. package/msg/be-tarask.mjs +78 -1
  75. package/msg/be.js +79 -2
  76. package/msg/be.mjs +78 -1
  77. package/msg/bg.js +78 -1
  78. package/msg/bg.mjs +78 -1
  79. package/msg/bn.js +79 -2
  80. package/msg/bn.mjs +78 -1
  81. package/msg/br.js +79 -2
  82. package/msg/br.mjs +78 -1
  83. package/msg/bs.js +78 -1
  84. package/msg/bs.mjs +78 -1
  85. package/msg/ca.js +78 -1
  86. package/msg/ca.mjs +78 -1
  87. package/msg/ce.js +78 -1
  88. package/msg/ce.mjs +78 -1
  89. package/msg/cs.js +86 -9
  90. package/msg/cs.mjs +78 -1
  91. package/msg/da.js +102 -25
  92. package/msg/da.mjs +78 -1
  93. package/msg/de.js +78 -1
  94. package/msg/de.mjs +78 -1
  95. package/msg/diq.js +80 -3
  96. package/msg/diq.mjs +78 -1
  97. package/msg/dtp.js +78 -1
  98. package/msg/dtp.mjs +78 -1
  99. package/msg/dty.js +78 -1
  100. package/msg/dty.mjs +78 -1
  101. package/msg/ee.js +78 -1
  102. package/msg/ee.mjs +78 -1
  103. package/msg/el.js +109 -32
  104. package/msg/el.mjs +78 -1
  105. package/msg/en-gb.js +78 -1
  106. package/msg/en-gb.mjs +78 -1
  107. package/msg/en.js +79 -2
  108. package/msg/en.mjs +78 -1
  109. package/msg/eo.js +78 -1
  110. package/msg/eo.mjs +78 -1
  111. package/msg/es.js +88 -11
  112. package/msg/es.mjs +78 -1
  113. package/msg/et.js +78 -1
  114. package/msg/et.mjs +78 -1
  115. package/msg/eu.js +78 -1
  116. package/msg/eu.mjs +78 -1
  117. package/msg/fa.js +79 -2
  118. package/msg/fa.mjs +78 -1
  119. package/msg/fi.js +97 -20
  120. package/msg/fi.mjs +78 -1
  121. package/msg/fo.js +78 -1
  122. package/msg/fo.mjs +78 -1
  123. package/msg/fr.js +101 -24
  124. package/msg/fr.mjs +78 -1
  125. package/msg/frr.js +79 -2
  126. package/msg/frr.mjs +78 -1
  127. package/msg/ga.js +550 -0
  128. package/msg/{cdo.mjs → ga.mjs} +80 -3
  129. package/msg/gl.js +101 -24
  130. package/msg/gl.mjs +78 -1
  131. package/msg/gn.js +79 -2
  132. package/msg/gn.mjs +78 -1
  133. package/msg/gor.js +78 -1
  134. package/msg/gor.mjs +78 -1
  135. package/msg/ha.js +78 -1
  136. package/msg/ha.mjs +78 -1
  137. package/msg/hak.js +79 -2
  138. package/msg/hak.mjs +78 -1
  139. package/msg/he.js +128 -51
  140. package/msg/he.mjs +78 -1
  141. package/msg/hi.js +78 -1
  142. package/msg/hi.mjs +78 -1
  143. package/msg/hr.js +78 -1
  144. package/msg/hr.mjs +78 -1
  145. package/msg/hrx.js +78 -1
  146. package/msg/hrx.mjs +78 -1
  147. package/msg/hsb.js +78 -1
  148. package/msg/hsb.mjs +78 -1
  149. package/msg/hu.js +80 -3
  150. package/msg/hu.mjs +78 -1
  151. package/msg/hy.js +78 -1
  152. package/msg/hy.mjs +78 -1
  153. package/msg/ia.js +101 -24
  154. package/msg/ia.mjs +78 -1
  155. package/msg/id.js +308 -231
  156. package/msg/id.mjs +78 -1
  157. package/msg/ig.js +86 -9
  158. package/msg/ig.mjs +78 -1
  159. package/msg/inh.js +78 -1
  160. package/msg/inh.mjs +78 -1
  161. package/msg/is.js +78 -1
  162. package/msg/is.mjs +78 -1
  163. package/msg/it.js +104 -27
  164. package/msg/it.mjs +78 -1
  165. package/msg/ja.js +101 -24
  166. package/msg/ja.mjs +78 -1
  167. package/msg/ka.js +80 -3
  168. package/msg/ka.mjs +78 -1
  169. package/msg/kab.js +87 -10
  170. package/msg/kab.mjs +78 -1
  171. package/msg/kbd-cyrl.js +79 -2
  172. package/msg/kbd-cyrl.mjs +78 -1
  173. package/msg/km.js +78 -1
  174. package/msg/km.mjs +78 -1
  175. package/msg/kn.js +78 -1
  176. package/msg/kn.mjs +78 -1
  177. package/msg/ko.js +103 -26
  178. package/msg/ko.mjs +78 -1
  179. package/msg/krc.js +550 -0
  180. package/msg/krc.mjs +531 -0
  181. package/msg/ksh.js +79 -2
  182. package/msg/ksh.mjs +78 -1
  183. package/msg/ku-latn.js +79 -2
  184. package/msg/ku-latn.mjs +78 -1
  185. package/msg/ky.js +80 -3
  186. package/msg/ky.mjs +78 -1
  187. package/msg/la.js +79 -2
  188. package/msg/la.mjs +78 -1
  189. package/msg/lb.js +89 -12
  190. package/msg/lb.mjs +78 -1
  191. package/msg/lki.js +78 -1
  192. package/msg/lki.mjs +78 -1
  193. package/msg/lo.js +78 -1
  194. package/msg/lo.mjs +78 -1
  195. package/msg/lrc.js +78 -1
  196. package/msg/lrc.mjs +78 -1
  197. package/msg/lt.js +79 -2
  198. package/msg/lt.mjs +78 -1
  199. package/msg/lv.js +89 -12
  200. package/msg/lv.mjs +78 -1
  201. package/msg/mg.js +78 -1
  202. package/msg/mg.mjs +78 -1
  203. package/msg/mk.js +78 -1
  204. package/msg/mk.mjs +78 -1
  205. package/msg/ml.js +78 -1
  206. package/msg/ml.mjs +78 -1
  207. package/msg/mnw.js +78 -1
  208. package/msg/mnw.mjs +78 -1
  209. package/msg/ms.js +87 -10
  210. package/msg/ms.mjs +78 -1
  211. package/msg/my.js +78 -1
  212. package/msg/my.mjs +78 -1
  213. package/msg/mzn.js +79 -2
  214. package/msg/mzn.mjs +78 -1
  215. package/msg/nb.js +78 -1
  216. package/msg/nb.mjs +78 -1
  217. package/msg/ne.js +87 -10
  218. package/msg/ne.mjs +78 -1
  219. package/msg/nl.js +101 -24
  220. package/msg/nl.mjs +78 -1
  221. package/msg/oc.js +78 -1
  222. package/msg/oc.mjs +78 -1
  223. package/msg/olo.js +79 -2
  224. package/msg/olo.mjs +78 -1
  225. package/msg/pa.js +87 -10
  226. package/msg/pa.mjs +78 -1
  227. package/msg/pl.js +101 -24
  228. package/msg/pl.mjs +78 -1
  229. package/msg/pms.js +101 -24
  230. package/msg/pms.mjs +78 -1
  231. package/msg/ps.js +96 -19
  232. package/msg/ps.mjs +78 -1
  233. package/msg/pt-br.js +101 -24
  234. package/msg/pt-br.mjs +78 -1
  235. package/msg/pt.js +101 -24
  236. package/msg/pt.mjs +78 -1
  237. package/msg/ro.js +110 -33
  238. package/msg/ro.mjs +78 -1
  239. package/msg/ru.js +101 -24
  240. package/msg/ru.mjs +78 -1
  241. package/msg/sc.js +78 -1
  242. package/msg/sc.mjs +78 -1
  243. package/msg/sco.js +79 -2
  244. package/msg/sco.mjs +78 -1
  245. package/msg/sd.js +78 -1
  246. package/msg/sd.mjs +78 -1
  247. package/msg/shn.js +78 -1
  248. package/msg/shn.mjs +78 -1
  249. package/msg/si.js +79 -2
  250. package/msg/si.mjs +78 -1
  251. package/msg/sk.js +79 -2
  252. package/msg/sk.mjs +78 -1
  253. package/msg/skr-arab.js +81 -4
  254. package/msg/skr-arab.mjs +78 -1
  255. package/msg/sl.js +102 -25
  256. package/msg/sl.mjs +78 -1
  257. package/msg/smn.js +80 -3
  258. package/msg/smn.mjs +78 -1
  259. package/msg/sq.js +87 -10
  260. package/msg/sq.mjs +78 -1
  261. package/msg/sr-latn.js +78 -1
  262. package/msg/sr-latn.mjs +78 -1
  263. package/msg/sr.js +78 -1
  264. package/msg/sr.mjs +78 -1
  265. package/msg/sv.js +101 -24
  266. package/msg/sv.mjs +78 -1
  267. package/msg/sw.js +79 -2
  268. package/msg/sw.mjs +78 -1
  269. package/msg/ta.js +97 -20
  270. package/msg/ta.mjs +78 -1
  271. package/msg/tcy.js +148 -71
  272. package/msg/tcy.mjs +78 -1
  273. package/msg/tdd.js +78 -1
  274. package/msg/tdd.mjs +78 -1
  275. package/msg/te.js +78 -1
  276. package/msg/te.mjs +78 -1
  277. package/msg/th.js +79 -2
  278. package/msg/th.mjs +78 -1
  279. package/msg/ti.js +78 -1
  280. package/msg/ti.mjs +78 -1
  281. package/msg/tl.js +78 -1
  282. package/msg/tl.mjs +78 -1
  283. package/msg/tlh.js +78 -1
  284. package/msg/tlh.mjs +78 -1
  285. package/msg/tr.js +101 -24
  286. package/msg/tr.mjs +78 -1
  287. package/msg/ug-arab.js +78 -1
  288. package/msg/ug-arab.mjs +78 -1
  289. package/msg/uk.js +78 -1
  290. package/msg/uk.mjs +78 -1
  291. package/msg/ur.js +78 -1
  292. package/msg/ur.mjs +78 -1
  293. package/msg/uz.js +93 -16
  294. package/msg/uz.mjs +78 -1
  295. package/msg/vi.js +102 -25
  296. package/msg/vi.mjs +78 -1
  297. package/msg/xmf.js +78 -1
  298. package/msg/xmf.mjs +78 -1
  299. package/msg/yo.js +78 -1
  300. package/msg/yo.mjs +78 -1
  301. package/msg/zgh.js +78 -1
  302. package/msg/zgh.mjs +78 -1
  303. package/msg/zh-hans.js +101 -24
  304. package/msg/zh-hans.mjs +78 -1
  305. package/msg/zh-hant.js +101 -24
  306. package/msg/zh-hant.mjs +78 -1
  307. package/package.json +4 -4
  308. package/php_compressed.js +54 -55
  309. package/php_compressed.js.map +1 -1
  310. package/python_compressed.js +57 -57
  311. package/python_compressed.js.map +1 -1
  312. package/core/keyboard_nav/navigation_policies/block_comment_navigation_policy.d.ts +0 -63
  313. package/msg/cdo.js +0 -473
package/core/block.d.ts CHANGED
@@ -174,6 +174,8 @@ export declare class Block {
174
174
  type: string;
175
175
  inputsInlineDefault?: boolean;
176
176
  workspace: Workspace;
177
+ /** A custom provider for generating the aria role description for this block. */
178
+ private ariaRoleDescriptionProvider;
177
179
  /**
178
180
  * @param workspace The block's workspace.
179
181
  * @param prototypeName Name of the language object containing type-specific
@@ -695,6 +697,22 @@ export declare class Block {
695
697
  * @param collapsed True if collapsed.
696
698
  */
697
699
  setCollapsed(collapsed: boolean): void;
700
+ /**
701
+ * Set a custom aria role description provider for this block. If not set,
702
+ * uses a default provider based on the block's properties (e.g. whether it has
703
+ * inputs, outputs, etc.).
704
+ *
705
+ * @param description The description or function to provide the description.
706
+ * If a string, we'll replace message references in the string, e.g.
707
+ * `%{BKY_CUSTOM_MESSAGE}` will be replaced with the value of
708
+ * `Blockly.Msg['CUSTOM_MESSAGE']`.}'
709
+ */
710
+ setAriaRoleDescriptionProvider(description: string | (() => string)): void;
711
+ /**
712
+ * @returns The custom string to use as the role description for this block,
713
+ * or undefined if no custom description is set.
714
+ */
715
+ getAriaRoleDescription(): string | undefined;
698
716
  /**
699
717
  * Create a human-readable text representation of this block and any children.
700
718
  *
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Raspberry Pi Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { BlockSvg } from './block_svg.js';
7
+ import type { Input } from './inputs/input.js';
8
+ import { RenderedConnection } from './rendered_connection.js';
9
+ import { Verbosity } from './utils/aria.js';
10
+ /**
11
+ * Prepositions to use when describing the relationship between two blocks based
12
+ * on their connection types.
13
+ */
14
+ export declare enum ConnectionPreposition {
15
+ UNKNOWN = 0,
16
+ BEFORE = 1,
17
+ AFTER = 2,
18
+ AROUND = 3,
19
+ INSIDE = 4
20
+ }
21
+ /**
22
+ * Returns an ARIA representation of the specified block.
23
+ *
24
+ * The returned label will contain a complete context of the block, including:
25
+ * - Whether it begins a block stack or statement input stack.
26
+ * - Its constituent editable and non-editable fields.
27
+ * - Properties, including: disabled, collapsed, replaceable (a shadow), etc.
28
+ * - Its parent toolbox category.
29
+ * - Whether it has inputs.
30
+ *
31
+ * Beyond this, the returned label is specifically assembled with commas in
32
+ * select locations with the intention of better 'prosody' in the screen reader
33
+ * readouts since there's a lot of information being shared with the user. The
34
+ * returned label also places more important information earlier in the label so
35
+ * that the user gets the most important context as soon as possible in case
36
+ * they wish to stop readout early.
37
+ *
38
+ * The returned label will be specialized based on whether the block is part of a
39
+ * flyout.
40
+ *
41
+ * @internal
42
+ * @param block The block for which an ARIA representation should be created.
43
+ * @param verbosity How much detail to include in the description.
44
+ * @returns The ARIA representation for the specified block.
45
+ */
46
+ export declare function computeAriaLabel(block: BlockSvg, verbosity?: Verbosity): string;
47
+ /**
48
+ * Sets the ARIA role and role description for the specified block, accounting
49
+ * for whether the block is part of a flyout.
50
+ *
51
+ * @internal
52
+ * @param block The block to set ARIA role and roledescription attributes on.
53
+ */
54
+ export declare function configureAriaRole(block: BlockSvg): void;
55
+ /**
56
+ * Returns a list of ARIA labels for the 'field row' for the specified Input.
57
+ *
58
+ * 'Field row' essentially means the horizontal run of readable fields that
59
+ * precede the Input. Together, these provide the domain context for the input,
60
+ * particularly in the context of connections. In some cases, there may not be
61
+ * any readable fields immediately prior to the Input. In that case, if the
62
+ * `lookback` attribute is specified, all of the fields on the row immediately
63
+ * above the Input will be used instead.
64
+ *
65
+ * @internal
66
+ * @param input The Input to compute a description/context label for.
67
+ * @param lookback If true, will use labels for fields on the previous row if
68
+ * the given input's row has no fields itself.
69
+ * @returns A list of labels for fields on the same row (or previous row, if
70
+ * lookback is specified) as the given input.
71
+ */
72
+ export declare function computeFieldRowLabel(input: Input, lookback: boolean, verbosity?: Verbosity): string[];
73
+ /**
74
+ * Returns a list of accessibility labels for fields and inputs on a block.
75
+ * Each entry in the returned array corresponds to one of: (a) a label for a
76
+ * continuous run of non-interactable fields, (b) a label for an editable field,
77
+ * (c) a label for an input. When an input contains nested blocks/fields/inputs,
78
+ * their contents are returned as a single item in the array per top-level
79
+ * input.
80
+ *
81
+ * @internal
82
+ * @param block The block to retrieve a list of field/input labels for.
83
+ * @returns A list of field/input labels for the given block.
84
+ */
85
+ export declare function getInputLabels(block: BlockSvg, verbosity?: Verbosity): string[];
86
+ /**
87
+ * Returns a subset of labels for inputs on the given block, ending at the
88
+ * specified input.
89
+ *
90
+ * The subset is determined based on the input type:
91
+ * - For non-statement inputs, only the label for the given input is returned.
92
+ * - For statement inputs, labels are collected from the start of the current
93
+ * statement section up to and including the given input. A statement section
94
+ * begins immediately after the previous statement input, or at the start of
95
+ * the block if none exists.
96
+ *
97
+ * @internal
98
+ * @param block The block to retrieve a list of field/input labels for.
99
+ * @param input The input that defines the end of the subset.
100
+ * @returns A list of field/input labels for the given block.
101
+ */
102
+ export declare function getInputLabelsSubset(block: BlockSvg, input: Input, verbosity?: Verbosity): string[];
103
+ /**
104
+ * Returns a translated string describing an in-progress move of a block to a new
105
+ * connection, suitable for announcement on the ARIA live region. The returned string
106
+ * will be assembled based on the types of the local and neighbour connections and
107
+ * the presence of any readable fields on the block's inputs. If multiple potential
108
+ * candidate connections are present, additional context will be included in the
109
+ * returned string to help disambiguate between them.
110
+ *
111
+ * @param local The moving side of the candidate connection pair
112
+ * @param neighbour The target side of the candidate connection pair
113
+ * @param disambiguationPolicy A function that determines whether it's useful to
114
+ * include parent input labels for disambiguation.
115
+ * @param isMoveStart Whether this announcement is for the start of a move. If false,
116
+ * skip announcing the block label since it should have already been announced.
117
+ */
118
+ export declare function computeMoveLabel(local: RenderedConnection, neighbour: RenderedConnection, disambiguationPolicy: (forLocal: boolean) => boolean, isMoveStart?: boolean): string;
119
+ //# sourceMappingURL=block_aria_composer.d.ts.map
@@ -28,6 +28,7 @@ import { IIcon } from './interfaces/i_icon.js';
28
28
  import { RenderedConnection } from './rendered_connection.js';
29
29
  import type { IPathObject } from './renderers/common/i_path_object.js';
30
30
  import type { BlockStyle } from './theme.js';
31
+ import * as aria from './utils/aria.js';
31
32
  import { Coordinate } from './utils/coordinate.js';
32
33
  import { Rect } from './utils/rect.js';
33
34
  import { FlyoutItemInfo } from './utils/toolbox.js';
@@ -734,7 +735,7 @@ export declare class BlockSvg extends Block implements IBoundedElement, IContext
734
735
  * main workspace. If this block has a single full-block field, that field
735
736
  * will be focused. Otherwise, this is a no-op.
736
737
  */
737
- performAction(): void;
738
+ performAction(e?: KeyboardEvent): void;
738
739
  /**
739
740
  * Returns a set of all of the parent blocks of the given block.
740
741
  *
@@ -756,5 +757,24 @@ export declare class BlockSvg extends Block implements IBoundedElement, IContext
756
757
  * @internal
757
758
  */
758
759
  getRowId(): string;
760
+ /**
761
+ * Updates the ARIA label, role and roledescription for this block.
762
+ */
763
+ private recomputeAriaAttributes;
764
+ /**
765
+ * Returns a description of this block suitable for screenreaders or use in
766
+ * ARIA attributes.
767
+ *
768
+ * @param verbosity How much detail to include in the description.
769
+ * @returns An accessibility description of this block.
770
+ */
771
+ getAriaLabel(verbosity: aria.Verbosity): string;
772
+ /**
773
+ * Count the number of blocks in this stack (connected by next connections)
774
+ * and return a label to describe it. Uses the standard label if there is only one block.
775
+ *
776
+ * @internal
777
+ */
778
+ getStackBlocksCountLabel(): string;
759
779
  }
760
780
  //# sourceMappingURL=block_svg.d.ts.map
package/core/blockly.d.ts CHANGED
@@ -270,8 +270,8 @@ export declare const VARIABLE_DYNAMIC_CATEGORY_NAME: string;
270
270
  */
271
271
  export declare const PROCEDURE_CATEGORY_NAME: string;
272
272
  export * from './interfaces/i_navigation_policy.js';
273
- export * from './keyboard_nav/navigation_policies/block_comment_navigation_policy.js';
274
273
  export * from './keyboard_nav/navigation_policies/block_navigation_policy.js';
274
+ export * from './keyboard_nav/navigation_policies/bubble_navigation_policy.js';
275
275
  export * from './keyboard_nav/navigation_policies/comment_bar_button_navigation_policy.js';
276
276
  export * from './keyboard_nav/navigation_policies/comment_editor_navigation_policy.js';
277
277
  export * from './keyboard_nav/navigation_policies/connection_navigation_policy.js';
@@ -13,6 +13,12 @@ import { Coordinate } from '../utils/coordinate.js';
13
13
  import { Rect } from '../utils/rect.js';
14
14
  import { Size } from '../utils/size.js';
15
15
  import { WorkspaceSvg } from '../workspace_svg.js';
16
+ /**
17
+ * Represents a either a string or a function that, when called, can provide a
18
+ * custom ARIA string to represent a bubble, or null if the default fallback
19
+ * should be used. See setAriaLabelProvider for more context.
20
+ */
21
+ export type AriaLabelProvider = string | ((bubble: Bubble) => string | null);
16
22
  /**
17
23
  * The abstract pop-up bubble class. This creates a UI that looks like a speech
18
24
  * bubble, where it has a "tail" that points to the block, and a "head" that
@@ -66,6 +72,7 @@ export declare abstract class Bubble implements IBubble, ISelectable, IFocusable
66
72
  private relativeLeft;
67
73
  private dragStrategy;
68
74
  private focusableElement;
75
+ private ariaLabelProvider;
69
76
  /**
70
77
  * @param workspace The workspace this bubble belongs to.
71
78
  * @param anchor The anchor location of the thing this bubble is attached to.
@@ -239,5 +246,37 @@ export declare abstract class Bubble implements IBubble, ISelectable, IFocusable
239
246
  * Returns the object that owns/hosts this bubble, if any.
240
247
  */
241
248
  getOwner(): (IHasBubble & IFocusableNode) | undefined;
249
+ /**
250
+ * Recomputes the ARIA label and role for this bubble. This is automatically called
251
+ * during initialization, but implementations may find it useful to call this if
252
+ * the bubble's label should be changed.
253
+ *
254
+ * Bubbles use a default non-specific label unless they're customized otherwise
255
+ * which is the responsibility of the bubble's owner rather than bubble
256
+ * implementations. Customization can be done via setAriaLabelProvider.
257
+ */
258
+ protected recomputeAriaContext(): void;
259
+ /**
260
+ * Sets a custom ARIA label provider for this bubble, or null if it should be reset
261
+ * to use the default method.
262
+ *
263
+ * Bubbles do not compute ARIA labels specifically to their implementation since
264
+ * they can be rather general-purpose. Instead, owners of the specific bubble
265
+ * instance (such as an icon) are responsible for defining custom label providers
266
+ * for their bubbles.
267
+ *
268
+ * Note that calling this isn't sufficient for it to actually be used.
269
+ * recomputeAriaContext will likely also need to be called to actually apply the
270
+ * custom label to the bubble's focusable element.
271
+ */
272
+ setAriaLabelProvider(provider: AriaLabelProvider | null): void;
273
+ /**
274
+ * Returns the ARIA label to use for this bubble based on the provider set via
275
+ * setAriaLabelProvider. This will return null if the provider is absent or
276
+ * returns null.
277
+ *
278
+ * @returns The ARIA label to use for this bubble, or null if one is not provided.
279
+ */
280
+ getAriaLabel(): string | null;
242
281
  }
243
282
  //# sourceMappingURL=bubble.d.ts.map
@@ -5,6 +5,8 @@
5
5
  */
6
6
  import type { BlocklyOptions } from '../blockly_options.js';
7
7
  import { Abstract as AbstractEvent } from '../events/events_abstract.js';
8
+ import type { IFocusableNode } from '../interfaces/i_focusable_node.js';
9
+ import type { IHasBubble } from '../interfaces/i_has_bubble.js';
8
10
  import { Options } from '../options.js';
9
11
  import { Coordinate } from '../utils/coordinate.js';
10
12
  import type { Rect } from '../utils/rect.js';
@@ -18,6 +20,7 @@ export declare class MiniWorkspaceBubble extends Bubble {
18
20
  readonly workspace: WorkspaceSvg;
19
21
  protected anchor: Coordinate;
20
22
  protected ownerRect?: Rect | undefined;
23
+ protected owner?: (IHasBubble & IFocusableNode) | undefined;
21
24
  /**
22
25
  * The minimum amount of change to the mini workspace view to trigger
23
26
  * resizing the bubble.
@@ -38,7 +41,7 @@ export declare class MiniWorkspaceBubble extends Bubble {
38
41
  */
39
42
  private autoLayout;
40
43
  /** @internal */
41
- constructor(workspaceOptions: BlocklyOptions, workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined);
44
+ constructor(workspaceOptions: BlocklyOptions, workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined, owner?: (IHasBubble & IFocusableNode) | undefined);
42
45
  dispose(): void;
43
46
  /** @internal */
44
47
  getWorkspace(): WorkspaceSvg;
@@ -3,6 +3,8 @@
3
3
  * Copyright 2023 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import type { IFocusableNode } from '../interfaces/i_focusable_node.js';
7
+ import type { IHasBubble } from '../interfaces/i_has_bubble.js';
6
8
  import { Coordinate } from '../utils/coordinate.js';
7
9
  import { Rect } from '../utils/rect.js';
8
10
  import { WorkspaceSvg } from '../workspace_svg.js';
@@ -15,8 +17,9 @@ export declare class TextBubble extends Bubble {
15
17
  readonly workspace: WorkspaceSvg;
16
18
  protected anchor: Coordinate;
17
19
  protected ownerRect?: Rect | undefined;
20
+ protected owner?: (IHasBubble & IFocusableNode) | undefined;
18
21
  private paragraph;
19
- constructor(text: string, workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined);
22
+ constructor(text: string, workspace: WorkspaceSvg, anchor: Coordinate, ownerRect?: Rect | undefined, owner?: (IHasBubble & IFocusableNode) | undefined);
20
23
  /** @returns the current text of this text bubble. */
21
24
  getText(): string;
22
25
  /** Sets the current text of this text bubble, and updates the display. */
@@ -6,7 +6,6 @@
6
6
  import type { BlockSvg } from '../block_svg.js';
7
7
  import type { IDragStrategy } from '../interfaces/i_draggable.js';
8
8
  import { DragDisposition } from '../interfaces/i_draggable.js';
9
- import { Direction } from '../keyboard_nav/keyboard_mover.js';
10
9
  import type { RenderedConnection } from '../rendered_connection.js';
11
10
  import { Coordinate } from '../utils.js';
12
11
  /** Represents a valid pair of connections between the dragging block and a block on the workspace. */
@@ -57,6 +56,21 @@ export declare class BlockDragStrategy implements IDragStrategy {
57
56
  * and return a newly instantiated block when e.g. dragging from a flyout.
58
57
  */
59
58
  protected getTargetBlock(): BlockSvg;
59
+ /**
60
+ * Announces a move on the ARIA live region for assistive technologies.
61
+ *
62
+ * @param isMoveStart Whether this announcement is for the start of a move. If false,
63
+ * skip announcing the block label since it should have already been announced at the
64
+ * start of the move.
65
+ */
66
+ private announceMove;
67
+ /**
68
+ * Checks if there are multiple compatible connections for the specified side of the pair.
69
+ *
70
+ * @param forLocal Whether we are considering the local or neighbour side of the pair
71
+ * @returns True if there are multiple compatible connections, false otherwise
72
+ */
73
+ private hasMultipleCompatibleConnections;
60
74
  /**
61
75
  * Handles any setup for starting the drag, including disconnecting the block
62
76
  * from any parent blocks.
@@ -141,6 +155,14 @@ export declare class BlockDragStrategy implements IDragStrategy {
141
155
  * compatible type (input, output, etc) and connection check.
142
156
  */
143
157
  private getConnectionCandidate;
158
+ /**
159
+ * Returns the closest connection candidate for the given block.
160
+ *
161
+ * @param block The block to find a connection for.
162
+ * @param delta The distance the block has traveled since dragging began.
163
+ * @returns The closest available connection candidate, if any.
164
+ */
165
+ private getClosestCandidate;
144
166
  /**
145
167
  * Get the radius to use when searching for a nearby valid connection.
146
168
  */
@@ -169,10 +191,30 @@ export declare class BlockDragStrategy implements IDragStrategy {
169
191
  /**
170
192
  * Get the nearest valid candidate connection in traversal order.
171
193
  *
172
- * @param direction The cardinal direction in which the block is being moved.
194
+ * @param delta The distance the block has moved since this drag began.
173
195
  * @returns A candidate connection and radius, or null if none was found.
174
196
  */
175
- findTraversalCandidate(direction: Direction): ConnectionCandidate | null;
197
+ findTraversalCandidate(delta: Coordinate): ConnectionCandidate | null;
198
+ /**
199
+ * Returns whether or not the given block is at a terminal position (start or
200
+ * end) of the blocks on the workspace. This helps distinguish between a block
201
+ * that is at the end of the line because all valid connections have been
202
+ * visited and the proposed constrained move destination is now to drop it on
203
+ * the workspace as a top-level block (in which case it will be in a terminal
204
+ * position), and a block that just entered move mode as a top-level block,
205
+ * and should therefore still be able to move to another connection point
206
+ * even if looping is disabled.
207
+ *
208
+ * @param block The block to check.
209
+ * @param direction The current dragging direction.
210
+ * @returns True if the block is at the start or end of its possible positions
211
+ * on the workspace.
212
+ */
213
+ private isInTerminalPosition;
214
+ /**
215
+ * Converts a connection pair to a connection candidate with a default
216
+ * distance of 0.
217
+ */
176
218
  private pairToCandidate;
177
219
  /**
178
220
  * Returns the cardinal direction that the block being dragged would have to
package/core/field.d.ts CHANGED
@@ -200,22 +200,20 @@ export declare abstract class Field<T = any> implements IKeyboardAccessible, IRe
200
200
  * Gets an ARIA-friendly label representation of this field's value.
201
201
  *
202
202
  * Note that implementations should generally always override this value to
203
- * ensure a non-null value is returned since the default implementation relies
204
- * on 'getValue' which may return null, and a null return value for this
203
+ * ensure a non-null value is returned. The default implementation relies on
204
+ * 'getText' which may return an empty string. A null return value from this
205
205
  * function will prompt ARIA label generation to skip the field's value
206
- * entirely when there may be a better contextual placeholder to use, instead,
207
- * specific to the field.
206
+ * entirely when there may be a better contextual placeholder to use isstead.
208
207
  *
209
- * For example, a text input field may have a value of null when empty. To
210
- * avoid hiding this field from screen reader, implementations should ensure
211
- * that if the value is null, this function would return an appropriate,
212
- * localized value such as "empty text".
208
+ * For example, to avoid hiding an empty text input field from screen reader,
209
+ * implementations should ensure that if the text is an empty string, this
210
+ * function would return an appropriate, localized value such as "empty text".
213
211
  *
214
212
  * Implementations are responsible for, and encouraged to, return a localized
215
213
  * version of the ARIA representation of the field's value.
216
214
  *
217
- * @returns An ARIA representation of the field's value, or null if no value
218
- * is currently defined or known for the field.
215
+ * @returns An ARIA representation of the field's text, or null if no text is
216
+ * currently defined or known for the field.
219
217
  */
220
218
  getAriaValue(): string | null;
221
219
  /**
@@ -237,11 +235,9 @@ export declare abstract class Field<T = any> implements IKeyboardAccessible, IRe
237
235
  * checkboxes represent their checked/non-checked status (i.e. value) through
238
236
  * a separate ARIA property.
239
237
  *
240
- * It's possible this returns an empty string if the field doesn't supply type
241
- * or value information for certain cases (such as a null value). This can
242
- * lead to the field being potentially COMPLETELY HIDDEN for screen reader
243
- * navigation so it's crucial for implementations to ensure a non-empty value
244
- * is returned here.
238
+ * It's not expected that this method, under normal operations, returns an empty
239
+ * string. If the field's value is empty then it will return a localized
240
+ * placeholder indicating that its value is empty.
245
241
  *
246
242
  * @param includeTypeInfo Whether to include the field's type information in
247
243
  * the returned label, if available.
@@ -282,9 +278,11 @@ export declare abstract class Field<T = any> implements IKeyboardAccessible, IRe
282
278
  */
283
279
  protected createBorderRect_(): void;
284
280
  /**
285
- * Create a field text element. Not to be overridden by subclasses. Instead
281
+ * Create a field text element. Not to be overridden by subclasses. Instead,
286
282
  * modify the result of the function inside initView, or create a separate
287
- * function to call.
283
+ * function to call. Aria state is hidden; use the aria label for the field
284
+ * and/or containing block to expose content to screen readers. Text content
285
+ * for custom blocks can be set after creation.
288
286
  */
289
287
  protected createTextElement_(): void;
290
288
  /**
@@ -114,6 +114,29 @@ export declare class FieldCheckbox extends Field<CheckboxBool> {
114
114
  * @returns The converted value.
115
115
  */
116
116
  private convertValueToBool;
117
+ /**
118
+ * Gets an ARIA-friendly label representation of this field's type.
119
+ *
120
+ * Implementations are responsible for, and encouraged to, return a localized
121
+ * version of the ARIA representation of the field's type.
122
+ *
123
+ * @returns An ARIA representation of the field's type or a default if it is
124
+ * unspecified.
125
+ */
126
+ getAriaTypeName(): string;
127
+ /**
128
+ * Gets an ARIA-friendly label representation of this field's value.
129
+ *
130
+ * Implementations are responsible for, and encouraged to, return a localized
131
+ * version of the ARIA representation of the field's value.
132
+ *
133
+ * The FieldCheckbox implementation is not used for the actual ARIA label of
134
+ * the field, since the checked state is already included in the ARIA checked
135
+ * state, but it is used for the ARIA label of its source block.
136
+ *
137
+ * @returns An ARIA representation of the field's text.
138
+ */
139
+ getAriaValue(): string | null;
117
140
  /**
118
141
  * Construct a FieldCheckbox from a JSON arg object.
119
142
  *
@@ -123,6 +146,10 @@ export declare class FieldCheckbox extends Field<CheckboxBool> {
123
146
  * @internal
124
147
  */
125
148
  static fromJson(options: FieldCheckboxFromJsonConfig): FieldCheckbox;
149
+ /**
150
+ * Recomputes the ARIA role and label for this field.
151
+ */
152
+ protected recomputeAriaContext(): void;
126
153
  }
127
154
  /**
128
155
  * Config options for the checkbox field.
@@ -56,6 +56,11 @@ export declare class FieldDropdown extends Field<string> {
56
56
  protected static IMAGE_Y_OFFSET: number;
57
57
  /** The total vertical padding above and below an image. */
58
58
  protected static IMAGE_Y_PADDING: number;
59
+ /**
60
+ * True once the field’s DOM has been created and it is safe to run ARIA
61
+ * updates in response to value changes.
62
+ */
63
+ isInitialized: boolean;
59
64
  /**
60
65
  * @param menuGenerator A non-empty array of options for a dropdown list, or a
61
66
  * function which generates these options. Also accepts Field.SKIP_SETUP
@@ -238,6 +243,50 @@ export declare class FieldDropdown extends Field<string> {
238
243
  * @throws {TypeError} If proposed options are incorrectly structured.
239
244
  */
240
245
  protected validateOptions(options: MenuOption[]): void;
246
+ /**
247
+ * Gets an ARIA-friendly label representation of this field's type.
248
+ *
249
+ * Implementations are responsible for, and encouraged to, return a localized
250
+ * version of the ARIA representation of the field's type.
251
+ *
252
+ * @returns An ARIA representation of the field's type or a default if it is
253
+ * unspecified.
254
+ */
255
+ getAriaTypeName(): string | null;
256
+ /**
257
+ * Gets an ARIA-friendly label representation of this field's value.
258
+ *
259
+ * Implementations are responsible for, and encouraged to, return a localized
260
+ * version of the ARIA representation of the field's value.
261
+ *
262
+ * @returns An ARIA representation of the field's text.
263
+ */
264
+ getAriaValue(): string;
265
+ /**
266
+ * Returns the ARIA label for the currently selected dropdown option.
267
+ *
268
+ * @returns The computed ARIA label for the selected option, or `null` if no
269
+ * option is selected.
270
+ */
271
+ private getSelectedAriaLabel;
272
+ /**
273
+ * Recomputes the ARIA role and label for this field.
274
+ */
275
+ protected recomputeAriaContext(): void;
276
+ /**
277
+ * Computes an ARIA-friendly label for a dropdown option.
278
+ *
279
+ * The label is derived using a prioritized set of sources.
280
+ *
281
+ * Returned values are guaranteed to be non-empty strings for all non-separator
282
+ * options. Whitespace-only values are ignored when determining a usable label.
283
+ *
284
+ * @param option The dropdown option for which to compute the ARIA label.
285
+ * @param index The index of the option within the dropdown (0-based).
286
+ * @returns A string suitable for use as an ARIA label. Returns an empty string
287
+ * only if the option is a separator.
288
+ */
289
+ private computeOptionAriaLabel;
241
290
  }
242
291
  /**
243
292
  * Definition of a human-readable image dropdown option.
@@ -247,6 +296,7 @@ export interface ImageProperties {
247
296
  alt: string;
248
297
  width: number;
249
298
  height: number;
299
+ ariaLabel?: string;
250
300
  }
251
301
  /**
252
302
  * An individual option in the dropdown menu. Can be either the string literal
@@ -255,7 +305,7 @@ export interface ImageProperties {
255
305
  * (text, ImageProperties object, or HTML element), and the second element is
256
306
  * the language-neutral value.
257
307
  */
258
- export type MenuOption = [string | ImageProperties | HTMLElement, string] | 'separator';
308
+ export type MenuOption = [string | ImageProperties | HTMLElement, string, string?] | 'separator';
259
309
  /**
260
310
  * A function that generates an array of menu options for FieldDropdown
261
311
  * or its descendants.
@@ -129,6 +129,30 @@ export declare class FieldImage extends Field<string> {
129
129
  * @internal
130
130
  */
131
131
  static fromJson(options: FieldImageFromJsonConfig): FieldImage;
132
+ /**
133
+ * Gets an ARIA-friendly label representation of this field's type.
134
+ *
135
+ * Implementations are responsible for, and encouraged to, return a localized
136
+ * version of the ARIA representation of the field's type.
137
+ *
138
+ * @returns An ARIA representation of the field's type or a default if it is
139
+ * unspecified.
140
+ */
141
+ getAriaTypeName(): string | null;
142
+ /**
143
+ * Gets an ARIA-friendly label representation of this field's value.
144
+ *
145
+ * Implementations are responsible for, and encouraged to, return a localized
146
+ * version of the ARIA representation of the field's value.
147
+ *
148
+ * @returns An ARIA representation of the field's text, or null if no text is
149
+ * currently defined or known for the field.
150
+ */
151
+ getAriaValue(): string | null;
152
+ /**
153
+ * Recomputes the ARIA role and label for this field.
154
+ */
155
+ protected recomputeAriaContext(): void;
132
156
  }
133
157
  /**
134
158
  * Config options for the image field.
@@ -263,6 +263,29 @@ export declare abstract class FieldInput<T extends InputTypes> extends Field<str
263
263
  * @returns The value to store.
264
264
  */
265
265
  protected getValueFromEditorText_(text: string): any;
266
+ /**
267
+ * Gets an ARIA-friendly label representation of this field's type.
268
+ *
269
+ * Implementations are responsible for, and encouraged to, return a localized
270
+ * version of the ARIA representation of the field's type.
271
+ *
272
+ * @returns An ARIA representation of the field's type or a default if it is
273
+ * unspecified.
274
+ */
275
+ getAriaTypeName(): string | null;
276
+ /**
277
+ * Gets an ARIA-friendly label representation of this field's value.
278
+ *
279
+ * Implementations are responsible for, and encouraged to, return a localized
280
+ * version of the ARIA representation of the field's value.
281
+ *
282
+ * @returns An ARIA representation of the field's text.
283
+ */
284
+ getAriaValue(): string | null;
285
+ /**
286
+ * Recomputes the ARIA role and label for this field.
287
+ */
288
+ protected recomputeAriaContext(): void;
266
289
  }
267
290
  /**
268
291
  * Config options for the input field.
@@ -160,6 +160,16 @@ export declare class FieldNumber extends FieldInput<number> {
160
160
  * @internal
161
161
  */
162
162
  static fromJson(options: FieldNumberFromJsonConfig): FieldNumber;
163
+ /**
164
+ * Gets an ARIA-friendly label representation of this field's type.
165
+ *
166
+ * Implementations are responsible for, and encouraged to, return a localized
167
+ * version of the ARIA representation of the field's type.
168
+ *
169
+ * @returns An ARIA representation of the field's type or a default if it is
170
+ * unspecified.
171
+ */
172
+ getAriaTypeName(): string | null;
163
173
  }
164
174
  /**
165
175
  * Config options for the number field.