one
Version:
One is a React framework for web, iOS, and Android apps.
155 lines (152 loc) • 4.24 kB
JavaScript
import { sampleCurve } from "./curves.mjs";
import { VIEW_BASE, domStyle } from "../web/DomView.mjs";
import { resolveEdges, resolveRadius } from "./normalize.mjs";
import { jsx, jsxs } from "react/jsx-runtime";
const EDGES = [
"top",
"bottom",
"left",
"right"
];
const DIRECTIONS = {
top: "to bottom",
bottom: "to top",
left: "to right",
right: "to left"
};
function curveStops(edge, paint) {
const alphas = sampleCurve(edge.curve);
const last = alphas.length - 1;
return alphas.map((_, index) => {
const visible = alphas[last - index] ?? 0;
return `${paint(visible)} ${(index / last * edge.size).toFixed(2)}px`;
});
}
function edgeMask(name, edge) {
const stops = curveStops(edge, (visible) => `rgba(0,0,0,${visible})`);
return `linear-gradient(${DIRECTIONS[name]}, ${stops.join(", ")}, black ${edge.size}px)`;
}
function stripLayout(name, size) {
const depth = Math.max(0, size);
const base = {
position: "absolute",
pointerEvents: "none"
};
switch (name) {
case "top": return {
...base,
top: 0,
left: 0,
right: 0,
height: depth
};
case "bottom": return {
...base,
bottom: 0,
left: 0,
right: 0,
height: depth
};
case "left": return {
...base,
top: 0,
bottom: 0,
left: 0,
width: depth
};
case "right": return {
...base,
top: 0,
bottom: 0,
right: 0,
width: depth
};
}
}
function stripGradient(name, edge, paint) {
const alphas = sampleCurve(edge.curve);
const last = alphas.length - 1;
const stops = alphas.map((_, index) => {
const visible = alphas[last - index] ?? 0;
return `${paint(visible)} ${(index / last * 100).toFixed(2)}%`;
});
return `linear-gradient(${DIRECTIONS[name]}, ${stops.join(", ")})`;
}
function colorPaint(color) {
return (visible) => `color-mix(in srgb, ${String(color)} ${((1 - visible) * 100).toFixed(2)}%, transparent)`;
}
function documentIsRTL() {
return typeof document !== "undefined" && document.documentElement.dir === "rtl";
}
function EdgeFade(props) {
const resolved = resolveEdges(props, documentIsRTL());
const { top: _top, bottom: _bottom, left: _left, right: _right, start: _start, end: _end, size: _size, curve: _curve, mode: _mode, color: _color, blurRadius: _blurRadius, frostProgression: _frostProgression, radius, style, children, testID, nativeID } = props;
const { borderRadius: styleRadius, ...cleanStyle } = domStyle(style);
const resolvedRadius = resolveRadius(radius, styleRadius);
const box = {
...VIEW_BASE,
...cleanStyle,
...resolvedRadius != null && {
borderRadius: resolvedRadius,
overflow: "hidden"
}
};
const hostProps = {
"data-testid": testID,
id: nativeID
};
const edges = EDGES.flatMap((name) => {
const edge = resolved[name];
return edge ? [{
name,
edge
}] : [];
});
if (resolved.mode === "mask") {
const maskImage = edges.map(({ name, edge }) => edgeMask(name, edge)).join(", ");
const maskStyle = edges.length ? {
maskImage,
maskComposite: "intersect",
maskRepeat: "no-repeat"
} : {};
return /* @__PURE__ */ jsx("div", {
...hostProps,
style: {
...box,
...maskStyle
},
children
});
}
if (resolved.mode === "overlay") {
const fallback = resolved.color ?? "black";
return /* @__PURE__ */ jsxs("div", {
...hostProps,
style: box,
children: [children, edges.map(({ name, edge }) => /* @__PURE__ */ jsx("div", { style: {
...stripLayout(name, edge.size),
backgroundImage: stripGradient(name, edge, colorPaint(edge.color ?? fallback))
} }, name))]
});
}
const veil = resolved.color;
return /* @__PURE__ */ jsxs("div", {
...hostProps,
style: box,
children: [children, edges.map(({ name, edge }) => {
const reach = resolved.frostProgression;
const blurMask = stripGradient(name, edge, (visible) => {
const strength = Math.min(1, (1 - visible) / reach);
return `rgba(0,0,0,${strength.toFixed(4)})`;
});
return /* @__PURE__ */ jsx("div", { style: {
...stripLayout(name, edge.size),
backdropFilter: `blur(${resolved.blurRadius}px)`,
maskImage: blurMask,
backgroundImage: veil ? stripGradient(name, edge, colorPaint(veil)) : void 0
} }, name);
})]
});
}
export { EdgeFade };
//# sourceMappingURL=EdgeFade.mjs.map