@ckeditor/ckeditor5-ui 43.0.0-alpha.6 → 43.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/dist/bindings/clickoutsidehandler.d.ts +5 -3
  2. package/dist/dropdown/dropdownview.d.ts +21 -8
  3. package/dist/dropdown/menu/dropdownmenubehaviors.d.ts +48 -0
  4. package/dist/dropdown/menu/dropdownmenubuttonview.d.ts +40 -0
  5. package/dist/dropdown/menu/dropdownmenulistitembuttonview.d.ts +21 -0
  6. package/dist/dropdown/menu/dropdownmenulistitemview.d.ts +26 -0
  7. package/dist/dropdown/menu/dropdownmenulistview.d.ts +28 -0
  8. package/dist/dropdown/menu/dropdownmenunestedmenupanelview.d.ts +38 -0
  9. package/dist/dropdown/menu/dropdownmenunestedmenuview.d.ts +135 -0
  10. package/dist/dropdown/menu/dropdownmenurootlistview.d.ts +144 -0
  11. package/dist/dropdown/menu/utils.d.ts +128 -0
  12. package/dist/dropdown/utils.d.ts +58 -0
  13. package/dist/editableui/editableuiview.d.ts +1 -1
  14. package/dist/editableui/inline/inlineeditableuiview.d.ts +13 -9
  15. package/dist/editorui/editorui.d.ts +4 -0
  16. package/dist/index-editor.css +16 -0
  17. package/dist/index.css +31 -0
  18. package/dist/index.css.map +1 -1
  19. package/dist/index.d.ts +7 -1
  20. package/dist/index.js +4717 -3869
  21. package/dist/index.js.map +1 -1
  22. package/dist/menubar/utils.d.ts +5 -5
  23. package/dist/panel/balloon/contextualballoon.d.ts +12 -6
  24. package/dist/toolbar/balloon/balloontoolbar.d.ts +5 -0
  25. package/dist/translations/af.js +1 -1
  26. package/dist/translations/af.umd.js +1 -1
  27. package/dist/translations/ar.js +1 -1
  28. package/dist/translations/ar.umd.js +1 -1
  29. package/dist/translations/ast.js +1 -1
  30. package/dist/translations/ast.umd.js +1 -1
  31. package/dist/translations/az.js +1 -1
  32. package/dist/translations/az.umd.js +1 -1
  33. package/dist/translations/bg.js +1 -1
  34. package/dist/translations/bg.umd.js +1 -1
  35. package/dist/translations/bn.js +1 -1
  36. package/dist/translations/bn.umd.js +1 -1
  37. package/dist/translations/bs.js +1 -1
  38. package/dist/translations/bs.umd.js +1 -1
  39. package/dist/translations/ca.js +1 -1
  40. package/dist/translations/ca.umd.js +1 -1
  41. package/dist/translations/cs.js +1 -1
  42. package/dist/translations/cs.umd.js +1 -1
  43. package/dist/translations/da.js +1 -1
  44. package/dist/translations/da.umd.js +1 -1
  45. package/dist/translations/de-ch.js +1 -1
  46. package/dist/translations/de-ch.umd.js +1 -1
  47. package/dist/translations/de.js +1 -1
  48. package/dist/translations/de.umd.js +1 -1
  49. package/dist/translations/el.js +1 -1
  50. package/dist/translations/el.umd.js +1 -1
  51. package/dist/translations/en-au.js +1 -1
  52. package/dist/translations/en-au.umd.js +1 -1
  53. package/dist/translations/en-gb.js +1 -1
  54. package/dist/translations/en-gb.umd.js +1 -1
  55. package/dist/translations/en.js +1 -1
  56. package/dist/translations/en.umd.js +1 -1
  57. package/dist/translations/eo.js +1 -1
  58. package/dist/translations/eo.umd.js +1 -1
  59. package/dist/translations/es-co.js +1 -1
  60. package/dist/translations/es-co.umd.js +1 -1
  61. package/dist/translations/es.js +1 -1
  62. package/dist/translations/es.umd.js +1 -1
  63. package/dist/translations/et.js +1 -1
  64. package/dist/translations/et.umd.js +1 -1
  65. package/dist/translations/eu.js +1 -1
  66. package/dist/translations/eu.umd.js +1 -1
  67. package/dist/translations/fa.js +1 -1
  68. package/dist/translations/fa.umd.js +1 -1
  69. package/dist/translations/fi.js +1 -1
  70. package/dist/translations/fi.umd.js +1 -1
  71. package/dist/translations/fr.js +1 -1
  72. package/dist/translations/fr.umd.js +1 -1
  73. package/dist/translations/gl.js +1 -1
  74. package/dist/translations/gl.umd.js +1 -1
  75. package/dist/translations/he.js +1 -1
  76. package/dist/translations/he.umd.js +1 -1
  77. package/dist/translations/hi.js +1 -1
  78. package/dist/translations/hi.umd.js +1 -1
  79. package/dist/translations/hr.js +1 -1
  80. package/dist/translations/hr.umd.js +1 -1
  81. package/dist/translations/hu.js +1 -1
  82. package/dist/translations/hu.umd.js +1 -1
  83. package/dist/translations/id.js +1 -1
  84. package/dist/translations/id.umd.js +1 -1
  85. package/dist/translations/it.js +1 -1
  86. package/dist/translations/it.umd.js +1 -1
  87. package/dist/translations/ja.js +1 -1
  88. package/dist/translations/ja.umd.js +1 -1
  89. package/dist/translations/jv.js +1 -1
  90. package/dist/translations/jv.umd.js +1 -1
  91. package/dist/translations/km.js +1 -1
  92. package/dist/translations/km.umd.js +1 -1
  93. package/dist/translations/kn.js +1 -1
  94. package/dist/translations/kn.umd.js +1 -1
  95. package/dist/translations/ko.js +1 -1
  96. package/dist/translations/ko.umd.js +1 -1
  97. package/dist/translations/ku.js +1 -1
  98. package/dist/translations/ku.umd.js +1 -1
  99. package/dist/translations/lt.js +1 -1
  100. package/dist/translations/lt.umd.js +1 -1
  101. package/dist/translations/lv.js +1 -1
  102. package/dist/translations/lv.umd.js +1 -1
  103. package/dist/translations/ms.js +1 -1
  104. package/dist/translations/ms.umd.js +1 -1
  105. package/dist/translations/nb.js +1 -1
  106. package/dist/translations/nb.umd.js +1 -1
  107. package/dist/translations/ne.js +1 -1
  108. package/dist/translations/ne.umd.js +1 -1
  109. package/dist/translations/nl.js +1 -1
  110. package/dist/translations/nl.umd.js +1 -1
  111. package/dist/translations/no.js +1 -1
  112. package/dist/translations/no.umd.js +1 -1
  113. package/dist/translations/pl.js +1 -1
  114. package/dist/translations/pl.umd.js +1 -1
  115. package/dist/translations/pt-br.js +1 -1
  116. package/dist/translations/pt-br.umd.js +1 -1
  117. package/dist/translations/pt.js +1 -1
  118. package/dist/translations/pt.umd.js +1 -1
  119. package/dist/translations/ro.js +1 -1
  120. package/dist/translations/ro.umd.js +1 -1
  121. package/dist/translations/ru.js +1 -1
  122. package/dist/translations/ru.umd.js +1 -1
  123. package/dist/translations/sk.js +1 -1
  124. package/dist/translations/sk.umd.js +1 -1
  125. package/dist/translations/sl.js +1 -1
  126. package/dist/translations/sl.umd.js +1 -1
  127. package/dist/translations/sq.js +1 -1
  128. package/dist/translations/sq.umd.js +1 -1
  129. package/dist/translations/sr-latn.js +1 -1
  130. package/dist/translations/sr-latn.umd.js +1 -1
  131. package/dist/translations/sr.js +1 -1
  132. package/dist/translations/sr.umd.js +1 -1
  133. package/dist/translations/sv.js +1 -1
  134. package/dist/translations/sv.umd.js +1 -1
  135. package/dist/translations/th.js +1 -1
  136. package/dist/translations/th.umd.js +1 -1
  137. package/dist/translations/ti.js +1 -1
  138. package/dist/translations/ti.umd.js +1 -1
  139. package/dist/translations/tk.js +1 -1
  140. package/dist/translations/tk.umd.js +1 -1
  141. package/dist/translations/tr.js +1 -1
  142. package/dist/translations/tr.umd.js +1 -1
  143. package/dist/translations/tt.js +1 -1
  144. package/dist/translations/tt.umd.js +1 -1
  145. package/dist/translations/ug.js +1 -1
  146. package/dist/translations/ug.umd.js +1 -1
  147. package/dist/translations/uk.js +1 -1
  148. package/dist/translations/uk.umd.js +1 -1
  149. package/dist/translations/ur.js +1 -1
  150. package/dist/translations/ur.umd.js +1 -1
  151. package/dist/translations/uz.js +1 -1
  152. package/dist/translations/uz.umd.js +1 -1
  153. package/dist/translations/vi.js +1 -1
  154. package/dist/translations/vi.umd.js +1 -1
  155. package/dist/translations/zh-cn.js +1 -1
  156. package/dist/translations/zh-cn.umd.js +1 -1
  157. package/dist/translations/zh.js +1 -1
  158. package/dist/translations/zh.umd.js +1 -1
  159. package/lang/contexts.json +1 -1
  160. package/lang/translations/af.po +4 -4
  161. package/lang/translations/ar.po +4 -4
  162. package/lang/translations/ast.po +4 -4
  163. package/lang/translations/az.po +4 -4
  164. package/lang/translations/bg.po +4 -4
  165. package/lang/translations/bn.po +4 -4
  166. package/lang/translations/bs.po +4 -4
  167. package/lang/translations/ca.po +4 -4
  168. package/lang/translations/cs.po +4 -4
  169. package/lang/translations/da.po +4 -4
  170. package/lang/translations/de-ch.po +4 -4
  171. package/lang/translations/de.po +4 -4
  172. package/lang/translations/el.po +4 -4
  173. package/lang/translations/en-au.po +4 -4
  174. package/lang/translations/en-gb.po +4 -4
  175. package/lang/translations/en.po +4 -4
  176. package/lang/translations/eo.po +4 -4
  177. package/lang/translations/es-co.po +4 -4
  178. package/lang/translations/es.po +4 -4
  179. package/lang/translations/et.po +4 -4
  180. package/lang/translations/eu.po +4 -4
  181. package/lang/translations/fa.po +4 -4
  182. package/lang/translations/fi.po +4 -4
  183. package/lang/translations/fr.po +4 -4
  184. package/lang/translations/gl.po +4 -4
  185. package/lang/translations/he.po +4 -4
  186. package/lang/translations/hi.po +4 -4
  187. package/lang/translations/hr.po +4 -4
  188. package/lang/translations/hu.po +4 -4
  189. package/lang/translations/id.po +4 -4
  190. package/lang/translations/it.po +4 -4
  191. package/lang/translations/ja.po +4 -4
  192. package/lang/translations/jv.po +4 -4
  193. package/lang/translations/km.po +4 -4
  194. package/lang/translations/kn.po +4 -4
  195. package/lang/translations/ko.po +4 -4
  196. package/lang/translations/ku.po +4 -4
  197. package/lang/translations/lt.po +4 -4
  198. package/lang/translations/lv.po +4 -4
  199. package/lang/translations/ms.po +4 -4
  200. package/lang/translations/nb.po +4 -4
  201. package/lang/translations/ne.po +4 -4
  202. package/lang/translations/nl.po +4 -4
  203. package/lang/translations/no.po +4 -4
  204. package/lang/translations/pl.po +4 -4
  205. package/lang/translations/pt-br.po +4 -4
  206. package/lang/translations/pt.po +4 -4
  207. package/lang/translations/ro.po +4 -4
  208. package/lang/translations/ru.po +4 -4
  209. package/lang/translations/sk.po +4 -4
  210. package/lang/translations/sl.po +4 -4
  211. package/lang/translations/sq.po +4 -4
  212. package/lang/translations/sr-latn.po +4 -4
  213. package/lang/translations/sr.po +4 -4
  214. package/lang/translations/sv.po +4 -4
  215. package/lang/translations/th.po +4 -4
  216. package/lang/translations/ti.po +4 -4
  217. package/lang/translations/tk.po +4 -4
  218. package/lang/translations/tr.po +4 -4
  219. package/lang/translations/tt.po +4 -4
  220. package/lang/translations/ug.po +4 -4
  221. package/lang/translations/uk.po +4 -4
  222. package/lang/translations/ur.po +4 -4
  223. package/lang/translations/uz.po +4 -4
  224. package/lang/translations/vi.po +4 -4
  225. package/lang/translations/zh-cn.po +4 -4
  226. package/lang/translations/zh.po +4 -4
  227. package/package.json +4 -3
  228. package/src/bindings/clickoutsidehandler.d.ts +5 -3
  229. package/src/bindings/clickoutsidehandler.js +3 -2
  230. package/src/dialog/dialog.js +0 -1
  231. package/src/dropdown/dropdownview.d.ts +21 -8
  232. package/src/dropdown/menu/dropdownmenubehaviors.d.ts +44 -0
  233. package/src/dropdown/menu/dropdownmenubehaviors.js +119 -0
  234. package/src/dropdown/menu/dropdownmenubuttonview.d.ts +36 -0
  235. package/src/dropdown/menu/dropdownmenubuttonview.js +65 -0
  236. package/src/dropdown/menu/dropdownmenulistitembuttonview.d.ts +17 -0
  237. package/src/dropdown/menu/dropdownmenulistitembuttonview.js +29 -0
  238. package/src/dropdown/menu/dropdownmenulistitemview.d.ts +22 -0
  239. package/src/dropdown/menu/dropdownmenulistitemview.js +34 -0
  240. package/src/dropdown/menu/dropdownmenulistview.d.ts +24 -0
  241. package/src/dropdown/menu/dropdownmenulistview.js +29 -0
  242. package/src/dropdown/menu/dropdownmenunestedmenupanelview.d.ts +34 -0
  243. package/src/dropdown/menu/dropdownmenunestedmenupanelview.js +63 -0
  244. package/src/dropdown/menu/dropdownmenunestedmenuview.d.ts +131 -0
  245. package/src/dropdown/menu/dropdownmenunestedmenuview.js +191 -0
  246. package/src/dropdown/menu/dropdownmenurootlistview.d.ts +140 -0
  247. package/src/dropdown/menu/dropdownmenurootlistview.js +160 -0
  248. package/src/dropdown/menu/utils.d.ts +124 -0
  249. package/src/dropdown/menu/utils.js +61 -0
  250. package/src/dropdown/utils.d.ts +58 -0
  251. package/src/dropdown/utils.js +101 -18
  252. package/src/editableui/editableuiview.d.ts +1 -1
  253. package/src/editableui/inline/inlineeditableuiview.d.ts +13 -9
  254. package/src/editableui/inline/inlineeditableuiview.js +29 -6
  255. package/src/editorui/accessibilityhelp/accessibilityhelp.js +3 -1
  256. package/src/editorui/editorui.d.ts +4 -0
  257. package/src/editorui/editorui.js +16 -1
  258. package/src/editorui/poweredby.js +0 -1
  259. package/src/index.d.ts +7 -1
  260. package/src/index.js +6 -0
  261. package/src/menubar/menubarmenuview.js +1 -0
  262. package/src/menubar/utils.d.ts +5 -5
  263. package/src/menubar/utils.js +21 -12
  264. package/src/panel/balloon/balloonpanelview.js +19 -12
  265. package/src/panel/balloon/contextualballoon.d.ts +12 -6
  266. package/src/panel/balloon/contextualballoon.js +24 -24
  267. package/src/toolbar/balloon/balloontoolbar.d.ts +5 -0
  268. package/src/toolbar/balloon/balloontoolbar.js +26 -5
  269. package/src/toolbar/block/blocktoolbar.js +0 -2
  270. package/theme/components/dropdown/menu/dropdownmenu.css +8 -0
  271. package/theme/components/dropdown/menu/dropdownmenubutton.css +9 -0
  272. package/theme/components/dropdown/menu/dropdownmenulistitem.css +10 -0
  273. package/theme/components/dropdown/menu/dropdownmenulistitembutton.css +10 -0
  274. package/theme/components/dropdown/menu/dropdownmenupanel.css +11 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ui/dropdown/menu/dropdownmenurootlistview
