@tulipfarm/sprout 0.2.0 → 0.3.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.
@@ -0,0 +1,529 @@
1
+ @layer base {
2
+ /* React Flow puts .light or .dark on its root. Base outranks components, so
3
+ this lives here to keep the page's tokens inside the graph. */
4
+ .sprout-agent-fanout-flow.light,
5
+ .sprout-agent-fanout-flow.dark {
6
+ --sprout-surface: inherit;
7
+ --sprout-hover: inherit;
8
+ --sprout-text: inherit;
9
+ --sprout-muted: inherit;
10
+ --sprout-line: inherit;
11
+ --sprout-border: inherit;
12
+ --sprout-primary: inherit;
13
+ --sprout-on-primary: inherit;
14
+ --sprout-danger: inherit;
15
+ --sprout-danger-subtle: inherit;
16
+ --sprout-chart-1: inherit;
17
+ --sprout-chart-2: inherit;
18
+ --sprout-chart-3: inherit;
19
+ --sprout-chart-4: inherit;
20
+ --sprout-chart-5: inherit;
21
+ }
22
+ }
23
+
24
+ @layer components {
25
+ .sprout-agent-fanout {
26
+ --sprout-agent-fanout-trip: 720ms;
27
+ --sprout-agent-fanout-trip-ease: cubic-bezier(0.5, 0, 0.2, 1);
28
+ container-type: inline-size;
29
+ box-sizing: border-box;
30
+ width: 100%;
31
+ min-width: 0;
32
+ overflow: hidden;
33
+ border: 1px solid var(--sprout-line);
34
+ border-radius: var(--sprout-radius-panel);
35
+ background: var(--sprout-surface);
36
+ color: var(--sprout-text);
37
+ font-family: var(--sprout-font);
38
+ }
39
+
40
+ .sprout-agent-fanout-task {
41
+ display: flex;
42
+ min-width: 0;
43
+ padding: 12px 16px;
44
+ border-bottom: 1px solid var(--sprout-line);
45
+ }
46
+ .sprout-agent-fanout-task-text {
47
+ min-width: 0;
48
+ font-size: var(--sprout-text-sm);
49
+ font-weight: 500;
50
+ line-height: 1.25rem;
51
+ overflow-wrap: anywhere;
52
+ }
53
+
54
+ .sprout-agent-fanout-graph {
55
+ position: relative;
56
+ }
57
+
58
+ /* The structural rules React Flow needs, scoped to the graph. */
59
+ .sprout-agent-fanout-flow {
60
+ position: relative;
61
+ direction: ltr;
62
+ width: 100%;
63
+ height: 100%;
64
+ overflow: hidden;
65
+ pointer-events: none;
66
+ }
67
+ .sprout-agent-fanout-flow .react-flow__container,
68
+ .sprout-agent-fanout-flow .react-flow__edgelabel-renderer {
69
+ position: absolute;
70
+ top: 0;
71
+ left: 0;
72
+ width: 100%;
73
+ height: 100%;
74
+ }
75
+ .sprout-agent-fanout-flow .react-flow__viewport,
76
+ .sprout-agent-fanout-flow .react-flow__nodes,
77
+ .sprout-agent-fanout-flow .react-flow__node {
78
+ transform-origin: 0 0;
79
+ }
80
+ .sprout-agent-fanout-flow .react-flow__edges svg {
81
+ position: absolute;
82
+ overflow: visible;
83
+ fill: none;
84
+ }
85
+ .sprout-agent-fanout-flow .react-flow__node {
86
+ position: absolute;
87
+ box-sizing: border-box;
88
+ }
89
+ .sprout-agent-fanout-handle.react-flow__handle {
90
+ position: absolute;
91
+ left: 50%;
92
+ width: 1px;
93
+ height: 1px;
94
+ min-width: 0;
95
+ min-height: 0;
96
+ border: 0;
97
+ opacity: 0;
98
+ translate: -50% 0;
99
+ }
100
+ .sprout-agent-fanout-handle.react-flow__handle-top {
101
+ top: 0;
102
+ }
103
+ .sprout-agent-fanout-handle.react-flow__handle-bottom {
104
+ bottom: 0;
105
+ }
106
+
107
+ .sprout-agent-fanout-edge {
108
+ stroke: var(--sprout-line);
109
+ stroke-width: 1;
110
+ }
111
+ .sprout-agent-fanout-trail {
112
+ stroke: var(--sprout-agent-fanout-color);
113
+ stroke-width: 2.5;
114
+ stroke-linecap: round;
115
+ stroke-dasharray: 0.3 2;
116
+ stroke-dashoffset: 0.3;
117
+ opacity: 0;
118
+ }
119
+ .sprout-agent-fanout-comet {
120
+ position: absolute;
121
+ top: 0;
122
+ left: 0;
123
+ width: 8px;
124
+ height: 8px;
125
+ border-radius: 50%;
126
+ background: var(--sprout-agent-fanout-color);
127
+ offset-rotate: 0deg;
128
+ opacity: 0;
129
+ pointer-events: none;
130
+ }
131
+
132
+ .sprout-agent-fanout-root {
133
+ position: relative;
134
+ display: grid;
135
+ place-items: center;
136
+ width: 44px;
137
+ height: 44px;
138
+ border-radius: 50%;
139
+ background: var(--sprout-primary);
140
+ color: var(--sprout-on-primary);
141
+ }
142
+ .sprout-agent-fanout-root[data-state="stopped"] {
143
+ background: var(--sprout-hover);
144
+ color: var(--sprout-muted);
145
+ box-shadow: inset 0 0 0 1px var(--sprout-line);
146
+ }
147
+
148
+ .sprout-agent-fanout-node {
149
+ display: flex;
150
+ flex-direction: column;
151
+ align-items: center;
152
+ gap: 6px;
153
+ width: 100%;
154
+ min-width: 0;
155
+ }
156
+ .sprout-agent-fanout-dot {
157
+ position: relative;
158
+ display: grid;
159
+ place-items: center;
160
+ box-sizing: border-box;
161
+ width: var(--sprout-agent-fanout-dot);
162
+ height: var(--sprout-agent-fanout-dot);
163
+ border: 1px solid var(--sprout-line);
164
+ border-radius: 50%;
165
+ background: var(--sprout-surface);
166
+ color: var(--sprout-muted);
167
+ }
168
+ .sprout-agent-fanout-dot > span {
169
+ display: contents;
170
+ }
171
+ .sprout-agent-fanout-dot::before {
172
+ position: absolute;
173
+ z-index: -1;
174
+ inset: calc(var(--sprout-agent-fanout-dot) * -0.27);
175
+ border-radius: 50%;
176
+ background: color-mix(
177
+ in oklab,
178
+ var(--sprout-agent-fanout-color) 14%,
179
+ transparent
180
+ );
181
+ content: "";
182
+ opacity: 0;
183
+ }
184
+ .sprout-agent-fanout-node {
185
+ isolation: isolate;
186
+ }
187
+ .sprout-agent-fanout-node[data-status="queued"] .sprout-agent-fanout-dot {
188
+ color: color-mix(in oklab, var(--sprout-muted) 70%, var(--sprout-surface));
189
+ }
190
+ .sprout-agent-fanout-node[data-status="working"] .sprout-agent-fanout-dot {
191
+ border-color: var(--sprout-agent-fanout-color);
192
+ background: color-mix(
193
+ in oklab,
194
+ var(--sprout-agent-fanout-color) 6%,
195
+ var(--sprout-surface)
196
+ );
197
+ color: color-mix(
198
+ in oklab,
199
+ var(--sprout-agent-fanout-color) 78%,
200
+ var(--sprout-text)
201
+ );
202
+ }
203
+ .sprout-agent-fanout-node[data-status="working"]
204
+ .sprout-agent-fanout-dot::before {
205
+ opacity: 1;
206
+ }
207
+ .sprout-agent-fanout-node[data-status="done"] .sprout-agent-fanout-dot {
208
+ border-color: var(--sprout-agent-fanout-color);
209
+ background: var(--sprout-agent-fanout-color);
210
+ color: var(--sprout-surface);
211
+ }
212
+ .sprout-agent-fanout-node[data-status="failed"] .sprout-agent-fanout-dot {
213
+ border-color: var(--sprout-danger);
214
+ background: var(--sprout-danger-subtle);
215
+ color: var(--sprout-danger);
216
+ }
217
+ .sprout-agent-fanout-node[data-status="stopped"] .sprout-agent-fanout-dot {
218
+ border-color: var(--sprout-border);
219
+ opacity: 0.6;
220
+ }
221
+ .sprout-agent-fanout-node-name {
222
+ max-width: calc(100% - 8px);
223
+ overflow: hidden;
224
+ color: var(--sprout-muted);
225
+ font-size: var(--sprout-text-xs);
226
+ line-height: 1rem;
227
+ text-overflow: ellipsis;
228
+ white-space: nowrap;
229
+ }
230
+
231
+ .sprout-agent-fanout-details {
232
+ border-top: 1px solid var(--sprout-line);
233
+ }
234
+ .sprout-agent-fanout-trigger {
235
+ display: flex;
236
+ align-items: center;
237
+ gap: 8px;
238
+ box-sizing: border-box;
239
+ width: 100%;
240
+ min-height: 40px;
241
+ padding: 0 16px;
242
+ border: 0;
243
+ background: transparent;
244
+ color: var(--sprout-muted);
245
+ font: inherit;
246
+ font-size: var(--sprout-text-sm);
247
+ text-align: start;
248
+ cursor: pointer;
249
+ }
250
+ .sprout-agent-fanout-trigger:hover {
251
+ background: var(--sprout-hover);
252
+ color: var(--sprout-text);
253
+ }
254
+ .sprout-agent-fanout-trigger:focus-visible {
255
+ outline: var(--sprout-focus-width) solid var(--sprout-focus-ring);
256
+ outline-offset: -2px;
257
+ }
258
+ .sprout-agent-fanout-trigger-label {
259
+ font-weight: 500;
260
+ }
261
+ .sprout-agent-fanout-trigger-count {
262
+ flex: 1;
263
+ font-size: var(--sprout-text-xs);
264
+ font-variant-numeric: tabular-nums;
265
+ }
266
+
267
+ .sprout-agent-fanout-rows {
268
+ margin: 0;
269
+ padding: 0;
270
+ list-style: none;
271
+ }
272
+ .sprout-agent-fanout-row {
273
+ display: grid;
274
+ grid-template-columns: minmax(0, 8rem) minmax(0, 1fr) auto;
275
+ align-items: baseline;
276
+ gap: 12px;
277
+ padding: 11px 16px;
278
+ border-top: 1px solid var(--sprout-line);
279
+ font-size: var(--sprout-text-sm);
280
+ line-height: 1.25rem;
281
+ }
282
+ .sprout-agent-fanout-row-name {
283
+ padding-inline-start: calc(var(--sprout-agent-fanout-depth, 0) * 12px);
284
+ overflow: hidden;
285
+ font-weight: 500;
286
+ text-overflow: ellipsis;
287
+ white-space: nowrap;
288
+ }
289
+ .sprout-agent-fanout-row-detail {
290
+ overflow: hidden;
291
+ color: var(--sprout-muted);
292
+ text-overflow: ellipsis;
293
+ white-space: nowrap;
294
+ }
295
+ .sprout-agent-fanout-row-status {
296
+ display: inline-flex;
297
+ align-items: center;
298
+ gap: 6px;
299
+ color: var(--sprout-muted);
300
+ font-size: var(--sprout-text-xs);
301
+ font-variant-numeric: tabular-nums;
302
+ white-space: nowrap;
303
+ }
304
+ .sprout-agent-fanout-row[data-status="working"]
305
+ .sprout-agent-fanout-row-status {
306
+ color: color-mix(
307
+ in oklab,
308
+ var(--sprout-agent-fanout-color) 72%,
309
+ var(--sprout-text)
310
+ );
311
+ }
312
+ .sprout-agent-fanout-row[data-status="done"] .sprout-agent-fanout-row-status {
313
+ color: var(--sprout-text);
314
+ }
315
+ .sprout-agent-fanout-row[data-status="failed"]
316
+ .sprout-agent-fanout-row-status {
317
+ color: var(--sprout-danger);
318
+ }
319
+ .sprout-agent-fanout-pulse {
320
+ width: 6px;
321
+ height: 6px;
322
+ border-radius: 50%;
323
+ background: var(--sprout-agent-fanout-color);
324
+ }
325
+
326
+ .sprout-agent-fanout-footer {
327
+ display: flex;
328
+ align-items: center;
329
+ justify-content: space-between;
330
+ gap: 12px;
331
+ padding: 8px 8px 8px 16px;
332
+ border-top: 1px solid var(--sprout-line);
333
+ background: color-mix(in oklab, var(--sprout-hover) 50%, transparent);
334
+ }
335
+ .sprout-agent-fanout-phase {
336
+ display: flex;
337
+ align-items: baseline;
338
+ gap: 8px;
339
+ min-width: 0;
340
+ margin: 0;
341
+ color: var(--sprout-muted);
342
+ font-size: var(--sprout-text-sm);
343
+ line-height: 1.25rem;
344
+ }
345
+ .sprout-agent-fanout-time {
346
+ font-size: var(--sprout-text-xs);
347
+ font-variant-numeric: tabular-nums;
348
+ }
349
+ .sprout-agent-fanout-action {
350
+ flex-shrink: 0;
351
+ }
352
+
353
+ @container (max-width: 420px) {
354
+ .sprout-agent-fanout-row {
355
+ grid-template-columns: minmax(0, 5.5rem) minmax(0, 1fr) auto;
356
+ gap: 8px;
357
+ padding-inline: 12px;
358
+ }
359
+ .sprout-agent-fanout-task,
360
+ .sprout-agent-fanout-trigger {
361
+ padding-inline: 12px;
362
+ }
363
+ }
364
+
365
+ @media (prefers-reduced-motion: no-preference) {
366
+ .sprout-agent-fanout-trail[data-trip="out"] {
367
+ animation: sprout-agent-fanout-out var(--sprout-agent-fanout-trip)
368
+ var(--sprout-agent-fanout-trip-ease) both;
369
+ }
370
+ .sprout-agent-fanout-trail[data-trip="back"] {
371
+ animation: sprout-agent-fanout-back var(--sprout-agent-fanout-trip)
372
+ var(--sprout-agent-fanout-trip-ease) both;
373
+ }
374
+ .sprout-agent-fanout-comet[data-trip="out"] {
375
+ animation: sprout-agent-fanout-comet-out var(--sprout-agent-fanout-trip)
376
+ var(--sprout-agent-fanout-trip-ease) both;
377
+ }
378
+ .sprout-agent-fanout-comet[data-trip="back"] {
379
+ animation: sprout-agent-fanout-comet-back var(--sprout-agent-fanout-trip)
380
+ var(--sprout-agent-fanout-trip-ease) both;
381
+ }
382
+
383
+ .sprout-agent-fanout-dot,
384
+ .sprout-agent-fanout-dot::before {
385
+ transition:
386
+ background-color 240ms var(--sprout-motion-ease),
387
+ border-color 240ms var(--sprout-motion-ease),
388
+ color 240ms var(--sprout-motion-ease),
389
+ opacity 240ms var(--sprout-motion-ease);
390
+ }
391
+ /* The node lights up when the pulse lands, not when it leaves. */
392
+ .sprout-agent-fanout-node[data-status="working"][data-changed]
393
+ .sprout-agent-fanout-dot,
394
+ .sprout-agent-fanout-node[data-status="working"][data-changed]
395
+ .sprout-agent-fanout-dot::before {
396
+ transition-delay: calc(var(--sprout-agent-fanout-trip) * 0.85);
397
+ }
398
+ .sprout-agent-fanout-node[data-status="working"]
399
+ .sprout-agent-fanout-dot::before {
400
+ animation: sprout-agent-fanout-breathe 1.6s ease-in-out infinite alternate;
401
+ animation-delay: calc(var(--sprout-agent-fanout-index) * -0.55s);
402
+ }
403
+ .sprout-agent-fanout-node[data-status="done"][data-changed]
404
+ .sprout-agent-fanout-dot {
405
+ animation: sprout-agent-fanout-pop 420ms var(--sprout-motion-ease);
406
+ }
407
+ .sprout-agent-fanout-root[data-changed] {
408
+ animation: sprout-agent-fanout-ring 900ms var(--sprout-motion-ease);
409
+ }
410
+ .sprout-agent-fanout-root[data-changed] > svg {
411
+ animation: sprout-agent-fanout-pop 420ms var(--sprout-motion-ease);
412
+ }
413
+ .sprout-agent-fanout-pulse {
414
+ animation: sprout-agent-fanout-pulse 1.4s ease-out infinite;
415
+ }
416
+ .sprout-agent-fanout-row-detail[data-changed],
417
+ .sprout-agent-fanout-row-status[data-changed] {
418
+ animation: sprout-agent-fanout-enter 320ms var(--sprout-motion-ease) both;
419
+ }
420
+ }
421
+
422
+ @media (forced-colors: active) {
423
+ .sprout-agent-fanout-edge,
424
+ .sprout-agent-fanout-trail {
425
+ stroke: CanvasText;
426
+ }
427
+ .sprout-agent-fanout-dot,
428
+ .sprout-agent-fanout-root {
429
+ border: 1px solid CanvasText;
430
+ }
431
+ }
432
+ }
433
+
434
+ @keyframes sprout-agent-fanout-out {
435
+ 0% {
436
+ stroke-dashoffset: 0.3;
437
+ opacity: 1;
438
+ }
439
+ 80% {
440
+ opacity: 1;
441
+ }
442
+ 100% {
443
+ stroke-dashoffset: -0.7;
444
+ opacity: 0;
445
+ }
446
+ }
447
+ @keyframes sprout-agent-fanout-back {
448
+ 0% {
449
+ stroke-dashoffset: -1;
450
+ opacity: 1;
451
+ }
452
+ 80% {
453
+ opacity: 1;
454
+ }
455
+ 100% {
456
+ stroke-dashoffset: 0;
457
+ opacity: 0;
458
+ }
459
+ }
460
+ @keyframes sprout-agent-fanout-comet-out {
461
+ 0% {
462
+ offset-distance: 0%;
463
+ opacity: 1;
464
+ }
465
+ 90% {
466
+ opacity: 1;
467
+ }
468
+ 100% {
469
+ offset-distance: 100%;
470
+ opacity: 0;
471
+ }
472
+ }
473
+ @keyframes sprout-agent-fanout-comet-back {
474
+ 0% {
475
+ offset-distance: 100%;
476
+ opacity: 1;
477
+ }
478
+ 90% {
479
+ opacity: 1;
480
+ }
481
+ 100% {
482
+ offset-distance: 0%;
483
+ opacity: 0;
484
+ }
485
+ }
486
+ @keyframes sprout-agent-fanout-breathe {
487
+ from {
488
+ scale: 0.82;
489
+ }
490
+ to {
491
+ scale: 1.08;
492
+ }
493
+ }
494
+ @keyframes sprout-agent-fanout-pop {
495
+ 0% {
496
+ scale: 0.82;
497
+ }
498
+ 60% {
499
+ scale: 1.08;
500
+ }
501
+ 100% {
502
+ scale: 1;
503
+ }
504
+ }
505
+ @keyframes sprout-agent-fanout-ring {
506
+ from {
507
+ box-shadow: 0 0 0 0
508
+ color-mix(in oklab, var(--sprout-primary) 28%, transparent);
509
+ }
510
+ to {
511
+ box-shadow: 0 0 0 14px transparent;
512
+ }
513
+ }
514
+ @keyframes sprout-agent-fanout-pulse {
515
+ 0% {
516
+ box-shadow: 0 0 0 0
517
+ color-mix(in oklab, var(--sprout-agent-fanout-color) 45%, transparent);
518
+ }
519
+ 100% {
520
+ box-shadow: 0 0 0 5px transparent;
521
+ }
522
+ }
523
+ @keyframes sprout-agent-fanout-enter {
524
+ from {
525
+ filter: blur(2px);
526
+ opacity: 0;
527
+ translate: 0 3px;
528
+ }
529
+ }
@@ -1,4 +1,5 @@
1
1
  @import "./accordion.css";
