@fluxy-chat/create-fluxy-chat 0.5.4 → 0.5.6

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.
@@ -1,354 +1,355 @@
1
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
2
4
 
3
5
  :root {
4
- --bg: #0f0f10;
5
- --surface: #18181b;
6
- --surface-2: #27272a;
7
- --border: #3f3f46;
8
- --text: #fafafa;
9
- --text-muted: #a1a1aa;
10
- --accent: #6366f1;
11
- --accent-hover: #4f46e5;
12
- --agent: #10b981;
13
- --danger: #ef4444;
14
- --radius: 10px;
15
- --font: "Inter", system-ui, -apple-system, sans-serif;
16
- }
17
-
18
- html, body, #root { height: 100%; }
6
+ --background: #fdfbf9;
7
+ --foreground: #0e1316;
8
+ --surface: #fdfbf9;
9
+ --surface-muted: #f3f0ec;
10
+ --surface-card: #ffffff;
11
+ --text-primary: #1a1a1a;
12
+ --text-muted: #6b7280;
13
+ --border: #e5e0d8;
14
+ --brand: #ff725e;
15
+ --destructive: #dc2626;
16
+ --ring: #ff725e;
17
+ --radius: 0.5rem;
18
+
19
+ --fluxy-logo-color: #ff6a1a;
20
+ --fluxy-cta-color: #c2410c;
21
+ --fluxy-bubble-sent-bg: #ff6a1a;
22
+ --fluxy-bubble-sent-text: #ffffff;
23
+ --fluxy-bubble-received-bg: #f4f4f5;
24
+ --fluxy-bubble-received-border: #e4e4e7;
25
+ --fluxy-bubble-received-text: #1a1a1a;
26
+ --primary: var(--fluxy-cta-color);
27
+ --primary-foreground: #ffffff;
28
+ --muted: var(--surface-muted);
29
+ --muted-foreground: var(--text-muted);
30
+ }
31
+
32
+ html,
33
+ body,
34
+ #root {
35
+ height: 100%;
36
+ }
19
37
 
20
38
  body {
21
- font-family: var(--font);
22
- background: var(--bg);
23
- color: var(--text);
24
- font-size: 14px;
25
- line-height: 1.5;
39
+ margin: 0;
40
+ background: var(--background);
41
+ color: var(--foreground);
42
+ font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
26
43
  -webkit-font-smoothing: antialiased;
27
44
  }
28
45
 
