@ckeditor/ckeditor5-ui 35.4.0 → 36.0.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 (89) hide show
  1. package/LICENSE.md +1 -1
  2. package/package.json +21 -21
  3. package/src/bindings/addkeyboardhandlingforgrid.js +1 -1
  4. package/src/bindings/clickoutsidehandler.js +5 -7
  5. package/src/bindings/injectcsstransitiondisabler.js +1 -1
  6. package/src/bindings/preventdefault.js +1 -1
  7. package/src/bindings/submithandler.js +1 -1
  8. package/src/button/button.js +1 -1
  9. package/src/button/buttonview.js +1 -1
  10. package/src/button/switchbuttonview.js +1 -1
  11. package/src/colorgrid/colorgridview.js +1 -1
  12. package/src/colorgrid/colortileview.js +1 -1
  13. package/src/colorgrid/utils.js +1 -1
  14. package/src/componentfactory.js +1 -1
  15. package/src/dropdown/button/dropdownbutton.js +1 -1
  16. package/src/dropdown/button/dropdownbuttonview.js +1 -1
  17. package/src/dropdown/button/splitbuttonview.js +1 -1
  18. package/src/dropdown/dropdownpanelfocusable.js +1 -1
  19. package/src/dropdown/dropdownpanelview.js +1 -1
  20. package/src/dropdown/dropdownview.js +1 -1
  21. package/src/dropdown/utils.js +84 -27
  22. package/src/editableui/editableuiview.js +1 -1
  23. package/src/editableui/inline/inlineeditableuiview.js +1 -1
  24. package/src/editorui/bodycollection.js +1 -1
  25. package/src/editorui/boxed/boxededitoruiview.js +1 -1
  26. package/src/editorui/editorui.js +476 -0
  27. package/src/editorui/editoruiview.js +1 -1
  28. package/src/focuscycler.js +1 -1
  29. package/src/formheader/formheaderview.js +1 -1
  30. package/src/icon/iconview.js +1 -1
  31. package/src/iframe/iframeview.js +10 -10
  32. package/src/index.js +3 -1
  33. package/src/input/inputview.js +1 -1
  34. package/src/inputnumber/inputnumberview.js +1 -1
  35. package/src/inputtext/inputtextview.js +1 -1
  36. package/src/label/labelview.js +1 -1
  37. package/src/labeledfield/labeledfieldview.js +1 -1
  38. package/src/labeledfield/utils.js +1 -1
  39. package/src/labeledinput/labeledinputview.js +1 -1
  40. package/src/list/listitemview.js +1 -1
  41. package/src/list/listseparatorview.js +1 -1
  42. package/src/list/listview.js +10 -2
  43. package/src/model.js +1 -1
  44. package/src/notification/notification.js +1 -1
  45. package/src/panel/balloon/balloonpanelview.js +1 -1
  46. package/src/panel/balloon/contextualballoon.js +37 -15
  47. package/src/panel/sticky/stickypanelview.js +1 -1
  48. package/src/template.js +1 -1
  49. package/src/toolbar/balloon/balloontoolbar.js +3 -3
  50. package/src/toolbar/block/blockbuttonview.js +1 -1
  51. package/src/toolbar/block/blocktoolbar.js +1 -1
  52. package/src/toolbar/normalizetoolbarconfig.js +1 -1
  53. package/src/toolbar/toolbarlinebreakview.js +1 -1
  54. package/src/toolbar/toolbarseparatorview.js +1 -1
  55. package/src/toolbar/toolbarview.js +15 -7
  56. package/src/tooltipmanager.js +1 -1
  57. package/src/view.js +1 -1
  58. package/src/viewcollection.js +1 -1
  59. package/theme/components/button/button.css +1 -1
  60. package/theme/components/button/switchbutton.css +1 -1
  61. package/theme/components/colorgrid/colorgrid.css +1 -1
  62. package/theme/components/dropdown/dropdown.css +1 -1
  63. package/theme/components/dropdown/listdropdown.css +1 -1
  64. package/theme/components/dropdown/splitbutton.css +1 -1
  65. package/theme/components/dropdown/toolbardropdown.css +1 -1
  66. package/theme/components/editorui/editorui.css +1 -1
  67. package/theme/components/formheader/formheader.css +1 -1
  68. package/theme/components/icon/icon.css +1 -1
  69. package/theme/components/input/input.css +1 -1
  70. package/theme/components/label/label.css +1 -1
  71. package/theme/components/labeledfield/labeledfieldview.css +1 -1
  72. package/theme/components/labeledinput/labeledinput.css +1 -1
  73. package/theme/components/list/list.css +1 -1
  74. package/theme/components/panel/balloonpanel.css +1 -1
  75. package/theme/components/panel/balloonrotator.css +1 -1
  76. package/theme/components/panel/fakepanel.css +1 -1
  77. package/theme/components/panel/stickypanel.css +1 -1
  78. package/theme/components/responsive-form/responsiveform.css +1 -1
  79. package/theme/components/toolbar/blocktoolbar.css +1 -1
  80. package/theme/components/toolbar/toolbar.css +1 -1
  81. package/theme/components/tooltip/tooltip.css +1 -1
  82. package/theme/globals/_hidden.css +1 -1
  83. package/theme/globals/_reset.css +1 -1
  84. package/theme/globals/_transition.css +1 -1
  85. package/theme/globals/_zindex.css +1 -1
  86. package/theme/globals/globals.css +1 -1
  87. package/theme/mixins/_dir.css +1 -1
  88. package/theme/mixins/_rwd.css +1 -1
  89. package/theme/mixins/_unselectable.css +1 -1