2
+ @import "./agent-fanout.css";
2
3
  @import "./alert.css";
3
4
  @import "./alert-dialog.css";
4
5
  @import "./aspect-ratio.css";
@@ -52,6 +53,7 @@
52
53
  @import "./pagination.css";
53
54
  @import "./plan-outline.css";
54
55
  @import "./popover.css";
56
+ @import "./presence-cursor.css";
55
57
  @import "./progress.css";
56
58
  @import "./prompt-list.css";
57
59
  @import "./questionnaire.css";
@@ -62,6 +64,7 @@
62
64
  @import "./review-card.css";
63
65
  @import "./rich-text-editor.css";
64
66
  @import "./schema-diagram.css";
67
+ @import "./sql-viewer.css";
65
68
  @import "./scroll-area.css";
66
69
  @import "./search-dialog.css";
67
70
  @import "./search-field.css";
@@ -206,7 +206,7 @@
206
206
  );
207
207
  --sprout-message-bubble-ink: var(--sprout-danger);
208
208
  }
209
- .sprout-message-bubble-destructive:focus-visible {
209
+ .sprout-message-bubble-destructive:is(button, a):focus-visible {
210
210
  outline-color: var(--sprout-danger);
211
211
  }
212
212
 
@@ -0,0 +1,68 @@
1
+ @layer components {
2
+ .sprout-presence-cursor {
3
+ position: absolute;
4
+ top: 0;
5
+ left: 0;
6
+ z-index: 1;
7
+ pointer-events: none;
8
+ user-select: none;
9
+ font-family: var(--sprout-font);
10
+ }
11
+
12
+ .sprout-presence-cursor-arrow {
13
+ display: block;
14
+ width: 18px;
15
+ height: 18px;
16
+ fill: var(--sprout-presence-color);
17
+ stroke: #fff;
18
+ stroke-width: 1.5px;
19
+ stroke-linejoin: round;
20
+ filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.2));
21
+ }
22
+
23
+ .sprout-presence-cursor-label,
24
+ .sprout-presence-cursor-avatar {
25
+ position: absolute;
26
+ top: 16px;
27
+ left: 14px;
28
+ box-shadow: var(--sprout-shadow-control);
29
+ }
30
+
31
+ .sprout-presence-cursor-label {
32
+ box-sizing: border-box;
33
+ max-width: 16rem;
34
+ padding: 4px 8px;
35
+ overflow: hidden;
36
+ border-radius: var(--sprout-radius-control);
37
+ background: var(--sprout-presence-color);
38
+ color: #fff;
39
+ font-size: var(--sprout-text-sm);
40
+ font-weight: 500;
41
+ line-height: 1.25rem;
42
+ white-space: nowrap;
43
+ text-overflow: ellipsis;
44
+ }
45
+
46
+ .sprout-presence-cursor-avatar {
47
+ display: flex;
48
+ border: 2px solid var(--sprout-presence-color);
49
+ border-radius: 9999px;
50
+ }
51
+
52
+ @media (prefers-reduced-motion: no-preference) {
53
+ .sprout-presence-cursor {
54
+ transition: transform var(--sprout-motion-normal)
55
+ var(--sprout-motion-ease);
56
+ }
57
+ }
58
+
59
+ @media (forced-colors: active) {
60
+ .sprout-presence-cursor-arrow {
61
+ fill: CanvasText;
62
+ stroke: Canvas;
63
+ }
64
+ .sprout-presence-cursor-label {
65
+ border: 1px solid CanvasText;
66
+ }
67
+ }
68
+ }