@heyramzi/ui 3.5.0 → 3.7.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 (45) hide show
  1. package/COMPONENTS.md +1 -0
  2. package/dist/ai/chat-window/icons.js +43 -0
  3. package/dist/ai/chat-window/index.js +5 -0
  4. package/dist/ai/chat-window/labels.js +16 -0
  5. package/dist/ai/chat-window/reveal.svelte.js +106 -0
  6. package/dist/ai/chat-window/types.js +4 -0
  7. package/package.json +1 -1
  8. package/src/ai/chat-window/ChatGlyph.svelte +38 -0
  9. package/src/ai/chat-window/ChatGlyph.svelte.d.ts +9 -0
  10. package/src/ai/chat-window/ChatGptWindow.svelte +636 -0
  11. package/src/ai/chat-window/ChatGptWindow.svelte.d.ts +25 -0
  12. package/src/ai/chat-window/ClaudeWindow.svelte +668 -0
  13. package/src/ai/chat-window/ClaudeWindow.svelte.d.ts +25 -0
  14. package/src/ai/chat-window/chat-window.test.ts +80 -0
  15. package/src/ai/chat-window/icons/LICENSE +24 -0
  16. package/src/ai/chat-window/icons/chatgpt-chevron.svg +2 -0
  17. package/src/ai/chat-window/icons/chatgpt-copy.svg +2 -0
  18. package/src/ai/chat-window/icons/chatgpt-mic.svg +2 -0
  19. package/src/ai/chat-window/icons/chatgpt-more.svg +2 -0
  20. package/src/ai/chat-window/icons/chatgpt-plus.svg +2 -0
  21. package/src/ai/chat-window/icons/chatgpt-regenerate.svg +2 -0
  22. package/src/ai/chat-window/icons/chatgpt-share.svg +2 -0
  23. package/src/ai/chat-window/icons/chatgpt-sidebar.svg +1 -0
  24. package/src/ai/chat-window/icons/chatgpt-thumb.svg +2 -0
  25. package/src/ai/chat-window/icons/chatgpt-voice.svg +2 -0
  26. package/src/ai/chat-window/icons/claude-chevron.svg +1 -0
  27. package/src/ai/chat-window/icons/claude-copy.svg +1 -0
  28. package/src/ai/chat-window/icons/claude-plus.svg +1 -0
  29. package/src/ai/chat-window/icons/claude-retry.svg +1 -0
  30. package/src/ai/chat-window/icons/claude-send.svg +1 -0
  31. package/src/ai/chat-window/icons/claude-sidebar.svg +1 -0
  32. package/src/ai/chat-window/icons/claude-sliders.svg +1 -0
  33. package/src/ai/chat-window/icons/claude-spark.svg +1 -0
  34. package/src/ai/chat-window/icons/claude-thumb.svg +1 -0
  35. package/src/ai/chat-window/icons.ts +46 -0
  36. package/src/ai/chat-window/index.ts +26 -0
  37. package/src/ai/chat-window/labels.ts +39 -0
  38. package/src/ai/chat-window/reveal.svelte.ts +106 -0
  39. package/src/ai/chat-window/types.ts +42 -0
  40. package/src/components/open-in/open-in.svelte +14 -15
  41. package/src/components/open-in/open-in.svelte.d.ts +2 -2
  42. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +39 -15
  43. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte.d.ts +2 -1
  44. package/src/shadcn/sidebar/sidebar-provider.svelte +9 -2
  45. package/src/shadcn/sidebar/sidebar-provider.svelte.d.ts +5 -0
