@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 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
- export { type BeeActionChoice, type BeeActionHandler, type BeeAssetVariant, type BeeAvatarPreset, type BeeDockClickBehavior, type BeeDockPosition, type BeeDockVariant, type BeeMotionMode, type BeeQualityTier, type BeeRenderer, type BeeVisualState, type DockMotionOptions, type MoveToOptions, type PromptOptions, type SetCustomDockPositionOptions, type SpeakOptions, ThreeBeeRenderer, type ThreeBeeRendererOptions, type TooltipArrowEdge, applyLegacyBeeMaterialCompat };
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
- export { type BeeActionChoice, type BeeActionHandler, type BeeAssetVariant, type BeeAvatarPreset, type BeeDockClickBehavior, type BeeDockPosition, type BeeDockVariant, type BeeMotionMode, type BeeQualityTier, type BeeRenderer, type BeeVisualState, type DockMotionOptions, type MoveToOptions, type PromptOptions, type SetCustomDockPositionOptions, type SpeakOptions, ThreeBeeRenderer, type ThreeBeeRendererOptions, type TooltipArrowEdge, applyLegacyBeeMaterialCompat };
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.2.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 && cp src/styles.css dist/styles.css",
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": {