@cometchat/skills-cli 2.0.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.
Files changed (95) hide show
  1. package/README.md +70 -0
  2. package/bin/cometchat.mjs +7 -0
  3. package/dist/index.js +4395 -0
  4. package/dist/registry/schemas/template.schema.json +142 -0
  5. package/dist/registry/v6/experiences/1-conversation-list/astro.template.json +89 -0
  6. package/dist/registry/v6/experiences/1-conversation-list/nextjs-pages.template.json +83 -0
  7. package/dist/registry/v6/experiences/1-conversation-list/nextjs.template.json +83 -0
  8. package/dist/registry/v6/experiences/1-conversation-list/react-router.template.json +102 -0
  9. package/dist/registry/v6/experiences/1-conversation-list/reactjs.template.json +86 -0
  10. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/ChatApp.css.tpl +39 -0
  11. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/ChatApp.tsx.tpl +86 -0
  12. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/CometChatSelector.tsx.tpl +40 -0
  13. package/dist/registry/v6/experiences/1-conversation-list/templates/astro/chat.astro.tpl +17 -0
  14. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatNoSSR.css.tpl +39 -0
  15. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatNoSSR.tsx.tpl +86 -0
  16. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/CometChatSelector.tsx.tpl +41 -0
  17. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs/chat-page.tsx.tpl +11 -0
  18. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatNoSSR.css.tpl +39 -0
  19. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatNoSSR.tsx.tpl +88 -0
  20. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/CometChatSelector.tsx.tpl +41 -0
  21. package/dist/registry/v6/experiences/1-conversation-list/templates/nextjs-pages/chat-page.tsx.tpl +15 -0
  22. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChat-route.tsx.tpl +22 -0
  23. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatNoSSR.css.tpl +39 -0
  24. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatNoSSR.tsx.tpl +87 -0
  25. package/dist/registry/v6/experiences/1-conversation-list/templates/react-router/CometChatSelector.tsx.tpl +40 -0
  26. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/App.css.tpl +32 -0
  27. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/App.tsx.tpl +55 -0
  28. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/CometChatSelector.tsx.tpl +40 -0
  29. package/dist/registry/v6/experiences/1-conversation-list/templates/reactjs/main.tsx.tpl +46 -0
  30. package/dist/registry/v6/experiences/2-one-to-one/astro.template.json +81 -0
  31. package/dist/registry/v6/experiences/2-one-to-one/nextjs.template.json +77 -0
  32. package/dist/registry/v6/experiences/2-one-to-one/react-router.template.json +93 -0
  33. package/dist/registry/v6/experiences/2-one-to-one/reactjs.template.json +77 -0
  34. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/ChatApp.css.tpl +21 -0
  35. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/ChatApp.tsx.tpl +66 -0
  36. package/dist/registry/v6/experiences/2-one-to-one/templates/astro/chat.astro.tpl +17 -0
  37. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/CometChatNoSSR.css.tpl +21 -0
  38. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/CometChatNoSSR.tsx.tpl +66 -0
  39. package/dist/registry/v6/experiences/2-one-to-one/templates/nextjs/chat-page.tsx.tpl +11 -0
  40. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChat-route.tsx.tpl +21 -0
  41. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChatNoSSR.css.tpl +21 -0
  42. package/dist/registry/v6/experiences/2-one-to-one/templates/react-router/CometChatNoSSR.tsx.tpl +67 -0
  43. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/App.css.tpl +4 -0
  44. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/App.tsx.tpl +44 -0
  45. package/dist/registry/v6/experiences/2-one-to-one/templates/reactjs/main.tsx.tpl +46 -0
  46. package/dist/registry/v6/experiences/3-tab-based/astro.template.json +93 -0
  47. package/dist/registry/v6/experiences/3-tab-based/nextjs.template.json +90 -0
  48. package/dist/registry/v6/experiences/3-tab-based/react-router.template.json +105 -0
  49. package/dist/registry/v6/experiences/3-tab-based/reactjs.template.json +90 -0
  50. package/dist/registry/v6/experiences/3-tab-based/templates/astro/ChatApp.css.tpl +39 -0
  51. package/dist/registry/v6/experiences/3-tab-based/templates/astro/ChatApp.tsx.tpl +93 -0
  52. package/dist/registry/v6/experiences/3-tab-based/templates/astro/CometChatTabs.css.tpl +43 -0
  53. package/dist/registry/v6/experiences/3-tab-based/templates/astro/CometChatTabs.tsx.tpl +72 -0
  54. package/dist/registry/v6/experiences/3-tab-based/templates/astro/chat.astro.tpl +17 -0
  55. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatNoSSR.css.tpl +39 -0
  56. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatNoSSR.tsx.tpl +93 -0
  57. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatTabs.css.tpl +43 -0
  58. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/CometChatTabs.tsx.tpl +73 -0
  59. package/dist/registry/v6/experiences/3-tab-based/templates/nextjs/chat-page.tsx.tpl +11 -0
  60. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChat-route.tsx.tpl +21 -0
  61. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatNoSSR.css.tpl +39 -0
  62. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatNoSSR.tsx.tpl +94 -0
  63. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatTabs.css.tpl +43 -0
  64. package/dist/registry/v6/experiences/3-tab-based/templates/react-router/CometChatTabs.tsx.tpl +72 -0
  65. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/App.css.tpl +7 -0
  66. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/App.tsx.tpl +62 -0
  67. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/CometChatTabs.css.tpl +43 -0
  68. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/CometChatTabs.tsx.tpl +72 -0
  69. package/dist/registry/v6/experiences/3-tab-based/templates/reactjs/main.tsx.tpl +46 -0
  70. package/dist/registry/v6/features/catalog.json +344 -0
  71. package/dist/registry/v6/production/astro/cometchat-token.ts.tpl +86 -0
  72. package/dist/registry/v6/production/astro.template.json +51 -0
  73. package/dist/registry/v6/production/nextjs/route.ts.tpl +79 -0
  74. package/dist/registry/v6/production/nextjs.template.json +50 -0
  75. package/dist/registry/v6/production/react-router/api.cometchat-token.ts.tpl +73 -0
  76. package/dist/registry/v6/production/react-router.template.json +58 -0
  77. package/dist/registry/v6/user-mgmt/astro/cometchat-user.ts.tpl +164 -0
  78. package/dist/registry/v6/user-mgmt/astro.template.json +33 -0
  79. package/dist/registry/v6/user-mgmt/nextjs/route.ts.tpl +212 -0
  80. package/dist/registry/v6/user-mgmt/nextjs.template.json +57 -0
  81. package/dist/registry/v6/user-mgmt/react-router/api.cometchat-user.ts.tpl +176 -0
  82. package/dist/registry/v6/user-mgmt/react-router.template.json +40 -0
  83. package/dist/registry/v6/widget/astro/CometChatWidget.css.tpl +105 -0
  84. package/dist/registry/v6/widget/astro/CometChatWidget.tsx.tpl +88 -0
  85. package/dist/registry/v6/widget/astro.template.json +38 -0
  86. package/dist/registry/v6/widget/nextjs/CometChatWidget.css.tpl +105 -0
  87. package/dist/registry/v6/widget/nextjs/CometChatWidget.tsx.tpl +88 -0
  88. package/dist/registry/v6/widget/nextjs.template.json +40 -0
  89. package/dist/registry/v6/widget/react-router/CometChatWidget.css.tpl +105 -0
  90. package/dist/registry/v6/widget/react-router/CometChatWidget.tsx.tpl +98 -0
  91. package/dist/registry/v6/widget/react-router.template.json +36 -0
  92. package/dist/registry/v6/widget/reactjs/CometChatWidget.css.tpl +105 -0
  93. package/dist/registry/v6/widget/reactjs/CometChatWidget.tsx.tpl +89 -0
  94. package/dist/registry/v6/widget/reactjs.template.json +36 -0
  95. package/package.json +53 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * CometChatWidget styles — floating button + drawer.
