@xbrain-swe/nova-chat-widget 0.1.6 → 0.1.8
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.cjs +47 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +47 -16
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -148,7 +148,7 @@ type ViewRenderer = (props: {
|
|
|
148
148
|
}) => React.ReactNode;
|
|
149
149
|
type ViewRendererMap = Partial<Record<ViewKind, ViewRenderer>>;
|
|
150
150
|
|
|
151
|
-
declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdropStyle, defaultOpen, idleText, onVerdictAction, }: {
|
|
151
|
+
declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdropStyle, defaultOpen, idleText, avatarSize, onVerdictAction, }: {
|
|
152
152
|
/** 특정 view만 자체 컴포넌트로 덮어쓰고 싶을 때 — 지정 안 한 view는 기본 렌더러를 쓴다. */
|
|
153
153
|
viewRenderers?: ViewRendererMap;
|
|
154
154
|
/** Provider의 기본 봇 대신 다른 봇과 고정적으로 대화하고 싶을 때. 힌트를 눌러 열면
|
|
@@ -167,6 +167,9 @@ declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdr
|
|
|
167
167
|
defaultOpen?: boolean;
|
|
168
168
|
/** 기본(idle) 상태 바 문구. */
|
|
169
169
|
idleText?: string;
|
|
170
|
+
/** 바(AI 버튼)의 동그란 아바타 지름(px), 기본 28. 바의 접힌 원은 52px이라 44~48이면 원을 거의 채운다.
|
|
171
|
+
* 채팅 헤더의 아바타는 이 값에 맞춰 24~36px로 따라 커진다. */
|
|
172
|
+
avatarSize?: number;
|
|
170
173
|
/** 판단 카드의 행동 버튼을 눌렀을 때 — 실제 동작(상담신청 폼 열기, 섹션 스크롤 등)은
|
|
171
174
|
* 소비자가 정한다. SDK는 버튼에 적힌 `action` 문자열을 그대로 넘겨줄 뿐 뜻을 모른다. */
|
|
172
175
|
onVerdictAction?: (action: string) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -148,7 +148,7 @@ type ViewRenderer = (props: {
|
|
|
148
148
|
}) => React.ReactNode;
|
|
149
149
|
type ViewRendererMap = Partial<Record<ViewKind, ViewRenderer>>;
|
|
150
150
|
|
|
151
|
-
declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdropStyle, defaultOpen, idleText, onVerdictAction, }: {
|
|
151
|
+
declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdropStyle, defaultOpen, idleText, avatarSize, onVerdictAction, }: {
|
|
152
152
|
/** 특정 view만 자체 컴포넌트로 덮어쓰고 싶을 때 — 지정 안 한 view는 기본 렌더러를 쓴다. */
|
|
153
153
|
viewRenderers?: ViewRendererMap;
|
|
154
154
|
/** Provider의 기본 봇 대신 다른 봇과 고정적으로 대화하고 싶을 때. 힌트를 눌러 열면
|
|
@@ -167,6 +167,9 @@ declare function XbNovaChat({ viewRenderers, botId, barStyle, panelStyle, backdr
|
|
|
167
167
|
defaultOpen?: boolean;
|
|
168
168
|
/** 기본(idle) 상태 바 문구. */
|
|
169
169
|
idleText?: string;
|
|
170
|
+
/** 바(AI 버튼)의 동그란 아바타 지름(px), 기본 28. 바의 접힌 원은 52px이라 44~48이면 원을 거의 채운다.
|
|
171
|
+
* 채팅 헤더의 아바타는 이 값에 맞춰 24~36px로 따라 커진다. */
|
|
172
|
+
avatarSize?: number;
|
|
170
173
|
/** 판단 카드의 행동 버튼을 눌렀을 때 — 실제 동작(상담신청 폼 열기, 섹션 스크롤 등)은
|
|
171
174
|
* 소비자가 정한다. SDK는 버튼에 적힌 `action` 문자열을 그대로 넘겨줄 뿐 뜻을 모른다. */
|
|
172
175
|
onVerdictAction?: (action: string) => void;
|
package/dist/index.js
CHANGED
|
@@ -1476,6 +1476,7 @@ function XbNovaChat({
|
|
|
1476
1476
|
backdropStyle,
|
|
1477
1477
|
defaultOpen = false,
|
|
1478
1478
|
idleText = "AI\uC5D0\uAC8C \uC774 \uCC28 \uBB3C\uC5B4\uBCF4\uAE30",
|
|
1479
|
+
avatarSize = 28,
|
|
1479
1480
|
onVerdictAction
|
|
1480
1481
|
}) {
|
|
1481
1482
|
const { auth, trackRegistry, factsRegistry, visitorId, clientActionHandlers, theme } = useXbNovaInternal();
|
|
@@ -1483,6 +1484,7 @@ function XbNovaChat({
|
|
|
1483
1484
|
"--xbnova-accent-1": theme.accentFrom,
|
|
1484
1485
|
"--xbnova-accent-2": theme.accentTo
|
|
1485
1486
|
};
|
|
1487
|
+
const headerAvatarSize = Math.min(36, Math.max(24, Math.round(avatarSize * 0.8)));
|
|
1486
1488
|
const avatarGradientStyle = {
|
|
1487
1489
|
background: "linear-gradient(135deg, var(--xbnova-accent-1), var(--xbnova-accent-2))"
|
|
1488
1490
|
};
|
|
@@ -1503,6 +1505,28 @@ function XbNovaChat({
|
|
|
1503
1505
|
nudgeNodeId: activeNudgeNodeId,
|
|
1504
1506
|
onDismissSheet: () => setOpen(false)
|
|
1505
1507
|
});
|
|
1508
|
+
const effectiveBotId = activeBotId ?? botId;
|
|
1509
|
+
const [cachedBranding, setCachedBranding] = useState4(null);
|
|
1510
|
+
useEffect8(() => {
|
|
1511
|
+
try {
|
|
1512
|
+
const raw = window.localStorage.getItem(`xbnova_branding:${effectiveBotId}`);
|
|
1513
|
+
setCachedBranding(raw ? JSON.parse(raw) : null);
|
|
1514
|
+
} catch {
|
|
1515
|
+
setCachedBranding(null);
|
|
1516
|
+
}
|
|
1517
|
+
}, [effectiveBotId]);
|
|
1518
|
+
useEffect8(() => {
|
|
1519
|
+
if (!onboarding?.branding) return;
|
|
1520
|
+
try {
|
|
1521
|
+
window.localStorage.setItem(
|
|
1522
|
+
`xbnova_branding:${effectiveBotId}`,
|
|
1523
|
+
JSON.stringify({ logo_url: onboarding.branding.logo_url, avatar_text: onboarding.branding.avatar_text })
|
|
1524
|
+
);
|
|
1525
|
+
} catch {
|
|
1526
|
+
}
|
|
1527
|
+
}, [onboarding?.branding, effectiveBotId]);
|
|
1528
|
+
const branding = onboarding?.branding ?? cachedBranding ?? void 0;
|
|
1529
|
+
const brandingReady = Boolean(onboarding) || cachedBranding !== null || Boolean(error);
|
|
1506
1530
|
useEffect8(() => {
|
|
1507
1531
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1508
1532
|
}, [messages]);
|
|
@@ -1630,8 +1654,10 @@ function XbNovaChat({
|
|
|
1630
1654
|
children: /* @__PURE__ */ jsx7(
|
|
1631
1655
|
Avatar,
|
|
1632
1656
|
{
|
|
1633
|
-
branding
|
|
1634
|
-
|
|
1657
|
+
branding,
|
|
1658
|
+
ready: brandingReady,
|
|
1659
|
+
size: avatarSize,
|
|
1660
|
+
className: "shadow-md",
|
|
1635
1661
|
gradient: avatarGradientStyle
|
|
1636
1662
|
}
|
|
1637
1663
|
)
|
|
@@ -1678,8 +1704,10 @@ function XbNovaChat({
|
|
|
1678
1704
|
/* @__PURE__ */ jsx7(
|
|
1679
1705
|
Avatar,
|
|
1680
1706
|
{
|
|
1681
|
-
branding
|
|
1682
|
-
|
|
1707
|
+
branding,
|
|
1708
|
+
ready: brandingReady,
|
|
1709
|
+
size: headerAvatarSize,
|
|
1710
|
+
className: "shrink-0",
|
|
1683
1711
|
gradient: avatarGradientStyle
|
|
1684
1712
|
}
|
|
1685
1713
|
),
|
|
@@ -1797,31 +1825,34 @@ function XbNovaChat({
|
|
|
1797
1825
|
}
|
|
1798
1826
|
function Avatar({
|
|
1799
1827
|
branding,
|
|
1800
|
-
|
|
1828
|
+
ready,
|
|
1829
|
+
size,
|
|
1830
|
+
className = "",
|
|
1801
1831
|
gradient
|
|
1802
1832
|
}) {
|
|
1833
|
+
const box = { width: size, height: size };
|
|
1803
1834
|
const logoUrl = branding?.logo_url?.trim() ?? "";
|
|
1804
1835
|
const [failedUrl, setFailedUrl] = useState4("");
|
|
1836
|
+
const [loadedUrl, setLoadedUrl] = useState4("");
|
|
1837
|
+
const base = `${className} relative flex flex-none items-center justify-center overflow-hidden rounded-full font-bold text-white`;
|
|
1838
|
+
if (!ready) {
|
|
1839
|
+
return /* @__PURE__ */ jsx7("span", { className: base, style: { ...gradient, ...box }, "aria-hidden": true });
|
|
1840
|
+
}
|
|
1805
1841
|
if (logoUrl && failedUrl !== logoUrl) {
|
|
1806
|
-
return /* @__PURE__ */ jsx7(
|
|
1842
|
+
return /* @__PURE__ */ jsx7("span", { className: base, style: { ...gradient, ...box }, children: /* @__PURE__ */ jsx7(
|
|
1807
1843
|
"img",
|
|
1808
1844
|
{
|
|
1809
1845
|
src: logoUrl,
|
|
1810
1846
|
alt: "",
|
|
1847
|
+
onLoad: () => setLoadedUrl(logoUrl),
|
|
1811
1848
|
onError: () => setFailedUrl(logoUrl),
|
|
1812
|
-
className:
|
|
1849
|
+
className: "absolute inset-0 h-full w-full rounded-full bg-white object-cover transition-opacity duration-200",
|
|
1850
|
+
style: { opacity: loadedUrl === logoUrl ? 1 : 0 }
|
|
1813
1851
|
}
|
|
1814
|
-
);
|
|
1852
|
+
) });
|
|
1815
1853
|
}
|
|
1816
1854
|
const text = branding?.avatar_text?.trim() || "AI";
|
|
1817
|
-
return /* @__PURE__ */ jsx7(
|
|
1818
|
-
"span",
|
|
1819
|
-
{
|
|
1820
|
-
className: `${className} flex items-center justify-center rounded-full font-bold text-white`,
|
|
1821
|
-
style: gradient,
|
|
1822
|
-
children: text
|
|
1823
|
-
}
|
|
1824
|
-
);
|
|
1855
|
+
return /* @__PURE__ */ jsx7("span", { className: base, style: { ...gradient, ...box, fontSize: Math.max(10, Math.round(size * 0.4)) }, children: text });
|
|
1825
1856
|
}
|
|
1826
1857
|
function Bubble({ role, children }) {
|
|
1827
1858
|
const mine = role === "user";
|