@ckeditor/ckeditor5-widget
Advanced tools
Comparing version 28.0.0 to 29.0.0
{ | ||
"name": "@ckeditor/ckeditor5-widget", | ||
"version": "28.0.0", | ||
"version": "29.0.0", | ||
"description": "Widget API for CKEditor 5.", | ||
@@ -14,25 +14,25 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-core": "^28.0.0", | ||
"@ckeditor/ckeditor5-engine": "^28.0.0", | ||
"@ckeditor/ckeditor5-enter": "^28.0.0", | ||
"@ckeditor/ckeditor5-ui": "^28.0.0", | ||
"@ckeditor/ckeditor5-utils": "^28.0.0", | ||
"@ckeditor/ckeditor5-typing": "^28.0.0", | ||
"@ckeditor/ckeditor5-core": "^29.0.0", | ||
"@ckeditor/ckeditor5-engine": "^29.0.0", | ||
"@ckeditor/ckeditor5-enter": "^29.0.0", | ||
"@ckeditor/ckeditor5-ui": "^29.0.0", | ||
"@ckeditor/ckeditor5-utils": "^29.0.0", | ||
"@ckeditor/ckeditor5-typing": "^29.0.0", | ||
"lodash-es": "^4.17.15" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-basic-styles": "^28.0.0", | ||
"@ckeditor/ckeditor5-block-quote": "^28.0.0", | ||
"@ckeditor/ckeditor5-clipboard": "^28.0.0", | ||
"@ckeditor/ckeditor5-editor-balloon": "^28.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^28.0.0", | ||
"@ckeditor/ckeditor5-essentials": "^28.0.0", | ||
"@ckeditor/ckeditor5-heading": "^28.0.0", | ||
"@ckeditor/ckeditor5-horizontal-line": "^28.0.0", | ||
"@ckeditor/ckeditor5-image": "^28.0.0", | ||
"@ckeditor/ckeditor5-link": "^28.0.0", | ||
"@ckeditor/ckeditor5-media-embed": "^28.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^28.0.0", | ||
"@ckeditor/ckeditor5-table": "^28.0.0", | ||
"@ckeditor/ckeditor5-undo": "^28.0.0" | ||
"@ckeditor/ckeditor5-basic-styles": "^29.0.0", | ||
"@ckeditor/ckeditor5-block-quote": "^29.0.0", | ||
"@ckeditor/ckeditor5-clipboard": "^29.0.0", | ||
"@ckeditor/ckeditor5-editor-balloon": "^29.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^29.0.0", | ||
"@ckeditor/ckeditor5-essentials": "^29.0.0", | ||
"@ckeditor/ckeditor5-heading": "^29.0.0", | ||
"@ckeditor/ckeditor5-horizontal-line": "^29.0.0", | ||
"@ckeditor/ckeditor5-image": "^29.0.0", | ||
"@ckeditor/ckeditor5-link": "^29.0.0", | ||
"@ckeditor/ckeditor5-media-embed": "^29.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^29.0.0", | ||
"@ckeditor/ckeditor5-table": "^29.0.0", | ||
"@ckeditor/ckeditor5-undo": "^29.0.0" | ||
}, | ||
@@ -39,0 +39,0 @@ "engines": { |
@@ -5,4 +5,4 @@ CKEditor 5 widget API | ||
[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-widget.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-widget) | ||
[![Dependency Status](https://david-dm.org/ckeditor/ckeditor5-widget/status.svg)](https://david-dm.org/ckeditor/ckeditor5-widget) | ||
[![devDependency Status](https://david-dm.org/ckeditor/ckeditor5-widget/dev-status.svg)](https://david-dm.org/ckeditor/ckeditor5-widget?type=dev) | ||
[![Coverage Status](https://coveralls.io/repos/github/ckeditor/ckeditor5/badge.svg?branch=master)](https://coveralls.io/github/ckeditor/ckeditor5?branch=master) | ||
[![Build Status](https://travis-ci.com/ckeditor/ckeditor5.svg?branch=master)](https://travis-ci.com/ckeditor/ckeditor5) | ||
@@ -9,0 +9,0 @@ This package implements the widget API for CKEditor 5. |
@@ -285,11 +285,11 @@ /** | ||
/** | ||
* Returns a model position which is optimal (in terms of UX) for inserting a widget block. | ||
* Returns a model range which is optimal (in terms of UX) for inserting a widget block. | ||
* | ||
* For instance, if a selection is in the middle of a paragraph, the position before this paragraph | ||
* For instance, if a selection is in the middle of a paragraph, the collapsed range before this paragraph | ||
* will be returned so that it is not split. If the selection is at the end of a paragraph, | ||
* the position after this paragraph will be returned. | ||
* the collapsed range after this paragraph will be returned. | ||
* | ||
* Note: If the selection is placed in an empty block, that block will be returned. If that position | ||
* is then passed to {@link module:engine/model/model~Model#insertContent}, | ||
* the block will be fully replaced by the image. | ||
* Note: If the selection is placed in an empty block, the range in that block will be returned. If that range | ||
* is then passed to {@link module:engine/model/model~Model#insertContent}, the block will be fully replaced | ||
* by the inserted widget block. | ||
* | ||
@@ -299,5 +299,5 @@ * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection | ||
* @param {module:engine/model/model~Model} model Model instance. | ||
* @returns {module:engine/model/position~Position} The optimal position. | ||
* @returns {module:engine/model/range~Range} The optimal range. | ||
*/ | ||
export function findOptimalInsertionPosition( selection, model ) { | ||
export function findOptimalInsertionRange( selection, model ) { | ||
const selectedElement = selection.getSelectedElement(); | ||
@@ -311,7 +311,7 @@ | ||
if ( typeAroundFakeCaretPosition ) { | ||
return model.createPositionAt( selectedElement, typeAroundFakeCaretPosition ); | ||
return model.createRange( model.createPositionAt( selectedElement, typeAroundFakeCaretPosition ) ); | ||
} | ||
if ( model.schema.isBlock( selectedElement ) ) { | ||
return model.createPositionAfter( selectedElement ); | ||
if ( model.schema.isObject( selectedElement ) && !model.schema.isInline( selectedElement ) ) { | ||
return model.createRangeOn( selectedElement ); | ||
} | ||
@@ -326,3 +326,3 @@ } | ||
if ( firstBlock.isEmpty ) { | ||
return model.createPositionAt( firstBlock, 0 ); | ||
return model.createRange( model.createPositionAt( firstBlock, 0 ) ); | ||
} | ||
@@ -334,26 +334,13 @@ | ||
if ( selection.focus.isTouching( positionAfter ) ) { | ||
return positionAfter; | ||
return model.createRange( positionAfter ); | ||
} | ||
// Otherwise return position before the block. | ||
return model.createPositionBefore( firstBlock ); | ||
return model.createRange( model.createPositionBefore( firstBlock ) ); | ||
} | ||
return selection.focus; | ||
return model.createRange( selection.focus ); | ||
} | ||
/** | ||
* Checks if the selection is on an object. | ||
* | ||
* @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection | ||
* @param {module:engine/model/schema~Schema} schema | ||
* @returns {Boolean} | ||
*/ | ||
export function checkSelectionOnObject( selection, schema ) { | ||
const selectedElement = selection.getSelectedElement(); | ||
return !!selectedElement && schema.isObject( selectedElement ); | ||
} | ||
/** | ||
* A util to be used in order to map view positions to correct model positions when implementing a widget | ||
@@ -360,0 +347,0 @@ * which renders non-empty view element for an empty model element. |
@@ -55,3 +55,4 @@ /** | ||
init() { | ||
const view = this.editor.editing.view; | ||
const editor = this.editor; | ||
const view = editor.editing.view; | ||
const viewDocument = view.document; | ||
@@ -68,4 +69,54 @@ | ||
// Model to view selection converter. | ||
// Converts selection placed over widget element to fake selection | ||
// Converts selection placed over widget element to fake selection. | ||
// | ||
// By default, the selection is downcasted by the engine to surround the attribute element, even though its only | ||
// child is an inline widget. A similar thing also happens when a collapsed marker is rendered as a UI element | ||
// next to an inline widget: the view selection contains both the widget and the marker. | ||
// | ||
// This prevents creating a correct fake selection when this inline widget is selected. Normalize the selection | ||
// in these cases based on the model: | ||
// | ||
// [<attributeElement><inlineWidget /></attributeElement>] -> <attributeElement>[<inlineWidget />]</attributeElement> | ||
// [<uiElement></uiElement><inlineWidget />] -> <uiElement></uiElement>[<inlineWidget />] | ||
// | ||
// Thanks to this: | ||
// | ||
// * fake selection can be set correctly, | ||
// * any logic depending on (View)Selection#getSelectedElement() also works OK. | ||
// | ||
// See https://github.com/ckeditor/ckeditor5/issues/9524. | ||
this.editor.editing.downcastDispatcher.on( 'selection', ( evt, data, conversionApi ) => { | ||
const viewWriter = conversionApi.writer; | ||
const modelSelection = data.selection; | ||
// The collapsed selection can't contain any widget. | ||
if ( modelSelection.isCollapsed ) { | ||
return; | ||
} | ||
const selectedModelElement = modelSelection.getSelectedElement(); | ||
if ( !selectedModelElement ) { | ||
return; | ||
} | ||
const selectedViewElement = editor.editing.mapper.toViewElement( selectedModelElement ); | ||
if ( !isWidget( selectedViewElement ) ) { | ||
return; | ||
} | ||
if ( !conversionApi.consumable.consume( modelSelection, 'selection' ) ) { | ||
return; | ||
} | ||
viewWriter.setSelection( viewWriter.createRangeOn( selectedViewElement ), { | ||
fake: true, | ||
label: getLabel( selectedViewElement ) | ||
} ); | ||
} ); | ||
// Mark all widgets inside the selection with the css class. | ||
// This handler is registered at the 'low' priority so it's triggered after the real selection conversion. | ||
this.editor.editing.downcastDispatcher.on( 'selection', ( evt, data, conversionApi ) => { | ||
// Remove selected class from previously selected widgets. | ||
@@ -76,6 +127,8 @@ this._clearPreviouslySelectedWidgets( conversionApi.writer ); | ||
const viewSelection = viewWriter.document.selection; | ||
const selectedElement = viewSelection.getSelectedElement(); | ||
let lastMarked = null; | ||
for ( const range of viewSelection.getRanges() ) { | ||
// Note: There could be multiple selected widgets in a range but no fake selection. | ||
// All of them must be marked as selected, for instance [<widget></widget><widget></widget>] | ||
for ( const value of range ) { | ||
@@ -90,7 +143,2 @@ const node = value.item; | ||
lastMarked = node; | ||
// Check if widget is a single element selected. | ||
if ( node == selectedElement ) { | ||
viewWriter.setSelection( viewSelection.getRanges(), { fake: true, label: getLabel( selectedElement ) } ); | ||
} | ||
} | ||
@@ -97,0 +145,0 @@ } |
@@ -63,3 +63,3 @@ /** | ||
* | ||
* @private | ||
* @protected | ||
* @type {Map.<module:engine/view/containerelement~ContainerElement, module:widget/widgetresize/resizer~Resizer>} | ||
@@ -71,6 +71,2 @@ */ | ||
this.editor.model.schema.setAttributeProperties( 'width', { | ||
isFormatting: true | ||
} ); | ||
this.editor.editing.view.addObserver( MouseObserver ); | ||
@@ -77,0 +73,0 @@ |
@@ -10,3 +10,2 @@ /** | ||
import View from '@ckeditor/ckeditor5-ui/src/view'; | ||
import Template from '@ckeditor/ckeditor5-ui/src/template'; | ||
@@ -20,2 +19,3 @@ import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect'; | ||
import ResizeState from './resizerstate'; | ||
import SizeView from './sizeview'; | ||
@@ -46,3 +46,3 @@ /** | ||
* @readonly | ||
* @member {module:widget/widgetresize/resizer~SizeView} #_sizeUI | ||
* @member {module:widget/widgetresize/sizeview~SizeView} #_sizeView | ||
*/ | ||
@@ -159,3 +159,3 @@ | ||
this._sizeUI.bindToState( this._options, this.state ); | ||
this._sizeView._bindToState( this._options, this.state ); | ||
@@ -314,4 +314,3 @@ this._initialViewWidth = this._options.viewElement.getStyle( 'width' ); | ||
_cleanup() { | ||
this._sizeUI.dismiss(); | ||
this._sizeUI.isVisible = false; | ||
this._sizeView._dismiss(); | ||
@@ -448,3 +447,3 @@ const editingView = this._options.editor.editing.view; | ||
/** | ||
* Sets up the {@link #_sizeUI} property and adds it to the passed `domElement`. | ||
* Sets up the {@link #_sizeView} property and adds it to the passed `domElement`. | ||
* | ||
@@ -455,10 +454,8 @@ * @private | ||
_appendSizeUI( domElement ) { | ||
const sizeUI = new SizeView(); | ||
this._sizeView = new SizeView(); | ||
// Make sure icon#element is rendered before passing to appendChild(). | ||
sizeUI.render(); | ||
this._sizeView.render(); | ||
this._sizeUI = sizeUI; | ||
domElement.appendChild( sizeUI.element ); | ||
domElement.appendChild( this._sizeView.element ); | ||
} | ||
@@ -485,57 +482,2 @@ | ||
/** | ||
* A view displaying the proposed new element size during the resizing. | ||
* | ||
* @extends {module:ui/view~View} | ||
*/ | ||
class SizeView extends View { | ||
constructor() { | ||
super(); | ||
const bind = this.bindTemplate; | ||
this.setTemplate( { | ||
tag: 'div', | ||
attributes: { | ||
class: [ | ||
'ck', | ||
'ck-size-view', | ||
bind.to( 'activeHandlePosition', value => value ? `ck-orientation-${ value }` : '' ) | ||
], | ||
style: { | ||
display: bind.if( 'isVisible', 'none', visible => !visible ) | ||
} | ||
}, | ||
children: [ { | ||
text: bind.to( 'label' ) | ||
} ] | ||
} ); | ||
} | ||
bindToState( options, resizerState ) { | ||
this.bind( 'isVisible' ).to( resizerState, 'proposedWidth', resizerState, 'proposedHeight', ( width, height ) => | ||
width !== null && height !== null ); | ||
this.bind( 'label' ).to( | ||
resizerState, 'proposedHandleHostWidth', | ||
resizerState, 'proposedHandleHostHeight', | ||
resizerState, 'proposedWidthPercents', | ||
( width, height, widthPercents ) => { | ||
if ( options.unit === 'px' ) { | ||
return `${ width }×${ height }`; | ||
} else { | ||
return `${ widthPercents }%`; | ||
} | ||
} | ||
); | ||
this.bind( 'activeHandlePosition' ).to( resizerState ); | ||
} | ||
dismiss() { | ||
this.unbind(); | ||
this.isVisible = false; | ||
} | ||
} | ||
// @private | ||
@@ -542,0 +484,0 @@ // @param {String} resizerPosition Expected resizer position like `"top-left"`, `"bottom-right"`. |
@@ -39,3 +39,3 @@ /** | ||
* items: editor.config.get( 'image.toolbar' ), | ||
* getRelatedElement: getSelectedImageWidget | ||
* getRelatedElement: getClosestSelectedImageWidget | ||
* } ); | ||
@@ -42,0 +42,0 @@ * } |
Sorry, the diff of this file is not supported yet
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
203944
60
3377
+ Added@ckeditor/ckeditor5-clipboard@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-core@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-engine@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-enter@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-paragraph@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-select-all@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-typing@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-ui@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-undo@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-upload@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-utils@29.2.0(transitive)
+ Added@ckeditor/ckeditor5-widget@29.2.0(transitive)
+ Addedckeditor5@29.2.0(transitive)
- Removed@ckeditor/ckeditor5-clipboard@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-core@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-engine@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-enter@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-paragraph@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-select-all@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-typing@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-ui@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-undo@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-upload@28.0.0(transitive)
- Removed@ckeditor/ckeditor5-utils@28.0.0(transitive)
- Removedckeditor5@28.0.0(transitive)