@smart-cloud/ai-kit-ui 1.1.15 → 1.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smart-cloud/ai-kit-ui",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "@emotion/cache": "^11.14.0",
21
21
  "@emotion/react": "^11.14.0",
22
22
  "@mantine/colors-generator": "^8.3.13",
23
- "@smart-cloud/ai-kit-core": "^1.1.6",
23
+ "@smart-cloud/ai-kit-core": "^1.1.7",
24
24
  "@smart-cloud/wpsuite-core": "^2.0.5",
25
25
  "@tabler/icons-react": "^3.36.1",
26
26
  "chroma-js": "^3.2.0",
@@ -1,6 +1,6 @@
1
1
  import createCache from "@emotion/cache";
2
2
  import { CacheProvider } from "@emotion/react";
3
- import { useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { SetStateAction, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { createPortal } from "react-dom";
5
5
 
6
6
  export type ShadowBoundaryMode = "local" | "overlay";
@@ -9,9 +9,6 @@ export type ShadowBoundaryProps = {
9
9
  /** Stylesheets to inject into the shadow root (as <link rel="stylesheet">). */
10
10
  stylesheets: string[];
11
11
 
12
- /** Optional class name applied to the host element. */
13
- className?: string;
14
-
15
12
  /** ID of the element inside the shadow root used as the portal target. */
16
13
  rootElementId: string;
17
14
 
@@ -30,6 +27,7 @@ export type ShadowBoundaryProps = {
30
27
  */
31
28
  overlayRootId?: string;
32
29
 
30
+ setHost: React.Dispatch<SetStateAction<HTMLElement | null>>;
33
31
  children: (api: {
34
32
  /** Portal target element inside the shadow root. */
35
33
  rootElement: HTMLDivElement;
@@ -88,11 +86,11 @@ function installAiKitPropertyRegistry() {
88
86
 
89
87
  export function ShadowBoundary({
90
88
  stylesheets,
91
- className,
92
89
  children,
93
90
  rootElementId,
94
91
  mode = "local",
95
92
  overlayRootId = "ai-kit-overlay-root",
93
+ setHost,
96
94
  }: ShadowBoundaryProps) {
97
95
  const hostRef = useRef<HTMLDivElement | null>(null);
98
96
 
@@ -135,6 +133,7 @@ export function ShadowBoundary({
135
133
  } else {
136
134
  host = hostRef.current;
137
135
  }
136
+ setHost(host);
138
137
 
139
138
  // 2) Ensure shadow root
140
139
  const shadow = host.shadowRoot ?? host.attachShadow({ mode: "open" });
@@ -207,7 +206,6 @@ export function ShadowBoundary({
207
206
  return (
208
207
  <div
209
208
  ref={hostRef}
210
- className={className}
211
209
  style={{
212
210
  outline: "none",
213
211
  boxShadow: "none",
@@ -216,11 +214,11 @@ export function ShadowBoundary({
216
214
  >
217
215
  {portalTarget && shadowRoot && emotionCache
218
216
  ? createPortal(
219
- <CacheProvider value={emotionCache}>
220
- {children({ rootElement: portalTarget, shadowRoot })}
221
- </CacheProvider>,
222
- portalTarget,
223
- )
217
+ <CacheProvider value={emotionCache}>
218
+ {children({ rootElement: portalTarget, shadowRoot })}
219
+ </CacheProvider>,
220
+ portalTarget,
221
+ )
224
222
  : null}
225
223
  </div>
226
224
  );
@@ -53,9 +53,8 @@ const TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;
53
53
 
54
54
  // New: history storage support
55
55
  const DEFAULT_HISTORY_STORAGE: HistoryStorageMode = "localstorage";
56
- const HISTORY_STORAGE_KEY = `ai-kit-chatbot-history-v1:${
57
- typeof window !== "undefined" ? window.location.hostname : "unknown"
58
- }`;
56
+ const HISTORY_STORAGE_KEY = `ai-kit-chatbot-history-v1:${typeof window !== "undefined" ? window.location.hostname : "unknown"
57
+ }`;
59
58
 
60
59
  export const DEFAULT_CHATBOT_LABELS: Required<AiChatbotLabels> = {
61
60
  modalTitle: "AI Assistant",
@@ -216,7 +215,6 @@ const AiChatbotBase: FC<AiChatbotProps & AiKitShellInjectedProps> = (props) => {
216
215
  openButtonIcon,
217
216
  showOpenButtonTitle = true,
218
217
  showOpenButtonIcon = true,
219
- className,
220
218
  colorMode,
221
219
  language,
222
220
  onClose,
@@ -346,8 +344,8 @@ const AiChatbotBase: FC<AiChatbotProps & AiKitShellInjectedProps> = (props) => {
346
344
  const rootClassName = useMemo(() => {
347
345
  const base = "ai-docs-ask";
348
346
  const pos = `ai-open-btn--${openButtonPosition}`;
349
- return className ? `${base} ${pos} ${className}` : `${base} ${pos}`;
350
- }, [className, openButtonPosition]);
347
+ return `${base} ${pos}`;
348
+ }, [openButtonPosition]);
351
349
 
352
350
  const adjustChatHeight = useCallback(() => {
353
351
  const el = chatContainerRef.current;
@@ -597,7 +595,7 @@ const AiChatbotBase: FC<AiChatbotProps & AiKitShellInjectedProps> = (props) => {
597
595
  try {
598
596
  const activeSessionId =
599
597
  sessionRef.current &&
600
- Date.now() - sessionRef.current.storedAt < TWENTY_FOUR_HOURS_MS
598
+ Date.now() - sessionRef.current.storedAt < TWENTY_FOUR_HOURS_MS
601
599
  ? sessionRef.current.id
602
600
  : undefined;
603
601
  if (!activeSessionId) return;
@@ -682,7 +680,7 @@ const AiChatbotBase: FC<AiChatbotProps & AiKitShellInjectedProps> = (props) => {
682
680
  try {
683
681
  const activeSessionId =
684
682
  sessionRef.current &&
685
- Date.now() - sessionRef.current.storedAt < TWENTY_FOUR_HOURS_MS
683
+ Date.now() - sessionRef.current.storedAt < TWENTY_FOUR_HOURS_MS
686
684
  ? sessionRef.current.id
687
685
  : undefined;
688
686
 
@@ -14,7 +14,7 @@ import {
14
14
  } from "@smart-cloud/ai-kit-core";
15
15
  import { useSelect } from "@wordpress/data";
16
16
  import { I18n } from "aws-amplify/utils";
17
- import { type ComponentType, useCallback, useMemo, useState } from "react";
17
+ import { type ComponentType, useEffect, useMemo, useState } from "react";
18
18
  import { ShadowBoundary } from "./ShadowBoundary";
19
19
 
20
20
  export type AiKitShellInjectedProps = {
@@ -47,12 +47,12 @@ export function withAiKitShell<P extends object>(
47
47
  colorMode,
48
48
  primaryColor,
49
49
  primaryShade,
50
- className,
51
- innerCSS,
50
+ themeOverrides,
52
51
  language,
53
52
  direction,
54
53
  } = { ...props, ...propOverrides } as AiWorkerProps & P;
55
54
 
55
+ const [host, setHost] = useState<HTMLElement | null>(null);
56
56
  const languageInStore: string | undefined | null = useSelect(() =>
57
57
  getStoreSelect(store).getLanguage(),
58
58
  );
@@ -126,19 +126,19 @@ export function withAiKitShell<P extends object>(
126
126
  ].includes(primaryColor) && { primaryColor }),
127
127
  ...(primaryShade &&
128
128
  Object.keys(primaryShade).length > 0 && {
129
- primaryShade: {
130
- light:
131
- primaryShade.light ??
132
- (typeof DEFAULT_THEME.primaryShade === "object"
133
- ? DEFAULT_THEME.primaryShade.light
134
- : (DEFAULT_THEME.primaryShade ?? 6)),
135
- dark:
136
- primaryShade.dark ??
137
- (typeof DEFAULT_THEME.primaryShade === "object"
138
- ? DEFAULT_THEME.primaryShade.dark
139
- : (DEFAULT_THEME.primaryShade ?? 6)),
140
- },
141
- }),
129
+ primaryShade: {
130
+ light:
131
+ primaryShade.light ??
132
+ (typeof DEFAULT_THEME.primaryShade === "object"
133
+ ? DEFAULT_THEME.primaryShade.light
134
+ : (DEFAULT_THEME.primaryShade ?? 6)),
135
+ dark:
136
+ primaryShade.dark ??
137
+ (typeof DEFAULT_THEME.primaryShade === "object"
138
+ ? DEFAULT_THEME.primaryShade.dark
139
+ : (DEFAULT_THEME.primaryShade ?? 6)),
140
+ },
141
+ }),
142
142
  components: {
143
143
  Button: {
144
144
  styles: { root: { borderRadius: "inherit" } },
@@ -175,35 +175,44 @@ export function withAiKitShell<P extends object>(
175
175
  },
176
176
  });
177
177
 
178
- const innerCSSHash = useMemo(() => {
179
- return innerCSS ? hashStringDjb2(innerCSS) : "";
180
- }, [innerCSS]);
178
+ const themeOverridesHash = useMemo(() => {
179
+ return themeOverrides ? hashStringDjb2(themeOverrides) : "";
180
+ }, [themeOverrides]);
181
+
182
+ useEffect(
183
+ () => {
181
184
 
182
- const injectStyle = useCallback(
183
- (rootElement: HTMLDivElement) => {
184
- const existingStyle = rootElement.ownerDocument.getElementById(
185
+ if (!host) {
186
+ return;
187
+ }
188
+
189
+ const existingStyle = host.shadowRoot!.getElementById(
185
190
  STYLE_TEXT_ID,
186
191
  ) as HTMLStyleElement | null;
187
192
 
188
- if (innerCSS) {
193
+ console.log('injectStyle called', host, host.shadowRoot, existingStyle);
194
+
195
+ if (themeOverrides) {
189
196
  if (!existingStyle) {
190
- const s = rootElement.ownerDocument.createElement("style");
197
+ console.log('Creating new style element');
198
+ const s = host.shadowRoot!.ownerDocument.createElement("style");
191
199
  s.id = STYLE_TEXT_ID;
192
- s.setAttribute("data-hash", innerCSSHash);
193
- s.textContent = innerCSS;
194
- rootElement.appendChild(s);
200
+ s.setAttribute("data-hash", themeOverridesHash);
201
+ s.textContent = themeOverrides;
202
+ host.shadowRoot!.appendChild(s);
195
203
  } else {
196
204
  const prevHash = existingStyle.getAttribute("data-hash") || "";
197
- if (prevHash !== innerCSSHash) {
198
- existingStyle.setAttribute("data-hash", innerCSSHash);
199
- existingStyle.textContent = innerCSS;
205
+ if (prevHash !== themeOverridesHash) {
206
+ console.log('Updating existing style element');
207
+ existingStyle.textContent = themeOverrides;
200
208
  }
201
209
  }
202
210
  } else if (existingStyle) {
211
+ console.log('Removing existing style element');
203
212
  existingStyle.remove();
204
213
  }
205
214
  },
206
- [innerCSS, innerCSSHash],
215
+ [host, themeOverrides, themeOverridesHash],
207
216
  );
208
217
 
209
218
  return (
@@ -212,7 +221,7 @@ export function withAiKitShell<P extends object>(
212
221
  variation={variation}
213
222
  overlayRootId="ai-kit-overlay-root"
214
223
  stylesheets={stylesheets}
215
- className={className}
224
+ setHost={setHost}
216
225
  rootElementId={
217
226
  variation === "modal" && !showOpenButton
218
227
  ? "ai-kit-portal-root"
@@ -220,7 +229,6 @@ export function withAiKitShell<P extends object>(
220
229
  }
221
230
  >
222
231
  {({ rootElement }) => {
223
- injectStyle(rootElement);
224
232
  rootElement.setAttribute(
225
233
  "data-ai-kit-variation",
226
234
  variation || "default",
@@ -258,8 +266,7 @@ export function withAiKitShell<P extends object>(
258
266
  );
259
267
  };
260
268
 
261
- Wrapped.displayName = `withAiKitShell(${
262
- RootComponent.displayName ?? RootComponent.name ?? "Component"
263
- })`;
269
+ Wrapped.displayName = `withAiKitShell(${RootComponent.displayName ?? RootComponent.name ?? "Component"
270
+ })`;
264
271
  return Wrapped;
265
272
  }