@tangle-network/sandbox-ui 0.60.0 → 0.62.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.
@@ -2,11 +2,9 @@ import {
2
2
  ProviderIcon
3
3
  } from "./chunk-GTJ5PSK5.js";
4
4
  import {
5
- buildWorkflowGraph
6
- } from "./chunk-WEYFEMIN.js";
7
- import {
5
+ buildWorkflowGraph,
8
6
  providerLabel
9
- } from "./chunk-7JLB7UZ3.js";
7
+ } from "./chunk-34F66QTV.js";
10
8
  import "./chunk-U67V476Y.js";
11
9
 
12
10
  // src/workflows/WorkflowGraph.tsx
package/dist/chat.d.ts CHANGED
@@ -180,6 +180,16 @@ interface AgentSessionControlsProps {
180
180
  model?: AgentSessionModelControl;
181
181
  /** Thinking-effort level applied to subsequent turns. */
182
182
  reasoning?: AgentSessionReasoningControl;
183
+ /**
184
+ * Restrict the model catalog to what the selected harness can actually run,
185
+ * the same way `harness.locked` does — but WITHOUT locking the harness
186
+ * dropdown. Off by default: the strip shows every model and picking an
187
+ * incompatible one snaps the harness to the model's native backend. Turn it
188
+ * ON for a harness-first surface (e.g. a workspace-wide, sandbox-bound
189
+ * harness) where that silent backend swap is undesirable — an incompatible
190
+ * model is then simply not offered.
191
+ */
192
+ filterModelsToHarness?: boolean;
183
193
  /** Right-aligned extra content (token meter, cost, status). */
184
194
  trailing?: React.ReactNode;
185
195
  className?: string;
@@ -218,12 +228,17 @@ interface AgentSessionControlsProps {
218
228
  * coherent automatically (see harness-model-compat): picking a harness
219
229
  * snaps an incompatible model to that harness's best catalog option;
220
230
  * picking a model the current harness can't run switches to the model's
221
- * native harness — unless the harness is `locked`, in which case the
222
- * catalog itself is filtered to compatible models.
231
+ * native harness — unless the catalog is restricted to the harness (when
232
+ * `locked`, or the consumer sets `filterModelsToHarness`), in which case the
233
+ * incompatible model is never offered and no swap happens.
234
+ *
235
+ * When a reasoning control is also present, the effort is re-clamped into the
236
+ * set the new (harness, model) pair supports on every harness/model change, so
237
+ * the effort picker's label never disagrees with the value actually in effect.
223
238
  *
224
239
  * Designed to slot into `SandboxWorkbench`'s `session.composerControls`.
225
240
  */
226
- declare function AgentSessionControls({ harness, profile, model, reasoning, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
241
+ declare function AgentSessionControls({ harness, profile, model, reasoning, filterModelsToHarness, trailing, className, context, layout, menuPlacement, }: AgentSessionControlsProps): react_jsx_runtime.JSX.Element | null;
227
242
 
228
243
  /** A staged attachment shown as a chip above the input. */
229
244
  interface ComposerFile {
package/dist/chat.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  modelProvider,
18
18
  snapHarnessToModel,
19
19
  snapModelToHarness
20
- } from "./chunk-V5JZOO3W.js";
20
+ } from "./chunk-R72QYE2U.js";
21
21
  import "./chunk-HU4B2M4K.js";
22
22
  import "./chunk-SF6LPMMN.js";
23
23
  import "./chunk-EI44GEQ5.js";
@@ -1,6 +1,17 @@
1
- import {
2
- providerLabel
3
- } from "./chunk-7JLB7UZ3.js";
1
+ // src/workflows/provider-label.ts
2
+ var PROVIDER_LABELS = {
3
+ github: "GitHub",
4
+ gitlab: "GitLab",
5
+ slack: "Slack",
6
+ stripe: "Stripe",
7
+ notion: "Notion",
8
+ linear: "Linear",
9
+ discord: "Discord"
10
+ };
11
+ function providerLabel(provider) {
12
+ const key = provider.toLowerCase();
13
+ return PROVIDER_LABELS[key] ?? provider.charAt(0).toUpperCase() + provider.slice(1);
14
+ }
4
15
 
5
16
  // src/workflows/model.ts
6
17
  import { parse as parseYaml } from "yaml";
@@ -293,5 +304,6 @@ function buildWorkflowGraph(yaml, options) {
293
304
  }
294
305
 
295
306
  export {
307
+ providerLabel,
296
308
  buildWorkflowGraph
297
309
  };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-3J6FG3FJ.js";
4
4
  import {
5
5
  PortsList
6
- } from "./chunk-D7JJLG4L.js";
6
+ } from "./chunk-OQZQFSWM.js";
7
7
  import {
8
8
  TerminalView
9
9
  } from "./chunk-VIREDUBF.js";
@@ -589,12 +589,24 @@ function RailExpandable({
589
589
  onClick: onNavigate,
590
590
  ...item.prefetch !== void 0 ? { prefetch: item.prefetch } : {},
591
591
  className: cn(
592
- "flex h-8 items-center gap-2 rounded-md px-2.5 text-[12px] transition-colors",
592
+ "flex h-8 min-w-0 items-center gap-2 rounded-md px-2.5 text-[12px] transition-colors",
593
593
  active ? "bg-[var(--accent-surface-strong)] font-medium text-[var(--accent-text)]" : "text-muted-foreground hover:bg-[var(--accent-surface-soft)] hover:text-foreground"
594
594
  ),
595
595
  children: [
596
596
  FIcon ? /* @__PURE__ */ jsx3(FIcon, { className: "h-4 w-4 shrink-0" }) : null,
597
- /* @__PURE__ */ jsx3("span", { className: "truncate", children: item.label })
597
+ /* @__PURE__ */ jsx3(
598
+ "span",
599
+ {
600
+ className: cn("min-w-0 flex-1 truncate", item.isLoading && "shimmer-text"),
601
+ ...item.isLoading ? { role: "status", "aria-label": "Agent responding" } : {},
602
+ children: item.label
603
+ }
604
+ ),
605
+ item.isLoading ? /* @__PURE__ */ jsxs2("span", { className: "responding-ellipsis", "aria-hidden": "true", children: [
606
+ /* @__PURE__ */ jsx3("span", {}),
607
+ /* @__PURE__ */ jsx3("span", {}),
608
+ /* @__PURE__ */ jsx3("span", {})
609
+ ] }) : null
598
610
  ]
599
611
  },
600
612
  item.id
@@ -28,6 +28,12 @@ import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
28
28
  import { Brain, ChevronDown, Sparkles } from "lucide-react";
29
29
  import { jsx, jsxs } from "react/jsx-runtime";
30
30
  var REASONING_LADDER = reasoningLadder;
31
+ function clampReasoningLevel(value, available) {
32
+ if (value === "auto" || !available || available.includes(value)) {
33
+ return value;
34
+ }
35
+ return available.length ? available[available.length - 1] : "auto";
36
+ }
31
37
  function ReasoningGlyph({ level }) {
32
38
  if (level === "auto") {
33
39
  return /* @__PURE__ */ jsx(Sparkles, { className: "h-3.5 w-3.5 text-muted-foreground" });
@@ -144,7 +150,11 @@ function ReasoningLevelPicker({
144
150
  }
145
151
 
146
152
  // src/chat/agent-session-controls.tsx
147
- import { reasoningEffortsFor } from "@tangle-network/agent-interface";
153
+ import {
154
+ harnessHonorsEffort,
155
+ harnessHonorsModel,
156
+ reasoningEffortsFor
157
+ } from "@tangle-network/agent-interface";
148
158
  import * as DropdownMenu2 from "@radix-ui/react-dropdown-menu";
149
159
  import { ChevronDown as ChevronDown3, Lock, SlidersHorizontal } from "lucide-react";
150
160
 
@@ -448,6 +458,14 @@ function ProfileForm({
448
458
 
449
459
  // src/chat/agent-session-controls.tsx
450
460
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
461
+ function selectorIgnoreNote(harness) {
462
+ const ignoresModel = !harnessHonorsModel(harness);
463
+ const ignoresEffort = !harnessHonorsEffort(harness);
464
+ if (ignoresModel && ignoresEffort) return "Ignores model & effort";
465
+ if (ignoresModel) return "Ignores model selection";
466
+ if (ignoresEffort) return "Ignores reasoning effort";
467
+ return null;
468
+ }
451
469
  function HarnessDropdown({
452
470
  value,
453
471
  onChange,
@@ -520,7 +538,8 @@ function HarnessDropdown({
520
538
  /* @__PURE__ */ jsx3(HarnessLogo, { type: option.type, size: 20, className: "mt-0.5" }),
521
539
  /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
522
540
  /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium", children: option.label }),
523
- option.description && /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: option.description })
541
+ option.description && /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: option.description }),
542
+ selectorIgnoreNote(option.type) && /* @__PURE__ */ jsx3("span", { className: "mt-0.5 inline-flex w-fit items-center rounded border border-[var(--md3-outline-variant)] px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: selectorIgnoreNote(option.type) })
524
543
  ] })
525
544
  ]
526
545
  },
@@ -530,11 +549,20 @@ function HarnessDropdown({
530
549
  ) })
531
550
  ] });
532
551
  }