@@ -0,0 +1,636 @@
1
+ <script lang="ts" module>
2
+ import type { ChatGptLabels } from "./labels.js";
3
+ import type { ChatMessage, ChatTheme } from "./types.js";
4
+
5
+ export interface ChatGptWindowProps {
6
+ /** The conversation's name, read out as the picture's label. */
7
+ title: string;
8
+ messages: ChatMessage[];
9
+ /** The picker in the bar. */
10
+ model?: string;
11
+ placeholder?: string;
12
+ theme?: ChatTheme;
13
+ /** Plays the messages in once the window is on screen. Off, it is a still. */
14
+ reveal?: boolean;
15
+ /** With `reveal`, plays each time this turns on, for a rotator. */
16
+ active?: boolean;
17
+ /** Called after the reveal ends and `hold` ms have passed. */
18
+ ondone?: () => void;
19
+ hold?: number;
20
+ /** Draws macOS's traffic lights, as the desktop app. */
21
+ frame?: boolean;
22
+ labels?: Partial<ChatGptLabels>;
23
+ class?: string;
24
+ }
25
+ </script>
26
+
27
+ <script lang="ts">
28
+ // =========================
29
+ // IMPORTS
30
+ // =========================
31
+ import ChatGlyph from "./ChatGlyph.svelte";
32
+ import { CHATGPT_ICONS as I } from "./icons.js";
33
+ import { CHATGPT_LABELS } from "./labels.js";
34
+ import { createReveal } from "./reveal.svelte.js";
35
+ import { fillName } from "./types.js";
36
+
37
+ // =========================
38
+ // PROPS
39
+ // =========================
40
+ let {
41
+ title,
42
+ messages,
43
+ model = "ChatGPT",
44
+ placeholder = "Ask anything",
45
+ theme = "auto",
46
+ reveal = false,
47
+ active = true,
48
+ ondone,
49
+ hold = 4000,
50
+ frame = true,
51
+ labels = {},
52
+ class: className = "",
53
+ }: ChatGptWindowProps = $props();
54
+
55
+ // =========================
56
+ // STATE
57
+ // =========================
58
+ const text = $derived({ ...CHATGPT_LABELS, ...labels });
59
+ const lastAssistant = $derived(messages.findLastIndex((m) => m.role === "assistant"));
60
+ const player = createReveal(() => ({
61
+ roles: messages.map((m) => m.role),
62
+ enabled: reveal,
63
+ active,
64
+ hold,
65
+ ondone,
66
+ }));
67
+ </script>
68
+
69
+ <!-- =========================== -->
70
+ <!-- MARKUP -->
71
+ <!-- =========================== -->
72
+ <figure
73
+ class="gpt {className}"
74
+ data-mode={theme}
75
+ aria-label="ChatGPT: {title}"
76
+ style:--gpt-stream="{player.streamMs}ms"
77
+ {@attach player.attach}
78
+ >
79
+ <div class="bar" aria-hidden="true">
80
+ {#if frame}
81
+ <span class="lights"><i></i><i></i><i></i></span>
82
+ {/if}
83
+ <span class="ib"><ChatGlyph src={I.sidebar} /></span>
84
+ <span class="model"
85
+ >{model}<span class="dim"><ChatGlyph src={I.chevron} size={16} /></span></span
86
+ >
87
+ <span class="share wide"><ChatGlyph src={I.share} />{text.share}</span>
88
+ <span class="ib end"><ChatGlyph src={I.more} /></span>
89
+ </div>
90
+
91
+ <div class="scroll">
92
+ <ol class="thread">
93
+ {#each messages as message, i (i)}
94
+ {@const phase = player.phase(i)}
95
+ <li class="turn {message.role}" data-phase={phase}>
96
+ {#if message.role === "user"}
97
+ <span class="vh">{text.userSaid}</span>
98
+ <p class="bubble">{message.text}</p>
99
+ {:else if message.role === "assistant"}
100
+ <span class="think" aria-hidden="true"></span>
101
+ <div class="reply">
102
+ <span class="vh">{text.assistantSaid}</span>
103
+ {#if message.content}
104
+ {@render message.content()}
105
+ {:else if message.text}
106
+ <p>{message.text}</p>
107
+ {/if}
108
+ </div>
109
+ {#if i === lastAssistant}
110
+ <div class="actions" aria-hidden="true">
111
+ <span class="ab"><ChatGlyph src={I.copy} /></span>
112
+ <span class="ab"><ChatGlyph src={I.thumb} /></span>
113
+ <span class="ab flip"><ChatGlyph src={I.thumb} /></span>
114
+ <span class="ab"><ChatGlyph src={I.share} /></span>
115
+ <span class="ab wide"><ChatGlyph src={I.regenerate} /></span>
116
+ <span class="ab"><ChatGlyph src={I.more} /></span>
117
+ </div>
118
+ {/if}
119
+ {:else}
120
+ <!-- An app call, as ChatGPT draws one between two parts of a reply: its label shimmers while it runs. -->
121
+ <p class="call">
122
+ <span class="tool-icon" aria-hidden="true">
123
+ {#if message.icon}
124
+ {@render message.icon()}
125
+ {:else if message.iconSrc}
126
+ <img src={message.iconSrc} alt="" width="20" height="20" />
127
+ {:else}
128
+ <span class="tool-letter">{message.name.slice(0, 1)}</span>
129
+ {/if}
130
+ </span>
131
+ <span class="tool-text">
132
+ {fillName(phase === "running" ? text.running : text.done, message.name)}
133
+ </span>
134
+ {#if message.label}
135
+ <span class="tool-label">{message.label}</span>
136
+ {/if}
137
+ <span class="tool-chev" aria-hidden="true"
138
+ ><ChatGlyph src={I.chevron} size={16} /></span
139
+ >
140
+ </p>
141
+ {/if}
142
+ </li>
143
+ {/each}
144
+ </ol>
145
+ </div>
146
+
147
+ <div class="dock" aria-hidden="true">
148
+ <div class="composer">
149
+ <span class="ib round"><ChatGlyph src={I.plus} size={22} /></span>
150
+ <span class="prompt">{placeholder}</span>
151
+ <span class="ib round wide"><ChatGlyph src={I.mic} /></span>
152
+ <span class="voice"><ChatGlyph src={I.voice} /></span>
153
+ </div>
154
+ <span class="note">{text.disclaimer}</span>
155
+ </div>
156
+ </figure>
157
+
158
+ <style>
159
+ @layer theme, base, components, utilities;
160
+
161
+ @layer components {
162
+ /* chatgpt.com's signed-in tokens, measured 11 Nov 2026. A connector needs an account, so this is the screen its users see. */
163
+ .gpt {
164
+ --gpt-bg: light-dark(#ffffff, #212121);
165
+ --gpt-bar: light-dark(#ffffff, #212121);
166
+ --gpt-bubble: light-dark(#f4f4f4, #303030);
167
+ --gpt-ink: light-dark(#0d0d0d, #ffffff);
168
+ --gpt-soft: light-dark(#5d5d5d, #afafaf);
169
+ --gpt-faint: light-dark(#767676, #979797);
170
+ --gpt-line: light-dark(rgb(13 13 13 / 0.07), rgb(255 255 255 / 0.1));
171
+ --gpt-rim: light-dark(rgb(0 0 0 / 0.1), rgb(255 255 255 / 0.12));
172
+ --gpt-composer: light-dark(#ffffff, #303030);
173
+ --gpt-solid: light-dark(#000000, #ffffff);
174
+ --gpt-on-solid: light-dark(#ffffff, #000000);
175
+ --gpt-letter: light-dark(#e8e8e8, #424242);
176
+
177
+ all: initial;
178
+ box-sizing: border-box;
179
+ display: grid;
180
+ grid-template-rows: auto minmax(0, 1fr) auto;
181
+ grid-template-columns: minmax(0, 1fr);
182
+ width: 100%;
183
+ height: 100%;
184
+ margin: 0;
185
+ container-type: inline-size;
186
+ overflow: hidden;
187
+ color-scheme: inherit;
188
+ /* The Mac window's 12px corner, not a kit role: it is the product's own. */
189
+ border-radius: 12px;
190
+ background: var(--gpt-bg);
191
+ color: var(--gpt-ink);
192
+ box-shadow:
193
+ 0 0 0 1px var(--gpt-rim),
194
+ var(--elev-overlay);
195
+ font-family:
196
+ ui-sans-serif,
197
+ -apple-system,
198
+ system-ui,
199
+ "Segoe UI",
200
+ Helvetica,
201
+ Arial,
202
+ sans-serif;
203
+ font-size: 16px;
204
+ line-height: 1.5;
205
+ text-align: left;
206
+ -webkit-font-smoothing: antialiased;
207
+ -moz-osx-font-smoothing: grayscale;
208
+ user-select: none;
209
+ }
210
+
211
+ .gpt[data-mode="light"] {
212
+ color-scheme: light;
213
+ }
214
+
215
+ .gpt[data-mode="dark"],
216
+ :global(.dark) .gpt[data-mode="auto"],
217
+ :global([data-theme="dark"]) .gpt[data-mode="auto"] {
218
+ color-scheme: dark;
219
+ }
220
+
221
+ :global([data-theme="light"]) .gpt[data-mode="auto"] {
222
+ color-scheme: light;
223
+ }
224
+
225
+ .gpt *,
226
+ .gpt *::before,
227
+ .gpt *::after {
228
+ box-sizing: border-box;
229
+ }
230
+
231
+ .vh {
232
+ position: absolute;
233
+ width: 1px;
234
+ height: 1px;
235
+ overflow: hidden;
236
+ clip-path: inset(50%);
237
+ white-space: nowrap;
238
+ }
239
+
240
+ /* A fake icon button: a span, so no site button style reaches it and nothing takes focus. */
241
+ .ib {
242
+ display: grid;
243
+ place-items: center;
244
+ flex: none;
245
+ width: 36px;
246
+ height: 36px;
247
+ border-radius: 10px;
248
+ color: var(--gpt-ink);
249
+ }
250
+
251
+ .round {
252
+ border-radius: 50%;
253
+ }
254
+
255
+ /* ---------- the bar ---------- */
256
+ .bar {
257
+ display: flex;
258
+ align-items: center;
259
+ gap: 2px;
260
+ height: 52px;
261
+ padding: 0 8px 0 14px;
262
+ background: var(--gpt-bar);
263
+ }
264
+
265
+ .lights {
266
+ display: flex;
267
+ gap: 8px;
268
+ margin-right: 12px;
269
+ }
270
+
271
+ .lights i {
272
+ width: 12px;
273
+ height: 12px;
274
+ border-radius: 50%;
275
+ background: #ff5f57;
276
+ box-shadow: inset 0 0 0 0.5px rgb(0 0 0 / 0.18);
277
+ }
278
+
279
+ .lights i:nth-child(2) {
280
+ background: #febc2e;
281
+ }
282
+
283
+ .lights i:nth-child(3) {
284
+ background: #28c840;
285
+ }
286
+
287
+ .model {
288
+ display: inline-flex;
289
+ align-items: center;
290
+ gap: 4px;
291
+ min-width: 0;
292
+ height: 36px;
293
+ padding: 0 8px;
294
+ font-size: 18px;
295
+ margin-right: auto;
296
+ line-height: 1.5556;
297
+ white-space: nowrap;
298
+ }
299
+
300
+ .dim {
301
+ color: var(--gpt-soft);
302
+ }
303
+
304
+ .share {
305
+ display: inline-flex;
306
+ align-items: center;
307
+ gap: 6px;
308
+ height: 36px;
309
+ padding: 0 12px 0 10px;
310
+ border-radius: 999px;
311
+ font-size: 14px;
312
+ font-weight: 500;
313
+ }
314
+
315
+ /* ---------- the conversation ---------- */
316
+ /* End-aligned: a chat sits scrolled to its newest turn, so a short window crops the top, never the composer. */
317
+ .scroll {
318
+ display: flex;
319
+ flex-direction: column;
320
+ justify-content: flex-end;
321
+ min-height: 0;
322
+ overflow: hidden;
323
+ }
324
+
325
+ .thread {
326
+ display: grid;
327
+ gap: 24px;
328
+ width: 100%;
329
+ max-width: 768px;
330
+ margin: 0 auto;
331
+ padding: 12px clamp(16px, 5cqi, 32px) 20px;
332
+ list-style: none;
333
+ }
334
+
335
+ .turn {
336
+ display: grid;
337
+ min-width: 0;
338
+ }
339
+
340
+ .user {
341
+ justify-items: end;
342
+ }
343
+
344
+ .bubble {
345
+ max-width: 70%;
346
+ margin: 0;
347
+ padding: 10px 16px;
348
+ border-radius: 22px;
349
+ background: var(--gpt-bubble);
350
+ overflow-wrap: anywhere;
351
+ white-space: pre-wrap;
352
+ }
353
+
354
+ /* The reply and the thinking dot share one cell, so the dot never pushes the reply down. */
355
+ .assistant > .think,
356
+ .assistant > .reply {
357
+ grid-area: 1 / 1;
358
+ }
359
+
360
+ .think {
361
+ align-self: start;
362
+ width: 12px;
363
+ height: 12px;
364
+ margin: 8px 0 0 2px;
365
+ border-radius: 50%;
366
+ background: var(--gpt-ink);
367
+ opacity: 0;
368
+ }
369
+
370
+ .reply {
371
+ display: grid;
372
+ gap: 16px;
373
+ min-width: 0;
374
+ line-height: 1.75;
375
+ overflow-wrap: anywhere;
376
+ }
377
+
378
+ /* What a site renders in the snippet takes ChatGPT's markdown look. */
379
+ .reply :global(:is(p, ul, ol, h3, table)) {
380
+ margin: 0;
381
+ }
382
+
383
+ .reply :global(:is(ul, ol)) {
384
+ padding-left: 1.5em;
385
+ }
386
+
387
+ .reply :global(:is(strong, b, h3, th)) {
388
+ font-weight: 600;
389
+ }
390
+
391
+ .reply :global(h3) {
392
+ font-size: 18px;
393
+ }
394
+
395
+ .reply :global(table) {
396
+ width: 100%;
397
+ border-collapse: collapse;
398
+ font-size: 14px;
399
+ line-height: 1.5;
400
+ font-variant-numeric: tabular-nums;
401
+ }
402
+
403
+ .reply :global(:is(th, td)) {
404
+ padding: 8px 8px 8px 0;
405
+ border-bottom: 1px solid var(--gpt-line);
406
+ text-align: left;
407
+ }
408
+
409
+ .reply :global(tr:last-child td) {
410
+ border-bottom: 0;
411
+ }
412
+
413
+ .actions {
414
+ display: flex;
415
+ margin: 6px 0 0 -8px;
416
+ }
417
+
418
+ .ab {
419
+ display: grid;
420
+ place-items: center;
421
+ width: 32px;
422
+ height: 32px;
423
+ border-radius: 8px;
424
+ color: var(--gpt-soft);
425
+ }
426
+
427
+ .flip {
428
+ scale: 1 -1;
429
+ }
430
+
431
+ .call {
432
+ display: flex;
433
+ align-items: center;
434
+ gap: 8px;
435
+ min-width: 0;
436
+ margin: 0;
437
+ font-size: 14px;
438
+ line-height: 1.4286;
439
+ color: var(--gpt-soft);
440
+ }
441
+
442
+ .tool-icon {
443
+ display: grid;
444
+ place-items: center;
445
+ flex: none;
446
+ width: 20px;
447
+ height: 20px;
448
+ overflow: hidden;
449
+ border-radius: 6px;
450
+ }
451
+
452
+ .tool-icon img {
453
+ display: block;
454
+ width: 100%;
455
+ height: 100%;
456
+ object-fit: cover;
457
+ }
458
+
459
+ .tool-letter {
460
+ display: grid;
461
+ place-items: center;
462
+ width: 100%;
463
+ height: 100%;
464
+ background: var(--gpt-letter);
465
+ color: var(--gpt-ink);
466
+ font-size: 12px;
467
+ font-weight: 600;
468
+ }
469
+
470
+ .tool-text {
471
+ flex: none;
472
+ font-weight: 500;
473
+ color: var(--gpt-ink);
474
+ }
475
+
476
+ .tool-label {
477
+ min-width: 0;
478
+ overflow: hidden;
479
+ white-space: nowrap;
480
+ text-overflow: ellipsis;
481
+ }
482
+
483
+ .tool-chev {
484
+ flex: none;
485
+ margin-left: -2px;
486
+ rotate: -90deg;
487
+ }
488
+
489
+ /* ---------- the composer ---------- */
490
+ .dock {
491
+ display: grid;
492
+ grid-template-columns: minmax(0, 1fr);
493
+ justify-items: center;
494
+ gap: 8px;
495
+ padding: 0 clamp(12px, 4cqi, 24px) 10px;
496
+ }
497
+
498
+ .composer {
499
+ display: flex;
500
+ align-items: center;
501
+ gap: 4px;
502
+ width: 100%;
503
+ max-width: 768px;
504
+ min-height: 52px;
505
+ padding: 6px 8px 6px 6px;
506
+ border-radius: 28px;
507
+ background: var(--gpt-composer);
508
+ box-shadow:
509
+ 0 0 0 1px light-dark(rgb(0 0 0 / 0.04), transparent),
510
+ 0 2px 8px light-dark(rgb(0 0 0 / 0.04), transparent),
511
+ 0 4px 80px 8px light-dark(rgb(0 0 0 / 0.024), transparent),
512
+ inset 0 0 1px light-dark(transparent, rgb(255 255 255 / 0.2));
513
+ color: var(--gpt-faint);
514
+ }
515
+
516
+ .prompt {
517
+ flex: 1;
518
+ min-width: 0;
519
+ padding-left: 4px;
520
+ overflow: hidden;
521
+ white-space: nowrap;
522
+ text-overflow: ellipsis;
523
+ }
524
+
525
+ .voice {
526
+ display: grid;
527
+ place-items: center;
528
+ flex: none;
529
+ width: 36px;
530
+ height: 36px;
531
+ border-radius: 50%;
532
+ background: var(--gpt-solid);
533
+ color: var(--gpt-on-solid);
534
+ }
535
+
536
+ .note {
537
+ font-size: 12px;
538
+ line-height: 1.3333;
539
+ color: var(--gpt-soft);
540
+ text-align: center;
541
+ }
542
+
543
+ /* At phone width the app drops its secondary controls and the disclaimer. */
544
+ @container (width < 460px) {
545
+ .wide,
546
+ .note,
547
+ .lights {
548
+ display: none;
549
+ }
550
+
551
+ .bubble {
552
+ max-width: 85%;
553
+ }
554
+
555
+ .dock {
556
+ padding-bottom: 12px;
557
+ }
558
+ }
559
+
560
+ /* ---------- the reveal: only opacity, a short rise and a mask move, so nothing reflows ---------- */
561
+ .turn > *,
562
+ .tool-text {
563
+ transition:
564
+ opacity var(--duration-fast) var(--ease-smooth-out),
565
+ translate var(--duration-fast) var(--ease-smooth-out);
566
+ }
567
+
568
+ .turn[data-phase="hidden"] > *,
569
+ .turn[data-phase="thinking"] > :not(.think) {
570
+ opacity: 0;
571
+ translate: 0 6px;
572
+ }
573
+
574
+ .turn[data-phase="thinking"] > .think {
575
+ opacity: 1;
576
+ translate: none;
577
+ animation: gpt-pulse calc(var(--duration-overlay) * 2.4) var(--ease-in-out) infinite;
578
+ }
579
+
580
+ .turn[data-phase="streaming"] > :is(.reply, .actions) {
581
+ animation: gpt-stream var(--gpt-stream) var(--ease-linear) both;
582
+ }
583
+
584
+ .turn[data-phase="streaming"] > .actions {
585
+ opacity: 0;
586
+ }
587
+
588
+ .reply,
589
+ .actions {
590
+ mask-image: linear-gradient(to bottom, #000 40%, transparent 60%);
591
+ mask-size: 100% 250%;
592
+ mask-position: 0 0;
593
+ }
594
+
595
+ /* The label keeps its colour; a dimmer band sweeps through it by mask. */
596
+ .turn[data-phase="running"] .tool-text {
597
+ mask-image: linear-gradient(100deg, #000 40%, rgb(0 0 0 / 0.4) 50%, #000 60%);
598
+ mask-size: 300% 100%;
599
+ animation: gpt-shimmer calc(var(--duration-overlay) * 3) var(--ease-linear) infinite;
600
+ }
601
+
602
+ @keyframes gpt-pulse {
603
+ 50% {
604
+ scale: 0.7;
605
+ }
606
+ }
607
+
608
+ @keyframes gpt-stream {
609
+ from {
610
+ mask-position: 0 100%;
611
+ }
612
+ to {
613
+ mask-position: 0 0;
614
+ }
615
+ }
616
+
617
+ @keyframes gpt-shimmer {
618
+ from {
619
+ mask-position: 100% 0;
620
+ }
621
+ to {
622
+ mask-position: 0 0;
623
+ }
624
+ }
625
+
626
+ @media (prefers-reduced-motion: reduce) {
627
+ .turn > *,
628
+ .tool-text,
629
+ .turn[data-phase] > *,
630
+ .turn[data-phase] .tool-text {
631
+ transition: none;
632
+ animation: none;
633
+ }
634
+ }
635
+ }
636
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { ChatGptLabels } from "./labels.js";
2
+ import type { ChatMessage, ChatTheme } from "./types.js";
3
+ export interface ChatGptWindowProps {
4
+ /** The conversation's name, read out as the picture's label. */
5
+ title: string;
6
+ messages: ChatMessage[];
7
+ /** The picker in the bar. */
8
+ model?: string;
9
+ placeholder?: string;
10
+ theme?: ChatTheme;
11
+ /** Plays the messages in once the window is on screen. Off, it is a still. */
12
+ reveal?: boolean;
13
+ /** With `reveal`, plays each time this turns on, for a rotator. */
14
+ active?: boolean;
15
+ /** Called after the reveal ends and `hold` ms have passed. */
16
+ ondone?: () => void;
17
+ hold?: number;
18
+ /** Draws macOS's traffic lights, as the desktop app. */
19
+ frame?: boolean;
20
+ labels?: Partial<ChatGptLabels>;
21
+ class?: string;
22
+ }
23
+ declare const $$Component: import("svelte").Component<ChatGptWindowProps, {}, "">;
24
+ type $$Component = ReturnType<typeof $$Component>;
25
+ export default $$Component;