72 lines
2.2 KiB
JavaScript
72 lines
2.2 KiB
JavaScript
export const HOVER_OUTLINE_CLASS = 'inline-editor-hover-outline';
|
|
export const LOCKED_OUTLINE_CLASS = 'inline-editor-locked-outline';
|
|
|
|
/** @param {HTMLElement|HTMLElement[]|null} value @returns {HTMLElement[]} */
|
|
function toArray(value) {
|
|
if (!value) return [];
|
|
return Array.isArray(value) ? value.filter(Boolean) : [value];
|
|
}
|
|
|
|
/** @param {HTMLElement[]} elements @param {string} className */
|
|
function addClassTo(elements, className) {
|
|
for (const element of elements) element.classList.add(className);
|
|
}
|
|
|
|
/** @param {HTMLElement[]} elements @param {string} className */
|
|
function removeClassFrom(elements, className) {
|
|
for (const element of elements) element.classList.remove(className);
|
|
}
|
|
|
|
/** @type {HTMLElement[]} */
|
|
let _hoveredElements = [];
|
|
/** @type {HTMLElement[]} */
|
|
let _lockedElements = [];
|
|
let _holdCount = 0;
|
|
|
|
/**
|
|
* Dashed outline for the transient hover. Elements already carrying a locked
|
|
* outline are skipped so they aren't outlined twice.
|
|
* @param {HTMLElement|HTMLElement[]} elements
|
|
*/
|
|
export function showHoverOutline(elements) {
|
|
const targets = toArray(elements).filter(element => !_lockedElements.includes(element));
|
|
if (!targets.length) return;
|
|
removeClassFrom(_hoveredElements, HOVER_OUTLINE_CLASS);
|
|
_hoveredElements = targets;
|
|
addClassTo(_hoveredElements, HOVER_OUTLINE_CLASS);
|
|
}
|
|
|
|
/** Hides the hover outline (no-op while held). */
|
|
export function hideHoverOutline() {
|
|
if (_holdCount > 0) return;
|
|
removeClassFrom(_hoveredElements, HOVER_OUTLINE_CLASS);
|
|
_hoveredElements = [];
|
|
}
|
|
|
|
export function holdHoverOutline() { _holdCount++; }
|
|
export function releaseHoverOutline() {
|
|
_holdCount = Math.max(0, _holdCount - 1);
|
|
if (_holdCount === 0) hideHoverOutline();
|
|
}
|
|
|
|
/**
|
|
* Solid outline for a committed selection — a drag preview, a shift+click
|
|
* group, or the element(s) an open annotation panel targets.
|
|
* @param {HTMLElement|HTMLElement[]} elements
|
|
*/
|
|
export function lockHoverOutline(elements) {
|
|
const targets = toArray(elements);
|
|
if (!targets.length) {
|
|
unlockHoverOutline();
|
|
return;
|
|
}
|
|
removeClassFrom(_lockedElements, LOCKED_OUTLINE_CLASS);
|
|
_lockedElements = targets;
|
|
addClassTo(_lockedElements, LOCKED_OUTLINE_CLASS);
|
|
}
|
|
|
|
export function unlockHoverOutline() {
|
|
removeClassFrom(_lockedElements, LOCKED_OUTLINE_CLASS);
|
|
_lockedElements = [];
|
|
}
|