@kaifusion/widget 1.0.3 → 1.0.5

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": "@kaifusion/widget",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.es.js",
6
6
  "module": "./dist/index.es.js",
@@ -19,8 +19,13 @@
19
19
  "scripts": {
20
20
  "dev": "vite",
21
21
  "build": "tsc && vite build",
22
+ "build:standalone": "vite build --config vite.config.standalone.ts",
22
23
  "preview": "vite preview"
23
24
  },
25
+ "peerDependencies": {
26
+ "react": "^18.0.0 || ^19.0.0",
27
+ "react-dom": "^18.0.0 || ^19.0.0"
28
+ },
24
29
  "dependencies": {
25
30
  "lucide-react": "^0.524.0",
26
31
  "motion": "^12.23.12",
@@ -30,14 +35,18 @@
30
35
  "rehype-raw": "^7.0.0",
31
36
  "remark-gfm": "^4.0.1",
32
37
  "remark-math": "^6.0.0",
38
+ "rollup": "^4.54.0",
33
39
  "uuid": "^11.1.0"
34
40
  },
35
41
  "devDependencies": {
42
+ "@tailwindcss/vite": "^4.1.4",
36
43
  "@types/node": "^25.0.3",
37
44
  "@types/react": "^19.1.8",
38
45
  "@types/react-dom": "^19.1.6",
39
46
  "@types/react-syntax-highlighter": "^15.5.13",
40
47
  "@vitejs/plugin-react": "^4.2.0",
48
+ "react": "^19.0.0",
49
+ "react-dom": "^19.0.0",
41
50
  "tailwindcss": "^4.1.4",
42
51
  "typescript": "^5.8.3",
43
52
  "vite": "^6.3.3",
@@ -34,7 +34,7 @@ interface Message {
34
34
  }
35
35
 
36
36
  export interface KaiChatWidgetProps {
37
- authToken: string;
37
+ authToken?: string;
38
38
  workflowId: string;
39
39
  title?: string;
40
40
  targetUrl: string;
@@ -64,6 +64,18 @@ export default function KaiChatWidget({
64
64
  ]);
65
65
  const [input, setInput] = useState("");
66
66
  const [isLoading, setIsLoading] = useState(false);
67
+ const [userProvidedToken, setUserProvidedToken] = useState<string | null>(
68
+ null
69
+ );
70
+
71
+ const effectiveToken = authToken || userProvidedToken;
72
+
73
+ const handleTokenSubmit = (token: string) => {
74
+ if (token.trim()) {
75
+ setUserProvidedToken(token);
76
+ }
77
+ };
78
+
67
79
  const [copiedCode, setCopiedCode] = useState<string | null>(null);
68
80
  const messagesEndRef = useRef<HTMLDivElement>(null);
69
81
  const sessionIdRef = useRef(uuidv4());
@@ -111,7 +123,7 @@ export default function KaiChatWidget({
111
123
  ]);
112
124
 
113
125
  try {
114
- const token = authToken || localStorage.getItem("auth_access_token");
126
+ const token = effectiveToken;
115
127
  const headers: Record<string, string> = {
116
128
  "Content-Type": "application/json",
117
129
  Accept: "text/event-stream",
@@ -654,39 +666,71 @@ export default function KaiChatWidget({
654
666
  </div>
655
667
 
656
668
  {/* Input Alanı */}
657
- <div className="p-4 bg-white border-t border-gray-100">
658
- <div className="flex gap-2 items-center bg-gray-50 rounded-full px-4 py-2 border border-gray-200 focus-within:border-blue-500 focus-within:ring-1 focus-within:ring-blue-500 transition-all">
659
- <input
660
- type="text"
661
- value={input}
662
- onChange={(e) => setInput(e.target.value)}
663
- onKeyDown={(e) => e.key === "Enter" && sendMessage()}
664
- placeholder="Mesajınızı yazın..."
665
- className="flex-1 bg-transparent border-none focus:ring-0 outline-none text-sm py-1"
666
- disabled={isLoading}
667
- />
668
- <button
669
- onClick={sendMessage}
670
- disabled={isLoading || !input.trim()}
671
- className={`p-2 rounded-full transition-all ${
672
- input.trim() && !isLoading
673
- ? "text-blue-600 hover:bg-blue-50"
674
- : "text-gray-400"
675
- }`}
676
- >
677
- {isLoading ? (
678
- <Loader2 className="w-5 h-5 animate-spin" />
679
- ) : (
680
- <Send className="w-5 h-5" />
681
- )}
682
- </button>
669
+ {effectiveToken ? (
670
+ <div className="p-4 bg-white border-t border-gray-100">
671
+ <div className="flex gap-2 items-center bg-gray-50 rounded-full px-4 py-2 border border-gray-200 focus-within:border-blue-500 focus-within:ring-1 focus-within:ring-blue-500 transition-all">
672
+ <input
673
+ type="text"
674
+ value={input}
675
+ onChange={(e) => setInput(e.target.value)}
676
+ onKeyDown={(e) => e.key === "Enter" && sendMessage()}
677
+ placeholder="Mesajınızı yazın..."
678
+ className="flex-1 bg-transparent border-none focus:ring-0 outline-none text-sm py-1 text-black"
679
+ disabled={isLoading}
680
+ />
681
+ <button
682
+ onClick={sendMessage}
683
+ disabled={isLoading || !input.trim()}
684
+ className={`p-2 rounded-full transition-all ${
685
+ input.trim() && !isLoading
686
+ ? "text-blue-600 hover:bg-blue-50"
687
+ : "text-gray-400"
688
+ }`}
689
+ >
690
+ {isLoading ? (
691
+ <Loader2 className="w-5 h-5 animate-spin" />
692
+ ) : (
693
+ <Send className="w-5 h-5" />
694
+ )}
695
+ </button>
696
+ </div>
697
+ <div className="text-center mt-2">
698
+ <span className="text-[10px] text-gray-400">
699
+ Powered by Agenticgro
700
+ </span>
701
+ </div>
683
702
  </div>
684
- <div className="text-center mt-2">
685
- <span className="text-[10px] text-gray-400">
686
- Powered by Agenticgro
687
- </span>
703
+ ) : (
704
+ <div className="p-4 bg-white border-t border-gray-100">
705
+ <div className="flex flex-col gap-3">
706
+ <p className="text-sm text-gray-600 text-center">
707
+ Devam etmek için lütfen Erişim Anahtarı giriniz:
708
+ </p>
709
+ <div className="flex gap-2">
710
+ <input
711
+ type="password"
712
+ placeholder="Access Token"
713
+ className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 outline-none text-sm text-gray-800"
714
+ onKeyDown={(e) => {
715
+ if (e.key === "Enter") {
716
+ handleTokenSubmit(e.currentTarget.value);
717
+ }
718
+ }}
719
+ />
720
+ <button
721
+ className="bg-blue-600 hover:bg-blue-700 text-white font-medium px-4 rounded-lg transition-colors text-sm"
722
+ onClick={(e) => {
723
+ const inputEl = e.currentTarget
724
+ .previousElementSibling as HTMLInputElement;
725
+ handleTokenSubmit(inputEl.value);
726
+ }}
727
+ >
728
+ Giriş
729
+ </button>
730
+ </div>
731
+ </div>
688
732
  </div>
689
- </div>
733
+ )}
690
734
  </motion.div>
691
735
  )}
692
736
  </AnimatePresence>
@@ -708,4 +752,4 @@ export default function KaiChatWidget({
708
752
  </motion.button>
709
753
  </div>
710
754
  );
711
- }
755
+ }
package/src/embed.tsx ADDED
@@ -0,0 +1,94 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import KaiChatWidget, { KaiChatWidgetProps } from "./KaiChatWidget";
4
+ // @ts-ignore
5
+ import styles from "./index.css?inline";
6
+
7
+ declare global {
8
+ interface Window {
9
+ KaiChat: {
10
+ init: (config: KaiChatWidgetProps) => void;
11
+ };
12
+ }
13
+ }
14
+
15
+ const KAI_CHAT_HOST_ID = "kai-chat-widget-host";
16
+
17
+ function init(config: KaiChatWidgetProps) {
18
+ if (document.getElementById(KAI_CHAT_HOST_ID)) {
19
+ return;
20
+ }
21
+
22
+ const host = document.createElement("div");
23
+ host.id = KAI_CHAT_HOST_ID;
24
+
25
+ host.style.position = "fixed";
26
+ host.style.zIndex = "2147483647";
27
+ host.style.bottom = "0";
28
+ host.style.right = "0";
29
+ host.style.width = "0";
30
+ host.style.height = "0";
31
+ host.style.overflow = "visible";
32
+
33
+ document.body.appendChild(host);
34
+
35
+ const shadow = host.attachShadow({ mode: "open" });
36
+
37
+ const styleTag = document.createElement("style");
38
+ styleTag.textContent = styles;
39
+ shadow.appendChild(styleTag);
40
+
41
+ const mountPoint = document.createElement("div");
42
+ mountPoint.id = "kai-chat-root";
43
+ shadow.appendChild(mountPoint);
44
+
45
+ const root = ReactDOM.createRoot(mountPoint);
46
+ root.render(
47
+ <React.StrictMode>
48
+ <KaiChatWidget {...config} />
49
+ </React.StrictMode>
50
+ );
51
+ }
52
+
53
+ // Global scope'a bağla
54
+ window.KaiChat = { init };
55
+
56
+ // OTOMATİK BAŞLATMA MANTIĞI
57
+ // Mevcut çalışan scripti bul (genellikle son eklenen scripttir veya src ile aranabilir)
58
+ // document.currentScript modern tarayıcılarda çalışır.
59
+ const currentScript = document.currentScript as HTMLScriptElement;
60
+
61
+ if (currentScript) {
62
+ const title = currentScript.getAttribute("data-title");
63
+ const authToken = currentScript.getAttribute("data-auth-token");
64
+ const workflowId = currentScript.getAttribute("data-workflow-id");
65
+ const targetUrl = currentScript.getAttribute("data-target-url");
66
+ const position = currentScript.getAttribute("data-position") as "left" | "right" | null;
67
+ const color = currentScript.getAttribute("data-color");
68
+
69
+ // Eğer gerekli parametreler varsa otomatik başlat
70
+ if (workflowId && targetUrl) {
71
+ // DOM hazır olana kadar bekle
72
+ if (document.readyState === "loading") {
73
+ document.addEventListener("DOMContentLoaded", () => {
74
+ init({
75
+ title: title || "ChatBot",
76
+ authToken: authToken || "",
77
+ workflowId,
78
+ targetUrl,
79
+ position: position || "right",
80
+ color: color || "#526cfe",
81
+ });
82
+ });
83
+ } else {
84
+ init({
85
+ title: title || "ChatBot",
86
+ authToken: authToken || "",
87
+ workflowId,
88
+ targetUrl,
89
+ position: position || "right",
90
+ color: color || "#526cfe",
91
+ });
92
+ }
93
+ }
94
+ }
package/src/index.css ADDED
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+
@@ -1,10 +0,0 @@
1
- export interface KaiChatWidgetProps {
2
- authToken: string;
3
- workflowId: string;
4
- title?: string;
5
- targetUrl: string;
6
- position?: "left" | "right";
7
- color?: string;
8
- icon?: React.ReactNode;
9
- }
10
- export default function KaiChatWidget({ authToken, workflowId, title, targetUrl, position, color, icon, }: KaiChatWidgetProps): import("react/jsx-runtime").JSX.Element;
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { default as KaiChatWidget } from './KaiChatWidget';
2
- export type { KaiChatWidgetProps } from './KaiChatWidget';