alien-dom
Version:
Next-generation JSX client renderer with observable data primitives, immediate DOM references, and more.
1,041 lines (1,031 loc) • 30.3 kB
JavaScript
import { isString, isNode, isFunction, toArray, isNumber, isPromise, deleteTimeline, getPrivate, kAlienAnimatedState, isSvgChild, setPrivate, isBoolean, AnimatedTransform, parseValue, resolveTransformFn, applyAnimatedValue, keys, cssTransformDefaults, defineEffectType, observe, applyProp, unmount, mountLastChild, mountFirstChild, updateStyle, getEffects, enableEffect, isIterable, cssTransformUnits, canMatch } from './chunk-JH7ONIU5.mjs';
// ../node_modules/.pnpm/linear-color@1.2.0/node_modules/linear-color/dist/mix-color.mjs
var mix = (from, to, progress) => -progress * from + progress * to + from;
function hueToRgb(p, q, t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1 / 6)
return p + (q - p) * 6 * t;
if (t < 1 / 2)
return q;
if (t < 2 / 3)
return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
function hslaToRgba({ hue, saturation, lightness, alpha: alpha2 }) {
hue /= 360;
saturation /= 100;
lightness /= 100;
let red = 0;
let green = 0;
let blue = 0;
if (!saturation) {
red = green = blue = lightness;
} else {
const q = lightness < 0.5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation;
const p = 2 * lightness - q;
red = hueToRgb(p, q, hue + 1 / 3);
green = hueToRgb(p, q, hue);
blue = hueToRgb(p, q, hue - 1 / 3);
}
return {
red: Math.round(red * 255),
green: Math.round(green * 255),
blue: Math.round(blue * 255),
alpha: alpha2
};
}
var clamp = (min, max, v) => Math.min(Math.max(v, min), max);
var number = {
test: (v) => typeof v === "number",
parse: parseFloat,
transform: (v) => v
};
var alpha = {
...number,
transform: (v) => clamp(0, 1, v)
};
var sanitize = (v) => Math.round(v * 1e5) / 1e5;
var floatRegex = /(-)?([\d]*\.?[\d])+/g;
var singleColorRegex = /^(#[0-9a-f]{3,8}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
function isString2(v) {
return typeof v === "string";
}
var isColorString = (type, testProp) => (v) => {
return Boolean(
isString2(v) && singleColorRegex.test(v) && v.startsWith(type) || testProp && Object.prototype.hasOwnProperty.call(v, testProp)
);
};
var splitColor = (aName, bName, cName) => (v) => {
if (!isString2(v))
return v;
const [a, b, c, alpha2] = v.match(floatRegex);
return {
[aName]: parseFloat(a),
[bName]: parseFloat(b),
[cName]: parseFloat(c),
alpha: alpha2 !== void 0 ? parseFloat(alpha2) : 1
};
};
var clampRgbUnit = (v) => clamp(0, 255, v);
var rgbUnit = {
...number,
transform: (v) => Math.round(clampRgbUnit(v))
};
var rgba = {
test: isColorString("rgb", "red"),
parse: splitColor("red", "green", "blue"),
transform: ({ red, green, blue, alpha: alpha2 = 1 }) => "rgba(" + rgbUnit.transform(red) + ", " + rgbUnit.transform(green) + ", " + rgbUnit.transform(blue) + ", " + sanitize(alpha.transform(alpha2)) + ")"
};
function parseHex(v) {
let r = "";
let g = "";
let b = "";
let a = "";
if (v.length > 5) {
r = v.substring(1, 3);
g = v.substring(3, 5);
b = v.substring(5, 7);
a = v.substring(7, 9);
} else {
r = v.substring(1, 2);
g = v.substring(2, 3);
b = v.substring(3, 4);
a = v.substring(4, 5);
r += r;
g += g;
b += b;
a += a;
}
return {
red: parseInt(r, 16),
green: parseInt(g, 16),
blue: parseInt(b, 16),
alpha: a ? parseInt(a, 16) / 255 : 1
};
}
var hex = {
test: isColorString("#"),
parse: parseHex,
transform: rgba.transform
};
var createUnitType = (unit) => ({
test: (v) => isString2(v) && v.endsWith(unit) && v.split(" ").length === 1,
parse: parseFloat,
transform: (v) => `${v}${unit}`
});
var percent = createUnitType("%");
var hsla = {
test: isColorString("hsl", "hue"),
parse: splitColor("hue", "saturation", "lightness"),
transform: ({ hue, saturation, lightness, alpha: alpha2 = 1 }) => {
return "hsla(" + Math.round(hue) + ", " + percent.transform(sanitize(saturation)) + ", " + percent.transform(sanitize(lightness)) + ", " + sanitize(alpha.transform(alpha2)) + ")";
}
};
var mixLinearColor = (from, to, v) => {
const fromExpo = from * from;
return Math.sqrt(Math.max(0, v * (to * to - fromExpo) + fromExpo));
};
var colorTypes = [hex, rgba, hsla];
var getColorType = (v) => colorTypes.find((type) => type.test(v));
var rgbaToString = {
value: function() {
return rgba.transform(this);
}
};
function parseColor(color) {
const type = getColorType(color);
if (!type) {
throw Error(
`'${color}' is not an animatable color. Use the equivalent color code instead.`
);
}
let model = isString2(color) ? type.parse(color) : color;
if (type === hsla) {
model = hslaToRgba(model);
}
Object.defineProperty(model, "toString", rgbaToString);
return model;
}
function mixColor(from, to, v) {
from = parseColor(from);
to = parseColor(to);
return rgba.transform({
red: mixLinearColor(from.red, to.red, v),
green: mixLinearColor(from.green, to.green, v),
blue: mixLinearColor(from.blue, to.blue, v),
alpha: mix(from.alpha, to.alpha, v)
});
}
// core/animate.ts
var animatedElements = /* @__PURE__ */ new Map();
function animate(selector, _animations) {
const targets = isString(selector) ? document.querySelectorAll(selector) : isNode(selector) ? [selector] : selector;
if (isFunction(_animations)) {
const step = _animations;
if (targets.length) {
targets.forEach((target, index) => {
const state = ensureAnimatedElement(target);
state.step = step;
state.frame = {
target,
done: false,
t0: 0,
dt: 0,
time: 0,
duration: 0,
current: {},
index
};
animatedElements.set(target, state);
});
startLoop();
}
} else {
const animations = toArray(_animations);
const springs = animations.map(
(animation) => toSpringResolver(animation.spring)
);
targets.forEach((target) => {
let timelines;
let state = ensureAnimatedElement(target);
state.nodes ||= {};
const definedKeys = /* @__PURE__ */ new Set();
animations.forEach((animation, i) => {
let keys2 = Object.keys({
...animation.to,
...animation.from
});
keys2.forEach((key) => {
const to = animation.to?.[key];
const from = animation.from != null ? animation.from[key] : null;
if (to != null || from != null) {
definedKeys.add(key);
}
});
if (animation.delay) {
const { delay } = animation;
if (isNumber(delay)) {
if (delay > 0) {
keys2.forEach((key) => {
timelines = addTimelineTimeout(
timelines,
target,
state,
animation,
springs[i],
delay,
key
);
});
keys2.length = 0;
}
} else if (isFunction(delay) || isPromise(delay)) {
keys2.forEach((key) => {
timelines = addTimelinePromise(
timelines,
target,
state,
animation,
springs[i],
delay,
key
);
});
keys2.length = 0;
} else {
keys2 = keys2.filter((key) => {
const keyDelay = delay[key];
if (keyDelay) {
if (isNumber(keyDelay)) {
timelines = addTimelineTimeout(
timelines,
target,
state,
animation,
springs[i],
keyDelay,
key
);
} else {
timelines = addTimelinePromise(
timelines,
target,
state,
animation,
springs[i],
keyDelay,
key
);
}
return false;
}
return true;
});
}
}
if (keys2.length) {
applyAnimation(target, state, animation, springs[i], keys2);
}
});
const oldTimelines = state.timelines;
if (oldTimelines) {
definedKeys.forEach((key) => {
deleteTimeline(oldTimelines, key);
});
}
if (timelines) {
state.timelines = { ...oldTimelines, ...timelines };
}
});
}
}
function ensureAnimatedElement(target) {
let state = getPrivate(target, kAlienAnimatedState);
if (!state) {
state = {
svgMode: isSvgChild(target),
nodes: null,
step: null,
frame: null,
timelines: null,
transform: null,
anchor: null,
style: {},
onStart: null
};
setPrivate(target, kAlienAnimatedState, state);
}
return state;
}
function addTimelineTimeout(timelines, target, state, animation, spring, delay, key) {
if (delay > 0) {
const dilation = animation.dilate ?? 1;
const timerId = setTimeout(() => {
applyAnimation(target, state, animation, spring, [key]);
}, delay * dilation);
const timeline = (timelines ||= {})[key] ||= [];
timeline.push({ ...animation, timerId });
} else {
applyAnimation(target, state, animation, spring, [key]);
}
return timelines;
}
function addTimelinePromise(timelines, target, state, animation, spring, delay, key) {
const abortCtrl = new AbortController();
const promise = isFunction(delay) ? delay(abortCtrl.signal, key) : Promise.race([
delay,
new Promise(
(resolve) => abortCtrl.signal.addEventListener("abort", resolve)
)
]);
if (promise) {
const timeline = (timelines ||= {})[key] ||= [];
timeline.push({ ...animation, abortCtrl });
promise.then(() => {
if (!abortCtrl.signal.aborted) {
applyAnimation(target, state, animation, spring, [key]);
}
}, console.error);
} else {
applyAnimation(target, state, animation, spring, [key]);
}
return timelines;
}
function applyAnimation(target, state, animation, spring, keys2) {
startLoop();
const { nodes, svgMode } = state;
const { onStart, onChange, onRest } = animation;
const frame = onChange || onRest ? {} : null;
state.anchor = animation.anchor || // If an anchor gets unset, we need to reset it to the default.
state.anchor && (svgMode ? svgDefaultAnchor : htmlDefaultAnchor);
state.onStart = onStart || null;
for (const key of keys2) {
const oldNode = nodes[key];
const node = updateAnimatedNode(
target,
svgMode,
key,
animation.to?.[key],
animation.from?.[key],
oldNode,
spring,
animation.dilate,
!animation.velocity || isNumber(animation.velocity) ? animation.velocity : animation.velocity[key],
!animation.immediate || isBoolean(animation.immediate) ? animation.immediate : animation.immediate[key],
frame,
onChange,
onRest
);
if (node && !oldNode) {
nodes[key] = node;
if (node.transformFn) {
state.transform ||= new AnimatedTransform(target, svgMode);
}
}
if (node && !node.done) {
animatedElements.set(target, state);
}
}
}
function updateAnimatedNode(target, svgMode, key, to, from, node, spring, dilate, velocity, immediate, frame, onChange, onRest) {
let parsedFrom;
let parsedTo;
const isColor = isColorKey(key, svgMode);
if (isColor) {
parsedFrom = from != null ? parseColor(resolveCssVariable(from, target)) : null;
parsedTo = to != null ? parseColor(resolveCssVariable(to, target)) : parsedFrom;
} else {
const defaultUnit = svgMode ? void 0 : defaultUnits[key];
parsedFrom = from != null ? parseValue(from, defaultUnit) : null;
parsedTo = parseValue(to, defaultUnit) ?? parsedFrom;
}
if (!parsedTo) {
return null;
}
node ||= {
v0: 0,
done: false,
to: parsedTo,
from: null,
nextFrom: null,
lastPosition: null,
lastVelocity: null,
dilation: 1,
isRelative: false,
transformFn: resolveTransformFn(key, svgMode),
spring: null,
frame: null,
onChange: null,
onRest: null
};
node.done = false;
node.to = parsedTo;
node.from = null;
node.nextFrom = parsedFrom || node.nextFrom;
node.spring = spring(key);
node.frame = frame || null;
node.dilation = dilate ?? 1;
node.onChange = onChange || null;
node.onRest = onRest || null;
if (parsedFrom || isColor) {
node.lastPosition = null;
}
if (immediate || velocity != null || isNaN(node.v0)) {
node.v0 = immediate ? NaN : velocity ?? 0;
node.lastVelocity = null;
}
if (svgMode && !isColor) {
node.isRelative = scaleKeys.includes(key) || parsedTo[1] == "%" || !!parsedFrom && parsedFrom[1] == "%";
}
return node;
}
var htmlDefaultAnchor = [0.5, 0.5];
var svgDefaultAnchor = [0, 0];
var htmlColorKeys = ["backgroundColor", "color"];
var svgColorKeys = ["fill", "stroke"];
function isColorKey(key, svgMode) {
return (svgMode ? svgColorKeys : htmlColorKeys).includes(key);
}
var defaultUnits = {
...cssTransformUnits,
borderRadius: "px"
};
var svgNonZeroDefaults = {
fill: "rgba(0,0,0,0)",
fillOpacity: "1",
stroke: "rgba(0,0,0,0)",
strokeOpacity: "1",
opacity: "1"
};
var scaleKeys = ["scale", "scaleX", "scaleY"];
var loop;
var lastTime;
function startLoop() {
if (loop)
return;
loop = requestAnimationFrame(function step(now) {
const dt = Math.min(64, now - (lastTime || now));
lastTime = now;
let stepResults;
for (const [target, state] of animatedElements) {
if (!target.isConnected) {
animatedElements.delete(target);
continue;
}
if (state.nodes) {
ensureFromValues(target, state, state.nodes);
}
if (state.step) {
const { step: step2, frame } = state;
frame.t0 ??= now;
frame.dt = dt;
frame.time = now;
frame.duration += dt;
const stepResult = step2(frame);
stepResults ||= /* @__PURE__ */ new Map();
stepResults.set(target, stepResult);
}
}
let loopDone = true;
for (const [target, state] of animatedElements) {
const { nodes, svgMode, style, onStart } = state;
if (onStart) {
onStart(target);
state.onStart = null;
}
const frames = /* @__PURE__ */ new Map();
if (nodes) {
for (const [key, node] of Object.entries(nodes)) {
if (node.done) {
continue;
}
if (node.from == null) {
continue;
}
const position = advance(node, node.spring, dt, key);
if (node.frame) {
const values = frames.get(node.frame) || [];
frames.set(node.frame, values);
values.push([key, node]);
}
const { to } = node;
if (Array.isArray(to)) {
if (node.transformFn) {
state.transform.addCall(key, position, to[1], node.transformFn);
} else {
const value = position + to[1];
applyAnimatedValue(target, style, svgMode, key, value);
}
} else {
const value = mixColor(node.from, to, position);
applyAnimatedValue(target, style, svgMode, key, value);
}
}
}
if (state.step) {
const frame = state.frame;
const stepResult = stepResults.get(target);
if (stepResult) {
for (const key of keys(stepResult)) {
const value = stepResult[key];
if (value !== void 0) {
frame.current[key] = value;
}
const transformFn = resolveTransformFn(key, svgMode);
if (transformFn) {
const defaultUnit = svgMode ? void 0 : defaultUnits[key];
const parsed = parseValue(value, defaultUnit);
if (parsed) {
state.transform ||= new AnimatedTransform(target, svgMode);
state.transform.addCall(key, parsed[0], parsed[1], transformFn);
}
} else {
applyAnimatedValue(target, null, svgMode, key, value);
}
}
}
if (frame.done) {
state.step = null;
state.frame = null;
}
}
state.transform?.apply(state);
for (const [frame, values] of frames) {
let frameDone = true;
for (const [prop, node] of values) {
frame[prop] = readValue(node);
if (!node.done) {
frameDone = false;
}
}
const { onChange, onRest } = values[0][1];
if (onChange) {
onChange(frame, target);
}
if (onRest && frameDone) {
onRest(frame, target);
}
}
const done = !(state.nodes && Object.values(state.nodes).some((node) => !node.done)) && !state.step;
if (done) {
animatedElements.delete(target);
} else {
loopDone = false;
}
}
if (loopDone) {
for (const [, state] of animatedElements) {
if (state.nodes) {
const done = Object.values(state.nodes).every((node) => node.done);
if (!done) {
loopDone = false;
break;
}
}
if (state.frame && !state.frame.done) {
loopDone = false;
break;
}
}
}
if (loopDone) {
loop = void 0;
lastTime = void 0;
} else {
loop = requestAnimationFrame(step);
}
});
}
function readValue({ lastPosition, from, to }) {
if (lastPosition == null) {
return void 0;
}
if (Array.isArray(to)) {
const unit = to[1];
if (unit) {
return lastPosition + unit;
}
return lastPosition;
}
return mixColor(from, to, lastPosition);
}
var maxPrecision = 0.1 / (window.devicePixelRatio || 1);
var defaultPrecisions = {
opacity: 0.01
};
function advance(node, config, dt, prop) {
let from;
let to;
if (Array.isArray(node.to)) {
from = node.from[0];
to = node.to[0];
} else {
from = 0;
to = 1;
}
if (node.lastPosition == null && node.from == null) {
return to;
}
let position = node.lastPosition == null ? from : node.lastPosition;
let velocity = node.lastVelocity == null ? node.v0 : node.lastVelocity;
let finished = false;
const equalFromTo = from == to;
if (isNaN(velocity) || equalFromTo && velocity === 0) {
finished = true;
} else {
const precision = defaultPrecisions[prop] || (equalFromTo ? 5e-3 : Math.min(Math.abs(to - from) * 1e-3, maxPrecision));
const restVelocity = config.restVelocity || precision / 10;
const bounceFactor = config.clamp ? 0 : config.bounce;
const canBounce = bounceFactor !== void 0;
const isGrowing = equalFromTo ? node.v0 > 0 : from < to;
let isMoving;
let isBouncing = false;
const step = 1;
const stepFactor = 1 / node.dilation;
const numSteps = Math.max(1, Math.ceil(dt / step));
for (let n = 0; n < numSteps; ++n) {
isMoving = Math.abs(velocity) > restVelocity;
if (!isMoving) {
finished = Math.abs(to - position) <= precision;
if (finished) {
break;
}
}
if (canBounce) {
isBouncing = position == to || position > to == isGrowing;
if (isBouncing) {
velocity = -velocity * bounceFactor;
position = to;
}
}
const springForce = -config.tension * 1e-6 * (position - to);
const dampingForce = -config.friction * 1e-3 * velocity;
const acceleration = (springForce + dampingForce) / config.mass;
velocity = velocity + acceleration * step * stepFactor;
position = position + velocity * step * stepFactor;
}
}
if (finished) {
node.done = true;
velocity = 0;
position = to;
}
node.lastVelocity = velocity;
node.lastPosition = position;
return position;
}
function toSpringResolver(spring) {
if (!isFunction(spring)) {
const resolved = resolveSpring(spring || {});
return () => resolved;
}
return (key) => resolveSpring(spring(key) || {});
}
function resolveSpring(spring) {
let { frequency, damping, tension, friction, mass = 1 } = spring;
if (frequency != null) {
frequency = Math.max(0.01, frequency);
damping = Math.max(0, damping ?? 1);
tension = Math.pow(2 * Math.PI / frequency, 2) * mass;
friction = 4 * Math.PI * damping * mass / frequency;
} else {
tension = 170 * (tension ?? 1);
friction = 26 * (friction ?? 1);
}
return {
...spring,
tension,
friction,
mass
};
}
function ensureFromValues(target, state, nodes) {
let computedStyle;
const getStyleProp = (prop) => {
if (state.svgMode) {
return target.getAttribute(prop) || svgNonZeroDefaults[prop] || "0";
}
return target.style[prop] || (computedStyle ||= getComputedStyle(target))[prop];
};
for (const [key, node] of Object.entries(nodes)) {
if (node.nextFrom) {
node.from = node.nextFrom;
node.nextFrom = null;
}
if (node.done || node.from) {
continue;
}
if (node.transformFn) {
let from;
for (const [fn, args] of state.transform.read()) {
if (fn == node.transformFn) {
from = args[0];
break;
}
if (state.svgMode && fn == "scale") {
if (key == "scaleX") {
from = args[0];
break;
}
if (key == "scaleY") {
from = args[1];
break;
}
}
}
const to = node.to;
if (!from || from[1] == to[1] || isNaN(node.v0)) {
node.from = from || [cssTransformDefaults[node.transformFn] || 0, to[1]];
} else {
console.error(`Unit mismatch for "${key}": ${from[1]} != ${to[1]}`);
}
} else {
const value = getStyleProp(key);
node.from = isColorKey(key, state.svgMode) ? parseColor(resolveCssVariable(value, target)) : [parseFloat(value), ""];
}
}
}
function resolveCssVariable(value, target) {
if (value.startsWith("var(")) {
const varNameStart = value.indexOf("(") + 1;
const varName = value.slice(varNameStart, -1);
const varValue = getComputedStyle(target).getPropertyValue(varName);
if (!varValue) {
throw Error(`CSS variable not found: ${varName}`);
}
return varValue;
}
return value;
}
// functions/observeAs.ts
var observeAs = /* @__PURE__ */ defineEffectType(
(target, action) => observe(() => action(target)).destructor
);
// addons/element/attributes.ts
function patchAttributes(context, attributes) {
for (const name of keys(attributes)) {
applyProp(context, name, attributes[name]);
}
}
// addons/element/classList.ts
function hasClass(context, className) {
return context.classList.contains(className);
}
function addClass(context, classes) {
for (const name of splitClassNames(classes)) {
context.classList.add(name);
}
}
function removeClass(context, classes) {
for (const name of splitClassNames(classes)) {
context.classList.remove(name);
}
}
function removeMatchingClass(context, pattern) {
const test = isFunction(pattern) ? pattern : pattern.test.bind(pattern);
for (let i = 0; i < context.classList.length; i++) {
const token = context.classList.item(i);
if (test(token)) {
context.classList.remove(token);
}
}
}
function toggleClass(context, classes, force) {
for (const name of splitClassNames(classes)) {
context.classList.toggle(name, isFunction(force) ? force(name) : force);
}
}
function hasEveryClass(context, classes) {
return toArray(classes).every(
(className) => className.split(/\s+/).every((name) => context.classList.contains(name))
);
}
function hasSomeClass(context, classes) {
return toArray(classes).some(
(className) => className.split(/\s+/).some((name) => context.classList.contains(name))
);
}
function matchClass(context, pattern) {
for (let i = 0; i < context.classList.length; i++) {
const token = context.classList.item(i);
if (isFunction(pattern)) {
const match = pattern(token);
if (match || match === "") {
return match;
}
} else {
const match = pattern.exec(token);
if (match) {
return match[1] ?? match[0];
}
}
}
return "";
}
function* splitClassNames(classes) {
for (const className of toArray(classes)) {
yield* className.split(/\s+/);
}
}
// internal/unwrap.ts
function unwrap(node) {
const children = [];
const parent = node.parentNode;
if (parent) {
while (node.firstChild) {
children.push(node.firstChild);
parent.insertBefore(node.firstChild, node);
}
parent.removeChild(node);
}
return children;
}
// addons/elementExtensions.ts
var AlienElement = class {
$(selector) {
return this.querySelector(selector);
}
$$(selector) {
return this.querySelectorAll(selector);
}
siblings(selector) {
const self = this;
const siblings = this.parentNode ? Array.from(this.parentNode.childNodes) : [];
let cursor = -1;
const iterable = {
[Symbol.iterator]: () => ({
next() {
const value = iterable.next();
return { value, done: !value };
}
}),
next() {
let sibling;
while ((sibling = siblings[++cursor]) && sibling != self) {
if (!selector) {
return sibling;
}
if (canMatch(sibling) && sibling.matches(selector)) {
return sibling;
}
}
},
first() {
for (const sibling of siblings) {
if (sibling == self) {
continue;
}
if (!selector) {
return sibling;
}
if (canMatch(sibling) && sibling.matches(selector)) {
return sibling;
}
}
}
};
return iterable;
}
filter(selector) {
return this.matches(selector) ? this : null;
}
replaceText(value) {
if (typeof value == "function") {
return observeAs(this, (target) => {
target.textContent = value();
});
} else {
this.textContent = value;
}
return this;
}
empty() {
while (this.firstChild) {
unmount(this.firstChild);
}
return this;
}
appendTo(parent) {
mountLastChild(parent, this);
return this;
}
prependTo(parent) {
mountFirstChild(parent, this);
return this;
}
hasClass(name) {
return hasSomeClass(this, name);
}
addClass(name) {
addClass(this, name);
return this;
}
removeClass(name) {
removeClass(this, name);
return this;
}
removeMatchingClasses(pattern) {
removeMatchingClass(this, pattern);
return this;
}
toggleClass(name, value) {
return this.classList.toggle(name, value);
}
/**
* Returns the first class name that matches the given pattern.
*
* If a capturing group exists in the pattern, the captured value will
* be returned. Otherwise, the entire match will be returned.
*
* An empty string is returned if no match is found.
*/
matchClass(pattern) {
return matchClass(this, pattern);
}
css(style) {
updateStyle(this, style, 1 /* Interrupt */);
return this;
}
// TODO: update `props` type to allow ReadonlyRef values
set(props) {
patchAttributes(this, props);
return this;
}
spring(animations) {
animate(this, animations);
return this;
}
};
var setMethodImpl = (obj, name, method) => obj.prototype[name] = function(...args) {
return method(this, ...args);
};
setMethodImpl(AlienElement, "unwrap", unwrap);
setMethodImpl(AlienElement, "effects", getEffects);
for (const [suffix, flags] of [
["", 0],
["Once", 1 /* Once */],
["Async", 2 /* Async */],
["OnceAsync", 1 /* Once */ | 2 /* Async */]
]) {
setMethodImpl(
AlienElement,
"effect" + suffix,
function(node, effect, target, args) {
return enableEffect(
getEffects(node),
effect,
flags,
target,
arguments.length > 2 && args
);
}
);
}
// addons/global/nodeList.ts
var AlienNodeListPrototype = /* @__PURE__ */ defineAlienNodeList();
var AlienElementListPrototype = {
...AlienNodeListPrototype,
__proto__: Array.prototype,
// Exists for compatibility with NodeList.
item(index) {
return this[index] || null;
}
};
function createAlienElementList(arg) {
if (arg && arg instanceof NodeList) {
return arg;
}
const list = !arg ? [] : isIterable(arg) ? [...arg] : [arg];
Object.setPrototypeOf(list, AlienElementListPrototype);
return list;
}
function defineAlienNodeList() {
return {
[Symbol.iterator]() {
const out = [];
this.forEach((value, index) => {
out[index] = value;
});
return out[Symbol.iterator]();
},
map(iterator) {
const out = [];
this.forEach((value, index) => {
out.push(iterator(value, index));
});
return out;
},
filter(selector) {
const out = [];
const filter = typeof selector == "string" ? (value) => canMatch(value) && value.matches(selector) : selector;
this.forEach((value, index) => {
if (filter(value, index)) {
out.push(value);
}
});
return out;
},
mapFilter(iterator) {
const out = [];
this.forEach((value, index) => {
const result = iterator(value, index);
if (result != null) {
out.push(result);
}
});
return out;
},
find(selector) {
const filter = typeof selector == "string" ? (value) => canMatch(value) && value.matches(selector) : selector;
for (let i = 0; i < this.length; i++) {
if (filter(this[i], i)) {
return this[i];
}
}
}
};
}
export { AlienElement, AlienNodeListPrototype, addClass, animate, createAlienElementList, hasClass, hasEveryClass, hasSomeClass, matchClass, mixColor, observeAs, parseColor, patchAttributes, removeClass, removeMatchingClass, toggleClass };