aaavatars 1.0.0 → 2.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 CHANGED
@@ -40,7 +40,7 @@ await avatar.current?.play("done");
40
40
  | `blink` / `look` / `motion` | turn blinking, pointer following or looping off |
41
41
  | `interactive` | click, double-click, drag-to-squish and press-and-hold reactions |
42
42
 
43
- Unset `shape`, `eyes`, `mouth`, `accessory` and colours come from the name.
43
+ Unset `shape`, `eyes` and colours come from the name. `mouth` and `accessory` stay off until you set them. Each name blinks on its own rhythm, in CSS only.
44
44
 
45
45
  `play(event)` accepts `acknowledge`, `handoff`, `done`, `success`, `failure`, `surprise`, `wake` and resolves when the animation ends. Under `prefers-reduced-motion`, or while the page is hidden, it resolves immediately.
46
46
 
package/dist/Avatar.js CHANGED
@@ -157,7 +157,10 @@ export const Avatar = forwardRef(function Avatar({ accessory, background, badge,
157
157
  if (interactive)
158
158
  moveDrag(event);
159
159
  }
160
- : undefined, onPointerUp: interactive ? endDrag : undefined, children: [label ? _jsx("title", { children: label }) : null, _jsx("style", { children: AVATAR_CSS }), _jsxs("defs", { children: [framed ? (_jsx("clipPath", { id: `${uid}-frame`, children: _jsx("rect", { width: 100, height: 100, rx: radius }) })) : null, fill === "gradient" ? (_jsxs("linearGradient", { id: `${uid}-fill`, x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: shadeHex(spec.body, 0.18) }), _jsx("stop", { offset: "100%", stopColor: shadeHex(spec.body, -0.22) })] })) : null, shading > 0 ? (_jsxs("radialGradient", { id: `${uid}-shade`, cx: "0.35", cy: "0.3", r: "0.85", children: [_jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: 0.55 * shading }), _jsx("stop", { offset: "45%", stopColor: "#ffffff", stopOpacity: 0 }), _jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: 0.35 * shading })] })) : null] }), framed ? (_jsx("rect", { "data-frame": "", width: 100, height: 100, rx: radius, fill: spec.background })) : null, _jsx("g", { clipPath: framed ? `url(#${uid}-frame)` : undefined, children: showImage ? (_jsx("g", { ref: bodyRef, className: "aaa-react", children: _jsx("image", { "data-image": "", height: 100, href: src, preserveAspectRatio: "xMidYMid slice", width: 100, onError: () => setImageFailed(true) }) })) : (_jsx("g", { transform: placement, children: _jsx("g", { ref: squishRef, className: "aaa-squish", children: _jsx("g", { className: "aaa-body-motion", children: _jsxs("g", { ref: bodyRef, className: "aaa-react", children: [accessoryBehind ? (_jsx(AccessoryShape, { accent: spec.accent, accessory: spec.accessory, body: spec.body, geometry: geometry })) : null, _jsx("path", { d: geometry.path, fill: bodyFill, stroke: bodyFill, strokeLinejoin: "round", strokeWidth: 8 }), shading > 0 ? (_jsx("path", { d: geometry.path, fill: `url(#${uid}-shade)`, stroke: `url(#${uid}-shade)`, strokeLinejoin: "round", strokeWidth: 8 })) : null, _jsx("g", { ref: eyesRef, className: "aaa-eyes-react", fill: spec.eyeColor, children: _jsx("g", { className: "aaa-look", children: content === "initial" ? (_jsx("text", { dominantBaseline: "central", fontFamily: "system-ui, sans-serif", fontSize: 38, fontWeight: 700, textAnchor: "middle", x: 50, y: (geometry.top + geometry.bottom) / 2 + 2, children: name.trim().charAt(0).toUpperCase() })) : (_jsx("g", { className: "aaa-eyes-motion", children: _jsx("g", { className: "aaa-blink", children: _jsx(EyePair, { eyes: spec.eyes, gap: geometry.eyeGap, y: geometry.eyeY }) }) })) }) }), hasMouth ? (_jsxs("g", { className: "aaa-look", children: [_jsx("g", { className: "aaa-mouth-rest", children: renderMouth ? (renderMouth(slot)) : (_jsx(MouthShape, { mouth: spec.mouth, slot: slot })) }), _jsx(MoodMouths, { slot: slot })] })) : null, !accessoryBehind && (spec.accessory !== "glasses" || content === "face") ? (_jsx(AccessoryShape, { accent: spec.accent, accessory: spec.accessory, body: spec.body, geometry: geometry })) : null] }) }) }) })) })] }));
160
+ : undefined, onPointerUp: interactive ? endDrag : undefined, children: [label ? _jsx("title", { children: label }) : null, _jsx("style", { children: AVATAR_CSS }), _jsxs("defs", { children: [framed ? (_jsx("clipPath", { id: `${uid}-frame`, children: _jsx("rect", { width: 100, height: 100, rx: radius }) })) : null, fill === "gradient" ? (_jsxs("linearGradient", { id: `${uid}-fill`, x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: shadeHex(spec.body, 0.18) }), _jsx("stop", { offset: "100%", stopColor: shadeHex(spec.body, -0.22) })] })) : null, shading > 0 ? (_jsxs("radialGradient", { id: `${uid}-shade`, cx: "0.35", cy: "0.3", r: "0.85", children: [_jsx("stop", { offset: "0%", stopColor: "#ffffff", stopOpacity: 0.55 * shading }), _jsx("stop", { offset: "45%", stopColor: "#ffffff", stopOpacity: 0 }), _jsx("stop", { offset: "100%", stopColor: "#000000", stopOpacity: 0.35 * shading })] })) : null] }), framed ? (_jsx("rect", { "data-frame": "", width: 100, height: 100, rx: radius, fill: spec.background })) : null, _jsx("g", { clipPath: framed ? `url(#${uid}-frame)` : undefined, children: showImage ? (_jsx("g", { ref: bodyRef, className: "aaa-react", children: _jsx("image", { "data-image": "", height: 100, href: src, preserveAspectRatio: "xMidYMid slice", width: 100, onError: () => setImageFailed(true) }) })) : (_jsx("g", { transform: placement, children: _jsx("g", { ref: squishRef, className: "aaa-squish", children: _jsx("g", { className: "aaa-body-motion", children: _jsxs("g", { ref: bodyRef, className: "aaa-react", children: [accessoryBehind ? (_jsx(AccessoryShape, { accent: spec.accent, accessory: spec.accessory, body: spec.body, geometry: geometry })) : null, _jsx("path", { d: geometry.path, fill: bodyFill, stroke: bodyFill, strokeLinejoin: "round", strokeWidth: 8 }), shading > 0 ? (_jsx("path", { d: geometry.path, fill: `url(#${uid}-shade)`, stroke: `url(#${uid}-shade)`, strokeLinejoin: "round", strokeWidth: 8 })) : null, _jsx("g", { ref: eyesRef, className: "aaa-eyes-react", fill: spec.eyeColor, children: _jsx("g", { className: "aaa-look", children: content === "initial" ? (_jsx("text", { dominantBaseline: "central", fontFamily: "system-ui, sans-serif", fontSize: 38, fontWeight: 700, textAnchor: "middle", x: 50, y: (geometry.top + geometry.bottom) / 2 + 2, children: name.trim().charAt(0).toUpperCase() })) : (_jsx("g", { className: "aaa-eyes-motion", children: _jsx("g", { className: "aaa-blink", style: {
161
+ animationDelay: `${spec.blinkDelay}s`,
162
+ animationDuration: `${spec.blinkDuration}s`,
163
+ }, children: _jsx(EyePair, { eyes: spec.eyes, gap: geometry.eyeGap, y: geometry.eyeY }) }) })) }) }), hasMouth ? (_jsxs("g", { className: "aaa-look", children: [_jsx("g", { className: "aaa-mouth-rest", children: renderMouth ? (renderMouth(slot)) : (_jsx(MouthShape, { mouth: spec.mouth, slot: slot })) }), _jsx(MoodMouths, { slot: slot })] })) : null, !accessoryBehind && (spec.accessory !== "glasses" || content === "face") ? (_jsx(AccessoryShape, { accent: spec.accent, accessory: spec.accessory, body: spec.body, geometry: geometry })) : null] }) }) }) })) })] }));
161
164
  if (!badge)
