@kibee/renderer-three 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +87 -1
- package/dist/index.d.ts +87 -1
- package/dist/index.js +186 -4
- package/dist/index.mjs +183 -3
- package/dist/styles.css +24 -0
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -36,6 +36,8 @@ interface DockMotionOptions {
|
|
|
36
36
|
}
|
|
37
37
|
interface ThreeBeeRendererOptions {
|
|
38
38
|
assetUrl?: string;
|
|
39
|
+
/** When set, loads GLB from memory (e.g. authenticated API proxy). Takes precedence over assetUrl. */
|
|
40
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
39
41
|
avatarPreset?: BeeAvatarPreset;
|
|
40
42
|
assetVariant?: BeeAssetVariant;
|
|
41
43
|
qualityTier?: BeeQualityTier;
|
|
@@ -279,4 +281,88 @@ declare class ThreeBeeRenderer implements BeeRenderer {
|
|
|
279
281
|
|
|
280
282
|
declare function applyLegacyBeeMaterialCompat(gltf: GLTF): Promise<void>;
|
|
281
283
|
|
|
282
|
-
|
|
284
|
+
type Motion = "breathe" | "pulse" | "spin" | "none";
|
|
285
|
+
interface DomAvatarRendererOptions {
|
|
286
|
+
mode: "vector" | "lottie";
|
|
287
|
+
svg?: string;
|
|
288
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
289
|
+
motion: Motion;
|
|
290
|
+
color?: string;
|
|
291
|
+
dockSize?: number;
|
|
292
|
+
dockPosition?: {
|
|
293
|
+
right?: string;
|
|
294
|
+
bottom?: string;
|
|
295
|
+
left?: string;
|
|
296
|
+
top?: string;
|
|
297
|
+
};
|
|
298
|
+
dockClickBehavior?: BeeDockClickBehavior;
|
|
299
|
+
}
|
|
300
|
+
declare class DomAvatarRenderer implements BeeRenderer {
|
|
301
|
+
private opts;
|
|
302
|
+
private root;
|
|
303
|
+
private avatar;
|
|
304
|
+
private tooltip;
|
|
305
|
+
private docked;
|
|
306
|
+
private clickBehavior;
|
|
307
|
+
private lottieAnim;
|
|
308
|
+
constructor(opts: DomAvatarRendererOptions);
|
|
309
|
+
mount(container?: HTMLElement): Promise<void>;
|
|
310
|
+
private loadLottie;
|
|
311
|
+
setState(state: BeeVisualState): void;
|
|
312
|
+
moveTo(x: number, y: number, options?: MoveToOptions): Promise<void>;
|
|
313
|
+
dock(_options?: DockMotionOptions): Promise<void>;
|
|
314
|
+
undock(_options?: DockMotionOptions): Promise<void>;
|
|
315
|
+
isDocked(): boolean;
|
|
316
|
+
speak(message: string, _options?: SpeakOptions): void;
|
|
317
|
+
prompt(_message: string, _options?: PromptOptions): Promise<string | null>;
|
|
318
|
+
hideMessage(): void;
|
|
319
|
+
showActions(_handler: BeeActionHandler): void;
|
|
320
|
+
hideActions(): void;
|
|
321
|
+
resize(): void;
|
|
322
|
+
setDockClickBehavior(mode: BeeDockClickBehavior): void;
|
|
323
|
+
getDockScreenPosition(): {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
};
|
|
327
|
+
getBeePosition(): {
|
|
328
|
+
x: number;
|
|
329
|
+
y: number;
|
|
330
|
+
docked: boolean;
|
|
331
|
+
};
|
|
332
|
+
destroy(): void;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
type AvatarMotion = "breathe" | "pulse" | "spin" | "none";
|
|
336
|
+
/** Mirror of the contracts WidgetAvatarConfig union (kept local to avoid a hard dep). */
|
|
337
|
+
type RendererAvatarConfig = {
|
|
338
|
+
mode: "default";
|
|
339
|
+
} | {
|
|
340
|
+
mode: "preset";
|
|
341
|
+
preset: "orb" | "ring";
|
|
342
|
+
} | {
|
|
343
|
+
mode: "custom";
|
|
344
|
+
assetUrl: string;
|
|
345
|
+
} | {
|
|
346
|
+
mode: "vector";
|
|
347
|
+
svg: string;
|
|
348
|
+
motion: AvatarMotion;
|
|
349
|
+
color?: string;
|
|
350
|
+
} | {
|
|
351
|
+
mode: "lottie";
|
|
352
|
+
assetUrl: string;
|
|
353
|
+
motion: AvatarMotion;
|
|
354
|
+
};
|
|
355
|
+
interface CreateRendererOptions {
|
|
356
|
+
three?: Partial<ThreeBeeRendererOptions>;
|
|
357
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
358
|
+
dockSize?: number;
|
|
359
|
+
dockPosition?: {
|
|
360
|
+
right?: string;
|
|
361
|
+
bottom?: string;
|
|
362
|
+
left?: string;
|
|
363
|
+
top?: string;
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
declare function createRenderer(avatar: RendererAvatarConfig, opts: CreateRendererOptions): BeeRenderer;
|
|
367
|
+
|
|
368
|
+
export { type BeeActionChoice, type BeeActionHandler, type BeeAssetVariant, type BeeAvatarPreset, type BeeDockClickBehavior, type BeeDockPosition, type BeeDockVariant, type BeeMotionMode, type BeeQualityTier, type BeeRenderer, type BeeVisualState, type CreateRendererOptions, type DockMotionOptions, DomAvatarRenderer, type DomAvatarRendererOptions, type MoveToOptions, type PromptOptions, type RendererAvatarConfig, type SetCustomDockPositionOptions, type SpeakOptions, ThreeBeeRenderer, type ThreeBeeRendererOptions, type TooltipArrowEdge, applyLegacyBeeMaterialCompat, createRenderer };
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,8 @@ interface DockMotionOptions {
|
|
|
36
36
|
}
|
|
37
37
|
interface ThreeBeeRendererOptions {
|
|
38
38
|
assetUrl?: string;
|
|
39
|
+
/** When set, loads GLB from memory (e.g. authenticated API proxy). Takes precedence over assetUrl. */
|
|
40
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
39
41
|
avatarPreset?: BeeAvatarPreset;
|
|
40
42
|
assetVariant?: BeeAssetVariant;
|
|
41
43
|
qualityTier?: BeeQualityTier;
|
|
@@ -279,4 +281,88 @@ declare class ThreeBeeRenderer implements BeeRenderer {
|
|
|
279
281
|
|
|
280
282
|
declare function applyLegacyBeeMaterialCompat(gltf: GLTF): Promise<void>;
|
|
281
283
|
|
|
282
|
-
|
|
284
|
+
type Motion = "breathe" | "pulse" | "spin" | "none";
|
|
285
|
+
interface DomAvatarRendererOptions {
|
|
286
|
+
mode: "vector" | "lottie";
|
|
287
|
+
svg?: string;
|
|
288
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
289
|
+
motion: Motion;
|
|
290
|
+
color?: string;
|
|
291
|
+
dockSize?: number;
|
|
292
|
+
dockPosition?: {
|
|
293
|
+
right?: string;
|
|
294
|
+
bottom?: string;
|
|
295
|
+
left?: string;
|
|
296
|
+
top?: string;
|
|
297
|
+
};
|
|
298
|
+
dockClickBehavior?: BeeDockClickBehavior;
|
|
299
|
+
}
|
|
300
|
+
declare class DomAvatarRenderer implements BeeRenderer {
|
|
301
|
+
private opts;
|
|
302
|
+
private root;
|
|
303
|
+
private avatar;
|
|
304
|
+
private tooltip;
|
|
305
|
+
private docked;
|
|
306
|
+
private clickBehavior;
|
|
307
|
+
private lottieAnim;
|
|
308
|
+
constructor(opts: DomAvatarRendererOptions);
|
|
309
|
+
mount(container?: HTMLElement): Promise<void>;
|
|
310
|
+
private loadLottie;
|
|
311
|
+
setState(state: BeeVisualState): void;
|
|
312
|
+
moveTo(x: number, y: number, options?: MoveToOptions): Promise<void>;
|
|
313
|
+
dock(_options?: DockMotionOptions): Promise<void>;
|
|
314
|
+
undock(_options?: DockMotionOptions): Promise<void>;
|
|
315
|
+
isDocked(): boolean;
|
|
316
|
+
speak(message: string, _options?: SpeakOptions): void;
|
|
317
|
+
prompt(_message: string, _options?: PromptOptions): Promise<string | null>;
|
|
318
|
+
hideMessage(): void;
|
|
319
|
+
showActions(_handler: BeeActionHandler): void;
|
|
320
|
+
hideActions(): void;
|
|
321
|
+
resize(): void;
|
|
322
|
+
setDockClickBehavior(mode: BeeDockClickBehavior): void;
|
|
323
|
+
getDockScreenPosition(): {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
};
|
|
327
|
+
getBeePosition(): {
|
|
328
|
+
x: number;
|
|
329
|
+
y: number;
|
|
330
|
+
docked: boolean;
|
|
331
|
+
};
|
|
332
|
+
destroy(): void;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
type AvatarMotion = "breathe" | "pulse" | "spin" | "none";
|
|
336
|
+
/** Mirror of the contracts WidgetAvatarConfig union (kept local to avoid a hard dep). */
|
|
337
|
+
type RendererAvatarConfig = {
|
|
338
|
+
mode: "default";
|
|
339
|
+
} | {
|
|
340
|
+
mode: "preset";
|
|
341
|
+
preset: "orb" | "ring";
|
|
342
|
+
} | {
|
|
343
|
+
mode: "custom";
|
|
344
|
+
assetUrl: string;
|
|
345
|
+
} | {
|
|
346
|
+
mode: "vector";
|
|
347
|
+
svg: string;
|
|
348
|
+
motion: AvatarMotion;
|
|
349
|
+
color?: string;
|
|
350
|
+
} | {
|
|
351
|
+
mode: "lottie";
|
|
352
|
+
assetUrl: string;
|
|
353
|
+
motion: AvatarMotion;
|
|
354
|
+
};
|
|
355
|
+
interface CreateRendererOptions {
|
|
356
|
+
three?: Partial<ThreeBeeRendererOptions>;
|
|
357
|
+
assetLoadFn?: () => Promise<ArrayBuffer>;
|
|
358
|
+
dockSize?: number;
|
|
359
|
+
dockPosition?: {
|
|
360
|
+
right?: string;
|
|
361
|
+
bottom?: string;
|
|
362
|
+
left?: string;
|
|
363
|
+
top?: string;
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
declare function createRenderer(avatar: RendererAvatarConfig, opts: CreateRendererOptions): BeeRenderer;
|
|
367
|
+
|
|
368
|
+
export { type BeeActionChoice, type BeeActionHandler, type BeeAssetVariant, type BeeAvatarPreset, type BeeDockClickBehavior, type BeeDockPosition, type BeeDockVariant, type BeeMotionMode, type BeeQualityTier, type BeeRenderer, type BeeVisualState, type CreateRendererOptions, type DockMotionOptions, DomAvatarRenderer, type DomAvatarRendererOptions, type MoveToOptions, type PromptOptions, type RendererAvatarConfig, type SetCustomDockPositionOptions, type SpeakOptions, ThreeBeeRenderer, type ThreeBeeRendererOptions, type TooltipArrowEdge, applyLegacyBeeMaterialCompat, createRenderer };
|
package/dist/index.js
CHANGED
|
@@ -30,8 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DomAvatarRenderer: () => DomAvatarRenderer,
|
|
33
34
|
ThreeBeeRenderer: () => ThreeBeeRenderer,
|
|
34
|
-
applyLegacyBeeMaterialCompat: () => applyLegacyBeeMaterialCompat
|
|
35
|
+
applyLegacyBeeMaterialCompat: () => applyLegacyBeeMaterialCompat,
|
|
36
|
+
createRenderer: () => createRenderer
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(index_exports);
|
|
37
39
|
|
|
@@ -967,7 +969,7 @@ var ThreeBeeRenderer = class {
|
|
|
967
969
|
try {
|
|
968
970
|
const loader = new import_GLTFLoader.GLTFLoader();
|
|
969
971
|
registerPbrSpecularGlossinessGLTFPlugin(loader);
|
|
970
|
-
const gltf = await loader.loadAsync(
|
|
972
|
+
const gltf = this.options.assetLoadFn ? await loader.parseAsync(await this.options.assetLoadFn(), "") : await loader.loadAsync(
|
|
971
973
|
this.options.assetUrl ?? "/models/bee-runtime.glb"
|
|
972
974
|
);
|
|
973
975
|
if (this.disposed) {
|
|
@@ -1024,7 +1026,7 @@ var ThreeBeeRenderer = class {
|
|
|
1024
1026
|
this.updateBeeScreenPosition();
|
|
1025
1027
|
return true;
|
|
1026
1028
|
} catch {
|
|
1027
|
-
if (this.options.assetUrl) {
|
|
1029
|
+
if (this.options.assetLoadFn || this.options.assetUrl) {
|
|
1028
1030
|
this.createPresetAvatar("orb");
|
|
1029
1031
|
return true;
|
|
1030
1032
|
}
|
|
@@ -1971,8 +1973,188 @@ var ThreeBeeRenderer = class {
|
|
|
1971
1973
|
});
|
|
1972
1974
|
}
|
|
1973
1975
|
};
|
|
1976
|
+
|
|
1977
|
+
// src/dom/DomAvatarRenderer.ts
|
|
1978
|
+
var STATE_CLASSES = ["kibee-2d-state--guiding", "kibee-2d-state--thinking", "kibee-2d-state--celebrating"];
|
|
1979
|
+
var MOTION_CLASSES = ["kibee-2d-motion--breathe", "kibee-2d-motion--pulse", "kibee-2d-motion--spin"];
|
|
1980
|
+
var DomAvatarRenderer = class {
|
|
1981
|
+
opts;
|
|
1982
|
+
root = null;
|
|
1983
|
+
avatar = null;
|
|
1984
|
+
tooltip = null;
|
|
1985
|
+
docked = true;
|
|
1986
|
+
clickBehavior;
|
|
1987
|
+
lottieAnim = null;
|
|
1988
|
+
constructor(opts) {
|
|
1989
|
+
this.opts = opts;
|
|
1990
|
+
this.clickBehavior = opts.dockClickBehavior ?? "undock";
|
|
1991
|
+
}
|
|
1992
|
+
async mount(container) {
|
|
1993
|
+
document.querySelectorAll(".kibee-root").forEach((el) => el.remove());
|
|
1994
|
+
const root = document.createElement("div");
|
|
1995
|
+
root.className = "kibee-root kibee-root--dom";
|
|
1996
|
+
const size = this.opts.dockSize ?? 60;
|
|
1997
|
+
root.style.setProperty("--kibee-dock-size", `${size}px`);
|
|
1998
|
+
const pos = this.opts.dockPosition ?? { right: "24px", bottom: "24px" };
|
|
1999
|
+
root.style.setProperty("--kibee-dock-right", pos.right ?? "auto");
|
|
2000
|
+
root.style.setProperty("--kibee-dock-bottom", pos.bottom ?? "auto");
|
|
2001
|
+
root.style.setProperty("--kibee-dock-left", pos.left ?? "auto");
|
|
2002
|
+
root.style.setProperty("--kibee-dock-top", pos.top ?? "auto");
|
|
2003
|
+
if (this.opts.color) root.style.setProperty("--kibee-2d-color", this.opts.color);
|
|
2004
|
+
const avatar = document.createElement("div");
|
|
2005
|
+
avatar.className = "kibee-2d-avatar";
|
|
2006
|
+
if (this.opts.mode === "vector") avatar.innerHTML = this.opts.svg ?? "";
|
|
2007
|
+
const tooltip = document.createElement("div");
|
|
2008
|
+
tooltip.className = "kibee-tooltip kibee-tooltip--hidden";
|
|
2009
|
+
avatar.addEventListener("click", () => {
|
|
2010
|
+
if (this.clickBehavior === "assist-panel") {
|
|
2011
|
+
window.dispatchEvent(new CustomEvent("kibee-assist-toggle"));
|
|
2012
|
+
} else {
|
|
2013
|
+
void this.undock();
|
|
2014
|
+
}
|
|
2015
|
+
});
|
|
2016
|
+
root.appendChild(avatar);
|
|
2017
|
+
root.appendChild(tooltip);
|
|
2018
|
+
(container ?? document.body).appendChild(root);
|
|
2019
|
+
this.root = root;
|
|
2020
|
+
this.avatar = avatar;
|
|
2021
|
+
this.tooltip = tooltip;
|
|
2022
|
+
if (this.opts.mode === "lottie" && this.opts.assetLoadFn) await this.loadLottie(avatar);
|
|
2023
|
+
this.setState("idle");
|
|
2024
|
+
}
|
|
2025
|
+
async loadLottie(host) {
|
|
2026
|
+
try {
|
|
2027
|
+
const [{ default: lottie }, buffer] = await Promise.all([
|
|
2028
|
+
import("lottie-web"),
|
|
2029
|
+
this.opts.assetLoadFn()
|
|
2030
|
+
]);
|
|
2031
|
+
const json = JSON.parse(new TextDecoder().decode(buffer));
|
|
2032
|
+
this.lottieAnim = lottie.loadAnimation({
|
|
2033
|
+
container: host,
|
|
2034
|
+
renderer: "svg",
|
|
2035
|
+
loop: true,
|
|
2036
|
+
autoplay: true,
|
|
2037
|
+
animationData: json
|
|
2038
|
+
});
|
|
2039
|
+
} catch {
|
|
2040
|
+
host.innerHTML = "<div class='kibee-2d-fallback'></div>";
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
setState(state) {
|
|
2044
|
+
if (!this.avatar) return;
|
|
2045
|
+
this.avatar.classList.remove(...STATE_CLASSES);
|
|
2046
|
+
if (this.opts.mode === "vector") {
|
|
2047
|
+
this.avatar.classList.remove(...MOTION_CLASSES);
|
|
2048
|
+
if (state === "idle") {
|
|
2049
|
+
if (this.opts.motion !== "none") this.avatar.classList.add(`kibee-2d-motion--${this.opts.motion}`);
|
|
2050
|
+
} else {
|
|
2051
|
+
this.avatar.classList.add(`kibee-2d-state--${state}`);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
moveTo(x, y, options) {
|
|
2056
|
+
if (!this.root) return Promise.resolve();
|
|
2057
|
+
const dur = options?.duration ?? 550;
|
|
2058
|
+
this.docked = false;
|
|
2059
|
+
this.root.style.transition = `transform ${dur}ms cubic-bezier(.22,.61,.36,1)`;
|
|
2060
|
+
this.root.style.transform = `translate(${x + (options?.offsetX ?? 0)}px, ${y + (options?.offsetY ?? 0)}px)`;
|
|
2061
|
+
if (dur === 0) return Promise.resolve();
|
|
2062
|
+
return new Promise((resolve) => {
|
|
2063
|
+
const done = () => {
|
|
2064
|
+
this.root?.removeEventListener("transitionend", done);
|
|
2065
|
+
resolve();
|
|
2066
|
+
};
|
|
2067
|
+
this.root.addEventListener("transitionend", done);
|
|
2068
|
+
setTimeout(done, dur + 80);
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2071
|
+
dock(_options) {
|
|
2072
|
+
if (this.root) this.root.style.transform = "";
|
|
2073
|
+
this.docked = true;
|
|
2074
|
+
return Promise.resolve();
|
|
2075
|
+
}
|
|
2076
|
+
undock(_options) {
|
|
2077
|
+
this.docked = false;
|
|
2078
|
+
return Promise.resolve();
|
|
2079
|
+
}
|
|
2080
|
+
isDocked() {
|
|
2081
|
+
return this.docked;
|
|
2082
|
+
}
|
|
2083
|
+
speak(message, _options) {
|
|
2084
|
+
if (!this.tooltip) return;
|
|
2085
|
+
this.tooltip.textContent = message;
|
|
2086
|
+
this.tooltip.classList.remove("kibee-tooltip--hidden");
|
|
2087
|
+
this.tooltip.classList.add("kibee-tooltip--visible");
|
|
2088
|
+
}
|
|
2089
|
+
prompt(_message, _options) {
|
|
2090
|
+
return Promise.resolve(null);
|
|
2091
|
+
}
|
|
2092
|
+
hideMessage() {
|
|
2093
|
+
if (!this.tooltip) return;
|
|
2094
|
+
this.tooltip.classList.remove("kibee-tooltip--visible");
|
|
2095
|
+
this.tooltip.classList.add("kibee-tooltip--hidden");
|
|
2096
|
+
}
|
|
2097
|
+
showActions(_handler) {
|
|
2098
|
+
}
|
|
2099
|
+
hideActions() {
|
|
2100
|
+
}
|
|
2101
|
+
resize() {
|
|
2102
|
+
}
|
|
2103
|
+
setDockClickBehavior(mode) {
|
|
2104
|
+
this.clickBehavior = mode;
|
|
2105
|
+
}
|
|
2106
|
+
getDockScreenPosition() {
|
|
2107
|
+
if (!this.root) return { x: 0, y: 0 };
|
|
2108
|
+
const r = this.root.getBoundingClientRect();
|
|
2109
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
|
|
2110
|
+
}
|
|
2111
|
+
getBeePosition() {
|
|
2112
|
+
const p = this.getDockScreenPosition();
|
|
2113
|
+
return { x: p.x, y: p.y, docked: this.docked };
|
|
2114
|
+
}
|
|
2115
|
+
destroy() {
|
|
2116
|
+
this.lottieAnim?.destroy();
|
|
2117
|
+
this.lottieAnim = null;
|
|
2118
|
+
this.root?.remove();
|
|
2119
|
+
this.root = null;
|
|
2120
|
+
this.avatar = null;
|
|
2121
|
+
this.tooltip = null;
|
|
2122
|
+
}
|
|
2123
|
+
};
|
|
2124
|
+
|
|
2125
|
+
// src/createRenderer.ts
|
|
2126
|
+
function createRenderer(avatar, opts) {
|
|
2127
|
+
if (avatar.mode === "vector") {
|
|
2128
|
+
return new DomAvatarRenderer({
|
|
2129
|
+
mode: "vector",
|
|
2130
|
+
svg: avatar.svg,
|
|
2131
|
+
motion: avatar.motion,
|
|
2132
|
+
color: avatar.color,
|
|
2133
|
+
dockSize: opts.dockSize,
|
|
2134
|
+
dockPosition: opts.dockPosition
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
if (avatar.mode === "lottie") {
|
|
2138
|
+
return new DomAvatarRenderer({
|
|
2139
|
+
mode: "lottie",
|
|
2140
|
+
assetLoadFn: opts.assetLoadFn,
|
|
2141
|
+
motion: avatar.motion,
|
|
2142
|
+
dockSize: opts.dockSize,
|
|
2143
|
+
dockPosition: opts.dockPosition
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
const three = { ...opts.three ?? {} };
|
|
2147
|
+
if (avatar.mode === "preset") three.avatarPreset = avatar.preset;
|
|
2148
|
+
else if (avatar.mode === "custom") {
|
|
2149
|
+
if (opts.assetLoadFn) three.assetLoadFn = opts.assetLoadFn;
|
|
2150
|
+
else three.assetUrl = avatar.assetUrl;
|
|
2151
|
+
}
|
|
2152
|
+
return new ThreeBeeRenderer(three);
|
|
2153
|
+
}
|
|
1974
2154
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1975
2155
|
0 && (module.exports = {
|
|
2156
|
+
DomAvatarRenderer,
|
|
1976
2157
|
ThreeBeeRenderer,
|
|
1977
|
-
applyLegacyBeeMaterialCompat
|
|
2158
|
+
applyLegacyBeeMaterialCompat,
|
|
2159
|
+
createRenderer
|
|
1978
2160
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -930,7 +930,7 @@ var ThreeBeeRenderer = class {
|
|
|
930
930
|
try {
|
|
931
931
|
const loader = new GLTFLoader();
|
|
932
932
|
registerPbrSpecularGlossinessGLTFPlugin(loader);
|
|
933
|
-
const gltf = await loader.loadAsync(
|
|
933
|
+
const gltf = this.options.assetLoadFn ? await loader.parseAsync(await this.options.assetLoadFn(), "") : await loader.loadAsync(
|
|
934
934
|
this.options.assetUrl ?? "/models/bee-runtime.glb"
|
|
935
935
|
);
|
|
936
936
|
if (this.disposed) {
|
|
@@ -987,7 +987,7 @@ var ThreeBeeRenderer = class {
|
|
|
987
987
|
this.updateBeeScreenPosition();
|
|
988
988
|
return true;
|
|
989
989
|
} catch {
|
|
990
|
-
if (this.options.assetUrl) {
|
|
990
|
+
if (this.options.assetLoadFn || this.options.assetUrl) {
|
|
991
991
|
this.createPresetAvatar("orb");
|
|
992
992
|
return true;
|
|
993
993
|
}
|
|
@@ -1934,7 +1934,187 @@ var ThreeBeeRenderer = class {
|
|
|
1934
1934
|
});
|
|
1935
1935
|
}
|
|
1936
1936
|
};
|
|
1937
|
+
|
|
1938
|
+
// src/dom/DomAvatarRenderer.ts
|
|
1939
|
+
var STATE_CLASSES = ["kibee-2d-state--guiding", "kibee-2d-state--thinking", "kibee-2d-state--celebrating"];
|
|
1940
|
+
var MOTION_CLASSES = ["kibee-2d-motion--breathe", "kibee-2d-motion--pulse", "kibee-2d-motion--spin"];
|
|
1941
|
+
var DomAvatarRenderer = class {
|
|
1942
|
+
opts;
|
|
1943
|
+
root = null;
|
|
1944
|
+
avatar = null;
|
|
1945
|
+
tooltip = null;
|
|
1946
|
+
docked = true;
|
|
1947
|
+
clickBehavior;
|
|
1948
|
+
lottieAnim = null;
|
|
1949
|
+
constructor(opts) {
|
|
1950
|
+
this.opts = opts;
|
|
1951
|
+
this.clickBehavior = opts.dockClickBehavior ?? "undock";
|
|
1952
|
+
}
|
|
1953
|
+
async mount(container) {
|
|
1954
|
+
document.querySelectorAll(".kibee-root").forEach((el) => el.remove());
|
|
1955
|
+
const root = document.createElement("div");
|
|
1956
|
+
root.className = "kibee-root kibee-root--dom";
|
|
1957
|
+
const size = this.opts.dockSize ?? 60;
|
|
1958
|
+
root.style.setProperty("--kibee-dock-size", `${size}px`);
|
|
1959
|
+
const pos = this.opts.dockPosition ?? { right: "24px", bottom: "24px" };
|
|
1960
|
+
root.style.setProperty("--kibee-dock-right", pos.right ?? "auto");
|
|
1961
|
+
root.style.setProperty("--kibee-dock-bottom", pos.bottom ?? "auto");
|
|
1962
|
+
root.style.setProperty("--kibee-dock-left", pos.left ?? "auto");
|
|
1963
|
+
root.style.setProperty("--kibee-dock-top", pos.top ?? "auto");
|
|
1964
|
+
if (this.opts.color) root.style.setProperty("--kibee-2d-color", this.opts.color);
|
|
1965
|
+
const avatar = document.createElement("div");
|
|
1966
|
+
avatar.className = "kibee-2d-avatar";
|
|
1967
|
+
if (this.opts.mode === "vector") avatar.innerHTML = this.opts.svg ?? "";
|
|
1968
|
+
const tooltip = document.createElement("div");
|
|
1969
|
+
tooltip.className = "kibee-tooltip kibee-tooltip--hidden";
|
|
1970
|
+
avatar.addEventListener("click", () => {
|
|
1971
|
+
if (this.clickBehavior === "assist-panel") {
|
|
1972
|
+
window.dispatchEvent(new CustomEvent("kibee-assist-toggle"));
|
|
1973
|
+
} else {
|
|
1974
|
+
void this.undock();
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1977
|
+
root.appendChild(avatar);
|
|
1978
|
+
root.appendChild(tooltip);
|
|
1979
|
+
(container ?? document.body).appendChild(root);
|
|
1980
|
+
this.root = root;
|
|
1981
|
+
this.avatar = avatar;
|
|
1982
|
+
this.tooltip = tooltip;
|
|
1983
|
+
if (this.opts.mode === "lottie" && this.opts.assetLoadFn) await this.loadLottie(avatar);
|
|
1984
|
+
this.setState("idle");
|
|
1985
|
+
}
|
|
1986
|
+
async loadLottie(host) {
|
|
1987
|
+
try {
|
|
1988
|
+
const [{ default: lottie }, buffer] = await Promise.all([
|
|
1989
|
+
import("lottie-web"),
|
|
1990
|
+
this.opts.assetLoadFn()
|
|
1991
|
+
]);
|
|
1992
|
+
const json = JSON.parse(new TextDecoder().decode(buffer));
|
|
1993
|
+
this.lottieAnim = lottie.loadAnimation({
|
|
1994
|
+
container: host,
|
|
1995
|
+
renderer: "svg",
|
|
1996
|
+
loop: true,
|
|
1997
|
+
autoplay: true,
|
|
1998
|
+
animationData: json
|
|
1999
|
+
});
|
|
2000
|
+
} catch {
|
|
2001
|
+
host.innerHTML = "<div class='kibee-2d-fallback'></div>";
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
setState(state) {
|
|
2005
|
+
if (!this.avatar) return;
|
|
2006
|
+
this.avatar.classList.remove(...STATE_CLASSES);
|
|
2007
|
+
if (this.opts.mode === "vector") {
|
|
2008
|
+
this.avatar.classList.remove(...MOTION_CLASSES);
|
|
2009
|
+
if (state === "idle") {
|
|
2010
|
+
if (this.opts.motion !== "none") this.avatar.classList.add(`kibee-2d-motion--${this.opts.motion}`);
|
|
2011
|
+
} else {
|
|
2012
|
+
this.avatar.classList.add(`kibee-2d-state--${state}`);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
moveTo(x, y, options) {
|
|
2017
|
+
if (!this.root) return Promise.resolve();
|
|
2018
|
+
const dur = options?.duration ?? 550;
|
|
2019
|
+
this.docked = false;
|
|
2020
|
+
this.root.style.transition = `transform ${dur}ms cubic-bezier(.22,.61,.36,1)`;
|
|
2021
|
+
this.root.style.transform = `translate(${x + (options?.offsetX ?? 0)}px, ${y + (options?.offsetY ?? 0)}px)`;
|
|
2022
|
+
if (dur === 0) return Promise.resolve();
|
|
2023
|
+
return new Promise((resolve) => {
|
|
2024
|
+
const done = () => {
|
|
2025
|
+
this.root?.removeEventListener("transitionend", done);
|
|
2026
|
+
resolve();
|
|
2027
|
+
};
|
|
2028
|
+
this.root.addEventListener("transitionend", done);
|
|
2029
|
+
setTimeout(done, dur + 80);
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
dock(_options) {
|
|
2033
|
+
if (this.root) this.root.style.transform = "";
|
|
2034
|
+
this.docked = true;
|
|
2035
|
+
return Promise.resolve();
|
|
2036
|
+
}
|
|
2037
|
+
undock(_options) {
|
|
2038
|
+
this.docked = false;
|
|
2039
|
+
return Promise.resolve();
|
|
2040
|
+
}
|
|
2041
|
+
isDocked() {
|
|
2042
|
+
return this.docked;
|
|
2043
|
+
}
|
|
2044
|
+
speak(message, _options) {
|
|
2045
|
+
if (!this.tooltip) return;
|
|
2046
|
+
this.tooltip.textContent = message;
|
|
2047
|
+
this.tooltip.classList.remove("kibee-tooltip--hidden");
|
|
2048
|
+
this.tooltip.classList.add("kibee-tooltip--visible");
|
|
2049
|
+
}
|
|
2050
|
+
prompt(_message, _options) {
|
|
2051
|
+
return Promise.resolve(null);
|
|
2052
|
+
}
|
|
2053
|
+
hideMessage() {
|
|
2054
|
+
if (!this.tooltip) return;
|
|
2055
|
+
this.tooltip.classList.remove("kibee-tooltip--visible");
|
|
2056
|
+
this.tooltip.classList.add("kibee-tooltip--hidden");
|
|
2057
|
+
}
|
|
2058
|
+
showActions(_handler) {
|
|
2059
|
+
}
|
|
2060
|
+
hideActions() {
|
|
2061
|
+
}
|
|
2062
|
+
resize() {
|
|
2063
|
+
}
|
|
2064
|
+
setDockClickBehavior(mode) {
|
|
2065
|
+
this.clickBehavior = mode;
|
|
2066
|
+
}
|
|
2067
|
+
getDockScreenPosition() {
|
|
2068
|
+
if (!this.root) return { x: 0, y: 0 };
|
|
2069
|
+
const r = this.root.getBoundingClientRect();
|
|
2070
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
|
|
2071
|
+
}
|
|
2072
|
+
getBeePosition() {
|
|
2073
|
+
const p = this.getDockScreenPosition();
|
|
2074
|
+
return { x: p.x, y: p.y, docked: this.docked };
|
|
2075
|
+
}
|
|
2076
|
+
destroy() {
|
|
2077
|
+
this.lottieAnim?.destroy();
|
|
2078
|
+
this.lottieAnim = null;
|
|
2079
|
+
this.root?.remove();
|
|
2080
|
+
this.root = null;
|
|
2081
|
+
this.avatar = null;
|
|
2082
|
+
this.tooltip = null;
|
|
2083
|
+
}
|
|
2084
|
+
};
|
|
2085
|
+
|
|
2086
|
+
// src/createRenderer.ts
|
|
2087
|
+
function createRenderer(avatar, opts) {
|
|
2088
|
+
if (avatar.mode === "vector") {
|
|
2089
|
+
return new DomAvatarRenderer({
|
|
2090
|
+
mode: "vector",
|
|
2091
|
+
svg: avatar.svg,
|
|
2092
|
+
motion: avatar.motion,
|
|
2093
|
+
color: avatar.color,
|
|
2094
|
+
dockSize: opts.dockSize,
|
|
2095
|
+
dockPosition: opts.dockPosition
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
if (avatar.mode === "lottie") {
|
|
2099
|
+
return new DomAvatarRenderer({
|
|
2100
|
+
mode: "lottie",
|
|
2101
|
+
assetLoadFn: opts.assetLoadFn,
|
|
2102
|
+
motion: avatar.motion,
|
|
2103
|
+
dockSize: opts.dockSize,
|
|
2104
|
+
dockPosition: opts.dockPosition
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
const three = { ...opts.three ?? {} };
|
|
2108
|
+
if (avatar.mode === "preset") three.avatarPreset = avatar.preset;
|
|
2109
|
+
else if (avatar.mode === "custom") {
|
|
2110
|
+
if (opts.assetLoadFn) three.assetLoadFn = opts.assetLoadFn;
|
|
2111
|
+
else three.assetUrl = avatar.assetUrl;
|
|
2112
|
+
}
|
|
2113
|
+
return new ThreeBeeRenderer(three);
|
|
2114
|
+
}
|
|
1937
2115
|
export {
|
|
2116
|
+
DomAvatarRenderer,
|
|
1938
2117
|
ThreeBeeRenderer,
|
|
1939
|
-
applyLegacyBeeMaterialCompat
|
|
2118
|
+
applyLegacyBeeMaterialCompat,
|
|
2119
|
+
createRenderer
|
|
1940
2120
|
};
|
package/dist/styles.css
CHANGED
|
@@ -737,3 +737,27 @@ body[data-kibee-empty-dock="true"] .kibee-root[data-docked="true"] .kibee-canvas
|
|
|
737
737
|
0 0 24px rgba(255, 208, 0, 0.18);
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
|
+
.kibee-root--dom .kibee-2d-avatar {
|
|
741
|
+
width: var(--kibee-dock-size, 60px);
|
|
742
|
+
height: var(--kibee-dock-size, 60px);
|
|
743
|
+
display: flex; align-items: center; justify-content: center;
|
|
744
|
+
color: var(--kibee-2d-color, currentColor); cursor: pointer;
|
|
745
|
+
}
|
|
746
|
+
.kibee-root--dom .kibee-2d-avatar svg { width: 100%; height: 100%; display: block; }
|
|
747
|
+
|
|
748
|
+
@media (prefers-reduced-motion: reduce) {
|
|
749
|
+
.kibee-2d-avatar, .kibee-2d-avatar * { animation: none !important; }
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.kibee-2d-motion--breathe { animation: kibee2dBreathe 3.2s ease-in-out infinite; }
|
|
753
|
+
.kibee-2d-motion--pulse { animation: kibee2dPulse 1.8s ease-in-out infinite; }
|
|
754
|
+
.kibee-2d-motion--spin { animation: kibee2dSpin 6s linear infinite; }
|
|
755
|
+
.kibee-2d-state--guiding { animation: kibee2dGuide 0.6s ease-in-out; }
|
|
756
|
+
.kibee-2d-state--thinking { animation: kibee2dPulse 0.9s ease-in-out infinite; }
|
|
757
|
+
.kibee-2d-state--celebrating { animation: kibee2dBounce 0.7s ease-out; }
|
|
758
|
+
|
|
759
|
+
@keyframes kibee2dBreathe { 0%,100%{transform:scale(1)} 50%{transform:scale(1.06)} }
|
|
760
|
+
@keyframes kibee2dPulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.78;transform:scale(1.04)} }
|
|
761
|
+
@keyframes kibee2dSpin { to { transform: rotate(360deg) } }
|
|
762
|
+
@keyframes kibee2dGuide { 0%{transform:rotate(0)} 30%{transform:rotate(-8deg)} 60%{transform:rotate(6deg)} 100%{transform:rotate(0)} }
|
|
763
|
+
@keyframes kibee2dBounce { 0%{transform:scale(1)} 30%{transform:scale(1.18) translateY(-6px)} 60%{transform:scale(.95)} 100%{transform:scale(1)} }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kibee/renderer-three",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean --tsconfig tsconfig.build.json &&
|
|
22
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean --tsconfig tsconfig.build.json && cat src/styles.css src/dom/domAvatarStyles.css > dist/styles.css",
|
|
23
23
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"gsap": "^3.12.5",
|
|
27
|
+
"lottie-web": "^5.12.2",
|
|
27
28
|
"three": "^0.168.0"
|
|
28
29
|
},
|
|
29
30
|
"peerDependencies": {
|