@wordpress/block-editor
Version:
144 lines (142 loc) • 5.99 kB
JavaScript
export function range(start, length) {
return Array.from({
length
}, (_, i) => start + i);
}
export class GridRect {
constructor({
columnStart,
rowStart,
columnEnd,
rowEnd,
columnSpan,
rowSpan
} = {}) {
this.columnStart = columnStart !== null && columnStart !== void 0 ? columnStart : 1;
this.rowStart = rowStart !== null && rowStart !== void 0 ? rowStart : 1;
if (columnSpan !== undefined) {
this.columnEnd = this.columnStart + columnSpan - 1;
} else {
this.columnEnd = columnEnd !== null && columnEnd !== void 0 ? columnEnd : this.columnStart;
}
if (rowSpan !== undefined) {
this.rowEnd = this.rowStart + rowSpan - 1;
} else {
this.rowEnd = rowEnd !== null && rowEnd !== void 0 ? rowEnd : this.rowStart;
}
}
get columnSpan() {
return this.columnEnd - this.columnStart + 1;
}
get rowSpan() {
return this.rowEnd - this.rowStart + 1;
}
contains(column, row) {
return column >= this.columnStart && column <= this.columnEnd && row >= this.rowStart && row <= this.rowEnd;
}
containsRect(rect) {
return this.contains(rect.columnStart, rect.rowStart) && this.contains(rect.columnEnd, rect.rowEnd);
}
intersectsRect(rect) {
return this.columnStart <= rect.columnEnd && this.columnEnd >= rect.columnStart && this.rowStart <= rect.rowEnd && this.rowEnd >= rect.rowStart;
}
}
export function getComputedCSS(element, property) {
return element.ownerDocument.defaultView.getComputedStyle(element).getPropertyValue(property);
}
/**
* Given a grid-template-columns or grid-template-rows CSS property value, gets the start and end
* position in pixels of each grid track.
*
* https://css-tricks.com/snippets/css/complete-guide-grid/#aa-grid-track
*
* @param {string} template The grid-template-columns or grid-template-rows CSS property value.
* Only supports fixed sizes in pixels.
* @param {number} gap The gap between grid tracks in pixels.
*
* @return {Array<{start: number, end: number}>} An array of objects with the start and end
* position in pixels of each grid track.
*/
export function getGridTracks(template, gap) {
const tracks = [];
for (const size of template.split(' ')) {
const previousTrack = tracks[tracks.length - 1];
const start = previousTrack ? previousTrack.end + gap : 0;
const end = start + parseFloat(size);
tracks.push({
start,
end
});
}
return tracks;
}
/**
* Given an array of grid tracks and a position in pixels, gets the index of the closest track to
* that position.
*
* https://css-tricks.com/snippets/css/complete-guide-grid/#aa-grid-track
*
* @param {Array<{start: number, end: number}>} tracks An array of objects with the start and end
* position in pixels of each grid track.
* @param {number} position The position in pixels.
* @param {string} edge The edge of the track to compare the
* position to. Either 'start' or 'end'.
*
* @return {number} The index of the closest track to the position. 0-based, unlike CSS grid which
* is 1-based.
*/
export function getClosestTrack(tracks, position, edge = 'start') {
return tracks.reduce((closest, track, index) => Math.abs(track[edge] - position) < Math.abs(tracks[closest][edge] - position) ? index : closest, 0);
}
export function getGridRect(gridElement, rect) {
const columnGap = parseFloat(getComputedCSS(gridElement, 'column-gap'));
const rowGap = parseFloat(getComputedCSS(gridElement, 'row-gap'));
const gridColumnTracks = getGridTracks(getComputedCSS(gridElement, 'grid-template-columns'), columnGap);
const gridRowTracks = getGridTracks(getComputedCSS(gridElement, 'grid-template-rows'), rowGap);
const columnStart = getClosestTrack(gridColumnTracks, rect.left) + 1;
const rowStart = getClosestTrack(gridRowTracks, rect.top) + 1;
const columnEnd = getClosestTrack(gridColumnTracks, rect.right, 'end') + 1;
const rowEnd = getClosestTrack(gridRowTracks, rect.bottom, 'end') + 1;
return new GridRect({
columnStart,
columnEnd,
rowStart,
rowEnd
});
}
export function getGridItemRect(gridItemElement) {
return getGridRect(gridItemElement.parentElement, new window.DOMRect(gridItemElement.offsetLeft, gridItemElement.offsetTop, gridItemElement.offsetWidth, gridItemElement.offsetHeight));
}
export function getGridInfo(gridElement) {
const gridTemplateColumns = getComputedCSS(gridElement, 'grid-template-columns');
const gridTemplateRows = getComputedCSS(gridElement, 'grid-template-rows');
const borderTopWidth = getComputedCSS(gridElement, 'border-top-width');
const borderRightWidth = getComputedCSS(gridElement, 'border-right-width');
const borderBottomWidth = getComputedCSS(gridElement, 'border-bottom-width');
const borderLeftWidth = getComputedCSS(gridElement, 'border-left-width');
const paddingTop = getComputedCSS(gridElement, 'padding-top');
const paddingRight = getComputedCSS(gridElement, 'padding-right');
const paddingBottom = getComputedCSS(gridElement, 'padding-bottom');
const paddingLeft = getComputedCSS(gridElement, 'padding-left');
const numColumns = gridTemplateColumns.split(' ').length;
const numRows = gridTemplateRows.split(' ').length;
const numItems = numColumns * numRows;
return {
numColumns,
numRows,
numItems,
currentColor: getComputedCSS(gridElement, 'color'),
style: {
gridTemplateColumns,
gridTemplateRows,
gap: getComputedCSS(gridElement, 'gap'),
inset: `
calc(${paddingTop} + ${borderTopWidth})
calc(${paddingRight} + ${borderRightWidth})
calc(${paddingBottom} + ${borderBottomWidth})
calc(${paddingLeft} + ${borderLeftWidth})
`
}
};
}
//# sourceMappingURL=utils.js.map