162
165
  return svg;
163
166
  return (_jsxs("span", { className: className, style: {
package/dist/spec.d.ts CHANGED
@@ -13,6 +13,8 @@ export interface AvatarSpec {
13
13
  accent: string;
14
14
  accessory: Accessory;
15
15
  background: string;
16
+ blinkDelay: number;
17
+ blinkDuration: number;
16
18
  body: string;
17
19
  eyeColor: string;
18
20
  eyes: Eyes;
package/dist/spec.js CHANGED
@@ -12,18 +12,8 @@ export const EYES = ["round", "dot", "tall", "wide"];
12
12
  export const MOUTHS = ["none", "smile", "flat", "open"];
13
13
  export const ACCESSORIES = ["none", "antenna", "sprout", "hat", "glasses", "bowtie"];
14
14
  export const FILLS = ["solid", "gradient"];
15
- const HASHED_MOUTHS = ["none", "none", "none", "smile", "flat", "open"];
16
- const HASHED_ACCESSORIES = [
17
- "none",
18
- "none",
19
- "none",
20
- "none",
21
- "antenna",
22
- "sprout",
23
- "hat",
24
- "glasses",
25
- "bowtie",
26
- ];
15
+ const BLINK_MIN_SECONDS = 5;
16
+ const BLINK_SPREAD_SECONDS = 4;
27
17
  export const DEFAULT_COLORS = ["#264653", "#2A9D8F", "#E9C46A", "#F4A261", "#E76F51"];
28
18
  function hash(value) {
29
19
  let result = 2166136261;
@@ -44,6 +34,9 @@ function seededRandom(seed) {
44
34
  function pick(items, random) {
45
35
  return items[Math.floor(random() * items.length)];
46
36
  }
37
+ function roundTenth(value) {
38
+ return Math.round(value * 10) / 10;
39
+ }
47
40
  function signedRange(random, limit) {
48
41
  return Math.round((random() * 2 - 1) * limit);
49
42
  }
@@ -67,20 +60,22 @@ export function createSpec(name, options = {}) {
67
60
  const offsetX = signedRange(random, 6);
68
61
  const offsetY = signedRange(random, 5);
69
62
  const rotate = signedRange(random, 12);
70
- const mouth = pick(HASHED_MOUTHS, random);
71
- const accessory = pick(HASHED_ACCESSORIES, random);
72
63
  const accentCandidates = colors.filter((_, index) => index !== bodyIndex && index !== backgroundIndex);
73
64
  const accent = accentCandidates.length ? pick(accentCandidates, random) : colors[0];
65
+ const blinkDuration = roundTenth(BLINK_MIN_SECONDS + random() * BLINK_SPREAD_SECONDS);
66
+ const blinkDelay = -roundTenth(random() * blinkDuration);
74
67
  const background = options.background ?? colors[backgroundIndex];
75
68
  const body = options.body ?? colors[bodyIndex];
76
69
  return {
77
70
  accent,
78
- accessory: options.accessory ?? accessory,
71
+ accessory: options.accessory ?? "none",
79
72
  background,
73
+ blinkDelay,
74
+ blinkDuration,
80
75
  body,
81
76
  eyeColor: relativeLuminance(body) > 0.4 ? "#141414" : "#FFFFFF",
82
77
  eyes: options.eyes ?? eyes,
83
- mouth: options.mouth ?? mouth,
78
+ mouth: options.mouth ?? "none",
84
79
  offsetX,
85
80
  offsetY,
86
81
  rotate,
package/dist/styles.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const AVATAR_CSS = "\n.aaa-body-motion,.aaa-react,.aaa-eyes-react,.aaa-eyes-motion,.aaa-blink,.aaa-squish{transform-box:fill-box;transform-origin:center}\n.aaa-mouth-rest,.aaa-mood{transform-box:fill-box;transform-origin:center;transition:opacity .2s,transform .2s}\n.aaa-mood{opacity:0}\n.aaa-accessory{transform-box:fill-box;transform-origin:50% 100%;transition:transform .3s ease-out}\n.aaa-accessory[data-accessory=glasses],.aaa-accessory[data-accessory=bowtie]{transform-origin:center}\n.aaa-squish{transition:transform .45s cubic-bezier(.34,1.56,.64,1)}\n.aaa-squish[data-dragging]{transition:none}\n.aaa[data-interactive]{cursor:grab;touch-action:none}\n.aaa[data-interactive]:active{cursor:grabbing}\n.aaa-look{transform:translate(var(--aaa-look-x,0px),var(--aaa-look-y,0px));transition:transform .25s ease-out}\n.aaa-blink{animation:aaa-blink 4.6s infinite}\n.aaa[data-status=idle] .aaa-body-motion{animation:aaa-bob 3.6s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-body-motion{animation:aaa-sway 3s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-eyes-motion{transform:translate(-5px,-6px);animation:aaa-ponder 2.4s ease-in-out infinite}\n.aaa[data-status=working] .aaa-body-motion{animation:aaa-bob .9s ease-in-out infinite}\n.aaa[data-status=working] .aaa-eyes-motion{animation:aaa-scan 1.1s ease-in-out infinite}\n.aaa[data-status=waiting] .aaa-body-motion{animation:aaa-hop 1.6s ease-out infinite}\n.aaa[data-status=waiting] .aaa-eyes-motion{transform:scale(1.18)}\n.aaa[data-status=error] .aaa-body-motion{transform:rotate(-10deg)}\n.aaa[data-status=error] .aaa-eyes-motion{transform:scaleY(.25)}\n.aaa[data-status=error] .aaa-blink{animation:none}\n.aaa[data-status=sleeping] .aaa-body-motion{animation:aaa-breathe 4.2s ease-in-out infinite}\n.aaa[data-status=sleeping] .aaa-eyes-motion{transform:translateY(2px) scaleY(.12)}\n.aaa[data-status=sleeping] .aaa-blink{animation:none}\n.aaa[data-status=working] .aaa-antenna-tip{animation:aaa-signal .9s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=thinking] .aaa-mood-small{opacity:1}\n.aaa[data-status=thinking] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){animation:aaa-acc-sway 2.4s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-accessory[data-accessory=glasses]{animation:aaa-glasses-think 2.4s ease-in-out infinite}\n.aaa[data-status=working] .aaa-mouth-rest{transform:scaleX(.7)}\n.aaa[data-status=working] .aaa-accessory[data-accessory=bowtie]{animation:aaa-wobble .9s ease-in-out infinite}\n.aaa[data-status=waiting] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=waiting] .aaa-mood-happy{opacity:1}\n.aaa[data-status=waiting] .aaa-accessory:not([data-accessory=glasses]){animation:aaa-wobble 1.6s ease-in-out infinite}\n.aaa[data-status=error] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=error] .aaa-mood-sad{opacity:1}\n.aaa[data-status=error] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(28deg)}\n.aaa[data-status=error] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(3px) rotate(8deg)}\n.aaa[data-status=error] .aaa-accessory[data-accessory=bowtie]{transform:rotate(18deg)}\n.aaa[data-status=sleeping] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=sleeping] .aaa-mood-o{opacity:1;animation:aaa-snore 4.2s ease-in-out infinite}\n.aaa[data-status=sleeping] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(-35deg)}\n.aaa[data-status=sleeping] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(5px)}\n.aaa[data-blink=off] .aaa-blink{animation:none}\n.aaa[data-motion=off] *{animation:none!important}\n@keyframes aaa-blink{0%,93%,100%{transform:scaleY(1)}96%{transform:scaleY(.1)}}\n@keyframes aaa-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}\n@keyframes aaa-sway{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}\n@keyframes aaa-ponder{0%,100%{transform:translate(-5px,-6px)}50%{transform:translate(5px,-6px)}}\n@keyframes aaa-scan{0%,100%{transform:translateX(-5px)}50%{transform:translateX(5px)}}\n@keyframes aaa-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.035,.97)}}\n@keyframes aaa-signal{0%,100%{opacity:1}50%{opacity:.25}}\n@keyframes aaa-acc-sway{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}\n@keyframes aaa-wobble{0%,100%{transform:rotate(-12deg)}50%{transform:rotate(12deg)}}\n@keyframes aaa-glasses-think{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}\n@keyframes aaa-snore{0%,100%{transform:scale(.7)}50%{transform:scale(1.1)}}\n@keyframes aaa-hop{0%,55%,100%{transform:translateY(0)}68%{transform:translateY(-7px)}80%{transform:translateY(0)}90%{transform:translateY(-3px)}}\n@media (prefers-reduced-motion:reduce){.aaa *{animation:none!important;transition:none!important}}\n";
1
+ export declare const AVATAR_CSS = "\n.aaa-body-motion,.aaa-react,.aaa-eyes-react,.aaa-eyes-motion,.aaa-blink,.aaa-squish{transform-box:fill-box;transform-origin:center}\n.aaa-mouth-rest,.aaa-mood{transform-box:fill-box;transform-origin:center;transition:opacity .2s,transform .2s}\n.aaa-mood{opacity:0}\n.aaa-accessory{transform-box:fill-box;transform-origin:50% 100%;transition:transform .3s ease-out}\n.aaa-accessory[data-accessory=glasses],.aaa-accessory[data-accessory=bowtie]{transform-origin:center}\n.aaa-squish{transition:transform .45s cubic-bezier(.34,1.56,.64,1)}\n.aaa-squish[data-dragging]{transition:none}\n.aaa[data-interactive]{cursor:grab;touch-action:none}\n.aaa[data-interactive]:active{cursor:grabbing}\n.aaa-look{transform:translate(var(--aaa-look-x,0px),var(--aaa-look-y,0px));transition:transform .25s ease-out}\n.aaa-blink{animation:aaa-blink 7s infinite}\n.aaa[data-status=idle] .aaa-body-motion{animation:aaa-bob 3.6s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-body-motion{animation:aaa-sway 3s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-eyes-motion{transform:translate(-5px,-6px);animation:aaa-ponder 2.4s ease-in-out infinite}\n.aaa[data-status=working] .aaa-body-motion{animation:aaa-bob .9s ease-in-out infinite}\n.aaa[data-status=working] .aaa-eyes-motion{animation:aaa-scan 1.1s ease-in-out infinite}\n.aaa[data-status=waiting] .aaa-body-motion{animation:aaa-hop 1.6s ease-out infinite}\n.aaa[data-status=waiting] .aaa-eyes-motion{transform:scale(1.18)}\n.aaa[data-status=error] .aaa-body-motion{transform:rotate(-10deg)}\n.aaa[data-status=error] .aaa-eyes-motion{transform:scaleY(.25)}\n.aaa[data-status=error] .aaa-blink{animation:none}\n.aaa[data-status=sleeping] .aaa-body-motion{animation:aaa-breathe 4.2s ease-in-out infinite}\n.aaa[data-status=sleeping] .aaa-eyes-motion{transform:translateY(2px) scaleY(.12)}\n.aaa[data-status=sleeping] .aaa-blink{animation:none}\n.aaa[data-status=working] .aaa-antenna-tip{animation:aaa-signal .9s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=thinking] .aaa-mood-small{opacity:1}\n.aaa[data-status=thinking] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){animation:aaa-acc-sway 2.4s ease-in-out infinite}\n.aaa[data-status=thinking] .aaa-accessory[data-accessory=glasses]{animation:aaa-glasses-think 2.4s ease-in-out infinite}\n.aaa[data-status=working] .aaa-mouth-rest{transform:scaleX(.7)}\n.aaa[data-status=working] .aaa-accessory[data-accessory=bowtie]{animation:aaa-wobble .9s ease-in-out infinite}\n.aaa[data-status=waiting] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=waiting] .aaa-mood-happy{opacity:1}\n.aaa[data-status=waiting] .aaa-accessory:not([data-accessory=glasses]){animation:aaa-wobble 1.6s ease-in-out infinite}\n.aaa[data-status=error] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=error] .aaa-mood-sad{opacity:1}\n.aaa[data-status=error] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(28deg)}\n.aaa[data-status=error] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(3px) rotate(8deg)}\n.aaa[data-status=error] .aaa-accessory[data-accessory=bowtie]{transform:rotate(18deg)}\n.aaa[data-status=sleeping] .aaa-mouth-rest{opacity:0}\n.aaa[data-status=sleeping] .aaa-mood-o{opacity:1;animation:aaa-snore 4.2s ease-in-out infinite}\n.aaa[data-status=sleeping] .aaa-accessory:is([data-accessory=antenna],[data-accessory=sprout]){transform:rotate(-35deg)}\n.aaa[data-status=sleeping] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(5px)}\n.aaa[data-blink=off] .aaa-blink{animation:none}\n.aaa[data-motion=off] *{animation:none!important}\n@keyframes aaa-blink{0%,28%,32%,90%,94%,100%{transform:scaleY(1)}30%,92%{transform:scaleY(.1)}}\n@keyframes aaa-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}\n@keyframes aaa-sway{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}\n@keyframes aaa-ponder{0%,100%{transform:translate(-5px,-6px)}50%{transform:translate(5px,-6px)}}\n@keyframes aaa-scan{0%,100%{transform:translateX(-5px)}50%{transform:translateX(5px)}}\n@keyframes aaa-breathe{0%,100%{transform:scale(1)}50%{transform:scale(1.035,.97)}}\n@keyframes aaa-signal{0%,100%{opacity:1}50%{opacity:.25}}\n@keyframes aaa-acc-sway{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}\n@keyframes aaa-wobble{0%,100%{transform:rotate(-12deg)}50%{transform:rotate(12deg)}}\n@keyframes aaa-glasses-think{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}\n@keyframes aaa-snore{0%,100%{transform:scale(.7)}50%{transform:scale(1.1)}}\n@keyframes aaa-hop{0%,55%,100%{transform:translateY(0)}68%{transform:translateY(-7px)}80%{transform:translateY(0)}90%{transform:translateY(-3px)}}\n@media (prefers-reduced-motion:reduce){.aaa *{animation:none!important;transition:none!important}}\n";
package/dist/styles.js CHANGED
@@ -9,7 +9,7 @@ export const AVATAR_CSS = `
9
9
  .aaa[data-interactive]{cursor:grab;touch-action:none}
10
10
  .aaa[data-interactive]:active{cursor:grabbing}
11
11
  .aaa-look{transform:translate(var(--aaa-look-x,0px),var(--aaa-look-y,0px));transition:transform .25s ease-out}
12
- .aaa-blink{animation:aaa-blink 4.6s infinite}
12
+ .aaa-blink{animation:aaa-blink 7s infinite}
13
13
  .aaa[data-status=idle] .aaa-body-motion{animation:aaa-bob 3.6s ease-in-out infinite}
14
14
  .aaa[data-status=thinking] .aaa-body-motion{animation:aaa-sway 3s ease-in-out infinite}
15
15
  .aaa[data-status=thinking] .aaa-eyes-motion{transform:translate(-5px,-6px);animation:aaa-ponder 2.4s ease-in-out infinite}
@@ -44,7 +44,7 @@ export const AVATAR_CSS = `
44
44
  .aaa[data-status=sleeping] .aaa-accessory:is([data-accessory=hat],[data-accessory=glasses]){transform:translateY(5px)}
45
45
  .aaa[data-blink=off] .aaa-blink{animation:none}
46
46
  .aaa[data-motion=off] *{animation:none!important}
47
- @keyframes aaa-blink{0%,93%,100%{transform:scaleY(1)}96%{transform:scaleY(.1)}}
47
+ @keyframes aaa-blink{0%,28%,32%,90%,94%,100%{transform:scaleY(1)}30%,92%{transform:scaleY(.1)}}
48
48
  @keyframes aaa-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
49
49
  @keyframes aaa-sway{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}
50
50
  @keyframes aaa-ponder{0%,100%{transform:translate(-5px,-6px)}50%{transform:translate(5px,-6px)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aaavatars",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Deterministic 2D character avatars with a play() animation API",
5
5
  "keywords": [
6
6
  "avatar",