552
+ function modelReasoningCapability(models, canonicalId) {
553
+ if (!models || !canonicalId) return null;
554
+ const entry = models.find((m) => canonicalModelId(m) === canonicalId);
555
+ return entry ? {
556
+ supportsReasoning: entry.supportsReasoning,
557
+ maxEffort: entry.maxReasoningEffort
558
+ } : null;
559
+ }
533
560
  function AgentSessionControls({
534
561
  harness,
535
562
  profile,
536
563
  model,
537
564
  reasoning,
565
+ filterModelsToHarness,
538
566
  trailing,
539
567
  className,
540
568
  context = "chat",
@@ -542,21 +570,45 @@ function AgentSessionControls({
542
570
  menuPlacement = "auto"
543
571
  }) {
544
572
  if (!harness && !profile && !model && !reasoning && !trailing) return null;
573
+ const restrictModelsToHarness = Boolean(
574
+ harness && (harness.locked || filterModelsToHarness)
575
+ );
576
+ const selectorHonorsModel = !harness || harnessHonorsModel(harness.value);
577
+ const selectorHonorsEffort = !harness || harnessHonorsEffort(harness.value);
578
+ const clampEffort = (harnessValue, modelId) => {
579
+ if (!reasoning) return;
580
+ const available = reasoningEffortsFor(
581
+ harnessValue,
582
+ modelReasoningCapability(model?.models, modelId)
583
+ );
584
+ const clamped = clampReasoningLevel(reasoning.value, available);
585
+ if (clamped !== reasoning.value) reasoning.onChange(clamped);
586
+ };
545
587
  const handleHarnessChange = (next) => {
546
588
  harness?.onChange(next);
589
+ let nextModelId = model?.value;
547
590
  if (model) {
548
591
  const snapped = snapModelToHarness(next, model.value, model.models);
549
- if (snapped !== model.value) model.onChange(snapped);
592
+ if (snapped !== model.value) {
593
+ model.onChange(snapped);
594
+ nextModelId = snapped;
595
+ }
550
596
  }
597
+ clampEffort(next, nextModelId);
551
598
  };
552
599
  const handleModelChange = (nextModelId) => {
553
600
  model?.onChange(nextModelId);
554
- if (harness && !harness.locked) {
601
+ let nextHarness = harness?.value;
602
+ if (harness && !restrictModelsToHarness) {
555
603
  const snapped = snapHarnessToModel(harness.value, nextModelId);
556
- if (snapped !== harness.value) harness.onChange(snapped);
604
+ if (snapped !== harness.value) {
605
+ harness.onChange(snapped);
606
+ nextHarness = snapped;
607
+ }
557
608
  }
609
+ if (nextHarness) clampEffort(nextHarness, nextModelId);
558
610
  };
559
- const visibleModels = model && harness?.locked ? model.models.filter(
611
+ const visibleModels = model && restrictModelsToHarness && harness ? model.models.filter(
560
612
  (entry) => isModelCompatibleWithHarness(
561
613
  harness.value,
562
614
  canonicalModelId(entry)
@@ -603,25 +655,19 @@ function AgentSessionControls({
603
655
  loading: model.loading,
604
656
  popular: model.popular,
605
657
  recents: model.recents,
606
- disabled: model.disabled || (visibleModels ?? []).length === 0,
658
+ disabled: model.disabled || (visibleModels ?? []).length === 0 || !selectorHonorsModel,
607
659
  side: layout === "gear" ? void 0 : "bottom",
608
660
  avoidCollisions
609
661
  }
610
662
  );
611
- const selectedModel = model?.models.find(
612
- (entry) => canonicalModelId(entry) === model.value
613
- );
614
- const modelReasoning = selectedModel ? {
615
- supportsReasoning: selectedModel.supportsReasoning,
616
- maxEffort: selectedModel.maxReasoningEffort
617
- } : null;
663
+ const modelReasoning = modelReasoningCapability(model?.models, model?.value);
618
664
  const reasoningNode = reasoning && /* @__PURE__ */ jsx3(
619
665
  ReasoningLevelPicker,
620
666
  {
621
667
  value: reasoning.value,
622
668
  onChange: reasoning.onChange,
623
669
  options: reasoning.options,
624
- disabled: reasoning.disabled,
670
+ disabled: reasoning.disabled || !selectorHonorsEffort,
625
671
  available: harness ? reasoningEffortsFor(harness.value, modelReasoning) : reasoning.available,
626
672
  side: layout === "gear" ? void 0 : "bottom",
627
673
  avoidCollisions
@@ -183,6 +183,8 @@ interface RailExpandableSubItem {
183
183
  }>;
184
184
  href: string;
185
185
  prefetch?: "none" | "intent" | "render" | "viewport";
186
+ /** Show a live working indicator on the row while the item is busy. */
187
+ isLoading?: boolean;
186
188
  }
187
189
  interface RailExpandableProps {
188
190
  icon: React.ComponentType<{
package/dist/dashboard.js CHANGED
@@ -54,7 +54,7 @@ import {
54
54
  canAdminSandbox,
55
55
  parseInsufficientBalance,
56
56
  useSidebar
57
- } from "./chunk-D7JJLG4L.js";
57
+ } from "./chunk-OQZQFSWM.js";
58
58
  import {
59
59
  BillingDashboard,
60
60
  InfoPanel,
package/dist/globals.css CHANGED
@@ -542,6 +542,9 @@
542
542
  .mt-6 {
543
543
  margin-top: calc(var(--spacing) * 6);
544
544
  }
545
+ .mt-px {
546
+ margin-top: 1px;
547
+ }
545
548
  .mr-1 {
546
549
  margin-right: calc(var(--spacing) * 1);
547
550
  }
@@ -605,6 +608,9 @@
605
608
  .ml-2 {
606
609
  margin-left: calc(var(--spacing) * 2);
607
610
  }
611
+ .ml-2\.5 {
612
+ margin-left: calc(var(--spacing) * 2.5);
613
+ }
608
614
  .ml-10 {
609
615
  margin-left: calc(var(--spacing) * 10);
610
616
  }
@@ -756,9 +762,6 @@
756
762
  .h-56 {
757
763
  height: calc(var(--spacing) * 56);
758
764
  }
759
- .h-64 {
760
- height: calc(var(--spacing) * 64);
761
- }
762
765
  .h-\[3px\] {
763
766
  height: 3px;
764
767
  }
@@ -789,9 +792,6 @@
789
792
  .h-\[640px\] {
790
793
  height: 640px;
791
794
  }
792
- .h-\[720px\] {
793
- height: 720px;
794
- }
795
795
  .h-\[var\(--avatar-size\)\] {
796
796
  height: var(--avatar-size);
797
797
  }
@@ -1092,9 +1092,6 @@
1092
1092
  .w-\[420px\] {
1093
1093
  width: 420px;
1094
1094
  }
1095
- .w-\[460px\] {
1096
- width: 460px;
1097
- }
1098
1095
  .w-\[480px\] {
1099
1096
  width: 480px;
1100
1097
  }
@@ -1143,6 +1140,9 @@
1143
1140
  .w-\[var\(--tool-icon-size\)\] {
1144
1141
  width: var(--tool-icon-size);
1145
1142
  }
1143
+ .w-fit {
1144
+ width: fit-content;
1145
+ }
1146
1146
  .w-full {
1147
1147
  width: 100%;
1148
1148
  }
@@ -1287,9 +1287,6 @@
1287
1287
  .flex-shrink-0 {
1288
1288
  flex-shrink: 0;
1289
1289
  }
1290
- .shrink {
1291
- flex-shrink: 1;
1292
- }
1293
1290
  .shrink-0 {
1294
1291
  flex-shrink: 0;
1295
1292
  }
@@ -1376,9 +1373,6 @@
1376
1373
  .cursor-default {
1377
1374
  cursor: default;
1378
1375
  }
1379
- .cursor-ew-resize {
1380
- cursor: ew-resize;
1381
- }
1382
1376
  .cursor-not-allowed {
1383
1377
  cursor: not-allowed;
1384
1378
  }
@@ -1909,6 +1903,12 @@
1909
1903
  .border-\[var\(--surface-danger-border\)\] {
1910
1904
  border-color: var(--surface-danger-border);
1911
1905
  }
1906
+ .border-\[var\(--surface-danger-border\)\]\/60 {
1907
+ border-color: var(--surface-danger-border);
1908
+ @supports (color: color-mix(in lab, red, red)) {
1909
+ border-color: color-mix(in oklab, var(--surface-danger-border) 60%, transparent);
1910
+ }
1911
+ }
1912
1912
  .border-\[var\(--surface-info-border\)\] {
1913
1913
  border-color: var(--surface-info-border);
1914
1914
  }
@@ -1963,12 +1963,6 @@
1963
1963
  border-color: color-mix(in oklab, var(--color-destructive) 30%, transparent);
1964
1964
  }
1965
1965
  }
1966
- .border-destructive\/40 {
1967
- border-color: color-mix(in srgb, hsl(var(--destructive)) 40%, transparent);
1968
- @supports (color: color-mix(in lab, red, red)) {
1969
- border-color: color-mix(in oklab, var(--color-destructive) 40%, transparent);
1970
- }
1971
- }
1972
1966
  .border-destructive\/50 {
1973
1967
  border-color: color-mix(in srgb, hsl(var(--destructive)) 50%, transparent);
1974
1968
  @supports (color: color-mix(in lab, red, red)) {
@@ -2014,6 +2008,12 @@
2014
2008
  border-color: color-mix(in oklab, var(--color-primary) 10%, transparent);
2015
2009
  }
2016
2010
  }
2011
+ .border-primary\/15 {
2012
+ border-color: color-mix(in srgb, hsl(var(--primary)) 15%, transparent);
2013
+ @supports (color: color-mix(in lab, red, red)) {
2014
+ border-color: color-mix(in oklab, var(--color-primary) 15%, transparent);
2015
+ }
2016
+ }
2017
2017
  .border-primary\/20 {
2018
2018
  border-color: color-mix(in srgb, hsl(var(--primary)) 20%, transparent);
2019
2019
  @supports (color: color-mix(in lab, red, red)) {
@@ -2026,12 +2026,6 @@
2026
2026
  border-color: color-mix(in oklab, var(--color-primary) 30%, transparent);
2027
2027
  }
2028
2028
  }
2029
- .border-primary\/40 {
2030
- border-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
2031
- @supports (color: color-mix(in lab, red, red)) {
2032
- border-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
2033
- }
2034
- }
2035
2029
  .border-primary\/50 {
2036
2030
  border-color: color-mix(in srgb, hsl(var(--primary)) 50%, transparent);
2037
2031
  @supports (color: color-mix(in lab, red, red)) {
@@ -2251,10 +2245,10 @@
2251
2245
  .bg-accent {
2252
2246
  background-color: var(--color-accent);
2253
2247
  }
2254
- .bg-accent\/30 {
2255
- background-color: color-mix(in srgb, hsl(var(--accent)) 30%, transparent);
2248
+ .bg-accent\/20 {
2249
+ background-color: color-mix(in srgb, hsl(var(--accent)) 20%, transparent);
2256
2250
  @supports (color: color-mix(in lab, red, red)) {
2257
- background-color: color-mix(in oklab, var(--color-accent) 30%, transparent);
2251
+ background-color: color-mix(in oklab, var(--color-accent) 20%, transparent);
2258
2252
  }
2259
2253
  }
2260
2254
  .bg-amber-500\/10 {
@@ -2320,6 +2314,12 @@
2320
2314
  .bg-card {
2321
2315
  background-color: var(--color-card);
2322
2316
  }
2317
+ .bg-card\/40 {
2318
+ background-color: color-mix(in srgb, hsl(var(--card)) 40%, transparent);
2319
+ @supports (color: color-mix(in lab, red, red)) {
2320
+ background-color: color-mix(in oklab, var(--color-card) 40%, transparent);
2321
+ }
2322
+ }
2323
2323
  .bg-card\/50 {
2324
2324
  background-color: color-mix(in srgb, hsl(var(--card)) 50%, transparent);
2325
2325
  @supports (color: color-mix(in lab, red, red)) {
@@ -2818,15 +2818,9 @@
2818
2818
  .pb-1 {
2819
2819
  padding-bottom: calc(var(--spacing) * 1);
2820
2820
  }
2821
- .pb-1\.5 {
2822
- padding-bottom: calc(var(--spacing) * 1.5);
2823
- }
2824
2821
  .pb-2 {
2825
2822
  padding-bottom: calc(var(--spacing) * 2);
2826
2823
  }
2827
- .pb-2\.5 {
2828
- padding-bottom: calc(var(--spacing) * 2.5);
2829
- }
2830
2824
  .pb-3 {
2831
2825
  padding-bottom: calc(var(--spacing) * 3);
2832
2826
  }
@@ -2845,8 +2839,8 @@
2845
2839
  .pl-3 {
2846
2840
  padding-left: calc(var(--spacing) * 3);
2847
2841
  }
2848
- .pl-4 {
2849
- padding-left: calc(var(--spacing) * 4);
2842
+ .pl-3\.5 {
2843
+ padding-left: calc(var(--spacing) * 3.5);
2850
2844
  }
2851
2845
  .pl-7 {
2852
2846
  padding-left: calc(var(--spacing) * 7);
@@ -3527,10 +3521,6 @@
3527
3521
  --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
3528
3522
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3529
3523
  }
3530
- .shadow-xl {
3531
- --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
3532
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
3533
- }
3534
3524
  .ring {
3535
3525
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
3536
3526
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -3750,13 +3740,6 @@
3750
3740
  }
3751
3741
  }
3752
3742
  }
3753
- .group-hover\:bg-primary {
3754
- &:is(:where(.group):hover *) {
3755
- @media (hover: hover) {
3756
- background-color: var(--color-primary);
3757
- }
3758
- }
3759
- }
3760
3743
  .group-hover\:text-primary {
3761
3744
  &:is(:where(.group):hover *) {
3762
3745
  @media (hover: hover) {
@@ -3799,11 +3782,6 @@
3799
3782
  }
3800
3783
  }
3801
3784
  }
3802
- .group-focus\:bg-primary {
3803
- &:is(:where(.group):focus *) {
3804
- background-color: var(--color-primary);
3805
- }
3806
- }
3807
3785
  .peer-disabled\:cursor-not-allowed {
3808
3786
  &:is(:where(.peer):disabled ~ *) {
3809
3787
  cursor: not-allowed;
@@ -4153,22 +4131,22 @@
4153
4131
  }
4154
4132
  }
4155
4133
  }
4156
- .hover\:bg-accent\/30 {
4134
+ .hover\:bg-accent\/25 {
4157
4135
  &:hover {
4158
4136
  @media (hover: hover) {
4159
- background-color: color-mix(in srgb, hsl(var(--accent)) 30%, transparent);
4137
+ background-color: color-mix(in srgb, hsl(var(--accent)) 25%, transparent);
4160
4138
  @supports (color: color-mix(in lab, red, red)) {
4161
- background-color: color-mix(in oklab, var(--color-accent) 30%, transparent);
4139
+ background-color: color-mix(in oklab, var(--color-accent) 25%, transparent);
4162
4140
  }
4163
4141
  }
4164
4142
  }
4165
4143
  }
4166
- .hover\:bg-accent\/35 {
4144
+ .hover\:bg-accent\/30 {
4167
4145
  &:hover {
4168
4146
  @media (hover: hover) {
4169
- background-color: color-mix(in srgb, hsl(var(--accent)) 35%, transparent);
4147
+ background-color: color-mix(in srgb, hsl(var(--accent)) 30%, transparent);
4170
4148
  @supports (color: color-mix(in lab, red, red)) {
4171
- background-color: color-mix(in oklab, var(--color-accent) 35%, transparent);
4149
+ background-color: color-mix(in oklab, var(--color-accent) 30%, transparent);
4172
4150
  }
4173
4151
  }
4174
4152
  }
@@ -4307,16 +4285,6 @@
4307
4285
  }
4308
4286
  }
4309
4287
  }
4310
- .hover\:bg-muted\/60 {
4311
- &:hover {
4312
- @media (hover: hover) {
4313
- background-color: color-mix(in srgb, hsl(var(--muted)) 60%, transparent);
4314
- @supports (color: color-mix(in lab, red, red)) {
4315
- background-color: color-mix(in oklab, var(--color-muted) 60%, transparent);
4316
- }
4317
- }
4318
- }
4319
- }
4320
4288
  .hover\:bg-muted\/80 {
4321
4289
  &:hover {
4322
4290
  @media (hover: hover) {
@@ -4896,15 +4864,6 @@
4896
4864
  opacity: 60%;
4897
4865
  }
4898
4866
  }
4899
- .disabled\:hover\:bg-transparent {
4900
- &:disabled {
4901
- &:hover {
4902
- @media (hover: hover) {
4903
- background-color: transparent;
4904
- }
4905
- }
4906
- }
4907
- }
4908
4867
  .data-\[disabled\]\:pointer-events-none {
4909
4868
  &[data-disabled] {
4910
4869
  pointer-events: none;
@@ -5444,11 +5403,6 @@
5444
5403
  }
5445
5404
  }
5446
5405
  }
5447
- .\[\@media\(hover\:none\)\]\:opacity-100 {
5448
- @media (hover:none) {
5449
- opacity: 100%;
5450
- }
5451
- }
5452
5406
  }
5453
5407
  :root,
5454
5408
  [data-sandbox-ui],
@@ -6057,6 +6011,56 @@
6057
6011
  background-size: 200% 100%;
6058
6012
  animation: shimmer 2s infinite;
6059
6013
  }
6014
+ .shimmer-text {
6015
+ background-image: linear-gradient(
6016
+ 90deg,
6017
+ hsl(var(--muted-foreground)) 0%,
6018
+ hsl(var(--muted-foreground)) 28%,
6019
+ var(--accent-text) 50%,
6020
+ hsl(var(--muted-foreground)) 72%,
6021
+ hsl(var(--muted-foreground)) 100%
6022
+ );
6023
+ background-size: 200% 100%;
6024
+ -webkit-background-clip: text;
6025
+ background-clip: text;
6026
+ -webkit-text-fill-color: transparent;
6027
+ animation: shimmer 1.3s linear infinite;
6028
+ }
6029
+ @media (prefers-reduced-motion: reduce) {
6030
+ .shimmer-text {
6031
+ animation: none;
6032
+ }
6033
+ }
6034
+ .responding-ellipsis {
6035
+ display: inline-flex;
6036
+ width: 1.25rem;
6037
+ margin-left: auto;
6038
+ flex-shrink: 0;
6039
+ align-items: center;
6040
+ justify-content: center;
6041
+ gap: 0.1875rem;
6042
+ color: hsl(var(--primary));
6043
+ }
6044
+ .responding-ellipsis > span {
6045
+ width: 0.25rem;
6046
+ height: 0.25rem;
6047
+ border-radius: 9999px;
6048
+ background: currentColor;
6049
+ opacity: 0.6;
6050
+ animation: responding-ellipsis 0.8s ease-in-out infinite;
6051
+ }
6052
+ .responding-ellipsis > span:nth-child(2) {
6053
+ animation-delay: 0.15s;
6054
+ }
6055
+ .responding-ellipsis > span:nth-child(3) {
6056
+ animation-delay: 0.3s;
6057
+ }
6058
+ @media (prefers-reduced-motion: reduce) {
6059
+ .responding-ellipsis > span {
6060
+ animation: none;
6061
+ opacity: 0.8;
6062
+ }
6063
+ }
6060
6064
  .animate-in {
6061
6065
  animation: fade-in 0.25s ease-out;
6062
6066
  }
@@ -6091,6 +6095,16 @@
6091
6095
  background-position: 200% 0;
6092
6096
  }
6093
6097
  }
6098
+ @keyframes responding-ellipsis {
6099
+ 0%, 80%, 100% {
6100
+ opacity: 0.6;
6101
+ transform: translateY(0);
6102
+ }
6103
+ 40% {
6104
+ opacity: 1;
6105
+ transform: translateY(-1.5px);
6106
+ }
6107
+ }
6094
6108
  @keyframes fade-in {
6095
6109
  from {
6096
6110
  opacity: 0;