29
- a { color: var(--accent); text-decoration: none; }
30
- a:hover { text-decoration: underline; }
31
-
32
- /* ---- App shell ---- */
33
-
34
- .shell {
46
+ .app-shell {
47
+ min-height: 100%;
35
48
  display: flex;
36
49
  flex-direction: column;
37
- height: 100%;
50
+ background: var(--background);
38
51
  }
39
52
 
40
- .app-header {
53
+ .topbar {
54
+ height: 56px;
41
55
  display: flex;
42
56
  align-items: center;
43
57
  justify-content: space-between;
44
58
  padding: 0 20px;
45
- height: 52px;
46
59
  border-bottom: 1px solid var(--border);
47
- background: var(--surface);
48
- flex-shrink: 0;
60
+ background: var(--surface-card);
49
61
  }
50
62
 
51
- .app-logo {
63
+ .brand {
52
64
  display: flex;
53
65
  align-items: center;
54
66
  gap: 8px;
55
- font-weight: 600;
67
+ font-weight: 650;
56
68
  font-size: 15px;
57
69
  }
58
70
 
59
- .app-nav {
71
+ .top-links {
60
72
  display: flex;
61
73
  align-items: center;
62
- gap: 16px;
74
+ gap: 14px;
75
+ font-size: 13px;
63
76
  }
64
77
 
65
- .nav-item { color: var(--text-muted); font-size: 13px; }
78
+ .top-links a,
79
+ .side a:not(.btn-primary) {
80
+ color: var(--fluxy-cta-color);
81
+ font-weight: 500;
82
+ text-decoration: none;
83
+ }
66
84
 
67
- .nav-link {
68
- font-size: 13px;
69
- color: var(--accent);
70
- border: 1px solid var(--accent);
71
- border-radius: 6px;
72
- padding: 4px 10px;
73
- transition: background 0.15s;
85
+ .top-links a:hover,
86
+ .side a:not(.btn-primary):hover {
87
+ text-decoration: underline;
74
88
  }
75
- .nav-link:hover { background: rgba(99,102,241,0.1); text-decoration: none; }
76
89
 
77
- /* ---- Layout ---- */
90
+ .meta {
91
+ color: var(--text-muted);
92
+ }
78
93
 
79
- .layout {
80
- display: flex;
94
+ .page {
81
95
  flex: 1;
96
+ display: grid;
97
+ grid-template-columns: minmax(0, 1fr) 280px;
82
98
  min-height: 0;
83
- overflow: hidden;
84
99
  }
85
100
 
86
- /* ---- Chat panel ---- */
87
-
88
- .chat-panel {
89
- flex: 1;
101
+ .chat-column {
90
102
  display: flex;
91
103
  flex-direction: column;
92
104
  min-width: 0;
93
- border-right: 1px solid var(--border);
94
- }
95
-
96
- .chat-header {
97
- display: flex;
98
- align-items: center;
99
- gap: 10px;
100
- padding: 12px 20px;
101
- border-bottom: 1px solid var(--border);
102
- background: var(--surface);
103
- flex-shrink: 0;
105
+ padding: 16px 20px 20px;
106
+ gap: 12px;
104
107
  }
105
108
 
106
- .room-name {
107
- font-weight: 600;
108
- font-size: 15px;
109
+ .status-row {
110
+ font-size: 12px;
111
+ color: var(--text-muted);
109
112
  }
110
113
 
111
- .status-badge {
112
- font-size: 11px;
113
- font-weight: 500;
114
- padding: 2px 8px;
114
+ .status-dot {
115
+ width: 8px;
116
+ height: 8px;
115
117
  border-radius: 99px;
116
- letter-spacing: 0.03em;
118
+ display: inline-block;
117
119
  }
118
- .status-badge.connected { background: rgba(16,185,129,0.15); color: var(--agent); }
119
- .status-badge.disconnected { background: rgba(239,68,68,0.15); color: var(--danger); }
120
+ .status-dot.on { background: #16a34a; }
121
+ .status-dot.off { background: #d97706; }
120
122
 
121
- .messages-list {
123
+ .chat-frame {
122
124
  flex: 1;
123
- overflow-y: auto;
124
- padding: 20px;
125
- display: flex;
126
- flex-direction: column;
127
- gap: 2px;
128
- scroll-behavior: smooth;
125
+ min-height: 420px;
126
+ background: var(--surface-card);
127
+ border: 1px solid var(--border);
128
+ border-radius: 16px;
129
+ overflow: hidden;
130
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
129
131
  }
130
132
 
131
- .empty-state {
132
- margin: auto;
133
- text-align: center;
134
- color: var(--text-muted);
135
- font-size: 14px;
133
+ .chat-frame > div {
134
+ height: 100% !important;
135
+ max-width: none !important;
136
+ border: none !important;
137
+ border-radius: 0 !important;
136
138
  }
137
139
 
138
- /* ---- Messages ---- */
139
-
140
- .message {
140
+ .prompts {
141
141
  display: flex;
142
- flex-direction: column;
143
- gap: 2px;
144
- padding: 6px 10px;
145
- border-radius: 8px;
146
- max-width: 75%;
147
- align-self: flex-start;
142
+ flex-wrap: wrap;
143
+ gap: 8px;
148
144
  }
149
145
 
150
- .message.self {
151
- align-self: flex-end;
152
- background: rgba(99,102,241,0.12);
146
+ .prompts button {
147
+ border: 1px solid var(--border);
148
+ background: var(--surface-card);
149
+ color: var(--foreground);
150
+ border-radius: 999px;
151
+ padding: 6px 12px;
152
+ font-size: 12px;
153
+ cursor: pointer;
153
154
  }
154
155
 
155
- .message.agent {
156
- background: rgba(16,185,129,0.08);
157
- border-left: 2px solid var(--agent);
156
+ .prompts button:hover {
157
+ border-color: var(--fluxy-cta-color);
158
+ color: var(--fluxy-cta-color);
158
159
  }
159
160
 
160
- .msg-author {
161
- font-size: 11px;
162
- font-weight: 600;
163
- color: var(--text-muted);
164
- text-transform: uppercase;
165
- letter-spacing: 0.05em;
161
+ .chat-error {
162
+ color: var(--destructive);
163
+ font-size: 13px;
166
164
  }
167
165
 
168
- .message.self .msg-author { color: var(--accent); }
169
- .message.agent .msg-author { color: var(--agent); }
170
-
171
- .msg-body {
172
- color: var(--text);
173
- line-height: 1.55;
174
- word-break: break-word;
175
- white-space: pre-wrap;
166
+ .side {
167
+ border-left: 1px solid var(--border);
168
+ background: var(--surface-muted);
169
+ padding: 20px 16px;
170
+ display: flex;
171
+ flex-direction: column;
172
+ gap: 16px;
176
173
  }
177
174
 
178
- /* ---- Typing indicator ---- */
179
-
180
- .typing-indicator .msg-body {
181
- display: flex;
182
- gap: 4px;
183
- align-items: center;
184
- padding: 4px 0;
175
+ .side section {
176
+ background: var(--surface-card);
177
+ border: 1px solid var(--border);
178
+ border-radius: 12px;
179
+ padding: 14px;
185
180
  }
186
181
 
187
- .dot {
188
- width: 6px;
189
- height: 6px;
190
- border-radius: 50%;
191
- background: var(--agent);
192
- animation: bounce 1.2s infinite ease-in-out;
182
+ .side h2 {
183
+ font-size: 11px;
184
+ text-transform: uppercase;
185
+ letter-spacing: 0.08em;
186
+ color: var(--text-muted);
187
+ margin: 0 0 10px;
193
188
  }
194
- .dot:nth-child(2) { animation-delay: 0.2s; }
195
- .dot:nth-child(3) { animation-delay: 0.4s; }
196
189
 
197
- @keyframes bounce {
198
- 0%, 80%, 100% { transform: translateY(0); opacity: 0.5; }
199
- 40% { transform: translateY(-4px); opacity: 1; }
190
+ .side dl {
191
+ display: flex;
192
+ flex-direction: column;
193
+ gap: 8px;
194
+ margin: 0;
200
195
  }
201
196
 
202
- /* ---- Composer ---- */
197
+ .side dt {
198
+ font-size: 11px;
199
+ color: var(--text-muted);
200
+ }
203
201
 
204
- .chat-error {
205
- margin: 0 20px 8px;
206
- color: var(--danger);
202
+ .side dd {
203
+ margin: 0;
207
204
  font-size: 13px;
205
+ word-break: break-all;
208
206
  }
209
207
 
210
- .composer {
208
+ .side ul {
209
+ margin: 0;
210
+ padding-left: 1.1rem;
211
+ color: var(--text-muted);
212
+ font-size: 13px;
211
213
  display: flex;
214
+ flex-direction: column;
212
215
  gap: 8px;
213
- padding: 14px 20px;
214
- border-top: 1px solid var(--border);
215
- background: var(--surface);
216
- flex-shrink: 0;
217
- align-items: center;
218
216
  }
219
217
 
220
- .composer input {
221
- flex: 1;
222
- background: var(--surface-2);
218
+ .signin-card {
219
+ margin: auto;
220
+ max-width: 440px;
221
+ width: calc(100% - 32px);
222
+ background: var(--surface-card);
223
223
  border: 1px solid var(--border);
224
- border-radius: var(--radius);
225
- padding: 9px 14px;
226
- color: var(--text);
227
- font-size: 14px;
228
- font-family: var(--font);
229
- outline: none;
230
- transition: border-color 0.15s;
224
+ border-radius: 16px;
225
+ padding: 32px;
226
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
231
227
  }
232
- .composer input:focus { border-color: var(--accent); }
233
- .composer input::placeholder { color: var(--text-muted); }
234
228
 
235
- .composer button {
236
- padding: 9px 16px;
237
- border-radius: var(--radius);
238
- border: none;
239
- font-size: 13px;
240
- font-weight: 500;
241
- cursor: pointer;
242
- transition: background 0.15s, opacity 0.15s;
243
- white-space: nowrap;
244
- font-family: var(--font);
229
+ .onboard {
230
+ margin: auto;
231
+ max-width: 520px;
232
+ width: calc(100% - 32px);
233
+ background: var(--surface-card);
234
+ border: 1px solid var(--border);
235
+ border-radius: 16px;
236
+ padding: 32px;
237
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
245
238
  }
246
- .composer button:disabled { opacity: 0.4; cursor: not-allowed; }
247
239
 
248
- .composer button[type="submit"] {
249
- background: var(--accent);
250
- color: #fff;
240
+ .onboard h1 {
241
+ margin: 0 0 8px;
242
+ font-size: 24px;
251
243
  }
252
- .composer button[type="submit"]:hover:not(:disabled) { background: var(--accent-hover); }
253
244
 
254
- .composer .btn-agent {
255
- background: rgba(16,185,129,0.12);
256
- color: var(--agent);
257
- border: 1px solid rgba(16,185,129,0.3);
245
+ .onboard p {
246
+ color: var(--text-muted);
247
+ font-size: 15px;
248
+ line-height: 1.55;
258
249
  }
259
- .composer .btn-agent:hover:not(:disabled) { background: rgba(16,185,129,0.2); }
260
250
 
261
- /* ---- Sidebar ---- */
251
+ .dots {
252
+ display: flex;
253
+ gap: 6px;
254
+ margin-bottom: 16px;
255
+ }
262
256
 
263
- .sidebar {
264
- width: 280px;
265
- flex-shrink: 0;
266
- overflow-y: auto;
267
- padding: 20px 16px;
257
+ .dot-step {
258
+ width: 8px;
259
+ height: 8px;
260
+ border-radius: 99px;
261
+ background: var(--border);
262
+ }
263
+
264
+ .dot-step.active {
265
+ background: var(--fluxy-cta-color);
266
+ width: 22px;
267
+ }
268
+
269
+ .onboard-actions {
268
270
  display: flex;
269
- flex-direction: column;
270
- gap: 12px;
271
- background: var(--surface);
271
+ align-items: center;
272
+ gap: 10px;
273
+ margin-top: 20px;
272
274
  }
273
275
 
274
- .sidebar-card {
275
- background: var(--surface-2);
276
+ .btn-ghost {
276
277
  border: 1px solid var(--border);
277
- border-radius: var(--radius);
278
- padding: 14px 16px;
278
+ background: transparent;
279
+ color: var(--foreground);
280
+ border-radius: 10px;
281
+ padding: 10px 16px;
282
+ font-weight: 600;
283
+ font-size: 14px;
284
+ cursor: pointer;
279
285
  }
280
286
 
281
- .sidebar-card h3 {
282
- font-size: 11px;
283
- font-weight: 600;
284
- text-transform: uppercase;
285
- letter-spacing: 0.07em;
286
- color: var(--text-muted);
287
- margin-bottom: 10px;
287
+ .btn-primary.side-btn {
288
+ margin-top: 10px;
289
+ width: 100%;
290
+ justify-content: center;
291
+ box-sizing: border-box;
288
292
  }
289
293
 
290
- .sidebar-card dl { display: flex; flex-direction: column; gap: 6px; }
291
- .sidebar-card dl > div { display: flex; flex-direction: column; gap: 1px; }
292
- .sidebar-card dt { font-size: 11px; color: var(--text-muted); }
293
- .sidebar-card dd {
294
+ .side-copy {
295
+ margin: 0;
294
296
  font-size: 13px;
295
- color: var(--text);
296
- overflow: hidden;
297
- text-overflow: ellipsis;
298
- white-space: nowrap;
297
+ color: var(--text-muted);
298
+ line-height: 1.45;
299
299
  }
300
300
 
301
- .sidebar-card ul {
302
- list-style: none;
303
- display: flex;
304
- flex-direction: column;
305
- gap: 8px;
301
+ .eyebrow {
302
+ font-size: 11px;
303
+ font-weight: 650;
304
+ letter-spacing: 0.08em;
305
+ text-transform: uppercase;
306
+ color: var(--fluxy-cta-color);
307
+ margin: 0 0 8px;
306
308
  }
307
- .sidebar-card li { font-size: 13px; color: var(--text-muted); }
308
- .sidebar-card li a { color: var(--accent); }
309
309
 
310
- /* ---- Setup required ---- */
310
+ .signin-card h1 {
311
+ margin: 0 0 8px;
312
+ font-size: 24px;
313
+ }
311
314
 
312
- .setup-card {
313
- margin: auto;
314
- background: var(--surface);
315
- border: 1px solid var(--border);
316
- border-radius: 14px;
317
- padding: 36px 40px;
318
- max-width: 480px;
319
- width: 90%;
320
- display: flex;
321
- flex-direction: column;
322
- gap: 16px;
315
+ .signin-card p {
316
+ color: var(--text-muted);
317
+ font-size: 14px;
318
+ line-height: 1.5;
323
319
  }
324
320
 
325
- .setup-card .logo {
326
- display: flex;
321
+ .btn-primary {
322
+ display: inline-flex;
327
323
  align-items: center;
328
- gap: 8px;
329
- font-weight: 700;
330
- font-size: 16px;
324
+ justify-content: center;
325
+ margin-top: 0;
326
+ background: var(--fluxy-cta-color);
327
+ color: #fff;
328
+ border: none;
329
+ border-radius: 10px;
330
+ padding: 10px 16px;
331
+ font-weight: 600;
332
+ font-size: 14px;
333
+ text-decoration: none;
334
+ cursor: pointer;
335
+ font-family: inherit;
331
336
  }
332
337
 
333
- .setup-card h1 {
334
- font-size: 22px;
335
- font-weight: 700;
338
+ .btn-primary:hover {
339
+ background: #9a3412;
336
340
  }
337
341
 
338
- .setup-card p { color: var(--text-muted); font-size: 14px; }
339
- .setup-card .hint { font-size: 13px; }
340
-
341
- .setup-card pre {
342
- background: var(--surface-2);
343
- border: 1px solid var(--border);
344
- border-radius: 8px;
345
- padding: 14px 16px;
346
- overflow-x: auto;
342
+ .fine-print {
343
+ margin-top: 12px;
344
+ font-size: 12px !important;
347
345
  }
348
346
 
349
- .setup-card code {
350
- font-family: "Fira Code", "Cascadia Code", monospace;
351
- font-size: 13px;
352
- color: var(--text);
353
- line-height: 1.8;
347
+ @media (max-width: 860px) {
348
+ .page {
349
+ grid-template-columns: 1fr;
350
+ }
351
+ .side {
352
+ border-left: none;
353
+ border-top: 1px solid var(--border);
354
+ }
354
355
  }
@@ -0,0 +1,54 @@
1
+ const STORAGE_KEY = "fluxy-cli-session";
2
+
3
+ export interface CliSession {
4
+ workerUrl: string;
5
+ memberJwt: string;
6
+ roomId: string;
7
+ agentId: string;
8
+ agentHandle: string;
9
+ projectId: string;
10
+ userId: string;
11
+ projectName?: string;
12
+ consoleUrl?: string;
13
+ }
14
+
15
+ function isCliSession(value: unknown): value is CliSession {
16
+ if (!value || typeof value !== "object") return false;
17
+ const v = value as Record<string, unknown>;
18
+ return typeof v.memberJwt === "string" && v.memberJwt.length > 0 && typeof v.workerUrl === "string";
19
+ }
20
+
21
+ export function readCliSessionFromHash(): CliSession | null {
22
+ if (typeof window === "undefined") return null;
23
+ const hash = window.location.hash.replace(/^#/, "");
24
+ const raw = new URLSearchParams(hash).get("fluxy_cli") || (hash.startsWith("fluxy_cli=") ? hash.slice("fluxy_cli=".length) : "");
25
+ if (!raw) return null;
26
+ try {
27
+ const parsed = JSON.parse(atob(decodeURIComponent(raw))) as unknown;
28
+ if (!isCliSession(parsed)) return null;
29
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
30
+ return parsed;
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+
36
+ export function loadCliSession(): CliSession | null {
37
+ const fromHash = readCliSessionFromHash();
38
+ if (fromHash) {
39
+ sessionStorage.setItem(STORAGE_KEY, JSON.stringify(fromHash));
40
+ return fromHash;
41
+ }
42
+ try {
43
+ const stored = sessionStorage.getItem(STORAGE_KEY);
44
+ if (!stored) return null;
45
+ const parsed = JSON.parse(stored) as unknown;
46
+ return isCliSession(parsed) ? parsed : null;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ export function clearCliSession() {
53
+ sessionStorage.removeItem(STORAGE_KEY);
54
+ }
@@ -0,0 +1,41 @@
1
+ export default {
2
+ content: [
3
+ "./index.html",
4
+ "./src/**/*.{ts,tsx}",
5
+ "./node_modules/@fluxy-chat/ui/dist/**/*.{js,mjs}",
6
+ ],
7
+ theme: {
8
+ extend: {
9
+ colors: {
10
+ background: "var(--background)",
11
+ foreground: "var(--foreground)",
12
+ border: "var(--border)",
13
+ muted: {
14
+ DEFAULT: "var(--surface-muted)",
15
+ foreground: "var(--text-muted)",
16
+ },
17
+ primary: {
18
+ DEFAULT: "var(--fluxy-cta-color)",
19
+ foreground: "#ffffff",
20
+ },
21
+ secondary: {
22
+ DEFAULT: "var(--surface-muted)",
23
+ foreground: "var(--foreground)",
24
+ },
25
+ card: {
26
+ DEFAULT: "var(--surface-card)",
27
+ foreground: "var(--foreground)",
28
+ },
29
+ destructive: {
30
+ DEFAULT: "var(--destructive)",
31
+ foreground: "#ffffff",
32
+ },
33
+ ring: "var(--ring)",
34
+ },
35
+ borderRadius: {
36
+ lg: "var(--radius)",
37
+ },
38
+ },
39
+ },
40
+ plugins: [],
41
+ };