@ckeditor/ckeditor5-ui 45.0.0-alpha.9 → 45.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.
- package/LICENSE.md +4 -0
- package/dist/index.js +244 -103
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/colorselector/colorgridsfragmentview.d.ts +9 -8
- package/src/colorselector/colorgridsfragmentview.js +9 -8
- package/src/colorselector/colorpickerfragmentview.d.ts +5 -4
- package/src/colorselector/colorpickerfragmentview.js +5 -4
- package/src/colorselector/colorselectorview.d.ts +8 -7
- package/src/colorselector/colorselectorview.js +9 -8
- package/src/componentfactory.js +1 -1
- package/src/dropdown/dropdownpanelview.js +2 -2
- package/src/dropdown/utils.d.ts +0 -2
- package/src/dropdown/utils.js +97 -20
- package/src/editorui/editorui.d.ts +29 -8
- package/src/editorui/editorui.js +56 -3
- package/src/menubar/menubarview.js +2 -2
- package/src/menubar/utils.js +7 -7
- package/src/panel/balloon/balloonpanelview.js +16 -8
- package/src/panel/balloon/contextualballoon.js +4 -1
- package/src/panel/sticky/stickypanelview.d.ts +0 -4
- package/src/panel/sticky/stickypanelview.js +35 -29
- package/src/textarea/textareaview.js +3 -3
- package/src/toolbar/toolbarview.d.ts +1 -1
- package/src/toolbar/toolbarview.js +1 -1
- package/src/tooltipmanager.d.ts +2 -0
- package/src/tooltipmanager.js +2 -0
- package/src/viewcollection.d.ts +1 -1
- package/src/viewcollection.js +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ckeditor/ckeditor5-ui",
|
3
|
-
"version": "45.
|
3
|
+
"version": "45.1.0-alpha.0",
|
4
4
|
"description": "The UI framework and standard UI library of CKEditor 5.",
|
5
5
|
"keywords": [
|
6
6
|
"ckeditor",
|
@@ -17,11 +17,11 @@
|
|
17
17
|
"type": "module",
|
18
18
|
"main": "src/index.js",
|
19
19
|
"dependencies": {
|
20
|
-
"@ckeditor/ckeditor5-core": "45.
|
21
|
-
"@ckeditor/ckeditor5-editor-multi-root": "45.
|
22
|
-
"@ckeditor/ckeditor5-engine": "45.
|
23
|
-
"@ckeditor/ckeditor5-icons": "45.
|
24
|
-
"@ckeditor/ckeditor5-utils": "45.
|
20
|
+
"@ckeditor/ckeditor5-core": "45.1.0-alpha.0",
|
21
|
+
"@ckeditor/ckeditor5-editor-multi-root": "45.1.0-alpha.0",
|
22
|
+
"@ckeditor/ckeditor5-engine": "45.1.0-alpha.0",
|
23
|
+
"@ckeditor/ckeditor5-icons": "45.1.0-alpha.0",
|
24
|
+
"@ckeditor/ckeditor5-utils": "45.1.0-alpha.0",
|
25
25
|
"@types/color-convert": "2.0.4",
|
26
26
|
"color-convert": "2.0.1",
|
27
27
|
"color-parse": "1.4.2",
|
@@ -114,14 +114,15 @@ export default class ColorGridsFragmentView extends View {
|
|
114
114
|
* Creates an instance of the view.
|
115
115
|
*
|
116
116
|
* @param locale The localization services instance.
|
117
|
-
* @param
|
118
|
-
* @param
|
119
|
-
* @param
|
120
|
-
* @param
|
121
|
-
* @param
|
122
|
-
* @param
|
123
|
-
* @param
|
124
|
-
* @param
|
117
|
+
* @param options Constructor options.
|
118
|
+
* @param options.colors An array with definitions of colors to be displayed in the table.
|
119
|
+
* @param options.columns The number of columns in the color grid.
|
120
|
+
* @param options.removeButtonLabel The label of the button responsible for removing the color.
|
121
|
+
* @param options.colorPickerLabel The label of the button responsible for color picker appearing.
|
122
|
+
* @param options.documentColorsLabel The label for the section with the document colors.
|
123
|
+
* @param options.documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
124
|
+
* @param options.focusTracker Tracks information about the DOM focus in the list.
|
125
|
+
* @param options.focusables A collection of views that can be focused in the view.
|
125
126
|
*/
|
126
127
|
constructor(locale: Locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, focusTracker, focusables }: {
|
127
128
|
colors: Array<ColorDefinition>;
|
@@ -105,14 +105,15 @@ export default class ColorGridsFragmentView extends View {
|
|
105
105
|
* Creates an instance of the view.
|
106
106
|
*
|
107
107
|
* @param locale The localization services instance.
|
108
|
-
* @param
|
109
|
-
* @param
|
110
|
-
* @param
|
111
|
-
* @param
|
112
|
-
* @param
|
113
|
-
* @param
|
114
|
-
* @param
|
115
|
-
* @param
|
108
|
+
* @param options Constructor options.
|
109
|
+
* @param options.colors An array with definitions of colors to be displayed in the table.
|
110
|
+
* @param options.columns The number of columns in the color grid.
|
111
|
+
* @param options.removeButtonLabel The label of the button responsible for removing the color.
|
112
|
+
* @param options.colorPickerLabel The label of the button responsible for color picker appearing.
|
113
|
+
* @param options.documentColorsLabel The label for the section with the document colors.
|
114
|
+
* @param options.documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
115
|
+
* @param options.focusTracker Tracks information about the DOM focus in the list.
|
116
|
+
* @param options.focusables A collection of views that can be focused in the view.
|
116
117
|
*/
|
117
118
|
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, focusTracker, focusables }) {
|
118
119
|
super(locale);
|
@@ -77,10 +77,11 @@ export default class ColorPickerFragmentView extends View {
|
|
77
77
|
* Creates an instance of the view.
|
78
78
|
*
|
79
79
|
* @param locale The localization services instance.
|
80
|
-
* @param
|
81
|
-
* @param
|
82
|
-
* @param
|
83
|
-
* @param
|
80
|
+
* @param options Constructor options.
|
81
|
+
* @param options.focusTracker Tracks information about the DOM focus in the list.
|
82
|
+
* @param options.focusables A collection of views that can be focused in the view.
|
83
|
+
* @param options.keystrokes An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
84
|
+
* @param options.colorPickerViewConfig The configuration of color picker feature. If set to `false`, the color picker
|
84
85
|
* will not be rendered.
|
85
86
|
*/
|
86
87
|
constructor(locale: Locale, { focusTracker, focusables, keystrokes, colorPickerViewConfig }: {
|
@@ -66,10 +66,11 @@ export default class ColorPickerFragmentView extends View {
|
|
66
66
|
* Creates an instance of the view.
|
67
67
|
*
|
68
68
|
* @param locale The localization services instance.
|
69
|
-
* @param
|
70
|
-
* @param
|
71
|
-
* @param
|
72
|
-
* @param
|
69
|
+
* @param options Constructor options.
|
70
|
+
* @param options.focusTracker Tracks information about the DOM focus in the list.
|
71
|
+
* @param options.focusables A collection of views that can be focused in the view.
|
72
|
+
* @param options.keystrokes An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
73
|
+
* @param options.colorPickerViewConfig The configuration of color picker feature. If set to `false`, the color picker
|
73
74
|
* will not be rendered.
|
74
75
|
*/
|
75
76
|
constructor(locale, { focusTracker, focusables, keystrokes, colorPickerViewConfig }) {
|
@@ -120,13 +120,14 @@ export default class ColorSelectorView extends View {
|
|
120
120
|
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
121
121
|
*
|
122
122
|
* @param locale The localization services instance.
|
123
|
-
* @param
|
124
|
-
* @param
|
125
|
-
* @param
|
126
|
-
* @param
|
127
|
-
* @param
|
128
|
-
* @param
|
129
|
-
* @param
|
123
|
+
* @param options Constructor options.
|
124
|
+
* @param options.colors An array with definitions of colors to be displayed in the table.
|
125
|
+
* @param options.columns The number of columns in the color grid.
|
126
|
+
* @param options.removeButtonLabel The label of the button responsible for removing the color.
|
127
|
+
* @param options.colorPickerLabel The label of the button responsible for color picker appearing.
|
128
|
+
* @param options.documentColorsLabel The label for the section with the document colors.
|
129
|
+
* @param options.documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
130
|
+
* @param options.colorPickerViewConfig The configuration of color picker feature. If set to `false`, the color picker will be hidden.
|
130
131
|
*/
|
131
132
|
constructor(locale: Locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, colorPickerViewConfig }: {
|
132
133
|
colors: Array<ColorDefinition>;
|
@@ -101,13 +101,14 @@ export default class ColorSelectorView extends View {
|
|
101
101
|
* Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
|
102
102
|
*
|
103
103
|
* @param locale The localization services instance.
|
104
|
-
* @param
|
105
|
-
* @param
|
106
|
-
* @param
|
107
|
-
* @param
|
108
|
-
* @param
|
109
|
-
* @param
|
110
|
-
* @param
|
104
|
+
* @param options Constructor options.
|
105
|
+
* @param options.colors An array with definitions of colors to be displayed in the table.
|
106
|
+
* @param options.columns The number of columns in the color grid.
|
107
|
+
* @param options.removeButtonLabel The label of the button responsible for removing the color.
|
108
|
+
* @param options.colorPickerLabel The label of the button responsible for color picker appearing.
|
109
|
+
* @param options.documentColorsLabel The label for the section with the document colors.
|
110
|
+
* @param options.documentColorsCount The number of colors in the document colors section inside the color dropdown.
|
111
|
+
* @param options.colorPickerViewConfig The configuration of color picker feature. If set to `false`, the color picker will be hidden.
|
111
112
|
*/
|
112
113
|
constructor(locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount, colorPickerLabel, colorPickerViewConfig }) {
|
113
114
|
super(locale);
|
@@ -145,7 +146,7 @@ export default class ColorSelectorView extends View {
|
|
145
146
|
this.colorPickerFragmentView.bind('isVisible').to(this, '_isColorPickerFragmentVisible');
|
146
147
|
/**
|
147
148
|
* This is kind of bindings. Unfortunately we could not use this.bind() method because the same property
|
148
|
-
*
|
149
|
+
* cannot be bound twice. So this is work around how to bind 'selectedColor' property between components.
|
149
150
|
*/
|
150
151
|
this.on('change:selectedColor', (evt, evtName, data) => {
|
151
152
|
this.colorGridsFragmentView.set('selectedColor', data);
|
package/src/componentfactory.js
CHANGED
@@ -85,7 +85,7 @@ export default class ComponentFactory {
|
|
85
85
|
* {@link module:ui/componentfactory~ComponentFactory#add added} to the factory.
|
86
86
|
*
|
87
87
|
* @error componentfactory-item-missing
|
88
|
-
* @param name The name of the missing component.
|
88
|
+
* @param {string} name The name of the missing component.
|
89
89
|
*/
|
90
90
|
throw new CKEditorError('componentfactory-item-missing', this, { name });
|
91
91
|
}
|
@@ -79,8 +79,8 @@ export default class DropdownPanelView extends View {
|
|
79
79
|
* provides the `focus()` method for the best user experience.
|
80
80
|
*
|
81
81
|
* @error ui-dropdown-panel-focus-child-missing-focus
|
82
|
-
* @param childView
|
83
|
-
* @param dropdownPanel
|
82
|
+
* @param {module:ui/view~View} childView Child view.
|
83
|
+
* @param {module:ui/dropdown/dropdownpanelview~DropdownPanelView} dropdownPanel A parent of a child.
|
84
84
|
*/
|
85
85
|
logWarning('ui-dropdown-panel-focus-child-missing-focus', { childView: this.children.first, dropdownPanel: this });
|
86
86
|
}
|
package/src/dropdown/utils.d.ts
CHANGED
@@ -79,8 +79,6 @@ import type { DropdownMenuDefinition } from './menu/utils.js';
|
|
79
79
|
*
|
80
80
|
* @param locale The locale instance.
|
81
81
|
* @param ButtonClassOrInstance The dropdown button view class. Needs to implement the
|
82
|
-
* @param behaviorOptions Attributes for the default behavior of the dropdown.
|
83
|
-
*
|
84
82
|
* {@link module:ui/dropdown/button/dropdownbutton~DropdownButton} interface.
|
85
83
|
* @returns The dropdown view instance.
|
86
84
|
*/
|
package/src/dropdown/utils.js
CHANGED
@@ -87,8 +87,6 @@ import ListItemButtonView from '../button/listitembuttonview.js';
|
|
87
87
|
*
|
88
88
|
* @param locale The locale instance.
|
89
89
|
* @param ButtonClassOrInstance The dropdown button view class. Needs to implement the
|
90
|
-
* @param behaviorOptions Attributes for the default behavior of the dropdown.
|
91
|
-
*
|
92
90
|
* {@link module:ui/dropdown/button/dropdownbutton~DropdownButton} interface.
|
93
91
|
* @returns The dropdown view instance.
|
94
92
|
*/
|
@@ -390,7 +388,7 @@ export function focusChildOnDropdownOpen(dropdownView, childSelectorCallback) {
|
|
390
388
|
* experience.
|
391
389
|
*
|
392
390
|
* @error ui-dropdown-focus-child-on-open-child-missing-focus
|
393
|
-
* @param {module:ui/view~View} view
|
391
|
+
* @param {module:ui/view~View} view Child to focus.
|
394
392
|
*/
|
395
393
|
logWarning('ui-dropdown-focus-child-on-open-child-missing-focus', { view: childToFocus });
|
396
394
|
}
|
@@ -525,23 +523,7 @@ function focusDropdownPanelOnOpen(dropdownView) {
|
|
525
523
|
* @param locale
|
526
524
|
*/
|
527
525
|
function bindViewCollectionItemsToDefinitions(dropdownView, listItems, definitions, locale) {
|
528
|
-
|
529
|
-
// to adjust the layout accordingly. It'd look weird if the items on the list were not aligned horizontally.
|
530
|
-
//
|
531
|
-
// Possible theoretical performance problem if many items are added one by one, as this will be called for each item.
|
532
|
-
listItems.on('change', () => {
|
533
|
-
// Filter-map. Check all items, leave only these that have buttons and return the buttons.
|
534
|
-
const listItemButtons = [...listItems].reduce((acc, item) => {
|
535
|
-
if (item instanceof ListItemView && item.children.first instanceof ListItemButtonView) {
|
536
|
-
acc.push(item.children.first);
|
537
|
-
}
|
538
|
-
return acc;
|
539
|
-
}, []);
|
540
|
-
const hasAnyCheckboxOnList = listItemButtons.some(button => button.isToggleable);
|
541
|
-
listItemButtons.forEach(item => {
|
542
|
-
item.hasCheckSpace = hasAnyCheckboxOnList;
|
543
|
-
});
|
544
|
-
});
|
526
|
+
bindDropdownToggleableButtonsAlignment(listItems);
|
545
527
|
listItems.bindTo(definitions).using(def => {
|
546
528
|
if (def.type === 'separator') {
|
547
529
|
return new ListSeparatorView(locale);
|
@@ -575,3 +557,98 @@ function bindViewCollectionItemsToDefinitions(dropdownView, listItems, definitio
|
|
575
557
|
return null;
|
576
558
|
});
|
577
559
|
}
|
560
|
+
/**
|
561
|
+
* Sets up alignment handling for toggleable buttons in a dropdown list.
|
562
|
+
*
|
563
|
+
* Buttons in dropdowns have reserved space for a check icon when they are toggleable.
|
564
|
+
* When at least one button in the list is toggleable, all other buttons (even non-toggleable ones)
|
565
|
+
* will have space on their left side to align with toggleable buttons.
|
566
|
+
*
|
567
|
+
* This function handles a special case where a new toggleable button is added (or removed) to a list
|
568
|
+
* where previous buttons weren't toggleable. In that case, those previous buttons will
|
569
|
+
* automatically allocate space to align with the new toggleable button.
|
570
|
+
*
|
571
|
+
* Example:
|
572
|
+
* ```
|
573
|
+
* Before adding toggleable button:
|
574
|
+
* +----------------+
|
575
|
+
* | Normal Button |
|
576
|
+
* +----------------+
|
577
|
+
* | Another Button |
|
578
|
+
* +----------------+
|
579
|
+
*
|
580
|
+
* After adding toggleable button:
|
581
|
+
* +-------------------+
|
582
|
+
* | Normal Button |
|
583
|
+
* +-------------------+
|
584
|
+
* | Another Button |
|
585
|
+
* +-------------------+
|
586
|
+
* | ✓ Toggle Button |
|
587
|
+
* +-------------------+
|
588
|
+
* ```
|
589
|
+
*
|
590
|
+
* @param listItems Collection of list items to observe for toggleable buttons.
|
591
|
+
*/
|
592
|
+
function bindDropdownToggleableButtonsAlignment(listItems) {
|
593
|
+
// Keep track of how many toggleable buttons are in the list.
|
594
|
+
let toggleableButtonsCount = 0;
|
595
|
+
// Helper function that checks if a view item is a list item button.
|
596
|
+
const pickListItemButtonIfPresent = (item) => {
|
597
|
+
// Check if the item is a ListItemView with a ListItemButtonView as its first child.
|
598
|
+
if (!(item instanceof ListItemView) || !(item.children.first instanceof ListItemButtonView)) {
|
599
|
+
return null;
|
600
|
+
}
|
601
|
+
return item.children.first;
|
602
|
+
};
|
603
|
+
// Helper function that checks if a view item is a toggleable button.
|
604
|
+
// Returns the button if it's toggleable - otherwise, returns null.
|
605
|
+
const pickListItemToggleableButtonIfPresent = (item) => {
|
606
|
+
const listItemButtonView = pickListItemButtonIfPresent(item);
|
607
|
+
// Only return buttons that are configured as toggleable.
|
608
|
+
if (!listItemButtonView || !listItemButtonView.isToggleable) {
|
609
|
+
return null;
|
610
|
+
}
|
611
|
+
return listItemButtonView;
|
612
|
+
};
|
613
|
+
// Updates all buttons in the list to either allocate space for check marks or not.
|
614
|
+
// This ensures all buttons are properly aligned regardless of their toggleable state.
|
615
|
+
const updateAllButtonsCheckSpace = (hasSpace) => {
|
616
|
+
for (const listItem of listItems) {
|
617
|
+
const listItemButton = pickListItemButtonIfPresent(listItem);
|
618
|
+
if (listItemButton) {
|
619
|
+
listItemButton.hasCheckSpace = hasSpace;
|
620
|
+
}
|
621
|
+
}
|
622
|
+
};
|
623
|
+
// Listen for changes in the list items collection.
|
624
|
+
listItems.on('change', (evt, data) => {
|
625
|
+
// Remember the current state - whether we have any toggleable buttons.
|
626
|
+
const prevToggleable = toggleableButtonsCount > 0;
|
627
|
+
// Process removed items - decrease count for each toggleable button removed.
|
628
|
+
for (const item of data.removed) {
|
629
|
+
if (pickListItemToggleableButtonIfPresent(item)) {
|
630
|
+
toggleableButtonsCount--;
|
631
|
+
}
|
632
|
+
}
|
633
|
+
// Process added items - increase count for each toggleable button added.
|
634
|
+
for (const item of data.added) {
|
635
|
+
const button = pickListItemButtonIfPresent(item);
|
636
|
+
if (!button) {
|
637
|
+
continue;
|
638
|
+
}
|
639
|
+
if (button.isToggleable) {
|
640
|
+
// Check if the button is toggleable and increase the count.
|
641
|
+
toggleableButtonsCount++;
|
642
|
+
}
|
643
|
+
// Depending on the current state, set the check space for the button.
|
644
|
+
button.hasCheckSpace = toggleableButtonsCount > 0;
|
645
|
+
}
|
646
|
+
// Check if the current state has changed.
|
647
|
+
const currentToggleable = toggleableButtonsCount > 0;
|
648
|
+
// Only update button alignment if we've crossed the threshold between
|
649
|
+
// having no toggleable buttons and having at least one.
|
650
|
+
if (prevToggleable !== currentToggleable) {
|
651
|
+
updateAllButtonsCheckSpace(currentToggleable);
|
652
|
+
}
|
653
|
+
});
|
654
|
+
}
|
@@ -13,7 +13,7 @@ import AriaLiveAnnouncer from '../arialiveannouncer.js';
|
|
13
13
|
import type EditorUIView from './editoruiview.js';
|
14
14
|
import type ToolbarView from '../toolbar/toolbarview.js';
|
15
15
|
import { FocusTracker } from '@ckeditor/ckeditor5-utils';
|
16
|
-
import type { Editor } from '@ckeditor/ckeditor5-core';
|
16
|
+
import type { Editor, ViewportOffsetConfig } from '@ckeditor/ckeditor5-core';
|
17
17
|
import type { default as MenuBarView, MenuBarConfigAddedGroup, MenuBarConfigAddedItem, MenuBarConfigAddedMenu } from '../menubar/menubarview.js';
|
18
18
|
declare const EditorUI_base: {
|
19
19
|
new (): import("@ckeditor/ckeditor5-utils").Observable;
|
@@ -75,7 +75,8 @@ export default abstract class EditorUI extends /* #__PURE__ */ EditorUI_base {
|
|
75
75
|
* top: 50,
|
76
76
|
* right: 50,
|
77
77
|
* bottom: 50,
|
78
|
-
* left: 50
|
78
|
+
* left: 50,
|
79
|
+
* visualTop: 50
|
79
80
|
* }
|
80
81
|
* ```
|
81
82
|
*
|
@@ -92,12 +93,7 @@ export default abstract class EditorUI extends /* #__PURE__ */ EditorUI_base {
|
|
92
93
|
*
|
93
94
|
* @observable
|
94
95
|
*/
|
95
|
-
viewportOffset:
|
96
|
-
left?: number;
|
97
|
-
right?: number;
|
98
|
-
top?: number;
|
99
|
-
bottom?: number;
|
100
|
-
};
|
96
|
+
viewportOffset: ViewportOffset;
|
101
97
|
/**
|
102
98
|
* Stores all editable elements used by the editor instance.
|
103
99
|
*/
|
@@ -114,6 +110,10 @@ export default abstract class EditorUI extends /* #__PURE__ */ EditorUI_base {
|
|
114
110
|
* The last focused element to which focus should return on `Esc` press.
|
115
111
|
*/
|
116
112
|
private _lastFocusedForeignElement;
|
113
|
+
/**
|
114
|
+
* The DOM emitter instance used for visual viewport watching.
|
115
|
+
*/
|
116
|
+
private _domEmitter?;
|
117
117
|
/**
|
118
118
|
* Creates an instance of the editor UI class.
|
119
119
|
*
|
@@ -291,6 +291,19 @@ export default abstract class EditorUI extends /* #__PURE__ */ EditorUI_base {
|
|
291
291
|
* Ensures that the focus tracker is aware of all views' DOM elements in the body collection.
|
292
292
|
*/
|
293
293
|
private _bindBodyCollectionWithFocusTracker;
|
294
|
+
/**
|
295
|
+
* Set initial viewport offset and setup visualTop augmentation.
|
296
|
+
*/
|
297
|
+
private _initViewportOffset;
|
298
|
+
/**
|
299
|
+
* Listen to visual viewport changes and update the viewportOffset with the visualTop property
|
300
|
+
* according to the visible part of it (visual viewport).
|
301
|
+
*/
|
302
|
+
private _initVisualViewportSupport;
|
303
|
+
/**
|
304
|
+
* Calculate the viewport top offset according to the visible part of it (visual viewport).
|
305
|
+
*/
|
306
|
+
private _getVisualViewportTopOffset;
|
294
307
|
}
|
295
308
|
/**
|
296
309
|
* Fired when the editor UI is ready.
|
@@ -351,4 +364,12 @@ export interface FocusableToolbarOptions {
|
|
351
364
|
*/
|
352
365
|
afterBlur?: () => void;
|
353
366
|
}
|
367
|
+
export interface ViewportOffset extends ViewportOffsetConfig {
|
368
|
+
/**
|
369
|
+
* The top offset of the visual viewport.
|
370
|
+
*
|
371
|
+
* This value is calculated based on the visual viewport position.
|
372
|
+
*/
|
373
|
+
visualTop?: number;
|
374
|
+
}
|
354
375
|
export {};
|
package/src/editorui/editorui.js
CHANGED
@@ -11,7 +11,7 @@ import TooltipManager from '../tooltipmanager.js';
|
|
11
11
|
import PoweredBy from './poweredby.js';
|
12
12
|
import EvaluationBadge from './evaluationbadge.js';
|
13
13
|
import AriaLiveAnnouncer from '../arialiveannouncer.js';
|
14
|
-
import { ObservableMixin, isVisible, FocusTracker } from '@ckeditor/ckeditor5-utils';
|
14
|
+
import { ObservableMixin, DomEmitterMixin, global, isVisible, FocusTracker, getVisualViewportOffset } from '@ckeditor/ckeditor5-utils';
|
15
15
|
import { normalizeMenuBarConfig } from '../menubar/utils.js';
|
16
16
|
/**
|
17
17
|
* A class providing the minimal interface that is required to successfully bootstrap any editor UI.
|
@@ -71,6 +71,10 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
71
71
|
* The last focused element to which focus should return on `Esc` press.
|
72
72
|
*/
|
73
73
|
_lastFocusedForeignElement = null;
|
74
|
+
/**
|
75
|
+
* The DOM emitter instance used for visual viewport watching.
|
76
|
+
*/
|
77
|
+
_domEmitter;
|
74
78
|
/**
|
75
79
|
* Creates an instance of the editor UI class.
|
76
80
|
*
|
@@ -86,7 +90,7 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
86
90
|
this.poweredBy = new PoweredBy(editor);
|
87
91
|
this.evaluationBadge = new EvaluationBadge(editor);
|
88
92
|
this.ariaLiveAnnouncer = new AriaLiveAnnouncer(editor);
|
89
|
-
this.
|
93
|
+
this._initViewportOffset(this._readViewportOffsetFromConfig());
|
90
94
|
this.once('ready', () => {
|
91
95
|
this._bindBodyCollectionWithFocusTracker();
|
92
96
|
this.isReady = true;
|
@@ -95,6 +99,7 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
95
99
|
this.listenTo(editingView.document, 'layoutChanged', this.update.bind(this));
|
96
100
|
this.listenTo(editingView, 'scrollToTheSelection', this._handleScrollToTheSelection.bind(this));
|
97
101
|
this._initFocusTracking();
|
102
|
+
this._initVisualViewportSupport();
|
98
103
|
}
|
99
104
|
/**
|
100
105
|
* The main (outermost) DOM element of the editor UI.
|
@@ -136,6 +141,9 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
136
141
|
}
|
137
142
|
this._editableElementsMap = new Map();
|
138
143
|
this._focusableToolbarDefinitions = [];
|
144
|
+
if (this._domEmitter) {
|
145
|
+
this._domEmitter.stopListening();
|
146
|
+
}
|
139
147
|
}
|
140
148
|
/**
|
141
149
|
* Stores the native DOM editable element used by the editor under a unique name.
|
@@ -279,7 +287,7 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
279
287
|
* {@link module:ui/editorui/editorui~EditorUI#getEditableElement `getEditableElement()`} methods instead.
|
280
288
|
*
|
281
289
|
* @error editor-ui-deprecated-editable-elements
|
282
|
-
* @param editorUI Editor UI instance the deprecated property belongs to.
|
290
|
+
* @param {module:ui/editorui/editorui~EditorUI} editorUI Editor UI instance the deprecated property belongs to.
|
283
291
|
*/
|
284
292
|
console.warn('editor-ui-deprecated-editable-elements: ' +
|
285
293
|
'The EditorUI#_editableElements property has been deprecated and will be removed in the near future.', { editorUI: this });
|
@@ -529,6 +537,51 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
529
537
|
this.focusTracker.remove(view.element);
|
530
538
|
});
|
531
539
|
}
|
540
|
+
/**
|
541
|
+
* Set initial viewport offset and setup visualTop augmentation.
|
542
|
+
*/
|
543
|
+
_initViewportOffset(viewportOffsetConfig) {
|
544
|
+
// Augment the viewport offset set from outside the editor with the visualTop property.
|
545
|
+
this.on('set:viewportOffset', (evt, name, value) => {
|
546
|
+
const visualTop = this._getVisualViewportTopOffset(value);
|
547
|
+
// Update only if there is a change in a value, so we do not trigger
|
548
|
+
// listeners to the viewportOffset observable.
|
549
|
+
if (value.visualTop !== visualTop) {
|
550
|
+
evt.return = { ...value, visualTop };
|
551
|
+
}
|
552
|
+
});
|
553
|
+
// Set the initial value after augmenting the setter.
|
554
|
+
this.set('viewportOffset', viewportOffsetConfig);
|
555
|
+
}
|
556
|
+
/**
|
557
|
+
* Listen to visual viewport changes and update the viewportOffset with the visualTop property
|
558
|
+
* according to the visible part of it (visual viewport).
|
559
|
+
*/
|
560
|
+
_initVisualViewportSupport() {
|
561
|
+
if (!global.window.visualViewport) {
|
562
|
+
return;
|
563
|
+
}
|
564
|
+
const updateViewport = () => {
|
565
|
+
const visualTop = this._getVisualViewportTopOffset(this.viewportOffset);
|
566
|
+
// Update only if there is a change in a value, so we do not trigger
|
567
|
+
// listeners to the viewportOffset observable.
|
568
|
+
if (this.viewportOffset.visualTop !== visualTop) {
|
569
|
+
this.viewportOffset = { ...this.viewportOffset, visualTop };
|
570
|
+
}
|
571
|
+
};
|
572
|
+
// Listen to the changes in the visual viewport to adjust the visualTop of viewport offset.
|
573
|
+
this._domEmitter = new (DomEmitterMixin())();
|
574
|
+
this._domEmitter.listenTo(global.window.visualViewport, 'scroll', updateViewport);
|
575
|
+
this._domEmitter.listenTo(global.window.visualViewport, 'resize', updateViewport);
|
576
|
+
}
|
577
|
+
/**
|
578
|
+
* Calculate the viewport top offset according to the visible part of it (visual viewport).
|
579
|
+
*/
|
580
|
+
_getVisualViewportTopOffset(viewportOffset) {
|
581
|
+
const visualViewportOffsetTop = getVisualViewportOffset().top;
|
582
|
+
const viewportTopOffset = viewportOffset.top || 0;
|
583
|
+
return visualViewportOffsetTop > viewportTopOffset ? 0 : viewportTopOffset - visualViewportOffsetTop;
|
584
|
+
}
|
532
585
|
}
|
533
586
|
/**
|
534
587
|
* Returns a number (weight) for a toolbar definition. Visible toolbars have a higher priority and so do
|
@@ -217,8 +217,8 @@ export default class MenuBarView extends View {
|
|
217
217
|
* {@link module:ui/menubar/menubarmenulistitembuttonview~MenuBarMenuListItemButtonView} (button).
|
218
218
|
*
|
219
219
|
* @error menu-bar-component-unsupported
|
220
|
-
* @param componentName A name of the unsupported component used in the configuration.
|
221
|
-
* @param componentView An unsupported component view.
|
220
|
+
* @param {string} componentName A name of the unsupported component used in the configuration.
|
221
|
+
* @param {module:ui/view~View} componentView An unsupported component view.
|
222
222
|
*/
|
223
223
|
logWarning('menu-bar-component-unsupported', {
|
224
224
|
componentName,
|
package/src/menubar/utils.js
CHANGED
@@ -1142,8 +1142,8 @@ function handleAdditions(originalConfig, config, items) {
|
|
1142
1142
|
* {@link module:core/editor/editorconfig~EditorConfig#menuBar menu bar configuration}.
|
1143
1143
|
*
|
1144
1144
|
* @error menu-bar-item-could-not-be-removed
|
1145
|
-
* @param menuBarConfig The full configuration of the menu bar.
|
1146
|
-
* @param
|
1145
|
+
* @param {object} menuBarConfig The full configuration of the menu bar.
|
1146
|
+
* @param {object} addedItemConfig The name of the item that was not removed from the menu bar.
|
1147
1147
|
*/
|
1148
1148
|
logWarning('menu-bar-item-could-not-be-added', {
|
1149
1149
|
menuBarConfig: originalConfig,
|
@@ -1222,9 +1222,9 @@ function purgeUnavailableComponents(originalConfig, config, componentFactory) {
|
|
1222
1222
|
* menu bar item.
|
1223
1223
|
*
|
1224
1224
|
* @error menu-bar-item-unavailable
|
1225
|
-
* @param menuBarConfig The full configuration of the menu bar.
|
1226
|
-
* @param parentMenuConfig The config of the menu the unavailable component was defined in.
|
1227
|
-
* @param componentName The name of the unavailable component.
|
1225
|
+
* @param {object} menuBarConfig The full configuration of the menu bar.
|
1226
|
+
* @param {object} parentMenuConfig The config of the menu the unavailable component was defined in.
|
1227
|
+
* @param {string} componentName The name of the unavailable component.
|
1228
1228
|
*/
|
1229
1229
|
logWarning('menu-bar-item-unavailable', {
|
1230
1230
|
menuBarConfig: originalConfig,
|
@@ -1303,8 +1303,8 @@ function warnAboutEmptyMenu(originalConfig, emptyMenuConfig, isUsingDefaultConfi
|
|
1303
1303
|
* to account for the missing menu items.
|
1304
1304
|
*
|
1305
1305
|
* @error menu-bar-menu-empty
|
1306
|
-
* @param menuBarConfig The full configuration of the menu bar.
|
1307
|
-
* @param emptyMenuConfig The definition of the menu that has no child items.
|
1306
|
+
* @param {object} menuBarConfig The full configuration of the menu bar.
|
1307
|
+
* @param {object} emptyMenuConfig The definition of the menu that has no child items.
|
1308
1308
|
*/
|
1309
1309
|
logWarning('menu-bar-menu-empty', {
|
1310
1310
|
menuBarConfig: originalConfig,
|
@@ -6,7 +6,7 @@
|
|
6
6
|
* @module ui/panel/balloon/balloonpanelview
|
7
7
|
*/
|
8
8
|
import View from '../../view.js';
|
9
|
-
import { getOptimalPosition, global, isRange, toUnit, isVisible, isText, ResizeObserver } from '@ckeditor/ckeditor5-utils';
|
9
|
+
import { getOptimalPosition, global, isRange, toUnit, isVisible, isText, ResizeObserver, Rect } from '@ckeditor/ckeditor5-utils';
|
10
10
|
import { isElement } from 'es-toolkit/compat';
|
11
11
|
import '../../../theme/components/panel/balloonpanel.css';
|
12
12
|
const toPx = /* #__PURE__ */ toUnit('px');
|
@@ -563,18 +563,26 @@ class BalloonPanelView extends View {
|
|
563
563
|
...(config && { config })
|
564
564
|
}),
|
565
565
|
// ------- Sticky
|
566
|
-
viewportStickyNorth: (targetRect, balloonRect, viewportRect
|
567
|
-
|
568
|
-
|
566
|
+
viewportStickyNorth: (targetRect, balloonRect, viewportRect) => {
|
567
|
+
// Get the intersection of the viewport and the document body.
|
568
|
+
const boundaryRect = new Rect(global.document.body).getIntersection(viewportRect.getVisible());
|
569
|
+
if (!boundaryRect) {
|
569
570
|
return null;
|
570
571
|
}
|
571
|
-
//
|
572
|
-
|
573
|
-
if
|
572
|
+
// Get the visible intersection of the boundary and the document body.
|
573
|
+
const visibleBoundaryRect = boundaryRect.getVisible();
|
574
|
+
// Check if the target is in the boundary.
|
575
|
+
if (!targetRect.getIntersection(visibleBoundaryRect)) {
|
576
|
+
return null;
|
577
|
+
}
|
578
|
+
// Checks if there is enough space to put the balloon on the top or bottom of the target.
|
579
|
+
// If not, makes the balloon sticky.
|
580
|
+
if (!(visibleBoundaryRect.top - targetRect.top - stickyVerticalOffset < balloonRect.height &&
|
581
|
+
visibleBoundaryRect.bottom - targetRect.bottom < balloonRect.height)) {
|
574
582
|
return null;
|
575
583
|
}
|
576
584
|
return {
|
577
|
-
top:
|
585
|
+
top: visibleBoundaryRect.top + stickyVerticalOffset,
|
578
586
|
left: targetRect.left + targetRect.width / 2 - balloonRect.width / 2,
|
579
587
|
name: 'arrowless',
|
580
588
|
config: {
|
@@ -265,7 +265,10 @@ export default class ContextualBalloon extends Plugin {
|
|
265
265
|
}
|
266
266
|
// Don't modify the original options object.
|
267
267
|
position = Object.assign({}, position, {
|
268
|
-
viewportOffsetConfig:
|
268
|
+
viewportOffsetConfig: {
|
269
|
+
...this.editor.ui.viewportOffset,
|
270
|
+
top: this.editor.ui.viewportOffset.visualTop
|
271
|
+
}
|
269
272
|
});
|
270
273
|
}
|
271
274
|
return position;
|