3
+ *
4
+ * Edit the .cometchat-widget-button selector to change the button position
5
+ * (default: bottom-right). Edit the .cometchat-widget-drawer selector to
6
+ * change the drawer size + position.
7
+ */
8
+
9
+ .cometchat-widget-button {
10
+ position: fixed;
11
+ bottom: 24px;
12
+ right: 24px;
13
+ width: 56px;
14
+ height: 56px;
15
+ border-radius: 50%;
16
+ border: none;
17
+ background: var(--cometchat-primary-color, #6852D6);
18
+ color: white;
19
+ font-size: 24px;
20
+ cursor: pointer;
21
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
22
+ z-index: 9999;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
27
+ }
28
+
29
+ .cometchat-widget-button:hover {
30
+ transform: scale(1.05);
31
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
32
+ }
33
+
34
+ .cometchat-widget-button:active {
35
+ transform: scale(0.98);
36
+ }
37
+
38
+ .cometchat-widget-drawer {
39
+ position: fixed;
40
+ bottom: 96px;
41
+ right: 24px;
42
+ width: 720px;
43
+ max-width: calc(100vw - 48px);
44
+ height: 600px;
45
+ max-height: calc(100vh - 120px);
46
+ background: white;
47
+ border-radius: 12px;
48
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
49
+ z-index: 9998;
50
+ display: flex;
51
+ overflow: hidden;
52
+ border: 1px solid var(--cometchat-border-color-default, #e8e8e8);
53
+ }
54
+
55
+ .cometchat-widget-conversations {
56
+ width: 280px;
57
+ border-right: 1px solid var(--cometchat-border-color-default, #e8e8e8);
58
+ overflow: hidden;
59
+ display: flex;
60
+ flex-direction: column;
61
+ }
62
+
63
+ .cometchat-widget-conversations > .cometchat {
64
+ overflow: hidden;
65
+ }
66
+
67
+ .cometchat-widget-messages {
68
+ flex: 1;
69
+ display: flex;
70
+ flex-direction: column;
71
+ overflow: hidden;
72
+ }
73
+
74
+ .cometchat-widget-empty {
75
+ flex: 1;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ background: var(--cometchat-background-color-03, #f5f5f5);
80
+ color: var(--cometchat-text-color-secondary, #727272);
81
+ font: var(--cometchat-font-body-regular, 400 14px Roboto);
82
+ padding: 16px;
83
+ text-align: center;
84
+ }
85
+
86
+ @media (max-width: 600px) {
87
+ .cometchat-widget-drawer {
88
+ bottom: 16px;
89
+ right: 16px;
90
+ left: 16px;
91
+ width: auto;
92
+ height: calc(100vh - 100px);
93
+ flex-direction: column;
94
+ }
95
+ .cometchat-widget-conversations {
96
+ width: 100%;
97
+ height: 200px;
98
+ border-right: none;
99
+ border-bottom: 1px solid var(--cometchat-border-color-default, #e8e8e8);
100
+ }
101
+ .cometchat-widget-button {
102
+ bottom: 16px;
103
+ right: 16px;
104
+ }
105
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * CometChatWidget — floating chat overlay (React Router v7 framework mode).
3
+ *
4
+ * React Router v7 SSRs by default. The CometChat SDK uses browser globals
5
+ * (WebSocket, IndexedDB, etc.) that don't exist on the server, so the
6
+ * widget defers its real render until after hydration via a mounted check.
7
+ *
8
+ * Assumes CometChatUIKit.init() and CometChatUIKit.login() have already
9
+ * been called by the existing chat route. The widget does NOT initialize
10
+ * CometChat — it just renders the existing logged-in user's chat.
11
+ *
12
+ * To use:
13
+ * import CometChatWidget from "./cometchat/CometChatWidget";
14
+ * // ...
15
+ * <CometChatWidget />
16
+ */
17
+ import { useEffect, useState } from "react";
18
+ import {
19
+ CometChatMessageComposer,
20
+ CometChatMessageHeader,
21
+ CometChatMessageList,
22
+ } from "@cometchat/chat-uikit-react";
23
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
24
+ import { CometChatSelector } from "./CometChatSelector";
25
+ import "./CometChatWidget.css";
26
+
27
+ export default function CometChatWidget() {
28
+ // SSR-safe: render nothing on the server, mount on the client.
29
+ const [mounted, setMounted] = useState(false);
30
+ useEffect(() => {
31
+ setMounted(true);
32
+ }, []);
33
+
34
+ const [open, setOpen] = useState(false);
35
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
36
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
37
+
38
+ // Close on Escape key
39
+ useEffect(() => {
40
+ if (!open) return;
41
+ const handler = (e: KeyboardEvent) => {
42
+ if (e.key === "Escape") setOpen(false);
43
+ };
44
+ window.addEventListener("keydown", handler);
45
+ return () => window.removeEventListener("keydown", handler);
46
+ }, [open]);
47
+
48
+ if (!mounted) return null;
49
+
50
+ return (
51
+ <>
52
+ <button
53
+ type="button"
54
+ className="cometchat-widget-button"
55
+ onClick={() => setOpen((v) => !v)}
56
+ aria-label={open ? "Close chat" : "Open chat"}
57
+ >
58
+ {open ? "✕" : "💬"}
59
+ </button>
60
+
61
+ {open && (
62
+ <div className="cometchat-widget-drawer" role="dialog" aria-label="Chat">
63
+ <div className="cometchat-widget-conversations">
64
+ <CometChatSelector
65
+ onSelectorItemClicked={(activeItem) => {
66
+ const item =
67
+ activeItem instanceof CometChat.Conversation
68
+ ? activeItem.getConversationWith()
69
+ : activeItem;
70
+ if (item instanceof CometChat.User) {
71
+ setSelectedUser(item);
72
+ setSelectedGroup(undefined);
73
+ } else if (item instanceof CometChat.Group) {
74
+ setSelectedUser(undefined);
75
+ setSelectedGroup(item);
76
+ }
77
+ }}
78
+ />
79
+ </div>
80
+ {selectedUser || selectedGroup ? (
81
+ <div className="cometchat-widget-messages">
82
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
83
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
84
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
85
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
86
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
87
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
88
+ </div>
89
+ ) : (
90
+ <div className="cometchat-widget-empty">
91
+ Select a conversation to start chatting
92
+ </div>
93
+ )}
94
+ </div>
95
+ )}
96
+ </>
97
+ );
98
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "../../schemas/template.schema.json",
3
+ "version": "1.0.0",
4
+ "experience_id": 1,
5
+ "framework": "react-router",
6
+ "sdk_compatibility": ">=6.0.0 <7.0.0",
7
+ "default_placement": "spa-root",
8
+ "deps": [],
9
+ "env_vars": [],
10
+ "files": [
11
+ {
12
+ "path": "app/cometchat/CometChatWidget.tsx",
13
+ "action": "create",
14
+ "template_ref": "CometChatWidget.tsx.tpl",
15
+ "owned": true
16
+ },
17
+ {
18
+ "path": "app/cometchat/CometChatWidget.css",
19
+ "action": "create",
20
+ "template_ref": "CometChatWidget.css.tpl",
21
+ "owned": true
22
+ }
23
+ ],
24
+ "verify_rules": [],
25
+ "next_steps": [
26
+ "1. The widget component is now at app/cometchat/CometChatWidget.tsx.",
27
+ "2. It uses an internal mounted-check (useState + useEffect) so React Router v7's SSR pass renders nothing on the server, then mounts the real widget after hydration.",
28
+ "3. Render it in your root layout (app/root.tsx) or any route component:",
29
+ " import CometChatWidget from \"./cometchat/CometChatWidget\";",
30
+ " // Then render <CometChatWidget /> anywhere in the JSX tree.",
31
+ "4. The widget reuses your existing CometChat init/login flow from the chat route.",
32
+ " You do NOT need to call init/login again inside the widget.",
33
+ "5. To customize position/size, edit the .cometchat-widget-button class in CometChatWidget.css.",
34
+ "6. The button appears in the bottom-right corner. Click it to open a drawer with the conversation list + message thread."
35
+ ]
36
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * CometChatWidget styles — floating button + drawer.
3
+ *
4
+ * Edit the .cometchat-widget-button selector to change the button position
5
+ * (default: bottom-right). Edit the .cometchat-widget-drawer selector to
6
+ * change the drawer size + position.
7
+ */
8
+
9
+ .cometchat-widget-button {
10
+ position: fixed;
11
+ bottom: 24px;
12
+ right: 24px;
13
+ width: 56px;
14
+ height: 56px;
15
+ border-radius: 50%;
16
+ border: none;
17
+ background: var(--cometchat-primary-color, #6852D6);
18
+ color: white;
19
+ font-size: 24px;
20
+ cursor: pointer;
21
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
22
+ z-index: 9999;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
27
+ }
28
+
29
+ .cometchat-widget-button:hover {
30
+ transform: scale(1.05);
31
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
32
+ }
33
+
34
+ .cometchat-widget-button:active {
35
+ transform: scale(0.98);
36
+ }
37
+
38
+ .cometchat-widget-drawer {
39
+ position: fixed;
40
+ bottom: 96px;
41
+ right: 24px;
42
+ width: 720px;
43
+ max-width: calc(100vw - 48px);
44
+ height: 600px;
45
+ max-height: calc(100vh - 120px);
46
+ background: white;
47
+ border-radius: 12px;
48
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
49
+ z-index: 9998;
50
+ display: flex;
51
+ overflow: hidden;
52
+ border: 1px solid var(--cometchat-border-color-default, #e8e8e8);
53
+ }
54
+
55
+ .cometchat-widget-conversations {
56
+ width: 280px;
57
+ border-right: 1px solid var(--cometchat-border-color-default, #e8e8e8);
58
+ overflow: hidden;
59
+ display: flex;
60
+ flex-direction: column;
61
+ }
62
+
63
+ .cometchat-widget-conversations > .cometchat {
64
+ overflow: hidden;
65
+ }
66
+
67
+ .cometchat-widget-messages {
68
+ flex: 1;
69
+ display: flex;
70
+ flex-direction: column;
71
+ overflow: hidden;
72
+ }
73
+
74
+ .cometchat-widget-empty {
75
+ flex: 1;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ background: var(--cometchat-background-color-03, #f5f5f5);
80
+ color: var(--cometchat-text-color-secondary, #727272);
81
+ font: var(--cometchat-font-body-regular, 400 14px Roboto);
82
+ padding: 16px;
83
+ text-align: center;
84
+ }
85
+
86
+ @media (max-width: 600px) {
87
+ .cometchat-widget-drawer {
88
+ bottom: 16px;
89
+ right: 16px;
90
+ left: 16px;
91
+ width: auto;
92
+ height: calc(100vh - 100px);
93
+ flex-direction: column;
94
+ }
95
+ .cometchat-widget-conversations {
96
+ width: 100%;
97
+ height: 200px;
98
+ border-right: none;
99
+ border-bottom: 1px solid var(--cometchat-border-color-default, #e8e8e8);
100
+ }
101
+ .cometchat-widget-button {
102
+ bottom: 16px;
103
+ right: 16px;
104
+ }
105
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * CometChatWidget — floating chat overlay.
3
+ *
4
+ * Renders a fixed-position button in the bottom-right corner. Click it to
5
+ * open a drawer containing the CometChat conversation list + message view.
6
+ *
7
+ * Assumes CometChatUIKit.init() and CometChatUIKit.login() have already been
8
+ * called elsewhere (e.g. in src/main.tsx). The widget just renders the
9
+ * existing logged-in user's chat — it does NOT initialize CometChat.
10
+ *
11
+ * To use:
12
+ * import CometChatWidget from "./cometchat/CometChatWidget";
13
+ * // ...
14
+ * <CometChatWidget />
15
+ */
16
+ import { useEffect, useState } from "react";
17
+ import {
18
+ CometChatMessageComposer,
19
+ CometChatMessageHeader,
20
+ CometChatMessageList,
21
+ } from "@cometchat/chat-uikit-react";
22
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
23
+ import { CometChatSelector } from "./CometChatSelector";
24
+ import "./CometChatWidget.css";
25
+
26
+ export default function CometChatWidget() {
27
+ const [open, setOpen] = useState(false);
28
+ const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>();
29
+ const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>();
30
+
31
+ // Close on Escape key
32
+ useEffect(() => {
33
+ if (!open) return;
34
+ const handler = (e: KeyboardEvent) => {
35
+ if (e.key === "Escape") setOpen(false);
36
+ };
37
+ window.addEventListener("keydown", handler);
38
+ return () => window.removeEventListener("keydown", handler);
39
+ }, [open]);
40
+
41
+ return (
42
+ <>
43
+ <button
44
+ type="button"
45
+ className="cometchat-widget-button"
46
+ onClick={() => setOpen((v) => !v)}
47
+ aria-label={open ? "Close chat" : "Open chat"}
48
+ >
49
+ {open ? "✕" : "💬"}
50
+ </button>
51
+
52
+ {open && (
53
+ <div className="cometchat-widget-drawer" role="dialog" aria-label="Chat">
54
+ <div className="cometchat-widget-conversations">
55
+ <CometChatSelector
56
+ onSelectorItemClicked={(activeItem) => {
57
+ const item =
58
+ activeItem instanceof CometChat.Conversation
59
+ ? activeItem.getConversationWith()
60
+ : activeItem;
61
+ if (item instanceof CometChat.User) {
62
+ setSelectedUser(item);
63
+ setSelectedGroup(undefined);
64
+ } else if (item instanceof CometChat.Group) {
65
+ setSelectedUser(undefined);
66
+ setSelectedGroup(item);
67
+ }
68
+ }}
69
+ />
70
+ </div>
71
+ {selectedUser || selectedGroup ? (
72
+ <div className="cometchat-widget-messages">
73
+ {selectedUser && <CometChatMessageHeader user={selectedUser} />}
74
+ {selectedGroup && <CometChatMessageHeader group={selectedGroup} />}
75
+ {selectedUser && <CometChatMessageList user={selectedUser} />}
76
+ {selectedGroup && <CometChatMessageList group={selectedGroup} />}
77
+ {selectedUser && <CometChatMessageComposer user={selectedUser} />}
78
+ {selectedGroup && <CometChatMessageComposer group={selectedGroup} />}
79
+ </div>
80
+ ) : (
81
+ <div className="cometchat-widget-empty">
82
+ Select a conversation to start chatting
83
+ </div>
84
+ )}
85
+ </div>
86
+ )}
87
+ </>
88
+ );
89
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "../../schemas/template.schema.json",
3
+ "version": "1.0.0",
4
+ "experience_id": 1,
5
+ "framework": "reactjs",
6
+ "sdk_compatibility": ">=6.0.0 <7.0.0",
7
+ "default_placement": "spa-root",
8
+ "deps": [],
9
+ "env_vars": [],
10
+ "files": [
11
+ {
12
+ "path": "src/cometchat/CometChatWidget.tsx",
13
+ "action": "create",
14
+ "template_ref": "CometChatWidget.tsx.tpl",
15
+ "owned": true
16
+ },
17
+ {
18
+ "path": "src/cometchat/CometChatWidget.css",
19
+ "action": "create",
20
+ "template_ref": "CometChatWidget.css.tpl",
21
+ "owned": true
22
+ }
23
+ ],
24
+ "verify_rules": [],
25
+ "next_steps": [
26
+ "1. The widget component is now at src/cometchat/CometChatWidget.tsx.",
27
+ "2. Import and render it in your root layout (e.g. src/App.tsx):",
28
+ " import CometChatWidget from './cometchat/CometChatWidget';",
29
+ " // Then render <CometChatWidget /> anywhere in your component tree.",
30
+ "3. The widget is a fixed-position floating button in the bottom-right corner.",
31
+ " Click it to open a drawer with the conversation list + message thread.",
32
+ "4. To customize position, edit the .cometchat-widget-button class in CometChatWidget.css.",
33
+ "5. The widget reuses your existing CometChat init/login flow from main.tsx —",
34
+ " you do NOT need to call init/login again inside the widget."
35
+ ]
36
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@cometchat/skills-cli",
3
+ "version": "2.0.0",
4
+ "description": "CLI for the CometChat skills v2 architecture — detect, view, apply, verify CometChat integrations in React projects.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "cometchat": "./bin/cometchat.mjs"
9
+ },
10
+ "files": [
11
+ "bin/",
12
+ "dist/",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "dev": "tsx src/index.ts",
17
+ "test": "node --test --import tsx test/*.test.ts",
18
+ "test:watch": "node --test --watch --import tsx test/*.test.ts",
19
+ "build": "rm -rf dist && esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --packages=external && node -e \"require('node:fs').cpSync(require('node:path').resolve('../registry/v6'),require('node:path').resolve('dist/registry/v6'),{recursive:true});require('node:fs').cpSync(require('node:path').resolve('../registry/schemas'),require('node:path').resolve('dist/registry/schemas'),{recursive:true});console.log(' bundled registry → dist/registry/');\"",
20
+ "typecheck": "tsc --noEmit",
21
+ "prepublishOnly": "npm run typecheck && npm test && npm run build"
22
+ },
23
+ "engines": {
24
+ "node": ">=18.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.0.0",
28
+ "esbuild": "^0.24.0",
29
+ "tsx": "^4.19.0",
30
+ "typescript": "^5.6.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "keywords": [
36
+ "cometchat",
37
+ "chat",
38
+ "react",
39
+ "nextjs",
40
+ "vite",
41
+ "astro",
42
+ "react-router",
43
+ "ai",
44
+ "agent",
45
+ "skills",
46
+ "cli"
47
+ ],
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/cometchat-team/cometchat-skills.git",
51
+ "directory": "packages/cli"
52
+ }
53
+ }