@ckeditor/ckeditor5-ui 43.3.1 → 44.0.0-alpha.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.
- package/README.md +13 -7
- package/dist/badge/badge.d.ts +133 -0
- package/dist/dropdown/dropdownview.d.ts +6 -0
- package/dist/editorui/bodycollection.d.ts +47 -12
- package/dist/editorui/editorui.d.ts +5 -0
- package/dist/editorui/evaluationbadge.d.ts +37 -0
- package/dist/editorui/poweredby.d.ts +12 -49
- package/dist/index-editor.css +52 -3
- package/dist/index.css +62 -3
- package/dist/index.css.map +1 -1
- package/dist/index.js +351 -144
- package/dist/index.js.map +1 -1
- package/dist/menubar/menubarmenupanelview.d.ts +1 -1
- package/dist/menubar/menubarmenuview.d.ts +5 -0
- package/dist/menubar/utils.d.ts +1 -0
- package/package.json +4 -4
- package/src/badge/badge.d.ts +129 -0
- package/src/badge/badge.js +218 -0
- package/src/dialog/dialogview.js +6 -2
- package/src/dropdown/dropdownview.d.ts +6 -0
- package/src/dropdown/dropdownview.js +9 -1
- package/src/editorui/bodycollection.d.ts +47 -12
- package/src/editorui/bodycollection.js +50 -19
- package/src/editorui/editorui.d.ts +5 -0
- package/src/editorui/editorui.js +3 -0
- package/src/editorui/evaluationbadge.d.ts +33 -0
- package/src/editorui/evaluationbadge.js +99 -0
- package/src/editorui/poweredby.d.ts +12 -49
- package/src/editorui/poweredby.js +36 -194
- package/src/menubar/menubarmenupanelview.d.ts +1 -1
- package/src/menubar/menubarmenuview.d.ts +5 -0
- package/src/menubar/menubarmenuview.js +23 -1
- package/src/menubar/utils.d.ts +1 -0
- package/src/menubar/utils.js +2 -0
- package/theme/globals/_evaluationbadge.css +54 -0
- package/theme/globals/_poweredby.css +15 -3
- package/theme/globals/globals.css +1 -0
package/src/editorui/editorui.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import ComponentFactory from '../componentfactory.js';
|
|
10
10
|
import TooltipManager from '../tooltipmanager.js';
|
|
11
11
|
import PoweredBy from './poweredby.js';
|
|
12
|
+
import EvaluationBadge from './evaluationbadge.js';
|
|
12
13
|
import AriaLiveAnnouncer from '../arialiveannouncer.js';
|
|
13
14
|
import { ObservableMixin, isVisible, FocusTracker } from '@ckeditor/ckeditor5-utils';
|
|
14
15
|
import { normalizeMenuBarConfig } from '../menubar/utils.js';
|
|
@@ -52,6 +53,7 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
|
52
53
|
this.focusTracker = new FocusTracker();
|
|
53
54
|
this.tooltipManager = new TooltipManager(editor);
|
|
54
55
|
this.poweredBy = new PoweredBy(editor);
|
|
56
|
+
this.evaluationBadge = new EvaluationBadge(editor);
|
|
55
57
|
this.ariaLiveAnnouncer = new AriaLiveAnnouncer(editor);
|
|
56
58
|
this.set('viewportOffset', this._readViewportOffsetFromConfig());
|
|
57
59
|
this.once('ready', () => {
|
|
@@ -95,6 +97,7 @@ export default class EditorUI extends /* #__PURE__ */ ObservableMixin() {
|
|
|
95
97
|
this.focusTracker.destroy();
|
|
96
98
|
this.tooltipManager.destroy(this.editor);
|
|
97
99
|
this.poweredBy.destroy();
|
|
100
|
+
this.evaluationBadge.destroy();
|
|
98
101
|
// Clean–up the references to the CKEditor instance stored in the native editable DOM elements.
|
|
99
102
|
for (const domElement of this._editableElementsMap.values()) {
|
|
100
103
|
domElement.ckeditorInstance = null;
|
|
@@ -0,0 +1,33 @@
|
|
|
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/editorui/evaluationbadge
|
|
7
|
+
*/
|
|
8
|
+
import type { Editor } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
import View from '../view.js';
|
|
10
|
+
import Badge, { type BadgeConfig } from '../badge/badge.js';
|
|
11
|
+
/**
|
|
12
|
+
* A helper that enables the "evaluation badge" feature in the editor at the bottom of the editable element
|
|
13
|
+
* (editor root, source editing area, etc.) when the editor is focused.
|
|
14
|
+
*
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
export default class EvaluationBadge extends Badge {
|
|
18
|
+
private licenseTypeMessage;
|
|
19
|
+
constructor(editor: Editor);
|
|
20
|
+
/**
|
|
21
|
+
* Enables "evaluation badge" label.
|
|
22
|
+
*/
|
|
23
|
+
protected _isEnabled(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Creates the content of the "evaluation badge".
|
|
26
|
+
*/
|
|
27
|
+
protected _createBadgeContent(): View<HTMLElement>;
|
|
28
|
+
/**
|
|
29
|
+
* Returns the normalized configuration for the "evaluation badge".
|
|
30
|
+
* It takes 'ui.poweredBy' configuration into account to determine the badge position and side.
|
|
31
|
+
*/
|
|
32
|
+
protected _getNormalizedConfig(): BadgeConfig;
|
|
33
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
import { parseBase64EncodedObject } from '@ckeditor/ckeditor5-utils';
|
|
6
|
+
import View from '../view.js';
|
|
7
|
+
import Badge from '../badge/badge.js';
|
|
8
|
+
/**
|
|
9
|
+
* A helper that enables the "evaluation badge" feature in the editor at the bottom of the editable element
|
|
10
|
+
* (editor root, source editing area, etc.) when the editor is focused.
|
|
11
|
+
*
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export default class EvaluationBadge extends Badge {
|
|
15
|
+
constructor(editor) {
|
|
16
|
+
super(editor, { balloonClass: 'ck-evaluation-badge-balloon' });
|
|
17
|
+
this.licenseTypeMessage = {
|
|
18
|
+
evaluation: 'For evaluation purposes only',
|
|
19
|
+
trial: 'For evaluation purposes only',
|
|
20
|
+
development: 'For development purposes only'
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Enables "evaluation badge" label.
|
|
25
|
+
*/
|
|
26
|
+
_isEnabled() {
|
|
27
|
+
const editor = this.editor;
|
|
28
|
+
const licenseKey = editor.config.get('licenseKey');
|
|
29
|
+
const licenseType = getLicenseTypeFromLicenseKey(licenseKey);
|
|
30
|
+
return Boolean(licenseType && this.licenseTypeMessage[licenseType]);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Creates the content of the "evaluation badge".
|
|
34
|
+
*/
|
|
35
|
+
_createBadgeContent() {
|
|
36
|
+
const licenseKey = this.editor.config.get('licenseKey');
|
|
37
|
+
const licenseType = getLicenseTypeFromLicenseKey(licenseKey);
|
|
38
|
+
return new EvaluationBadgeView(this.editor.locale, this.licenseTypeMessage[licenseType]);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns the normalized configuration for the "evaluation badge".
|
|
42
|
+
* It takes 'ui.poweredBy' configuration into account to determine the badge position and side.
|
|
43
|
+
*/
|
|
44
|
+
_getNormalizedConfig() {
|
|
45
|
+
const badgeConfig = super._getNormalizedConfig();
|
|
46
|
+
const userConfig = this.editor.config.get('ui.poweredBy') || {};
|
|
47
|
+
const position = userConfig.position || badgeConfig.position;
|
|
48
|
+
const poweredBySide = userConfig.side || badgeConfig.side;
|
|
49
|
+
return {
|
|
50
|
+
position,
|
|
51
|
+
side: poweredBySide === 'left' ? 'right' : 'left',
|
|
52
|
+
verticalOffset: badgeConfig.verticalOffset,
|
|
53
|
+
horizontalOffset: badgeConfig.horizontalOffset
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A view displaying the "evaluation badge".
|
|
59
|
+
*/
|
|
60
|
+
class EvaluationBadgeView extends View {
|
|
61
|
+
/**
|
|
62
|
+
* Creates an instance of the "evaluation badge" view.
|
|
63
|
+
*
|
|
64
|
+
* @param locale The localization services instance.
|
|
65
|
+
* @param label The label text.
|
|
66
|
+
*/
|
|
67
|
+
constructor(locale, label) {
|
|
68
|
+
super(locale);
|
|
69
|
+
this.setTemplate({
|
|
70
|
+
tag: 'div',
|
|
71
|
+
attributes: {
|
|
72
|
+
class: ['ck', 'ck-evaluation-badge'],
|
|
73
|
+
'aria-hidden': true
|
|
74
|
+
},
|
|
75
|
+
children: [
|
|
76
|
+
{
|
|
77
|
+
tag: 'span',
|
|
78
|
+
attributes: {
|
|
79
|
+
class: ['ck', 'ck-evaluation-badge__label']
|
|
80
|
+
},
|
|
81
|
+
children: [label]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns the license type based on the license key.
|
|
89
|
+
*/
|
|
90
|
+
function getLicenseTypeFromLicenseKey(licenseKey) {
|
|
91
|
+
if (licenseKey == 'GPL') {
|
|
92
|
+
return 'GPL';
|
|
93
|
+
}
|
|
94
|
+
const licenseContent = parseBase64EncodedObject(licenseKey.split('.')[1]);
|
|
95
|
+
if (!licenseContent) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return licenseContent.licenseType || 'production';
|
|
99
|
+
}
|
|
@@ -5,67 +5,30 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module ui/editorui/poweredby
|
|
7
7
|
*/
|
|
8
|
-
import type { Editor } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
};
|
|
8
|
+
import type { Editor, UiConfig } from '@ckeditor/ckeditor5-core';
|
|
9
|
+
import View from '../view.js';
|
|
10
|
+
import Badge from '../badge/badge.js';
|
|
11
|
+
type PoweredByConfig = Required<UiConfig>['poweredBy'];
|
|
13
12
|
/**
|
|
14
13
|
* A helper that enables the "powered by" feature in the editor and renders a link to the project's
|
|
15
14
|
* webpage next to the bottom of the editable element (editor root, source editing area, etc.) when the editor is focused.
|
|
16
15
|
*
|
|
17
16
|
* @private
|
|
18
17
|
*/
|
|
19
|
-
export default class PoweredBy extends
|
|
20
|
-
/**
|
|
21
|
-
* Editor instance the helper was created for.
|
|
22
|
-
*/
|
|
23
|
-
private readonly editor;
|
|
24
|
-
/**
|
|
25
|
-
* A reference to the balloon panel hosting and positioning the "powered by" link and logo.
|
|
26
|
-
*/
|
|
27
|
-
private _balloonView;
|
|
28
|
-
/**
|
|
29
|
-
* A throttled version of the {@link #_showBalloon} method meant for frequent use to avoid performance loss.
|
|
30
|
-
*/
|
|
31
|
-
private _showBalloonThrottled;
|
|
32
|
-
/**
|
|
33
|
-
* A reference to the last editable element (root, source editing area, etc.) focused by the user.
|
|
34
|
-
* Since the focus can move to other focusable elements in the UI, this reference allows positioning the balloon over the
|
|
35
|
-
* right element whether the user is typing or using the UI.
|
|
36
|
-
*/
|
|
37
|
-
private _lastFocusedEditableElement;
|
|
38
|
-
/**
|
|
39
|
-
* Creates a "powered by" helper for a given editor. The feature is initialized on Editor#ready
|
|
40
|
-
* event.
|
|
41
|
-
*
|
|
42
|
-
* @param editor
|
|
43
|
-
*/
|
|
18
|
+
export default class PoweredBy extends Badge {
|
|
44
19
|
constructor(editor: Editor);
|
|
45
20
|
/**
|
|
46
|
-
*
|
|
47
|
-
*/
|
|
48
|
-
destroy(): void;
|
|
49
|
-
/**
|
|
50
|
-
* Enables "powered by" label once the editor (ui) is ready.
|
|
51
|
-
*/
|
|
52
|
-
private _handleEditorReady;
|
|
53
|
-
/**
|
|
54
|
-
* Creates an instance of the {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView balloon panel}
|
|
55
|
-
* with the "powered by" view inside ready for positioning.
|
|
56
|
-
*/
|
|
57
|
-
private _createBalloonView;
|
|
58
|
-
/**
|
|
59
|
-
* Attempts to display the balloon with the "powered by" view.
|
|
21
|
+
* Enables "powered by" label.
|
|
60
22
|
*/
|
|
61
|
-
|
|
23
|
+
protected _isEnabled(): boolean;
|
|
62
24
|
/**
|
|
63
|
-
*
|
|
25
|
+
* Creates a "powered by" badge content.
|
|
64
26
|
*/
|
|
65
|
-
|
|
27
|
+
protected _createBadgeContent(): View<HTMLElement>;
|
|
66
28
|
/**
|
|
67
|
-
*
|
|
29
|
+
* Returns the normalized configuration for the "powered by" badge.
|
|
30
|
+
* It takes the user configuration into account and falls back to the default one.
|
|
68
31
|
*/
|
|
69
|
-
|
|
32
|
+
protected _getNormalizedConfig(): Required<PoweredByConfig>;
|
|
70
33
|
}
|
|
71
34
|
export {};
|
|
@@ -2,18 +2,11 @@
|
|
|
2
2
|
* @license Copyright (c) 2003-2024, 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
|
-
import {
|
|
6
|
-
import BalloonPanelView from '../panel/balloon/balloonpanelview.js';
|
|
7
|
-
import IconView from '../icon/iconview.js';
|
|
5
|
+
import { parseBase64EncodedObject } from '@ckeditor/ckeditor5-utils';
|
|
8
6
|
import View from '../view.js';
|
|
9
|
-
import
|
|
7
|
+
import Badge from '../badge/badge.js';
|
|
8
|
+
import IconView from '../icon/iconview.js';
|
|
10
9
|
import poweredByIcon from '../../theme/icons/project-logo.svg';
|
|
11
|
-
const ICON_WIDTH = 53;
|
|
12
|
-
const ICON_HEIGHT = 10;
|
|
13
|
-
// ⚠ Note, whenever changing the threshold, make sure to update the docs/support/managing-ckeditor-logo.md docs
|
|
14
|
-
// as this information is also mentioned there ⚠.
|
|
15
|
-
const NARROW_ROOT_HEIGHT_THRESHOLD = 50;
|
|
16
|
-
const NARROW_ROOT_WIDTH_THRESHOLD = 350;
|
|
17
10
|
const DEFAULT_LABEL = 'Powered by';
|
|
18
11
|
/**
|
|
19
12
|
* A helper that enables the "powered by" feature in the editor and renders a link to the project's
|
|
@@ -21,129 +14,52 @@ const DEFAULT_LABEL = 'Powered by';
|
|
|
21
14
|
*
|
|
22
15
|
* @private
|
|
23
16
|
*/
|
|
24
|
-
export default class PoweredBy extends
|
|
25
|
-
/**
|
|
26
|
-
* Creates a "powered by" helper for a given editor. The feature is initialized on Editor#ready
|
|
27
|
-
* event.
|
|
28
|
-
*
|
|
29
|
-
* @param editor
|
|
30
|
-
*/
|
|
17
|
+
export default class PoweredBy extends Badge {
|
|
31
18
|
constructor(editor) {
|
|
32
|
-
super();
|
|
33
|
-
this.editor = editor;
|
|
34
|
-
this._balloonView = null;
|
|
35
|
-
this._lastFocusedEditableElement = null;
|
|
36
|
-
this._showBalloonThrottled = throttle(this._showBalloon.bind(this), 50, { leading: true });
|
|
37
|
-
editor.on('ready', this._handleEditorReady.bind(this));
|
|
19
|
+
super(editor, { balloonClass: 'ck-powered-by-balloon' });
|
|
38
20
|
}
|
|
39
21
|
/**
|
|
40
|
-
*
|
|
22
|
+
* Enables "powered by" label.
|
|
41
23
|
*/
|
|
42
|
-
|
|
43
|
-
const balloon = this._balloonView;
|
|
44
|
-
if (balloon) {
|
|
45
|
-
// Balloon gets destroyed by the body collection.
|
|
46
|
-
// The powered by view gets destroyed by the balloon.
|
|
47
|
-
balloon.unpin();
|
|
48
|
-
this._balloonView = null;
|
|
49
|
-
}
|
|
50
|
-
this._showBalloonThrottled.cancel();
|
|
51
|
-
this.stopListening();
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Enables "powered by" label once the editor (ui) is ready.
|
|
55
|
-
*/
|
|
56
|
-
_handleEditorReady() {
|
|
24
|
+
_isEnabled() {
|
|
57
25
|
const editor = this.editor;
|
|
58
|
-
const forceVisible =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return;
|
|
26
|
+
const forceVisible = editor.config.get('ui.poweredBy.forceVisible');
|
|
27
|
+
if (forceVisible) {
|
|
28
|
+
return true;
|
|
62
29
|
}
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
editor.ui.focusTracker.on('change:isFocused', (evt, data, isFocused) => {
|
|
68
|
-
this._updateLastFocusedEditableElement();
|
|
69
|
-
if (isFocused) {
|
|
70
|
-
this._showBalloon();
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
this._hideBalloon();
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
editor.ui.focusTracker.on('change:focusedElement', (evt, data, focusedElement) => {
|
|
77
|
-
this._updateLastFocusedEditableElement();
|
|
78
|
-
if (focusedElement) {
|
|
79
|
-
this._showBalloon();
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
editor.ui.on('update', () => {
|
|
83
|
-
this._showBalloonThrottled();
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Creates an instance of the {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView balloon panel}
|
|
88
|
-
* with the "powered by" view inside ready for positioning.
|
|
89
|
-
*/
|
|
90
|
-
_createBalloonView() {
|
|
91
|
-
const editor = this.editor;
|
|
92
|
-
const balloon = this._balloonView = new BalloonPanelView();
|
|
93
|
-
const poweredByConfig = getNormalizedConfig(editor);
|
|
94
|
-
const view = new PoweredByView(editor.locale, poweredByConfig.label);
|
|
95
|
-
balloon.content.add(view);
|
|
96
|
-
balloon.set({
|
|
97
|
-
class: 'ck-powered-by-balloon'
|
|
98
|
-
});
|
|
99
|
-
editor.ui.view.body.add(balloon);
|
|
100
|
-
this._balloonView = balloon;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Attempts to display the balloon with the "powered by" view.
|
|
104
|
-
*/
|
|
105
|
-
_showBalloon() {
|
|
106
|
-
if (!this._lastFocusedEditableElement) {
|
|
107
|
-
return;
|
|
30
|
+
const licenseKey = editor.config.get('licenseKey');
|
|
31
|
+
if (licenseKey == 'GPL') {
|
|
32
|
+
return true;
|
|
108
33
|
}
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
this._createBalloonView();
|
|
113
|
-
}
|
|
114
|
-
this._balloonView.pin(attachOptions);
|
|
34
|
+
const licenseContent = parseBase64EncodedObject(licenseKey.split('.')[1]);
|
|
35
|
+
if (!licenseContent) {
|
|
36
|
+
return true;
|
|
115
37
|
}
|
|
38
|
+
return !licenseContent.whiteLabel;
|
|
116
39
|
}
|
|
117
40
|
/**
|
|
118
|
-
*
|
|
41
|
+
* Creates a "powered by" badge content.
|
|
119
42
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this._balloonView.unpin();
|
|
123
|
-
}
|
|
43
|
+
_createBadgeContent() {
|
|
44
|
+
return new PoweredByView(this.editor.locale, this._getNormalizedConfig().label);
|
|
124
45
|
}
|
|
125
46
|
/**
|
|
126
|
-
*
|
|
47
|
+
* Returns the normalized configuration for the "powered by" badge.
|
|
48
|
+
* It takes the user configuration into account and falls back to the default one.
|
|
127
49
|
*/
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
// If it's none of the editable element, then the focus is somewhere in the UI. Let's display powered by
|
|
144
|
-
// over the first element then.
|
|
145
|
-
this._lastFocusedEditableElement = editableEditorElements[0];
|
|
146
|
-
}
|
|
50
|
+
_getNormalizedConfig() {
|
|
51
|
+
const badgeConfig = super._getNormalizedConfig();
|
|
52
|
+
const userConfig = this.editor.config.get('ui.poweredBy') || {};
|
|
53
|
+
const position = userConfig.position || badgeConfig.position;
|
|
54
|
+
const verticalOffset = position === 'inside' ? 5 : badgeConfig.verticalOffset;
|
|
55
|
+
return {
|
|
56
|
+
position,
|
|
57
|
+
side: userConfig.side || badgeConfig.side,
|
|
58
|
+
label: userConfig.label === undefined ? DEFAULT_LABEL : userConfig.label,
|
|
59
|
+
verticalOffset: userConfig.verticalOffset !== undefined ? userConfig.verticalOffset : verticalOffset,
|
|
60
|
+
horizontalOffset: userConfig.horizontalOffset !== undefined ? userConfig.horizontalOffset : badgeConfig.horizontalOffset,
|
|
61
|
+
forceVisible: !!userConfig.forceVisible
|
|
62
|
+
};
|
|
147
63
|
}
|
|
148
64
|
}
|
|
149
65
|
/**
|
|
@@ -151,7 +67,7 @@ export default class PoweredBy extends /* #__PURE__ */ DomEmitterMixin() {
|
|
|
151
67
|
*/
|
|
152
68
|
class PoweredByView extends View {
|
|
153
69
|
/**
|
|
154
|
-
*
|
|
70
|
+
* Creates an instance of the "powered by" view.
|
|
155
71
|
*
|
|
156
72
|
* @param locale The localization services instance.
|
|
157
73
|
* @param label The label text.
|
|
@@ -164,14 +80,6 @@ class PoweredByView extends View {
|
|
|
164
80
|
content: poweredByIcon,
|
|
165
81
|
isColorInherited: false
|
|
166
82
|
});
|
|
167
|
-
iconView.extendTemplate({
|
|
168
|
-
attributes: {
|
|
169
|
-
style: {
|
|
170
|
-
width: ICON_WIDTH + 'px',
|
|
171
|
-
height: ICON_HEIGHT + 'px'
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
83
|
this.setTemplate({
|
|
176
84
|
tag: 'div',
|
|
177
85
|
attributes: {
|
|
@@ -207,69 +115,3 @@ class PoweredByView extends View {
|
|
|
207
115
|
});
|
|
208
116
|
}
|
|
209
117
|
}
|
|
210
|
-
function getBalloonAttachOptions(editor, focusedEditableElement) {
|
|
211
|
-
const poweredByConfig = getNormalizedConfig(editor);
|
|
212
|
-
const positioningFunction = poweredByConfig.side === 'right' ?
|
|
213
|
-
getLowerRightCornerPosition(focusedEditableElement, poweredByConfig) :
|
|
214
|
-
getLowerLeftCornerPosition(focusedEditableElement, poweredByConfig);
|
|
215
|
-
return {
|
|
216
|
-
target: focusedEditableElement,
|
|
217
|
-
positions: [positioningFunction]
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
function getLowerRightCornerPosition(focusedEditableElement, config) {
|
|
221
|
-
return getLowerCornerPosition(focusedEditableElement, config, (rootRect, balloonRect) => {
|
|
222
|
-
return rootRect.left + rootRect.width - balloonRect.width - config.horizontalOffset;
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
function getLowerLeftCornerPosition(focusedEditableElement, config) {
|
|
226
|
-
return getLowerCornerPosition(focusedEditableElement, config, rootRect => rootRect.left + config.horizontalOffset);
|
|
227
|
-
}
|
|
228
|
-
function getLowerCornerPosition(focusedEditableElement, config, getBalloonLeft) {
|
|
229
|
-
return (visibleEditableElementRect, balloonRect) => {
|
|
230
|
-
const editableElementRect = new Rect(focusedEditableElement);
|
|
231
|
-
if (editableElementRect.width < NARROW_ROOT_WIDTH_THRESHOLD || editableElementRect.height < NARROW_ROOT_HEIGHT_THRESHOLD) {
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
let balloonTop;
|
|
235
|
-
if (config.position === 'inside') {
|
|
236
|
-
balloonTop = editableElementRect.bottom - balloonRect.height;
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
balloonTop = editableElementRect.bottom - balloonRect.height / 2;
|
|
240
|
-
}
|
|
241
|
-
balloonTop -= config.verticalOffset;
|
|
242
|
-
const balloonLeft = getBalloonLeft(editableElementRect, balloonRect);
|
|
243
|
-
// Clone the editable element rect and place it where the balloon would be placed.
|
|
244
|
-
// This will allow getVisible() to work from editable element's perspective (rect source).
|
|
245
|
-
// and yield a result as if the balloon was on the same (scrollable) layer as the editable element.
|
|
246
|
-
const newBalloonPositionRect = visibleEditableElementRect
|
|
247
|
-
.clone()
|
|
248
|
-
.moveTo(balloonLeft, balloonTop)
|
|
249
|
-
.getIntersection(balloonRect.clone().moveTo(balloonLeft, balloonTop));
|
|
250
|
-
const newBalloonPositionVisibleRect = newBalloonPositionRect.getVisible();
|
|
251
|
-
if (!newBalloonPositionVisibleRect || newBalloonPositionVisibleRect.getArea() < balloonRect.getArea()) {
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
return {
|
|
255
|
-
top: balloonTop,
|
|
256
|
-
left: balloonLeft,
|
|
257
|
-
name: `position_${config.position}-side_${config.side}`,
|
|
258
|
-
config: {
|
|
259
|
-
withArrow: false
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
function getNormalizedConfig(editor) {
|
|
265
|
-
const userConfig = editor.config.get('ui.poweredBy');
|
|
266
|
-
const position = userConfig && userConfig.position || 'border';
|
|
267
|
-
return {
|
|
268
|
-
position,
|
|
269
|
-
label: DEFAULT_LABEL,
|
|
270
|
-
verticalOffset: position === 'inside' ? 5 : 0,
|
|
271
|
-
horizontalOffset: 5,
|
|
272
|
-
side: editor.locale.contentLanguageDirection === 'ltr' ? 'right' : 'left',
|
|
273
|
-
...userConfig
|
|
274
|
-
};
|
|
275
|
-
}
|
|
@@ -50,4 +50,4 @@ export default class MenuBarMenuPanelView extends View implements FocusableView
|
|
|
50
50
|
*
|
|
51
51
|
* They are reflected as CSS class suffixes on the panel view element.
|
|
52
52
|
*/
|
|
53
|
-
export type MenuBarMenuPanelPosition = 'se' | 'sw' | 'ne' | 'nw' | 'w' | 'e';
|
|
53
|
+
export type MenuBarMenuPanelPosition = 'se' | 'sw' | 'ne' | 'nw' | 'w' | 'ws' | 'e' | 'es';
|
|
@@ -100,6 +100,11 @@ export default class MenuBarMenuView extends View implements FocusableView {
|
|
|
100
100
|
* the {@link module:ui/menubar/menubarview~MenuBarView menu bar} and the UI language direction.
|
|
101
101
|
*/
|
|
102
102
|
get _panelPositions(): Array<PositioningFunction>;
|
|
103
|
+
/**
|
|
104
|
+
* The default position of the panel when the menu is opened.
|
|
105
|
+
* It is used when the optimal position cannot be calculated.
|
|
106
|
+
*/
|
|
107
|
+
private get _defaultMenuPositionName();
|
|
103
108
|
/**
|
|
104
109
|
* A function used to calculate the optimal position for the dropdown panel.
|
|
105
110
|
*
|
|
@@ -118,7 +118,7 @@ class MenuBarMenuView extends View {
|
|
|
118
118
|
fitInViewport: true,
|
|
119
119
|
positions: this._panelPositions
|
|
120
120
|
});
|
|
121
|
-
this.panelView.position = (optimalPanelPosition ? optimalPanelPosition.name : this.
|
|
121
|
+
this.panelView.position = (optimalPanelPosition ? optimalPanelPosition.name : this._defaultMenuPositionName);
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
@@ -150,6 +150,28 @@ class MenuBarMenuView extends View {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* The default position of the panel when the menu is opened.
|
|
155
|
+
* It is used when the optimal position cannot be calculated.
|
|
156
|
+
*/
|
|
157
|
+
get _defaultMenuPositionName() {
|
|
158
|
+
if (this.locale.uiLanguageDirection === 'ltr') {
|
|
159
|
+
if (this.parentMenuView) {
|
|
160
|
+
return 'es';
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
return 'se';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (this.parentMenuView) {
|
|
168
|
+
return 'ws';
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
return 'sw';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
153
175
|
}
|
|
154
176
|
/**
|
|
155
177
|
* A function used to calculate the optimal position for the dropdown panel.
|
package/src/menubar/utils.d.ts
CHANGED
package/src/menubar/utils.js
CHANGED
|
@@ -496,6 +496,7 @@ export const MenuBarMenuViewPanelPositioningFunctions = {
|
|
|
496
496
|
* groupId: 'insertInline',
|
|
497
497
|
* items: [
|
|
498
498
|
* 'menuBar:link',
|
|
499
|
+
* 'menuBar:bookmark',
|
|
499
500
|
* 'menuBar:comment',
|
|
500
501
|
* 'menuBar:insertMergeField'
|
|
501
502
|
* ]
|
|
@@ -753,6 +754,7 @@ export const DefaultMenuBarItems = [
|
|
|
753
754
|
groupId: 'insertInline',
|
|
754
755
|
items: [
|
|
755
756
|
'menuBar:link',
|
|
757
|
+
'menuBar:bookmark',
|
|
756
758
|
'menuBar:comment',
|
|
757
759
|
'menuBar:insertMergeField'
|
|
758
760
|
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 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
|
+
:root {
|
|
7
|
+
/* where 7.5(px) is the font size of the evaluation badge label and 13(px) is the base font size. */
|
|
8
|
+
--ck-evaluation-badge-font-size: calc(var(--ck-font-size-base) * 7.5 / 13);
|
|
9
|
+
/* where 7.5(px) is the line height of the evaluation badge label and 13(px) is the base font size. */
|
|
10
|
+
--ck-evaluation-badge-line-height: calc(var(--ck-font-size-base) * 7.5 / 13);
|
|
11
|
+
/* where -0.2(px) is the letter spacing of the evaluation badge label and 13(px) is the base font size. */
|
|
12
|
+
--ck-evaluation-badge-letter-spacing: calc(var(--ck-font-size-base) * -0.2 / 13);
|
|
13
|
+
--ck-evaluation-badge-padding-vertical: 2px;
|
|
14
|
+
--ck-evaluation-badge-padding-horizontal: 4px;
|
|
15
|
+
--ck-evaluation-badge-text-color: hsl(0, 0%, 31%);
|
|
16
|
+
--ck-evaluation-badge-border-radius: var(--ck-border-radius);
|
|
17
|
+
--ck-evaluation-badge-background: hsl(0, 0%, 100%);
|
|
18
|
+
--ck-evaluation-badge-border-color: var(--ck-color-focus-border);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.ck.ck-balloon-panel.ck-evaluation-badge-balloon {
|
|
22
|
+
--ck-border-radius: var(--ck-evaluation-badge-border-radius);
|
|
23
|
+
|
|
24
|
+
box-shadow: none;
|
|
25
|
+
background: var(--ck-evaluation-badge-background);
|
|
26
|
+
min-height: unset;
|
|
27
|
+
z-index: calc( var(--ck-z-panel) - 1 );
|
|
28
|
+
|
|
29
|
+
& .ck.ck-evaluation-badge {
|
|
30
|
+
line-height: var(--ck-evaluation-badge-line-height);
|
|
31
|
+
padding: var(--ck-evaluation-badge-padding-vertical) var(--ck-evaluation-badge-padding-horizontal);
|
|
32
|
+
|
|
33
|
+
& .ck-evaluation-badge__label {
|
|
34
|
+
display: block;
|
|
35
|
+
padding: 0 2px;
|
|
36
|
+
font-size: var(--ck-evaluation-badge-font-size);
|
|
37
|
+
letter-spacing: var(--ck-evaluation-badge-letter-spacing);
|
|
38
|
+
font-weight: bold;
|
|
39
|
+
line-height: normal;
|
|
40
|
+
text-transform: uppercase;
|
|
41
|
+
color: var(--ck-evaluation-badge-text-color);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&[class*="position_inside"] {
|
|
46
|
+
border-color: transparent;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&[class*="position_border"] {
|
|
50
|
+
border: var(--ck-focus-ring);
|
|
51
|
+
border-color: var(--ck-evaluation-badge-border-color);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|