@ckeditor/ckeditor5-utils
Advanced tools
Comparing version 29.2.0 to 30.0.0
{ | ||
"name": "@ckeditor/ckeditor5-utils", | ||
"version": "29.2.0", | ||
"version": "30.0.0", | ||
"description": "Miscellaneous utilities used by CKEditor 5.", | ||
@@ -17,6 +17,6 @@ "keywords": [ | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-build-classic": "^29.2.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^29.2.0", | ||
"@ckeditor/ckeditor5-core": "^29.2.0", | ||
"@ckeditor/ckeditor5-engine": "^29.2.0", | ||
"@ckeditor/ckeditor5-build-classic": "^30.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^30.0.0", | ||
"@ckeditor/ckeditor5-core": "^30.0.0", | ||
"@ckeditor/ckeditor5-engine": "^30.0.0", | ||
"assertion-error": "^1.1.0", | ||
@@ -23,0 +23,0 @@ "js-beautify": "^1.11.0" |
@@ -88,2 +88,3 @@ /** | ||
* Checks if the error is of the `CKEditorError` type. | ||
* @returns {Boolean} | ||
*/ | ||
@@ -146,3 +147,2 @@ is( type ) { | ||
* @param {Object} [data] Additional data to be logged. | ||
* @returns {String} | ||
*/ | ||
@@ -172,3 +172,2 @@ export function logWarning( errorName, data ) { | ||
* @param {Object} [data] Additional data to be logged. | ||
* @returns {String} | ||
*/ | ||
@@ -175,0 +174,0 @@ export function logError( errorName, data ) { |
@@ -59,3 +59,3 @@ /** | ||
* | ||
* @param {Iterable.<Object>|Object} initialItemsOrOptions The initial items of the collection or | ||
* @param {Iterable.<Object>|Object} [initialItemsOrOptions] The initial items of the collection or | ||
* the options object. | ||
@@ -62,0 +62,0 @@ * @param {Object} [options={}] The options object, when the first argument is an array of initial items. |
@@ -16,2 +16,4 @@ /** | ||
// @if CK_DEBUG_POSITION // import { RectDrawer } from '@ckeditor/ckeditor5-minimap/src/utils'; | ||
/** | ||
@@ -78,6 +80,6 @@ * Calculates the `position: absolute` coordinates of a given element so it can be positioned with respect to the | ||
* | ||
* @param {module:utils/dom/position~Options} options Positioning options object. | ||
* @param {module:utils/dom/position~Options} options The input data and configuration of the helper. | ||
* @returns {module:utils/dom/position~Position} | ||
*/ | ||
export function getOptimalPosition( { element, target, positions, limiter, fitInViewport } ) { | ||
export function getOptimalPosition( { element, target, positions, limiter, fitInViewport, viewportOffsetConfig } ) { | ||
// If the {@link module:utils/dom/position~Options#target} is a function, use what it returns. | ||
@@ -99,48 +101,50 @@ // https://github.com/ckeditor/ckeditor5-utils/issues/157 | ||
let bestPositionRect; | ||
let bestPositionName; | ||
let bestPosition; | ||
// @if CK_DEBUG_POSITION // RectDrawer.clear(); | ||
// @if CK_DEBUG_POSITION // RectDrawer.draw( targetRect, { outlineWidth: '5px' }, 'Target' ); | ||
const positionOptions = { targetRect, elementRect, positionedElementAncestor }; | ||
// If there are no limits, just grab the very first position and be done with that drama. | ||
if ( !limiter && !fitInViewport ) { | ||
[ bestPositionName, bestPositionRect ] = getPositionNameAndRect( positions[ 0 ], targetRect, elementRect ); | ||
bestPosition = new Position( positions[ 0 ], positionOptions ); | ||
} else { | ||
const limiterRect = limiter && new Rect( limiter ).getVisible(); | ||
const viewportRect = fitInViewport && new Rect( global.window ); | ||
const bestPosition = getBestPositionNameAndRect( positions, { targetRect, elementRect, limiterRect, viewportRect } ); | ||
const viewportRect = fitInViewport && getConstrainedViewportRect( viewportOffsetConfig ); | ||
// @if CK_DEBUG_POSITION // if ( viewportRect ) { | ||
// @if CK_DEBUG_POSITION // RectDrawer.draw( viewportRect, { outlineWidth: '5px' }, 'Viewport' ); | ||
// @if CK_DEBUG_POSITION // } | ||
// @if CK_DEBUG_POSITION // if ( limiter ) { | ||
// @if CK_DEBUG_POSITION // RectDrawer.draw( limiterRect, { outlineWidth: '5px', outlineColor: 'green' }, 'Visible limiter' ); | ||
// @if CK_DEBUG_POSITION // } | ||
Object.assign( positionOptions, { limiterRect, viewportRect } ); | ||
// If there's no best position found, i.e. when all intersections have no area because | ||
// rects have no width or height, then just use the first available position. | ||
[ bestPositionName, bestPositionRect ] = bestPosition || getPositionNameAndRect( positions[ 0 ], targetRect, elementRect ); | ||
bestPosition = getBestPosition( positions, positionOptions ) || new Position( positions[ 0 ], positionOptions ); | ||
} | ||
let absoluteRectCoordinates = getAbsoluteRectCoordinates( bestPositionRect ); | ||
if ( positionedElementAncestor ) { | ||
absoluteRectCoordinates = shiftRectCoordinatesDueToPositionedAncestor( absoluteRectCoordinates, positionedElementAncestor ); | ||
} | ||
return { | ||
left: absoluteRectCoordinates.left, | ||
top: absoluteRectCoordinates.top, | ||
name: bestPositionName | ||
}; | ||
return bestPosition; | ||
} | ||
// For given position function, returns a corresponding `Rect` instance. | ||
// Returns a viewport `Rect` shrunk by the viewport offset config from all sides. | ||
// | ||
// @private | ||
// @param {Function} position A function returning {@link module:utils/dom/position~Position}. | ||
// @param {utils/dom/rect~Rect} targetRect A rect of the target. | ||
// @param {utils/dom/rect~Rect} elementRect A rect of positioned element. | ||
// @returns {Array|null} An array containing position name and its Rect (or null if position should be ignored). | ||
function getPositionNameAndRect( position, targetRect, elementRect ) { | ||
const positionData = position( targetRect, elementRect ); | ||
// @param {Object} An object containing viewportOffset config. | ||
// @returns {utils/dom/rect~Rect} A shrunken rect of the viewport. | ||
function getConstrainedViewportRect( viewportOffsetConfig ) { | ||
viewportOffsetConfig = Object.assign( { top: 0, bottom: 0, left: 0, right: 0 }, viewportOffsetConfig ); | ||
if ( !positionData ) { | ||
return null; | ||
} | ||
const viewportRect = new Rect( global.window ); | ||
const { left, top, name } = positionData; | ||
viewportRect.top += viewportOffsetConfig.top; | ||
viewportRect.height -= viewportOffsetConfig.top; | ||
viewportRect.bottom -= viewportOffsetConfig.bottom; | ||
viewportRect.height -= viewportOffsetConfig.bottom; | ||
return [ name, elementRect.clone().moveTo( left, top ) ]; | ||
return viewportRect; | ||
} | ||
@@ -154,13 +158,14 @@ | ||
// @param {Object} options | ||
// @param {module:utils/dom/position~Options#positions} positions Functions returning {@link module:utils/dom/position~Position} | ||
// to be checked, in the order of preference. | ||
// @param {module:utils/dom/position~Options#positions} positions Functions returning | ||
// {@link module:utils/dom/position~Position}to be checked, in the order of preference. | ||
// @param {Object} options | ||
// @param {utils/dom/rect~Rect} options.targetRect A rect of the {@link module:utils/dom/position~Options#target}. | ||
// @param {utils/dom/rect~Rect} options.elementRect A rect of positioned {@link module:utils/dom/position~Options#element}. | ||
// @param {utils/dom/rect~Rect} options.elementRect A rect of positioned | ||
// {@link module:utils/dom/position~Options#element}. | ||
// @param {utils/dom/rect~Rect} options.limiterRect A rect of the {@link module:utils/dom/position~Options#limiter}. | ||
// @param {utils/dom/rect~Rect} options.viewportRect A rect of the viewport. | ||
// @param {utils/dom/rect~Rect} options.viewportRect A rect of the {@link module:utils/dom/position~Options#viewport}. | ||
// | ||
// @returns {Array} An array containing the name of the position and it's rect. | ||
function getBestPositionNameAndRect( positions, options ) { | ||
const { elementRect, viewportRect } = options; | ||
function getBestPosition( positions, options ) { | ||
const { elementRect } = options; | ||
@@ -170,138 +175,30 @@ // This is when element is fully visible. | ||
// Let's calculate intersection areas for positions. It will end early if best match is found. | ||
const processedPositions = processPositionsToAreas( positions, options ); | ||
const positionInstances = positions | ||
.map( positioningFunction => new Position( positioningFunction, options ) ) | ||
// Some positioning functions may return `null` if they don't want to participate. | ||
.filter( position => !!position.name ); | ||
// First let's check all positions that fully fit in the viewport. | ||
if ( viewportRect ) { | ||
const processedPositionsInViewport = processedPositions.filter( ( { viewportIntersectArea } ) => { | ||
return viewportIntersectArea === elementRectArea; | ||
} ); | ||
let maxFitFactor = 0; | ||
let bestPosition = null; | ||
// Try to find best position from those which fit completely in viewport. | ||
const bestPositionData = getBestOfProcessedPositions( processedPositionsInViewport, elementRectArea ); | ||
for ( const position of positionInstances ) { | ||
const { _limiterIntersectionArea, _viewportIntersectionArea } = position; | ||
if ( bestPositionData ) { | ||
return bestPositionData; | ||
} | ||
} | ||
// Either there is no viewportRect or there is no position that fits completely in the viewport. | ||
return getBestOfProcessedPositions( processedPositions, elementRectArea ); | ||
} | ||
// For a given array of positioning functions, calculates intersection areas for them. | ||
// | ||
// Note: If some position fully fits into the `limiterRect`, it will be returned early, without further consideration | ||
// of other positions. | ||
// | ||
// @private | ||
// | ||
// @param {module:utils/dom/position~Options#positions} positions Functions returning {@link module:utils/dom/position~Position} | ||
// to be checked, in the order of preference. | ||
// @param {Object} options | ||
// @param {utils/dom/rect~Rect} options.targetRect A rect of the {@link module:utils/dom/position~Options#target}. | ||
// @param {utils/dom/rect~Rect} options.elementRect A rect of positioned {@link module:utils/dom/position~Options#element}. | ||
// @param {utils/dom/rect~Rect} options.limiterRect A rect of the {@link module:utils/dom/position~Options#limiter}. | ||
// @param {utils/dom/rect~Rect} options.viewportRect A rect of the viewport. | ||
// | ||
// @returns {Array.<Object>} Array of positions with calculated intersection areas. Each item is an object containing: | ||
// * {String} positionName Name of position. | ||
// * {utils/dom/rect~Rect} positionRect Rect of position. | ||
// * {Number} limiterIntersectArea Area of intersection of the position with limiter part that is in the viewport. | ||
// * {Number} viewportIntersectArea Area of intersection of the position with viewport. | ||
function processPositionsToAreas( positions, { targetRect, elementRect, limiterRect, viewportRect } ) { | ||
const processedPositions = []; | ||
// This is when element is fully visible. | ||
const elementRectArea = elementRect.getArea(); | ||
for ( const position of positions ) { | ||
const positionData = getPositionNameAndRect( position, targetRect, elementRect ); | ||
if ( !positionData ) { | ||
continue; | ||
} | ||
const [ positionName, positionRect ] = positionData; | ||
let limiterIntersectArea = 0; | ||
let viewportIntersectArea = 0; | ||
if ( limiterRect ) { | ||
if ( viewportRect ) { | ||
// Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited. | ||
const limiterViewportIntersectRect = limiterRect.getIntersection( viewportRect ); | ||
if ( limiterViewportIntersectRect ) { | ||
// If the limiter is within the viewport, then check the intersection between that part of the | ||
// limiter and actual position. | ||
limiterIntersectArea = limiterViewportIntersectRect.getIntersectionArea( positionRect ); | ||
} | ||
} else { | ||
limiterIntersectArea = limiterRect.getIntersectionArea( positionRect ); | ||
} | ||
} | ||
if ( viewportRect ) { | ||
viewportIntersectArea = viewportRect.getIntersectionArea( positionRect ); | ||
} | ||
const processedPosition = { | ||
positionName, | ||
positionRect, | ||
limiterIntersectArea, | ||
viewportIntersectArea | ||
}; | ||
// If a such position is found that element is fully contained by the limiter then, obviously, | ||
// there will be no better one, so finishing. | ||
if ( limiterIntersectArea === elementRectArea ) { | ||
return [ processedPosition ]; | ||
if ( _limiterIntersectionArea === elementRectArea ) { | ||
return position; | ||
} | ||
processedPositions.push( processedPosition ); | ||
} | ||
// To maximize both viewport and limiter intersection areas we use distance on _viewportIntersectionArea | ||
// and _limiterIntersectionArea plane (without sqrt because we are looking for max value). | ||
const fitFactor = _viewportIntersectionArea ** 2 + _limiterIntersectionArea ** 2; | ||
return processedPositions; | ||
} | ||
// For a given array of processed position data (with calculated Rects for positions and intersection areas) | ||
// returns such that provides the best fit of the `elementRect` into the `limiterRect` and `viewportRect` at the same time. | ||
// | ||
// **Note**: It will return early if some position fully fits into the `limiterRect`. | ||
// | ||
// @private | ||
// @param {Array.<Object>} Array of positions with calculated intersection areas (in order of preference). | ||
// Each item is an object containing: | ||
// | ||
// * {String} positionName Name of position. | ||
// * {utils/dom/rect~Rect} positionRect Rect of position. | ||
// * {Number} limiterIntersectArea Area of intersection of the position with limiter part that is in the viewport. | ||
// * {Number} viewportIntersectArea Area of intersection of the position with viewport. | ||
// | ||
// @param {Number} elementRectArea Area of positioned {@link module:utils/dom/position~Options#element}. | ||
// @returns {Array|null} An array containing the name of the position and it's rect, or null if not found. | ||
function getBestOfProcessedPositions( processedPositions, elementRectArea ) { | ||
let maxFitFactor = 0; | ||
let bestPositionRect; | ||
let bestPositionName; | ||
for ( const { positionName, positionRect, limiterIntersectArea, viewportIntersectArea } of processedPositions ) { | ||
// If a such position is found that element is fully container by the limiter then, obviously, | ||
// there will be no better one, so finishing. | ||
if ( limiterIntersectArea === elementRectArea ) { | ||
return [ positionName, positionRect ]; | ||
} | ||
// To maximize both viewport and limiter intersection areas we use distance on viewportIntersectArea | ||
// and limiterIntersectArea plane (without sqrt because we are looking for max value). | ||
const fitFactor = viewportIntersectArea ** 2 + limiterIntersectArea ** 2; | ||
if ( fitFactor > maxFitFactor ) { | ||
maxFitFactor = fitFactor; | ||
bestPositionRect = positionRect; | ||
bestPositionName = positionName; | ||
bestPosition = position; | ||
} | ||
} | ||
return bestPositionRect ? [ bestPositionName, bestPositionRect ] : null; | ||
return bestPosition; | ||
} | ||
@@ -318,13 +215,16 @@ | ||
// | ||
// @param {Object} absoluteRectCoordinates An object with absolute rect coordinates. | ||
// @param {Object} absoluteRectCoordinates.top | ||
// @param {Object} absoluteRectCoordinates.left | ||
// @param {utils/dom/rect~Rect} rect A rect with absolute rect coordinates. | ||
// @param {Number} rect.top | ||
// @param {Number} rect.left | ||
// @param {HTMLElement} positionedElementAncestor An ancestor element that should be considered. | ||
// | ||
// @returns {Object} An object corresponding to `absoluteRectCoordinates` input but with values shifted | ||
// @returns {utils/dom/rect~Rect} A rect corresponding to `absoluteRect` input but with values shifted | ||
// to make up for the positioned element ancestor. | ||
function shiftRectCoordinatesDueToPositionedAncestor( { left, top }, positionedElementAncestor ) { | ||
const ancestorPosition = getAbsoluteRectCoordinates( new Rect( positionedElementAncestor ) ); | ||
function shiftRectToCompensatePositionedAncestor( rect, positionedElementAncestor ) { | ||
const ancestorPosition = getRectForAbsolutePositioning( new Rect( positionedElementAncestor ) ); | ||
const ancestorBorderWidths = getBorderWidths( positionedElementAncestor ); | ||
let moveX = 0; | ||
let moveY = 0; | ||
// (https://github.com/ckeditor/ckeditor5-ui-default/issues/126) | ||
@@ -334,4 +234,4 @@ // If there's some positioned ancestor of the panel, then its `Rect` must be taken into | ||
// with respect to that positioned ancestor. | ||
left -= ancestorPosition.left; | ||
top -= ancestorPosition.top; | ||
moveX -= ancestorPosition.left; | ||
moveY -= ancestorPosition.top; | ||
@@ -343,4 +243,4 @@ // (https://github.com/ckeditor/ckeditor5-utils/issues/139) | ||
// must compensate that scrolling. | ||
left += positionedElementAncestor.scrollLeft; | ||
top += positionedElementAncestor.scrollTop; | ||
moveX += positionedElementAncestor.scrollLeft; | ||
moveY += positionedElementAncestor.scrollTop; | ||
@@ -352,6 +252,6 @@ // (https://github.com/ckeditor/ckeditor5-utils/issues/139) | ||
// not upper-left corner of its border. | ||
left -= ancestorBorderWidths.left; | ||
top -= ancestorBorderWidths.top; | ||
moveX -= ancestorBorderWidths.left; | ||
moveY -= ancestorBorderWidths.top; | ||
return { left, top }; | ||
rect.moveBy( moveX, moveY ); | ||
} | ||
@@ -365,12 +265,171 @@ | ||
// @returns {Object} Object containing `left` and `top` properties, in absolute coordinates. | ||
function getAbsoluteRectCoordinates( { left, top } ) { | ||
function getRectForAbsolutePositioning( rect ) { | ||
const { scrollX, scrollY } = global.window; | ||
return { | ||
left: left + scrollX, | ||
top: top + scrollY | ||
}; | ||
return rect.clone().moveBy( scrollX, scrollY ); | ||
} | ||
/** | ||
* A position class which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper. | ||
* | ||
* {@link module:utils/dom/position~Position#top} and {@link module:utils/dom/position~Position#left} properties of the position instance | ||
* translate directly to the `top` and `left` properties in CSS "`position: absolute` coordinate system". If set on the positioned element | ||
* in DOM, they will make it display it in the right place in the viewport. | ||
*/ | ||
export class Position { | ||
/** | ||
* Creates an instance of the {@link module:utils/dom/position~Position} class. | ||
* | ||
* @param {module:utils/dom/position~positioningFunction} [positioningFunction] function The function that defines the expected | ||
* coordinates the positioned element should move to. | ||
* @param {Object} [options] options object. | ||
* @param {module:utils/dom/rect~Rect} options.elementRect The positioned element rect. | ||
* @param {module:utils/dom/rect~Rect} options.targetRect The target element rect. | ||
* @param {module:utils/dom/rect~Rect} options.viewportRect The viewport rect. | ||
* @param {HTMLElement|null} [options.positionedElementAncestor] Nearest element ancestor element which CSS position is not "static". | ||
*/ | ||
constructor( positioningFunction, options ) { | ||
const positioningFunctionOutput = positioningFunction( options.targetRect, options.elementRect, options.viewportRect ); | ||
// Nameless position for a function that didn't participate. | ||
if ( !positioningFunctionOutput ) { | ||
return; | ||
} | ||
const { left, top, name, config } = positioningFunctionOutput; | ||
Object.assign( this, { name, config } ); | ||
this._positioningFunctionCorrdinates = { left, top }; | ||
this._options = options; | ||
/** | ||
* Position name. | ||
* | ||
* @readonly | ||
* @member {String} #name | ||
*/ | ||
/** | ||
* Additional position configuration, as passed from the {@link module:utils/dom/position~positioningFunction positioning function}. | ||
* | ||
* This object can be use, for instance, to pass through presentation options used by the consumer of the | ||
* {@link module:utils/dom/position~getOptimalPosition} helper. | ||
* | ||
* @readonly | ||
* @member {Object} #config | ||
*/ | ||
} | ||
/** | ||
* The left value in pixels in the CSS `position: absolute` coordinate system. | ||
* Set it on the positioned element in DOM to move it to the position. | ||
* | ||
* @readonly | ||
* @type {Number} | ||
*/ | ||
get left() { | ||
return this._absoluteRect.left; | ||
} | ||
/** | ||
* The top value in pixels in the CSS `position: absolute` coordinate system. | ||
* Set it on the positioned element in DOM to move it to the position. | ||
* | ||
* @readonly | ||
* @type {Number} | ||
*/ | ||
get top() { | ||
return this._absoluteRect.top; | ||
} | ||
/** | ||
* An intersection area between positioned element and limiter within viewport constraints. | ||
* | ||
* @readonly | ||
* @private | ||
* @type {Number} | ||
*/ | ||
get _limiterIntersectionArea() { | ||
const limiterRect = this._options.limiterRect; | ||
if ( limiterRect ) { | ||
const viewportRect = this._options.viewportRect; | ||
if ( viewportRect ) { | ||
// Consider only the part of the limiter which is visible in the viewport. So the limiter is getting limited. | ||
const limiterViewportIntersectRect = limiterRect.getIntersection( viewportRect ); | ||
if ( limiterViewportIntersectRect ) { | ||
// If the limiter is within the viewport, then check the intersection between that part of the | ||
// limiter and actual position. | ||
return limiterViewportIntersectRect.getIntersectionArea( this._rect ); | ||
} | ||
} else { | ||
return limiterRect.getIntersectionArea( this._rect ); | ||
} | ||
} | ||
return 0; | ||
} | ||
/** | ||
* An intersection area between positioned element and viewport. | ||
* | ||
* @readonly | ||
* @private | ||
* @type {Number} | ||
*/ | ||
get _viewportIntersectionArea() { | ||
const viewportRect = this._options.viewportRect; | ||
if ( viewportRect ) { | ||
return viewportRect.getIntersectionArea( this._rect ); | ||
} | ||
return 0; | ||
} | ||
/** | ||
* An already positioned element rect. A clone of the element rect passed to the constructor | ||
* but placed in the viewport according to the positioning function. | ||
* | ||
* @private | ||
* @type {module:utils/dom/rect~Rect} | ||
*/ | ||
get _rect() { | ||
if ( this._cachedRect ) { | ||
return this._cachedRect; | ||
} | ||
this._cachedRect = this._options.elementRect.clone().moveTo( | ||
this._positioningFunctionCorrdinates.left, | ||
this._positioningFunctionCorrdinates.top | ||
); | ||
return this._cachedRect; | ||
} | ||
/** | ||
* An already absolutely positioned element rect. See ({@link #_rect}). | ||
* | ||
* @private | ||
* @type {module:utils/dom/rect~Rect} | ||
*/ | ||
get _absoluteRect() { | ||
if ( this._cachedAbsoluteRect ) { | ||
return this._cachedAbsoluteRect; | ||
} | ||
this._cachedAbsoluteRect = getRectForAbsolutePositioning( this._rect ); | ||
if ( this._options.positionedElementAncestor ) { | ||
shiftRectToCompensatePositionedAncestor( this._cachedAbsoluteRect, this._options.positionedElementAncestor ); | ||
} | ||
return this._cachedAbsoluteRect; | ||
} | ||
} | ||
/** | ||
* The `getOptimalPosition()` helper options. | ||
@@ -394,8 +453,11 @@ * | ||
/** | ||
* An array of functions which return {@link module:utils/dom/position~Position} relative | ||
* to the `target`, in the order of preference. | ||
* An array of positioning functions. | ||
* | ||
* **Note**: If a function returns `null`, it is ignored by the `getOptimalPosition()`. | ||
* **Note**: Positioning functions are processed in the order of preference. The first function that works | ||
* in the current environment (e.g. offers the complete fit in the viewport geometry) will be picked by | ||
* `getOptimalPosition()`. | ||
* | ||
* @member {Array.<Function>} #positions | ||
* **Note**: Any positioning function returning `null` is ignored. | ||
* | ||
* @member {Array.<module:utils/dom/position~positioningFunction>} #positions | ||
*/ | ||
@@ -418,10 +480,51 @@ | ||
/** | ||
* An object describing a position in `position: absolute` coordinate | ||
* system, along with position name. | ||
* Viewport offset config object. It restricts the visible viewport available to the `getOptimalPosition()` from each side. | ||
* | ||
* @typedef {Object} module:utils/dom/position~Position | ||
* { | ||
* top: 50, | ||
* right: 50, | ||
* bottom: 50, | ||
* left: 50 | ||
* } | ||
* | ||
* @property {Number} top Top position offset. | ||
* @property {Number} left Left position offset. | ||
* @property {String} name Name of the position. | ||
* @member {Object} #viewportOffsetConfig | ||
*/ | ||
/** | ||
* A positioning function which, based on positioned element and target {@link module:utils/dom/rect~Rect Rects}, returns rect coordinates | ||
* representing the geometrical relation between them. Used by the {@link module:utils/dom/position~getOptimalPosition} helper. | ||
* | ||
* // This simple position will place the element directly under the target, in the middle: | ||
* // | ||
* // [ Target ] | ||
* // +-----------------+ | ||
* // | Element | | ||
* // +-----------------+ | ||
* // | ||
* const position = ( targetRect, elementRect, [ viewportRect ] ) => ( { | ||
* top: targetRect.bottom, | ||
* left: targetRect.left + targetRect.width / 2 - elementRect.width / 2, | ||
* name: 'bottomMiddle', | ||
* | ||
* // Note: The config is optional. | ||
* config: { | ||
* zIndex: '999' | ||
* } | ||
* } ); | ||
* | ||
* @callback module:utils/dom/position~positioningFunction | ||
* @param {module:utils/dom/rect~Rect} elementRect The rect of the element to be positioned. | ||
* @param {module:utils/dom/rect~Rect} targetRect The rect of the target the element (its rect) is relatively positioned to. | ||
* @param {module:utils/dom/rect~Rect} viewportRect The rect of the visual browser viewport. | ||
* @returns {Object|null} return When the function returns `null`, it will not be considered by | ||
* {@link module:utils/dom/position~getOptimalPosition}. | ||
* @returns {Number} return.top The `top` value of the element rect that would represent the position. | ||
* @returns {Number} return.left The `left` value of the element rect that would represent the position. | ||
* @returns {Number} return.name The name of the position. It helps the user of the {@link module:utils/dom/position~getOptimalPosition} | ||
* helper to recognize different positioning function results. It will pass through to the {@link module:utils/dom/position~Position} | ||
* returned by the helper. | ||
* @returns {Number} [return.config] An optional configuration that will pass-through the | ||
* {@link module:utils/dom/position~getOptimalPosition} helper to the {@link module:utils/dom/position~Position} returned by this helper. | ||
* This configuration may, for instance, let the user of {@link module:utils/dom/position~getOptimalPosition} know that this particular | ||
* position comes with a certain presentation. | ||
*/ |
@@ -36,2 +36,3 @@ /** | ||
* * `f1-f12`, | ||
* * `` ` ``, `-`, `=`, `[`, `]`, `;`, `'`, `,`, `.`, `/`, `\`, | ||
* * `arrow(left|up|right|bottom)`, | ||
@@ -255,2 +256,7 @@ * * `backspace`, `delete`, `enter`, `esc`, `tab`, | ||
// other characters | ||
for ( const char of '`-=[];\',./\\' ) { | ||
keyCodes[ char ] = char.charCodeAt( 0 ); | ||
} | ||
return keyCodes; | ||
@@ -257,0 +263,0 @@ } |
@@ -134,3 +134,3 @@ /** | ||
* @param {String} language Target language. | ||
* @param {module:utils/translation-service~Message|String} message A message that will be translated. | ||
* @param {module:utils/translation-service~Message} message A message that will be translated. | ||
* @param {Number} [quantity] The number of elements for which a plural form should be picked from the target language dictionary. | ||
@@ -137,0 +137,0 @@ * @returns {String} Translated sentence. |
@@ -14,3 +14,3 @@ /** | ||
const version = '29.2.0'; | ||
const version = '30.0.0'; | ||
@@ -17,0 +17,0 @@ export default version; |
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
6837
257640
58