package/LICENSE.md CHANGED
@@ -2,7 +2,7 @@ Software License Agreement
2
2
  ==========================
3
3
 
4
4
  **CKEditor 5 UI framework** – https://github.com/ckeditor/ckeditor5-ui <br>
5
- Copyright (c) 2003-2022, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
5
+ Copyright (c) 2003-2023, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
6
6
 
7
7
  Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-ui",
3
- "version": "35.4.0",
3
+ "version": "36.0.1",
4
4
  "description": "The UI framework and standard UI library of CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -11,29 +11,29 @@
11
11
  ],
12
12
  "main": "src/index.js",
13
13
  "dependencies": {
14
- "@ckeditor/ckeditor5-utils": "^35.4.0",
15
- "@ckeditor/ckeditor5-core": "^35.4.0",
14
+ "@ckeditor/ckeditor5-utils": "^36.0.1",
15
+ "@ckeditor/ckeditor5-core": "^36.0.1",
16
16
  "lodash-es": "^4.17.15"
17
17
  },
18
18
  "devDependencies": {
19
- "@ckeditor/ckeditor5-basic-styles": "^35.4.0",
20
- "@ckeditor/ckeditor5-block-quote": "^35.4.0",
21
- "@ckeditor/ckeditor5-editor-balloon": "^35.4.0",
22
- "@ckeditor/ckeditor5-editor-classic": "^35.4.0",
23
- "@ckeditor/ckeditor5-engine": "^35.4.0",
24
- "@ckeditor/ckeditor5-enter": "^35.4.0",
25
- "@ckeditor/ckeditor5-essentials": "^35.4.0",
26
- "@ckeditor/ckeditor5-font": "^35.4.0",
27
- "@ckeditor/ckeditor5-find-and-replace": "^35.4.0",
28
- "@ckeditor/ckeditor5-heading": "^35.4.0",
29
- "@ckeditor/ckeditor5-image": "^35.4.0",
30
- "@ckeditor/ckeditor5-link": "^35.4.0",
31
- "@ckeditor/ckeditor5-list": "^35.4.0",
32
- "@ckeditor/ckeditor5-mention": "^35.4.0",
33
- "@ckeditor/ckeditor5-paragraph": "^35.4.0",
34
- "@ckeditor/ckeditor5-horizontal-line": "^35.4.0",
35
- "@ckeditor/ckeditor5-table": "^35.4.0",
36
- "@ckeditor/ckeditor5-typing": "^35.4.0",
19
+ "@ckeditor/ckeditor5-basic-styles": "^36.0.1",
20
+ "@ckeditor/ckeditor5-block-quote": "^36.0.1",
21
+ "@ckeditor/ckeditor5-editor-balloon": "^36.0.1",
22
+ "@ckeditor/ckeditor5-editor-classic": "^36.0.1",
23
+ "@ckeditor/ckeditor5-engine": "^36.0.1",
24
+ "@ckeditor/ckeditor5-enter": "^36.0.1",
25
+ "@ckeditor/ckeditor5-essentials": "^36.0.1",
26
+ "@ckeditor/ckeditor5-font": "^36.0.1",
27
+ "@ckeditor/ckeditor5-find-and-replace": "^36.0.1",
28
+ "@ckeditor/ckeditor5-heading": "^36.0.1",
29
+ "@ckeditor/ckeditor5-image": "^36.0.1",
30
+ "@ckeditor/ckeditor5-link": "^36.0.1",
31
+ "@ckeditor/ckeditor5-list": "^36.0.1",
32
+ "@ckeditor/ckeditor5-mention": "^36.0.1",
33
+ "@ckeditor/ckeditor5-paragraph": "^36.0.1",
34
+ "@ckeditor/ckeditor5-horizontal-line": "^36.0.1",
35
+ "@ckeditor/ckeditor5-table": "^36.0.1",
36
+ "@ckeditor/ckeditor5-typing": "^36.0.1",
37
37
  "typescript": "^4.8.4",
38
38
  "webpack": "^5.58.1",
39
39
  "webpack-cli": "^4.9.0"
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,10 +1,7 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
- /**
6
- * @module ui/bindings/clickoutsidehandler
7
- */
8
5
  /* global document */
9
6
  /**
10
7
  * Handles clicking **outside** of a specified set of elements, then fires an action.
@@ -17,8 +14,8 @@
17
14
  * @param {module:utils/dom/emittermixin~Emitter} options.emitter The emitter to which this behavior
18
15
  * should be added.
19
16
  * @param {Function} options.activator Function returning a `Boolean`, to determine whether the handler is active.
20
- * @param {Array.<HTMLElement>} options.contextElements HTML elements that determine the scope of the
21
- * handler. Clicking any of them or their descendants will **not** fire the callback.
17
+ * @param {Array.<HTMLElement>} options.contextElements Array of HTML elements or a callback returning an array of HTML elements
18
+ * that determine the scope of the handler. Clicking any of them or their descendants will **not** fire the callback.
22
19
  * @param {Function} options.callback An action executed by the handler.
23
20
  */
24
21
  export default function clickOutsideHandler({ emitter, activator, callback, contextElements }) {
@@ -29,7 +26,8 @@ export default function clickOutsideHandler({ emitter, activator, callback, cont
29
26
  // Check if `composedPath` is `undefined` in case the browser does not support native shadow DOM.
30
27
  // Can be removed when all supported browsers support native shadow DOM.
31
28
  const path = typeof domEvt.composedPath == 'function' ? domEvt.composedPath() : [];
32
- for (const contextElement of contextElements) {
29
+ const contextElementsList = typeof contextElements == 'function' ? contextElements() : contextElements;
30
+ for (const contextElement of contextElementsList) {
33
31
  if (contextElement.contains(domEvt.target) || path.includes(contextElement)) {
34
32
  return;
35
33
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -15,6 +15,7 @@ import ListSeparatorView from '../list/listseparatorview';
15
15
  import ButtonView from '../button/buttonview';
16
16
  import SplitButtonView from './button/splitbuttonview';
17
17
  import SwitchButtonView from '../button/switchbuttonview';
18
+ import ViewCollection from '../viewcollection';
18
19
  import clickOutsideHandler from '../bindings/clickoutsidehandler';
19
20
  import { global, priorities, logWarning } from '@ckeditor/ckeditor5-utils';
20
21
  import '../../theme/components/dropdown/toolbardropdown.css';
@@ -98,30 +99,33 @@ export function createDropdown(locale, ButtonClass = DropdownButtonView) {
98
99
  /**
99
100
  * Adds an instance of {@link module:ui/toolbar/toolbarview~ToolbarView} to a dropdown.
100
101
  *
101
- * const buttons = [];
102
+ * const buttonsCreator = () => {
103
+ * const buttons = [];
102
104
  *
103
- * // Either create a new ButtonView instance or create existing.
104
- * buttons.push( new ButtonView() );
105
- * buttons.push( editor.ui.componentFactory.create( 'someButton' ) );
105
+ * // Either create a new ButtonView instance or create existing.
106
+ * buttons.push( new ButtonView() );
107
+ * buttons.push( editor.ui.componentFactory.create( 'someButton' ) );
108
+ * };
106
109
  *
107
110
  * const dropdown = createDropdown( locale );
108
111
  *
109
- * addToolbarToDropdown( dropdown, buttons );
110
- *
111
- * dropdown.toolbarView.isVertical = true;
112
+ * addToolbarToDropdown( dropdown, buttonsCreator, { isVertical: true } );
112
113
  *
113
114
  * // Will render a vertical button dropdown labeled "A button dropdown"
114
115
  * // with a button group in the panel containing two buttons.
116
+ * // Buttons inside the dropdown will be created on first dropdown panel open.
115
117
  * dropdown.render()
116
118
  * document.body.appendChild( dropdown.element );
117
119
  *
118
120
  * **Note:** To improve the accessibility, you can tell the dropdown to focus the first active button of the toolbar when the dropdown
119
121
  * {@link module:ui/dropdown/dropdownview~DropdownView#isOpen gets open}. See the documentation of `options` to learn more.
120
122
  *
123
+ * **Note:** Toolbar view will be created on first open of the dropdown.
124
+ *
121
125
  * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:ui/toolbar/toolbarview~ToolbarView}.
122
126
  *
123
127
  * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which `ToolbarView` will be added.
124
- * @param {Iterable.<module:ui/button/buttonview~ButtonView>} buttons
128
+ * @param {Iterable.<module:ui/button/buttonview~ButtonView>|Function} buttonsOrCallback
125
129
  * @param {Object} [options]
126
130
  * @param {Boolean} [options.enableActiveItemFocusOnDropdownOpen=false] When set `true`, the focus will automatically move to the first
127
131
  * active {@link module:ui/toolbar/toolbarview~ToolbarView#items item} of the toolbar upon
@@ -129,21 +133,56 @@ export function createDropdown(locale, ButtonClass = DropdownButtonView) {
129
133
  * `true` (for instance {@link module:ui/button/buttonview~ButtonView buttons}). If no active items is found, the toolbar will be focused
130
134
  * as a whole resulting in the focus moving to its first focusable item (default behavior of
131
135
  * {@link module:ui/dropdown/dropdownview~DropdownView}).
136
+ * @param {String} [options.ariaLabel] Label used by assistive technologies to describe toolbar element.
137
+ * @param {String} [options.maxWidth] The maximum width of the toolbar element.
138
+ * Details: {@link module:ui/toolbar/toolbarview~ToolbarView#maxWidth}.
139
+ * @param {String} [options.class] An additional CSS class added to the toolbar element.
140
+ * @param {Boolean} [options.isCompact] When set true, makes the toolbar look compact with toolbar element.
141
+ * @param {Boolean} [options.isVertical] Controls the orientation of toolbar items.
132
142
  */
133
- export function addToolbarToDropdown(dropdownView, buttons, options = {}) {
134
- const locale = dropdownView.locale;
135
- const t = locale.t;
136
- const toolbarView = dropdownView.toolbarView = new ToolbarView(locale);
137
- toolbarView.set('ariaLabel', t('Dropdown toolbar'));
143
+ export function addToolbarToDropdown(dropdownView, buttonsOrCallback, options = {}) {
138
144
  dropdownView.extendTemplate({
139
145
  attributes: {
140
146
  class: ['ck-toolbar-dropdown']
141
147
  }
142
148
  });
143
- buttons.map(view => toolbarView.items.add(view));
149
+ if (dropdownView.isOpen) {
150
+ addToolbarToOpenDropdown(dropdownView, buttonsOrCallback, options);
151
+ }
152
+ else {
153
+ dropdownView.once('change:isOpen', () => addToolbarToOpenDropdown(dropdownView, buttonsOrCallback, options), { priority: 'highest' });
154
+ }
144
155
  if (options.enableActiveItemFocusOnDropdownOpen) {
145
156
  // Accessibility: Focus the first active button in the toolbar when the dropdown gets open.
146
- focusChildOnDropdownOpen(dropdownView, () => toolbarView.items.find((item) => item.isOn));
157
+ focusChildOnDropdownOpen(dropdownView, () => dropdownView.toolbarView.items.find((item) => item.isOn));
158
+ }
159
+ }
160
+ /**
161
+ * Adds an instance of {@link module:ui/toolbar/toolbarview~ToolbarView} to a dropdown.
162
+ */
163
+ function addToolbarToOpenDropdown(dropdownView, buttonsOrCallback, options) {
164
+ const locale = dropdownView.locale;
165
+ const t = locale.t;
166
+ const toolbarView = dropdownView.toolbarView = new ToolbarView(locale);
167
+ const buttons = typeof buttonsOrCallback == 'function' ? buttonsOrCallback() : buttonsOrCallback;
168
+ toolbarView.ariaLabel = options.ariaLabel || t('Dropdown toolbar');
169
+ if (options.maxWidth) {
170
+ toolbarView.maxWidth = options.maxWidth;
171
+ }
172
+ if (options.class) {
173
+ toolbarView.class = options.class;
174
+ }
175
+ if (options.isCompact) {
176
+ toolbarView.isCompact = options.isCompact;
177
+ }
178
+ if (options.isVertical) {
179
+ toolbarView.isVertical = true;
180
+ }
181
+ if (buttons instanceof ViewCollection) {
182
+ toolbarView.items.bindTo(buttons).using(item => item);
183
+ }
184
+ else {
185
+ toolbarView.items.addMany(buttons);
147
186
  }
148
187
  dropdownView.panelView.children.add(toolbarView);
149
188
  toolbarView.items.delegate('execute').to(dropdownView);
@@ -187,15 +226,39 @@ export function addToolbarToDropdown(dropdownView, buttons, options = {}) {
187
226
  * to focus the first active item (a host to a {@link module:ui/button/buttonview~ButtonView} with
188
227
  * {@link module:ui/button/buttonview~ButtonView#isOn} set `true`) or the very first item when none are active.
189
228
  *
229
+ * **Note:** List view will be created on first open of the dropdown.
230
+ *
190
231
  * See {@link module:ui/dropdown/utils~createDropdown} and {@link module:list/list~List}.
191
232
  *
192
233
  * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdown instance to which `ListVIew` will be added.
193
- * @param {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>} items
194
- * A collection of the list item definitions to populate the list.
234
+ * @param {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>|Function} itemsOrCallback A collection of the list item
235
+ * definitions or a callback returning a list item definitions to populate the list.
236
+ * @param {Object} [options]
237
+ * @param {String} [options.ariaLabel] Label used by assistive technologies to describe list element.
195
238
  */
196
- export function addListToDropdown(dropdownView, items) {
239
+ export function addListToDropdown(dropdownView, itemsOrCallback, options = {}) {
240
+ if (dropdownView.isOpen) {
241
+ addListToOpenDropdown(dropdownView, itemsOrCallback, options);
242
+ }
243
+ else {
244
+ dropdownView.once('change:isOpen', () => addListToOpenDropdown(dropdownView, itemsOrCallback, options), { priority: 'highest' });
245
+ }
246
+ // Accessibility: Focus the first active button in the list when the dropdown gets open.
247
+ focusChildOnDropdownOpen(dropdownView, () => dropdownView.listView.items.find(item => {
248
+ if (item instanceof ListItemView) {
249
+ return item.children.first.isOn;
250
+ }
251
+ return false;
252
+ }));
253
+ }
254
+ /**
255
+ * Adds an instance of {@link module:ui/list/listview~ListView} to a dropdown.
256
+ */
257
+ function addListToOpenDropdown(dropdownView, itemsOrCallback, options) {
197
258
  const locale = dropdownView.locale;
198
259
  const listView = dropdownView.listView = new ListView(locale);
260
+ const items = typeof itemsOrCallback == 'function' ? itemsOrCallback() : itemsOrCallback;
261
+ listView.ariaLabel = options.ariaLabel;
199
262
  listView.items.bindTo(items).using(def => {
200
263
  if (def.type === 'separator') {
201
264
  return new ListSeparatorView(locale);
@@ -219,13 +282,6 @@ export function addListToDropdown(dropdownView, items) {
219
282
  });
220
283
  dropdownView.panelView.children.add(listView);
221
284
  listView.items.delegate('execute').to(dropdownView);
222
- // Accessibility: Focus the first active button in the list when the dropdown gets open.
223
- focusChildOnDropdownOpen(dropdownView, () => listView.items.find(item => {
224
- if (item instanceof ListItemView) {
225
- return item.children.first.isOn;
226
- }
227
- return false;
228
- }));
229
285
  }
230
286
  /**
231
287
  * A helper to be used on an existing {@link module:ui/dropdown/dropdownview~DropdownView} that focuses
@@ -344,10 +400,11 @@ function focusDropdownButtonOnClose(dropdownView) {
344
400
  if (isOpen) {
345
401
  return;
346
402
  }
403
+ const element = dropdownView.panelView.element;
347
404
  // If the dropdown was closed, move the focus back to the button (#12125).
348
405
  // Don't touch the focus, if it moved somewhere else (e.g. moved to the editing root on #execute) (#12178).
349
406
  // Note: Don't use the state of the DropdownView#focusTracker here. It fires #blur with the timeout.
350
- if (dropdownView.panelView.element.contains(global.document.activeElement)) {
407
+ if (element && element.contains(global.document.activeElement)) {
351
408
  dropdownView.buttonView.focus();
352
409
  }
353
410
  });
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
  /**