aaavatars 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -13
- package/dist/Avatar.d.ts +14 -4
- package/dist/Avatar.js +160 -19
- package/dist/animations.d.ts +28 -3
- package/dist/animations.js +334 -99
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/parts.d.ts +6 -2
- package/dist/parts.js +107 -13
- package/dist/pointer.d.ts +1 -0
- package/dist/pointer.js +55 -13
- package/dist/styles.d.ts +1 -1
- package/dist/styles.js +234 -40
- package/dist/visibility.d.ts +1 -0
- package/dist/visibility.js +26 -0
- package/package.json +1 -1
- package/dist/value.d.ts +0 -20
- package/dist/value.js +0 -66
package/dist/parts.js
CHANGED
|
@@ -3,17 +3,111 @@ const STROKE = { fill: "none", strokeLinecap: "round", strokeWidth: 4 };
|
|
|
3
3
|
export function mouthSlot(geometry, color) {
|
|
4
4
|
return { color, width: geometry.eyeGap * 1.2, x: 50, y: geometry.eyeY + 17 };
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
const EYE_HALF_HEIGHT = { dot: 7, round: 10, tall: 11, wide: 7 };
|
|
7
|
+
const EYE_HALF_WIDTH = { dot: 7, round: 8, tall: 5, wide: 11 };
|
|
8
|
+
const SEGMENTS = 12;
|
|
9
|
+
const CROSS = [
|
|
10
|
+
[0, -3.5],
|
|
11
|
+
[5, -8.5],
|
|
12
|
+
[8.5, -5],
|
|
13
|
+
[3.5, 0],
|
|
14
|
+
[8.5, 5],
|
|
15
|
+
[5, 8.5],
|
|
16
|
+
[0, 3.5],
|
|
17
|
+
[-5, 8.5],
|
|
18
|
+
[-8.5, 5],
|
|
19
|
+
[-3.5, 0],
|
|
20
|
+
[-8.5, -5],
|
|
21
|
+
[-5, -8.5],
|
|
22
|
+
];
|
|
23
|
+
function arc(cx, cy, rx, ry, from, to) {
|
|
24
|
+
const k = (4 / 3) * Math.tan((to - from) / 4);
|
|
25
|
+
const point = (angle) => [cx + rx * Math.cos(angle), cy + ry * Math.sin(angle)];
|
|
26
|
+
const tangent = (angle) => [-rx * Math.sin(angle), ry * Math.cos(angle)];
|
|
27
|
+
const [x0, y0] = point(from);
|
|
28
|
+
const [x1, y1] = point(to);
|
|
29
|
+
const [tx0, ty0] = tangent(from);
|
|
30
|
+
const [tx1, ty1] = tangent(to);
|
|
31
|
+
return [
|
|
32
|
+
[x0 + k * tx0, y0 + k * ty0],
|
|
33
|
+
[x1 - k * tx1, y1 - k * ty1],
|
|
34
|
+
[x1, y1],
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
function line([x0, y0], [x1, y1]) {
|
|
38
|
+
return [
|
|
39
|
+
[x0 + (x1 - x0) / 3, y0 + (y1 - y0) / 3],
|
|
40
|
+
[x0 + ((x1 - x0) * 2) / 3, y0 + ((y1 - y0) * 2) / 3],
|
|
41
|
+
[x1, y1],
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
function toPath(start, segments) {
|
|
45
|
+
const at = ([x, y]) => `${+x.toFixed(2)} ${+y.toFixed(2)}`;
|
|
46
|
+
return `M${at(start)}${segments.map((segment) => `C${segment.map(at).join(" ")}`).join("")}Z`;
|
|
47
|
+
}
|
|
48
|
+
const DEG = Math.PI / 180;
|
|
49
|
+
function ellipse(rx, ry) {
|
|
50
|
+
const step = (2 * Math.PI) / SEGMENTS;
|
|
51
|
+
return toPath([0, -ry], Array.from({ length: SEGMENTS }, (_, index) => arc(0, 0, rx, ry, -90 * DEG + index * step, -90 * DEG + (index + 1) * step)));
|
|
52
|
+
}
|
|
53
|
+
function stadium(r, half) {
|
|
54
|
+
const top = r - half;
|
|
55
|
+
const bottom = half - r;
|
|
56
|
+
return toPath([0, -half], [
|
|
57
|
+
arc(0, top, r, r, 270 * DEG, 315 * DEG),
|
|
58
|
+
arc(0, top, r, r, 315 * DEG, 360 * DEG),
|
|
59
|
+
line([r, top], [r, 0]),
|
|
60
|
+
line([r, 0], [r, bottom]),
|
|
61
|
+
...[0, 45, 90, 135].map((from) => arc(0, bottom, r, r, from * DEG, (from + 45) * DEG)),
|
|
62
|
+
line([-r, bottom], [-r, 0]),
|
|
63
|
+
line([-r, 0], [-r, top]),
|
|
64
|
+
arc(0, top, r, r, 180 * DEG, 225 * DEG),
|
|
65
|
+
arc(0, top, r, r, 225 * DEG, 270 * DEG),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
function polygon(vertices, dx = 0) {
|
|
69
|
+
const shifted = vertices.map(([x, y]) => [x + dx, y]);
|
|
70
|
+
const edges = shifted.map((from, index) => ({ from, to: shifted[(index + 1) % shifted.length], parts: 1 }));
|
|
71
|
+
for (let count = edges.length; count < SEGMENTS; count += 1) {
|
|
72
|
+
const longest = edges.reduce((best, edge) => Math.hypot(edge.to[0] - edge.from[0], edge.to[1] - edge.from[1]) / edge.parts >
|
|
73
|
+
Math.hypot(best.to[0] - best.from[0], best.to[1] - best.from[1]) / best.parts
|
|
74
|
+
? edge
|
|
75
|
+
: best);
|
|
76
|
+
longest.parts += 1;
|
|
77
|
+
}
|
|
78
|
+
const anchors = edges.flatMap(({ from, to, parts }) => Array.from({ length: parts }, (_, index) => [
|
|
79
|
+
from[0] + ((to[0] - from[0]) * index) / parts,
|
|
80
|
+
from[1] + ((to[1] - from[1]) * index) / parts,
|
|
81
|
+
]));
|
|
82
|
+
const cx = shifted.reduce((sum, [x]) => sum + x, 0) / shifted.length;
|
|
83
|
+
const cy = shifted.reduce((sum, [, y]) => sum + y, 0) / shifted.length;
|
|
84
|
+
const offTop = ([x, y]) => Math.abs(Math.atan2(x - cx, cy - y));
|
|
85
|
+
const first = anchors.reduce((best, anchor, index) => (offTop(anchor) < offTop(anchors[best]) ? index : best), 0);
|
|
86
|
+
const ordered = [...anchors.slice(first), ...anchors.slice(0, first)];
|
|
87
|
+
return toPath(ordered[0], ordered.map((anchor, index) => line(anchor, ordered[(index + 1) % ordered.length])));
|
|
88
|
+
}
|
|
89
|
+
export function eyePath(eyes, pose, side, gap) {
|
|
90
|
+
if (pose === "cross")
|
|
91
|
+
return polygon(CROSS);
|
|
92
|
+
if (pose === "cursor")
|
|
93
|
+
return polygon([[-2, -13.5], [2, -13.5], [2, 13.5], [-2, 13.5]], -side * gap);
|
|
94
|
+
if (pose === "prompt" && side === -1) {
|
|
95
|
+
return polygon([[-8, -14], [0, -14], [10, 0], [0, 14], [-8, 14], [2, 0]], gap - 11.5);
|
|
96
|
+
}
|
|
97
|
+
if (pose === "prompt")
|
|
98
|
+
return polygon([[-9, 8.5], [9, 8.5], [9, 14], [-9, 14]], 10.5 - gap);
|
|
99
|
+
if (eyes === "tall")
|
|
100
|
+
return stadium(5, 11);
|
|
101
|
+
return ellipse(EYE_HALF_WIDTH[eyes], EYE_HALF_HEIGHT[eyes]);
|
|
102
|
+
}
|
|
103
|
+
function LidMask({ eyes, id, side }) {
|
|
104
|
+
const half = EYE_HALF_HEIGHT[eyes];
|
|
105
|
+
return (_jsxs("mask", { id: id, maskUnits: "userSpaceOnUse", x: -20, y: -20, width: 40, height: 40, children: [_jsx("rect", { x: -20, y: -20, width: 40, height: 40, fill: "#fff" }), _jsx("rect", { className: `aaa-lid aaa-lid-top aaa-lid-${side}`, "data-h": half, x: -20, y: -half - 20, width: 40, height: 20, fill: "#000" }), _jsx("rect", { className: `aaa-lid aaa-lid-bottom aaa-lid-${side}`, "data-h": half, x: -20, y: half, width: 40, height: 20, fill: "#000" })] }));
|
|
106
|
+
}
|
|
107
|
+
export function EyePair({ eyes, gap, id, pose, y, }) {
|
|
108
|
+
const h = EYE_HALF_HEIGHT[eyes];
|
|
109
|
+
const w = EYE_HALF_WIDTH[eyes];
|
|
110
|
+
return (_jsx(_Fragment, { children: ["l", "r"].map((side) => (_jsx("g", { transform: `translate(${side === "l" ? 50 - gap : 50 + gap} ${y})`, children: _jsxs("g", { className: `aaa-eye aaa-eye-${side}`, "data-gap": gap, "data-h": h, "data-shape": pose, "data-w": w, style: { "--aaa-eye-h": h, "--aaa-eye-w": w }, children: [_jsx(LidMask, { eyes: eyes, id: `${id}-lid-${side}`, side: side }), _jsx("g", { mask: `url(#${id}-lid-${side})`, children: _jsx("path", { className: "aaa-shape", d: eyePath(eyes, pose, side === "l" ? -1 : 1, gap) }) })] }) }, side))) }));
|
|
17
111
|
}
|
|
18
112
|
export function MouthShape({ mouth, slot }) {
|
|
19
113
|
const half = slot.width / 2;
|
|
@@ -28,11 +122,11 @@ export function MouthShape({ mouth, slot }) {
|
|
|
28
122
|
}
|
|
29
123
|
return null;
|
|
30
124
|
}
|
|
31
|
-
export const MOODS = ["happy", "sad", "o", "small"];
|
|
125
|
+
export const MOODS = ["happy", "sad", "o", "small", "flat"];
|
|
32
126
|
export function MoodMouths({ slot }) {
|
|
33
127
|
const half = slot.width / 2;
|
|
34
128
|
const { color, x, y } = slot;
|
|
35
|
-
return (_jsxs(_Fragment, { children: [_jsx("g", { className: "aaa-mood aaa-mood-happy", children: _jsx("path", { d: `M${x - half} ${y - 3}Q${x} ${y + 12} ${x + half} ${y - 3}Z`, fill: color }) }), _jsx("g", { className: "aaa-mood aaa-mood-sad", children: _jsx("path", { d: `M${x - half * 0.8} ${y + 4}Q${x} ${y - 5} ${x + half * 0.8} ${y + 4}`, stroke: color, ...STROKE }) }), _jsx("g", { className: "aaa-mood aaa-mood-o", children: _jsx("ellipse", { cx: x, cy: y + 1, rx: 5, ry: 6.5, fill: color }) }), _jsx("g", { className: "aaa-mood aaa-mood-small", children: _jsx("path", { d: `M${x + 1} ${y}H${x + 9}`, stroke: color, ...STROKE }) })] }));
|
|
129
|
+
return (_jsxs(_Fragment, { children: [_jsx("g", { className: "aaa-mood aaa-mood-happy", children: _jsx("path", { d: `M${x - half} ${y - 3}Q${x} ${y + 12} ${x + half} ${y - 3}Z`, fill: color }) }), _jsx("g", { className: "aaa-mood aaa-mood-sad", children: _jsx("path", { d: `M${x - half * 0.8} ${y + 4}Q${x} ${y - 5} ${x + half * 0.8} ${y + 4}`, stroke: color, ...STROKE }) }), _jsx("g", { className: "aaa-mood aaa-mood-o", children: _jsx("ellipse", { cx: x, cy: y + 1, rx: 5, ry: 6.5, fill: color }) }), _jsx("g", { className: "aaa-mood aaa-mood-small", children: _jsx("path", { d: `M${x + 1} ${y}H${x + 9}`, stroke: color, ...STROKE }) }), _jsx("g", { className: "aaa-mood aaa-mood-flat", children: _jsx("path", { d: `M${x - half * 0.5} ${y + 1}H${x + half * 0.5}`, stroke: color, ...STROKE }) })] }));
|
|
36
130
|
}
|
|
37
131
|
export function AccessoryShape(props) {
|
|
38
132
|
if (props.accessory === "none")
|
package/dist/pointer.d.ts
CHANGED
package/dist/pointer.js
CHANGED
|
@@ -1,23 +1,62 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const LOOK_X = 7;
|
|
2
|
+
const LOOK_Y = 5;
|
|
3
|
+
const HEAD_SHIFT = 2.2;
|
|
4
|
+
const HEAD_TILT = 8;
|
|
5
|
+
const STALE_MS = 900;
|
|
3
6
|
const watchers = new Set();
|
|
4
7
|
let pointer = null;
|
|
5
8
|
let frame = 0;
|
|
9
|
+
let staleTimer;
|
|
10
|
+
const PROPERTIES = [
|
|
11
|
+
"--aaa-look-x",
|
|
12
|
+
"--aaa-look-y",
|
|
13
|
+
"--aaa-look-sx",
|
|
14
|
+
"--aaa-head-x",
|
|
15
|
+
"--aaa-head-y",
|
|
16
|
+
"--aaa-head-r",
|
|
17
|
+
];
|
|
18
|
+
const CENTRED_PHASES = [0, 0.41, 0.7];
|
|
19
|
+
export function restartGazeCentred(svg) {
|
|
20
|
+
const phase = Number.parseFloat(svg.style.getPropertyValue("--aaa-phase")) || 0;
|
|
21
|
+
const cohort = Math.min(Math.floor(phase * CENTRED_PHASES.length), CENTRED_PHASES.length - 1);
|
|
22
|
+
const glancing = svg.dataset.gaze === "follow" || svg.dataset.gaze === "wander";
|
|
23
|
+
svg.style.setProperty("--aaa-gaze-phase", glancing ? String(CENTRED_PHASES[cohort]) : "0");
|
|
24
|
+
}
|
|
25
|
+
function release(svg) {
|
|
26
|
+
if (!svg.hasAttribute("data-pointer"))
|
|
27
|
+
return;
|
|
28
|
+
for (const property of PROPERTIES)
|
|
29
|
+
svg.style.removeProperty(property);
|
|
30
|
+
restartGazeCentred(svg);
|
|
31
|
+
svg.removeAttribute("data-pointer");
|
|
32
|
+
}
|
|
33
|
+
function clamp(value, limit) {
|
|
34
|
+
return Math.max(-limit, Math.min(limit, value));
|
|
35
|
+
}
|
|
6
36
|
function aim() {
|
|
7
37
|
frame = 0;
|
|
8
|
-
const targets = [...watchers]
|
|
38
|
+
const targets = [...watchers]
|
|
39
|
+
.filter((svg) => !svg.hasAttribute("data-offscreen"))
|
|
40
|
+
.map((svg) => ({ svg, bounds: svg.getBoundingClientRect() }));
|
|
9
41
|
for (const { svg, bounds } of targets) {
|
|
10
42
|
if (!pointer || bounds.bottom < 0 || bounds.top > window.innerHeight) {
|
|
11
|
-
svg
|
|
12
|
-
svg.style.removeProperty("--aaa-look-y");
|
|
43
|
+
release(svg);
|
|
13
44
|
continue;
|
|
14
45
|
}
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
46
|
+
const size = Math.max(bounds.width, 1);
|
|
47
|
+
const dx = (pointer.x - (bounds.left + bounds.width / 2)) / size;
|
|
48
|
+
const dy = (pointer.y - (bounds.top + bounds.height / 2)) / size;
|
|
49
|
+
const x = clamp(dx * LOOK_X, LOOK_X);
|
|
50
|
+
const y = clamp(dy * LOOK_Y * 0.9, LOOK_Y);
|
|
51
|
+
const nx = x / LOOK_X;
|
|
52
|
+
const ny = y / LOOK_Y;
|
|
53
|
+
svg.setAttribute("data-pointer", "");
|
|
54
|
+
svg.style.setProperty("--aaa-look-x", `${x.toFixed(2)}px`);
|
|
55
|
+
svg.style.setProperty("--aaa-look-y", `${y.toFixed(2)}px`);
|
|
56
|
+
svg.style.setProperty("--aaa-look-sx", (1 - 0.06 * nx * nx).toFixed(3));
|
|
57
|
+
svg.style.setProperty("--aaa-head-x", `${(nx * HEAD_SHIFT).toFixed(2)}px`);
|
|
58
|
+
svg.style.setProperty("--aaa-head-y", `${(ny * HEAD_SHIFT).toFixed(2)}px`);
|
|
59
|
+
svg.style.setProperty("--aaa-head-r", `${(nx * ny * HEAD_TILT).toFixed(2)}deg`);
|
|
21
60
|
}
|
|
22
61
|
}
|
|
23
62
|
function schedule() {
|
|
@@ -29,8 +68,11 @@ function handleMove(event) {
|
|
|
29
68
|
return;
|
|
30
69
|
pointer = { x: event.clientX, y: event.clientY };
|
|
31
70
|
schedule();
|
|
71
|
+
clearTimeout(staleTimer);
|
|
72
|
+
staleTimer = setTimeout(handleLeave, STALE_MS);
|
|
32
73
|
}
|
|
33
74
|
function handleLeave() {
|
|
75
|
+
clearTimeout(staleTimer);
|
|
34
76
|
pointer = null;
|
|
35
77
|
schedule();
|
|
36
78
|
}
|
|
@@ -42,11 +84,11 @@ export function watchPointer(svg) {
|
|
|
42
84
|
watchers.add(svg);
|
|
43
85
|
return () => {
|
|
44
86
|
watchers.delete(svg);
|
|
45
|
-
svg
|
|
46
|
-
svg.style.removeProperty("--aaa-look-y");
|
|
87
|
+
release(svg);
|
|
47
88
|
if (watchers.size === 0) {
|
|
48
89
|
window.removeEventListener("pointermove", handleMove);
|
|
49
90
|
document.documentElement.removeEventListener("pointerleave", handleLeave);
|
|
91
|
+
clearTimeout(staleTimer);
|
|
50
92
|
pointer = null;
|
|
51
93
|
}
|
|
52
94
|
};
|
package/dist/styles.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AVATAR_CSS
|
|
1
|
+
export declare const AVATAR_CSS: string;
|
package/dist/styles.js
CHANGED
|
@@ -1,61 +1,255 @@
|
|
|
1
|
+
const EASE_OUT = "cubic-bezier(.22,1,.36,1)";
|
|
2
|
+
const EASE_SPRING = "cubic-bezier(.34,1.56,.64,1)";
|
|
3
|
+
const EASE_SMOOTH = "cubic-bezier(.37,0,.63,1)";
|
|
4
|
+
function gazeTransform(x, y) {
|
|
5
|
+
const squash = 1 - 0.06 * Math.min((x / 6) ** 2, 1);
|
|
6
|
+
return `translate(${x}px,${y}px) scaleX(${squash.toFixed(3)})`;
|
|
7
|
+
}
|
|
8
|
+
function glances(name, points, move) {
|
|
9
|
+
const frames = points.flatMap(([percent, x, y], index) => {
|
|
10
|
+
const next = points[index + 1];
|
|
11
|
+
const transform = gazeTransform(x, y);
|
|
12
|
+
const arrive = `${percent}%{transform:${transform};animation-timing-function:linear}`;
|
|
13
|
+
if (!next)
|
|
14
|
+
return [arrive];
|
|
15
|
+
const leave = `${Math.max(percent, next[0] - move)}%{transform:${transform};animation-timing-function:${EASE_OUT}}`;
|
|
16
|
+
return [arrive, leave];
|
|
17
|
+
});
|
|
18
|
+
return `@keyframes ${name}{${frames.join("")}}`;
|
|
19
|
+
}
|
|
20
|
+
function orbit(name, side) {
|
|
21
|
+
const frames = Array.from({ length: 17 }, (_, index) => {
|
|
22
|
+
const angle = (index / 16) * Math.PI * 4;
|
|
23
|
+
const cos = Math.cos(angle);
|
|
24
|
+
const depth = 1 - side * 0.08 * Math.sin(angle);
|
|
25
|
+
const foreshorten = 0.72 + 0.28 * Math.abs(cos);
|
|
26
|
+
const shift = (-side * (1 - cos)).toFixed(4);
|
|
27
|
+
return `${(index / 16) * 100}%{transform:translateX(calc(var(--aaa-gap)*${shift}px)) scale(${(foreshorten * depth).toFixed(3)},${depth.toFixed(3)})}`;
|
|
28
|
+
});
|
|
29
|
+
return `@keyframes ${name}{${frames.join("")}}`;
|
|
30
|
+
}
|
|
31
|
+
function blinks(percents, half) {
|
|
32
|
+
const open = [0, 100, ...percents.flatMap((at) => [at - half, at + half])];
|
|
33
|
+
return `@keyframes aaa-blink{${open.map((at) => `${at.toFixed(2)}%`).join(",")}{transform:scaleY(1)}${percents.map((at) => `${at}%`).join(",")}{transform:scaleY(.08)}}`;
|
|
34
|
+
}
|
|
35
|
+
const lid = (amount) => `translateY(calc(var(--aaa-eye-h)*${amount}px))`;
|
|
36
|
+
const HEART = (side) => `translateX(calc((var(--aaa-gap) + 3.6)*${-side}px)) rotate(${side * 42}deg) scale(calc(7.5/var(--aaa-eye-w)),calc(11.5/var(--aaa-eye-h)))`;
|
|
37
|
+
const timeline = (name, total, stops) => `@keyframes ${name}{${stops.map(([ms, transform]) => `${+((ms / total) * 100).toFixed(3)}%{transform:${transform};animation-timing-function:${EASE_SMOOTH}}`).join("")}}`;
|
|
38
|
+
const peek = (amount) => `translateY(calc(var(--aaa-eye-h)*${amount}px))`;
|
|
39
|
+
const loop = (seconds, easing = "ease-in-out") => `calc(${seconds}s*var(--aaa-tempo,1)) ${easing} calc(-${seconds}s*var(--aaa-phase,0)) infinite`;
|
|
40
|
+
const gazeLoop = (seconds) => `calc(${seconds}s*var(--aaa-tempo,1)) linear calc(-${seconds}s*var(--aaa-gaze-phase,var(--aaa-phase,0))) infinite`;
|
|
1
41
|
export const AVATAR_CSS = `
|
|
2
|
-
.aaa-body-motion,.aaa-react,.aaa-eyes-react,.aaa-eyes-motion,.aaa-blink,.aaa-squish{transform-box:fill-box;transform-origin:center}
|
|
42
|
+
.aaa-body-motion,.aaa-react,.aaa-eyes-react,.aaa-gaze,.aaa-eyes-motion,.aaa-blink,.aaa-squish,.aaa-head,.aaa-look,.aaa-eye{transform-box:fill-box;transform-origin:center}
|
|
3
43
|
.aaa-mouth-rest,.aaa-mood{transform-box:fill-box;transform-origin:center;transition:opacity .2s,transform .2s}
|
|
4
44
|
.aaa-mood{opacity:0}
|
|
5
45
|
.aaa-accessory{transform-box:fill-box;transform-origin:50% 100%;transition:transform .3s ease-out}
|
|
6
46
|
.aaa-accessory[data-accessory=glasses],.aaa-accessory[data-accessory=bowtie]{transform-origin:center}
|
|
7
|
-
.aaa-squish{transition:transform .45s
|
|
47
|
+
.aaa-squish{transition:transform .45s ${EASE_SPRING}}
|
|
8
48
|
.aaa-squish[data-dragging]{transition:none}
|
|
9
49
|
.aaa[data-interactive]{cursor:grab;touch-action:none}
|
|
10
50
|
.aaa[data-interactive]:active{cursor:grabbing}
|
|
11
|
-
.aaa-look{transform:translate(var(--aaa-look-x,0px),var(--aaa-look-y,0px));transition:transform .
|
|
12
|
-
.aaa-
|
|
13
|
-
.aaa
|
|
14
|
-
.aaa
|
|
15
|
-
.aaa
|
|
16
|
-
.aaa
|
|
17
|
-
.aaa
|
|
18
|
-
.aaa
|
|
19
|
-
.aaa
|
|
20
|
-
.aaa[data-
|
|
21
|
-
.aaa[data-
|
|
22
|
-
.aaa[data-
|
|
23
|
-
.aaa[data-
|
|
24
|
-
.aaa[data-
|
|
25
|
-
.aaa[data-
|
|
26
|
-
.aaa[data-
|
|
27
|
-
.aaa[data-
|
|
28
|
-
.aaa[data-
|
|
29
|
-
.aaa[data-
|
|
30
|
-
.aaa[data-
|
|
31
|
-
.aaa[data-
|
|
32
|
-
.aaa[data-
|
|
33
|
-
.aaa[data-
|
|
34
|
-
.aaa[data-
|
|
35
|
-
.aaa[data-
|
|
36
|
-
.aaa[data-
|
|
37
|
-
.aaa[data-
|
|
38
|
-
.aaa[data-
|
|
39
|
-
.aaa[data-
|
|
40
|
-
.aaa[data-
|
|
41
|
-
.aaa[data-
|
|
42
|
-
.aaa[data-
|
|
43
|
-
.aaa[data-
|
|
44
|
-
.aaa[data-
|
|
51
|
+
.aaa-look{transform:translate(var(--aaa-look-x,0px),var(--aaa-look-y,0px)) scaleX(var(--aaa-look-sx,1));transition:transform .28s ${EASE_OUT}}
|
|
52
|
+
.aaa-head{transform:translate(var(--aaa-head-x,0px),var(--aaa-head-y,0px)) rotate(var(--aaa-head-r,0deg));transition:transform .6s ${EASE_SPRING}}
|
|
53
|
+
.aaa-eyes-motion{transition:transform .32s cubic-bezier(.16,1,.3,1)}
|
|
54
|
+
.aaa-eye{transition:transform .32s cubic-bezier(.16,1,.3,1)}
|
|
55
|
+
.aaa-blink{animation:aaa-blink 14s linear infinite}
|
|
56
|
+
.aaa-lid{transform-box:fill-box;transition:transform .32s cubic-bezier(.16,1,.3,1)}
|
|
57
|
+
.aaa-lid-top{transform-origin:50% 100%}
|
|
58
|
+
.aaa-lid-bottom{transform-origin:50% 0}
|
|
59
|
+
.aaa-shape{transition:d .32s cubic-bezier(.16,1,.3,1)}
|
|
60
|
+
.aaa-eye:not([data-shape=eye]) .aaa-lid-top{transform:translateY(-12px)}
|
|
61
|
+
.aaa-eye:not([data-shape=eye]) .aaa-lid-bottom{transform:translateY(12px)}
|
|
62
|
+
.aaa[data-activity=idle] .aaa-body-motion{animation:aaa-drift ${loop(11)}}
|
|
63
|
+
.aaa[data-activity=thinking] .aaa-body-motion{animation:aaa-sway ${loop(3)}}
|
|
64
|
+
.aaa[data-activity=coding] .aaa-body-motion{animation:aaa-bob ${loop(1.6)}}
|
|
65
|
+
.aaa[data-activity=coding][data-expression=neutral] .aaa-blink{animation:none}
|
|
66
|
+
.aaa[data-activity=coding][data-expression=neutral] .aaa-eye-r{animation:aaa-caret 1.06s steps(1) .32s infinite}
|
|
67
|
+
.aaa[data-activity=working] .aaa-body-motion{animation:aaa-bob ${loop(0.9)}}
|
|
68
|
+
.aaa[data-activity=waiting] .aaa-eye-l{animation:aaa-orbit-l 3.2s linear .32s infinite}
|
|
69
|
+
.aaa[data-activity=waiting] .aaa-eye-r{animation:aaa-orbit-r 3.2s linear .32s infinite}
|
|
70
|
+
.aaa[data-activity=waiting][data-expression=neutral] .aaa-blink{animation:none}
|
|
71
|
+
.aaa[data-activity=asking] .aaa-body-motion{transform:rotate(-7deg)}
|
|
72
|
+
.aaa[data-activity=asking][data-expression=neutral] .aaa-eye-r{transform:scale(1.25)}
|
|
73
|
+
.aaa[data-activity=stuck] .aaa-body-motion{transform:rotate(-10deg)}
|
|
74
|
+
.aaa[data-activity=stuck][data-expression=neutral] .aaa-blink{animation:none}
|
|
75
|
+
.aaa[data-activity=sleeping] .aaa-body-motion{animation:aaa-breathe ${loop(4.2)}}
|
|
76
|
+
.aaa[data-activity=sleeping] .aaa-lid-top{transform:${lid(".85")}}
|
|
77
|
+
.aaa[data-activity=sleeping] .aaa-lid-bottom{transform:${lid("-.85")}}
|
|
78
|
+
.aaa[data-activity=sleeping] .aaa-react{transform:translateY(3px)}
|
|
79
|
+
.aaa[data-activity=sleeping][data-expression=neutral] .aaa-blink{animation:none}
|
|
80
|
+
.aaa[data-activity=listening] .aaa-body-motion{animation:aaa-nod ${loop(2.8)}}
|
|
81
|
+
.aaa[data-activity=listening][data-expression=neutral] .aaa-eye{animation:aaa-caret 1.06s steps(1) .32s infinite}
|
|
82
|
+
.aaa[data-activity=listening][data-expression=neutral] .aaa-blink{animation:none}
|
|
83
|
+
.aaa[data-activity=reviewing] .aaa-lid-top{transform:${lid(".78")}}
|
|
84
|
+
.aaa[data-activity=reviewing] .aaa-lid-bottom{transform:${lid("-.78")}}
|
|
85
|
+
.aaa[data-activity=reviewing][data-expression=neutral] .aaa-blink{animation:none}
|
|
86
|
+
.aaa[data-activity=reviewing] .aaa-eye{animation:aaa-inspect ${loop(6.08, "linear")}}
|
|
87
|
+
.aaa[data-activity=reviewing] .aaa-body-motion{animation:aaa-inspect-head ${loop(6.08, "linear")}}
|
|
88
|
+
.aaa[data-activity=speaking] .aaa-body-motion{animation:aaa-bob ${loop(1.4)}}
|
|
89
|
+
.aaa[data-activity=speaking] .aaa-mouth-rest{animation:aaa-talk .32s ease-in-out infinite}
|
|
90
|
+
.aaa[data-gaze=follow]:not([data-pointer]) .aaa-gaze,.aaa[data-gaze=wander] .aaa-gaze{animation:aaa-saccade ${gazeLoop(16)}}
|
|
91
|
+
.aaa[data-gaze=ponder] .aaa-gaze{animation:aaa-ponder ${gazeLoop(3.6)}}
|
|
92
|
+
.aaa[data-gaze=scan] .aaa-gaze{animation:aaa-scan ${gazeLoop(1.6)}}
|
|
93
|
+
.aaa[data-gaze=read] .aaa-gaze{animation:aaa-read ${gazeLoop(4.8)}}
|
|
94
|
+
.aaa[data-gaze=down] .aaa-gaze{animation:aaa-down ${gazeLoop(7)}}
|
|
95
|
+
.aaa[data-gaze=away] .aaa-gaze{animation:aaa-away ${gazeLoop(9)}}
|
|
96
|
+
.aaa[data-activity=searching] .aaa-body-motion{transform:translateY(1px) scale(1.04)}
|
|
97
|
+
.aaa[data-activity=searching][data-expression=neutral] .aaa-eye{animation:aaa-search ${loop(2.6, "linear")}}
|
|
98
|
+
.aaa[data-activity=writing] .aaa-body-motion{animation:aaa-bob ${loop(2.4)}}
|
|
99
|
+
.aaa[data-activity=working] .aaa-antenna-tip{animation:aaa-signal .9s ease-in-out infinite}
|
|
100
|
+
.aaa[data-activity=thinking][data-expression=neutral] .aaa-mouth-rest{opacity:0}
|
|
101
|
+
.aaa[data-activity=thinking][data-expression=neutral] .aaa-mood-small{opacity:1}
|
|
102
|
+
.aaa[data-activity=thinking] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){animation:aaa-acc-sway 2.4s ease-in-out infinite}
|
|
103
|
+
.aaa[data-activity=thinking] .aaa-accessory[data-accessory=glasses]{animation:aaa-glasses-think 2.4s ease-in-out infinite}
|
|
104
|
+
.aaa[data-activity=working] .aaa-mouth-rest{transform:scaleX(.7)}
|
|
105
|
+
.aaa[data-activity=working] .aaa-accessory[data-accessory=bowtie]{animation:aaa-wobble .9s ease-in-out infinite}
|
|
106
|
+
.aaa[data-activity=waiting][data-expression=neutral] .aaa-mouth-rest{opacity:0}
|
|
107
|
+
.aaa[data-activity=waiting][data-expression=neutral] .aaa-mood-happy{opacity:1}
|
|
108
|
+
.aaa[data-activity=waiting] .aaa-accessory:not([data-accessory=glasses]){animation:aaa-wobble 1.6s ease-in-out infinite}
|
|
109
|
+
.aaa[data-activity=stuck][data-expression=neutral] .aaa-mouth-rest{opacity:0}
|
|
110
|
+
.aaa[data-activity=stuck][data-expression=neutral] .aaa-mood-sad{opacity:1}
|
|
111
|
+
.aaa[data-activity=stuck] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(28deg)}
|
|
112
|
+
.aaa[data-activity=stuck] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(3px) rotate(8deg)}
|
|
113
|
+
.aaa[data-activity=stuck] .aaa-accessory[data-accessory=bowtie]{transform:rotate(18deg)}
|
|
114
|
+
.aaa[data-activity=sleeping][data-expression=neutral] .aaa-mouth-rest{opacity:0}
|
|
115
|
+
.aaa[data-activity=sleeping][data-expression=neutral] .aaa-mood-o{opacity:1;animation:aaa-snore 4.2s ease-in-out infinite}
|
|
116
|
+
.aaa[data-activity=sleeping] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(-35deg)}
|
|
117
|
+
.aaa[data-activity=sleeping] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(5px)}
|
|
118
|
+
.aaa:not([data-expression=neutral]) .aaa-mouth-rest{opacity:0}
|
|
119
|
+
.aaa:is([data-expression=happy],[data-expression=love]) .aaa-mood-happy{opacity:1}
|
|
120
|
+
.aaa:is([data-expression=sad],[data-expression=angry]) .aaa-mood-sad{opacity:1}
|
|
121
|
+
.aaa[data-expression=confused] .aaa-mood-small{opacity:1}
|
|
122
|
+
.aaa[data-expression=tired] .aaa-mood-flat{opacity:1}
|
|
123
|
+
.aaa[data-expression=curious] .aaa-mood-o{opacity:1;transform:scale(.6)}
|
|
124
|
+
.aaa:not([data-expression=neutral]) .aaa-lid{transform:none}
|
|
125
|
+
.aaa:not([data-expression=neutral]) .aaa-eye{animation:none}
|
|
126
|
+
.aaa[data-expression=happy] .aaa-lid-bottom{transform:${lid("-1")}}
|
|
127
|
+
.aaa[data-expression=sad] .aaa-lid-top.aaa-lid-l{transform:${lid(".8")} rotate(-16deg)}
|
|
128
|
+
.aaa[data-expression=sad] .aaa-lid-top.aaa-lid-r{transform:${lid(".8")} rotate(16deg)}
|
|
129
|
+
.aaa[data-expression=angry] .aaa-lid-top.aaa-lid-l{transform:${lid(".83")} rotate(16deg)}
|
|
130
|
+
.aaa[data-expression=angry] .aaa-lid-top.aaa-lid-r{transform:${lid(".83")} rotate(-16deg)}
|
|
131
|
+
.aaa[data-expression=confused] .aaa-lid-top.aaa-lid-r{transform:${lid(".55")} rotate(-8deg)}
|
|
132
|
+
.aaa[data-expression=love] .aaa-eye{transform-origin:50% 100%}
|
|
133
|
+
.aaa[data-expression=love] .aaa-eye-l{transform:${HEART(-1)}}
|
|
134
|
+
.aaa[data-expression=love] .aaa-eye-r{transform:${HEART(1)}}
|
|
135
|
+
.aaa[data-expression=love] .aaa-eyes-react{animation:aaa-heartbeat 1.52s infinite}
|
|
136
|
+
.aaa[data-expression=tired] .aaa-lid-top.aaa-lid-l{transform:${lid(".6")} rotate(-7deg)}
|
|
137
|
+
.aaa[data-expression=tired] .aaa-lid-top.aaa-lid-r{transform:${lid(".6")} rotate(7deg)}
|
|
138
|
+
.aaa[data-expression=tired] .aaa-lid-bottom{transform:${lid("-.12")}}
|
|
139
|
+
.aaa[data-expression=curious] .aaa-eyes-motion{transform:scale(1.12)}
|
|
140
|
+
.aaa[data-reacting] .aaa-gaze,.aaa[data-reacting] .aaa-blink,.aaa[data-reacting] .aaa-eye{animation:none}
|
|
141
|
+
.aaa[data-reacting] .aaa-look{--aaa-look-x:0px;--aaa-look-y:0px;--aaa-look-sx:1}
|
|
142
|
+
.aaa[data-reacting] .aaa-head{--aaa-head-x:0px;--aaa-head-y:0px;--aaa-head-r:0deg}
|
|
45
143
|
.aaa[data-blink=off] .aaa-blink{animation:none}
|
|
46
144
|
.aaa[data-motion=off] *{animation:none!important}
|
|
47
|
-
|
|
145
|
+
.aaa[data-offscreen] *{animation-play-state:paused!important}
|
|
146
|
+
${blinks([3, 21, 47, 66, 88], 0.6)}
|
|
147
|
+
${glances("aaa-saccade", [
|
|
148
|
+
[0, 0, 0],
|
|
149
|
+
[9, -4, -1],
|
|
150
|
+
[22, 3, 2],
|
|
151
|
+
[33, 5, -3],
|
|
152
|
+
[41, 0, 0],
|
|
153
|
+
[52, -5, -4],
|
|
154
|
+
[61, 5, -4],
|
|
155
|
+
[70, 0, 0],
|
|
156
|
+
[78, -3, 3],
|
|
157
|
+
[90, 2, -1],
|
|
158
|
+
[100, 0, 0],
|
|
159
|
+
], 1.2)}
|
|
160
|
+
${glances("aaa-ponder", [
|
|
161
|
+
[0, 0, 0],
|
|
162
|
+
[8, -5, -4],
|
|
163
|
+
[50, 5, -4],
|
|
164
|
+
[92, 0, 0],
|
|
165
|
+
[100, 0, 0],
|
|
166
|
+
], 7)}
|
|
167
|
+
${glances("aaa-read", [
|
|
168
|
+
[0, -5, -2],
|
|
169
|
+
[8, -2, -2],
|
|
170
|
+
[16, 1, -2],
|
|
171
|
+
[24, 4, -2],
|
|
172
|
+
[33, -5, 0.5],
|
|
173
|
+
[41, -2, 0.5],
|
|
174
|
+
[49, 1, 0.5],
|
|
175
|
+
[57, 4, 0.5],
|
|
176
|
+
[66, -5, 3],
|
|
177
|
+
[74, -2, 3],
|
|
178
|
+
[82, 1, 3],
|
|
179
|
+
[90, 4, 3],
|
|
180
|
+
[100, -5, -2],
|
|
181
|
+
], 2)}
|
|
182
|
+
${timeline("aaa-inspect", 6080, [
|
|
183
|
+
[0, peek("0")],
|
|
184
|
+
[880, peek("0")],
|
|
185
|
+
[1280, peek(".55")],
|
|
186
|
+
[1840, peek(".55")],
|
|
187
|
+
[2000, peek("-.55")],
|
|
188
|
+
[2580, peek("-.55")],
|
|
189
|
+
[2720, peek("0")],
|
|
190
|
+
[3480, peek("0")],
|
|
191
|
+
[3620, peek(".55")],
|
|
192
|
+
[4240, peek(".55")],
|
|
193
|
+
[4420, peek("0")],
|
|
194
|
+
[6080, peek("0")],
|
|
195
|
+
])}
|
|
196
|
+
${timeline("aaa-inspect-head", 6080, [
|
|
197
|
+
[0, "translateY(0)"],
|
|
198
|
+
[880, "translateY(0)"],
|
|
199
|
+
[1280, "translateY(2.5px)"],
|
|
200
|
+
[1840, "translateY(2.5px)"],
|
|
201
|
+
[2000, "translateY(-2px)"],
|
|
202
|
+
[2580, "translateY(-2px)"],
|
|
203
|
+
[2720, "translateY(0)"],
|
|
204
|
+
[6080, "translateY(0)"],
|
|
205
|
+
])}
|
|
206
|
+
${glances("aaa-down", [
|
|
207
|
+
[0, -2, 5],
|
|
208
|
+
[30, 1, 5.5],
|
|
209
|
+
[55, 3, 5],
|
|
210
|
+
[70, 3, 5],
|
|
211
|
+
[85, -1, 5.5],
|
|
212
|
+
[100, -2, 5],
|
|
213
|
+
], 8)}
|
|
214
|
+
${glances("aaa-away", [
|
|
215
|
+
[0, 6, 1.5],
|
|
216
|
+
[40, 6, 2],
|
|
217
|
+
[48, 5.5, -1],
|
|
218
|
+
[72, 6, 1.5],
|
|
219
|
+
[76, 0, 0],
|
|
220
|
+
[84, 0, 0],
|
|
221
|
+
[88, 6, 1.5],
|
|
222
|
+
[100, 6, 1.5],
|
|
223
|
+
], 1.5)}
|
|
224
|
+
${glances("aaa-search", [
|
|
225
|
+
[0, -5, -2],
|
|
226
|
+
[10, 4, -3],
|
|
227
|
+
[20, 4, -3],
|
|
228
|
+
[26, -3, 2],
|
|
229
|
+
[38, -3, 2],
|
|
230
|
+
[44, 5, 1],
|
|
231
|
+
[56, 5, 1],
|
|
232
|
+
[62, -1, -4],
|
|
233
|
+
[74, -1, -4],
|
|
234
|
+
[80, -5, 3],
|
|
235
|
+
[92, -5, 3],
|
|
236
|
+
[100, -5, -2],
|
|
237
|
+
], 2.5)}
|
|
238
|
+
@keyframes aaa-scan{0%{transform:${gazeTransform(-4, 1)};animation-timing-function:cubic-bezier(.45,.05,.55,.95)}70%{transform:${gazeTransform(4, 1)};animation-timing-function:${EASE_OUT}}80%,100%{transform:${gazeTransform(-4, 1)}}}
|
|
239
|
+
${orbit("aaa-orbit-l", -1)}
|
|
240
|
+
${orbit("aaa-orbit-r", 1)}
|
|
241
|
+
@keyframes aaa-heartbeat{0%,24%,48%,100%{transform:scale(1)}6%{transform:scale(1.155)}18%{transform:scale(1.093)}}
|
|
48
242
|
@keyframes aaa-drift{0%,100%{transform:translate(0,0) rotate(0deg) scale(1)}20%{transform:translate(4px,-3px) rotate(5deg) scale(1.02,.98)}45%{transform:translate(-2px,-5px) rotate(-3deg) scale(.98,1.02)}70%{transform:translate(-5px,-1px) rotate(-6deg) scale(1.02,.98)}85%{transform:translate(-1px,1px) rotate(2deg) scale(1)}}
|
|
49
243
|
@keyframes aaa-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
|
|
50
244
|
@keyframes aaa-sway{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}
|
|
51
|
-
@keyframes aaa-ponder{0%,100%{transform:translate(-5px,-6px)}50%{transform:translate(5px,-6px)}}
|
|
52
|
-
@keyframes aaa-scan{0%,100%{transform:translateX(-5px)}50%{transform:translateX(5px)}}
|
|
53
245
|
@keyframes aaa-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.035,.97)}}
|
|
54
246
|
@keyframes aaa-signal{0%,100%{opacity:1}50%{opacity:.25}}
|
|
55
247
|
@keyframes aaa-acc-sway{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}
|
|
56
248
|
@keyframes aaa-wobble{0%,100%{transform:rotate(-12deg)}50%{transform:rotate(12deg)}}
|
|
57
249
|
@keyframes aaa-glasses-think{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
|
|
58
250
|
@keyframes aaa-snore{0%,100%{transform:scale(.7)}50%{transform:scale(1.1)}}
|
|
59
|
-
@keyframes aaa-
|
|
251
|
+
@keyframes aaa-nod{0%,100%{transform:rotate(-7deg)}50%{transform:rotate(-3deg) translateY(1px)}}
|
|
252
|
+
@keyframes aaa-talk{0%,100%{transform:scaleY(1)}50%{transform:scaleY(.4)}}
|
|
253
|
+
@keyframes aaa-caret{0%{opacity:1}50%{opacity:0}}
|
|
60
254
|
@media (prefers-reduced-motion:reduce){.aaa *{animation:none!important;transition:none!important}}
|
|
61
255
|
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function watchVisibility(svg: SVGSVGElement): () => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
let observer = null;
|
|
2
|
+
let watched = 0;
|
|
3
|
+
function handleEntries(entries) {
|
|
4
|
+
for (const entry of entries) {
|
|
5
|
+
if (entry.isIntersecting)
|
|
6
|
+
entry.target.removeAttribute("data-offscreen");
|
|
7
|
+
else
|
|
8
|
+
entry.target.setAttribute("data-offscreen", "");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function watchVisibility(svg) {
|
|
12
|
+
if (typeof IntersectionObserver !== "function")
|
|
13
|
+
return () => { };
|
|
14
|
+
observer ??= new IntersectionObserver(handleEntries);
|
|
15
|
+
observer.observe(svg);
|
|
16
|
+
watched += 1;
|
|
17
|
+
return () => {
|
|
18
|
+
observer?.unobserve(svg);
|
|
19
|
+
svg.removeAttribute("data-offscreen");
|
|
20
|
+
watched -= 1;
|
|
21
|
+
if (watched === 0) {
|
|
22
|
+
observer?.disconnect();
|
|
23
|
+
observer = null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
package/package.json
CHANGED
package/dist/value.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type Accessory, type Eyes, type Fill, type Mouth, type Shape } from "./spec.js";
|
|
2
|
-
export interface AvatarValue {
|
|
3
|
-
accessory?: Accessory;
|
|
4
|
-
background?: string;
|
|
5
|
-
body?: string;
|
|
6
|
-
eyes?: Eyes;
|
|
7
|
-
fill?: Fill;
|
|
8
|
-
mouth?: Mouth;
|
|
9
|
-
shape?: Shape;
|
|
10
|
-
}
|
|
11
|
-
export type ParsedAvatarValue = {
|
|
12
|
-
ok: true;
|
|
13
|
-
value: AvatarValue;
|
|
14
|
-
} | {
|
|
15
|
-
ok: false;
|
|
16
|
-
error: string;
|
|
17
|
-
};
|
|
18
|
-
export declare const AVATAR_VALUE_MAX_LENGTH = 200;
|
|
19
|
-
export declare function parseAvatarValue(raw: string): ParsedAvatarValue;
|
|
20
|
-
export declare function formatAvatarValue(value: AvatarValue): string;
|