@clubmed/usg-chat-ui 1.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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ## 0.0.1
4
+ - Initial scaffolding for the reusable chat package.
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ <div style="text-align: center" align="center">
2
+ <img src="https://ns.clubmed.com/fbs/RWD/branding2023/Logo/MicrosoftTeams-image%20(9).png" width="200" alt="Club Med"/>
3
+ </div>
4
+
5
+ <div align="center">
6
+ <h1>@clubmed/usg-chat-ui</h1>
7
+ <hr />
8
+
9
+ [![npm version](https://badge.fury.io/js/%40clubmed%2Ftrident-ui.svg)](https://badge.fury.io/js/%40clubmed%2Fusg-chat-ui)
10
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
11
+
12
+ </div>
13
+
14
+ Reusable chat experience extracted from the ClubMed USG project. Everything is published as ESM-only output so it can be consumed by any Vite/Next/CRA-style React host.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @clubmed/usg-chat-ui
20
+ ```
21
+
22
+ ## Provider setup
23
+
24
+ Drop the ready-made `<Chat />` organism into your page and pass the minimal props (`apiUrl`, `accessToken`, `user`, optional `logout`). Internally it wires the chat provider, HTTP client, and feature contexts so you don’t need to juggle multiple wrappers.
25
+
26
+ ```tsx
27
+ import type {ChatUser} from "@clubmed/usg-chat-ui";
28
+ import {Chat} from "@clubmed/usg-chat-ui/organisms/Chat";;
29
+
30
+ const session = useSession(); // host-specific auth hook
31
+
32
+ export function ChatPanel() {
33
+ const user: ChatUser | null = session
34
+ ? {
35
+ userId: session.userId,
36
+ userName: session.name,
37
+ userEmail: session.email,
38
+ }
39
+ : null;
40
+
41
+ return (
42
+ <ChatProvider>
43
+ apiUrl={process.env.API_URL!}
44
+ accessToken={session.accessToken}
45
+ user={user}
46
+ logout={session.logout}
47
+ >
48
+ <Chat />
49
+ </ChatProvider>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ### Configuration keys
55
+
56
+ | Field | Description |
57
+ |----------------------|-----------------------------------------------------------------------------------------|
58
+ | `config.apiUrl` | Base URL for server-to-server requests (e.g. `https://backend.internal`). |
59
+ | `config.fetcher` | Optional custom `fetch` implementation (for SSR polyfills, logging, etc.). |
60
+ | `config.accessToken` | Latest access token. When omitted/`null`, requests are sent anonymously. |
61
+ | `config.user` | Lightweight `{ userId, userName, userEmail }` object propagated via headers. |
62
+ | `logout` | Optional handler wired into settings so users can disconnect directly from the chat UI. |
63
+
64
+ If you need to customize HTTP transport or headers, provide a `fetcher` override or extend the HTTP client directly—`ChatProvider` keeps the config surface minimal (`apiUrl`, `fetcher`, `accessToken`, `user`).
65
+
66
+ ## Storybook
67
+
68
+ Storybook v10 is configured at the workspace root (`usg-ui/.storybook`). Run `yarn storybook` from `usg-ui/` to browse molecules and verify appearance tokens in isolation. The build output (`storybook-static`) can be published alongside the npm package for visual regression if desired.
package/package.json ADDED
@@ -0,0 +1,108 @@
1
+ {
2
+ "name": "@clubmed/usg-chat-ui",
3
+ "version": "1.0.0",
4
+ "description": "Reusable ClubMed USG chat experience",
5
+ "type": "module",
6
+ "license": "UNLICENSED",
7
+ "module": "./index.js",
8
+ "types": "./index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./index.js",
12
+ "types": "./index.d.ts"
13
+ },
14
+ "./styles.css": "./styles/index.css",
15
+ "./core/*": {
16
+ "types": "./core/*.d.ts",
17
+ "import": "./core/*.js",
18
+ "default": "./core/*.js"
19
+ },
20
+ "./contexts/*": {
21
+ "types": "./contexts/*.d.ts",
22
+ "import": "./contexts/*.js",
23
+ "default": "./contexts/*.js"
24
+ },
25
+ "./molecules/*": {
26
+ "types": "./molecules/*.d.ts",
27
+ "import": "./molecules/*.js",
28
+ "default": "./molecules/*.js"
29
+ },
30
+ "./organisms/*": {
31
+ "types": "./organisms/*.d.ts",
32
+ "import": "./organisms/*.js",
33
+ "default": "./organisms/*.js"
34
+ },
35
+ "./utils/*": {
36
+ "types": "./utils/*.d.ts",
37
+ "import": "./utils/*.js",
38
+ "default": "./utils/*.js"
39
+ },
40
+ "./helpers/*": {
41
+ "types": "./utils/*.d.ts",
42
+ "import": "./utils/*.js",
43
+ "default": "./utils/*.js"
44
+ }
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "styles",
49
+ "README.md",
50
+ "CHANGELOG.md"
51
+ ],
52
+ "sideEffects": [
53
+ "./styles/index.css",
54
+ "./dist/assets/style.css"
55
+ ],
56
+ "scripts": {
57
+ "clean": "rimraf dist",
58
+ "typecheck": "tsc --project tsconfig.json --noEmit",
59
+ "build": "npm run clean && vite build",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest watch",
62
+ "dev": "vite build --watch"
63
+ },
64
+ "peerDependencies": {
65
+ "react": "^19.0.0",
66
+ "react-dom": "^19.0.0"
67
+ },
68
+ "devDependencies": {
69
+ "@blocknote/core": "^0.41.1",
70
+ "@blocknote/mantine": "^0.41.1",
71
+ "@blocknote/react": "^0.41.1",
72
+ "@blocknote/xl-ai": "^0.41.1",
73
+ "@radix-ui/react-collapsible": "^1.1.12",
74
+ "@radix-ui/react-label": "^2.1.7",
75
+ "@radix-ui/react-slot": "^1.2.3",
76
+ "@radix-ui/react-tabs": "^1.1.13",
77
+ "@types/hast": "^3.0.4",
78
+ "@types/node": "^20.0.0",
79
+ "@types/react": "^19.0.0",
80
+ "@types/react-dom": "^19.0.0",
81
+ "@vitejs/plugin-react-swc": "^3.7.0",
82
+ "@y-sweet/client": "^0.9.1",
83
+ "ai": "^5.0.82",
84
+ "class-variance-authority": "^0.7.1",
85
+ "clsx": "^2.1.1",
86
+ "framer-motion": "^12.23.24",
87
+ "globby": "^13.2.2",
88
+ "isomorphic-dompurify": "^2.35.0",
89
+ "lucide-react": "^0.545.0",
90
+ "react": "^19.2.3",
91
+ "react-dom": "^19.2.3",
92
+ "react-markdown": "^10.1.0",
93
+ "remark-gfm": "^4.0.1",
94
+ "rimraf": "^5.0.5",
95
+ "rollup-preserve-directives": "^1.1.0",
96
+ "shiki": "^3.20.0",
97
+ "sonner": "^2.0.7",
98
+ "tailwind-merge": "^3.3.1",
99
+ "typescript": "^5.6.2",
100
+ "use-stick-to-bottom": "^1.1.1",
101
+ "vite": "^5.3.4",
102
+ "vite-plugin-dts": "4.5.4",
103
+ "vite-plugin-static-copy": "3.1.4",
104
+ "vite-plugin-svgr": "^4.2.0",
105
+ "yjs": "^13.6.27",
106
+ "zustand": "^5.0.8"
107
+ }
108
+ }
@@ -0,0 +1,171 @@
1
+ /* Placeholder styles for the @clubmed/usg-chat-ui package */
2
+
3
+ @tailwind base;
4
+ @tailwind components;
5
+ @tailwind utilities;
6
+
7
+ .usg-chat-ui {
8
+ --usg-chat-font: 'Inter', system-ui;
9
+ color-scheme: light;
10
+ --background: #ffffff;
11
+ --foreground: #111111;
12
+ --muted: #f4f4f5;
13
+ --muted-foreground: #3f3f46;
14
+ --border: #dcdcdc;
15
+ --card: #ffffff;
16
+ --card-foreground: #111111;
17
+ --accent: #e5e5e5;
18
+ --primary: #111111;
19
+ --primary-foreground: #f5f5f5;
20
+ --secondary: #f5f5f5;
21
+ --secondary-foreground: #1a1a1a;
22
+ --status-positive: #f2f2f2;
23
+ --status-positive-foreground: #161616;
24
+ --status-warning: #ededed;
25
+ --status-warning-foreground: #161616;
26
+ --status-critical: #e8e8e8;
27
+ --status-critical-foreground: #111111;
28
+
29
+ /* Spacing scale */
30
+ --spacing-xs: 0.25rem; /* 4px */
31
+ --spacing-sm: 0.5rem; /* 8px */
32
+ --spacing-md: 1rem; /* 16px */
33
+ --spacing-lg: 1.5rem; /* 24px */
34
+ --spacing-xl: 2rem; /* 32px */
35
+ --spacing-2xl: 3rem; /* 48px */
36
+
37
+ /* Shadows */
38
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
39
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
40
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
41
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
42
+
43
+ /* Radii */
44
+ --radius-sm: 0.5rem; /* 8px */
45
+ --radius-md: 0.75rem; /* 12px */
46
+ --radius-lg: 1rem; /* 16px */
47
+ --radius-xl: 1.5rem; /* 24px */
48
+
49
+ /* Blur */
50
+ --blur-sm: 4px;
51
+ --blur-md: 8px;
52
+ --blur-lg: 16px;
53
+ --blur-xl: 24px;
54
+
55
+ /* Transitions */
56
+ --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
57
+ --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
58
+ --transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1);
59
+ }
60
+
61
+ .usg-chat-ui.dark {
62
+ color-scheme: dark;
63
+ --background: #0b0b0b;
64
+ --foreground: #f5f5f5;
65
+ --muted: #1a1a1a;
66
+ --muted-foreground: #d4d4d8;
67
+ --border: #2a2a2a;
68
+ --card: #0f0f0f;
69
+ --card-foreground: #f5f5f5;
70
+ --accent: #1f1f1f;
71
+ --primary: #f5f5f5;
72
+ --primary-foreground: #111111;
73
+ --secondary: #161616;
74
+ --secondary-foreground: #f5f5f5;
75
+ --status-positive: #202020;
76
+ --status-positive-foreground: #f5f5f5;
77
+ --status-warning: #1c1c1c;
78
+ --status-warning-foreground: #f1f1f1;
79
+ --status-critical: #181818;
80
+ --status-critical-foreground: #f1f1f1;
81
+ }
82
+
83
+ .usg-chat-ui.light {
84
+ color-scheme: light;
85
+ --background: #ffffff;
86
+ --foreground: #111111;
87
+ --muted: #f4f4f5;
88
+ --muted-foreground: #3f3f46;
89
+ --border: #dcdcdc;
90
+ --card: #ffffff;
91
+ --card-foreground: #111111;
92
+ --accent: #e5e5e5;
93
+ --primary: #111111;
94
+ --primary-foreground: #f5f5f5;
95
+ --secondary: #f5f5f5;
96
+ --secondary-foreground: #1a1a1a;
97
+ --status-positive: #f2f2f2;
98
+ --status-positive-foreground: #161616;
99
+ --status-warning: #ededed;
100
+ --status-warning-foreground: #161616;
101
+ --status-critical: #e8e8e8;
102
+ --status-critical-foreground: #111111;
103
+ }
104
+
105
+ .usg-chat-ui {
106
+ background: var(--background);
107
+ color: var(--foreground);
108
+ font-family: var(--font-geist-sans), system-ui, sans-serif;
109
+ transition: background var(--transition-base), color var(--transition-base);
110
+ -webkit-font-smoothing: antialiased;
111
+ -moz-osx-font-smoothing: grayscale;
112
+ font-feature-settings: "rlig" 1, "calt" 1;
113
+ text-rendering: optimizeLegibility;
114
+ }
115
+
116
+ .usg-chat-ui code,
117
+ .usg-chat-ui pre,
118
+ .usg-chat-ui [class*="font-mono"],
119
+ .usg-chat-ui kbd {
120
+ font-family: var(--font-geist-mono), monospace;
121
+ }
122
+
123
+ /* Ensure prose elements use Geist */
124
+ .usg-chat-ui .prose {
125
+ font-family: var(--font-geist-sans);
126
+ }
127
+
128
+ .usg-chat-ui .prose code {
129
+ font-family: var(--font-geist-mono);
130
+ }
131
+
132
+ .usg-chat-ui input,
133
+ .usg-chat-ui textarea,
134
+ .usg-chat-ui select {
135
+ color: inherit;
136
+ background-color: var(--background);
137
+ }
138
+
139
+ .usg-chat-ui input::placeholder,
140
+ .usg-chat-ui textarea::placeholder {
141
+ color: var(--muted-foreground);
142
+ opacity: 0.6;
143
+ }
144
+
145
+ /* Custom Scrollbar */
146
+ .usg-chat-ui ::-webkit-scrollbar {
147
+ width: 8px;
148
+ height: 8px;
149
+ }
150
+
151
+ .usg-chat-ui ::-webkit-scrollbar-track {
152
+ background: transparent;
153
+ }
154
+
155
+ .usg-chat-ui ::-webkit-scrollbar-thumb {
156
+ background: rgb(160 160 160 / 0.4);
157
+ border-radius: 4px;
158
+ transition: background var(--transition-fast);
159
+ }
160
+
161
+ .usg-chat-ui ::-webkit-scrollbar-thumb:hover {
162
+ background: rgb(160 160 160 / 0.6);
163
+ }
164
+
165
+ .usg-chat-ui.dark ::-webkit-scrollbar-thumb {
166
+ background: rgb(96 96 96 / 0.4);
167
+ }
168
+
169
+ .usg-chat-ui.dark ::-webkit-scrollbar-thumb:hover {
170
+ background: rgb(96 96 96 / 0.6);
171
+ }