@firetable/project-xiaochun 0.1.15 → 0.1.17
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-CN.md +26 -14
- package/README.md +26 -14
- package/dist/avatar-element.d.ts +10 -4
- package/dist/chunks/{chunk-T6EHFEEZ.js → chunk-4RT7LXB5.js} +39 -8
- package/dist/chunks/chunk-4RT7LXB5.js.map +7 -0
- package/dist/chunks/{chunk-KQSKHPVF.js → chunk-6EHOJ2CJ.js} +136 -10
- package/dist/chunks/chunk-6EHOJ2CJ.js.map +7 -0
- package/dist/chunks/{chunk-KKRZ3SUD.js → chunk-BJF55B44.js} +86 -3
- package/dist/chunks/chunk-BJF55B44.js.map +7 -0
- package/dist/client.d.ts +64 -5
- package/dist/element.cjs +206 -12
- package/dist/element.cjs.map +2 -2
- package/dist/element.js +4 -4
- package/dist/index.cjs +247 -13
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +20 -6
- package/dist/index.js.map +1 -1
- package/dist/loader.global.js +2 -2
- package/dist/loader.global.js.map +3 -3
- package/dist/protocol.cjs +86 -3
- package/dist/protocol.cjs.map +2 -2
- package/dist/protocol.d.ts +111 -4
- package/dist/protocol.js +18 -4
- package/dist/react.cjs +190 -14
- package/dist/react.cjs.map +2 -2
- package/dist/react.d.ts +6 -0
- package/dist/react.js +23 -9
- package/dist/react.js.map +2 -2
- package/package.json +2 -2
- package/dist/chunks/chunk-KKRZ3SUD.js.map +0 -7
- package/dist/chunks/chunk-KQSKHPVF.js.map +0 -7
- package/dist/chunks/chunk-T6EHFEEZ.js.map +0 -7
package/dist/element.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @firetable/project-xiaochun v0.1.
|
|
1
|
+
/*! @firetable/project-xiaochun v0.1.17 | MIT | https://github.com/FireTable/project-xiaochun */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -31,7 +31,7 @@ var XC_PROTOCOL_VERSION = 1;
|
|
|
31
31
|
var XC_DEFAULT_ORIGIN = "https://xiaochun.firetable.tech";
|
|
32
32
|
var XC_DEFAULT_SRC = `${XC_DEFAULT_ORIGIN}/embed`;
|
|
33
33
|
var XC_WINDOW_CORNER_RADIUS = 20;
|
|
34
|
-
var XC_UI_PARTS = ["chat", "bubble", "outfit", "scene"];
|
|
34
|
+
var XC_UI_PARTS = ["chat", "bubble", "outfit", "scene", "lang", "github"];
|
|
35
35
|
var XC_UI_PART_SET = new Set(XC_UI_PARTS);
|
|
36
36
|
var XC_UI_LEGACY_PARTS = ["chat", "bubble"];
|
|
37
37
|
function parseXcUiList(items) {
|
|
@@ -49,6 +49,49 @@ function normalizeXcUiOption(v) {
|
|
|
49
49
|
if (Array.isArray(v)) return parseXcUiList(v);
|
|
50
50
|
return { parts: [], unknown: [], legacy: false };
|
|
51
51
|
}
|
|
52
|
+
function parseXcUiAutoHide(raw) {
|
|
53
|
+
if (raw === true || raw === false || raw === "transparent") return raw;
|
|
54
|
+
if (typeof raw !== "string") return void 0;
|
|
55
|
+
const v = raw.trim().toLowerCase();
|
|
56
|
+
if (v === "1" || v === "true") return true;
|
|
57
|
+
if (v === "0" || v === "false") return false;
|
|
58
|
+
if (v === "transparent") return "transparent";
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
var XC_CAMERA_RANGES = {
|
|
62
|
+
fov: [15, 60],
|
|
63
|
+
distance: [1, 15],
|
|
64
|
+
height: [-1, 1]
|
|
65
|
+
};
|
|
66
|
+
var XC_CAMERA_NUM_KEYS = ["fov", "distance", "height"];
|
|
67
|
+
var XC_CAMERA_KEYS = ["fov", "distance", "height", "intro"];
|
|
68
|
+
function normalizeXcCamera(raw) {
|
|
69
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return { ok: false, error: "camera must be an object" };
|
|
70
|
+
const src = raw;
|
|
71
|
+
for (const k of Object.keys(src)) {
|
|
72
|
+
if (!XC_CAMERA_KEYS.includes(k)) return { ok: false, error: `unknown camera key: ${k} (expected ${XC_CAMERA_KEYS.join(" | ")})` };
|
|
73
|
+
}
|
|
74
|
+
const out = {};
|
|
75
|
+
const clamped = [];
|
|
76
|
+
for (const k of XC_CAMERA_NUM_KEYS) {
|
|
77
|
+
const v = src[k];
|
|
78
|
+
if (v === void 0) continue;
|
|
79
|
+
if (v === null) {
|
|
80
|
+
out[k] = null;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (typeof v !== "number" || !Number.isFinite(v)) return { ok: false, error: `camera.${k} must be a finite number or null` };
|
|
84
|
+
const [lo, hi] = XC_CAMERA_RANGES[k];
|
|
85
|
+
const c = Math.min(hi, Math.max(lo, v));
|
|
86
|
+
if (c !== v) clamped.push(k);
|
|
87
|
+
out[k] = c;
|
|
88
|
+
}
|
|
89
|
+
if (src.intro !== void 0) {
|
|
90
|
+
if (src.intro !== null && typeof src.intro !== "boolean") return { ok: false, error: "camera.intro must be a boolean or null" };
|
|
91
|
+
out.intro = src.intro;
|
|
92
|
+
}
|
|
93
|
+
return { ok: true, camera: out, clamped };
|
|
94
|
+
}
|
|
52
95
|
var XC_ID_RE = /^[a-z][a-z0-9_]{0,63}$/;
|
|
53
96
|
var isXcId = (v) => typeof v === "string" && XC_ID_RE.test(v);
|
|
54
97
|
function xcMessage(type, payload, id) {
|
|
@@ -165,7 +208,20 @@ var GestureGate = class {
|
|
|
165
208
|
var FALLBACK_PLACEHOLDER = "data:image/svg+xml;utf8," + encodeURIComponent(
|
|
166
209
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 180"><defs><linearGradient id="g" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#f6b8ae"/><stop offset="1" stop-color="#ea8377"/></linearGradient></defs><ellipse cx="60" cy="170" rx="34" ry="6" fill="#000" opacity=".12"/><circle cx="60" cy="48" r="26" fill="url(#g)" opacity=".75"/><path d="M26 160c2-40 18-62 34-62s32 22 34 62z" fill="url(#g)" opacity=".6"/></svg>'
|
|
167
210
|
);
|
|
211
|
+
var noSelect = (st) => {
|
|
212
|
+
st.setProperty("user-select", "none");
|
|
213
|
+
st.setProperty("-webkit-user-select", "none");
|
|
214
|
+
st.setProperty("-webkit-touch-callout", "none");
|
|
215
|
+
st.setProperty("-webkit-tap-highlight-color", "transparent");
|
|
216
|
+
};
|
|
168
217
|
var css = (v, d) => v === void 0 ? d : typeof v === "number" ? `${v}px` : v;
|
|
218
|
+
var XC_DEFAULT_WIDTH = 600;
|
|
219
|
+
var XC_DEFAULT_HEIGHT = 1080;
|
|
220
|
+
var defaultWidthCss = (floating = false) => floating ? `min(${XC_DEFAULT_WIDTH}px, calc(100vw - 2 * var(--xc-offset-x, 16px)))` : `min(${XC_DEFAULT_WIDTH}px, 100vw)`;
|
|
221
|
+
var defaultHeightCss = (floating = false) => {
|
|
222
|
+
const unit = typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("height", "1svh") ? "svh" : "vh";
|
|
223
|
+
return floating ? `min(${XC_DEFAULT_HEIGHT}px, calc(100${unit} - 2 * var(--xc-offset-y, 16px)))` : `min(${XC_DEFAULT_HEIGHT}px, 100${unit})`;
|
|
224
|
+
};
|
|
169
225
|
function createXiaochun(options) {
|
|
170
226
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
171
227
|
throw new Error("[project-xiaochun] createXiaochun must run in a browser");
|
|
@@ -220,6 +276,16 @@ function createXiaochun(options) {
|
|
|
220
276
|
}
|
|
221
277
|
const uiParse = normalizeXcUiOption(options.ui);
|
|
222
278
|
const uiParts = uiParse.parts;
|
|
279
|
+
const uiAutoHide = parseXcUiAutoHide(options.uiAutoHide);
|
|
280
|
+
if (options.uiAutoHide !== void 0 && uiAutoHide === void 0) console.warn(`[project-xiaochun] ignoring invalid uiAutoHide: ${String(options.uiAutoHide)} (use true | false | 'transparent')`);
|
|
281
|
+
let camera = {};
|
|
282
|
+
if (options.camera !== void 0) {
|
|
283
|
+
const r = normalizeXcCamera(options.camera);
|
|
284
|
+
if (r.ok) {
|
|
285
|
+
camera = r.camera;
|
|
286
|
+
if (r.clamped.length) console.warn(`[project-xiaochun] camera.${r.clamped.join(", camera.")} out of range, clamped (fov ${XC_CAMERA_RANGES.fov.join("\u2013")}, distance ${XC_CAMERA_RANGES.distance.join("\u2013")}, height ${XC_CAMERA_RANGES.height.join("\u2013")})`);
|
|
287
|
+
} else console.warn(`[project-xiaochun] ignoring invalid camera option: ${r.error}`);
|
|
288
|
+
}
|
|
223
289
|
if (uiParse.legacy) console.warn(`[project-xiaochun] option "ui: true" is deprecated, use an array of parts, e.g. ui: ['chat', 'bubble', 'outfit', 'scene'].`);
|
|
224
290
|
if (uiParse.unknown.length) console.warn(`[project-xiaochun] ignoring unknown ui part(s): ${uiParse.unknown.join(", ")} (known: ${XC_UI_PARTS.join(", ")})`);
|
|
225
291
|
const outfitOpt = options.outfit ?? (isXcId(options.model) ? options.model : void 0);
|
|
@@ -234,11 +300,12 @@ function createXiaochun(options) {
|
|
|
234
300
|
wrapper.setAttribute("data-xiaochun", "");
|
|
235
301
|
const ws = wrapper.style;
|
|
236
302
|
ws.position = position === "inline" ? "relative" : "fixed";
|
|
237
|
-
ws.width = css(options.width, "
|
|
238
|
-
ws.height = css(options.height, "
|
|
303
|
+
ws.width = css(options.width, defaultWidthCss(position !== "inline"));
|
|
304
|
+
ws.height = css(options.height, defaultHeightCss(position !== "inline"));
|
|
239
305
|
ws.maxWidth = "100%";
|
|
240
306
|
ws.overflow = "visible";
|
|
241
307
|
ws.contain = "layout style";
|
|
308
|
+
noSelect(ws);
|
|
242
309
|
ws.boxShadow = "var(--xc-shadow, none)";
|
|
243
310
|
const applyWrapperBg = () => {
|
|
244
311
|
ws.background = transparent ? "" : "var(--xc-bg, transparent)";
|
|
@@ -273,8 +340,8 @@ function createXiaochun(options) {
|
|
|
273
340
|
img.src = options.placeholder || FALLBACK_PLACEHOLDER;
|
|
274
341
|
img.alt = "Project XiaoChun";
|
|
275
342
|
img.decoding = "async";
|
|
276
|
-
img.width =
|
|
277
|
-
img.height =
|
|
343
|
+
img.width = XC_DEFAULT_WIDTH;
|
|
344
|
+
img.height = XC_DEFAULT_HEIGHT;
|
|
278
345
|
placeholderEl = img;
|
|
279
346
|
}
|
|
280
347
|
const ps = placeholderEl.style;
|
|
@@ -288,6 +355,7 @@ function createXiaochun(options) {
|
|
|
288
355
|
ps.transition = "opacity .25s ease";
|
|
289
356
|
ps.pointerEvents = "auto";
|
|
290
357
|
ps.cursor = lazy === false ? "default" : "pointer";
|
|
358
|
+
noSelect(ps);
|
|
291
359
|
placeholderEl.addEventListener("click", () => activate());
|
|
292
360
|
wrapper.appendChild(placeholderEl);
|
|
293
361
|
}
|
|
@@ -446,6 +514,11 @@ function createXiaochun(options) {
|
|
|
446
514
|
if (transparent) u.searchParams.set("transparent", "1");
|
|
447
515
|
if (uiParts.length) u.searchParams.set("ui", uiParts.join(","));
|
|
448
516
|
if (options.lang) u.searchParams.set("lang", options.lang);
|
|
517
|
+
if (uiAutoHide !== void 0) u.searchParams.set("uiAutoHide", String(uiAutoHide));
|
|
518
|
+
if (typeof camera.fov === "number") u.searchParams.set("cameraFov", String(camera.fov));
|
|
519
|
+
if (typeof camera.distance === "number") u.searchParams.set("cameraDistance", String(camera.distance));
|
|
520
|
+
if (typeof camera.height === "number") u.searchParams.set("cameraHeight", String(camera.height));
|
|
521
|
+
if (typeof camera.intro === "boolean") u.searchParams.set("cameraIntro", camera.intro ? "1" : "0");
|
|
449
522
|
if (options.heavy) u.searchParams.set("heavy", options.heavy);
|
|
450
523
|
if (options.controls === false) u.searchParams.set("controls", "0");
|
|
451
524
|
if (initialScene && isXcId(initialScene)) u.searchParams.set("scene", initialScene);
|
|
@@ -477,6 +550,7 @@ function createXiaochun(options) {
|
|
|
477
550
|
s.colorScheme = "normal";
|
|
478
551
|
s.borderRadius = `var(--xc-radius, ${radiusValue()})`;
|
|
479
552
|
f.setAttribute("part", "iframe");
|
|
553
|
+
noSelect(s);
|
|
480
554
|
s.opacity = "0";
|
|
481
555
|
s.transition = "opacity .25s ease";
|
|
482
556
|
s.pointerEvents = passthrough ? "none" : "auto";
|
|
@@ -582,6 +656,9 @@ function createXiaochun(options) {
|
|
|
582
656
|
ack(data.id);
|
|
583
657
|
break;
|
|
584
658
|
}
|
|
659
|
+
case "xc.lang-changed":
|
|
660
|
+
emit("lang-changed", data.payload);
|
|
661
|
+
break;
|
|
585
662
|
case "xc.prefetched":
|
|
586
663
|
ack(data.id, data.payload);
|
|
587
664
|
break;
|
|
@@ -826,6 +903,7 @@ function createXiaochun(options) {
|
|
|
826
903
|
emit(activeGesture.kind, { phase: "end", ...b });
|
|
827
904
|
activeGesture = null;
|
|
828
905
|
lockSelection(false);
|
|
906
|
+
saveBox();
|
|
829
907
|
}
|
|
830
908
|
function onGesture(kind, raw) {
|
|
831
909
|
if (destroyed || !caps?.gestures) return;
|
|
@@ -854,6 +932,7 @@ function createXiaochun(options) {
|
|
|
854
932
|
if (p.phase === "end") {
|
|
855
933
|
activeGesture = null;
|
|
856
934
|
lockSelection(false);
|
|
935
|
+
saveBox();
|
|
857
936
|
}
|
|
858
937
|
}
|
|
859
938
|
function syncGestures() {
|
|
@@ -878,11 +957,63 @@ function createXiaochun(options) {
|
|
|
878
957
|
const onWindowResize = () => {
|
|
879
958
|
if (!userMoved || activeGesture || destroyed) return;
|
|
880
959
|
const cur = readBox();
|
|
881
|
-
const
|
|
960
|
+
const vp = viewport();
|
|
961
|
+
const fit = position === "inline" ? { ...fitBox({ ...cur, top: 0 }, { width: vp.width, height: Number.MAX_SAFE_INTEGER }), top: Math.max(cur.top, -window.scrollY) } : fitBox(cur, vp);
|
|
882
962
|
if (fit.left === cur.left && fit.top === cur.top && fit.width === cur.width && fit.height === cur.height) return;
|
|
883
963
|
applyBox(fit, position === "inline" ? { left: cur.left - inlineShift.x, top: cur.top - inlineShift.y } : null, fit.width !== cur.width || fit.height !== cur.height);
|
|
884
964
|
};
|
|
885
965
|
window.addEventListener("resize", onWindowResize, { passive: true });
|
|
966
|
+
const boxKey = options.persistBox === true ? "xiaochun:box" : typeof options.persistBox === "string" && options.persistBox ? `xiaochun:box:${options.persistBox}` : null;
|
|
967
|
+
const saveBox = () => {
|
|
968
|
+
if (!boxKey) return;
|
|
969
|
+
try {
|
|
970
|
+
const b = readBox();
|
|
971
|
+
const at = position === "inline" ? inlineShift : { x: b.left, y: b.top };
|
|
972
|
+
window.localStorage.setItem(boxKey, JSON.stringify({ v: 1, mode: position, x: Math.round(at.x), y: Math.round(at.y), width: Math.round(b.width), height: Math.round(b.height) }));
|
|
973
|
+
} catch {
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
const loadBox = () => {
|
|
977
|
+
if (!boxKey) return null;
|
|
978
|
+
try {
|
|
979
|
+
const raw = window.localStorage.getItem(boxKey);
|
|
980
|
+
if (raw === null) return null;
|
|
981
|
+
let o = null;
|
|
982
|
+
try {
|
|
983
|
+
o = JSON.parse(raw);
|
|
984
|
+
} catch {
|
|
985
|
+
}
|
|
986
|
+
const ok = (v, lo, hi) => typeof v === "number" && Number.isFinite(v) && v >= lo && v <= hi;
|
|
987
|
+
if (o && o.v === 1 && o.mode === position && ok(o.x, -1e5, 1e5) && ok(o.y, -1e5, 1e5) && ok(o.width, 1, 1e5) && ok(o.height, 1, 1e5)) {
|
|
988
|
+
return { x: o.x, y: o.y, width: o.width, height: o.height };
|
|
989
|
+
}
|
|
990
|
+
window.localStorage.removeItem(boxKey);
|
|
991
|
+
} catch {
|
|
992
|
+
}
|
|
993
|
+
return null;
|
|
994
|
+
};
|
|
995
|
+
function restoreBox() {
|
|
996
|
+
if (!boxKey || !draggableOn && resizeLimits === null) return;
|
|
997
|
+
const st = loadBox();
|
|
998
|
+
if (!st) return;
|
|
999
|
+
const vp = viewport();
|
|
1000
|
+
const lim = resizeLimits ?? DEFAULT_RESIZE_LIMITS;
|
|
1001
|
+
const cur = readBox();
|
|
1002
|
+
const useW = resizeLimits !== null && options.width === void 0;
|
|
1003
|
+
const useH = resizeLimits !== null && options.height === void 0;
|
|
1004
|
+
const clampN = (v, lo, hi) => Math.min(Math.max(v, lo), Math.max(lo, hi));
|
|
1005
|
+
const width = useW ? clampN(st.width, lim.minWidth, Math.min(lim.maxWidth, vp.width)) : cur.width;
|
|
1006
|
+
const height = useH ? clampN(st.height, lim.minHeight, Math.min(lim.maxHeight, vp.height)) : cur.height;
|
|
1007
|
+
if (position === "inline") {
|
|
1008
|
+
const base = { left: cur.left - inlineShift.x, top: cur.top - inlineShift.y };
|
|
1009
|
+
const left = clampN(base.left + st.x, 0, vp.width - width);
|
|
1010
|
+
const top = Math.max(base.top + st.y, -window.scrollY);
|
|
1011
|
+
applyBox({ left, top, width, height }, base, useW || useH);
|
|
1012
|
+
} else {
|
|
1013
|
+
applyBox(fitBox({ left: st.x, top: st.y, width, height }, vp), null, useW || useH);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
restoreBox();
|
|
886
1017
|
scheduleLazy();
|
|
887
1018
|
const api = {
|
|
888
1019
|
element: wrapper,
|
|
@@ -939,11 +1070,44 @@ function createXiaochun(options) {
|
|
|
939
1070
|
setConfig: (cfg) => send("xc.setConfig", cfg),
|
|
940
1071
|
setSize(width, height) {
|
|
941
1072
|
if (destroyed) return;
|
|
942
|
-
ws.width = css(width, "
|
|
943
|
-
ws.height = css(height, "
|
|
1073
|
+
ws.width = css(width, defaultWidthCss(position !== "inline"));
|
|
1074
|
+
ws.height = css(height, defaultHeightCss(position !== "inline"));
|
|
1075
|
+
if (ws.maxWidth === "none") ws.maxWidth = "100%";
|
|
944
1076
|
invalidateRect();
|
|
945
1077
|
},
|
|
946
1078
|
getBox: () => readBox(),
|
|
1079
|
+
clearPersistedBox(opts) {
|
|
1080
|
+
if (boxKey) {
|
|
1081
|
+
try {
|
|
1082
|
+
window.localStorage.removeItem(boxKey);
|
|
1083
|
+
} catch {
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (destroyed || opts?.reset !== true) return;
|
|
1087
|
+
endActiveGesture();
|
|
1088
|
+
ws.width = css(options.width, defaultWidthCss(position !== "inline"));
|
|
1089
|
+
ws.height = css(options.height, defaultHeightCss(position !== "inline"));
|
|
1090
|
+
ws.maxWidth = "100%";
|
|
1091
|
+
if (position === "inline") {
|
|
1092
|
+
inlineShift = { x: 0, y: 0 };
|
|
1093
|
+
ws.removeProperty("translate");
|
|
1094
|
+
} else {
|
|
1095
|
+
ws.left = "";
|
|
1096
|
+
ws.top = "";
|
|
1097
|
+
ws.right = "";
|
|
1098
|
+
ws.bottom = "";
|
|
1099
|
+
if (position === "bottom-right") {
|
|
1100
|
+
ws.right = "var(--xc-offset-x, 16px)";
|
|
1101
|
+
ws.bottom = "var(--xc-offset-y, 16px)";
|
|
1102
|
+
}
|
|
1103
|
+
if (position === "bottom-left") {
|
|
1104
|
+
ws.left = "var(--xc-offset-x, 16px)";
|
|
1105
|
+
ws.bottom = "var(--xc-offset-y, 16px)";
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
userMoved = false;
|
|
1109
|
+
invalidateRect();
|
|
1110
|
+
},
|
|
947
1111
|
setBorderRadius(radius) {
|
|
948
1112
|
radiusOpt = radius;
|
|
949
1113
|
applyRadius();
|
|
@@ -1034,14 +1198,20 @@ var OBSERVED = [
|
|
|
1034
1198
|
"placeholder",
|
|
1035
1199
|
"heavy",
|
|
1036
1200
|
"ui",
|
|
1201
|
+
"ui-autohide",
|
|
1202
|
+
"camera-fov",
|
|
1203
|
+
"camera-distance",
|
|
1204
|
+
"camera-height",
|
|
1205
|
+
"camera-intro",
|
|
1037
1206
|
"controls",
|
|
1038
1207
|
"allowed-origins",
|
|
1039
1208
|
"cross-origin-isolated",
|
|
1040
1209
|
"persist",
|
|
1210
|
+
"persist-box",
|
|
1041
1211
|
"allow-custom-model",
|
|
1042
1212
|
"prefetch"
|
|
1043
1213
|
];
|
|
1044
|
-
var REBUILD = /* @__PURE__ */ new Set(["src", "position", "lazy", "placeholder", "heavy", "ui", "controls", "allowed-origins", "transparent", "cross-origin-isolated", "persist", "allow-custom-model", "prefetch"]);
|
|
1214
|
+
var REBUILD = /* @__PURE__ */ new Set(["src", "position", "lazy", "placeholder", "heavy", "ui", "ui-autohide", "controls", "allowed-origins", "transparent", "cross-origin-isolated", "persist", "persist-box", "allow-custom-model", "prefetch"]);
|
|
1045
1215
|
function radiusAttr(v) {
|
|
1046
1216
|
if (v === null || v.trim() === "") return void 0;
|
|
1047
1217
|
const t = v.trim();
|
|
@@ -1057,22 +1227,37 @@ function prefetchAttr(v) {
|
|
|
1057
1227
|
if (v === "" || v === "true") return true;
|
|
1058
1228
|
return v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1059
1229
|
}
|
|
1230
|
+
function persistBoxAttr(v) {
|
|
1231
|
+
if (v === null || v === "false" || v === "0") return void 0;
|
|
1232
|
+
if (v === "" || v === "true" || v === "1") return true;
|
|
1233
|
+
return v;
|
|
1234
|
+
}
|
|
1060
1235
|
function uiAttr(v) {
|
|
1061
1236
|
if (v === null || v === "false" || v === "0") return void 0;
|
|
1062
1237
|
if (v === "" || v === "true" || v === "1") return true;
|
|
1063
1238
|
return v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1064
1239
|
}
|
|
1240
|
+
function cameraAttrs(el) {
|
|
1241
|
+
const num = (name) => {
|
|
1242
|
+
const v = el.getAttribute(name);
|
|
1243
|
+
if (v === null || v.trim() === "") return null;
|
|
1244
|
+
const n = Number(v);
|
|
1245
|
+
return Number.isFinite(n) ? n : null;
|
|
1246
|
+
};
|
|
1247
|
+
const i = el.getAttribute("camera-intro");
|
|
1248
|
+
return { fov: num("camera-fov"), distance: num("camera-distance"), height: num("camera-height"), intro: i === null ? null : i !== "false" && i !== "0" };
|
|
1249
|
+
}
|
|
1065
1250
|
function parsePx(v) {
|
|
1066
1251
|
const m = v?.trim().match(/^(\d+(?:\.\d+)?)\s*x\s*(\d+(?:\.\d+)?)$/i);
|
|
1067
1252
|
return m ? { w: Number(m[1]), h: Number(m[2]) } : void 0;
|
|
1068
1253
|
}
|
|
1069
1254
|
function parseSize(v) {
|
|
1070
|
-
if (!v) return { width:
|
|
1255
|
+
if (!v) return { width: void 0, height: void 0 };
|
|
1071
1256
|
const m = v.trim().split(/x/i);
|
|
1072
1257
|
const px = (s) => /^\d+(\.\d+)?$/.test(s) ? `${s}px` : s;
|
|
1073
1258
|
if (m.length >= 2) return { width: px(m[0]), height: px(m[1]) };
|
|
1074
1259
|
const w = parseFloat(m[0]);
|
|
1075
|
-
return Number.isFinite(w) && /^\d+(\.\d+)?$/.test(m[0]) ? { width: `${w}px`, height: `${Math.round(w * 1.5)}px` } : { width: m[0], height:
|
|
1260
|
+
return Number.isFinite(w) && /^\d+(\.\d+)?$/.test(m[0]) ? { width: `${w}px`, height: `${Math.round(w * 1.5)}px` } : { width: m[0], height: void 0 };
|
|
1076
1261
|
}
|
|
1077
1262
|
function createElementClass() {
|
|
1078
1263
|
class XiaochunAvatarElementImpl extends HTMLElement {
|
|
@@ -1127,6 +1312,8 @@ function createElementClass() {
|
|
|
1127
1312
|
} else if (name === "border-radius") c.setBorderRadius(radiusAttr(newV));
|
|
1128
1313
|
else if (name === "draggable") c.setDraggable(boolAttr(this, "draggable", false));
|
|
1129
1314
|
else if (name === "resizable" || name === "min-size" || name === "max-size") c.setResizable(this.resizableOption());
|
|
1315
|
+
else if (name.startsWith("camera-")) void c.setConfig({ camera: cameraAttrs(this) }).catch(() => {
|
|
1316
|
+
});
|
|
1130
1317
|
else if (name === "mic") void c.mic(boolAttr(this, "mic", false)).catch(() => {
|
|
1131
1318
|
});
|
|
1132
1319
|
else if (name === "paused") {
|
|
@@ -1159,10 +1346,13 @@ function createElementClass() {
|
|
|
1159
1346
|
outfit: this.getAttribute("outfit") ?? this.getAttribute("model") ?? void 0,
|
|
1160
1347
|
scene: this.getAttribute("scene") ?? void 0,
|
|
1161
1348
|
persist: this.getAttribute("persist") || void 0,
|
|
1349
|
+
persistBox: persistBoxAttr(this.getAttribute("persist-box")),
|
|
1162
1350
|
allowCustomModel: boolAttr(this, "allow-custom-model", false),
|
|
1163
1351
|
prefetch: prefetchAttr(this.getAttribute("prefetch")),
|
|
1164
1352
|
heavy: this.getAttribute("heavy") ?? void 0,
|
|
1165
1353
|
ui: uiAttr(this.getAttribute("ui")),
|
|
1354
|
+
uiAutoHide: parseXcUiAutoHide(this.getAttribute("ui-autohide")),
|
|
1355
|
+
camera: cameraAttrs(this),
|
|
1166
1356
|
controls: boolAttr(this, "controls", true),
|
|
1167
1357
|
crossOriginIsolated: boolAttr(this, "cross-origin-isolated", false)
|
|
1168
1358
|
});
|
|
@@ -1176,6 +1366,7 @@ function createElementClass() {
|
|
|
1176
1366
|
fwd("error", "xc-error");
|
|
1177
1367
|
fwd("outfit-changed", "xc-outfit-changed");
|
|
1178
1368
|
fwd("scene-changed", "xc-scene-changed");
|
|
1369
|
+
fwd("lang-changed", "xc-lang-changed");
|
|
1179
1370
|
fwd("move", "xc-move");
|
|
1180
1371
|
fwd("resize", "xc-resize");
|
|
1181
1372
|
if (boolAttr(this, "paused", false)) c.pause();
|
|
@@ -1215,6 +1406,9 @@ function createElementClass() {
|
|
|
1215
1406
|
getScenes() {
|
|
1216
1407
|
return this.requireClient().getScenes();
|
|
1217
1408
|
}
|
|
1409
|
+
clearPersistedBox(opts) {
|
|
1410
|
+
this.client?.clearPersistedBox(opts);
|
|
1411
|
+
}
|
|
1218
1412
|
prefetch(ids) {
|
|
1219
1413
|
return this.requireClient().prefetch(ids);
|
|
1220
1414
|
}
|