@ckeditor/ckeditor5-ui
Advanced tools
Comparing version 18.0.0 to 19.0.0
Changelog | ||
========= | ||
## [19.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v18.0.0...v19.0.0) (2020-04-29) | ||
### MAJOR BREAKING CHANGES | ||
* `ViewCollection` no longer has the `locale` property. | ||
* The `ViewCollection#constructor()` no longer accepts the `locale` parameter. | ||
* `LabeledView` component was renamed to `LabeledFieldView`. Also, its instance of a labeled component's view is available through `LabeledFieldView#fieldView`. It replaced the `LabeledView#view`. | ||
### MINOR BREAKING CHANGES | ||
* The `DropdownView#focusTracker` property has been removed as it served no purpose. | ||
### Features | ||
* Allowed defining initial items of `ViewCollection` and `BodyCollection` in the constructor. See [ckeditor/ckeditor5#6319](https://github.com/ckeditor/ckeditor5/issues/6319). ([6cd15de](https://github.com/ckeditor/ckeditor5-ui/commit/6cd15de)) | ||
The `View#createCollection()` method now also accepts an iterator of views. | ||
* Introduce `FormHeaderView` UI component. Closes [ckeditor/ckeditor5#6109](https://github.com/ckeditor/ckeditor5/issues/6109). ([eb1ce18](https://github.com/ckeditor/ckeditor5-ui/commit/eb1ce18)) | ||
* The `BlockToolbar` should group items when there is no place to show them all. Closes [ckeditor/ckeditor5#6449](https://github.com/ckeditor/ckeditor5/issues/6449). Closes [ckeditor/ckeditor5#6575](https://github.com/ckeditor/ckeditor5/issues/6575). Closes [ckeditor/ckeditor5#6570](https://github.com/ckeditor/ckeditor5/issues/6570). ([fcd9c4e](https://github.com/ckeditor/ckeditor5-ui/commit/fcd9c4e)) | ||
Improved `ToolbarView#maxWidth` and items grouping when the toolbar is invisible. | ||
### Bug fixes | ||
* Call `ResizeObserver.destroy()` when destroying block toolbar. ([59449d2](https://github.com/ckeditor/ckeditor5-ui/commit/59449d2)) | ||
### Other changes | ||
* Removed the obsolete `DropdownView#focusTracker`. Closes [ckeditor/ckeditor5#6548](https://github.com/ckeditor/ckeditor5/issues/6548). ([ac750c7](https://github.com/ckeditor/ckeditor5-ui/commit/ac750c7)) | ||
* Rename `LabeledView` component to `LabeledFieldView`. See [ckeditor/ckeditor5#6110](https://github.com/ckeditor/ckeditor5/issues/6110). ([5a7aca7](https://github.com/ckeditor/ckeditor5-ui/commit/5a7aca7)) | ||
* Updated translations. ([2a391d6](https://github.com/ckeditor/ckeditor5-ui/commit/2a391d6)) | ||
## [18.0.0](https://github.com/ckeditor/ckeditor5-ui/compare/v17.0.0...v18.0.0) (2020-03-19) | ||
@@ -5,0 +38,0 @@ |
{ | ||
"name": "@ckeditor/ckeditor5-ui", | ||
"version": "18.0.0", | ||
"version": "19.0.0", | ||
"description": "The UI framework and standard UI library of CKEditor 5.", | ||
@@ -12,21 +12,21 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-core": "^18.0.0", | ||
"@ckeditor/ckeditor5-utils": "^18.0.0", | ||
"@ckeditor/ckeditor5-core": "^19.0.0", | ||
"@ckeditor/ckeditor5-utils": "^19.0.0", | ||
"lodash-es": "^4.17.10" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-basic-styles": "^18.0.0", | ||
"@ckeditor/ckeditor5-block-quote": "^18.0.0", | ||
"@ckeditor/ckeditor5-editor-balloon": "^18.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^18.0.0", | ||
"@ckeditor/ckeditor5-engine": "^18.0.0", | ||
"@ckeditor/ckeditor5-enter": "^18.0.0", | ||
"@ckeditor/ckeditor5-essentials": "^18.0.0", | ||
"@ckeditor/ckeditor5-heading": "^18.0.0", | ||
"@ckeditor/ckeditor5-image": "^18.0.0", | ||
"@ckeditor/ckeditor5-link": "^18.0.0", | ||
"@ckeditor/ckeditor5-list": "^18.0.0", | ||
"@ckeditor/ckeditor5-mention": "^18.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^18.0.0", | ||
"@ckeditor/ckeditor5-typing": "^18.0.0", | ||
"@ckeditor/ckeditor5-basic-styles": "^19.0.0", | ||
"@ckeditor/ckeditor5-block-quote": "^19.0.0", | ||
"@ckeditor/ckeditor5-editor-balloon": "^19.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^19.0.0", | ||
"@ckeditor/ckeditor5-engine": "^19.0.0", | ||
"@ckeditor/ckeditor5-enter": "^19.0.0", | ||
"@ckeditor/ckeditor5-essentials": "^19.0.0", | ||
"@ckeditor/ckeditor5-heading": "^19.0.0", | ||
"@ckeditor/ckeditor5-image": "^19.0.0", | ||
"@ckeditor/ckeditor5-link": "^19.0.0", | ||
"@ckeditor/ckeditor5-list": "^19.0.0", | ||
"@ckeditor/ckeditor5-mention": "^19.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^19.0.0", | ||
"@ckeditor/ckeditor5-typing": "^19.0.0", | ||
"eslint": "^5.5.0", | ||
@@ -33,0 +33,0 @@ "eslint-config-ckeditor5": "^2.0.0", |
@@ -11,3 +11,2 @@ /** | ||
import View from '../view'; | ||
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker'; | ||
import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler'; | ||
@@ -160,10 +159,2 @@ | ||
/** | ||
* Tracks information about DOM focus in the dropdown. | ||
* | ||
* @readonly | ||
* @member {module:utils/focustracker~FocusTracker} | ||
*/ | ||
this.focusTracker = new FocusTracker(); | ||
/** | ||
* Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}. It manages | ||
@@ -282,5 +273,2 @@ * keystrokes of the dropdown: | ||
// Register #element in the focus tracker. | ||
this.focusTracker.add( this.element ); | ||
const closeDropdown = ( data, cancel ) => { | ||
@@ -287,0 +275,0 @@ if ( this.isOpen ) { |
@@ -37,2 +37,20 @@ /** | ||
/** | ||
* Creates a new instance of the {@link module:ui/editorui/bodycollection~BodyCollection}. | ||
* | ||
* @param {module:utils/locale~Locale} locale The {@link module:core/editor/editor~Editor editor's locale} instance. | ||
* @param {Iterable.<module:ui/view~View>} [initialItems] The initial items of the collection. | ||
*/ | ||
constructor( locale, initialItems = [] ) { | ||
super( initialItems ); | ||
/** | ||
* The {@link module:core/editor/editor~Editor#locale editor's locale} instance. | ||
* See the view {@link module:ui/view~View#locale locale} property. | ||
* | ||
* @member {module:utils/locale~Locale} | ||
*/ | ||
this.locale = locale; | ||
} | ||
/** | ||
* Attaches the body collection to the DOM body element. You need to execute this method to render the content of | ||
@@ -39,0 +57,0 @@ * the body collection. |
@@ -55,2 +55,4 @@ /** | ||
* } ); | ||
* | ||
* Check out the {@glink framework/guides/deep-dive/ui/focus-tracking "Deep dive into focus tracking" guide} to learn more. | ||
*/ | ||
@@ -57,0 +59,0 @@ export default class FocusCycler { |
@@ -383,5 +383,5 @@ /** | ||
* balloonToolbar: { | ||
* items: [ 'bold', 'italic', 'undo', 'redo' ] | ||
* items: [ 'bold', 'italic', 'undo', 'redo' ], | ||
* shouldNotGroupWhenFull: true | ||
* }, | ||
* shouldNotGroupWhenFull: true | ||
* }; | ||
@@ -388,0 +388,0 @@ * |
@@ -22,5 +22,11 @@ /** | ||
import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect'; | ||
import normalizeToolbarConfig from '../normalizetoolbarconfig'; | ||
import ResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/resizeobserver'; | ||
import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit'; | ||
import iconPilcrow from '@ckeditor/ckeditor5-core/theme/icons/pilcrow.svg'; | ||
const toPx = toUnit( 'px' ); | ||
/** | ||
@@ -82,2 +88,10 @@ * The block toolbar plugin. | ||
/** | ||
* A cached and normalized `config.blockToolbar` object. | ||
* | ||
* @type {module:core/editor/editorconfig~EditorConfig#blockToolbar} | ||
* @private | ||
*/ | ||
this._blockToolbarConfig = normalizeToolbarConfig( this.editor.config.get( 'blockToolbar' ) ); | ||
/** | ||
* The toolbar view. | ||
@@ -103,2 +117,16 @@ * | ||
/** | ||
* An instance of the resize observer that allows to respond to changes in editable's geometry | ||
* so the toolbar can stay within its boundaries (and group toolbar items that do not fit). | ||
* | ||
* **Note**: Used only when `shouldNotGroupWhenFull` was **not** set in the | ||
* {@link module:core/editor/editorconfig~EditorConfig#blockToolbar configuration}. | ||
* | ||
* **Note:** Created in {@link #afterInit}. | ||
* | ||
* @protected | ||
* @member {module:utils/dom/resizeobserver~ResizeObserver} | ||
*/ | ||
this._resizeObserver = null; | ||
// Close the #panelView upon clicking outside of the plugin UI. | ||
@@ -155,5 +183,5 @@ clickOutsideHandler( { | ||
const factory = this.editor.ui.componentFactory; | ||
const config = this.editor.config.get( 'blockToolbar' ) || []; | ||
const config = this._blockToolbarConfig; | ||
this.toolbarView.fillFromConfig( config, factory ); | ||
this.toolbarView.fillFromConfig( config.items, factory ); | ||
@@ -164,2 +192,13 @@ // Hide panel before executing each button in the panel. | ||
} | ||
if ( !config.shouldNotGroupWhenFull ) { | ||
this.listenTo( this.editor, 'ready', () => { | ||
const editableElement = this.editor.ui.view.editable.element; | ||
// Set #toolbarView's max-width just after the initialization and update it on the editable resize. | ||
this._resizeObserver = new ResizeObserver( editableElement, () => { | ||
this.toolbarView.maxWidth = this._getToolbarMaxWidth(); | ||
} ); | ||
} ); | ||
} | ||
} | ||
@@ -177,2 +216,6 @@ | ||
this.toolbarView.destroy(); | ||
if ( this._resizeObserver ) { | ||
this._resizeObserver.destroy(); | ||
} | ||
} | ||
@@ -187,3 +230,6 @@ | ||
_createToolbarView() { | ||
const toolbarView = new ToolbarView( this.editor.locale ); | ||
const shouldGroupWhenFull = !this._blockToolbarConfig.shouldNotGroupWhenFull; | ||
const toolbarView = new ToolbarView( this.editor.locale, { | ||
shouldGroupWhenFull | ||
} ); | ||
@@ -335,2 +381,28 @@ toolbarView.extendTemplate( { | ||
// So here's the thing: If there was no initial panelView#show() or these two were in different order, the toolbar | ||
// positioning will break in RTL editors. Weird, right? What you show know is that the toolbar | ||
// grouping works thanks to: | ||
// | ||
// * the ResizeObserver, which kicks in as soon as the toolbar shows up in DOM (becomes visible again). | ||
// * the observable ToolbarView#maxWidth, which triggers re-grouping when changed. | ||
// | ||
// Here are the possible scenarios: | ||
// | ||
// 1. (WRONG ❌) If the #maxWidth is set when the toolbar is invisible, it won't affect item grouping (no DOMRects, no grouping). | ||
// Then, when panelView.pin() is called, the position of the toolbar will be calculated for the old | ||
// items grouping state, and when finally ResizeObserver kicks in (hey, the toolbar is visible now, right?) | ||
// it will group/ungroup some items and the length of the toolbar will change. But since in RTL the toolbar | ||
// is attached on the right side and the positioning uses CSS "left", it will result in the toolbar shifting | ||
// to the left and being displayed in the wrong place. | ||
// 2. (WRONG ❌) If the panelView.pin() is called first and #maxWidth set next, then basically the story repeats. The balloon | ||
// calculates the position for the old toolbar grouping state, then the toolbar re-groups items and because | ||
// it is positioned using CSS "left" it will move. | ||
// 3. (RIGHT ✅) We show the panel first (the toolbar does re-grouping but it does not matter), then the #maxWidth | ||
// is set allowing the toolbar to re-group again and finally panelView.pin() does the positioning when the | ||
// items grouping state is stable and final. | ||
// | ||
// https://github.com/ckeditor/ckeditor5/issues/6449, https://github.com/ckeditor/ckeditor5/issues/6575 | ||
this.panelView.show(); | ||
this.toolbarView.maxWidth = this._getToolbarMaxWidth(); | ||
this.panelView.pin( { | ||
@@ -399,2 +471,19 @@ target: this.buttonView.element, | ||
} | ||
/** | ||
* Gets the {@link #toolbarView} max-width, based on | ||
* editable width plus distance between farthest edge of the {@link #buttonView} and the editable. | ||
* | ||
* @private | ||
* @returns {String} maxWidth A maximum width that toolbar can have, in pixels. | ||
*/ | ||
_getToolbarMaxWidth() { | ||
const editableElement = this.editor.ui.view.editable.element; | ||
const editableRect = new Rect( editableElement ); | ||
const buttonRect = new Rect( this.buttonView.element ); | ||
const isRTL = this.editor.locale.uiLanguageDirection === 'rtl'; | ||
const offset = isRTL ? ( buttonRect.left - editableRect.right ) + buttonRect.width : editableRect.left - buttonRect.left; | ||
return toPx( editableRect.width + offset ); | ||
} | ||
} | ||
@@ -416,2 +505,13 @@ | ||
* | ||
* ## Configuring items grouping | ||
* | ||
* You can prevent automatic items grouping by setting the `shouldNotGroupWhenFull` option: | ||
* | ||
* const config = { | ||
* blockToolbar: { | ||
* items: [ 'paragraph', 'heading1', 'heading2', '|', 'bulletedList', 'numberedList' ], | ||
* shouldNotGroupWhenFull: true | ||
* }, | ||
* }; | ||
* | ||
* Read more about configuring the main editor toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}. | ||
@@ -418,0 +518,0 @@ * |
@@ -528,2 +528,11 @@ /** | ||
/** | ||
* A flag indicating that an items grouping update has been queued (e.g. due to the toolbar being visible) | ||
* and should be executed immediately the next time the toolbar shows up. | ||
* | ||
* @readonly | ||
* @member {Boolean} | ||
*/ | ||
this.shouldUpdateGroupingOnNextResize = false; | ||
// Only those items that were not grouped are visible to the user. | ||
@@ -618,3 +627,4 @@ view.itemsView.children.bindTo( this.ungroupedItems ).using( item => item ); | ||
// from DOM. DOMRects won't work anyway and there will be tons of warning in the console and | ||
// nothing else. | ||
// nothing else. This happens, for instance, when the toolbar is detached from DOM and | ||
// some logic adds or removes its #items. | ||
if ( !this.viewElement.ownerDocument.body.contains( this.viewElement ) ) { | ||
@@ -624,2 +634,13 @@ return; | ||
// Do not update grouping when the element is invisible. Such toolbar has DOMRect filled with zeros | ||
// and that would cause all items to be grouped. Instead, queue the grouping so it runs next time | ||
// the toolbar is visible (the next ResizeObserver callback execution). This is handy because | ||
// the grouping could be caused by increasing the #maxWidth when the toolbar was invisible and the next | ||
// time it shows up, some items could actually be ungrouped (https://github.com/ckeditor/ckeditor5/issues/6575). | ||
if ( !this.viewElement.offsetParent ) { | ||
this.shouldUpdateGroupingOnNextResize = true; | ||
return; | ||
} | ||
let wereItemsGrouped; | ||
@@ -707,3 +728,5 @@ | ||
this.resizeObserver = new ResizeObserver( this.viewElement, entry => { | ||
if ( !previousWidth || previousWidth !== entry.contentRect.width ) { | ||
if ( !previousWidth || previousWidth !== entry.contentRect.width || this.shouldUpdateGroupingOnNextResize ) { | ||
this.shouldUpdateGroupingOnNextResize = false; | ||
this._updateGrouping(); | ||
@@ -710,0 +733,0 @@ |
@@ -256,3 +256,4 @@ /** | ||
* | ||
* this.items = this.createCollection(); | ||
* const child = new ChildView( locale ); | ||
* this.items = this.createCollection( [ child ] ); | ||
* | ||
@@ -269,17 +270,12 @@ * this.setTemplate( { | ||
* const view = new SampleView( locale ); | ||
* const child = new ChildView( locale ); | ||
* | ||
* view.render(); | ||
* | ||
* // It will append <p></p> to the <body>. | ||
* // It will append <p><child#element></p> to the <body>. | ||
* document.body.appendChild( view.element ); | ||
* | ||
* // From now on the child is nested under its parent, which is also reflected in DOM. | ||
* // <p><child#element></p> | ||
* view.items.add( child ); | ||
* | ||
* @param {Iterable.<module:ui/view~View>} [views] Initial views of the collection. | ||
* @returns {module:ui/viewcollection~ViewCollection} A new collection of view instances. | ||
*/ | ||
createCollection() { | ||
const collection = new ViewCollection(); | ||
createCollection( views ) { | ||
const collection = new ViewCollection( views ); | ||
@@ -286,0 +282,0 @@ this._viewCollections.add( collection ); |
@@ -54,6 +54,6 @@ /** | ||
* | ||
* @param {module:utils/locale~Locale} [locale] The {@link module:core/editor/editor~Editor editor's locale} instance. | ||
* @param {Iterable.<module:ui/view~View>} [initialItems] The initial items of the collection. | ||
*/ | ||
constructor( locale ) { | ||
super( { | ||
constructor( initialItems = [] ) { | ||
super( initialItems, { | ||
// An #id Number attribute should be legal and not break the `ViewCollection` instance. | ||
@@ -66,9 +66,3 @@ // https://github.com/ckeditor/ckeditor5-ui/issues/93 | ||
this.on( 'add', ( evt, view, index ) => { | ||
if ( !view.isRendered ) { | ||
view.render(); | ||
} | ||
if ( view.element && this._parentElement ) { | ||
this._parentElement.insertBefore( view.element, this._parentElement.children[ index ] ); | ||
} | ||
this._renderViewIntoCollectionParent( view, index ); | ||
} ); | ||
@@ -84,10 +78,2 @@ | ||
/** | ||
* The {@link module:core/editor/editor~Editor#locale editor's locale} instance. | ||
* See the view {@link module:ui/view~View#locale locale} property. | ||
* | ||
* @member {module:utils/locale~Locale} | ||
*/ | ||
this.locale = locale; | ||
/** | ||
* A parent element within which child views are rendered and managed in DOM. | ||
@@ -118,2 +104,7 @@ * | ||
this._parentElement = elementOrDocFragment; | ||
// Take care of the initial collection items passed to the constructor. | ||
for ( const view of this ) { | ||
this._renderViewIntoCollectionParent( view ); | ||
} | ||
} | ||
@@ -202,2 +193,26 @@ | ||
/** | ||
* This method {@link module:ui/view~View#render renders} a new view added to the collection. | ||
* | ||
* If the {@link #_parentElement parent element} of the collection is set, this method also adds | ||
* the view's {@link module:ui/view~View#element} as a child of the parent in DOM at a specified index. | ||
* | ||
* **Note**: If index is not specified, the view's element is pushed as the last child | ||
* of the parent element. | ||
* | ||
* @private | ||
* @param {module:ui/view~View} view A new view added to the collection. | ||
* @param {Number} [index] An index the view holds in the collection. When not specified, | ||
* the view is added at the end. | ||
*/ | ||
_renderViewIntoCollectionParent( view, index ) { | ||
if ( !view.isRendered ) { | ||
view.render(); | ||
} | ||
if ( view.element && this._parentElement ) { | ||
this._parentElement.insertBefore( view.element, this._parentElement.children[ index ] ); | ||
} | ||
} | ||
/** | ||
* Removes a child view from the collection. If the {@link #setParent parent element} of the | ||
@@ -204,0 +219,0 @@ * collection has been set, the {@link module:ui/view~View#element element} of the view is also removed |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
570521
141
10460
+ Added@ckeditor/ckeditor5-core@19.0.1(transitive)
+ Added@ckeditor/ckeditor5-engine@19.0.1(transitive)
+ Added@ckeditor/ckeditor5-utils@19.0.2(transitive)
- Removed@ckeditor/ckeditor5-core@18.0.0(transitive)
- Removed@ckeditor/ckeditor5-engine@18.0.0(transitive)
- Removed@ckeditor/ckeditor5-utils@18.0.0(transitive)