7
+ */
8
+ import DropdownMenuListItemButtonView from './dropdownmenulistitembuttonview.js';
9
+ import DropdownMenuNestedMenuView from './dropdownmenunestedmenuview.js';
10
+ import DropdownMenuListView from './dropdownmenulistview.js';
11
+ import type BodyCollection from '../../editorui/bodycollection.js';
12
+ import type { DropdownMenuDefinition } from './utils.js';
13
+ import type { Locale, BaseEvent } from '@ckeditor/ckeditor5-utils';
14
+ /**
15
+ * Creates and manages a multi-level menu UI structure, suitable to be used inside dropdown components.
16
+ *
17
+ * This class creates a menu structure based on {@link module:ui/dropdown/menu/utils~DropdownMenuDefinition declarative definition}
18
+ * passed in the constructor.
19
+ *
20
+ * Below is an example of a simple definition, that describes a menu with two sub-menus (Menu 1, Menu 2) and four buttons in total (Item A,
21
+ * Item B, Item C, Item D):
22
+ *
23
+ * ```js
24
+ * [
25
+ * {
26
+ * id: 'menu_1',
27
+ * menu: 'Menu 1',
28
+ * children: [
29
+ * { id: 'menu_1_a', label: 'Item A' },
30
+ * { id: 'menu_1_b', label: 'Item B' }
31
+ * ]
32
+ * },
33
+ * {
34
+ * id: 'menu_2',
35
+ * menu: 'Menu 2',
36
+ * children: [
37
+ * { id: 'menu_2_c', label: 'Item C' },
38
+ * ]
39
+ * },
40
+ * { id: 'item_d', label: 'Item D' }
41
+ * ]
42
+ * ```
43
+ *
44
+ * The menu is build using multiple view classes. The most important are:
45
+ *
46
+ * * {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView `DropdownMenuNestedMenuView`} - "menu" - provides
47
+ * a panel with a nested menu, and a button which opens the panel,
48
+ * * {@link module:ui/dropdown/menu/dropdownmenulistitembuttonview~DropdownMenuListItemButtonView `DropdownMenuListItemButtonView`} -
49
+ * "button" or "leaf button" (as opposed to buttons provided by `DropdownMenuNestedMenuView`) - should trigger some action when pressed.
50
+ *
51
+ * Instances of these two classes are created based on the data provided in definitions. They are assigned proper IDs and labels.
52
+ * Other view classes build a proper DOM structure around menus and buttons.
53
+ *
54
+ * The `DropdownMenuNestedMenuView` instances provides panels, which may include further menus or buttons. These panels are added to
55
+ * a `BodyCollection` view, which means they are appended outside the DOM editor and UI structure.
56
+ *
57
+ * When "leaf button" is pressed, it fires `execute` event which is delegated to `DropdownMenuRootListView` as `menu:execute` event. You
58
+ * can listen to this event to perform an action:
59
+ *
60
+ * ```js
61
+ * rootListView.on( 'menu:execute', evt => {
62
+ * console.log( evt.source.id ); // E.g. will print 'menu_1_a' when 'Item A' is pressed.
63
+ * } );
64
+ * ```
65
+ *
66
+ * All menus and "leaf" buttons created from the definition can be easily accessed through {@link ~DropdownMenuRootListView#menus `menus`}
67
+ * and {@link ~DropdownMenuRootListView#buttons `buttons`} properties.
68
+ *
69
+ * For performance reasons, the whole menu structure is created only when `DropdownMenuRootListView` is rendered for the first time.
70
+ *
71
+ * It is recommended to use this class together with {@link module:ui/dropdown/utils~addMenuToDropdown `addMenuToDropdown()` helper}.
72
+ */
73
+ export default class DropdownMenuRootListView extends DropdownMenuListView {
74
+ /**
75
+ * The CSS class to be applied to nested menu panels in this dropdown menu.
76
+ *
77
+ * It is necessary, as the panels are created in body collection, outside editor and UI structure.
78
+ */
79
+ menuPanelClass: string | undefined;
80
+ /**
81
+ * The definitions object used to create the whole menu structure.
82
+ */
83
+ private readonly _definition;
84
+ /**
85
+ * Cached array of all menus in the dropdown menu (including nested menus).
86
+ */
87
+ private _cachedMenus;
88
+ /**
89
+ * Cached array of all buttons in the dropdown menu (including buttons in nested menus).
90
+ */
91
+ private _cachedButtons;
92
+ /**
93
+ * Editor body collection into which nested menus panels will be appended.
94
+ */
95
+ private _bodyCollection;
96
+ /**
97
+ * Creates an instance of the DropdownMenuRootListView class.
98
+ *
99
+ * @param locale
100
+ * @param bodyCollection
101
+ * @param definition The definition object used to create the menu structure.
102
+ */
103
+ constructor(locale: Locale, bodyCollection: BodyCollection, definition: DropdownMenuDefinition);
104
+ /**
105
+ * Returns the array of all menus in the dropdown menu (including nested menus).
106
+ */
107
+ get menus(): Array<DropdownMenuNestedMenuView>;
108
+ /**
109
+ * Returns the array of all buttons in the dropdown menu (including buttons in nested menus).
110
+ *
111
+ * Note, that this includes only "leaf" buttons, as specified in the definition passed in constructor. Buttons created as a part of
112
+ * the nested menus, that open nested menus when hovered or pressed, are not included.
113
+ */
114
+ get buttons(): Array<DropdownMenuListItemButtonView>;
115
+ /**
116
+ * @inheritDoc
117
+ */
118
+ render(): void;
119
+ /**
120
+ * Closes all nested menus.
121
+ */
122
+ closeMenus(): void;
123
+ /**
124
+ * Recursively creates the whole view tree structure for the dropdown menu, according to the passed `definitions`.
125
+ *
126
+ * @private
127
+ */
128
+ private _createStructure;
129
+ }
130
+ /**
131
+ * Fired when one of the menu buttons is executed (through mouse click or keyboard).
132
+ *
133
+ * This event is a delegated `execute` event fired by the pressed button. The `event.source` is the button which was executed.
134
+ *
135
+ * @eventName ~DropdownMenuRootListView#menu:execute
136
+ */
137
+ export interface DropdownMenuRootListViewExecuteEvent extends BaseEvent {
138
+ name: 'menu:execute';
139
+ args: [];
140
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ui/dropdown/menu/dropdownmenurootlistview
7
+ */
8
+ import DropdownMenuListItemButtonView from './dropdownmenulistitembuttonview.js';
9
+ import DropdownMenuNestedMenuView from './dropdownmenunestedmenuview.js';
10
+ import DropdownMenuListView from './dropdownmenulistview.js';
11
+ import DropdownMenuListItemView from './dropdownmenulistitemview.js';
12
+ import { DropdownRootMenuBehaviors } from './dropdownmenubehaviors.js';
13
+ /**
14
+ * Creates and manages a multi-level menu UI structure, suitable to be used inside dropdown components.
15
+ *
16
+ * This class creates a menu structure based on {@link module:ui/dropdown/menu/utils~DropdownMenuDefinition declarative definition}
17
+ * passed in the constructor.
18
+ *
19
+ * Below is an example of a simple definition, that describes a menu with two sub-menus (Menu 1, Menu 2) and four buttons in total (Item A,
20
+ * Item B, Item C, Item D):
21
+ *
22
+ * ```js
23
+ * [
24
+ * {
25
+ * id: 'menu_1',
26
+ * menu: 'Menu 1',
27
+ * children: [
28
+ * { id: 'menu_1_a', label: 'Item A' },
29
+ * { id: 'menu_1_b', label: 'Item B' }
30
+ * ]
31
+ * },
32
+ * {
33
+ * id: 'menu_2',
34
+ * menu: 'Menu 2',
35
+ * children: [
36
+ * { id: 'menu_2_c', label: 'Item C' },
37
+ * ]
38
+ * },
39
+ * { id: 'item_d', label: 'Item D' }
40
+ * ]
41
+ * ```
42
+ *
43
+ * The menu is build using multiple view classes. The most important are:
44
+ *
45
+ * * {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView `DropdownMenuNestedMenuView`} - "menu" - provides
46
+ * a panel with a nested menu, and a button which opens the panel,
47
+ * * {@link module:ui/dropdown/menu/dropdownmenulistitembuttonview~DropdownMenuListItemButtonView `DropdownMenuListItemButtonView`} -
48
+ * "button" or "leaf button" (as opposed to buttons provided by `DropdownMenuNestedMenuView`) - should trigger some action when pressed.
49
+ *
50
+ * Instances of these two classes are created based on the data provided in definitions. They are assigned proper IDs and labels.
51
+ * Other view classes build a proper DOM structure around menus and buttons.
52
+ *
53
+ * The `DropdownMenuNestedMenuView` instances provides panels, which may include further menus or buttons. These panels are added to
54
+ * a `BodyCollection` view, which means they are appended outside the DOM editor and UI structure.
55
+ *
56
+ * When "leaf button" is pressed, it fires `execute` event which is delegated to `DropdownMenuRootListView` as `menu:execute` event. You
57
+ * can listen to this event to perform an action:
58
+ *
59
+ * ```js
60
+ * rootListView.on( 'menu:execute', evt => {
61
+ * console.log( evt.source.id ); // E.g. will print 'menu_1_a' when 'Item A' is pressed.
62
+ * } );
63
+ * ```
64
+ *
65
+ * All menus and "leaf" buttons created from the definition can be easily accessed through {@link ~DropdownMenuRootListView#menus `menus`}
66
+ * and {@link ~DropdownMenuRootListView#buttons `buttons`} properties.
67
+ *
68
+ * For performance reasons, the whole menu structure is created only when `DropdownMenuRootListView` is rendered for the first time.
69
+ *
70
+ * It is recommended to use this class together with {@link module:ui/dropdown/utils~addMenuToDropdown `addMenuToDropdown()` helper}.
71
+ */
72
+ export default class DropdownMenuRootListView extends DropdownMenuListView {
73
+ /**
74
+ * Creates an instance of the DropdownMenuRootListView class.
75
+ *
76
+ * @param locale
77
+ * @param bodyCollection
78
+ * @param definition The definition object used to create the menu structure.
79
+ */
80
+ constructor(locale, bodyCollection, definition) {
81
+ super(locale);
82
+ /**
83
+ * Cached array of all menus in the dropdown menu (including nested menus).
84
+ */
85
+ this._cachedMenus = [];
86
+ /**
87
+ * Cached array of all buttons in the dropdown menu (including buttons in nested menus).
88
+ */
89
+ this._cachedButtons = [];
90
+ this._bodyCollection = bodyCollection;
91
+ this._definition = definition;
92
+ this.set('menuPanelClass', undefined);
93
+ }
94
+ /**
95
+ * Returns the array of all menus in the dropdown menu (including nested menus).
96
+ */
97
+ get menus() {
98
+ return Array.from(this._cachedMenus.values());
99
+ }
100
+ /**
101
+ * Returns the array of all buttons in the dropdown menu (including buttons in nested menus).
102
+ *
103
+ * Note, that this includes only "leaf" buttons, as specified in the definition passed in constructor. Buttons created as a part of
104
+ * the nested menus, that open nested menus when hovered or pressed, are not included.
105
+ */
106
+ get buttons() {
107
+ return Array.from(this._cachedButtons.values());
108
+ }
109
+ /**
110
+ * @inheritDoc
111
+ */
112
+ render() {
113
+ this._createStructure(this._definition, null);
114
+ super.render();
115
+ DropdownRootMenuBehaviors.toggleMenusAndFocusItemsOnHover(this);
116
+ DropdownRootMenuBehaviors.closeMenuWhenAnotherOnTheSameLevelOpens(this);
117
+ }
118
+ /**
119
+ * Closes all nested menus.
120
+ */
121
+ closeMenus() {
122
+ this.menus.forEach(menu => {
123
+ menu.isOpen = false;
124
+ });
125
+ }
126
+ /**
127
+ * Recursively creates the whole view tree structure for the dropdown menu, according to the passed `definitions`.
128
+ *
129
+ * @private
130
+ */
131
+ _createStructure(definitions, parentMenuView) {
132
+ const items = [];
133
+ for (const def of definitions) {
134
+ let createdView;
135
+ if ('menu' in def) {
136
+ createdView = new DropdownMenuNestedMenuView(this.locale, this._bodyCollection, def.id, def.menu, parentMenuView);
137
+ createdView.panelView.bind('class').to(this, 'menuPanelClass');
138
+ if (!parentMenuView) {
139
+ createdView.delegate(...DropdownMenuNestedMenuView.DELEGATED_EVENTS).to(this, (name) => `menu:${name}`);
140
+ }
141
+ this._cachedMenus.push(createdView);
142
+ this._createStructure(def.children, createdView);
143
+ }
144
+ else {
145
+ createdView = new DropdownMenuListItemButtonView(this.locale, def.id, def.label);
146
+ if (!parentMenuView) {
147
+ createdView.delegate('execute').to(this, 'menu:execute');
148
+ }
149
+ this._cachedButtons.push(createdView);
150
+ }
151
+ const listItemView = new DropdownMenuListItemView(this.locale, parentMenuView, createdView);
152
+ if (!parentMenuView) {
153
+ listItemView.delegate('mouseenter').to(this, 'menu:mouseenter');
154
+ }
155
+ items.push(listItemView);
156
+ }
157
+ const targetListView = parentMenuView ? parentMenuView.listView : this;
158
+ targetListView.items.addMany(items);
159
+ }
160
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module ui/dropdown/menu/utils
7
+ */
8
+ import type { PositioningFunction } from '@ckeditor/ckeditor5-utils';
9
+ /**
10
+ * Contains every positioning function used by {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView} that
11
+ * decides where the {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView#panelView} should be placed.
12
+ *
13
+ * Positioning functions:
14
+ *
15
+ * ┌──────┬───────────────┐
16
+ * │ │ │
17
+ * └──────┤ │
18
+ * │ │
19
+ * │ ES │
20
+ * └───────────────┘
21
+ *
22
+ * ┌───────────────┬──────┐
23
+ * │ │ │
24
+ * │ ├──────┘
25
+ * │ │
26
+ * │ WS │
27
+ * └───────────────┘
28
+ *
29
+ * ┌───────────────┐
30
+ * │ EN │
31
+ * │ │
32
+ * ┌──────┤ │
33
+ * │ │ │
34
+ * └──────┴───────────────┘
35
+ *
36
+ * ┌───────────────┐
37
+ * │ WN │
38
+ * │ │
39
+ * │ ├──────┐
40
+ * │ │ │
41
+ * └───────────────┴──────┘
42
+ */
43
+ export declare const DropdownMenuPanelPositioningFunctions: Record<string, PositioningFunction>;
44
+ /**
45
+ * Represents the definition of a dropdown menu.
46
+ */
47
+ export type DropdownNestedMenuDefinition = {
48
+ /**
49
+ * Unique ID for the menu.
50
+ */
51
+ id: string;
52
+ /**
53
+ * The menu name. It is used as a label for the button which opens the menu list.
54
+ */
55
+ menu: string;
56
+ /**
57
+ * The children of the dropdown menu.
58
+ */
59
+ children: DropdownMenuDefinition;
60
+ };
61
+ /**
62
+ * Represents the definition of a dropdown menu item.
63
+ */
64
+ export type DropdownMenuButtonDefinition = {
65
+ /**
66
+ * Unique ID for the button.
67
+ */
68
+ id: string;
69
+ /**
70
+ * The label for the button.
71
+ */
72
+ label: string;
73
+ };
74
+ /**
75
+ * A definition for a nestable menu component.
76
+ *
77
+ * The menu can be flat and include only top-level items, or it can include multiple levels of nested sub-menus.
78
+ *
79
+ * Example:
80
+ *
81
+ * ```ts
82
+ * [
83
+ * {
84
+ * id: 'menu_1',
85
+ * menu: 'Menu 1',
86
+ * children: [
87
+ * {
88
+ * id: 'menu_1_1',
89
+ * menu: 'Nested menu 1',
90
+ * children: [
91
+ * {
92
+ * id: 'item_x',
93
+ * label: 'Item X'
94
+ * }
95
+ * ]
96
+ * },
97
+ * {
98
+ * id: 'menu_1_2',
99
+ * menu: 'Nested menu 2',
100
+ * children: [
101
+ * {
102
+ * id: 'item_y',
103
+ * label: 'Item Y'
104
+ * },
105
+ * {
106
+ * id: 'item_z',
107
+ * label: 'Item Z'
108
+ * }
109
+ * ]
110
+ * }
111
+ * ]
112
+ * },
113
+ * {
114
+ * id: 'top_a',
115
+ * label: 'Top Item A'
116
+ * },
117
+ * {
118
+ * id: 'top_b',
119
+ * label: 'Top Item B'
120
+ * }
121
+ * ];
122
+ * ```
123
+ */
124
+ export type DropdownMenuDefinition = Array<DropdownNestedMenuDefinition | DropdownMenuButtonDefinition>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ const NESTED_PANEL_HORIZONTAL_OFFSET = 5;
6
+ /**
7
+ * Contains every positioning function used by {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView} that
8
+ * decides where the {@link module:ui/dropdown/menu/dropdownmenunestedmenuview~DropdownMenuNestedMenuView#panelView} should be placed.
9
+ *
10
+ * Positioning functions:
11
+ *
12
+ * ┌──────┬───────────────┐
13
+ * │ │ │
14
+ * └──────┤ │
15
+ * │ │
16
+ * │ ES │
17
+ * └───────────────┘
18
+ *
19
+ * ┌───────────────┬──────┐
20
+ * │ │ │
21
+ * │ ├──────┘
22
+ * │ │
23
+ * │ WS │
24
+ * └───────────────┘
25
+ *
26
+ * ┌───────────────┐
27
+ * │ EN │
28
+ * │ │
29
+ * ┌──────┤ │
30
+ * │ │ │
31
+ * └──────┴───────────────┘
32
+ *
33
+ * ┌───────────────┐
34
+ * │ WN │
35
+ * │ │
36
+ * │ ├──────┐
37
+ * │ │ │
38
+ * └───────────────┴──────┘
39
+ */
40
+ export const DropdownMenuPanelPositioningFunctions = {
41
+ eastSouth: buttonRect => ({
42
+ top: buttonRect.top,
43
+ left: buttonRect.right - NESTED_PANEL_HORIZONTAL_OFFSET,
44
+ name: 'es'
45
+ }),
46
+ eastNorth: (buttonRect, panelRect) => ({
47
+ top: buttonRect.top - panelRect.height + buttonRect.height,
48
+ left: buttonRect.right - NESTED_PANEL_HORIZONTAL_OFFSET,
49
+ name: 'en'
50
+ }),
51
+ westSouth: (buttonRect, panelRect) => ({
52
+ top: buttonRect.top,
53
+ left: buttonRect.left - panelRect.width + NESTED_PANEL_HORIZONTAL_OFFSET,
54
+ name: 'ws'
55
+ }),
56
+ westNorth: (buttonRect, panelRect) => ({
57
+ top: buttonRect.top - panelRect.height + buttonRect.height,
58
+ left: buttonRect.left - panelRect.width + NESTED_PANEL_HORIZONTAL_OFFSET,
59
+ name: 'wn'
60
+ })
61
+ };
@@ -9,9 +9,11 @@ import type Model from '../model.js';
9
9
  import type DropdownButton from './button/dropdownbutton.js';
10
10
  import type { FocusableView } from '../focuscycler.js';
11
11
  import type { FalsyValue } from '../template.js';
12
+ import type BodyCollection from '../editorui/bodycollection.js';
12
13
  import { type Collection, type Locale } from '@ckeditor/ckeditor5-utils';
13
14
  import '../../theme/components/dropdown/toolbardropdown.css';
14
15
  import '../../theme/components/dropdown/listdropdown.css';
16
+ import type { DropdownMenuDefinition } from './menu/utils.js';
15
17
  /**
16
18
  * A helper for creating dropdowns. It creates an instance of a {@link module:ui/dropdown/dropdownview~DropdownView dropdown},
17
19
  * with a {@link module:ui/dropdown/button/dropdownbutton~DropdownButton button},
@@ -77,10 +79,66 @@ import '../../theme/components/dropdown/listdropdown.css';
77
79
  *
78
80
  * @param locale The locale instance.
79
81
  * @param ButtonClassOrInstance The dropdown button view class. Needs to implement the
82
+ * @param behaviorOptions Attributes for the default behavior of the dropdown.
83
+ *
80
84
  * {@link module:ui/dropdown/button/dropdownbutton~DropdownButton} interface.
81
85
  * @returns The dropdown view instance.
82
86
  */
83
87
  export declare function createDropdown(locale: Locale | undefined, ButtonClassOrInstance?: (new (locale?: Locale) => DropdownButton & FocusableView) | (DropdownButton & FocusableView)): DropdownView;
88
+ /**
89
+ * Adds a menu UI component to a dropdown and sets all common behaviors and interactions between the dropdown and the menu.
90
+ *
91
+ * Use this helper to create multi-level dropdown menus that are displayed in a toolbar.
92
+ *
93
+ * Internally, it creates an instance of {@link module:ui/dropdown/menu/dropdownmenurootlistview~DropdownMenuRootListView}.
94
+ *
95
+ * Example:
96
+ *
97
+ * ```ts
98
+ * const definitions = [
99
+ * {
100
+ * id: 'menu_1',
101
+ * menu: 'Menu 1',
102
+ * children: [
103
+ * {
104
+ * id: 'menu_1_a',
105
+ * label: 'Item A'
106
+ * },
107
+ * {
108
+ * id: 'menu_1_b',
109
+ * label: 'Item B'
110
+ * }
111
+ * ]
112
+ * },
113
+ * {
114
+ * id: 'top_a',
115
+ * label: 'Top Item A'
116
+ * },
117
+ * {
118
+ * id: 'top_b',
119
+ * label: 'Top Item B'
120
+ * }
121
+ * ];
122
+ *
123
+ * const dropdownView = createDropdown( editor.locale );
124
+ *
125
+ * addMenuToDropdown( dropdownView, editor.ui.view.body, definitions );
126
+ * ```
127
+ *
128
+ * After using this helper, the `dropdown` will fire {@link module:ui/dropdown/dropdownview~DropdownViewEvent `execute`} event when
129
+ * a nested menu button is pressed.
130
+ *
131
+ * The helper will make sure that the `dropdownMenuRootListView` is lazy loaded, i.e., the menu component structure will be initialized
132
+ * and rendered only after the `dropdown` is opened for the first time.
133
+ *
134
+ * @param dropdownView A dropdown instance to which the menu component will be added.
135
+ * @param body Body collection to which floating menu panels will be added.
136
+ * @param definition The menu component definition.
137
+ * @param options.ariaLabel Label used by assistive technologies to describe the top-level menu.
138
+ */
139
+ export declare function addMenuToDropdown(dropdownView: DropdownView, body: BodyCollection, definition: DropdownMenuDefinition, options?: {
140
+ ariaLabel?: string;
141
+ }): void;
84
142
  /**
85
143
  * Adds an instance of {@link module:ui/toolbar/toolbarview~ToolbarView} to a dropdown.
86
144
  *