@firetable/project-xiaochun 0.1.18 → 0.1.19
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 +8 -5
- package/README.md +8 -5
- package/dist/avatar-element.d.ts +3 -1
- package/dist/chunks/{chunk-KL7L3MGQ.js → chunk-RTBOYZAZ.js} +6 -3
- package/dist/chunks/chunk-RTBOYZAZ.js.map +7 -0
- package/dist/chunks/{chunk-Y5MRWV67.js → chunk-SPCT7EQA.js} +10 -4
- package/dist/chunks/chunk-SPCT7EQA.js.map +7 -0
- package/dist/chunks/{chunk-BN4H52OR.js → chunk-WYS3WVG4.js} +14 -3
- package/dist/chunks/chunk-WYS3WVG4.js.map +7 -0
- package/dist/client.d.ts +9 -0
- package/dist/element.cjs +18 -1
- package/dist/element.cjs.map +2 -2
- package/dist/element.js +4 -4
- package/dist/index.cjs +22 -2
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +4 -4
- package/dist/loader.global.js +2 -2
- package/dist/loader.global.js.map +3 -3
- package/dist/protocol.cjs +5 -2
- package/dist/protocol.cjs.map +2 -2
- package/dist/protocol.d.ts +36 -3
- package/dist/protocol.js +2 -2
- package/dist/react.cjs +14 -1
- package/dist/react.cjs.map +2 -2
- package/dist/react.d.ts +4 -0
- package/dist/react.js +5 -3
- package/dist/react.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunks/chunk-BN4H52OR.js.map +0 -7
- package/dist/chunks/chunk-KL7L3MGQ.js.map +0 -7
- package/dist/chunks/chunk-Y5MRWV67.js.map +0 -7
package/dist/react.d.ts
CHANGED
|
@@ -83,6 +83,10 @@ export interface XiaochunHandle {
|
|
|
83
83
|
mic(enabled: boolean): Promise<void>;
|
|
84
84
|
pause(): void;
|
|
85
85
|
resume(): void;
|
|
86
|
+
/** 改正在播的宿主音频倍速 (0.25~3)。见 XiaochunInstance.setPlaybackRate。 */
|
|
87
|
+
setPlaybackRate(rate: number): void;
|
|
88
|
+
/** 改宿主音频音量 (0~1)。见 XiaochunInstance.setVolume。 */
|
|
89
|
+
setVolume(volume: number): void;
|
|
86
90
|
activate(): void;
|
|
87
91
|
destroy(): void;
|
|
88
92
|
/** 模型加载完成时 resolve。 */
|
package/dist/react.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
/*! @firetable/project-xiaochun v0.1.
|
|
1
|
+
/*! @firetable/project-xiaochun v0.1.19 | MIT | https://github.com/FireTable/project-xiaochun */
|
|
2
2
|
"use client";
|
|
3
3
|
import {
|
|
4
4
|
createXiaochun,
|
|
5
5
|
defaultHeightCss,
|
|
6
6
|
defaultWidthCss
|
|
7
|
-
} from "./chunks/chunk-
|
|
7
|
+
} from "./chunks/chunk-WYS3WVG4.js";
|
|
8
8
|
import {
|
|
9
9
|
isXcId
|
|
10
|
-
} from "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-RTBOYZAZ.js";
|
|
11
11
|
|
|
12
12
|
// src/react.ts
|
|
13
13
|
import { createElement, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
@@ -182,6 +182,8 @@ function XiaochunInner(props, ref) {
|
|
|
182
182
|
mic: (e) => c()?.mic(e) ?? reject(),
|
|
183
183
|
pause: () => c()?.pause(),
|
|
184
184
|
resume: () => c()?.resume(),
|
|
185
|
+
setPlaybackRate: (rate) => c()?.setPlaybackRate(rate),
|
|
186
|
+
setVolume: (volume) => c()?.setVolume(volume),
|
|
185
187
|
activate: () => c()?.activate(),
|
|
186
188
|
destroy: () => c()?.destroy(),
|
|
187
189
|
get ready() {
|
package/dist/react.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/react.ts"],
|
|
4
|
-
"sourcesContent": ["'use client';\n/**\n * react.ts \u2014 React \u5C01\u88C5 (\u5B50\u8DEF\u5F84\u5BFC\u51FA `@firetable/project-xiaochun/react`, react \u662F\u53EF\u9009 peerDependency)\u3002\n *\n * import { Xiaochun, useXiaochun } from '@firetable/project-xiaochun/react';\n * <Xiaochun ref={ref} width={320} height={480} transparent onReady={...} />\n * ref.current?.say('\u4F60\u597D') / ref.current?.speakAudio(arrayBuffer)\n *\n * \u8BBE\u8BA1\u8981\u70B9:\n * - \u517C\u5BB9 React 18 / 19 (\u53EA\u7528 forwardRef / useImperativeHandle / useEffect / useState / createElement, \u4E0D\u5199 JSX \u2192 \u65E0\u9700 jsx \u8FD0\u884C\u65F6)\u3002\n * - SSR / Next.js \u5B89\u5168: \u6587\u4EF6\u5934 'use client'; \u670D\u52A1\u7AEF\u53EA\u6E32\u67D3\u4E00\u4E2A**\u56FA\u5B9A\u5C3A\u5BF8**\u7684\u7A7A <div> (\u4E0D\u4EA7\u751F CLS), iframe \u53EA\u5728\u5BA2\u6237\u7AEF effect \u91CC\u521B\u5EFA\u3002\n * - StrictMode \u53CC\u6302\u8F7D\u4E0D\u6CC4\u6F0F: effect cleanup \u4E00\u5B9A destroy(); lazy \u6A21\u5F0F\u4E0B\u5047\u6302\u8F7D\u6839\u672C\u4E0D\u4F1A\u521B\u5EFA iframe\u3002\n * - \u4E0D\u6539\u53D8\u4E3B\u5165\u53E3\u4F53\u79EF: \u4E3B\u5165\u53E3 (index) \u4E0D\u5F15\u7528\u672C\u6587\u4EF6, \u4E0D\u7528 React \u7684\u4EBA\u4E0D\u4F1A\u591A\u62C9\u4E00\u4E2A\u5B57\u8282\u3002\n * - \u521B\u5EFA\u671F\u9009\u9879 (src/lazy/position/\u2026) \u53D8\u5316\u4F1A\u91CD\u5EFA\u5B9E\u4F8B; lang / outfit / scene / paused / mic / width / height / draggable / resizable / borderRadius / camera \u53D8\u5316\u5219\u70ED\u66F4\u65B0\n * (\u4E0D\u91CD\u5EFA iframe, effect \u91CC\u8C03 setter)\u3002\u5C24\u5176 width / height: \u7528\u6237\u7F29\u653E (resizable) \u540E\u5BBF\u4E3B\u628A\u65B0\u5C3A\u5BF8\u5199\u56DE props \u4E5F\u4E0D\u4F1A\u91CD\u5EFA, \u6A21\u578B / \u52A8\u753B\u72B6\u6001\u90FD\u4FDD\u7559\u3002\n */\nimport { createElement, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport type { CSSProperties, ForwardedRef, ReactElement } from 'react';\nimport { createXiaochun, defaultHeightCss, defaultWidthCss } from './client';\nimport type {\n XiaochunAudioOptions,\n XiaochunAudioSource,\n XiaochunAudioStream,\n XiaochunEvents,\n XiaochunInstance,\n XiaochunOptions,\n} from './client';\nimport { isXcId } from './protocol';\nimport type { XcConfig, XcExpressionPayload, XcMotionPayload, XcOutfitInfo, XcPrefetchedPayload, XcSceneInfo, XcStatePayload } from './protocol';\n\n/** \u4E8B\u4EF6\u56DE\u8C03 (\u5168\u90E8\u53EF\u9009)\u3002\u5F15\u7528\u53D8\u5316\u4E0D\u4F1A\u91CD\u5EFA\u5B9E\u4F8B (\u5185\u90E8\u7528 ref \u6301\u6709\u6700\u65B0\u503C)\u3002 */\nexport interface XiaochunCallbacks {\n /** xc.ready \u63E1\u624B\u6210\u529F\u3002 */\n onHandshake?: (p: XiaochunEvents['handshake']) => void;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210 (= xc.loaded)\u3002 */\n onReady?: (p: XiaochunEvents['ready']) => void;\n onProgress?: (p: XiaochunEvents['progress']) => void;\n onState?: (p: XiaochunEvents['state']) => void;\n onStt?: (p: XiaochunEvents['stt']) => void;\n onUtterance?: (p: XiaochunEvents['utterance']) => void;\n onHitRegion?: (p: XiaochunEvents['hit-region']) => void;\n /** \u670D\u88C5\u5DF2\u751F\u6548 (\u542B\u9996\u6B21\u52A0\u8F7D initial:true)\u3002 */\n onOutfitChanged?: (p: XiaochunEvents['outfit-changed']) => void;\n /** \u573A\u666F\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u573A\u666F initial:true)\u3002 */\n onSceneChanged?: (p: XiaochunEvents['scene-changed']) => void;\n /** iframe \u754C\u9762\u8BED\u8A00\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u8BED\u8A00 initial:true; \u7528\u6237\u70B9\u8BED\u8A00\u6309\u94AE / setConfig({ lang }) \u5F15\u8D77\u7684\u53D8\u5316)\u3002 */\n onLangChanged?: (p: XiaochunEvents['lang-changed']) => void;\n onError?: (p: XiaochunEvents['error']) => void;\n onDestroy?: () => void;\n /** \u7528\u6237\u62D6\u52A8\u5934\u50CF (draggable): start / move / end, \u4F4D\u7F6E\u5DF2\u9650\u5E45 (\u89C6\u53E3\u5750\u6807)\u3002 */\n onMove?: (p: XiaochunEvents['move']) => void;\n /** \u7528\u6237\u7F29\u653E\u5934\u50CF (resizable): start / move / end, \u5C3A\u5BF8\u5DF2\u9650\u5E45\u3002\u60F3\u628A\u5C3A\u5BF8\u540C\u6B65\u8FDB\u81EA\u5DF1\u7684\u72B6\u6001, \u5728 phase === 'end' \u65F6\u5199\u56DE width / height \u5373\u53EF (\u4E0D\u4F1A\u91CD\u5EFA iframe)\u3002 */\n onResize?: (p: XiaochunEvents['resize']) => void;\n}\n\nexport interface XiaochunHookOptions extends Omit<XiaochunOptions, 'container'>, XiaochunCallbacks {\n /** \u53D7\u63A7\u6682\u505C: true = xc.pause, false = xc.resume\u3002 */\n paused?: boolean;\n /** \u53D7\u63A7\u9EA6\u514B\u98CE: true = \u5F00\u59CB\u542C (\u9996\u6B21\u4F1A\u52A0\u8F7D STT), false = \u505C\u3002 */\n mic?: boolean;\n}\n\nexport interface UseXiaochunResult {\n /** \u7ED1\u5B9A\u5230\u4F60\u81EA\u5DF1\u7684\u5BB9\u5668: `<div ref={containerRef} style={{ width: 320, height: 480 }} />`\u3002\u56DE\u8C03 ref, React 18/19 \u901A\u7528\u3002 */\n containerRef: (el: HTMLElement | null) => void;\n /** \u5E95\u5C42 SDK \u5B9E\u4F8B; \u670D\u52A1\u7AEF / \u5C1A\u672A\u6302\u8F7D / \u5DF2\u5378\u8F7D\u65F6\u4E3A null\u3002 */\n client: XiaochunInstance | null;\n /** \u6A21\u578B\u662F\u5426\u52A0\u8F7D\u5B8C\u6210\u3002 */\n ready: boolean;\n /** \u6700\u8FD1\u4E00\u6B21 xc.state\u3002 */\n state: XcStatePayload | null;\n}\n\nconst EVENT_MAP: Array<[keyof XiaochunEvents, keyof XiaochunCallbacks]> = [\n ['handshake', 'onHandshake'],\n ['ready', 'onReady'],\n ['progress', 'onProgress'],\n ['state', 'onState'],\n ['stt', 'onStt'],\n ['utterance', 'onUtterance'],\n ['hit-region', 'onHitRegion'],\n ['outfit-changed', 'onOutfitChanged'],\n ['scene-changed', 'onSceneChanged'],\n ['lang-changed', 'onLangChanged'],\n ['error', 'onError'],\n ['move', 'onMove'],\n ['resize', 'onResize'],\n ['destroy', 'onDestroy'],\n];\n\n/**\n * \u5728\u4F60\u81EA\u5DF1\u7684\u5BB9\u5668\u91CC\u521B\u5EFA / \u9500\u6BC1\u4E00\u4E2A\u5C0F\u8822\u5B9E\u4F8B (\u5BA2\u6237\u7AEF only)\u3002\n * \u9700\u8981\u5B8C\u5168\u81EA\u5B9A\u4E49\u5E03\u5C40\u65F6\u7528\u5B83; \u60F3\u7701\u4E8B\u7528 <Xiaochun />\u3002\n */\nexport function useXiaochun(options: XiaochunHookOptions = {}): UseXiaochunResult {\n const [el, setEl] = useState<HTMLElement | null>(null);\n const [client, setClient] = useState<XiaochunInstance | null>(null);\n const [ready, setReady] = useState(false);\n const [state, setState] = useState<XcStatePayload | null>(null);\n\n // \u56DE\u8C03\u4E0E\"\u70ED\u66F4\u65B0\u578B\"\u9009\u9879\u653E\u8FDB ref: \u5B83\u4EEC\u53D8\u5316\u4E0D\u5E94\u91CD\u5EFA iframe\n const live = useRef(options);\n live.current = options;\n\n const o = options;\n const originsKey = (o.allowedOrigins ?? []).join(',');\n\n useEffect(() => {\n if (!el) return;\n const cur = live.current;\n const { onHandshake: _a, onReady: _b, onProgress: _c, onState: _d, onStt: _e, onUtterance: _f, onHitRegion: _g, onError: _h, onDestroy: _i, onOutfitChanged: _j, onSceneChanged: _k, onLangChanged: _l, onMove: _q, onResize: _r, paused: _p, mic: _m, allowedOrigins, ...create } = cur;\n void [_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _p, _m, _q, _r];\n const inst = createXiaochun({ ...create, allowedOrigins: allowedOrigins?.slice(), container: el });\n const offs: Array<() => void> = [];\n for (const [ev, cbName] of EVENT_MAP) {\n offs.push(inst.on(ev, (p: unknown) => { (live.current[cbName] as ((x: unknown) => void) | undefined)?.(p); }));\n }\n offs.push(inst.on('ready', () => setReady(true)));\n offs.push(inst.on('state', (s) => setState(s)));\n if (cur.paused) inst.pause();\n if (cur.mic) void inst.ready.then(() => inst.mic(true)).catch(() => {});\n setClient(inst);\n return () => {\n // StrictMode \u7684\u5047\u5378\u8F7D / \u771F\u5378\u8F7D / \u91CD\u5EFA \u90FD\u8D70\u8FD9\u91CC: \u5FC5\u987B\u9500\u6BC1, \u5426\u5219 iframe \u4E0E window \u76D1\u542C\u6CC4\u6F0F\n offs.forEach((off) => off());\n inst.destroy();\n setClient(null);\n setReady(false);\n setState(null);\n };\n // \u53EA\u6709\"\u521B\u5EFA\u671F\u9009\u9879\"\u53D8\u5316\u624D\u91CD\u5EFA; lang/outfit/scene/paused/mic/\u56DE\u8C03\u8D70\u4E0B\u9762\u7684\u70ED\u66F4\u65B0\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [el, o.src, o.origin, originsKey, o.lazy, o.lazyMargin, o.placeholder, o.transparent, o.position,\n JSON.stringify(o.ui ?? null), o.uiAutoHide, o.heavy, o.controls, o.autoPause, o.passthrough, o.sandbox, o.handshakeTimeout, o.crossOriginIsolated, o.zIndex,\n o.allowCustomModel, o.persist, o.persistBox, Array.isArray(o.prefetch) ? o.prefetch.join(',') : o.prefetch]);\n\n // \u70ED\u66F4\u65B0: lang / outfit (model \u662F\u65E7\u522B\u540D) / scene (\u8DF3\u8FC7\u9996\u6B21: \u521B\u5EFA\u65F6\u5DF2\u7ECF\u4F5C\u4E3A\u521D\u59CB\u9009\u9879\u4F20\u5165)\u3002\n // transparent \u662F\u521B\u5EFA\u671F\u9009\u9879 (\u53D8\u5316\u4F1A\u91CD\u5EFA); \u60F3\u4E0D\u91CD\u5EFA\u5730\u5207\u900F\u660E\u8BF7\u7528 scene\u3002\n const wantOutfit = o.outfit ?? o.model;\n const cameraKey = JSON.stringify(o.camera ?? null);\n const first = useRef({ lang: o.lang, outfit: wantOutfit, scene: o.scene, width: o.width, height: o.height, camera: cameraKey });\n const resizableKey = JSON.stringify(o.resizable ?? false);\n useEffect(() => {\n if (!client || first.current.lang === o.lang) return;\n first.current.lang = o.lang;\n if (o.lang) void client.setConfig({ lang: o.lang }).catch(() => {});\n }, [client, o.lang]);\n useEffect(() => {\n if (!client || first.current.outfit === wantOutfit) return;\n first.current.outfit = wantOutfit;\n // busy / unknown_id \u4F1A\u8D70 onError, \u8FD9\u91CC\u4E0D\u91CD\u590D\u5904\u7406; \u65E7\u7528\u6CD5 model=\"https://\u2026\" \u4ECD\u8D70 setModel (\u53D7 allowCustomModel \u7EA6\u675F)\n if (wantOutfit) void (isXcId(wantOutfit) ? client.setOutfit(wantOutfit) : client.setModel(wantOutfit)).catch(() => {});\n }, [client, wantOutfit]);\n // camera: \u70ED\u66F4\u65B0 (\u521B\u5EFA\u65F6\u5DF2\u968F URL \u4F20\u5165; \u4E4B\u540E\u53D8\u5316\u8D70 setConfig, \u5C11\u5199\u7684\u9879 = null \u6062\u590D\u9ED8\u8BA4; \u7ACB\u523B\u91CD\u65B0\u53D6\u666F\u5E76\u53D6\u6D88\u8FDB\u884C\u4E2D\u7684\u63A8\u955C\u5934)\n useEffect(() => {\n if (!client || first.current.camera === cameraKey) return;\n first.current.camera = cameraKey;\n const c = o.camera;\n void client.setConfig({ camera: { fov: c?.fov ?? null, distance: c?.distance ?? null, height: c?.height ?? null, intro: c?.intro ?? null } }).catch(() => {});\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, cameraKey]);\n useEffect(() => {\n if (!client || first.current.scene === o.scene) return;\n first.current.scene = o.scene;\n if (o.scene) void client.setScene(o.scene).catch(() => {});\n }, [client, o.scene]);\n // \u5C3A\u5BF8 / \u624B\u52BF\u5F00\u5173: \u70ED\u66F4\u65B0, \u4E0D\u91CD\u5EFA iframe (\u7F29\u653E\u662F\u8FD0\u884C\u65F6\u72B6\u6001; \u53EA\u6709 props \u91CC\u7684\u503C\u771F\u7684\u53D8\u4E86\u624D\u8C03 setSize, \u7528\u6237\u7F29\u653E\u540E\u7684\u5C3A\u5BF8\u4E0D\u4F1A\u88AB\u65E0\u5173\u7684\u91CD\u6E32\u67D3\u8986\u76D6)\n useEffect(() => {\n if (!client || (first.current.width === o.width && first.current.height === o.height)) return;\n first.current.width = o.width; first.current.height = o.height;\n client.setSize(o.width, o.height); // undefined = \u9ED8\u8BA4 600x1080 (\u53D7\u89C6\u53E3\u9650\u5236)\n }, [client, o.width, o.height]);\n useEffect(() => { client?.setDraggable(o.draggable === true); }, [client, o.draggable]);\n useEffect(() => { client?.setBorderRadius(o.borderRadius); }, [client, o.borderRadius]);\n useEffect(() => { client?.setResizable(o.resizable ?? false); // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, resizableKey]);\n useEffect(() => {\n if (!client || o.paused === undefined) return;\n if (o.paused) client.pause(); else client.resume();\n }, [client, o.paused]);\n const micWanted = useRef(o.mic);\n useEffect(() => {\n if (!client || o.mic === undefined || micWanted.current === o.mic) { micWanted.current = o.mic; return; }\n micWanted.current = o.mic;\n void client.mic(!!o.mic).catch(() => {});\n }, [client, o.mic]);\n\n const containerRef = useCallback((node: HTMLElement | null) => setEl(node), []);\n return { containerRef, client, ready, state };\n}\n\n/** ref \u66B4\u9732\u7684\u547D\u4EE4\u5F0F\u53E5\u67C4 (\u5B9E\u4F8B\u5C1A\u672A\u521B\u5EFA / \u5DF2\u9500\u6BC1\u65F6, \u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u4F1A reject)\u3002 */\nexport interface XiaochunHandle {\n say(text: string, opts?: { mode?: 'speak' | 'chat' }): Promise<void>;\n /** \u76F4\u63A5\u64AD\u653E\u5BBF\u4E3B\u7ED9\u7684\u97F3\u9891 (\u4E0D\u8D70 TTS), \u540C\u65F6\u7531 EMAGE \u751F\u6210\u52A8\u4F5C + \u53E3\u578B\u3002 */\n speakAudio(source: XiaochunAudioSource, opts?: XiaochunAudioOptions): Promise<void>;\n speakAudioStream(opts: XiaochunAudioOptions & { sampleRate: number }): XiaochunAudioStream;\n motion(m: XcMotionPayload | string): Promise<void>;\n expression(name: XcExpressionPayload['name']): Promise<void>;\n /** TODO: \u534F\u8BAE\u5DF2\u9884\u7559, /embed \u6682\u672A\u5B9E\u73B0 \u2192 reject unsupported\u3002 */\n lookAt(x: number, y: number): Promise<void>;\n /** \u6362\u5185\u7F6E\u670D\u88C5 (\u4E32\u884C + last-wins, \u89C1 XiaochunInstance.setOutfit)\u3002 */\n setOutfit(id: string): Promise<void>;\n setScene(id: string): Promise<void>;\n getOutfits(): Promise<XcOutfitInfo[]>;\n getScenes(): Promise<XcSceneInfo[]>;\n /** \u6E05\u9664 persistBox \u4FDD\u5B58\u7684\u4F4D\u7F6E / \u5927\u5C0F; { reset: true } \u540C\u65F6\u8FD8\u539F\u5230\u521D\u59CB\u4F4D\u7F6E\u548C\u5927\u5C0F\u3002 */\n clearPersistedBox(opts?: { reset?: boolean }): void;\n /** \u9884\u53D6\u670D\u88C5\u8D44\u6E90\u5230 iframe \u7684 IndexedDB; ids \u7701\u7565 = \u5168\u90E8 (\u5A5A\u7EB1\u9664\u5916)\u3002 */\n prefetch(ids?: string[]): Promise<XcPrefetchedPayload>;\n /** \u65E7\u547D\u4EE4; \u4EFB\u610F URL \u9700 allowCustomModel\u3002\u5185\u7F6E\u670D\u88C5\u8BF7\u7528 setOutfit\u3002 */\n setModel(m: string | { url?: string; outfit?: string; name?: string }): Promise<void>;\n setConfig(cfg: XcConfig): Promise<void>;\n startListening(): Promise<void>;\n stopListening(): Promise<void>;\n mic(enabled: boolean): Promise<void>;\n pause(): void;\n resume(): void;\n activate(): void;\n destroy(): void;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210\u65F6 resolve\u3002 */\n readonly ready: Promise<void>;\n /** \u5E95\u5C42 SDK \u5B9E\u4F8B (\u670D\u52A1\u7AEF / \u672A\u6302\u8F7D\u65F6 null)\u3002 */\n readonly instance: XiaochunInstance | null;\n}\n\nexport interface XiaochunProps extends XiaochunHookOptions {\n className?: string;\n /** \u5916\u5C42 div \u7684\u6837\u5F0F; width/height \u7531 props \u51B3\u5B9A (\u56FA\u5B9A\u5C3A\u5BF8, \u9632 CLS), \u8FD9\u91CC\u7684\u540C\u540D\u5B57\u6BB5\u4F1A\u88AB\u8986\u76D6\u3002 */\n style?: CSSProperties;\n}\n\nconst css = (v: number | string | undefined, d: string) => (v === undefined ? d : typeof v === 'number' ? `${v}px` : v);\nconst NOT_MOUNTED = () => new Error('[project-xiaochun] <Xiaochun /> is not mounted');\n\nfunction XiaochunInner(props: XiaochunProps, ref: ForwardedRef<XiaochunHandle>): ReactElement {\n const { className, style, ...hookOptions } = props;\n const { containerRef, client } = useXiaochun(hookOptions);\n const clientRef = useRef<XiaochunInstance | null>(null);\n clientRef.current = client;\n\n useImperativeHandle(ref, () => {\n const c = () => clientRef.current;\n const reject = <T,>(): Promise<T> => Promise.reject(NOT_MOUNTED());\n return {\n say: (t, o) => c()?.say(t, o) ?? reject(),\n speakAudio: (s, o) => c()?.speakAudio(s, o) ?? reject(),\n speakAudioStream: (o) => { const x = c(); if (!x) throw NOT_MOUNTED(); return x.speakAudioStream(o); },\n motion: (m) => c()?.motion(m) ?? reject(),\n expression: (n) => c()?.expression(n) ?? reject(),\n lookAt: (x, y) => c()?.lookAt(x, y) ?? reject(),\n setOutfit: (id) => c()?.setOutfit(id) ?? reject(),\n setScene: (id) => c()?.setScene(id) ?? reject(),\n getOutfits: () => c()?.getOutfits() ?? reject(),\n getScenes: () => c()?.getScenes() ?? reject(),\n clearPersistedBox: (opts) => c()?.clearPersistedBox(opts),\n prefetch: (ids) => c()?.prefetch(ids) ?? reject(),\n setModel: (m) => c()?.setModel(m) ?? reject(),\n setConfig: (cfg) => c()?.setConfig(cfg) ?? reject(),\n startListening: () => c()?.startListening() ?? reject(),\n stopListening: () => c()?.stopListening() ?? reject(),\n mic: (e) => c()?.mic(e) ?? reject(),\n pause: () => c()?.pause(),\n resume: () => c()?.resume(),\n activate: () => c()?.activate(),\n destroy: () => c()?.destroy(),\n get ready() { return c()?.ready ?? reject<void>(); },\n get instance() { return c(); },\n };\n }, []);\n\n // \u670D\u52A1\u7AEF\u4E0E\u9996\u5E27\u5BA2\u6237\u7AEF\u6E32\u67D3\u5B8C\u5168\u4E00\u81F4 (hydration \u5B89\u5168): \u56FA\u5B9A\u5C3A\u5BF8\u7684\u7A7A div\n const box: CSSProperties = {\n ...style,\n width: css(props.width, defaultWidthCss()),\n height: css(props.height, defaultHeightCss()),\n maxWidth: '100%',\n position: style?.position ?? 'relative',\n };\n return createElement('div', { ref: containerRef, className, style: box, 'data-xiaochun-host': '' });\n}\n\n/** `<Xiaochun />`: \u5728\u5BA2\u6237\u7AEF\u521B\u5EFA\u5C0F\u8822 iframe; ref \u66B4\u9732 say / speakAudio / motion / \u2026 \u7B49\u547D\u4EE4\u5F0F\u65B9\u6CD5\u3002 */\nexport const Xiaochun = forwardRef<XiaochunHandle, XiaochunProps>(XiaochunInner);\nXiaochun.displayName = 'Xiaochun';\n\nexport type { XiaochunOptions, XiaochunInstance, XiaochunAudioOptions, XiaochunAudioSource, XiaochunAudioStream } from './client';\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["'use client';\n/**\n * react.ts \u2014 React \u5C01\u88C5 (\u5B50\u8DEF\u5F84\u5BFC\u51FA `@firetable/project-xiaochun/react`, react \u662F\u53EF\u9009 peerDependency)\u3002\n *\n * import { Xiaochun, useXiaochun } from '@firetable/project-xiaochun/react';\n * <Xiaochun ref={ref} width={320} height={480} transparent onReady={...} />\n * ref.current?.say('\u4F60\u597D') / ref.current?.speakAudio(arrayBuffer)\n *\n * \u8BBE\u8BA1\u8981\u70B9:\n * - \u517C\u5BB9 React 18 / 19 (\u53EA\u7528 forwardRef / useImperativeHandle / useEffect / useState / createElement, \u4E0D\u5199 JSX \u2192 \u65E0\u9700 jsx \u8FD0\u884C\u65F6)\u3002\n * - SSR / Next.js \u5B89\u5168: \u6587\u4EF6\u5934 'use client'; \u670D\u52A1\u7AEF\u53EA\u6E32\u67D3\u4E00\u4E2A**\u56FA\u5B9A\u5C3A\u5BF8**\u7684\u7A7A <div> (\u4E0D\u4EA7\u751F CLS), iframe \u53EA\u5728\u5BA2\u6237\u7AEF effect \u91CC\u521B\u5EFA\u3002\n * - StrictMode \u53CC\u6302\u8F7D\u4E0D\u6CC4\u6F0F: effect cleanup \u4E00\u5B9A destroy(); lazy \u6A21\u5F0F\u4E0B\u5047\u6302\u8F7D\u6839\u672C\u4E0D\u4F1A\u521B\u5EFA iframe\u3002\n * - \u4E0D\u6539\u53D8\u4E3B\u5165\u53E3\u4F53\u79EF: \u4E3B\u5165\u53E3 (index) \u4E0D\u5F15\u7528\u672C\u6587\u4EF6, \u4E0D\u7528 React \u7684\u4EBA\u4E0D\u4F1A\u591A\u62C9\u4E00\u4E2A\u5B57\u8282\u3002\n * - \u521B\u5EFA\u671F\u9009\u9879 (src/lazy/position/\u2026) \u53D8\u5316\u4F1A\u91CD\u5EFA\u5B9E\u4F8B; lang / outfit / scene / paused / mic / width / height / draggable / resizable / borderRadius / camera \u53D8\u5316\u5219\u70ED\u66F4\u65B0\n * (\u4E0D\u91CD\u5EFA iframe, effect \u91CC\u8C03 setter)\u3002\u5C24\u5176 width / height: \u7528\u6237\u7F29\u653E (resizable) \u540E\u5BBF\u4E3B\u628A\u65B0\u5C3A\u5BF8\u5199\u56DE props \u4E5F\u4E0D\u4F1A\u91CD\u5EFA, \u6A21\u578B / \u52A8\u753B\u72B6\u6001\u90FD\u4FDD\u7559\u3002\n */\nimport { createElement, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport type { CSSProperties, ForwardedRef, ReactElement } from 'react';\nimport { createXiaochun, defaultHeightCss, defaultWidthCss } from './client';\nimport type {\n XiaochunAudioOptions,\n XiaochunAudioSource,\n XiaochunAudioStream,\n XiaochunEvents,\n XiaochunInstance,\n XiaochunOptions,\n} from './client';\nimport { isXcId } from './protocol';\nimport type { XcConfig, XcExpressionPayload, XcMotionPayload, XcOutfitInfo, XcPrefetchedPayload, XcSceneInfo, XcStatePayload } from './protocol';\n\n/** \u4E8B\u4EF6\u56DE\u8C03 (\u5168\u90E8\u53EF\u9009)\u3002\u5F15\u7528\u53D8\u5316\u4E0D\u4F1A\u91CD\u5EFA\u5B9E\u4F8B (\u5185\u90E8\u7528 ref \u6301\u6709\u6700\u65B0\u503C)\u3002 */\nexport interface XiaochunCallbacks {\n /** xc.ready \u63E1\u624B\u6210\u529F\u3002 */\n onHandshake?: (p: XiaochunEvents['handshake']) => void;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210 (= xc.loaded)\u3002 */\n onReady?: (p: XiaochunEvents['ready']) => void;\n onProgress?: (p: XiaochunEvents['progress']) => void;\n onState?: (p: XiaochunEvents['state']) => void;\n onStt?: (p: XiaochunEvents['stt']) => void;\n onUtterance?: (p: XiaochunEvents['utterance']) => void;\n onHitRegion?: (p: XiaochunEvents['hit-region']) => void;\n /** \u670D\u88C5\u5DF2\u751F\u6548 (\u542B\u9996\u6B21\u52A0\u8F7D initial:true)\u3002 */\n onOutfitChanged?: (p: XiaochunEvents['outfit-changed']) => void;\n /** \u573A\u666F\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u573A\u666F initial:true)\u3002 */\n onSceneChanged?: (p: XiaochunEvents['scene-changed']) => void;\n /** iframe \u754C\u9762\u8BED\u8A00\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u8BED\u8A00 initial:true; \u7528\u6237\u70B9\u8BED\u8A00\u6309\u94AE / setConfig({ lang }) \u5F15\u8D77\u7684\u53D8\u5316)\u3002 */\n onLangChanged?: (p: XiaochunEvents['lang-changed']) => void;\n onError?: (p: XiaochunEvents['error']) => void;\n onDestroy?: () => void;\n /** \u7528\u6237\u62D6\u52A8\u5934\u50CF (draggable): start / move / end, \u4F4D\u7F6E\u5DF2\u9650\u5E45 (\u89C6\u53E3\u5750\u6807)\u3002 */\n onMove?: (p: XiaochunEvents['move']) => void;\n /** \u7528\u6237\u7F29\u653E\u5934\u50CF (resizable): start / move / end, \u5C3A\u5BF8\u5DF2\u9650\u5E45\u3002\u60F3\u628A\u5C3A\u5BF8\u540C\u6B65\u8FDB\u81EA\u5DF1\u7684\u72B6\u6001, \u5728 phase === 'end' \u65F6\u5199\u56DE width / height \u5373\u53EF (\u4E0D\u4F1A\u91CD\u5EFA iframe)\u3002 */\n onResize?: (p: XiaochunEvents['resize']) => void;\n}\n\nexport interface XiaochunHookOptions extends Omit<XiaochunOptions, 'container'>, XiaochunCallbacks {\n /** \u53D7\u63A7\u6682\u505C: true = xc.pause, false = xc.resume\u3002 */\n paused?: boolean;\n /** \u53D7\u63A7\u9EA6\u514B\u98CE: true = \u5F00\u59CB\u542C (\u9996\u6B21\u4F1A\u52A0\u8F7D STT), false = \u505C\u3002 */\n mic?: boolean;\n}\n\nexport interface UseXiaochunResult {\n /** \u7ED1\u5B9A\u5230\u4F60\u81EA\u5DF1\u7684\u5BB9\u5668: `<div ref={containerRef} style={{ width: 320, height: 480 }} />`\u3002\u56DE\u8C03 ref, React 18/19 \u901A\u7528\u3002 */\n containerRef: (el: HTMLElement | null) => void;\n /** \u5E95\u5C42 SDK \u5B9E\u4F8B; \u670D\u52A1\u7AEF / \u5C1A\u672A\u6302\u8F7D / \u5DF2\u5378\u8F7D\u65F6\u4E3A null\u3002 */\n client: XiaochunInstance | null;\n /** \u6A21\u578B\u662F\u5426\u52A0\u8F7D\u5B8C\u6210\u3002 */\n ready: boolean;\n /** \u6700\u8FD1\u4E00\u6B21 xc.state\u3002 */\n state: XcStatePayload | null;\n}\n\nconst EVENT_MAP: Array<[keyof XiaochunEvents, keyof XiaochunCallbacks]> = [\n ['handshake', 'onHandshake'],\n ['ready', 'onReady'],\n ['progress', 'onProgress'],\n ['state', 'onState'],\n ['stt', 'onStt'],\n ['utterance', 'onUtterance'],\n ['hit-region', 'onHitRegion'],\n ['outfit-changed', 'onOutfitChanged'],\n ['scene-changed', 'onSceneChanged'],\n ['lang-changed', 'onLangChanged'],\n ['error', 'onError'],\n ['move', 'onMove'],\n ['resize', 'onResize'],\n ['destroy', 'onDestroy'],\n];\n\n/**\n * \u5728\u4F60\u81EA\u5DF1\u7684\u5BB9\u5668\u91CC\u521B\u5EFA / \u9500\u6BC1\u4E00\u4E2A\u5C0F\u8822\u5B9E\u4F8B (\u5BA2\u6237\u7AEF only)\u3002\n * \u9700\u8981\u5B8C\u5168\u81EA\u5B9A\u4E49\u5E03\u5C40\u65F6\u7528\u5B83; \u60F3\u7701\u4E8B\u7528 <Xiaochun />\u3002\n */\nexport function useXiaochun(options: XiaochunHookOptions = {}): UseXiaochunResult {\n const [el, setEl] = useState<HTMLElement | null>(null);\n const [client, setClient] = useState<XiaochunInstance | null>(null);\n const [ready, setReady] = useState(false);\n const [state, setState] = useState<XcStatePayload | null>(null);\n\n // \u56DE\u8C03\u4E0E\"\u70ED\u66F4\u65B0\u578B\"\u9009\u9879\u653E\u8FDB ref: \u5B83\u4EEC\u53D8\u5316\u4E0D\u5E94\u91CD\u5EFA iframe\n const live = useRef(options);\n live.current = options;\n\n const o = options;\n const originsKey = (o.allowedOrigins ?? []).join(',');\n\n useEffect(() => {\n if (!el) return;\n const cur = live.current;\n const { onHandshake: _a, onReady: _b, onProgress: _c, onState: _d, onStt: _e, onUtterance: _f, onHitRegion: _g, onError: _h, onDestroy: _i, onOutfitChanged: _j, onSceneChanged: _k, onLangChanged: _l, onMove: _q, onResize: _r, paused: _p, mic: _m, allowedOrigins, ...create } = cur;\n void [_a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _p, _m, _q, _r];\n const inst = createXiaochun({ ...create, allowedOrigins: allowedOrigins?.slice(), container: el });\n const offs: Array<() => void> = [];\n for (const [ev, cbName] of EVENT_MAP) {\n offs.push(inst.on(ev, (p: unknown) => { (live.current[cbName] as ((x: unknown) => void) | undefined)?.(p); }));\n }\n offs.push(inst.on('ready', () => setReady(true)));\n offs.push(inst.on('state', (s) => setState(s)));\n if (cur.paused) inst.pause();\n if (cur.mic) void inst.ready.then(() => inst.mic(true)).catch(() => {});\n setClient(inst);\n return () => {\n // StrictMode \u7684\u5047\u5378\u8F7D / \u771F\u5378\u8F7D / \u91CD\u5EFA \u90FD\u8D70\u8FD9\u91CC: \u5FC5\u987B\u9500\u6BC1, \u5426\u5219 iframe \u4E0E window \u76D1\u542C\u6CC4\u6F0F\n offs.forEach((off) => off());\n inst.destroy();\n setClient(null);\n setReady(false);\n setState(null);\n };\n // \u53EA\u6709\"\u521B\u5EFA\u671F\u9009\u9879\"\u53D8\u5316\u624D\u91CD\u5EFA; lang/outfit/scene/paused/mic/\u56DE\u8C03\u8D70\u4E0B\u9762\u7684\u70ED\u66F4\u65B0\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [el, o.src, o.origin, originsKey, o.lazy, o.lazyMargin, o.placeholder, o.transparent, o.position,\n JSON.stringify(o.ui ?? null), o.uiAutoHide, o.heavy, o.controls, o.autoPause, o.passthrough, o.sandbox, o.handshakeTimeout, o.crossOriginIsolated, o.zIndex,\n o.allowCustomModel, o.persist, o.persistBox, Array.isArray(o.prefetch) ? o.prefetch.join(',') : o.prefetch]);\n\n // \u70ED\u66F4\u65B0: lang / outfit (model \u662F\u65E7\u522B\u540D) / scene (\u8DF3\u8FC7\u9996\u6B21: \u521B\u5EFA\u65F6\u5DF2\u7ECF\u4F5C\u4E3A\u521D\u59CB\u9009\u9879\u4F20\u5165)\u3002\n // transparent \u662F\u521B\u5EFA\u671F\u9009\u9879 (\u53D8\u5316\u4F1A\u91CD\u5EFA); \u60F3\u4E0D\u91CD\u5EFA\u5730\u5207\u900F\u660E\u8BF7\u7528 scene\u3002\n const wantOutfit = o.outfit ?? o.model;\n const cameraKey = JSON.stringify(o.camera ?? null);\n const first = useRef({ lang: o.lang, outfit: wantOutfit, scene: o.scene, width: o.width, height: o.height, camera: cameraKey });\n const resizableKey = JSON.stringify(o.resizable ?? false);\n useEffect(() => {\n if (!client || first.current.lang === o.lang) return;\n first.current.lang = o.lang;\n if (o.lang) void client.setConfig({ lang: o.lang }).catch(() => {});\n }, [client, o.lang]);\n useEffect(() => {\n if (!client || first.current.outfit === wantOutfit) return;\n first.current.outfit = wantOutfit;\n // busy / unknown_id \u4F1A\u8D70 onError, \u8FD9\u91CC\u4E0D\u91CD\u590D\u5904\u7406; \u65E7\u7528\u6CD5 model=\"https://\u2026\" \u4ECD\u8D70 setModel (\u53D7 allowCustomModel \u7EA6\u675F)\n if (wantOutfit) void (isXcId(wantOutfit) ? client.setOutfit(wantOutfit) : client.setModel(wantOutfit)).catch(() => {});\n }, [client, wantOutfit]);\n // camera: \u70ED\u66F4\u65B0 (\u521B\u5EFA\u65F6\u5DF2\u968F URL \u4F20\u5165; \u4E4B\u540E\u53D8\u5316\u8D70 setConfig, \u5C11\u5199\u7684\u9879 = null \u6062\u590D\u9ED8\u8BA4; \u7ACB\u523B\u91CD\u65B0\u53D6\u666F\u5E76\u53D6\u6D88\u8FDB\u884C\u4E2D\u7684\u63A8\u955C\u5934)\n useEffect(() => {\n if (!client || first.current.camera === cameraKey) return;\n first.current.camera = cameraKey;\n const c = o.camera;\n void client.setConfig({ camera: { fov: c?.fov ?? null, distance: c?.distance ?? null, height: c?.height ?? null, intro: c?.intro ?? null } }).catch(() => {});\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, cameraKey]);\n useEffect(() => {\n if (!client || first.current.scene === o.scene) return;\n first.current.scene = o.scene;\n if (o.scene) void client.setScene(o.scene).catch(() => {});\n }, [client, o.scene]);\n // \u5C3A\u5BF8 / \u624B\u52BF\u5F00\u5173: \u70ED\u66F4\u65B0, \u4E0D\u91CD\u5EFA iframe (\u7F29\u653E\u662F\u8FD0\u884C\u65F6\u72B6\u6001; \u53EA\u6709 props \u91CC\u7684\u503C\u771F\u7684\u53D8\u4E86\u624D\u8C03 setSize, \u7528\u6237\u7F29\u653E\u540E\u7684\u5C3A\u5BF8\u4E0D\u4F1A\u88AB\u65E0\u5173\u7684\u91CD\u6E32\u67D3\u8986\u76D6)\n useEffect(() => {\n if (!client || (first.current.width === o.width && first.current.height === o.height)) return;\n first.current.width = o.width; first.current.height = o.height;\n client.setSize(o.width, o.height); // undefined = \u9ED8\u8BA4 600x1080 (\u53D7\u89C6\u53E3\u9650\u5236)\n }, [client, o.width, o.height]);\n useEffect(() => { client?.setDraggable(o.draggable === true); }, [client, o.draggable]);\n useEffect(() => { client?.setBorderRadius(o.borderRadius); }, [client, o.borderRadius]);\n useEffect(() => { client?.setResizable(o.resizable ?? false); // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, resizableKey]);\n useEffect(() => {\n if (!client || o.paused === undefined) return;\n if (o.paused) client.pause(); else client.resume();\n }, [client, o.paused]);\n const micWanted = useRef(o.mic);\n useEffect(() => {\n if (!client || o.mic === undefined || micWanted.current === o.mic) { micWanted.current = o.mic; return; }\n micWanted.current = o.mic;\n void client.mic(!!o.mic).catch(() => {});\n }, [client, o.mic]);\n\n const containerRef = useCallback((node: HTMLElement | null) => setEl(node), []);\n return { containerRef, client, ready, state };\n}\n\n/** ref \u66B4\u9732\u7684\u547D\u4EE4\u5F0F\u53E5\u67C4 (\u5B9E\u4F8B\u5C1A\u672A\u521B\u5EFA / \u5DF2\u9500\u6BC1\u65F6, \u8FD4\u56DE Promise \u7684\u65B9\u6CD5\u4F1A reject)\u3002 */\nexport interface XiaochunHandle {\n say(text: string, opts?: { mode?: 'speak' | 'chat' }): Promise<void>;\n /** \u76F4\u63A5\u64AD\u653E\u5BBF\u4E3B\u7ED9\u7684\u97F3\u9891 (\u4E0D\u8D70 TTS), \u540C\u65F6\u7531 EMAGE \u751F\u6210\u52A8\u4F5C + \u53E3\u578B\u3002 */\n speakAudio(source: XiaochunAudioSource, opts?: XiaochunAudioOptions): Promise<void>;\n speakAudioStream(opts: XiaochunAudioOptions & { sampleRate: number }): XiaochunAudioStream;\n motion(m: XcMotionPayload | string): Promise<void>;\n expression(name: XcExpressionPayload['name']): Promise<void>;\n /** TODO: \u534F\u8BAE\u5DF2\u9884\u7559, /embed \u6682\u672A\u5B9E\u73B0 \u2192 reject unsupported\u3002 */\n lookAt(x: number, y: number): Promise<void>;\n /** \u6362\u5185\u7F6E\u670D\u88C5 (\u4E32\u884C + last-wins, \u89C1 XiaochunInstance.setOutfit)\u3002 */\n setOutfit(id: string): Promise<void>;\n setScene(id: string): Promise<void>;\n getOutfits(): Promise<XcOutfitInfo[]>;\n getScenes(): Promise<XcSceneInfo[]>;\n /** \u6E05\u9664 persistBox \u4FDD\u5B58\u7684\u4F4D\u7F6E / \u5927\u5C0F; { reset: true } \u540C\u65F6\u8FD8\u539F\u5230\u521D\u59CB\u4F4D\u7F6E\u548C\u5927\u5C0F\u3002 */\n clearPersistedBox(opts?: { reset?: boolean }): void;\n /** \u9884\u53D6\u670D\u88C5\u8D44\u6E90\u5230 iframe \u7684 IndexedDB; ids \u7701\u7565 = \u5168\u90E8 (\u5A5A\u7EB1\u9664\u5916)\u3002 */\n prefetch(ids?: string[]): Promise<XcPrefetchedPayload>;\n /** \u65E7\u547D\u4EE4; \u4EFB\u610F URL \u9700 allowCustomModel\u3002\u5185\u7F6E\u670D\u88C5\u8BF7\u7528 setOutfit\u3002 */\n setModel(m: string | { url?: string; outfit?: string; name?: string }): Promise<void>;\n setConfig(cfg: XcConfig): Promise<void>;\n startListening(): Promise<void>;\n stopListening(): Promise<void>;\n mic(enabled: boolean): Promise<void>;\n pause(): void;\n resume(): void;\n /** \u6539\u6B63\u5728\u64AD\u7684\u5BBF\u4E3B\u97F3\u9891\u500D\u901F (0.25~3)\u3002\u89C1 XiaochunInstance.setPlaybackRate\u3002 */\n setPlaybackRate(rate: number): void;\n /** \u6539\u5BBF\u4E3B\u97F3\u9891\u97F3\u91CF (0~1)\u3002\u89C1 XiaochunInstance.setVolume\u3002 */\n setVolume(volume: number): void;\n activate(): void;\n destroy(): void;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210\u65F6 resolve\u3002 */\n readonly ready: Promise<void>;\n /** \u5E95\u5C42 SDK \u5B9E\u4F8B (\u670D\u52A1\u7AEF / \u672A\u6302\u8F7D\u65F6 null)\u3002 */\n readonly instance: XiaochunInstance | null;\n}\n\nexport interface XiaochunProps extends XiaochunHookOptions {\n className?: string;\n /** \u5916\u5C42 div \u7684\u6837\u5F0F; width/height \u7531 props \u51B3\u5B9A (\u56FA\u5B9A\u5C3A\u5BF8, \u9632 CLS), \u8FD9\u91CC\u7684\u540C\u540D\u5B57\u6BB5\u4F1A\u88AB\u8986\u76D6\u3002 */\n style?: CSSProperties;\n}\n\nconst css = (v: number | string | undefined, d: string) => (v === undefined ? d : typeof v === 'number' ? `${v}px` : v);\nconst NOT_MOUNTED = () => new Error('[project-xiaochun] <Xiaochun /> is not mounted');\n\nfunction XiaochunInner(props: XiaochunProps, ref: ForwardedRef<XiaochunHandle>): ReactElement {\n const { className, style, ...hookOptions } = props;\n const { containerRef, client } = useXiaochun(hookOptions);\n const clientRef = useRef<XiaochunInstance | null>(null);\n clientRef.current = client;\n\n useImperativeHandle(ref, () => {\n const c = () => clientRef.current;\n const reject = <T,>(): Promise<T> => Promise.reject(NOT_MOUNTED());\n return {\n say: (t, o) => c()?.say(t, o) ?? reject(),\n speakAudio: (s, o) => c()?.speakAudio(s, o) ?? reject(),\n speakAudioStream: (o) => { const x = c(); if (!x) throw NOT_MOUNTED(); return x.speakAudioStream(o); },\n motion: (m) => c()?.motion(m) ?? reject(),\n expression: (n) => c()?.expression(n) ?? reject(),\n lookAt: (x, y) => c()?.lookAt(x, y) ?? reject(),\n setOutfit: (id) => c()?.setOutfit(id) ?? reject(),\n setScene: (id) => c()?.setScene(id) ?? reject(),\n getOutfits: () => c()?.getOutfits() ?? reject(),\n getScenes: () => c()?.getScenes() ?? reject(),\n clearPersistedBox: (opts) => c()?.clearPersistedBox(opts),\n prefetch: (ids) => c()?.prefetch(ids) ?? reject(),\n setModel: (m) => c()?.setModel(m) ?? reject(),\n setConfig: (cfg) => c()?.setConfig(cfg) ?? reject(),\n startListening: () => c()?.startListening() ?? reject(),\n stopListening: () => c()?.stopListening() ?? reject(),\n mic: (e) => c()?.mic(e) ?? reject(),\n pause: () => c()?.pause(),\n resume: () => c()?.resume(),\n setPlaybackRate: (rate) => c()?.setPlaybackRate(rate),\n setVolume: (volume) => c()?.setVolume(volume),\n activate: () => c()?.activate(),\n destroy: () => c()?.destroy(),\n get ready() { return c()?.ready ?? reject<void>(); },\n get instance() { return c(); },\n };\n }, []);\n\n // \u670D\u52A1\u7AEF\u4E0E\u9996\u5E27\u5BA2\u6237\u7AEF\u6E32\u67D3\u5B8C\u5168\u4E00\u81F4 (hydration \u5B89\u5168): \u56FA\u5B9A\u5C3A\u5BF8\u7684\u7A7A div\n const box: CSSProperties = {\n ...style,\n width: css(props.width, defaultWidthCss()),\n height: css(props.height, defaultHeightCss()),\n maxWidth: '100%',\n position: style?.position ?? 'relative',\n };\n return createElement('div', { ref: containerRef, className, style: box, 'data-xiaochun-host': '' });\n}\n\n/** `<Xiaochun />`: \u5728\u5BA2\u6237\u7AEF\u521B\u5EFA\u5C0F\u8822 iframe; ref \u66B4\u9732 say / speakAudio / motion / \u2026 \u7B49\u547D\u4EE4\u5F0F\u65B9\u6CD5\u3002 */\nexport const Xiaochun = forwardRef<XiaochunHandle, XiaochunProps>(XiaochunInner);\nXiaochun.displayName = 'Xiaochun';\n\nexport type { XiaochunOptions, XiaochunInstance, XiaochunAudioOptions, XiaochunAudioSource, XiaochunAudioStream } from './client';\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firetable/project-xiaochun",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Embed Project XiaoChun (3D anime companion) into any web page via a lazy, origin-checked iframe. Zero-dependency SDK + <xiaochun-avatar> web component.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "FireTable",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/gesture-box.ts", "../../src/client.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * gesture-box.ts \u2014 iframe \u624B\u52BF (xc.gesture-move / xc.gesture-resize) \u5728\u5BBF\u4E3B\u4FA7\u7684\u7EAF\u903B\u8F91: \u6821\u9A8C + \u51E0\u4F55\u9650\u5E45\u3002\u96F6 DOM \u4F9D\u8D56, \u53EF\u5355\u6D4B\u3002\n *\n * \u5BBF\u4E3B SDK \u5BF9 iframe \u53D1\u6765\u7684\u624B\u52BF**\u4E0D\u4FE1\u4EFB**: \u8F7D\u8377\u9010\u5B57\u6BB5\u6821\u9A8C (\u7C7B\u578B / \u6709\u9650\u6570 / \u91CF\u7EA7 / \u89D2\u540D), \u5E8F\u53F7\u5FC5\u987B\u6309\u89C4\u5219\u9012\u589E (GestureGate),\n * \u4F4D\u7F6E / \u5C3A\u5BF8\u5168\u90E8\u5728\u8FD9\u91CC\u6309\"\u5F53\u524D\u89C6\u53E3 + \u6700\u5C0F / \u6700\u5927\u5C3A\u5BF8\"\u5939\u7D27, iframe \u8BF4\u591A\u5C11\u5C31\u79FB\u591A\u5C11\u662F\u4E0D\u53EF\u80FD\u7684\u3002\n * \u8BA1\u7B97\u4E00\u5F8B\u7528 start \u65F6\u7684\u76D2\u5B50 + \u7D2F\u8BA1\u4F4D\u79FB (totalDx / totalDy), \u4E0D\u7D2F\u52A0\u589E\u91CF: \u4E22\u5305 / \u5939\u7D27\u90FD\u4E0D\u4F1A\u8BA9\u7ED3\u679C\u6F02\u79FB\u3002\n */\nimport type { XcGestureCorner } from './protocol';\n\nexport interface Box { left: number; top: number; width: number; height: number }\nexport interface Viewport { width: number; height: number }\nexport interface ResizeLimits { minWidth: number; minHeight: number; maxWidth: number; maxHeight: number }\n\n/** \u9ED8\u8BA4\u9650\u5E45: \u6700\u5C0F 120x180 (\u518D\u5C0F\u89D2\u8272\u57FA\u672C\u770B\u4E0D\u6E05), \u6700\u5927\u53EA\u53D7\u89C6\u53E3\u9650\u5236\u3002 */\nexport const DEFAULT_RESIZE_LIMITS: Readonly<ResizeLimits> = Object.freeze({\n minWidth: 120, minHeight: 180, maxWidth: Infinity, maxHeight: Infinity,\n});\n\nexport interface XiaochunResizeLimits {\n /** \u6700\u5C0F\u5BBD (px), \u9ED8\u8BA4 120\u3002 */\n minWidth?: number;\n /** \u6700\u5C0F\u9AD8 (px), \u9ED8\u8BA4 180\u3002 */\n minHeight?: number;\n /** \u6700\u5927\u5BBD (px), \u9ED8\u8BA4\u53EA\u53D7\u89C6\u53E3\u9650\u5236\u3002 */\n maxWidth?: number;\n /** \u6700\u5927\u9AD8 (px), \u9ED8\u8BA4\u53EA\u53D7\u89C6\u53E3\u9650\u5236\u3002 */\n maxHeight?: number;\n}\n\nconst finitePositive = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v) && v > 0;\n\n/** `resizable` \u9009\u9879 \u2192 \u9650\u5E45; false / undefined \u2192 null (\u5173\u95ED); true \u2192 \u9ED8\u8BA4\u9650\u5E45; \u5BF9\u8C61 \u2192 \u9010\u9879\u8986\u76D6 (\u975E\u6CD5\u503C\u7528\u9ED8\u8BA4)\u3002min \u4E0D\u4F1A\u8D85\u8FC7 max\u3002 */\nexport function normalizeResizable(v: boolean | XiaochunResizeLimits | undefined): ResizeLimits | null {\n if (!v) return null;\n const o = v === true ? {} : v;\n const minWidth = finitePositive(o.minWidth) ? o.minWidth : DEFAULT_RESIZE_LIMITS.minWidth;\n const minHeight = finitePositive(o.minHeight) ? o.minHeight : DEFAULT_RESIZE_LIMITS.minHeight;\n const maxWidth = finitePositive(o.maxWidth) ? Math.max(o.maxWidth, minWidth) : Infinity;\n const maxHeight = finitePositive(o.maxHeight) ? Math.max(o.maxHeight, minHeight) : Infinity;\n return { minWidth, minHeight, maxWidth, maxHeight };\n}\n\nconst clamp = (v: number, lo: number, hi: number) => Math.min(Math.max(v, lo), Math.max(lo, hi));\n\n/** \u79FB\u52A8: \u8D77\u70B9\u76D2\u5B50 + \u7D2F\u8BA1\u4F4D\u79FB, \u5939\u5728\u89C6\u53E3\u5185 (\u76D2\u5B50\u6BD4\u89C6\u53E3\u5927\u65F6\u8D34\u5DE6\u4E0A)\u3002 */\nexport function moveBox(start: Box, totalDx: number, totalDy: number, vp: Viewport): Box {\n return {\n left: clamp(start.left + totalDx, 0, vp.width - start.width),\n top: clamp(start.top + totalDy, 0, vp.height - start.height),\n width: start.width,\n height: start.height,\n };\n}\n\n/**\n * \u7F29\u653E: \u88AB\u62D6\u7684\u89D2\u8DDF\u624B, \u5BF9\u89D2\u56FA\u5B9A; \u5BBD\u9AD8\u5939\u5728 [min, min(max, \u89C6\u53E3\u5185\u8FD8\u80FD\u4F38\u5C55\u7684\u7A7A\u95F4)]\u3002\n * \u4F8B: \u62D6 SE \u89D2 \u2192 \u5DE6\u4E0A\u56FA\u5B9A, \u53F3 / \u4E0B\u8FB9\u754C\u4E0D\u80FD\u8D8A\u8FC7\u89C6\u53E3; \u62D6 NW \u89D2 \u2192 \u53F3\u4E0B\u56FA\u5B9A, \u5DE6 / \u4E0A\u8FB9\u754C\u4E0D\u80FD\u8D8A\u8FC7\u89C6\u53E3\u3002\n */\nexport function resizeBox(start: Box, corner: XcGestureCorner, totalDx: number, totalDy: number, limits: ResizeLimits, vp: Viewport): Box {\n const west = corner === 'NW' || corner === 'SW';\n const north = corner === 'NW' || corner === 'NE';\n const right = start.left + start.width, bottom = start.top + start.height;\n const wantW = west ? start.width - totalDx : start.width + totalDx;\n const wantH = north ? start.height - totalDy : start.height + totalDy;\n const roomW = west ? right : vp.width - start.left;\n const roomH = north ? bottom : vp.height - start.top;\n const width = clamp(wantW, limits.minWidth, Math.min(limits.maxWidth, roomW));\n const height = clamp(wantH, limits.minHeight, Math.min(limits.maxHeight, roomH));\n return { left: west ? right - width : start.left, top: north ? bottom - height : start.top, width, height };\n}\n\n/** \u7A97\u53E3 / \u89C6\u53E3\u53D8\u5C0F\u540E\u628A\u76D2\u5B50\u91CD\u65B0\u5939\u56DE\u89C6\u53E3 (\u5C3A\u5BF8\u4E5F\u4E0D\u8D85\u8FC7\u89C6\u53E3)\u3002 */\nexport function fitBox(b: Box, vp: Viewport): Box {\n const width = Math.min(b.width, Math.max(1, vp.width)), height = Math.min(b.height, Math.max(1, vp.height));\n return { left: clamp(b.left, 0, vp.width - width), top: clamp(b.top, 0, vp.height - height), width, height };\n}\n\n// \u2500\u2500 \u8F7D\u8377\u6821\u9A8C \u2500\u2500\nconst CORNERS = new Set(['NW', 'NE', 'SW', 'SE']);\nconst PHASES = new Set(['start', 'move', 'end']);\nconst REASONS = new Set(['up', 'cancel', 'blur']);\n/** \u5355\u6B21\u7D2F\u8BA1\u4F4D\u79FB\u7684\u5408\u7406\u4E0A\u9650 (CSS px)\u3002\u5C4F\u5E55\u518D\u5927\u4E5F\u5230\u4E0D\u4E86, \u8D85\u8FC7\u7684\u4E00\u5F8B\u5F53\u4F5C\u4F2A\u9020\u3002 */\nexport const MAX_GESTURE_DELTA = 20_000;\n\nexport interface ParsedGesture {\n gesture: number;\n seq: number;\n phase: 'start' | 'move' | 'end';\n totalDx: number;\n totalDy: number;\n corner?: XcGestureCorner;\n}\n\nconst delta = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v) && Math.abs(v) <= MAX_GESTURE_DELTA;\nconst counter = (v: unknown): v is number => typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;\n\n/** \u6821\u9A8C iframe \u53D1\u6765\u7684\u624B\u52BF\u8F7D\u8377; \u4E0D\u5408\u6CD5\u8FD4\u56DE null\u3002kind='resize' \u8FD8\u8981\u6C42\u5408\u6CD5\u7684 corner\u3002 */\nexport function parseGesturePayload(kind: 'move' | 'resize', raw: unknown): ParsedGesture | null {\n if (raw === null || typeof raw !== 'object') return null;\n const p = raw as Record<string, unknown>;\n if (!counter(p.gesture) || !counter(p.seq) || typeof p.phase !== 'string' || !PHASES.has(p.phase)) return null;\n if (!delta(p.dx) || !delta(p.dy) || !delta(p.totalDx) || !delta(p.totalDy)) return null;\n if (p.reason !== undefined && (typeof p.reason !== 'string' || !REASONS.has(p.reason))) return null;\n const out: ParsedGesture = { gesture: p.gesture, seq: p.seq, phase: p.phase as ParsedGesture['phase'], totalDx: p.totalDx, totalDy: p.totalDy };\n if (kind === 'resize') {\n if (typeof p.corner !== 'string' || !CORNERS.has(p.corner)) return null;\n out.corner = p.corner as XcGestureCorner;\n }\n return out;\n}\n\n/**\n * \u624B\u52BF\u5E8F\u53F7\u95F8\u95E8: \u53EA\u653E\u884C\"\u5408\u6CD5\u7684\u624B\u52BF\u5E8F\u5217\" \u2014\u2014 start(gesture \u6BD4\u4E0A\u4E00\u4E2A\u5927, seq=0) \u2192 move* (seq \u4E25\u683C\u9012\u589E) \u2192 end\u3002\n * \u8FDF\u5230 / \u91CD\u653E / \u4E71\u5E8F / \u6CA1\u6709 start \u7684\u6D88\u606F\u4E00\u5F8B\u62D2\u7EDD\u3002\u4E00\u4E2A\u95F8\u95E8\u5BF9\u5E94\u4E00\u79CD\u624B\u52BF (move \u6216 resize)\u3002\n */\nexport class GestureGate {\n private lastGesture = 0;\n private lastSeq = -1;\n private open = false;\n\n get active(): boolean { return this.open; }\n\n accept(p: Pick<ParsedGesture, 'gesture' | 'seq' | 'phase'>): boolean {\n if (p.phase === 'start') {\n if (p.gesture <= this.lastGesture || p.seq !== 0) return false;\n this.lastGesture = p.gesture;\n this.lastSeq = 0;\n this.open = true;\n return true;\n }\n if (!this.open || p.gesture !== this.lastGesture || p.seq <= this.lastSeq) return false;\n this.lastSeq = p.seq;\n if (p.phase === 'end') this.open = false;\n return true;\n }\n\n /** \u5BBF\u4E3B\u4E3B\u52A8\u7ED3\u675F (\u5173\u95ED\u624B\u52BF / \u9500\u6BC1): \u4E4B\u540E\u540C\u4E00\u624B\u52BF\u7684\u8FDF\u5230\u6D88\u606F\u88AB\u62D2\u7EDD\u3002 */\n close(): void { this.open = false; }\n}\n", "/**\n * client.ts \u2014 \u65E0\u6846\u67B6\u3001\u96F6\u8FD0\u884C\u65F6\u4F9D\u8D56\u7684 Project XiaoChun \u5D4C\u5165 SDK\u3002\n *\n * const xc = createXiaochun({ container: '#avatar', transparent: true });\n * await xc.ready; // \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210 (xc.loaded)\n * await xc.say('\u4F60\u597D\u5440'); // \u5FF5\u5B8C (xc.utterance end) \u624D resolve\n *\n * \u9ED8\u8BA4 lazy: \u5148\u653E\u56FA\u5B9A\u5C3A\u5BF8\u7684\u5360\u4F4D (\u4E0D\u4EA7\u751F CLS), \u6D4F\u89C8\u5668\u7A7A\u95F2 + \u8FDB\u5165\u89C6\u53E3 + (\u6216\u70B9\u51FB/\u8C03\u7528 API) \u4E4B\u540E\u624D\u521B\u5EFA iframe\u3002\n */\nimport {\n XC_DEFAULT_SRC,\n isXcEnvelope,\n isXcId,\n normalizeOrigin,\n normalizeXcUiOption,\n parseXcUiAutoHide,\n XC_UI_PARTS,\n XC_CAMERA_RANGES,\n normalizeXcCamera,\n XC_WINDOW_CORNER_RADIUS,\n xcMessage,\n type XcAudioFormat,\n type XcAudioOptions,\n type XcCamera,\n type XcConfig,\n type XcErrorCode,\n type XcExpressionPayload,\n type XcFrameMessage,\n type XcHeavyMode,\n type XcHitRegionPayload,\n type XcHostMessageType,\n type XcLang,\n type XcLangChangedPayload,\n type XcLoadProgressPayload,\n type XcMotionPayload,\n type XcOutfitChangedPayload,\n type XcOutfitInfo,\n type XcPrefetchedPayload,\n type XcReadyPayload,\n type XcSceneChangedPayload,\n type XcSceneId,\n type XcSceneInfo,\n type XcSttPayload,\n type XcStatePayload,\n type XcUiAutoHide,\n type XcUiPart,\n type XcUtterancePayload,\n} from './protocol';\nimport {\n DEFAULT_RESIZE_LIMITS, GestureGate, fitBox, moveBox, normalizeResizable, parseGesturePayload, resizeBox,\n type Box, type ResizeLimits, type Viewport, type XiaochunResizeLimits,\n} from './gesture-box';\n\nexport type { XiaochunResizeLimits } from './gesture-box';\nexport type XiaochunPosition = 'inline' | 'bottom-right' | 'bottom-left';\n/** lazy: false=\u7ACB\u5373\u521B\u5EFA; true/'idle'=\u8FDB\u5165\u89C6\u53E3\u4E14\u7A7A\u95F2\u540E\u521B\u5EFA; 'click'=\u4EC5\u70B9\u51FB\u5360\u4F4D\u6216\u8C03\u7528 API \u65F6\u521B\u5EFA\u3002 */\nexport type XiaochunLazy = boolean | 'idle' | 'click';\n\nexport interface XiaochunOptions {\n /** \u6302\u8F7D\u5BB9\u5668 (\u5143\u7D20\u6216\u9009\u62E9\u5668)\u3002 */\n container: HTMLElement | string;\n /** /embed \u9875\u9762\u5730\u5740, \u9ED8\u8BA4\u5B98\u65B9\u90E8\u7F72\u3002\u81EA\u5EFA/\u672C\u5730\u8C03\u8BD5\u65F6\u8986\u76D6\u3002 */\n src?: string;\n /** iframe \u7684 origin, \u9ED8\u8BA4\u7531 src \u63A8\u5BFC\u3002\u6240\u6709\u63E1\u624B/\u6D88\u606F\u6821\u9A8C\u90FD\u4EE5\u5B83\u4E3A\u51C6\u3002 */\n origin?: string;\n /** \u989D\u5916\u5141\u8BB8\u53D1 xc.ready \u7684 origin (\u5982 CDN \u91CD\u5B9A\u5411); \u9ED8\u8BA4\u53EA\u6709 origin\u3002\u4E0D\u652F\u6301 '*'\u3002 */\n allowedOrigins?: string[];\n lazy?: XiaochunLazy;\n /** \u8DDD\u89C6\u53E3\u591A\u5C11 px \u5185\u5C31\u5F00\u59CB\u52A0\u8F7D (IntersectionObserver rootMargin)\u3002\u8C03\u5927=\u66F4\u65E9\u52A0\u8F7D, \u66F4\u8017\u6D41\u91CF; \u8C03\u5C0F=\u66F4\u7701\u4F46\u6EDA\u5230\u65F6\u53EF\u80FD\u8FD8\u6CA1\u597D\u3002\u9ED8\u8BA4 200\u3002 */\n lazyMargin?: number;\n /** \u5360\u4F4D\u56FE URL / \u5143\u7D20; false = \u4E0D\u8981\u5360\u4F4D\u3002 */\n placeholder?: string | HTMLElement | false;\n /**\n * \u80CC\u666F\u900F\u660E (\u53E0\u5728\u5BBF\u4E3B\u9875\u4E0A)\u3002\u7B49\u4EF7\u4E8E `scene: 'transparent'`; \u540C\u65F6\u7ED9\u4E86 `scene` \u6216\u5DF2\u4FDD\u5B58\u7684\u504F\u597D\u65F6, \u4EE5\u5B83\u4EEC\u4E3A\u51C6\u3002\n * \u8FD0\u884C\u4E2D\u60F3\u5207\u6362\u8BF7\u7528 `setScene()`: SDK \u4F1A\u540C\u6B65\u5916\u58F3\u80CC\u666F\u548C\u7A7F\u900F\u3002\n */\n transparent?: boolean;\n /** \u521D\u59CB\u573A\u666F: 'light' | 'dark' | 'transparent' (\u4EE5 getScenes() \u4E3A\u51C6)\u3002\u7701\u7565 = \u8DDF\u968F transparent \u9009\u9879 / \u7CFB\u7EDF\u4EAE\u6697\u3002 */\n scene?: XcSceneId | (string & {});\n /**\n * \u56FA\u5B9A\u5C3A\u5BF8, \u6570\u5B57=px, \u5B57\u7B26\u4E32=CSS \u957F\u5EA6\u3002\u9ED8\u8BA4 600x1080 (\u5BBD\u9AD8\u6BD4 \u2248 0.556, \u4E0E\u684C\u9762\u7AEF\u7A97\u53E3\u7684\u7AD6\u7248\u6BD4\u4F8B\u540C\u4E00\u91CF\u7EA7)\u3002\n * **\u9ED8\u8BA4\u503C\u53D7\u89C6\u53E3\u9650\u5236**: \u5BBD = min(600px, \u89C6\u53E3\u5BBD) \u4E14\u5916\u58F3 max-width:100% (\u4E0D\u8D85\u8FC7\u5BB9\u5668\u5BBD), \u9AD8 = min(1080px, \u89C6\u53E3\u9AD8), \u7A84\u5C4F / \u5C0F\u7A97\u53E3\u4E0D\u4F1A\u6EA2\u51FA; \u663E\u5F0F\u7ED9\u7684\u503C\u539F\u6837\u4F7F\u7528 (\u5BBD\u4ECD\u6709 max-width:100%)\u3002\n * \u52A1\u5FC5\u7ED9\u5B9A\u6216\u63A5\u53D7\u9ED8\u8BA4\u503C, \u5426\u5219\u65E0\u6CD5\u9884\u7559\u7A7A\u95F4 (CLS)\u3002\u8FD0\u884C\u65F6\u7528 setSize() \u6539\u3002\n */\n width?: number | string;\n height?: number | string;\n position?: XiaochunPosition;\n /**\n * \u5141\u8BB8\u7528\u6237\u62D6\u52A8\u5934\u50CF, \u9ED8\u8BA4 false\u3002**\u624B\u52BF\u62D6\u52A8**: \u5728\u89D2\u8272\u4E0A\u6309\u4F4F\u5DE6\u952E\u62D6 (\u89E6\u5C4F: \u624B\u6307\u62D6) = \u79FB\u52A8\u6574\u4E2A\u5934\u50CF (\u8BC6\u522B\u5728 iframe \u91CC, \u590D\u7528 Tauri \u684C\u5BA0\u7684\u624B\u52BF\u72B6\u6001\u673A,\n * \u5BBF\u4E3B\u6267\u884C\u79FB\u52A8\u5E76\u9650\u5E45\u5728\u89C6\u53E3\u5185); \u900F\u660E + \u7A7F\u900F\u573A\u666F\u4E0B\u53EA\u6709\u70B9\u5728\u89D2\u8272\u4E0A\u624D\u63A5\u7BA1, \u5176\u4F59\u4F4D\u7F6E\u4ECD\u7A7F\u900F\u7ED9\u5BBF\u4E3B\u9875\u3002\u5185\u8054 (position: 'inline') \u7528 CSS translate \u4F4D\u79FB, \u4E0D\u6539\u53D8\u5E03\u5C40\u6D41\u3002\n * \u60AC\u6D6E\u6A21\u5F0F (bottom-right / bottom-left) \u540C\u6837\u8D70\u624B\u52BF (\u6539 left/top)\u3002\u8FD0\u884C\u4E2D\u53EF\u7528 `setDraggable()` \u5F00\u5173, \u4E0D\u91CD\u5EFA iframe\u3002\n * \u9700\u8981 /embed \u7684 capabilities.gestures (\u65E7\u7248\u6CA1\u6709 \u2192 \u624B\u52BF\u65E0\u6548, \u5E76\u89E6\u53D1\u4E00\u6B21 error{code:'unsupported'})\u3002\n */\n draggable?: boolean;\n /**\n * \u5916\u58F3\u5706\u89D2 (iframe / \u5360\u4F4D\u56FE / \u5916\u58F3\u4E00\u8D77\u88C1), \u6570\u5B57 = px, \u6216\u4EFB\u610F CSS \u957F\u5EA6\u3002\u9ED8\u8BA4: **\u975E\u900F\u660E\u573A\u666F (light / dark) = 20px** (\u4E0E Tauri \u684C\u5BA0\u7A97\u53E3\u7684\u5706\u89D2\u540C\u503C,\n * \u89C1 XC_WINDOW_CORNER_RADIUS), \u900F\u660E\u573A\u666F = 0 (\u6CA1\u6709\u5E95\u8272\u53EF\u88C1, \u89D2\u8272\u4E0D\u88AB\u88C1\u89D2)\u3002`--xc-radius` CSS \u53D8\u91CF\u4F18\u5148\u7EA7\u66F4\u9AD8\u3002\u8FD0\u884C\u4E2D\u53EF\u7528 `setBorderRadius()` \u6539, \u4E0D\u91CD\u5EFA iframe\u3002\n * \u5706\u89D2\u534A\u5F84\u662F\u56FA\u5B9A px, \u7F29\u653E (resizable) \u65F6\u4E0D\u968F\u5C3A\u5BF8\u53D8\u5F62\u3002\u4F20 0 \u6062\u590D\u65B9\u89D2\u3002\n */\n borderRadius?: number | string;\n /**\n * \u5141\u8BB8\u7528\u6237\u7F29\u653E\u5934\u50CF, \u9ED8\u8BA4 false\u3002**\u89D2\u843D\u7F29\u653E**: iframe \u56DB\u4E2A\u89D2\u5404\u6709\u4E00\u4E2A 40px \u70ED\u533A (\u60AC\u505C\u51FA\u73B0\u5706\u5F27\u63D0\u793A, \u5149\u6807\u53D8\u6210\u7F29\u653E\u7BAD\u5934), \u6309\u4F4F\u62D6\u52A8 = \u7F29\u653E, \u5BF9\u89D2\u56FA\u5B9A\u3002\n * true = \u9ED8\u8BA4\u9650\u5E45 (\u6700\u5C0F 120x180, \u6700\u5927\u53EA\u53D7\u89C6\u53E3\u9650\u5236); \u5BF9\u8C61\u53EF\u81EA\u5B9A\u4E49 minWidth / minHeight / maxWidth / maxHeight (px)\u3002\n * \u7F29\u653E\u53EA\u6539\u5916\u58F3\u5C3A\u5BF8, **\u4E0D\u91CD\u5EFA iframe**: \u6A21\u578B / \u52A8\u753B / \u5BF9\u8BDD\u72B6\u6001\u90FD\u4FDD\u6301\u3002\u901A\u8FC7 `resize` \u4E8B\u4EF6\u62FF\u5230\u65B0\u5C3A\u5BF8, `getBox()` \u968F\u65F6\u8BFB\u53D6\u3002\u8FD0\u884C\u4E2D\u53EF\u7528 `setResizable()` \u5F00\u5173\u3002\n * \u9700\u8981 capabilities.gestures (\u65E7\u7248 /embed \u65E0\u6548, \u89E6\u53D1\u4E00\u6B21 error{code:'unsupported'})\u3002\n */\n resizable?: boolean | XiaochunResizeLimits;\n /**\n * iframe \u754C\u9762\u8BED\u8A00 ('zh-CN' | 'en' | 'ja')\u3002\u663E\u5F0F\u6307\u5B9A\u65F6\u4F18\u5148\u4E8E iframe \u81EA\u5DF1\u8BB0\u4F4F\u7684\u7528\u6237\u9009\u62E9; \u4E0D\u5199 = \u7528 iframe localStorage \u91CC\u7528\u6237\u4E0A\u6B21\u5728\u8BED\u8A00\u6309\u94AE\u91CC\u9009\u7684, \u518D\u6CA1\u6709\u5C31\u8DDF\u968F\u6D4F\u89C8\u5668\u8BED\u8A00 (\u9ED8\u8BA4 zh-CN)\u3002\n * \u8FD0\u884C\u4E2D\u53EF\u7528 `setConfig({ lang })` \u6539 (\u4E0D\u6301\u4E45\u5316); \u7528\u6237\u70B9\u5185\u7F6E\u8BED\u8A00\u6309\u94AE (`ui` \u91CC\u7684 'lang') \u4F1A\u5B58\u8FDB iframe \u81EA\u5DF1\u7684 localStorage, \u5E76\u53D1 `lang-changed` \u4E8B\u4EF6\u3002\n */\n lang?: XcLang;\n /** \u521D\u59CB\u670D\u88C5: \u5185\u7F6E\u670D\u88C5 id (\u5982 'xiaochun_maid', \u89C1 getOutfits())\u3002\u672A\u77E5 id \u56DE\u9000\u9ED8\u8BA4\u670D\u88C5, \u5E76\u89E6\u53D1 error{code:'unknown_id'}\u3002 */\n outfit?: string;\n /**\n * @deprecated \u8BF7\u6539\u7528 `outfit`\u3002\u503C\u662F\u5185\u7F6E\u670D\u88C5 id \u65F6\u7B49\u4EF7\u4E8E `outfit`; https URL \u4E0D\u80FD\u518D\u901A\u8FC7\u521B\u5EFA\u9009\u9879\u4F20\u5165\n * (\u4EFB\u610F URL \u9700\u8981 `allowCustomModel: true`, \u4E4B\u540E\u7528 `setModel({ url })`)\u3002\n */\n model?: string;\n /**\n * \u5141\u8BB8 `setModel({ url })` \u52A0\u8F7D\u4EFB\u610F https .vrm/.vrmaddon/.vrmbase, \u9ED8\u8BA4 false (\u5173\u95ED)\u3002\n * \u6A21\u578B\u662F\u7B2C\u4E09\u65B9\u6587\u4EF6, \u4F1A\u5728 iframe \u91CC\u88AB\u89E3\u6790, \u53EA\u5728\u4F60\u4FE1\u4EFB\u8BE5 URL \u65F6\u6253\u5F00\u3002\u5185\u7F6E\u670D\u88C5 (`setOutfit`) \u4E0D\u53D7\u5F71\u54CD\u3002\n */\n allowCustomModel?: boolean;\n /**\n * \u504F\u597D (\u670D\u88C5 + \u573A\u666F) \u5728\u5BBF\u4E3B\u9875\u7684\u989D\u5916\u4FDD\u5B58 (\u53EF\u9009), \u9ED8\u8BA4 false\u3002\u4FDD\u5B58\u4F4D\u7F6E\u662F**\u5BBF\u4E3B\u9875**\u7684 localStorage; \u8BFB\u51FA\u6765\u540E\u4F5C\u4E3A\u663E\u5F0F\u503C\u4F20\u7ED9 iframe, \u6240\u4EE5\u4F1A\u76D6\u8FC7 iframe \u81EA\u5DF1 localStorage \u91CC\u5B58\u7684 (iframe \u672C\u6765\u5C31\u4F1A\u8BB0\u4F4F\u7528\u6237\u7684\u9009\u62E9, \u4F46\u5B83\u7684\u5B58\u50A8\u53EF\u80FD\u88AB\u6D4F\u89C8\u5668\u5206\u533A)\u3002\n * false \u4E0D\u4FDD\u5B58\n * 'host' \u4FDD\u5B58\u5230 localStorage['xiaochun:prefs']\n * \u5176\u5B83\u5B57\u7B26\u4E32 \u4FDD\u5B58\u5230 localStorage[\u8BE5\u5B57\u7B26\u4E32] (\u540C\u9875\u591A\u4E2A\u5B9E\u4F8B\u4E92\u4E0D\u8986\u76D6\u65F6\u7528)\n * \u4F18\u5148\u7EA7: \u663E\u5F0F\u7684 outfit / scene \u9009\u9879 > \u5DF2\u4FDD\u5B58\u7684\u504F\u597D > \u9ED8\u8BA4\u3002\u53EA\u6709 setOutfit / setScene \u5F15\u8D77\u7684\u53D8\u5316\u4F1A\u5199\u5165\u3002\n */\n persist?: false | 'host' | (string & {});\n /**\n * \u8BB0\u4F4F\u7528\u6237\u62D6\u52A8 / \u7F29\u653E\u540E\u7684**\u4F4D\u7F6E\u548C\u5927\u5C0F**\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4 false = \u4E0D\u8BB0\uFF09\u3002\u4FDD\u5B58\u5230**\u5BBF\u4E3B\u9875**\u7684 localStorage\uFF08\u8BFB\u5199\u90FD\u5305\u4E86 try/catch\uFF0C\u88AB\u7981\u7528 / \u914D\u989D\u6EE1\u53EA\u662F\u4E0D\u8BB0\u5FC6\uFF09\uFF0C\n * \u5728 draggable / resizable \u624B\u52BF**\u7ED3\u675F**\u65F6\u5199\u5165\uFF0C\u4E0B\u6B21\u521B\u5EFA\u65F6\u6062\u590D\u3002\n * false / \u4E0D\u5199 \u4E0D\u8BB0\n * true \u5B58\u5230 localStorage['xiaochun:box']\n * '<\u540D\u5B57>' \u5B58\u5230 localStorage['xiaochun:box:<\u540D\u5B57>']\uFF08\u540C\u4E00\u7AD9\u70B9\u591A\u4E2A\u5B9E\u4F8B / \u591A\u4E2A\u9875\u9762\u4E92\u4E0D\u8986\u76D6\u65F6\u7528\uFF1B\u4E5F\u53EF\u5F53\u7248\u672C\u53F7\uFF0C\u6539\u540D\u5373\u4E22\u5F03\u65E7\u503C\uFF09\n * \u4F18\u5148\u7EA7\uFF1A\u663E\u5F0F\u7684 width / height \u9009\u9879 > \u5DF2\u4FDD\u5B58\u7684 > \u9ED8\u8BA4\uFF08600x1080\uFF09\u3002\u4F4D\u7F6E\u6CA1\u6709\u5BF9\u5E94\u7684\u663E\u5F0F\u9009\u9879\uFF08`position` \u53EA\u662F\u9884\u8BBE\u951A\u70B9\uFF09\uFF0C\u5DF2\u4FDD\u5B58\u7684\u4F4D\u7F6E\u59CB\u7EC8\u751F\u6548\u3002\n * \u6240\u4EE5\u60F3\u8BA9\"\u7528\u6237\u7F29\u653E\u8FC7\u7684\u5927\u5C0F\"\u88AB\u6062\u590D\uFF0C\u5C31**\u4E0D\u8981**\u4F20 width / height\uFF08\u7528\u9ED8\u8BA4\u503C\uFF09\u3002\n * \u53EA\u5728\u5BF9\u5E94\u624B\u52BF\u6253\u5F00\u65F6\u6062\u590D\uFF08\u9700\u8981 draggable \u6216 resizable\uFF1B\u6CA1\u5F00\u624B\u52BF\u7684\u5B9E\u4F8B\u4E0D\u4F1A\u88AB\u65E7\u503C\u6539\u4F4D\u7F6E\uFF09\uFF1B\u4FDD\u5B58\u7684 `position` \u6A21\u5F0F\uFF08inline / bottom-right / bottom-left\uFF09\u4E0E\u5F53\u524D\u4E0D\u540C\u5219\u5FFD\u7565\u3002\n * \u6062\u590D\u65F6\u94B3\u5236\u5230**\u5F53\u524D\u89C6\u53E3**\uFF1A\u5927\u5C0F\u5939\u5728 [\u6700\u5C0F, \u89C6\u53E3]\uFF08\u6700\u5C0F = resizable \u7684 minWidth/minHeight\uFF0C\u9ED8\u8BA4 120x180\uFF09\uFF0C\u60AC\u6D6E\u6A21\u5F0F\u7684\u4F4D\u7F6E\u5939\u8FDB\u89C6\u53E3\uFF1B\n * \u5185\u8054\u6A21\u5F0F\u6A2A\u5411\u5939\u8FDB\u89C6\u53E3\u3001\u7EB5\u5411\u53EA\u4FDD\u8BC1\u4E0D\u8D8A\u8FC7\u6587\u6863\u9876\u90E8\uFF08\u5185\u8054\u76D2\u5B50\u53EF\u4EE5\u5728\u6EDA\u52A8\u7684\u9875\u9762\u91CC\uFF09\u3002\u7A97\u53E3\u4E4B\u540E\u53D8\u5C0F\u65F6\uFF0C\u65E2\u6709\u7684 resize \u76D1\u542C\u4E5F\u4F1A\u7EE7\u7EED\u628A\u5B83\u5939\u56DE\u89C6\u53E3\u3002\n * \u6E05\u9664\uFF1A`clearPersistedBox()`\uFF08\u53EA\u5220\u5B58\u50A8\uFF09\u6216 `clearPersistedBox({ reset: true })`\uFF08\u540C\u65F6\u56DE\u5230\u521D\u59CB\u4F4D\u7F6E / \u5927\u5C0F\uFF09\u3002\n */\n persistBox?: boolean | (string & {});\n /**\n * \u8981\u663E\u793A\u7684 iframe \u5185\u7F6E\u754C\u9762\u90E8\u4EF6 (\u6570\u7EC4, \u9ED8\u8BA4\u4E0D\u5199 = \u5168\u4E0D\u663E\u793A):\n * 'chat' \u5E95\u90E8\u804A\u5929\u680F (\u5BF9\u8BDD\u8D70 WebLLM, \u4F1A\u591A\u4E0B\u8F7D\u4E00\u90E8\u5206\u4EE3\u7801)\n * 'bubble' \u5934\u9876\u6C14\u6CE1 (\u8BF4\u8BDD\u6587\u672C / \u72B6\u6001)\n * 'outfit' \u6362\u88C5\u6309\u94AE } \u5916\u89C2/\u6587\u6848/\u4EA4\u4E92\u4E0E\u4E3B\u7AD9 TopHeader \u4E00\u81F4; \u70B9\u6309\u94AE\u8D70\u548C setOutfit() / setScene() \u540C\u4E00\u6761\u767D\u540D\u5355 + \u4E32\u884C (last-wins) \u8DEF\u5F84,\n * 'lang' \u8BED\u8A00\u5207\u6362\u6309\u94AE (\u4E2D\u6587 / English / \u65E5\u672C\u8A9E; \u4E0E\u4E3B\u7AD9 TopHeader \u540C\u4E00\u4E2A\u7EC4\u4EF6, \u7528\u6237\u7684\u9009\u62E9\u8BB0\u5728 iframe \u81EA\u5DF1\u7684 localStorage, \u53D1 lang-changed \u4E8B\u4EF6)\n * 'github' GitHub \u6309\u94AE (\u65B0\u6807\u7B7E\u9875\u6253\u5F00\u9879\u76EE\u4ED3\u5E93)\n * 'scene' \u6362\u573A\u666F\u6309\u94AE } \u7167\u5E38\u89E6\u53D1 outfit-changed / scene-changed, \u5BBF\u4E3B\u7528 SDK \u6362\u88C5\u65F6\u6309\u94AE\u72B6\u6001\u540C\u6B65\u3002\u504F\u597D\u7531 iframe \u81EA\u5DF1\u7684 localStorage \u8BB0\u4F4F (\u663E\u5F0F outfit/scene \u4F18\u5148); \u60F3\u81EA\u5DF1\u5B58\u4E5F\u53EF\u7528 persist \u6216\u76D1\u542C\u4E8B\u4EF6\u3002\n * \u4F8B: `ui: ['outfit', 'scene']`\u3002\u672A\u77E5\u540D\u5B57\u5FFD\u7565\u5E76 console.warn\u3002\u521B\u5EFA\u671F\u9009\u9879: \u53D8\u5316\u4F1A\u91CD\u5EFA iframe\u3002\n * 'outfit' / 'scene' / 'lang' / 'github' \u53EA\u5BF9\u65B0\u7248 /embed \u6709\u6548 (\u65E7\u7248\u5FFD\u7565\u672A\u77E5\u90E8\u4EF6\u540D)\u3002\n * @deprecated \u5E03\u5C14\u5199\u6CD5: `ui: true` (0.1.14 \u7684\u65E7\u5199\u6CD5) \u7B49\u4EF7\u4E8E `['chat', 'bubble']` \u5E76 console.warn; \u4E0D\u8981\u518D\u7528\u3002\n */\n ui?: XcUiPart[] | boolean;\n /**\n * \u5185\u7F6E\u754C\u9762 (ui \u91CC\u7684\u6309\u94AE + \u804A\u5929\u680F chat) \u7684\u663E\u793A\u7B56\u7565, \u9ED8\u8BA4 **'transparent'**, \u4E0E Tauri \u684C\u9762\u7AEF\u9010\u5B57\u4E00\u81F4: \u53EA\u6709\u900F\u660E\u573A\u666F\u9ED8\u8BA4\u9690\u85CF, \u5355\u51FB\u89D2\u8272\u51FA\u73B0\n * (\u6309\u4F4F\u62D6\u52A8 / \u957F\u6309\u62D6\u4E0D\u7B97\u70B9\u51FB, \u6240\u4EE5\u4E0D\u4E0E `draggable` \u51B2\u7A81), \u518D\u5355\u51FB\u89D2\u8272\u6216\u5355\u51FB\u7A7A\u767D\u6536\u8D77, 10 \u79D2\u65E0\u64CD\u4F5C\u81EA\u52A8\u6536\u8D77 (\u60AC\u505C\u5728\u6309\u94AE / \u804A\u5929\u680F\u4E0A\u3001\u83DC\u5355\u6253\u5F00\u3001\u8F93\u5165\u4E2D\u4E0D\u6536); \u89E6\u5C4F\u540C\u6837\u662F\u8F7B\u70B9\u89D2\u8272\u3002\u4EAE / \u6697\u573A\u666F\u5E38\u663E\u3002\n * 'transparent' \u9ED8\u8BA4: \u53EA\u6709\u900F\u660E\u573A\u666F\u70B9\u51FB\u51FA\u73B0\n * true \u6240\u6709\u573A\u666F\u90FD\u70B9\u51FB\u51FA\u73B0 (\u4EAE / \u6697\u573A\u666F\u4E5F\u9ED8\u8BA4\u9690\u85CF)\n * false \u4E00\u76F4\u663E\u793A (0.1.15 \u53CA\u4EE5\u524D\u7684\u884C\u4E3A)\n * \u521B\u5EFA\u671F\u9009\u9879 (\u53D8\u5316\u4F1A\u91CD\u5EFA iframe); \u8FD0\u884C\u4E2D\u53EF\u7528 `setConfig({ uiAutoHide })`\u3002\u65E7\u7248 /embed (\u63E1\u624B\u91CC\u6CA1\u6709 capabilities.ui) \u5FFD\u7565\u5B83, \u754C\u9762\u5E38\u663E\u3002\n * \u6CE8\u610F: \u900F\u660E\u573A\u666F\u4E0B\u70B9\u51FB\u5BBF\u4E3B\u9875\u7684\u7A7A\u767D\u5904\u5230\u4E0D\u4E86 iframe (\u7A7F\u900F), \u6240\u4EE5\u90A3\u91CC\u53EA\u80FD\u9760 10 \u79D2\u8D85\u65F6 / \u518D\u70B9\u89D2\u8272\u6536\u8D77\u3002\n */\n uiAutoHide?: XcUiAutoHide;\n /**\n * \u76F8\u673A: `{ fov, distance, height, intro }` (\u89C1 XcCamera; \u8303\u56F4\u89C1 XC_CAMERA_RANGES: fov 15\u201360\u00B0\u3001distance 1\u201315m\u3001height \u00B11m, \u8D8A\u754C\u5939\u5230\u8FB9\u754C), \u7F3A\u7701 = \u4E0D\u8986\u76D6\u3002\n * \u521B\u5EFA\u671F\u901A\u8FC7 URL \u4F20\u7ED9 iframe (\u6A21\u578B\u52A0\u8F7D\u524D\u751F\u6548, \u9996\u6B21\u53D6\u666F / \u63A8\u955C\u5934\u76F4\u63A5\u6309\u5B83\u6765); \u8FD0\u884C\u4E2D\u7528 `setConfig({ camera })` \u6539\n * (\u7F3A\u7701\u952E\u4E0D\u53D8, null = \u6062\u590D\u9ED8\u8BA4; \u4F1A\u7ACB\u523B\u91CD\u65B0\u53D6\u666F\u5E76\u53D6\u6D88\u8FDB\u884C\u4E2D\u7684\u63A8\u955C\u5934)\u3002\u65E7\u7248 /embed (\u63E1\u624B\u91CC\u6CA1\u6709 capabilities.camera) \u5FFD\u7565\u5B83\u3002\n */\n camera?: XcCamera;\n heavy?: XcHeavyMode;\n /**\n * \u81EA\u52A8\u9884\u53D6\u670D\u88C5\u8D44\u6E90\u5230 iframe \u7684 IndexedDB (\u4E4B\u540E setOutfit \u4E0D\u8D70\u7F51\u7EDC), \u9ED8\u8BA4 false\u3002\n * true = \u5168\u90E8\u5185\u7F6E\u670D\u88C5 **\u9664\u4E86**\u5A5A\u7EB1 (13.9MB); string[] = \u53EA\u9884\u53D6\u8FD9\u4E9B id\u3002\n * \u53EA\u5728 `heavy: 'eager'` \u65F6\u81EA\u52A8\u89E6\u53D1 (\u6A21\u578B\u9996\u6B21\u52A0\u8F7D\u5B8C\u6210\u540E\u53D1\u4E00\u6B21 xc.prefetch): \u5E76\u53D1 1, \u6392\u5728 EMAGE \u52A0\u8F7D\u4E4B\u540E, \u4E0D\u4F1A\u548C\u6362\u88C5\u62A2\u5E26\u5BBD\u3002\n * heavy \u4E3A\u9ED8\u8BA4 'lazy' \u65F6\u672C\u9009\u9879\u4E0D\u751F\u6548 \u2014\u2014 \u60F3\u6309\u9700\u9884\u53D6\u8BF7\u76F4\u63A5\u8C03\u7528 `prefetch()`\u3002\n */\n prefetch?: boolean | string[];\n /**\n * iframe \u5185\u6EDA\u8F6E\u7F29\u653E, \u9ED8\u8BA4 true (\u4E0E\u4E3B\u7AD9\u4E00\u81F4)\u3002\u900F\u660E\u573A\u666F\u53EA\u5728\u6307\u9488\u843D\u5728\u89D2\u8272\u4E0A\u65F6\u7F29\u653E, \u5176\u4F59\u4F4D\u7F6E\u6EDA\u8F6E\u7A7F\u900F\u7ED9\u5BBF\u4E3B\u9875;\n * \u4E0D\u900F\u660E\u573A\u666F\u6574\u4E2A iframe \u533A\u57DF\u7684\u6EDA\u8F6E = \u7F29\u653E (\u4F1A\u541E\u6389\u8BE5\u533A\u57DF\u7684\u9875\u9762\u6EDA\u52A8)\u3002\u4F20 false \u9501\u5B9A (URL controls=0)\u3002\n */\n controls?: boolean;\n /** \u89C6\u53E3\u5916\u81EA\u52A8 xc.pause / \u56DE\u6765 xc.resume, \u9ED8\u8BA4 true\u3002 */\n autoPause?: boolean;\n /** \u900F\u660E\u6A21\u5F0F\u4E0B\u6309\"\u662F\u5426\u70B9\u5728\u89D2\u8272\u4E0A\"\u5207\u6362 iframe \u7684 pointer-events, \u9ED8\u8BA4 = transparent\u3002 */\n passthrough?: boolean;\n /** iframe sandbox \u5C5E\u6027; false = \u4E0D\u52A0\u3002\u9ED8\u8BA4\u5141\u8BB8 scripts/same-origin/popups\u3002 */\n sandbox?: string | false;\n /** \u63E1\u624B\u8D85\u65F6 (ms), \u8D85\u65F6 emit error{code:'timeout'}\u3002\u8C03\u5927\u9002\u5408\u6162\u7F51\u7EDC, \u8C03\u5C0F\u53CD\u9988\u66F4\u5FEB\u3002\u9ED8\u8BA4 20000\u3002 */\n handshakeTimeout?: number;\n /**\n * \u7ED9 iframe \u7684 `allow` \u8FFD\u52A0 `cross-origin-isolated` (\u9ED8\u8BA4 false: allow \u4ECD\u662F 'microphone; autoplay')\u3002\n * \u4EC5\u5F53\u5BBF\u4E3B\u9875\u81EA\u5DF1\u5DF2\u8DE8\u6E90\u9694\u79BB (\u54CD\u5E94\u5934 COOP: same-origin + COEP: credentialless / require-corp) \u65F6\u624D\u751F\u6548;\n * \u5F00\u542F\u540E iframe \u5185 crossOriginIsolated=true \u2192 EMAGE \u7684 onnxruntime-web \u53EF\u7528\u591A\u7EBF\u7A0B wasm (SharedArrayBuffer)\u3002\n * \u526F\u4F5C\u7528: \u5BBF\u4E3B\u9875\u4E0A\u7684\u7B2C\u4E09\u65B9\u8D44\u6E90/iframe \u4E5F\u5FC5\u987B\u6EE1\u8DB3 COEP, \u89C1 docs/EMBED.md\u3002\u5BBF\u4E3B\u672A\u9694\u79BB\u65F6\u5F00\u4E86\u4E5F\u65E0\u5BB3 (\u6D4F\u89C8\u5668\u5FFD\u7565)\u3002\n */\n crossOriginIsolated?: boolean;\n zIndex?: number;\n}\n\n/** speakAudio / speakAudioStream \u7684\u9009\u9879\u3002 */\nexport interface XiaochunAudioOptions extends XcAudioOptions {\n /** \u7F16\u7801; \u7701\u7565 = 'encoded' (\u5BB9\u5668\u683C\u5F0F)\u3002\u4F20 ArrayBuffer \u7684\u539F\u59CB PCM \u65F6\u5FC5\u987B\u5199 'pcm16' | 'float32'\u3002 */\n format?: XcAudioFormat;\n /** MIME \u63D0\u793A (\u5982 'audio/mpeg'); Blob \u4F1A\u81EA\u52A8\u53D6 blob.type\u3002 */\n mimeType?: string;\n /** \u539F\u59CB PCM \u7684\u91C7\u6837\u7387 (8000~96000, \u6574\u6BB5\u9ED8\u8BA4 16000, \u6D41\u5F0F\u5FC5\u586B); \u5BB9\u5668\u683C\u5F0F\u5FFD\u7565\u3002 */\n sampleRate?: number;\n /** \u539F\u59CB PCM \u58F0\u9053\u6570 (\u4EA4\u9519), 1 \u6216 2\u3002 */\n channels?: 1 | 2;\n /**\n * ArrayBuffer \u662F\u5426\u7528 transferable \u96F6\u62F7\u8D1D\u53D1\u9001 (\u9ED8\u8BA4 true)\u3002\n * true: \u53D1\u51FA\u540E\u4F20\u5165\u7684\u90A3\u4E2A ArrayBuffer \u4F1A\u88AB detach (byteLength \u53D8 0), \u9002\u5408\u5927\u97F3\u9891;\n * false: \u7ED3\u6784\u5316\u514B\u9686\u4E00\u4EFD, \u539F buffer \u4ECD\u53EF\u7528, \u4F46\u591A\u4E00\u6B21\u62F7\u8D1D\u3002TypedArray \u89C6\u56FE\u603B\u662F\u62F7\u8D1D\u5176\u8303\u56F4\u540E\u518D\u8F6C\u79FB\u3002\n */\n transfer?: boolean;\n /** URL \u5B57\u7B26\u4E32\u7684\u83B7\u53D6\u4F4D\u7F6E: 'host' (\u9ED8\u8BA4) = \u5BBF\u4E3B\u9875 fetch \u540E\u8F6C\u79FB\u7ED9 iframe, \u4E0D\u9700\u8981 iframe \u80FD\u8BBF\u95EE\u8BE5 URL; 'frame' = \u628A URL \u4EA4\u7ED9 iframe fetch (\u9700 https + CORS)\u3002 */\n fetch?: 'host' | 'frame';\n /** \u89E6\u53D1\u540E\u7ACB\u5373\u6253\u65AD\u8FD9\u6B21\u8BF4\u8BDD (\u53D1 xc.audio.end{abort:true})\u3002 */\n signal?: AbortSignal;\n}\n\nexport type XiaochunAudioSource = ArrayBuffer | ArrayBufferView | Blob | string;\n\n/** \u6D41\u5F0F\u97F3\u9891\u53E5\u67C4: write \u539F\u59CB PCM \u5757, end \u6536\u5C3E, abort \u7ACB\u5373\u6253\u65AD; done \u5728\u8BF4\u8BDD\u7ED3\u675F (\u6216\u88AB\u62A2\u5360) \u65F6 resolve\u3002 */\nexport interface XiaochunAudioStream {\n write(data: Int16Array | Float32Array | ArrayBuffer): void;\n end(): void;\n abort(): void;\n readonly done: Promise<void>;\n}\n\nexport type XiaochunErrorCode = XcErrorCode | 'timeout';\nexport interface XiaochunError { code: XiaochunErrorCode; message: string; command?: string }\n\n/** `move` / `resize` \u4E8B\u4EF6\u8F7D\u8377: \u624B\u52BF\u5404\u9636\u6BB5\u5916\u58F3\u5728\u89C6\u53E3\u4E2D\u7684\u4F4D\u7F6E\u4E0E\u5C3A\u5BF8 (CSS px)\u3002 */\nexport interface XiaochunBoxEvent { phase: 'start' | 'move' | 'end'; left: number; top: number; width: number; height: number }\n\nexport interface XiaochunEvents {\n /** xc.ready \u63E1\u624B\u6210\u529F (\u534F\u8BAE\u5C42)\u3002 */\n handshake: XcReadyPayload;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210 (= xc.loaded)\u3002 */\n ready: { model: string };\n progress: XcLoadProgressPayload;\n state: XcStatePayload;\n stt: XcSttPayload;\n utterance: XcUtterancePayload;\n 'hit-region': XcHitRegionPayload;\n /** \u670D\u88C5\u5DF2\u751F\u6548 (\u542B\u9996\u6B21\u52A0\u8F7D, initial:true)\u3002\u540C\u76EE\u6807\u7684\u91CD\u590D\u8BF7\u6C42\u4E0D\u4F1A\u518D\u89E6\u53D1\u3002 */\n 'outfit-changed': XcOutfitChangedPayload;\n /** \u573A\u666F\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u573A\u666F, initial:true)\u3002 */\n 'scene-changed': XcSceneChangedPayload;\n /** iframe \u754C\u9762\u8BED\u8A00\u5DF2\u751F\u6548 (\u542B\u63E1\u624B\u540E\u4E0A\u62A5\u7684\u5F53\u524D\u8BED\u8A00, initial:true; \u7528\u6237\u70B9\u8BED\u8A00\u6309\u94AE / setConfig({ lang }) \u5F15\u8D77\u7684\u53D8\u5316)\u3002 */\n 'lang-changed': XcLangChangedPayload;\n /** \u7528\u6237\u62D6\u52A8\u5934\u50CF (draggable): start / move / end \u5404\u53D1\u4E00\u6B21, \u4F4D\u7F6E\u5DF2\u9650\u5E45\u3002 */\n move: XiaochunBoxEvent;\n /** \u7528\u6237\u7F29\u653E\u5934\u50CF (resizable): start / move / end \u5404\u53D1\u4E00\u6B21, \u5C3A\u5BF8\u5DF2\u9650\u5E45\u3002 */\n resize: XiaochunBoxEvent;\n error: XiaochunError;\n destroy: undefined;\n}\n\nexport interface XiaochunInstance {\n readonly element: HTMLElement;\n readonly iframe: HTMLIFrameElement | null;\n /** \u6A21\u578B\u52A0\u8F7D\u5B8C\u6210\u65F6 resolve; destroy \u65F6 reject\u3002 */\n readonly ready: Promise<void>;\n /** \u624B\u52A8\u521B\u5EFA iframe (lazy \u6A21\u5F0F\u4E0B\u7B49\u4EF7\u4E8E\"\u7528\u6237\u70B9\u51FB\")\u3002 */\n activate(): void;\n say(text: string, opts?: { mode?: 'speak' | 'chat' }): Promise<void>;\n /**\n * \u76F4\u63A5\u64AD\u653E\u5BBF\u4E3B\u7ED9\u7684\u97F3\u9891 (\u4E0D\u7ECF\u8FC7 TTS): iframe \u5185\u89E3\u7801 \u2192 EMAGE \u751F\u6210\u52A8\u4F5C + \u53E3\u578B, \u5FF5\u5B8C (xc.utterance end) \u624D resolve\u3002\n * \u9996\u6B21\u8C03\u7528\u624D\u52A0\u8F7D EMAGE \u6A21\u578B (\u9996\u6B21\u4F1A\u6162); opts.motion=false \u5219\u53EA\u64AD\u653E\u4E0D\u52A0\u8F7D\u3002\n * xc.utterance start \u5728\u601D\u8003\u52A8\u4F5C\u548C\u9996\u7A97\u4E4B\u540E\u3001\u58F0\u97F3\u65F6\u949F\u8D77\u6B65\u65F6\u624D\u53D1, \u4E0D\u662F\u547D\u4EE4\u4E00\u5230\u5C31\u53D1\u3002\n */\n speakAudio(source: XiaochunAudioSource, opts?: XiaochunAudioOptions): Promise<void>;\n /** \u6D41\u5F0F\u97F3\u9891 (\u539F\u59CB PCM \u5206\u5757)\u3002sampleRate \u5FC5\u586B; \u9996\u4E2A write \u5F00\u59CB\u8FD9\u6B21\u8BF4\u8BDD, utterance start \u4ECD\u7B49\u5230\u58F0\u97F3\u65F6\u949F\u8D77\u6B65\u3002 */\n speakAudioStream(opts: XiaochunAudioOptions & { sampleRate: number }): XiaochunAudioStream;\n motion(m: XcMotionPayload | string): Promise<void>;\n expression(name: XcExpressionPayload['name']): Promise<void>;\n /** TODO: \u534F\u8BAE\u5DF2\u9884\u7559, /embed \u6682\u672A\u5B9E\u73B0 \u2192 \u4F1A\u6536\u5230 error{code:'unsupported'}\u3002 */\n lookAt(x: number, y: number): Promise<void>;\n /**\n * \u6362\u5185\u7F6E\u670D\u88C5 (id \u89C1 getOutfits())\u3002Promise \u5728\u670D\u88C5**\u751F\u6548\u540E** resolve (xc.outfit-changed)\u3002\n * \u5E76\u53D1\u89C4\u5219: \u4E32\u884C + last-wins \u2014\u2014 \u52A0\u8F7D\u4E2D\u518D\u6B21\u8C03\u7528\u4F1A\u6392\u961F, \u6392\u961F\u7684\u65E7\u8BF7\u6C42\u88AB\u66F4\u65B0\u7684\u9876\u6389\u65F6 reject `[busy]` (\u53EF\u5FFD\u7565, \u4EE5\u6700\u65B0\u4E00\u6B21\u4E3A\u51C6);\n * \u8BF4\u8BDD\u4E0D\u4F1A\u88AB\u6253\u65AD, \u6362\u88C5\u5728\u540E\u53F0\u5B8C\u6210\u540E\u624D\u751F\u6548\u3002\u76EE\u6807\u5DF2\u662F\u5F53\u524D\u670D\u88C5\u5219\u76F4\u63A5 resolve\u3002\n * \u65E7\u7248 /embed (\u63E1\u624B\u91CC\u6CA1\u6709 capabilities.outfits) \u4F1A reject `[unsupported]`\u3002\n */\n setOutfit(id: string): Promise<void>;\n /** \u5207\u573A\u666F ('light' | 'dark' | 'transparent', \u89C1 getScenes())\u3002SDK \u540C\u6B65\u5916\u58F3\u80CC\u666F\u3001\u7A7F\u900F\u5F00\u5173\u4E0E pointer-events\u3002 */\n setScene(id: XcSceneId | (string & {})): Promise<void>;\n /**\n * \u9884\u53D6\u5185\u7F6E\u670D\u88C5\u8D44\u6E90\u5230 iframe \u7684 IndexedDB (\u53EA\u4E0B\u8F7D, \u4E0D\u89E3\u538B\u4E0D\u5408\u6210)\u3002ids \u7701\u7565 = \u5168\u90E8\u5185\u7F6E\u670D\u88C5, \u5A5A\u7EB1 (13.9MB) \u9664\u5916; \u663E\u5F0F\u70B9\u540D\u5219\u7167\u505A\u3002\n * \u5168\u5C40\u4E32\u884C (\u5E76\u53D1 1); resolve \u7684\u7ED3\u679C\u91CC failed \u975E\u7A7A\u65F6\u53EF\u7A0D\u540E\u91CD\u8BD5\u3002\u8FDB\u5EA6\u89C1 progress \u4E8B\u4EF6 (payload.phase === 'prefetch')\u3002\n * \u65E7\u7248 /embed reject `[unsupported]`; \u7528\u6237\u5F00\u4E86\u7701\u6D41\u91CF\u6A21\u5F0F\u65F6 resolve \u4E14 skipped:'save-data'\u3002\n */\n prefetch(ids?: string[]): Promise<XcPrefetchedPayload>;\n /** \u63E1\u624B\u540E\u8FD4\u56DE\u53EF\u6362\u7684\u5185\u7F6E\u670D\u88C5 (\u4E0D\u542B\u88F8\u6A21); \u65E7\u7248 /embed \u8FD4\u56DE []\u3002\u4F1A\u89E6\u53D1 iframe \u521B\u5EFA (lazy \u6A21\u5F0F)\u3002 */\n getOutfits(): Promise<XcOutfitInfo[]>;\n /** \u63E1\u624B\u540E\u8FD4\u56DE\u53EF\u5207\u7684\u573A\u666F; \u65E7\u7248 /embed \u8FD4\u56DE []\u3002 */\n getScenes(): Promise<XcSceneInfo[]>;\n /** \u6700\u8FD1\u4E00\u6B21 xc.outfit-changed \u7684\u670D\u88C5 id (\u81EA\u5B9A\u4E49 URL \u6A21\u578B / \u5C1A\u672A\u52A0\u8F7D = null)\u3002 */\n readonly outfit: string | null;\n /** \u6700\u8FD1\u4E00\u6B21 xc.scene-changed \u7684\u573A\u666F id (\u63E1\u624B\u524D = null)\u3002 */\n readonly scene: string | null;\n /**\n * \u65E7\u547D\u4EE4, \u4FDD\u7559\u517C\u5BB9\u3002\u5185\u7F6E\u670D\u88C5\u8BF7\u6539\u7528 `setOutfit` (\u5E76\u53D1\u66F4\u7A33\u3001\u80FD\u62FF\u5230\u5B8C\u6210\u901A\u77E5)\u3002\n * `{ url }` \u9ED8\u8BA4\u88AB\u62D2\u7EDD (reject `[unsupported]`), \u9700\u521B\u5EFA\u9009\u9879 `allowCustomModel: true`\u3002\n */\n setModel(m: string | { url?: string; outfit?: string; name?: string }): Promise<void>;\n setConfig(cfg: XcConfig): Promise<void>;\n /** \u8FD0\u884C\u65F6\u8BBE\u7F6E\u5916\u58F3\u5C3A\u5BF8 (\u6570\u5B57 = px, \u5B57\u7B26\u4E32 = CSS \u957F\u5EA6, undefined = \u6062\u590D\u9ED8\u8BA4 600x1080 (\u53D7\u89C6\u53E3\u9650\u5236)); \u4E0D\u91CD\u5EFA iframe\u3002\u7528\u6237\u7F29\u653E\u540E\u5BBF\u4E3B\u8981\u540C\u6B65\u81EA\u5DF1\u7684\u72B6\u6001\u65F6\u7528 `resize` \u4E8B\u4EF6\u3002 */\n setSize(width: number | string | undefined, height: number | string | undefined): void;\n /** \u5916\u58F3\u5F53\u524D\u5728\u89C6\u53E3\u4E2D\u7684\u4F4D\u7F6E\u4E0E\u5C3A\u5BF8 (CSS px)\u3002 */\n getBox(): { left: number; top: number; width: number; height: number };\n /** \u6E05\u9664 `persistBox` \u4FDD\u5B58\u7684\u4F4D\u7F6E / \u5927\u5C0F\uFF08\u6CA1\u5F00 persistBox \u65F6\u662F\u7A7A\u64CD\u4F5C\uFF09\u3002`reset: true` \u53E6\u5916\u628A\u5F53\u524D\u76D2\u5B50\u8FD8\u539F\u5230\u521D\u59CB\u4F4D\u7F6E\u548C\u5927\u5C0F\uFF08\u6309 width / height \u9009\u9879\u6216\u9ED8\u8BA4\u503C\uFF0C\u4E0D\u91CD\u5EFA iframe\uFF09\u3002 */\n clearPersistedBox(opts?: { reset?: boolean }): void;\n /** \u8FD0\u884C\u65F6\u5F00\u5173\u624B\u52BF\u62D6\u52A8 (\u7B49\u4EF7\u4E8E `draggable` \u9009\u9879), \u4E0D\u91CD\u5EFA iframe\u3002 */\n /** \u6539\u5916\u58F3\u5706\u89D2 (\u6570\u5B57 px / CSS \u957F\u5EA6); \u4F20 undefined \u6062\u590D\u9ED8\u8BA4 (\u975E\u900F\u660E 20px / \u900F\u660E 0)\u3002 */\n setBorderRadius(radius: number | string | undefined): void;\n setDraggable(on: boolean): void;\n /** \u8FD0\u884C\u65F6\u5F00\u5173 / \u8C03\u6574\u89D2\u843D\u7F29\u653E (\u7B49\u4EF7\u4E8E `resizable` \u9009\u9879), \u4E0D\u91CD\u5EFA iframe\u3002false = \u5173\u3002 */\n setResizable(on: boolean | XiaochunResizeLimits): void;\n startListening(): Promise<void>;\n stopListening(): Promise<void>;\n mic(enabled: boolean): Promise<void>;\n pause(): void;\n resume(): void;\n destroy(): void;\n on<K extends keyof XiaochunEvents>(event: K, cb: (payload: XiaochunEvents[K]) => void): () => void;\n}\n\nconst FALLBACK_PLACEHOLDER =\n 'data:image/svg+xml;utf8,' +\n encodeURIComponent(\n '<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>',\n );\n\n/**\n * \u4E0D\u8BA9\u5934\u50CF\u88AB\u5BBF\u4E3B\u9875\u7684\u6587\u5B57\u9009\u533A\u9009\u4E2D: Chrome \u5728\u9009\u533A\u8DE8\u8FC7 iframe (\u62D6\u9009\u5212\u8FC7 / Cmd\u00B7Ctrl+A / \u5168\u9009) \u65F6\u4F1A\u7ED9\u6574\u5757 iframe \u76D6\u4E00\u5C42\u84DD\u8272\u9AD8\u4EAE\n * (\u5B9E\u6D4B Chrome \u7684 iframe \u4F1A\u88AB\u67D3\u8272; \u7ED9 iframe \u81EA\u8EAB\u8BBE user-select:none \u5373\u53EF\u6D88\u9664, \u5BBF\u4E3B\u9875\u81EA\u5DF1\u7684\u6587\u5B57\u4ECD\u7167\u5E38\u88AB\u9009\u4E2D)\u3002\n * \u53EA\u7528 CSSOM \u5185\u8054\u6837\u5F0F (\u4E0D\u6CE8\u5165 <style>), \u4E0D\u53D7\u5BBF\u4E3B CSP style-src \u5F71\u54CD, \u4E5F\u4E0D\u5F71\u54CD pointer-events / \u900F\u660E\u7A7F\u900F\u3002\n */\nconst noSelect = (st: CSSStyleDeclaration) => {\n st.setProperty('user-select', 'none');\n st.setProperty('-webkit-user-select', 'none');\n st.setProperty('-webkit-touch-callout', 'none');\n st.setProperty('-webkit-tap-highlight-color', 'transparent');\n};\n\nconst css = (v: number | string | undefined, d: string) =>\n v === undefined ? d : typeof v === 'number' ? `${v}px` : v;\n\n/** \u9ED8\u8BA4\u5C3A\u5BF8 (px): 600x1080\u3002\u53EA\u5728\u6CA1\u663E\u5F0F\u4F20 width / height \u65F6\u4F7F\u7528, \u5E76\u53D7\u89C6\u53E3\u9650\u5236 (\u89C1 defaultWidthCss / defaultHeightCss)\u3002 */\nexport const XC_DEFAULT_WIDTH = 600;\nexport const XC_DEFAULT_HEIGHT = 1080;\n/**\n * \u9ED8\u8BA4\u5BBD: 600px \u4F46\u4E0D\u8D85\u8FC7\u89C6\u53E3\u5BBD (min(600px, 100vw))\u3002\u4E0D\u7528 min(600px, 100%): \u767E\u5206\u6BD4\u5728 \"\u6309\u5185\u5BB9\u6536\u7F29\" \u7684\u5BB9\u5668 (inline-block / \u7EDD\u5BF9\u5B9A\u4F4D / <xiaochun-avatar> \u7684 :host)\n * \u91CC\u4F1A\u5FAA\u73AF\u4F9D\u8D56\u800C\u584C\u6210 0\u3002\u6BD4\u89C6\u53E3\u66F4\u7A84\u7684\u5BB9\u5668 (\u5982 300px \u7684\u4FA7\u680F) \u7531\u5916\u58F3\u7684 max-width:100% \u518D\u94B3\u4E00\u6B21, \u6240\u4EE5\u7A84\u5C4F / \u7A84\u5BB9\u5668\u90FD\u4E0D\u4F1A\u6EA2\u51FA\u3002\n */\nexport const defaultWidthCss = (floating = false): string =>\n floating ? `min(${XC_DEFAULT_WIDTH}px, calc(100vw - 2 * var(--xc-offset-x, 16px)))` : `min(${XC_DEFAULT_WIDTH}px, 100vw)`;\n/**\n * \u9ED8\u8BA4\u9AD8: 1080px \u4F46\u4E0D\u8D85\u8FC7\u89C6\u53E3\u9AD8 (\u5C0F\u7A97\u53E3 / \u624B\u673A\u6A2A\u5C4F\u94B3\u5236)\u3002\u6D4F\u89C8\u5668\u652F\u6301\u65F6\u7528 svh (\u79FB\u52A8\u7AEF\u5730\u5740\u680F\u4F38\u7F29\u65F6\u4E5F\u4E0D\u6EA2\u51FA), \u5426\u5219 vh\u3002\n * SSR \u4E0B (\u6CA1\u6709 CSS.supports) \u4E00\u5F8B vh, \u4E0E React \u670D\u52A1\u7AEF\u6E32\u67D3\u7684\u9996\u5E27\u4FDD\u6301\u4E00\u81F4\u3002\n */\nexport const defaultHeightCss = (floating = false): string => {\n const unit = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('height', '1svh') ? 'svh' : 'vh';\n // \u60AC\u6D6E (position\u2260inline) \u8D34\u7740\u5C4F\u5E55\u8FB9 + \u8FB9\u8DDD (--xc-offset-*), \u9ED8\u8BA4\u503C\u8981\u628A\u4E24\u4FA7\u8FB9\u8DDD\u6263\u6389, \u5426\u5219\u6574\u5757\u4F1A\u9876\u51FA\u5C4F\u5E55\n return floating ? `min(${XC_DEFAULT_HEIGHT}px, calc(100${unit} - 2 * var(--xc-offset-y, 16px)))` : `min(${XC_DEFAULT_HEIGHT}px, 100${unit})`;\n};\n\nexport function createXiaochun(options: XiaochunOptions): XiaochunInstance {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n throw new Error('[project-xiaochun] createXiaochun must run in a browser');\n }\n const container =\n typeof options.container === 'string' ? document.querySelector<HTMLElement>(options.container) : options.container;\n if (!container) throw new Error(`[project-xiaochun] container not found: ${String(options.container)}`);\n\n // \u2500\u2500 \u5730\u5740 / origin \u2500\u2500\n const src = options.src ?? XC_DEFAULT_SRC;\n let srcUrl: URL;\n try { srcUrl = new URL(src, window.location.href); } catch { throw new Error(`[project-xiaochun] invalid src: ${src}`); }\n const frameOrigin = normalizeOrigin(options.origin ?? srcUrl.origin);\n if (!frameOrigin) throw new Error('[project-xiaochun] invalid origin (wildcards are not allowed)');\n const trusted = new Set<string>([frameOrigin]);\n for (const o of options.allowedOrigins ?? []) {\n const n = normalizeOrigin(o);\n if (!n) throw new Error(`[project-xiaochun] invalid allowedOrigins entry: ${o} (wildcards are not allowed)`);\n trusted.add(n);\n }\n\n // \u2500\u2500 \u504F\u597D (persist, \u53EF\u9009): \u5BBF\u4E3B localStorage; iframe \u53E6\u6709\u81EA\u5DF1\u7684\u5B58\u50A8 \u2500\u2500\n const prefsKey = options.persist === 'host' ? 'xiaochun:prefs' : typeof options.persist === 'string' && options.persist ? options.persist : null;\n type Prefs = { outfit?: string; scene?: string };\n const readPrefs = (): Prefs => {\n if (!prefsKey) return {};\n try {\n const raw = JSON.parse(window.localStorage.getItem(prefsKey) ?? 'null') as Record<string, unknown> | null;\n const out: Prefs = {};\n if (raw && typeof raw === 'object') {\n if (isXcId(raw.outfit)) out.outfit = raw.outfit;\n if (isXcId(raw.scene)) out.scene = raw.scene;\n }\n return out;\n } catch { return {}; }\n };\n const writePrefs = (patch: { [K in keyof Prefs]?: string | null }) => {\n if (!prefsKey) return;\n try {\n const next: Record<string, string> = { ...readPrefs() };\n for (const [k, v] of Object.entries(patch)) { if (v) next[k] = v; else delete next[k]; }\n window.localStorage.setItem(prefsKey, JSON.stringify(next));\n } catch { /* localStorage \u4E0D\u53EF\u7528 (\u9690\u79C1\u6A21\u5F0F / \u914D\u989D): \u9759\u9ED8\u653E\u5F03\u4FDD\u5B58 */ }\n };\n const prefs = readPrefs();\n\n if (options.model !== undefined && options.outfit === undefined) {\n console.warn('[project-xiaochun] option \"model\" is deprecated, use \"outfit\" (built-in outfit id).');\n }\n // ui: \u90E8\u4EF6\u540D\u6570\u7EC4 (\u767D\u540D\u5355); \u5E03\u5C14 true \u662F\u5F03\u7528\u7684\u65E7\u5199\u6CD5 (= chat + bubble)\n const uiParse = normalizeXcUiOption(options.ui);\n const uiParts = uiParse.parts;\n // uiAutoHide: \u7F3A\u7701 = \u4E0D\u5199\u8FDB URL (iframe \u7528\u81EA\u5DF1\u7684\u9ED8\u8BA4 true); \u975E\u6CD5\u503C console.warn \u5E76\u5FFD\u7565\n const uiAutoHide = parseXcUiAutoHide(options.uiAutoHide);\n if (options.uiAutoHide !== undefined && uiAutoHide === undefined) console.warn(`[project-xiaochun] ignoring invalid uiAutoHide: ${String(options.uiAutoHide)} (use true | false | 'transparent')`);\n // camera: \u975E\u6CD5 \u2192 console.warn \u5E76\u6574\u4F53\u5FFD\u7565; \u8D8A\u754C \u2192 \u5939\u5230\u8303\u56F4\u5E76 warn; null / undefined \u9879\u4E0D\u5199\u8FDB URL\n let camera: XcCamera = {};\n if (options.camera !== undefined) {\n const r = normalizeXcCamera(options.camera);\n if (r.ok) {\n camera = r.camera;\n 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')})`);\n } else console.warn(`[project-xiaochun] ignoring invalid camera option: ${r.error}`);\n }\n if (uiParse.legacy) console.warn('[project-xiaochun] option \"ui: true\" is deprecated, use an array of parts, e.g. ui: [\\'chat\\', \\'bubble\\', \\'outfit\\', \\'scene\\'].');\n if (uiParse.unknown.length) console.warn(`[project-xiaochun] ignoring unknown ui part(s): ${uiParse.unknown.join(', ')} (known: ${XC_UI_PARTS.join(', ')})`);\n const outfitOpt = options.outfit ?? (isXcId(options.model) ? options.model : undefined);\n const initialOutfit = outfitOpt ?? prefs.outfit;\n const initialScene = options.scene ?? prefs.scene ?? (options.transparent ? 'transparent' : undefined);\n // \u573A\u666F\u540D\u672A\u77E5 (\u65E7\u7248/\u81EA\u5B9A\u4E49\u90E8\u7F72) \u65F6\u9000\u56DE transparent \u9009\u9879; \u63E1\u624B\u540E\u7684 xc.scene-changed \u4F1A\u6821\u6B63\n let transparent = initialScene === 'transparent' || (initialScene !== 'light' && initialScene !== 'dark' && (options.transparent ?? false));\n let passthrough = options.passthrough ?? transparent;\n const lazy: XiaochunLazy = options.lazy ?? true;\n const position = options.position ?? 'inline';\n const handshakeTimeout = options.handshakeTimeout ?? 20_000;\n\n // \u2500\u2500 DOM: wrapper (\u56FA\u5B9A\u5C3A\u5BF8, \u9632 CLS) \u2500\u2500\n const wrapper = document.createElement('div');\n wrapper.setAttribute('data-xiaochun', '');\n const ws = wrapper.style;\n ws.position = position === 'inline' ? 'relative' : 'fixed';\n ws.width = css(options.width, defaultWidthCss(position !== 'inline'));\n ws.height = css(options.height, defaultHeightCss(position !== 'inline'));\n ws.maxWidth = '100%';\n ws.overflow = 'visible';\n ws.contain = 'layout style';\n noSelect(ws); // \u5BBF\u4E3B\u9875\u7684\u6587\u5B57\u9009\u533A (\u62D6\u9009\u5212\u8FC7 / Cmd+A) \u4E0D\u4F1A\u628A\u5934\u50CF\u67D3\u6210\u84DD\u8272, \u89C1 noSelect\n // \u2500\u2500 \u6837\u5F0F hook: \u5BBF\u4E3B\u7528 CSS \u81EA\u5B9A\u4E49\u5C5E\u6027\u63A7\u5236\u5916\u89C2 (\u81EA\u5B9A\u4E49\u5C5E\u6027\u4F1A\u7A7F\u900F Shadow DOM, \u5728\u5BB9\u5668\u6216\u4EFB\u610F\u7956\u5148\u4E0A\u8BBE\u7F6E\u5373\u53EF) \u2500\u2500\n // \u6CE8\u610F: \u53EA\u80FD\u5F71\u54CD iframe \u7684\u300C\u5916\u58F3\u300D(\u5706\u89D2/\u9634\u5F71/\u4F4D\u7F6E/\u5C42\u7EA7/\u80CC\u666F); iframe \u5185\u90E8 (\u89D2\u8272\u6E32\u67D3\u3001\u6C14\u6CE1) \u662F\u8DE8\u57DF\u6587\u6863, \u5BBF\u4E3B CSS \u78B0\u4E0D\u5230\u3002\n // --xc-radius \u5706\u89D2, CSS \u957F\u5EA6, \u9ED8\u8BA4 0\u3002\u8303\u56F4 0 ~ \u5BBD\u5EA6\u7684\u4E00\u534A (50% = \u5706\u5F62\u5934\u50CF\u6846)\u3002\u8C03\u5927 = \u66F4\u5706; \u8FC7\u5927\u4F1A\u88C1\u6389\u89D2\u8272\u7684\u5934/\u811A\u3002\n // --xc-shadow box-shadow \u7B80\u5199, \u9ED8\u8BA4 none\u3002\u900F\u660E\u60AC\u6D6E\u5934\u50CF\u5EFA\u8BAE\u4FDD\u6301 none (\u5426\u5219\u4F1A\u51FA\u73B0\u4E00\u4E2A\u65B9\u5757\u9634\u5F71); \u5361\u7247\u5F0F\u5D4C\u5165\u53EF\u7528 '0 8px 24px rgba(0,0,0,.18)'\u3002\n // --xc-z-index \u4EC5\u60AC\u6D6E (position\u2260inline) \u751F\u6548, \u9ED8\u8BA4 2147483000 (\u63A5\u8FD1 int \u4E0A\u9650, \u76D6\u4F4F\u7EDD\u5927\u591A\u6570\u9875\u9762\u5143\u7D20)\u3002\u8C03\u5C0F = \u8BA9\u5BBF\u4E3B\u7684\u5F39\u7A97/\u5BFC\u822A\u76D6\u5728\u5934\u50CF\u4E0A\u9762\u3002\n // --xc-offset-x \u4EC5\u60AC\u6D6E: \u8DDD\u5C4F\u5E55\u5DE6/\u53F3\u8FB9\u7684\u8FB9\u8DDD, \u9ED8\u8BA4 16px\u3002\u8C03\u5927 = \u79BB\u8FB9\u7F18\u66F4\u8FDC (\u79FB\u52A8\u7AEF\u6CE8\u610F\u907F\u5F00\u7CFB\u7EDF\u624B\u52BF\u533A, \u5EFA\u8BAE \u2265 12px)\u3002\n // --xc-offset-y \u4EC5\u60AC\u6D6E: \u8DDD\u5C4F\u5E55\u5E95\u8FB9\u7684\u8FB9\u8DDD, \u9ED8\u8BA4 16px\u3002\u8C03\u5927 = \u62AC\u9AD8 (\u907F\u5F00\u5E95\u90E8\u5BFC\u822A\u680F/Cookie \u6A2A\u5E45)\u3002\n // --xc-bg \u975E\u900F\u660E\u6A21\u5F0F\u4E0B iframe \u52A0\u8F7D\u524D/\u5706\u89D2\u5916\u7684\u5E95\u8272, \u9ED8\u8BA4 transparent\u3002transparent: true \u65F6\u5FFD\u7565\u3002\n ws.boxShadow = 'var(--xc-shadow, none)';\n const applyWrapperBg = () => { ws.background = transparent ? '' : 'var(--xc-bg, transparent)'; };\n applyWrapperBg();\n // \u5706\u89D2: \u9009\u9879 > (\u975E\u900F\u660E 20px / \u900F\u660E 0); \u5BBF\u4E3B\u7684 --xc-radius CSS \u53D8\u91CF\u59CB\u7EC8\u4F18\u5148\n let radiusOpt: number | string | undefined = options.borderRadius;\n const radiusValue = () => (radiusOpt !== undefined ? css(radiusOpt, '0px') : transparent ? '0px' : `${XC_WINDOW_CORNER_RADIUS}px`);\n const applyRadius = () => {\n const v = `var(--xc-radius, ${radiusValue()})`;\n ws.borderRadius = v;\n if (placeholderEl) placeholderEl.style.borderRadius = v;\n if (iframe) iframe.style.borderRadius = v;\n };\n ws.borderRadius = `var(--xc-radius, ${radiusValue()})`;\n if (position === 'bottom-right') { ws.right = 'var(--xc-offset-x, 16px)'; ws.bottom = 'var(--xc-offset-y, 16px)'; }\n if (position === 'bottom-left') { ws.left = 'var(--xc-offset-x, 16px)'; ws.bottom = 'var(--xc-offset-y, 16px)'; }\n if (position !== 'inline') ws.zIndex = `var(--xc-z-index, ${options.zIndex ?? 2147483000})`;\n ws.pointerEvents = 'none'; // \u5BB9\u5668\u672C\u8EAB\u4E0D\u5403\u4E8B\u4EF6; \u5360\u4F4D/iframe \u5404\u81EA\u5F00\n wrapper.setAttribute('part', 'wrapper'); // ::part(wrapper) (\u4EC5 <xiaochun-avatar> \u7684 Shadow DOM \u5185\u6709\u610F\u4E49)\n container.appendChild(wrapper);\n\n let placeholderEl: HTMLElement | null = null;\n if (options.placeholder !== false) {\n if (options.placeholder instanceof HTMLElement) placeholderEl = options.placeholder;\n else {\n const img = document.createElement('img');\n img.src = options.placeholder || FALLBACK_PLACEHOLDER;\n img.alt = 'Project XiaoChun';\n img.decoding = 'async';\n img.width = XC_DEFAULT_WIDTH; img.height = XC_DEFAULT_HEIGHT; // \u6709 width/height \u5C5E\u6027 + \u4E0B\u9762\u7684 100% \u6837\u5F0F, \u89E3\u7801\u524D\u4E5F\u4E0D\u6296\u52A8\n placeholderEl = img;\n }\n const ps = placeholderEl.style;\n placeholderEl.setAttribute('part', 'placeholder');\n ps.borderRadius = `var(--xc-radius, ${radiusValue()})`;\n ps.position = 'absolute'; ps.inset = '0'; ps.width = '100%'; ps.height = '100%';\n ps.objectFit = 'contain'; ps.transition = 'opacity .25s ease'; ps.pointerEvents = 'auto';\n ps.cursor = lazy === false ? 'default' : 'pointer';\n noSelect(ps); // \u5360\u4F4D\u56FE (<img>) \u540C\u6837\u4F1A\u88AB\u9009\u533A\u67D3\u84DD\n placeholderEl.addEventListener('click', () => activate());\n wrapper.appendChild(placeholderEl);\n }\n\n // \u2500\u2500 \u4E8B\u4EF6 \u2500\u2500\n const listeners = new Map<string, Set<(p: any) => void>>();\n const emit = <K extends keyof XiaochunEvents>(ev: K, payload: XiaochunEvents[K]) => {\n listeners.get(ev)?.forEach((cb) => { try { cb(payload); } catch (e) { console.error('[project-xiaochun] listener error', e); } });\n };\n\n // \u2500\u2500 ready promise \u2500\u2500\n let resolveReady!: () => void;\n let rejectReady!: (e: Error) => void;\n const ready = new Promise<void>((res, rej) => { resolveReady = res; rejectReady = rej; });\n ready.catch(() => {}); // \u907F\u514D\u6CA1\u4EBA await \u65F6\u7684 unhandled rejection\n\n // \u2500\u2500 \u72B6\u6001 \u2500\u2500\n let iframe: HTMLIFrameElement | null = null;\n let port: MessagePort | null = null;\n let destroyed = false;\n let userPaused = false;\n let autoPaused = false;\n let loaded = false;\n let lastHit = false;\n let caps: XcReadyPayload['capabilities'] | null = null;\n let currentOutfit: string | null = null;\n let currentScene: string | null = null;\n /** \u547D\u4EE4\u4F9D\u8D56\u7684 capabilities \u5B57\u6BB5; \u63E1\u624B\u540E\u82E5 iframe \u6CA1\u6709 (\u65E7\u7248 /embed) \u5C31\u672C\u5730 reject, \u4E0D\u53D1\u51FA\u53BB\u3002 */\n type CapKey = 'outfits' | 'scenes' | 'prefetch';\n const queue: Array<{ type: XcHostMessageType; payload?: unknown; id?: string; transfer?: Transferable[]; requires?: CapKey }> = [];\n const pending = new Map<string, { resolve: (v?: unknown) => void; reject: (e: Error) => void; sawEnd: boolean }>();\n let idSeq = 0;\n let handshakeTimer: ReturnType<typeof setTimeout> | null = null;\n let io: IntersectionObserver | null = null;\n let idleHandle: number | null = null;\n let resolveHandshake!: () => void;\n const handshaked = new Promise<void>((res) => { resolveHandshake = res; });\n\n /** \u672C\u5730\u62D2\u7EDD\u4E00\u6761\u547D\u4EE4 (iframe \u4E0D\u652F\u6301): reject \u5BF9\u5E94 Promise + \u89E6\u53D1 error \u4E8B\u4EF6\u3002 */\n const failLocal = (type: XcHostMessageType, id: string | undefined, code: XiaochunErrorCode, message: string) => {\n emit('error', { code, message, command: type });\n const p = id ? pending.get(id) : undefined;\n if (p && id) { pending.delete(id); p.reject(new Error(`[${code}] ${message}`)); }\n };\n const unsupportedByFrame = (type: XcHostMessageType, id: string | undefined) =>\n failLocal(type, id, 'unsupported', `${type} is not supported by this /embed deployment (older version; its xc.ready has no capabilities for it)`);\n\n const postToFrame = (type: XcHostMessageType, payload?: unknown, id?: string, transfer?: Transferable[], requires?: CapKey) => {\n if (!port) { queue.push({ type, payload, id, transfer, requires }); return; }\n if (requires && !caps?.[requires]) { unsupportedByFrame(type, id); return; }\n port.postMessage(xcMessage(type, payload, id), transfer ?? []);\n };\n\n const send = (type: XcHostMessageType, payload?: unknown, wait = false, transfer?: Transferable[], fixedId?: string, requires?: CapKey): Promise<any> => {\n if (destroyed) return Promise.reject(new Error('[project-xiaochun] instance destroyed'));\n if (!iframe) activate(); // \u4EFB\u4F55\u4EA4\u4E92 API \u90FD\u89C6\u4E3A\"\u7528\u6237\u610F\u56FE\", \u7ACB\u5373\u521B\u5EFA\n const id = fixedId ?? `c${++idSeq}`;\n // \u547D\u4EE4\u5E94\u7B54\u53EF\u4EE5\u5E26\u4E00\u4E2A\u503C (\u5982 xc.prefetched \u7684\u7ED3\u679C); \u5176\u5B83\u547D\u4EE4 resolve(undefined)\n const p: Promise<any> = wait\n ? new Promise<any>((resolve, reject) => pending.set(id, { resolve, reject, sawEnd: false }))\n : Promise.resolve();\n postToFrame(type, payload, id, transfer, requires);\n return p;\n };\n\n // \u2500\u2500 \u5BBF\u4E3B\u97F3\u9891 \u2500\u2500\n /** TypedArray \u89C6\u56FE \u2192 \u53EA\u542B\u5176\u8303\u56F4\u7684\u72EC\u7ACB ArrayBuffer (\u62F7\u8D1D); ArrayBuffer \u539F\u6837\u8FD4\u56DE\u3002 */\n const toBuffer = (d: ArrayBuffer | ArrayBufferView): ArrayBuffer =>\n d instanceof ArrayBuffer ? d : (d.buffer as ArrayBuffer).slice(d.byteOffset, d.byteOffset + d.byteLength);\n const bindAbort = (signal: AbortSignal | undefined, id: string) => {\n if (!signal) return;\n const abort = () => { if (!destroyed) postToFrame('xc.audio.end', { abort: true }, id); };\n if (signal.aborted) abort(); else signal.addEventListener('abort', abort, { once: true });\n };\n const speakAudio = async (source: XiaochunAudioSource, opts: XiaochunAudioOptions = {}): Promise<void> => {\n if (destroyed) throw new Error('[project-xiaochun] instance destroyed');\n if (!iframe) activate(); // \u5148\u521B\u5EFA iframe (lazy \u6A21\u5F0F\u4E0B\u4E0E fetch \u5E76\u884C, \u7701\u4E00\u70B9\u9996\u6B21\u5EF6\u8FDF)\n const { signal, transfer, fetch: fetchWhere, ...rest } = opts;\n const payload: Record<string, unknown> = { ...rest };\n const list: Transferable[] = [];\n if (typeof source === 'string') {\n if (fetchWhere === 'frame') payload.source = source;\n else {\n const res = await fetch(source);\n if (!res.ok) throw new Error(`[project-xiaochun] audio fetch failed: HTTP ${res.status}`);\n const buf = await res.arrayBuffer();\n payload.source = buf; list.push(buf);\n payload.mimeType ??= res.headers.get('content-type') ?? undefined;\n }\n } else if (typeof Blob !== 'undefined' && source instanceof Blob) {\n payload.source = source; // Blob \u8D70\u7ED3\u6784\u5316\u514B\u9686 (\u6D4F\u89C8\u5668\u5185\u90E8\u5F15\u7528\u540C\u4E00\u4EFD\u6570\u636E, \u4E0D\u6574\u6BB5\u590D\u5236)\n payload.mimeType ??= source.type || undefined;\n } else {\n const buf = toBuffer(source as ArrayBuffer | ArrayBufferView);\n payload.source = buf;\n // \u89C6\u56FE\u603B\u662F\u62F7\u8D1D\u540E\u7684\u65B0 buffer \u2192 \u8F6C\u79FB; \u7528\u6237\u4F20\u5165\u7684 ArrayBuffer \u4EC5\u5728 transfer !== false \u65F6\u8F6C\u79FB (\u4F1A\u88AB detach)\n if (!(source instanceof ArrayBuffer) || transfer !== false) list.push(buf);\n }\n if (destroyed) throw new Error('[project-xiaochun] instance destroyed');\n const id = `c${++idSeq}`;\n const done = send('xc.audio', payload, true, list, id);\n bindAbort(signal, id); // \u5FC5\u987B\u5728 send \u4E4B\u540E (\u4FE1\u53F7\u5DF2 aborted \u65F6, abort \u6D88\u606F\u8981\u6392\u5728 xc.audio \u540E\u9762)\n return done;\n };\n const speakAudioStream = (opts: XiaochunAudioOptions & { sampleRate: number }): XiaochunAudioStream => {\n if (destroyed) throw new Error('[project-xiaochun] instance destroyed');\n const { signal, transfer, fetch: _f, mimeType: _m, ...rest } = opts;\n const id = `c${++idSeq}`;\n let started = false;\n let ended = false;\n let fmt: 'pcm16' | 'float32' | null = rest.format === 'pcm16' || rest.format === 'float32' ? rest.format : null;\n let done: Promise<void> = Promise.resolve();\n const handle: XiaochunAudioStream = {\n write(data) {\n if (ended) throw new Error('[project-xiaochun] audio stream already ended');\n if (destroyed) throw new Error('[project-xiaochun] instance destroyed');\n if (data instanceof Int16Array) fmt ??= 'pcm16';\n else if (data instanceof Float32Array) fmt ??= 'float32';\n if (!fmt) throw new Error('[project-xiaochun] speakAudioStream: set opts.format when writing raw ArrayBuffers');\n const buf = toBuffer(data);\n const body: Record<string, unknown> = { data: buf, format: fmt, sampleRate: rest.sampleRate, channels: rest.channels };\n if (!started) {\n started = true;\n body.text = rest.text; body.motion = rest.motion; body.lipsync = rest.lipsync;\n done = send('xc.audio.chunk', body, true, [buf], id);\n bindAbort(signal, id);\n } else {\n postToFrame('xc.audio.chunk', body, id, !(data instanceof ArrayBuffer) || transfer !== false ? [buf] : []);\n }\n },\n end() {\n if (ended) return;\n ended = true;\n if (started) postToFrame('xc.audio.end', {}, id);\n },\n abort() {\n if (ended && !started) return;\n ended = true;\n if (started) postToFrame('xc.audio.end', { abort: true }, id);\n },\n get done() { return done; },\n };\n return handle;\n };\n\n // \u2500\u2500 iframe \u521B\u5EFA \u2500\u2500\n function buildUrl(): string {\n const u = new URL(srcUrl.href);\n u.searchParams.set('host', window.location.origin); // iframe \u7AEF\u7528\u5B83\u505A\u63E1\u624B\u767D\u540D\u5355\n if (transparent) u.searchParams.set('transparent', '1');\n if (uiParts.length) u.searchParams.set('ui', uiParts.join(','));\n if (options.lang) u.searchParams.set('lang', options.lang);\n if (uiAutoHide !== undefined) u.searchParams.set('uiAutoHide', String(uiAutoHide));\n if (typeof camera.fov === 'number') u.searchParams.set('cameraFov', String(camera.fov));\n if (typeof camera.distance === 'number') u.searchParams.set('cameraDistance', String(camera.distance));\n if (typeof camera.height === 'number') u.searchParams.set('cameraHeight', String(camera.height));\n if (typeof camera.intro === 'boolean') u.searchParams.set('cameraIntro', camera.intro ? '1' : '0');\n if (options.heavy) u.searchParams.set('heavy', options.heavy);\n if (options.controls === false) u.searchParams.set('controls', '0');\n if (initialScene && isXcId(initialScene)) u.searchParams.set('scene', initialScene);\n if (initialOutfit) u.searchParams.set('outfit', initialOutfit);\n return u.href;\n }\n\n function activate(): void {\n if (destroyed || iframe) return;\n cancelIdle();\n io?.disconnect(); io = null;\n const f = document.createElement('iframe');\n f.title = 'Project XiaoChun';\n f.loading = 'lazy';\n f.allow = options.crossOriginIsolated === true\n ? 'microphone; autoplay; cross-origin-isolated' // \u5BBF\u4E3B\u5DF2 COOP/COEP \u9694\u79BB\u65F6, \u989D\u5916\u59D4\u6D3E\u8DE8\u6E90\u9694\u79BB \u2192 iframe \u5185 SharedArrayBuffer / \u591A\u7EBF\u7A0B wasm\n : 'microphone; autoplay'; // \u5BBF\u4E3B\u5FC5\u987B\u59D4\u6D3E: \u9EA6\u514B\u98CE (STT) + \u81EA\u52A8\u64AD\u653E (TTS \u97F3\u9891; \u7F3A\u5B83\u5219\u70B9\u51FB\u5BBF\u4E3B\u9875\u540E iframe \u5185 AudioContext \u4ECD\u88AB\u62E6)\n f.referrerPolicy = 'strict-origin-when-cross-origin';\n if (options.sandbox !== false) {\n f.setAttribute('sandbox', options.sandbox ?? 'allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox');\n }\n f.setAttribute('allowtransparency', 'true');\n f.setAttribute('scrolling', 'no');\n const s = f.style;\n s.position = 'absolute'; s.inset = '0'; s.width = '100%'; s.height = '100%';\n s.border = '0'; s.background = 'transparent'; s.colorScheme = 'normal';\n s.borderRadius = `var(--xc-radius, ${radiusValue()})`; // \u5706\u89D2\u88C1\u526A iframe \u5185\u5BB9 (\u5BBF\u4E3B CSS \u53EA\u80FD\u6539\u8FD9\u5C42\u5916\u58F3, \u6539\u4E0D\u5230 iframe \u5185\u90E8)\n f.setAttribute('part', 'iframe');\n noSelect(s);\n s.opacity = '0'; s.transition = 'opacity .25s ease';\n s.pointerEvents = passthrough ? 'none' : 'auto';\n f.src = buildUrl();\n iframe = f;\n wrapper.appendChild(f);\n if (placeholderEl) placeholderEl.style.cursor = 'default';\n handshakeTimer = setTimeout(() => {\n if (!port) emit('error', { code: 'timeout', message: `no xc.ready from ${frameOrigin} within ${handshakeTimeout}ms` });\n }, handshakeTimeout);\n setupAutoPause();\n if (passthrough) enablePassthrough();\n }\n\n // \u2500\u2500 \u6765\u81EA iframe \u7684\u63E1\u624B (window message) \u2500\u2500\n const onWindowMessage = (ev: MessageEvent) => {\n if (destroyed || !iframe || ev.source !== iframe.contentWindow) return; // \u53EA\u8BA4\u6211\u4EEC\u8FD9\u4E2A iframe\n if (!trusted.has(ev.origin)) {\n emit('error', { code: 'origin_denied', message: `ignored message from untrusted origin ${ev.origin}` });\n return;\n }\n const data = ev.data;\n if (!isXcEnvelope(data) || data.type !== 'xc.ready' || port) return; // \u63E1\u624B\u53EA\u505A\u4E00\u6B21\n const ch = new MessageChannel();\n port = ch.port1;\n port.onmessage = onPortMessage;\n caps = (data.payload as XcReadyPayload | undefined)?.capabilities ?? null;\n // targetOrigin = \u5DF2\u6821\u9A8C\u7684 ev.origin, \u7EDD\u4E0D\u7528 '*'\u3002allowCustomModel \u8D70 xc.init \u7684 config (\u4E0D\u8FDB URL), \u65E7 iframe \u4F1A\u5FFD\u7565\u672A\u77E5\u5B57\u6BB5\n // \u624B\u52BF\u5F00\u5173\u968F xc.init \u4E00\u8D77\u4EA4\u7ED9 iframe (iframe \u9ED8\u8BA4\u4E0D\u8BC6\u522B\u4EFB\u4F55\u624B\u52BF); \u65E7\u7248 /embed \u6CA1\u6709 capabilities.gestures \u2192 \u4E0D\u53D1\n const gWant = wantGestures();\n sentGestures = gWant;\n const initConfig: XcConfig = {\n ...(options.allowCustomModel ? { allowCustomModel: true } : {}),\n ...(gWant.move || gWant.resize ? { gestures: gWant } : {}),\n };\n iframe.contentWindow!.postMessage(\n xcMessage('xc.init', { hostOrigin: window.location.origin, ...(Object.keys(initConfig).length ? { config: initConfig } : {}) }),\n ev.origin,\n [ch.port2],\n );\n warnGestureUnsupported();\n if (handshakeTimer) { clearTimeout(handshakeTimer); handshakeTimer = null; }\n emit('handshake', data.payload as XcReadyPayload);\n resolveHandshake();\n for (const m of queue.splice(0)) {\n if (m.requires && !caps?.[m.requires]) unsupportedByFrame(m.type, m.id);\n else port.postMessage(xcMessage(m.type, m.payload, m.id), m.transfer ?? []);\n }\n syncPause();\n };\n window.addEventListener('message', onWindowMessage);\n\n /** \u547D\u4EE4\u5E94\u7B54: \u7528\u540C\u4E00\u4E2A\u4FE1\u5C01 id resolve \u5BF9\u5E94\u7684 Promise (xc.outfit-changed / xc.scene-changed)\u3002 */\n function ack(id: string | undefined, value?: unknown) {\n const p = id ? pending.get(id) : undefined;\n if (p && id) { pending.delete(id); p.resolve(value); }\n }\n\n // \u2500\u2500 \u6765\u81EA iframe \u7684\u7AEF\u53E3\u6D88\u606F \u2500\u2500\n function onPortMessage(ev: MessageEvent) {\n const data = ev.data as XcFrameMessage;\n if (!isXcEnvelope(data)) return;\n switch (data.type) {\n case 'xc.load.progress': emit('progress', data.payload); break;\n case 'xc.loaded':\n if (!loaded) {\n loaded = true;\n // \u81EA\u52A8\u9884\u53D6: \u53EA\u5728 heavy:'eager' \u4E14 iframe \u58F0\u660E\u652F\u6301\u65F6; \u5931\u8D25 / \u90E8\u5206\u5931\u8D25\u90FD\u4E0D\u6253\u6270\u5BBF\u4E3B (\u663E\u5F0F prefetch() \u624D\u8FD4\u56DE\u7ED3\u679C)\n if (options.prefetch && options.heavy === 'eager' && caps?.prefetch) {\n const ids = Array.isArray(options.prefetch) ? options.prefetch : undefined;\n void api.prefetch(ids).catch(() => {});\n }\n if (iframe) iframe.style.opacity = '1';\n if (placeholderEl) {\n const el = placeholderEl;\n el.style.opacity = '0'; el.style.pointerEvents = 'none';\n setTimeout(() => el.remove(), 300);\n placeholderEl = null;\n }\n resolveReady();\n }\n emit('ready', data.payload);\n break;\n case 'xc.outfit-changed': {\n const pl = data.payload;\n if (!pl.noop) {\n currentOutfit = pl.id;\n emit('outfit-changed', pl);\n if (!pl.initial && pl.id) writePrefs({ outfit: pl.id }); // \u53EA\u8BB0\u7528\u6237/\u5BBF\u4E3B\u4E3B\u52A8\u6362\u7684, \u4E0D\u8BB0\u9ED8\u8BA4\u670D\u88C5\n }\n ack(data.id);\n break;\n }\n case 'xc.scene-changed': {\n const pl = data.payload;\n currentScene = pl.id;\n if (pl.transparent !== transparent) applyTransparency(pl.transparent); // iframe \u662F\u4E8B\u5B9E\u6E90: \u540C\u6B65\u5916\u58F3\u80CC\u666F / \u7A7F\u900F / pointer-events\n if (!pl.noop) {\n emit('scene-changed', pl);\n if (!pl.initial) writePrefs({ scene: pl.id });\n }\n ack(data.id);\n break;\n }\n case 'xc.lang-changed': emit('lang-changed', data.payload); break;\n case 'xc.prefetched': ack(data.id, data.payload); break;\n case 'xc.state': emit('state', data.payload); break;\n case 'xc.stt': emit('stt', data.payload); break;\n case 'xc.utterance': {\n emit('utterance', data.payload);\n const p = data.id ? pending.get(data.id) : undefined;\n if (p && data.payload.phase === 'end') { pending.delete(data.id!); p.resolve(); }\n break;\n }\n case 'xc.hit-region': {\n const { hit } = data.payload;\n emit('hit-region', data.payload);\n if (passthrough && iframe && hit !== lastHit) {\n lastHit = hit;\n iframe.style.pointerEvents = hit ? 'auto' : 'none';\n }\n break;\n }\n case 'xc.gesture-move': onGesture('move', data.payload); break;\n case 'xc.gesture-resize': onGesture('resize', data.payload); break;\n case 'xc.error': {\n const { code, message, command } = data.payload;\n emit('error', { code, message, command });\n // \u521D\u59CB ?outfit= / ?scene= \u88AB iframe \u5224\u4E3A\u975E\u6CD5: \u5DF2\u4FDD\u5B58\u7684\u504F\u597D\u662F\u574F\u7684, \u6E05\u6389\u514D\u5F97\u6BCF\u6B21\u90FD\u62A5\n if (code === 'unknown_id' && (command === 'outfit' || command === 'scene')) writePrefs({ [command]: null });\n const p = data.id ? pending.get(data.id) : undefined;\n if (p && data.id) { pending.delete(data.id); p.reject(new Error(`[${code}] ${message}`)); }\n break;\n }\n default: break;\n }\n }\n\n // \u2500\u2500 \u5BBF\u4E3B pointer \u2192 iframe (\u900F\u660E\u7A7F\u900F\u6A21\u5F0F) \u2500\u2500\n // iframe \u5904\u4E8E pointer-events:none \u65F6, \u5BBF\u4E3B\u9875\u7684 pointermove \u624D\u662F\u552F\u4E00\u7EBF\u7D22:\n // - \u6307\u9488\u4E0D\u5728 iframe \u8303\u56F4\u5185\u65F6\u53EA\u505A\u4E00\u6B21\u5EC9\u4EF7\u7684\u77E9\u5F62\u6BD4\u8F83 (\u77E9\u5F62\u7F13\u5B58, \u4E0D\u5728\u6BCF\u5E27 getBoundingClientRect \u4EE5\u514D\u5F3A\u5236\u56DE\u6D41);\n // - \u6307\u9488\u5728\u8303\u56F4\u5185\u65F6\u6BCF\u5E27\u6700\u591A\u53D1\u4E00\u6B21 xc.pointer, \u4E14\u79FB\u52A8\u4E0D\u8DB3 2px \u6216\u8DDD\u4E0A\u6B21\u4E0D\u8DB3 32ms \u5219\u8DF3\u8FC7, \u907F\u514D iframe \u91CC\u6BCF\u5E27\u4E00\u6B21\u5C04\u7EBF\u68C0\u6D4B\u3002\n const POINTER_MIN_INTERVAL_MS = 32;\n const POINTER_MIN_MOVE_PX = 2;\n let pointerRaf = 0;\n let lastPtr: { x: number; y: number } | null = null;\n let lastPosted: { x: number; y: number; t: number } | null = null;\n let rectCache: DOMRect | null = null;\n let rectRo: ResizeObserver | null = null;\n let rectAt = 0;\n const invalidateRect = () => { rectCache = null; };\n const getRect = (): DOMRect | null => {\n if (!iframe) return null;\n const now = performance.now();\n // \u515C\u5E95 TTL: \u5185\u8054\u5E03\u5C40\u88AB\u9875\u9762\u5176\u5B83\u5185\u5BB9\u63A8\u52A8 (\u4E0D\u89E6\u53D1 resize/scroll) \u65F6, \u6700\u591A 400ms \u540E\u81EA\u6108\n if (!rectCache || now - rectAt > 400) { rectCache = iframe.getBoundingClientRect(); rectAt = now; }\n return rectCache;\n };\n const onHostPointer = (e: PointerEvent) => {\n if (!iframe || !port || iframe.style.pointerEvents === 'auto') return; // iframe \u81EA\u5DF1\u62FF\u5230\u4E8B\u4EF6\u65F6\u7531\u5B83\u4E0A\u62A5\n lastPtr = { x: e.clientX, y: e.clientY };\n if (pointerRaf) return;\n pointerRaf = requestAnimationFrame(() => {\n pointerRaf = 0;\n if (!iframe || !port || !lastPtr) return;\n const r = getRect();\n if (!r) return;\n const x = lastPtr.x - r.left, y = lastPtr.y - r.top;\n if (x < 0 || y < 0 || x > r.width || y > r.height) {\n lastPosted = null;\n if (lastHit) { lastHit = false; iframe.style.pointerEvents = 'none'; }\n return;\n }\n const now = performance.now();\n if (lastPosted && now - lastPosted.t < POINTER_MIN_INTERVAL_MS) return;\n if (lastPosted && Math.abs(x - lastPosted.x) < POINTER_MIN_MOVE_PX && Math.abs(y - lastPosted.y) < POINTER_MIN_MOVE_PX) return;\n lastPosted = { x, y, t: now };\n port.postMessage(xcMessage('xc.pointer', { x, y }));\n });\n };\n // \u7A7F\u900F\u76D1\u542C\u53EF\u542F\u505C (\u8FD0\u884C\u4E2D\u5207 scene \u65F6\u9700\u8981): enable / disable \u90FD\u5E42\u7B49\u3002\n let passthroughActive = false;\n function enablePassthrough() {\n if (passthroughActive || !iframe) return;\n passthroughActive = true;\n window.addEventListener('pointermove', onHostPointer, { passive: true });\n // \u89E6\u5C4F\u6CA1\u6709 hover: \u70B9\u4E00\u4E0B (pointerdown) \u4E5F\u63A2\u6D4B\u4E00\u6B21\u547D\u4E2D, \u547D\u4E2D\u540E iframe \u8F6C auto, \u4E0B\u4E00\u6B21\u70B9\u51FB\u5373\u53EF\u843D\u5230\u89D2\u8272 / \u5185\u7F6E\u6309\u94AE\u4E0A\n window.addEventListener('pointerdown', onHostPointer, { passive: true });\n window.addEventListener('scroll', invalidateRect, { passive: true, capture: true });\n window.addEventListener('resize', invalidateRect, { passive: true });\n if (typeof ResizeObserver !== 'undefined') {\n rectRo = new ResizeObserver(invalidateRect);\n rectRo.observe(iframe);\n }\n }\n function disablePassthrough() {\n if (!passthroughActive) return;\n passthroughActive = false;\n window.removeEventListener('pointermove', onHostPointer);\n window.removeEventListener('pointerdown', onHostPointer);\n window.removeEventListener('scroll', invalidateRect, true);\n window.removeEventListener('resize', invalidateRect);\n rectRo?.disconnect(); rectRo = null;\n if (pointerRaf) { cancelAnimationFrame(pointerRaf); pointerRaf = 0; }\n lastPtr = null;\n }\n /**\n * \u8FD0\u884C\u4E2D\u5207\u6362\u900F\u660E \u2194 \u975E\u900F\u660E (xc.scene-changed \u9A71\u52A8): \u540C\u6B65\u5916\u58F3\u80CC\u666F\u3001\u5F00\u5173\u7A7F\u900F\u76D1\u542C\u3001\u91CD\u7F6E\u547D\u4E2D\u72B6\u6001\u3002\n * - \u5207\u5230\u975E\u900F\u660E: \u5F3A\u5236 iframe pointer-events:auto (\u6574\u5757\u753B\u5E03\u90FD\u662F\u89D2\u8272\u80CC\u666F, \u4E0D\u8BE5\u7A7F\u900F), \u5173\u6389\u7A7F\u900F\u76D1\u542C;\n * - \u5207\u5230\u900F\u660E: passthrough \u9009\u9879\u663E\u5F0F\u7ED9\u4E86\u5C31\u6309\u5B83, \u5426\u5219\u6253\u5F00; iframe \u5148 none, \u7B49 xc.pointer / xc.hit-region \u518D\u5207 auto;\n * - \u4E24\u79CD\u60C5\u51B5\u90FD\u6E05\u6389 lastHit / lastPosted / \u77E9\u5F62\u7F13\u5B58, \u5426\u5219 iframe \u4FA7\u5DF2\u91CD\u7F6E\u7684\u53BB\u91CD\u72B6\u6001\u4F1A\u548C\u8FD9\u91CC\u5BF9\u4E0D\u4E0A, \u5BFC\u81F4\u6307\u9488\u4E0D\u52A8\u65F6\u7B2C\u4E00\u6B21\u547D\u4E2D\u88AB\u541E\u3002\n */\n function applyTransparency(next: boolean) {\n transparent = next;\n applyWrapperBg();\n applyRadius();\n passthrough = next ? (options.passthrough ?? true) : false;\n lastHit = false; lastPosted = null; rectCache = null;\n if (passthrough) enablePassthrough(); else disablePassthrough();\n if (iframe) iframe.style.pointerEvents = passthrough ? 'none' : 'auto';\n }\n\n // \u2500\u2500 \u89C6\u53E3\u5916\u81EA\u52A8\u6682\u505C \u2500\u2500\n let pauseIo: IntersectionObserver | null = null;\n function setupAutoPause() {\n if (options.autoPause === false || typeof IntersectionObserver === 'undefined') return;\n pauseIo = new IntersectionObserver((entries) => {\n const visible = entries[entries.length - 1]?.isIntersecting ?? true;\n autoPaused = !visible;\n syncPause();\n });\n pauseIo.observe(wrapper);\n }\n let sentPaused = false;\n function syncPause() {\n if (!port) return;\n const want = userPaused || autoPaused;\n if (want === sentPaused) return;\n sentPaused = want;\n port.postMessage(xcMessage(want ? 'xc.pause' : 'xc.resume'));\n }\n\n // \u2500\u2500 lazy \u8C03\u5EA6 \u2500\u2500\n function cancelIdle() {\n if (idleHandle === null) return;\n const w = window as Window & { cancelIdleCallback?: (h: number) => void };\n if (w.cancelIdleCallback) w.cancelIdleCallback(idleHandle); else clearTimeout(idleHandle);\n idleHandle = null;\n }\n function scheduleLazy() {\n if (lazy === false) { activate(); return; }\n if (lazy === 'click') return;\n const go = () => {\n const w = window as Window & { requestIdleCallback?: (cb: () => void, o?: { timeout: number }) => number };\n // \u7A7A\u95F2\u56DE\u8C03 timeout 3s: \u4E3B\u7EBF\u7A0B\u4E00\u76F4\u5FD9\u4E5F\u6700\u8FDF 3s \u540E\u521B\u5EFA, \u8C03\u5927\u66F4\u4E0D\u5F71\u54CD\u9996\u5C4F, \u8C03\u5C0F\u66F4\u5FEB\u51FA\u73B0\n idleHandle = w.requestIdleCallback ? w.requestIdleCallback(() => { idleHandle = null; activate(); }, { timeout: 3000 }) : (setTimeout(activate, 1200) as unknown as number);\n };\n if (typeof IntersectionObserver === 'undefined') { go(); return; }\n io = new IntersectionObserver((entries) => {\n if (entries.some((e) => e.isIntersecting)) { io?.disconnect(); io = null; go(); }\n }, { rootMargin: `${options.lazyMargin ?? 200}px` });\n io.observe(wrapper);\n }\n\n // \u2500\u2500 \u624B\u52BF: \u62D6\u52A8 / \u7F29\u653E (iframe \u91CC\u8BC6\u522B, \u5BBF\u4E3B\u8FD9\u91CC\u6267\u884C + \u9650\u5E45) \u2500\u2500\n // \u534F\u8BAE: xc.gesture-move / xc.gesture-resize (\u89C1 protocol.ts \u7684 XcGestureBase)\u3002\u5BBF\u4E3B\u4E0D\u4FE1\u4EFB iframe \u53D1\u6765\u7684\u4EFB\u4F55\u6570:\n // \u6821\u9A8C\u8F7D\u8377 (parseGesturePayload) \u2192 \u5E8F\u53F7\u95F8\u95E8 (GestureGate) \u2192 \u4EE5\"\u624B\u52BF\u5F00\u59CB\u65F6\u7684\u76D2\u5B50 + \u7D2F\u8BA1\u4F4D\u79FB\"\u5939\u5728\u89C6\u53E3 / \u6700\u5C0F\u6700\u5927\u5C3A\u5BF8\u5185 (gesture-box.ts)\u3002\n // \u5BBF\u4E3B\u6CA1\u5F00 draggable / resizable \u65F6, \u5BF9\u5E94\u6D88\u606F\u4E00\u5F8B\u5FFD\u7565; \u540C\u4E00\u65F6\u523B\u53EA\u5141\u8BB8\u4E00\u4E2A\u624B\u52BF\u3002\n let draggableOn = options.draggable === true;\n let resizeLimits: ResizeLimits | null = normalizeResizable(options.resizable);\n const gates = { move: new GestureGate(), resize: new GestureGate() };\n let activeGesture: { kind: 'move' | 'resize'; start: Box; inlineBase: { left: number; top: number } | null; corner?: 'NW' | 'NE' | 'SW' | 'SE' } | null = null;\n /** \u5185\u8054\u6A21\u5F0F\u9760 CSS translate \u4F4D\u79FB (\u4E0D\u6539\u5E03\u5C40\u6D41); \u8BB0\u4E0B\u5F53\u524D\u4F4D\u79FB, \u624D\u80FD\u8FD8\u539F\u51FA\"\u6D41\u5185\u539F\u70B9\"\u3002 */\n let inlineShift = { x: 0, y: 0 };\n let userMoved = false;\n let sentGestures: { move: boolean; resize: boolean } | null = null;\n let warnedGesture = false;\n const viewport = (): Viewport => ({\n width: document.documentElement.clientWidth || window.innerWidth,\n height: document.documentElement.clientHeight || window.innerHeight,\n });\n const readBox = (): Box => { const r = wrapper.getBoundingClientRect(); return { left: r.left, top: r.top, width: r.width, height: r.height }; };\n const wantGestures = () => ({ move: draggableOn && caps?.gestures?.move === true, resize: resizeLimits !== null && caps?.gestures?.resize === true });\n\n function applyBox(b: Box, inlineBase: { left: number; top: number } | null, withSize: boolean): void {\n if (withSize) { ws.width = `${b.width}px`; ws.height = `${b.height}px`; ws.maxWidth = 'none'; } // maxWidth:100% \u4F1A\u628A\u7528\u6237\u62C9\u5927\u7684\u5BBD\u5EA6\u538B\u56DE\u5BB9\u5668\u5BBD\n if (position === 'inline') {\n const base = inlineBase ?? { left: b.left - inlineShift.x, top: b.top - inlineShift.y };\n inlineShift = { x: b.left - base.left, y: b.top - base.top };\n ws.setProperty('translate', `${inlineShift.x}px ${inlineShift.y}px`);\n } else {\n ws.left = `${b.left}px`; ws.top = `${b.top}px`; ws.right = 'auto'; ws.bottom = 'auto';\n }\n userMoved = true;\n invalidateRect();\n }\n\n // \u62D6\u52A8\u671F\u95F4\u4E0D\u51FA\u73B0\u9009\u4E2D\u84DD\u6846: \u5BBF\u4E3B\u9875\u4E34\u65F6 user-select:none \u5E76\u6E05\u6389\u5DF2\u6709\u9009\u533A (iframe \u5185\u90E8\u53E6\u6709\u5904\u7406)\n let selectionLock: { us: string; wus: string } | null = null;\n function lockSelection(on: boolean): void {\n const de = document.documentElement;\n if (on && !selectionLock) {\n selectionLock = { us: de.style.getPropertyValue('user-select'), wus: de.style.getPropertyValue('-webkit-user-select') };\n de.style.setProperty('user-select', 'none'); de.style.setProperty('-webkit-user-select', 'none');\n try { window.getSelection()?.removeAllRanges(); } catch { /* ignore */ }\n } else if (!on && selectionLock) {\n de.style.setProperty('user-select', selectionLock.us); de.style.setProperty('-webkit-user-select', selectionLock.wus);\n selectionLock = null;\n }\n }\n function endActiveGesture(kind?: 'move' | 'resize'): void {\n if (!activeGesture || (kind && activeGesture.kind !== kind)) return;\n gates[activeGesture.kind].close();\n const b = readBox();\n emit(activeGesture.kind, { phase: 'end', ...b });\n activeGesture = null;\n lockSelection(false);\n saveBox();\n }\n\n function onGesture(kind: 'move' | 'resize', raw: unknown): void {\n if (destroyed || !caps?.gestures) return;\n if (kind === 'move' ? !draggableOn : resizeLimits === null) return; // \u5BBF\u4E3B\u6CA1\u5F00: \u5FFD\u7565\n const p = parseGesturePayload(kind, raw);\n if (!p) return;\n if (p.phase === 'start' ? activeGesture !== null : activeGesture?.kind !== kind) return; // \u540C\u4E00\u65F6\u523B\u53EA\u5141\u8BB8\u4E00\u4E2A\u624B\u52BF\n if (!gates[kind].accept(p)) return;\n if (p.phase === 'start') {\n const start = readBox();\n activeGesture = {\n kind, start, corner: p.corner,\n inlineBase: position === 'inline' ? { left: start.left - inlineShift.x, top: start.top - inlineShift.y } : null,\n };\n lockSelection(true);\n emit(kind, { phase: 'start', ...start });\n return;\n }\n const a = activeGesture!;\n const vp = viewport();\n const next = kind === 'move'\n ? moveBox(a.start, p.totalDx, p.totalDy, vp)\n : resizeBox(a.start, a.corner!, p.totalDx, p.totalDy, resizeLimits!, vp);\n applyBox(next, a.inlineBase, kind === 'resize');\n emit(kind, { phase: p.phase, ...next });\n if (p.phase === 'end') { activeGesture = null; lockSelection(false); saveBox(); }\n }\n\n /** \u628A draggable / resizable \u7684\u5F53\u524D\u503C\u540C\u6B65\u7ED9 iframe (\u53EA\u5728\u53D8\u5316\u65F6\u53D1 xc.setConfig{gestures}); \u63E1\u624B\u65F6\u5DF2\u968F xc.init \u53D1\u8FC7\u4E00\u6B21\u3002 */\n function syncGestures(): void {\n if (destroyed) return;\n const want = wantGestures();\n if (!want.move) endActiveGesture('move');\n if (!want.resize) endActiveGesture('resize');\n if (!port || !caps) return;\n warnGestureUnsupported();\n if (sentGestures && sentGestures.move === want.move && sentGestures.resize === want.resize) return;\n sentGestures = want;\n if (caps.gestures) port.postMessage(xcMessage('xc.setConfig', { gestures: want }));\n }\n /** \u65E7\u7248 /embed (\u63E1\u624B\u91CC\u6CA1\u6709 capabilities.gestures) \u5374\u5F00\u4E86\u624B\u52BF: \u544A\u77E5\u4E00\u6B21\u3002 */\n function warnGestureUnsupported(): void {\n if (warnedGesture || !caps || caps.gestures) return;\n const needMove = draggableOn;\n if (!needMove && resizeLimits === null) return;\n warnedGesture = true;\n const what = [needMove ? 'draggable' : '', resizeLimits !== null ? 'resizable' : ''].filter(Boolean).join(' / ');\n emit('error', { code: 'unsupported', message: `${what} needs gesture support (capabilities.gestures), which this /embed deployment does not advertise (older version)`, command: 'gestures' });\n }\n\n // \u7A97\u53E3\u53D8\u5C0F\u540E\u628A\u7528\u6237\u62D6\u8FC7 / \u7F29\u8FC7\u7684\u5934\u50CF\u5939\u56DE\u89C6\u53E3 (\u6CA1\u52A8\u8FC7\u5C31\u4E0D\u7BA1, \u4EA4\u7ED9\u9875\u9762\u81EA\u5DF1\u7684\u5E03\u5C40)\n const onWindowResize = () => {\n if (!userMoved || activeGesture || destroyed) return;\n const cur = readBox();\n const vp = viewport();\n // \u5185\u8054\u76D2\u5B50\u53EF\u4EE5\u5728\u6EDA\u52A8\u7684\u9875\u9762\u4E0B\u65B9: \u7EB5\u5411\u4E0D\u6309\u89C6\u53E3\u5939 (\u5426\u5219\u4F1A\u628A\u89C6\u53E3\u5916\u7684\u76D2\u5B50\u62FD\u8FDB\u89C6\u53E3), \u53EA\u4FDD\u8BC1\u4E0D\u8D8A\u8FC7\u6587\u6863\u9876\u90E8; \u6A2A\u5411 / \u5C3A\u5BF8\u7167\u5E38\u5939\u8FDB\u89C6\u53E3\n const fit = position === 'inline'\n ? { ...fitBox({ ...cur, top: 0 }, { width: vp.width, height: Number.MAX_SAFE_INTEGER }), top: Math.max(cur.top, -window.scrollY) }\n : fitBox(cur, vp);\n if (fit.left === cur.left && fit.top === cur.top && fit.width === cur.width && fit.height === cur.height) return;\n applyBox(fit, position === 'inline' ? { left: cur.left - inlineShift.x, top: cur.top - inlineShift.y } : null, fit.width !== cur.width || fit.height !== cur.height);\n };\n window.addEventListener('resize', onWindowResize, { passive: true });\n\n // \u2500\u2500 \u4F4D\u7F6E / \u5927\u5C0F\u8BB0\u5FC6 (persistBox) \u2500\u2500\n // \u5B58\u7684\u662F { v, mode, x, y, width, height }: \u60AC\u6D6E\u6A21\u5F0F x/y = \u89C6\u53E3 left/top; \u5185\u8054\u6A21\u5F0F x/y = \u76F8\u5BF9\"\u6D41\u5185\u539F\u70B9\"\u7684\u4F4D\u79FB (translate), \u4E0E\u6EDA\u52A8\u65E0\u5173\u3002\n const boxKey = options.persistBox === true ? 'xiaochun:box' : typeof options.persistBox === 'string' && options.persistBox ? `xiaochun:box:${options.persistBox}` : null;\n const saveBox = (): void => {\n if (!boxKey) return;\n try {\n const b = readBox();\n const at = position === 'inline' ? inlineShift : { x: b.left, y: b.top };\n 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) }));\n } catch { /* \u9690\u79C1\u6A21\u5F0F / \u914D\u989D / \u88AB\u7981\u7528: \u53EA\u662F\u4E0D\u8BB0\u5FC6 */ }\n };\n const loadBox = (): { x: number; y: number; width: number; height: number } | null => {\n if (!boxKey) return null;\n try {\n const raw = window.localStorage.getItem(boxKey);\n if (raw === null) return null;\n let o: Record<string, unknown> | null = null;\n try { o = JSON.parse(raw) as Record<string, unknown> | null; } catch { /* \u574F JSON: \u4E0B\u9762\u4E00\u5E76\u6E05\u6389 */ }\n const ok = (v: unknown, lo: number, hi: number): v is number => typeof v === 'number' && Number.isFinite(v) && v >= lo && v <= hi;\n 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)) {\n return { x: o.x, y: o.y, width: o.width, height: o.height };\n }\n window.localStorage.removeItem(boxKey); // \u574F\u6570\u636E / \u522B\u7684\u7248\u672C / \u522B\u7684\u5B9A\u4F4D\u6A21\u5F0F: \u6E05\u6389\n } catch { /* ignore */ }\n return null;\n };\n /** \u521B\u5EFA\u65F6\u6062\u590D: \u9700\u8981\u624B\u52BF\u5F00\u7740; \u663E\u5F0F width / height \u9009\u9879\u4F18\u5148\u4E8E\u5DF2\u4FDD\u5B58\u7684\u5927\u5C0F; \u5168\u90E8\u94B3\u5230\u5F53\u524D\u89C6\u53E3\u3002 */\n function restoreBox(): void {\n if (!boxKey || (!draggableOn && resizeLimits === null)) return;\n const st = loadBox();\n if (!st) return;\n const vp = viewport();\n const lim = resizeLimits ?? DEFAULT_RESIZE_LIMITS;\n const cur = readBox();\n const useW = resizeLimits !== null && options.width === undefined;\n const useH = resizeLimits !== null && options.height === undefined;\n const clampN = (v: number, lo: number, hi: number) => Math.min(Math.max(v, lo), Math.max(lo, hi));\n const width = useW ? clampN(st.width, lim.minWidth, Math.min(lim.maxWidth, vp.width)) : cur.width;\n const height = useH ? clampN(st.height, lim.minHeight, Math.min(lim.maxHeight, vp.height)) : cur.height;\n if (position === 'inline') {\n const base = { left: cur.left - inlineShift.x, top: cur.top - inlineShift.y };\n const left = clampN(base.left + st.x, 0, vp.width - width);\n const top = Math.max(base.top + st.y, -window.scrollY); // \u7EB5\u5411: \u4E0D\u8D8A\u8FC7\u6587\u6863\u9876\u90E8 (\u5185\u8054\u76D2\u5B50\u53EF\u4EE5\u5728\u6EDA\u52A8\u7684\u9875\u9762\u4E0B\u65B9, \u4E0D\u6309\u89C6\u53E3\u5939)\n applyBox({ left, top, width, height }, base, useW || useH);\n } else {\n applyBox(fitBox({ left: st.x, top: st.y, width, height }, vp), null, useW || useH);\n }\n }\n restoreBox();\n\n scheduleLazy();\n\n const api: XiaochunInstance = {\n element: wrapper,\n get iframe() { return iframe; },\n ready,\n activate,\n say: (text, opts) => send('xc.say', { text, mode: opts?.mode }, true),\n speakAudio,\n speakAudioStream,\n motion: (m) => send('xc.motion', typeof m === 'string' ? (m.startsWith('http') || m.startsWith('/') ? { url: m } : { name: m }) : m),\n expression: (name) => send('xc.expression', { name }),\n lookAt: (x, y) => send('xc.lookAt', { x, y }),\n setOutfit: (id) => {\n if (!isXcId(id)) return Promise.reject(new Error('[bad_request] invalid outfit id'));\n return send('xc.setOutfit', { id }, true, undefined, undefined, 'outfits');\n },\n setScene: (id) => {\n if (!isXcId(id)) return Promise.reject(new Error('[bad_request] invalid scene id'));\n return send('xc.setScene', { id }, true, undefined, undefined, 'scenes');\n },\n prefetch: (ids) => {\n if (ids !== undefined && (!Array.isArray(ids) || ids.some((x) => !isXcId(x)))) {\n return Promise.reject(new Error('[bad_request] prefetch ids must be an array of outfit ids'));\n }\n return send('xc.prefetch', ids ? { ids } : {}, true, undefined, undefined, 'prefetch');\n },\n getOutfits: async () => { if (!iframe) activate(); await handshaked; return caps?.outfits ? caps.outfits.slice() : []; },\n getScenes: async () => { if (!iframe) activate(); await handshaked; return caps?.scenes ? caps.scenes.slice() : []; },\n get outfit() { return currentOutfit; },\n get scene() { return currentScene; },\n setModel: (m) => {\n const msg = typeof m === 'string' ? (/^(https?:)?\\/|\\.vrm/i.test(m) ? { url: m } : { outfit: m }) : m;\n if (msg.url !== undefined && msg.outfit === undefined && !options.allowCustomModel) {\n const message = 'custom model URLs are disabled; pass allowCustomModel: true to createXiaochun() (only for URLs you trust) or use setOutfit() with a built-in id';\n emit('error', { code: 'unsupported', message, command: 'xc.setModel' });\n return Promise.reject(new Error(`[unsupported] ${message}`));\n }\n return send('xc.setModel', msg);\n },\n setConfig: (cfg) => send('xc.setConfig', cfg),\n setSize(width, height) {\n if (destroyed) return;\n ws.width = css(width, defaultWidthCss(position !== 'inline')); ws.height = css(height, defaultHeightCss(position !== 'inline'));\n if (ws.maxWidth === 'none') ws.maxWidth = '100%'; // \u7528\u6237\u62C9\u5927\u8FC7 (applyBox \u4F1A\u6E05\u6389 max-width): \u5BBF\u4E3B\u91CD\u65B0\u7ED9\u5C3A\u5BF8\u540E\u6062\u590D\u4E0D\u6EA2\u51FA\u5BB9\u5668\u7684\u7EA6\u675F\n invalidateRect();\n },\n getBox: () => readBox(),\n clearPersistedBox(opts) {\n if (boxKey) { try { window.localStorage.removeItem(boxKey); } catch { /* ignore */ } }\n if (destroyed || opts?.reset !== true) return;\n endActiveGesture();\n ws.width = css(options.width, defaultWidthCss(position !== 'inline')); ws.height = css(options.height, defaultHeightCss(position !== 'inline')); ws.maxWidth = '100%';\n if (position === 'inline') { inlineShift = { x: 0, y: 0 }; ws.removeProperty('translate'); }\n else {\n ws.left = ''; ws.top = ''; ws.right = ''; ws.bottom = '';\n if (position === 'bottom-right') { ws.right = 'var(--xc-offset-x, 16px)'; ws.bottom = 'var(--xc-offset-y, 16px)'; }\n if (position === 'bottom-left') { ws.left = 'var(--xc-offset-x, 16px)'; ws.bottom = 'var(--xc-offset-y, 16px)'; }\n }\n userMoved = false;\n invalidateRect();\n },\n setBorderRadius(radius) {\n radiusOpt = radius;\n applyRadius();\n },\n setDraggable(on) {\n draggableOn = on === true;\n syncGestures();\n },\n setResizable(on) {\n resizeLimits = normalizeResizable(on);\n syncGestures();\n },\n startListening: () => send('xc.mic', { enabled: true }),\n stopListening: () => send('xc.mic', { enabled: false }),\n mic: (enabled) => send('xc.mic', { enabled }),\n pause() { userPaused = true; syncPause(); },\n resume() { userPaused = false; syncPause(); },\n destroy() {\n if (destroyed) return;\n try { port?.postMessage(xcMessage('xc.destroy')); } catch { /* ignore */ }\n destroyed = true;\n cancelIdle();\n io?.disconnect(); pauseIo?.disconnect();\n if (handshakeTimer) clearTimeout(handshakeTimer);\n if (pointerRaf) cancelAnimationFrame(pointerRaf);\n window.removeEventListener('message', onWindowMessage);\n window.removeEventListener('resize', onWindowResize);\n lockSelection(false);\n disablePassthrough();\n resolveHandshake(); // \u8FD8\u5728\u7B49 getOutfits() / getScenes() \u7684\u8C03\u7528\u65B9\u62FF\u5230 [] \u800C\u4E0D\u662F\u6C38\u8FDC\u6302\u8D77\n try { port?.close(); } catch { /* ignore */ }\n port = null;\n for (const p of pending.values()) p.reject(new Error('[project-xiaochun] instance destroyed'));\n pending.clear();\n queue.length = 0;\n if (!loaded) rejectReady(new Error('[project-xiaochun] destroyed before ready'));\n wrapper.remove(); // \u540C\u65F6\u79FB\u9664 iframe \u2192 \u6D4F\u89C8\u5668\u91CA\u653E WebGL \u4E0A\u4E0B\u6587\n iframe = null;\n emit('destroy', undefined);\n listeners.clear();\n },\n on(event, cb) {\n let set = listeners.get(event);\n if (!set) { set = new Set(); listeners.set(event, set); }\n set.add(cb as (p: any) => void);\n return () => { set!.delete(cb as (p: any) => void); };\n },\n };\n return api;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|