lively-mascot 0.2.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/CHANGELOG.md +37 -0
- package/CHANGELOG.zh-CN.md +37 -0
- package/LICENSE +21 -0
- package/README.md +357 -0
- package/README.zh-CN.md +357 -0
- package/dist/lively-mascot.cjs +1 -0
- package/dist/lively-mascot.min.css +3115 -0
- package/dist/lively-mascot.min.js +8 -0
- package/dist/lively-mascot.mjs +10 -0
- package/package.json +72 -0
- package/src/characters/cat.css +331 -0
- package/src/characters/cat.js +130 -0
- package/src/characters/ghost.css +77 -0
- package/src/characters/ghost.js +68 -0
- package/src/characters/jelly.css +54 -0
- package/src/characters/jelly.js +55 -0
- package/src/characters/robot.css +83 -0
- package/src/characters/robot.js +82 -0
- package/src/characters/sprout.css +69 -0
- package/src/characters/sprout.js +87 -0
- package/src/core/emotions.js +206 -0
- package/src/core/rig.js +282 -0
- package/src/lively-mascot.css +2501 -0
- package/src/lively-mascot.js +330 -0
- package/types/index.d.ts +66 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lively-mascot · core SDK (v0.2.0)
|
|
3
|
+
*
|
|
4
|
+
* Requires: src/core/emotions.js, src/core/rig.js (loaded before this script)
|
|
5
|
+
* Character files (src/characters/*.js) register themselves after this script.
|
|
6
|
+
*
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
(function (root, factory) {
|
|
10
|
+
if (typeof module === "object" && typeof module.exports === "object") {
|
|
11
|
+
var emo = require("./core/emotions.js");
|
|
12
|
+
var api = factory(emo.groups, emo.emotions);
|
|
13
|
+
// Character modules are optional in the browser, where callers choose
|
|
14
|
+
// which scripts to include. The npm entry loads all bundled characters.
|
|
15
|
+
if (typeof globalThis !== "undefined") globalThis.LivelyMascot = api;
|
|
16
|
+
require("./core/rig.js");
|
|
17
|
+
require("./characters/sprout.js");
|
|
18
|
+
require("./characters/cat.js");
|
|
19
|
+
require("./characters/robot.js");
|
|
20
|
+
require("./characters/ghost.js");
|
|
21
|
+
require("./characters/jelly.js");
|
|
22
|
+
module.exports = api;
|
|
23
|
+
} else {
|
|
24
|
+
root.LivelyMascot = factory(
|
|
25
|
+
root.LivelyEmotionGroups || {},
|
|
26
|
+
root.LivelyEmotions || {}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
})(typeof self !== "undefined" ? self : this, function (LivelyEmotionGroups, LivelyEmotions) {
|
|
30
|
+
"use strict";
|
|
31
|
+
|
|
32
|
+
// --- DOM Helpers ---
|
|
33
|
+
function el(tag, attrs, children) {
|
|
34
|
+
var node = document.createElement(tag);
|
|
35
|
+
if (attrs) for (var k in attrs) {
|
|
36
|
+
if (Object.prototype.hasOwnProperty.call(attrs, k)) {
|
|
37
|
+
var v = attrs[k];
|
|
38
|
+
if (v === undefined || v === null || v === "") continue;
|
|
39
|
+
if (k === "class") node.className = String(v);
|
|
40
|
+
else if (k === "text") node.textContent = String(v);
|
|
41
|
+
else node.setAttribute(k, String(v));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (children) for (var i = 0; i < children.length; i++) node.appendChild(children[i]);
|
|
45
|
+
return node;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
49
|
+
function svg(tag, attrs, children) {
|
|
50
|
+
var node = document.createElementNS(SVG_NS, tag);
|
|
51
|
+
if (attrs) for (var k in attrs) {
|
|
52
|
+
if (Object.prototype.hasOwnProperty.call(attrs, k)) {
|
|
53
|
+
var v = attrs[k];
|
|
54
|
+
if (v === undefined || v === null || v === "") continue;
|
|
55
|
+
node.setAttribute(k, String(v));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (children) for (var i = 0; i < children.length; i++) node.appendChild(children[i]);
|
|
59
|
+
return node;
|
|
60
|
+
}
|
|
61
|
+
function hEl(tag, attrs, children) {
|
|
62
|
+
var node = document.createElement(tag);
|
|
63
|
+
if (attrs) for (var k in attrs) {
|
|
64
|
+
if (Object.prototype.hasOwnProperty.call(attrs, k)) {
|
|
65
|
+
var v = attrs[k];
|
|
66
|
+
if (v === undefined || v === null || v === "") continue;
|
|
67
|
+
if (k === "class") node.className = String(v);
|
|
68
|
+
else if (k === "text") node.textContent = String(v);
|
|
69
|
+
else node.setAttribute(k, String(v));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (children) for (var i = 0; i < children.length; i++) node.appendChild(children[i]);
|
|
73
|
+
return node;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Shared face builder. Every character reuses the same eye/pupil/mouth
|
|
78
|
+
* library so emotion CSS works uniformly across sprout, cat, robot, etc.
|
|
79
|
+
*
|
|
80
|
+
* @param {object} api the rig.api object (registers eyes / pupils / face)
|
|
81
|
+
* @returns {{ wrap: HTMLElement, face: SVGElement }} wrap = .lively-face-wrap
|
|
82
|
+
*/
|
|
83
|
+
function buildFaceSvg(api) {
|
|
84
|
+
var clipId = "lively-eye-clip-" + Math.random().toString(36).slice(2, 9);
|
|
85
|
+
|
|
86
|
+
function buildEye(cx, cy) {
|
|
87
|
+
var wrapper = svg("g", { transform: "translate(" + cx + " " + cy + ")" });
|
|
88
|
+
var eye = svg("g", { class: "lively-face__eye" });
|
|
89
|
+
api.registerEye(eye);
|
|
90
|
+
eye.appendChild(svg("ellipse", { rx: 10, ry: 11.5 }));
|
|
91
|
+
var clip = svg("g", { "clip-path": "url(#" + clipId + ")" });
|
|
92
|
+
var pupil = svg("g");
|
|
93
|
+
api.registerPupil(pupil, { maxX: 8, maxY: 6 });
|
|
94
|
+
pupil.appendChild(svg("circle", { class: "lively-face__pupil", r: 6.2 }));
|
|
95
|
+
pupil.appendChild(svg("circle", { class: "lively-face__shine", cx: 2.2, cy: -2.4, r: 2.1 }));
|
|
96
|
+
clip.appendChild(pupil);
|
|
97
|
+
eye.appendChild(clip);
|
|
98
|
+
eye.appendChild(svg("path", { class: "lively-face__happy", d: "M-6.5 1.5 Q0 -6 6.5 1.5" }));
|
|
99
|
+
wrapper.appendChild(eye);
|
|
100
|
+
return wrapper;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
var face = svg("g", { class: "lively-face" });
|
|
104
|
+
api.registerFace(face);
|
|
105
|
+
|
|
106
|
+
// Blush
|
|
107
|
+
face.appendChild(svg("ellipse", { class: "lively-face__blush", cx: 20, cy: 57, rx: 7, ry: 4 }));
|
|
108
|
+
face.appendChild(svg("ellipse", { class: "lively-face__blush", cx: 80, cy: 57, rx: 7, ry: 4 }));
|
|
109
|
+
|
|
110
|
+
// Eyes
|
|
111
|
+
face.appendChild(buildEye(34, 43));
|
|
112
|
+
face.appendChild(buildEye(66, 43));
|
|
113
|
+
|
|
114
|
+
// Default mouth
|
|
115
|
+
face.appendChild(svg("path", { class: "lively-face__mouth", d: "M42 63 Q50 70 58 63" }));
|
|
116
|
+
// Happy mouth
|
|
117
|
+
face.appendChild(svg("path", { class: "lively-face__happy-mouth", d: "M40 61 Q50 74 60 61 Q50 66 40 61 Z" }));
|
|
118
|
+
// Sad mouth
|
|
119
|
+
face.appendChild(svg("path", { class: "lively-face__sad-mouth", d: "M43 67 Q50 62 57 67" }));
|
|
120
|
+
// Open mouth
|
|
121
|
+
face.appendChild(svg("ellipse", { class: "lively-face__open-mouth", cx: 50, cy: 65, rx: 5, ry: 6 }));
|
|
122
|
+
// Flat mouth
|
|
123
|
+
face.appendChild(svg("line", { class: "lively-face__flat-mouth", x1: 43, y1: 65, x2: 57, y2: 65 }));
|
|
124
|
+
// Bored mouth: almost level, with a restrained lift at one corner.
|
|
125
|
+
face.appendChild(svg("path", { class: "lively-face__bored-mouth", d: "M42.5 65.2 C47.5 65.9 53 65.7 57.5 64.2" }));
|
|
126
|
+
// Sleep eyes
|
|
127
|
+
face.appendChild(svg("line", { class: "lively-face__sleep-eye lively-face__sleep-eye--l", x1: 27, y1: 43, x2: 41, y2: 43 }));
|
|
128
|
+
face.appendChild(svg("line", { class: "lively-face__sleep-eye lively-face__sleep-eye--r", x1: 59, y1: 43, x2: 73, y2: 43 }));
|
|
129
|
+
// Angry brows
|
|
130
|
+
face.appendChild(svg("line", { class: "lively-face__angry-brow lively-face__angry-brow--l", x1: 25, y1: 32, x2: 38, y2: 35 }));
|
|
131
|
+
face.appendChild(svg("line", { class: "lively-face__angry-brow lively-face__angry-brow--r", x1: 75, y1: 32, x2: 62, y2: 35 }));
|
|
132
|
+
// X eyes
|
|
133
|
+
face.appendChild(svg("g", { class: "lively-face__x-eye lively-face__x-eye--l", transform: "translate(34,43)" }, [
|
|
134
|
+
svg("line", { x1: -6, y1: -7, x2: 6, y2: 7 }),
|
|
135
|
+
svg("line", { x1: 6, y1: -7, x2: -6, y2: 7 })
|
|
136
|
+
]));
|
|
137
|
+
face.appendChild(svg("g", { class: "lively-face__x-eye lively-face__x-eye--r", transform: "translate(66,43)" }, [
|
|
138
|
+
svg("line", { x1: -6, y1: -7, x2: 6, y2: 7 }),
|
|
139
|
+
svg("line", { x1: 6, y1: -7, x2: -6, y2: 7 })
|
|
140
|
+
]));
|
|
141
|
+
// Heart eyes
|
|
142
|
+
face.appendChild(svg("path", { class: "lively-face__heart-eye lively-face__heart-eye--l", transform: "translate(34,42)", d: "M0 3 C0 0, -5 -4, -7 -1 C-9 2, 0 9, 0 9 C0 9, 9 2, 7 -1 C5 -4, 0 0, 0 3Z" }));
|
|
143
|
+
face.appendChild(svg("path", { class: "lively-face__heart-eye lively-face__heart-eye--r", transform: "translate(66,42)", d: "M0 3 C0 0, -5 -4, -7 -1 C-9 2, 0 9, 0 9 C0 9, 9 2, 7 -1 C5 -4, 0 0, 0 3Z" }));
|
|
144
|
+
// Cry eyes
|
|
145
|
+
face.appendChild(svg("path", { class: "lively-face__cry-eye lively-face__cry-eye--l", transform: "translate(34,43)", d: "M-6 2 Q0 -4 6 2" }));
|
|
146
|
+
face.appendChild(svg("path", { class: "lively-face__cry-eye lively-face__cry-eye--r", transform: "translate(66,43)", d: "M-6 2 Q0 -4 6 2" }));
|
|
147
|
+
// Tears
|
|
148
|
+
face.appendChild(svg("g", { class: "lively-face__tear lively-face__tear--l", transform: "translate(40,52)" }, [
|
|
149
|
+
svg("ellipse", { cx: 0, cy: 0, rx: 2.5, ry: 3.5, fill: "#6ec7ff", opacity: "0.8" }),
|
|
150
|
+
svg("ellipse", { cx: 0, cy: 8, rx: 1.8, ry: 2.5, fill: "#6ec7ff", opacity: "0.5" })
|
|
151
|
+
]));
|
|
152
|
+
face.appendChild(svg("g", { class: "lively-face__tear lively-face__tear--r", transform: "translate(60,52)" }, [
|
|
153
|
+
svg("ellipse", { cx: 0, cy: 0, rx: 2.5, ry: 3.5, fill: "#6ec7ff", opacity: "0.8" }),
|
|
154
|
+
svg("ellipse", { cx: 0, cy: 8, rx: 1.8, ry: 2.5, fill: "#6ec7ff", opacity: "0.5" })
|
|
155
|
+
]));
|
|
156
|
+
// Sweat drop
|
|
157
|
+
face.appendChild(svg("g", { class: "lively-face__sweat", transform: "translate(82,30)" }, [
|
|
158
|
+
svg("path", { d: "M0 0 C-3 5, -3 10, 0 12 C3 10, 3 5, 0 0Z", fill: "#6ec7ff", opacity: "0.7" })
|
|
159
|
+
]));
|
|
160
|
+
// Star eyes
|
|
161
|
+
face.appendChild(svg("g", { class: "lively-face__star-eye lively-face__star-eye--l", transform: "translate(34,43)" }, [
|
|
162
|
+
svg("polygon", { points: "0,-8 2,-3 7,-3 3,1 5,7 0,3 -5,7 -3,1 -7,-3 -2,-3", fill: "#ffe066" })
|
|
163
|
+
]));
|
|
164
|
+
face.appendChild(svg("g", { class: "lively-face__star-eye lively-face__star-eye--r", transform: "translate(66,43)" }, [
|
|
165
|
+
svg("polygon", { points: "0,-8 2,-3 7,-3 3,1 5,7 0,3 -5,7 -3,1 -7,-3 -2,-3", fill: "#ffe066" })
|
|
166
|
+
]));
|
|
167
|
+
// Sparkles
|
|
168
|
+
face.appendChild(svg("g", { class: "lively-face__sparkle lively-face__sparkle--1", transform: "translate(15,20)" }, [
|
|
169
|
+
svg("line", { x1: 0, y1: -4, x2: 0, y2: 4, stroke: "#ffe066", "stroke-width": "1.5" }),
|
|
170
|
+
svg("line", { x1: -4, y1: 0, x2: 4, y2: 0, stroke: "#ffe066", "stroke-width": "1.5" })
|
|
171
|
+
]));
|
|
172
|
+
face.appendChild(svg("g", { class: "lively-face__sparkle lively-face__sparkle--2", transform: "translate(85,18)" }, [
|
|
173
|
+
svg("line", { x1: 0, y1: -3, x2: 0, y2: 3, stroke: "#ffe066", "stroke-width": "1.2" }),
|
|
174
|
+
svg("line", { x1: -3, y1: 0, x2: 3, y2: 0, stroke: "#ffe066", "stroke-width": "1.2" })
|
|
175
|
+
]));
|
|
176
|
+
// Waiting dots
|
|
177
|
+
face.appendChild(svg("g", { class: "lively-face__waiting-dots", transform: "translate(42,68)" }, [
|
|
178
|
+
svg("circle", { cx: 0, cy: 0, r: 2, fill: "#888" }),
|
|
179
|
+
svg("circle", { cx: 8, cy: 0, r: 2, fill: "#888" }),
|
|
180
|
+
svg("circle", { cx: 16, cy: 0, r: 2, fill: "#888" })
|
|
181
|
+
]));
|
|
182
|
+
|
|
183
|
+
var faceSvg = svg("svg", { viewBox: "0 0 100 100", "aria-hidden": "true" });
|
|
184
|
+
var defs = svg("defs");
|
|
185
|
+
var clipPath = svg("clipPath", { id: clipId });
|
|
186
|
+
clipPath.appendChild(svg("ellipse", { rx: 10, ry: 11.5 }));
|
|
187
|
+
defs.appendChild(clipPath);
|
|
188
|
+
faceSvg.appendChild(defs);
|
|
189
|
+
faceSvg.appendChild(face);
|
|
190
|
+
var wrap = hEl("div", { class: "lively-face-wrap" });
|
|
191
|
+
wrap.appendChild(faceSvg);
|
|
192
|
+
|
|
193
|
+
return { wrap: wrap, face: face };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// --- Character Registry ---
|
|
197
|
+
// Characters register themselves via LivelyMascot.registerCharacter() from
|
|
198
|
+
// their own script files (e.g. src/characters/sprout.js, src/characters/cat.js).
|
|
199
|
+
var characters = {};
|
|
200
|
+
|
|
201
|
+
function registerCharacter(id, render, name, viewBox) {
|
|
202
|
+
characters[id] = { id: id, name: name || id, viewBox: viewBox || "0 0 100 100", render: render };
|
|
203
|
+
}
|
|
204
|
+
function getCharacter(type) { return characters[type] || characters.sprout; }
|
|
205
|
+
|
|
206
|
+
function normalizeViewMode(mode) {
|
|
207
|
+
return String(mode || "3d").toLowerCase() === "2d" ? "2d" : "3d";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function normalizeOutlineVisible(value) {
|
|
211
|
+
return value !== false && String(value).toLowerCase() !== "false";
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// --- Core API ---
|
|
215
|
+
function createMascot(target, options) {
|
|
216
|
+
options = options || {};
|
|
217
|
+
var type = options.type || "sprout";
|
|
218
|
+
var character = getCharacter(type);
|
|
219
|
+
var viewMode = normalizeViewMode(options.viewMode || options.mode);
|
|
220
|
+
var outlineVisible = normalizeOutlineVisible(options.outlineVisible);
|
|
221
|
+
var root = el("div", {
|
|
222
|
+
class: "lively-mascot lively-mascot--" + character.id + " lively-mascot--" + viewMode + (!outlineVisible ? " lively-mascot--outline-hidden" : "") + (options.animated === false ? " lively-mascot--static" : ""),
|
|
223
|
+
style: "width:" + (options.size || 106) + "px;height:" + (options.size || 106) + "px",
|
|
224
|
+
"aria-hidden": "true",
|
|
225
|
+
});
|
|
226
|
+
var rigEl = el("div", { class: "lively-mascot__rig" });
|
|
227
|
+
// gaze wrapper holds all character parts so the whole face turns with the
|
|
228
|
+
// body posture (sway / lean) instead of staying dead-on.
|
|
229
|
+
var gazeEl = el("div", { class: "lively-mascot__gaze" });
|
|
230
|
+
rigEl.appendChild(gazeEl);
|
|
231
|
+
var theme = { body: options.color || "", outline: options.outline || "", accent: options.accent || "" };
|
|
232
|
+
function applyTheme() {
|
|
233
|
+
root.style.setProperty("--lively-body", theme.body || null);
|
|
234
|
+
root.style.setProperty("--lively-outline", theme.outline || null);
|
|
235
|
+
root.style.setProperty("--lively-accent", theme.accent || null);
|
|
236
|
+
}
|
|
237
|
+
applyTheme();
|
|
238
|
+
var rig = createRig(root, rigEl, {
|
|
239
|
+
followCursor: options.followCursor,
|
|
240
|
+
hopInterval: options.hopInterval,
|
|
241
|
+
animated: options.animated
|
|
242
|
+
}, { onClick: options.onClick });
|
|
243
|
+
character.render(rig.api, gazeEl);
|
|
244
|
+
rig.api.registerGazeWrap(gazeEl);
|
|
245
|
+
// Loading ring overlay — shared by ALL characters (shown via .is-emotion-28).
|
|
246
|
+
gazeEl.appendChild(el("div", { class: "lively__loading-overlay", "aria-hidden": "true" }));
|
|
247
|
+
root.appendChild(rigEl);
|
|
248
|
+
target.appendChild(root);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
el: root,
|
|
252
|
+
type: character.id,
|
|
253
|
+
get viewMode() { return viewMode; },
|
|
254
|
+
setViewMode: function (mode) {
|
|
255
|
+
viewMode = normalizeViewMode(mode);
|
|
256
|
+
root.classList.toggle("lively-mascot--2d", viewMode === "2d");
|
|
257
|
+
root.classList.toggle("lively-mascot--3d", viewMode === "3d");
|
|
258
|
+
return viewMode;
|
|
259
|
+
},
|
|
260
|
+
get outlineVisible() { return outlineVisible; },
|
|
261
|
+
setOutlineVisible: function (visible) {
|
|
262
|
+
outlineVisible = normalizeOutlineVisible(visible);
|
|
263
|
+
root.classList.toggle("lively-mascot--outline-hidden", !outlineVisible);
|
|
264
|
+
return outlineVisible;
|
|
265
|
+
},
|
|
266
|
+
setTheme: function (p) {
|
|
267
|
+
p = p || {};
|
|
268
|
+
if (p.body) theme.body = p.body;
|
|
269
|
+
if (p.outline) theme.outline = p.outline;
|
|
270
|
+
if (p.accent) theme.accent = p.accent;
|
|
271
|
+
applyTheme();
|
|
272
|
+
},
|
|
273
|
+
setEmotion: function (emotionId) {
|
|
274
|
+
root.className = root.className.replace(/is-emotion-\d+/g, "").trim();
|
|
275
|
+
root.classList.add("is-emotion-" + emotionId);
|
|
276
|
+
rig.api.setEmotionState(String(emotionId));
|
|
277
|
+
},
|
|
278
|
+
clearEmotion: function () {
|
|
279
|
+
root.className = root.className.replace(/is-emotion-\d+/g, "").trim();
|
|
280
|
+
root.classList.add("is-emotion-02");
|
|
281
|
+
rig.api.setEmotionState("02");
|
|
282
|
+
},
|
|
283
|
+
destroy: function () { rig.destroy(); root.remove(); }
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function defineMascotElement(tag) {
|
|
288
|
+
tag = tag || "lively-mascot";
|
|
289
|
+
if (typeof customElements === "undefined" || customElements.get(tag)) return;
|
|
290
|
+
var _create = createMascot;
|
|
291
|
+
var LivelyMascotElement = (function () {
|
|
292
|
+
function LivelyMascotElement() {
|
|
293
|
+
var _newTarget = this.constructor;
|
|
294
|
+
var _this = Reflect.construct(HTMLElement, [], _newTarget);
|
|
295
|
+
return _this;
|
|
296
|
+
}
|
|
297
|
+
LivelyMascotElement.prototype = Object.create(HTMLElement.prototype, {
|
|
298
|
+
constructor: { value: LivelyMascotElement, writable: true, configurable: true }
|
|
299
|
+
});
|
|
300
|
+
LivelyMascotElement.observedAttributes = ["type", "color", "size", "view-mode", "mode", "show-outline"];
|
|
301
|
+
LivelyMascotElement.prototype.connectedCallback = function () { this._render(); };
|
|
302
|
+
LivelyMascotElement.prototype.disconnectedCallback = function () { if (this._inst) this._inst.destroy(); this._inst = null; this.textContent = ""; };
|
|
303
|
+
LivelyMascotElement.prototype.attributeChangedCallback = function () { if (this.isConnected) this._render(); };
|
|
304
|
+
LivelyMascotElement.prototype._render = function () {
|
|
305
|
+
if (this._inst) this._inst.destroy();
|
|
306
|
+
this.textContent = "";
|
|
307
|
+
this._inst = _create(this, {
|
|
308
|
+
type: this.getAttribute("type"),
|
|
309
|
+
color: this.getAttribute("color"),
|
|
310
|
+
size: this.getAttribute("size") ? Number(this.getAttribute("size")) : undefined,
|
|
311
|
+
viewMode: this.getAttribute("view-mode") || this.getAttribute("mode") || undefined,
|
|
312
|
+
outlineVisible: this.getAttribute("show-outline") !== "false"
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
return LivelyMascotElement;
|
|
316
|
+
})();
|
|
317
|
+
customElements.define(tag, LivelyMascotElement);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return {
|
|
321
|
+
createMascot: createMascot,
|
|
322
|
+
registerCharacter: registerCharacter,
|
|
323
|
+
defineMascotElement: defineMascotElement,
|
|
324
|
+
buildFaceSvg: buildFaceSvg,
|
|
325
|
+
characters: characters,
|
|
326
|
+
emotions: LivelyEmotions,
|
|
327
|
+
emotionGroups: LivelyEmotionGroups,
|
|
328
|
+
version: "0.2.0"
|
|
329
|
+
};
|
|
330
|
+
});
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export type ViewMode = "2d" | "3d";
|
|
2
|
+
|
|
3
|
+
export interface MascotOptions {
|
|
4
|
+
type?: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
outline?: string;
|
|
7
|
+
accent?: string;
|
|
8
|
+
size?: number;
|
|
9
|
+
followCursor?: boolean;
|
|
10
|
+
viewMode?: ViewMode;
|
|
11
|
+
mode?: ViewMode;
|
|
12
|
+
outlineVisible?: boolean;
|
|
13
|
+
animated?: boolean;
|
|
14
|
+
hopInterval?: [number, number] | null;
|
|
15
|
+
onClick?: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MascotInstance {
|
|
19
|
+
readonly el: HTMLElement;
|
|
20
|
+
readonly type: string;
|
|
21
|
+
readonly viewMode: ViewMode;
|
|
22
|
+
readonly outlineVisible: boolean;
|
|
23
|
+
setViewMode(mode: ViewMode): ViewMode;
|
|
24
|
+
setOutlineVisible(visible: boolean): boolean;
|
|
25
|
+
setTheme(theme: { body?: string; outline?: string; accent?: string }): void;
|
|
26
|
+
setEmotion(id: string | number): void;
|
|
27
|
+
clearEmotion(): void;
|
|
28
|
+
destroy(): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface EmotionDefinition {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
group: string;
|
|
35
|
+
desc: string;
|
|
36
|
+
bodyAnim?: string;
|
|
37
|
+
bodyFilter?: string;
|
|
38
|
+
leafAnim?: string;
|
|
39
|
+
footAnim?: string;
|
|
40
|
+
blink?: boolean | "fast";
|
|
41
|
+
gaze?: boolean;
|
|
42
|
+
hop?: boolean;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const createMascot: (target: Element, options?: MascotOptions) => MascotInstance;
|
|
47
|
+
export const registerCharacter: (id: string, render: Function, name?: string, viewBox?: string) => void;
|
|
48
|
+
export const defineMascotElement: (tag?: string) => void;
|
|
49
|
+
export const buildFaceSvg: (api: object) => { wrap: HTMLElement; face: SVGElement };
|
|
50
|
+
export const characters: Record<string, object>;
|
|
51
|
+
export const emotions: Record<string, EmotionDefinition>;
|
|
52
|
+
export const emotionGroups: Record<string, { name: string; order: number }>;
|
|
53
|
+
export const version: string;
|
|
54
|
+
|
|
55
|
+
declare const LivelyMascot: {
|
|
56
|
+
createMascot: typeof createMascot;
|
|
57
|
+
registerCharacter: typeof registerCharacter;
|
|
58
|
+
defineMascotElement: typeof defineMascotElement;
|
|
59
|
+
buildFaceSvg: typeof buildFaceSvg;
|
|
60
|
+
characters: typeof characters;
|
|
61
|
+
emotions: typeof emotions;
|
|
62
|
+
emotionGroups: typeof emotionGroups;
|
|
63
|
+
version: typeof version;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default LivelyMascot;
|