@wordpress/block-library
Version:
Block library for the WordPress editor.
472 lines (470 loc) • 15.2 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/block-library/src/utils/waveform-utils.js
var waveform_utils_exports = {};
__export(waveform_utils_exports, {
applyWaveformPlayerStyles: () => applyWaveformPlayerStyles,
createWaveformContainer: () => createWaveformContainer,
getWaveformColors: () => getWaveformColors,
getWaveformGradientStops: () => getWaveformGradientStops,
initWaveformPlayer: () => initWaveformPlayer,
logPlayError: () => logPlayError,
setupPlayButtonAccessibility: () => setupPlayButtonAccessibility,
setupPlayButtonArtwork: () => setupPlayButtonArtwork,
styleSvgIcons: () => styleSvgIcons,
updateSeekControlLabel: () => updateSeekControlLabel
});
module.exports = __toCommonJS(waveform_utils_exports);
var import_colord = require("colord");
var import_waveform_player = __toESM(require("@arraypress/waveform-player"));
var DEFAULT_WAVEFORM_HEIGHT = 100;
var DEFAULT_SEEK_LABEL = "Seek";
function getComputedStyle(element) {
return element.ownerDocument.defaultView.getComputedStyle(element);
}
function getTopLevelGradientParts(gradientValue) {
const match = gradientValue?.trim().match(/^[\w-]+-gradient\((.*)\)$/i);
if (!match) {
return [];
}
const parts = [];
let depth = 0;
let current = "";
for (const character of match[1]) {
if (character === "(") {
++depth;
} else if (character === ")") {
--depth;
}
if (character === "," && depth === 0) {
parts.push(current.trim());
current = "";
continue;
}
current += character;
}
if (current.trim()) {
parts.push(current.trim());
}
return parts;
}
function getLeadingColorFunction(value) {
const match = value.match(/^([\w-]+)\(/);
if (!match) {
return;
}
const supportedFunctions = [
"color",
"color-mix",
"hsl",
"hsla",
"hwb",
"lab",
"lch",
"oklab",
"oklch",
"rgb",
"rgba",
"var"
];
if (!supportedFunctions.includes(match[1].toLowerCase())) {
return;
}
let depth = 0;
let foundOpeningParenthesis = false;
for (let index = 0; index < value.length; index++) {
const character = value[index];
if (character === "(") {
foundOpeningParenthesis = true;
++depth;
} else if (character === ")") {
--depth;
}
if (foundOpeningParenthesis && depth === 0) {
return value.slice(0, index + 1);
}
}
}
function getColorStopValue(gradientPart) {
const colorFunction = getLeadingColorFunction(gradientPart);
if (colorFunction) {
return colorFunction;
}
const [possibleColor] = gradientPart.split(/\s+/);
if ((0, import_colord.colord)(possibleColor).isValid()) {
return possibleColor;
}
}
function getWaveformGradientDirection(gradientValue) {
const parts = getTopLevelGradientParts(gradientValue);
const direction = parts[0];
const angleMatch = direction?.match(/^(-?\d+(?:\.\d+)?)deg$/i);
if (angleMatch) {
const angle = (Number(angleMatch[1]) % 360 + 360) % 360;
if (angle === 90 || angle === 270) {
return "horizontal";
}
if (angle === 0 || angle === 180) {
return "vertical";
}
return "diagonal";
}
if (!direction?.startsWith("to ")) {
return void 0;
}
const sideOrCorner = direction.toLowerCase().replace(/^to\s+/, "");
const hasHorizontalSide = sideOrCorner.includes("left") || sideOrCorner.includes("right");
const hasVerticalSide = sideOrCorner.includes("top") || sideOrCorner.includes("bottom");
if (hasHorizontalSide && hasVerticalSide) {
return "diagonal";
}
if (hasHorizontalSide) {
return "horizontal";
}
if (hasVerticalSide) {
return "vertical";
}
}
function resolveColorValue(element, colorValue) {
if (!colorValue || (0, import_colord.colord)(colorValue).isValid()) {
return colorValue;
}
const colorResolver = element.ownerDocument.createElement("span");
colorResolver.style.color = colorValue;
if (!colorResolver.style.color) {
return colorValue;
}
element.appendChild(colorResolver);
const resolvedColor = getComputedStyle(colorResolver).color;
colorResolver.remove();
return resolvedColor && (0, import_colord.colord)(resolvedColor).isValid() ? resolvedColor : colorValue;
}
function getResolvedGradientStops(element, gradientValue) {
const stops = getWaveformGradientStops(gradientValue)?.map((colorValue) => resolveColorValue(element, colorValue)).filter((colorValue) => (0, import_colord.colord)(colorValue).isValid());
return stops?.length > 1 ? stops : void 0;
}
function applyAlpha(colorValue, alpha) {
if (Array.isArray(colorValue)) {
return colorValue.map(
(color) => (0, import_colord.colord)(color).alpha(alpha).toRgbString()
);
}
return (0, import_colord.colord)(colorValue).alpha(alpha).toRgbString();
}
function getRepresentativeColor(colorValue) {
if (Array.isArray(colorValue)) {
return colorValue[colorValue.length - 1];
}
return colorValue;
}
function getWaveformGradientStops(gradientValue) {
const stops = getTopLevelGradientParts(gradientValue).map(getColorStopValue).filter(Boolean);
return stops.length > 1 ? stops : void 0;
}
function serializeColorValue(colorValue) {
return Array.isArray(colorValue) ? JSON.stringify(colorValue) : colorValue;
}
function getWaveformColors(element, waveformColorValue, textColorValue, waveformGradientValue) {
const textColor = textColorValue || getComputedStyle(element).color;
const waveformGradientStops = getResolvedGradientStops(
element,
waveformGradientValue
);
const waveformBaseColor = waveformGradientStops || waveformColorValue || textColor;
const waveformColor = applyAlpha(waveformBaseColor, 0.3);
const progressColor = applyAlpha(waveformBaseColor, 0.6);
const waveformGradient = waveformGradientStops ? getWaveformGradientDirection(waveformGradientValue) : void 0;
return {
textColor,
waveformColor,
progressColor,
...waveformGradient && { waveformGradient }
};
}
function createWaveformContainer({
url,
title,
artist,
artwork,
waveformColor,
progressColor,
waveformGradient,
buttonColor,
seekLabel,
seekValueText,
height = DEFAULT_WAVEFORM_HEIGHT,
waveformStyle = "bars"
}) {
const container = document.createElement("div");
container.setAttribute("data-waveform-player", "");
container.setAttribute("data-url", url);
container.setAttribute("data-height", String(height));
container.setAttribute("data-waveform-style", waveformStyle);
container.setAttribute(
"data-waveform-color",
serializeColorValue(waveformColor)
);
container.setAttribute(
"data-progress-color",
serializeColorValue(progressColor)
);
if (waveformGradient) {
container.setAttribute("data-waveform-gradient", waveformGradient);
}
container.setAttribute("data-button-color", buttonColor);
container.setAttribute(
"data-seek-label",
getSeekControlLabel(seekLabel)
);
if (seekValueText) {
container.setAttribute("data-seek-value-text", seekValueText);
}
container.setAttribute("data-text-color", buttonColor);
container.setAttribute("data-text-secondary-color", buttonColor);
if (title) {
container.setAttribute("data-title", title);
}
if (artist) {
container.setAttribute("data-artist", artist);
}
if (artwork) {
container.setAttribute("data-artwork", artwork);
}
return container;
}
function applyWaveformPlayerStyles(container, {
backgroundColor,
backgroundGradient,
textColor,
playButtonColor,
playButtonGradient
} = {}) {
const waveformContainer = container.querySelector(".waveform-container");
const playButton = container.querySelector(".waveform-btn");
const playButtonBaseColor = getRepresentativeColor(
getResolvedGradientStops(container, playButtonGradient) || playButtonColor
);
if (playButtonBaseColor) {
container.style.setProperty(
"--wfp-button-color",
playButtonBaseColor
);
} else {
container.style.removeProperty("--wfp-button-color");
}
if (textColor) {
container.style.setProperty("--wfp-text-color", textColor);
container.style.setProperty("--wfp-text-secondary-color", textColor);
} else {
container.style.removeProperty("--wfp-text-color");
container.style.removeProperty("--wfp-text-secondary-color");
}
if (playButton) {
if (playButtonGradient) {
playButton.style.background = playButtonGradient;
} else {
playButton.style.removeProperty("background");
}
}
if (waveformContainer) {
if (backgroundGradient) {
waveformContainer.style.background = backgroundGradient;
} else if (backgroundColor) {
waveformContainer.style.removeProperty("background");
waveformContainer.style.backgroundColor = backgroundColor;
} else {
waveformContainer.style.removeProperty("background");
waveformContainer.style.removeProperty("background-color");
}
}
}
function styleSvgIcons(container, buttonColor) {
const isButtonDark = (0, import_colord.colord)(buttonColor).isDark();
const iconColor = isButtonDark ? "#ffffff" : "#000000";
const svgPaths = container.querySelectorAll("svg path");
svgPaths.forEach((path) => {
path.style.fill = iconColor;
});
}
function setupPlayButtonAccessibility(container, { play: playLabel = "Play", pause: pauseLabel = "Pause" } = {}) {
const playBtn = container.querySelector(".waveform-btn");
if (!playBtn) {
return;
}
playBtn.setAttribute("aria-label", playLabel);
const onPlay = () => playBtn.setAttribute("aria-label", pauseLabel);
const onPause = () => playBtn.setAttribute("aria-label", playLabel);
container.addEventListener("waveformplayer:play", onPlay);
container.addEventListener("waveformplayer:pause", onPause);
container.addEventListener("waveformplayer:ended", onPause);
return () => {
container.removeEventListener("waveformplayer:play", onPlay);
container.removeEventListener("waveformplayer:pause", onPause);
container.removeEventListener("waveformplayer:ended", onPause);
};
}
function getSeekControlLabel(label) {
return label || DEFAULT_SEEK_LABEL;
}
function updateSeekControlLabel(instance, label) {
const seekLabel = getSeekControlLabel(label);
instance.options.seekLabel = seekLabel;
instance.applySeekLabel?.(seekLabel);
const seekControl = instance?.container?.querySelector(
".waveform-container"
);
if (seekControl) {
seekControl.setAttribute("aria-label", seekLabel);
}
}
function setupPlayButtonArtwork(container, artworkUrl) {
if (!artworkUrl) {
container.classList.remove("has-play-button-artwork");
container.style.removeProperty("--wp--playlist--play-button-artwork");
return;
}
container.classList.add("has-play-button-artwork");
container.style.setProperty(
"--wp--playlist--play-button-artwork",
`url(${JSON.stringify(artworkUrl)})`
);
}
function logPlayError(error) {
if (error.name === "AbortError") {
return;
}
console.error("Playlist play error:", error);
}
function initWaveformPlayer(element, {
src,
title,
artist,
image,
imageAlt,
waveformColor: waveformColorValue,
waveformGradient: waveformGradientValue,
textColor: textColorValue,
backgroundColor,
backgroundGradient,
autoPlay,
onEnded,
labels,
waveformStyle,
showPlayButtonArtwork = false
}) {
const playerArtwork = showPlayButtonArtwork ? void 0 : image;
const { textColor, waveformColor, progressColor, waveformGradient } = getWaveformColors(
element,
waveformColorValue,
textColorValue,
waveformGradientValue
);
const waveformGradientStops = getResolvedGradientStops(
element,
waveformGradientValue
);
const waveformButtonColor = getRepresentativeColor(
waveformGradientStops || waveformColorValue
);
const container = createWaveformContainer({
url: src,
title,
artist,
artwork: playerArtwork,
waveformColor,
progressColor,
waveformGradient,
buttonColor: textColor,
seekLabel: title || labels?.seek,
seekValueText: labels?.seekValueText,
waveformStyle
});
element.appendChild(container);
const instance = new import_waveform_player.default(container);
if (instance.artworkEl) {
instance.artworkEl.alt = imageAlt || "";
}
applyWaveformPlayerStyles(container, {
backgroundColor,
backgroundGradient,
textColor,
playButtonColor: showPlayButtonArtwork ? void 0 : waveformButtonColor,
playButtonGradient: showPlayButtonArtwork ? void 0 : waveformGradientValue
});
let cleanupPlayButtonAccessibility;
const handlers = {
ready: () => {
styleSvgIcons(container, waveformButtonColor || textColor);
if (showPlayButtonArtwork) {
setupPlayButtonArtwork(container, image);
}
cleanupPlayButtonAccessibility = setupPlayButtonAccessibility(
container,
labels
);
if (autoPlay) {
instance.play()?.catch(logPlayError);
}
},
ended: () => onEnded?.()
};
container.addEventListener("waveformplayer:ready", handlers.ready);
container.addEventListener("waveformplayer:ended", handlers.ended);
return {
instance,
container,
destroy: () => {
cleanupPlayButtonAccessibility?.();
container.removeEventListener(
"waveformplayer:ready",
handlers.ready
);
container.removeEventListener(
"waveformplayer:ended",
handlers.ended
);
instance.destroy();
container.remove();
}
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
applyWaveformPlayerStyles,
createWaveformContainer,
getWaveformColors,
getWaveformGradientStops,
initWaveformPlayer,
logPlayError,
setupPlayButtonAccessibility,
setupPlayButtonArtwork,
styleSvgIcons,
updateSeekControlLabel
});
//# sourceMappingURL=waveform-utils.cjs.map