feat: add tooltip core (#212)

This commit is contained in:
Wesley Luyten
2025-12-05 20:18:54 -06:00
committed by GitHub
parent 99fef78f63
commit cbf41ce4c7
16 changed files with 534 additions and 633 deletions
+4 -2
View File
@@ -1,3 +1,5 @@
import { toKebabCase } from '@videojs/utils';
/**
* Converts a `NamedNodeMap` to a plain object.
*/
@@ -22,9 +24,9 @@ export function setAttributes(element: HTMLElement, attributes: Record<string, a
if (key === 'style' && typeof value === 'object') {
for (const [styleKey, styleValue] of Object.entries(value)) {
if (typeof styleValue === 'string') {
element.style.setProperty(styleKey, styleValue);
element.style.setProperty(toKebabCase(styleKey), styleValue);
} else if (styleValue == null) {
element.style.removeProperty(styleKey);
element.style.removeProperty(toKebabCase(styleKey));
}
}
} else {
+34 -2
View File
@@ -26,7 +26,7 @@ export function getDocumentOrShadowRoot(node: Node): Document | ShadowRoot | nul
return null;
}
export function getDocument(node: Element | null): Document {
export function getDocument(node?: Element | null): Document {
return node?.ownerDocument ?? document;
}
@@ -111,7 +111,7 @@ export function getNodeChildren(
return directChildren.flatMap(child => [child, ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);
}
export function getBoundingClientRectWithoutTransform(element: HTMLElement): DOMRect {
export function getUntransformedBoundingRect(element: HTMLElement): DOMRect {
let el = element;
let left = 0;
let top = 0;
@@ -134,6 +134,38 @@ export function getBoundingClientRectWithoutTransform(element: HTMLElement): DOM
} as DOMRect;
}
export function addTranslateToBoundingRect(rect: DOMRect, element: HTMLElement): DOMRect {
// Get translate from transform
const style = getWindow(element).getComputedStyle(element);
const translate = style.translate;
if (translate && translate !== 'none') {
const values = translate.split(' ');
// Parse translateX (can be px, %, etc)
const translateX = parseTranslateValue(values[0] ?? '0', element.offsetWidth);
const translateY = parseTranslateValue(values[1] ?? '0', element.offsetHeight);
return {
...rect,
left: rect.left + translateX,
top: rect.top + translateY,
};
}
return rect;
}
function parseTranslateValue(value: string, referenceSize: number): number {
if (value.endsWith('%')) {
return (Number.parseFloat(value) / 100) * referenceSize;
}
if (value.endsWith('px')) {
return Number.parseFloat(value);
}
// Handle other units like em, rem, etc if needed
return Number.parseFloat(value) || 0;
}
export function getInBoundsAdjustments(
popupRect: DOMRect,
containerRect: DOMRect,
+1
View File
@@ -1,5 +1,6 @@
export * from './shared/console';
export * from './shared/crypto';
export * from './shared/math';
export * from './shared/memoize';
export * from './shared/state';
export * from './shared/string';
+27
View File
@@ -0,0 +1,27 @@
export interface Point {
x: number;
y: number;
}
/**
* Get progress ratio of a point on a line segment.
* @param x - The x coordinate of the point.
* @param y - The y coordinate of the point.
* @param p1 - The first point of the line segment.
* @param p2 - The second point of the line segment.
*/
export function getPointProgressOnLine(x: number, y: number, p1: Point, p2: Point): number {
const dx = p2.x - p1.x;
const dy = p2.y - p1.y;
const lengthSquared = dx * dx + dy * dy;
if (lengthSquared === 0) return 0; // Avoid division by zero if p1 === p2
const projection = ((x - p1.x) * dx + (y - p1.y) * dy) / lengthSquared;
return Math.max(0, Math.min(1, projection)); // Clamp between 0 and 1
}
export function distance(p1: Point, p2: Point): number {
return Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2);
}
+12
View File
@@ -9,3 +9,15 @@ export function toCamelCase(str: string): string {
.toLowerCase()
.replace(/[-_]([a-z])/g, (_$0, $1) => $1.toUpperCase());
}
/**
* Converts a string to kebab case.
*
* @param str - The string to convert.
* @returns The kebab case string.
*/
export function toKebabCase(str: string): string {
return str
.replace(/([A-Z])/g, '-$1')
.toLowerCase();
}