@tangle-network/sandbox-ui 0.46.0 → 0.47.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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ProviderIcon
3
- } from "./chunk-CXV6X33U.js";
3
+ } from "./chunk-GTJ5PSK5.js";
4
4
  import {
5
5
  buildWorkflowGraph
6
6
  } from "./chunk-SUC6ZJZW.js";
package/dist/assistant.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ProviderIcon
3
- } from "./chunk-CXV6X33U.js";
3
+ } from "./chunk-GTJ5PSK5.js";
4
4
  import {
5
5
  providerLabel
6
6
  } from "./chunk-7JLB7UZ3.js";
@@ -97,6 +97,74 @@ var PROVIDER_LOGO_SLUGS = {
97
97
  buffer: "buffer",
98
98
  hootsuite: "hootsuite"
99
99
  };
100
+ var ACTIVEPIECES_CDN = "https://cdn.activepieces.com/pieces";
101
+ var PROVIDER_LOGO_URLS = {
102
+ // Catalog logo whose filename/extension differs from the provider id.
103
+ "cal-com": `${ACTIVEPIECES_CDN}/cal.com.png`,
104
+ "customer-io": `${ACTIVEPIECES_CDN}/customerio.png`,
105
+ anthropic: `${ACTIVEPIECES_CDN}/claude.png`,
106
+ telegram: `${ACTIVEPIECES_CDN}/telegram_bot.png`,
107
+ "twilio-sms": `${ACTIVEPIECES_CDN}/twilio.png`,
108
+ "amazon-sqs": `${ACTIVEPIECES_CDN}/aws-sqs.png`,
109
+ frame: `${ACTIVEPIECES_CDN}/frameio.png`,
110
+ "jira-cloud": `${ACTIVEPIECES_CDN}/jira.png`,
111
+ "jira-data-center": `${ACTIVEPIECES_CDN}/jira.png`,
112
+ stripe: `${ACTIVEPIECES_CDN}/stripe.png`,
113
+ "stripe-pack": `${ACTIVEPIECES_CDN}/stripe.png`,
114
+ gemini: `${ACTIVEPIECES_CDN}/google-gemini.png`,
115
+ "google-gemini": `${ACTIVEPIECES_CDN}/google-gemini.png`,
116
+ bluesky: `${ACTIVEPIECES_CDN}/bluesky.png`,
117
+ emailit: `${ACTIVEPIECES_CDN}/emailit.svg`,
118
+ cloutly: `${ACTIVEPIECES_CDN}/cloutly.svg`,
119
+ gistly: `${ACTIVEPIECES_CDN}/gistly.svg`,
120
+ jotform: `${ACTIVEPIECES_CDN}/jotform.svg`,
121
+ supadata: `${ACTIVEPIECES_CDN}/supadata.svg`,
122
+ "hugging-face": `${ACTIVEPIECES_CDN}/huggingface.svg`,
123
+ huggingface: `${ACTIVEPIECES_CDN}/huggingface.svg`,
124
+ heygen: `${ACTIVEPIECES_CDN}/heygen.jpg`,
125
+ instasent: `${ACTIVEPIECES_CDN}/instasent.jpg`,
126
+ "chainalysis-api": `${ACTIVEPIECES_CDN}/chainalysis-api.jpg`,
127
+ scrapegraphai: `${ACTIVEPIECES_CDN}/scrapegraphai.jpg`,
128
+ localai: `${ACTIVEPIECES_CDN}/localai.jpeg`,
129
+ talkable: "https://www.talkable.com/wp-content/uploads/2021/12/talkable-favicon.svg",
130
+ // Sub-connector or variant reusing its parent connector's catalog logo.
131
+ "facebook-leads": `${ACTIVEPIECES_CDN}/facebook.png`,
132
+ "facebook-pages": `${ACTIVEPIECES_CDN}/facebook.png`,
133
+ "whatsapp-business": `${ACTIVEPIECES_CDN}/whatsapp.png`,
134
+ onedrive: `${ACTIVEPIECES_CDN}/oneDrive.png`,
135
+ "microsoft-onedrive": `${ACTIVEPIECES_CDN}/oneDrive.png`,
136
+ "outlook-mail": `${ACTIVEPIECES_CDN}/microsoft-outlook.png`,
137
+ "microsoft-calendar": `${ACTIVEPIECES_CDN}/microsoft-outlook.png`,
138
+ "microsoft-outlook-calendar": `${ACTIVEPIECES_CDN}/microsoft-outlook.png`,
139
+ sharepoint: `${ACTIVEPIECES_CDN}/microsoft-sharepoint.png`,
140
+ "notion-database": `${ACTIVEPIECES_CDN}/notion.png`,
141
+ "slack-inbound": `${ACTIVEPIECES_CDN}/slack.png`,
142
+ helpscout: `${ACTIVEPIECES_CDN}/help-scout.png`,
143
+ figjam: `${ACTIVEPIECES_CDN}/figma.png`,
144
+ webhook: `${ACTIVEPIECES_CDN}/new-core/webhooks.svg`,
145
+ // Absent from the catalog CDN — served from a public icon source.
146
+ make: "https://cdn.simpleicons.org/make",
147
+ n8n: "https://cdn.simpleicons.org/n8n",
148
+ zapier: "https://cdn.simpleicons.org/zapier",
149
+ auth0: "https://cdn.simpleicons.org/auth0",
150
+ basecamp: "https://cdn.simpleicons.org/basecamp",
151
+ ebay: "https://cdn.simpleicons.org/ebay",
152
+ gusto: "https://cdn.simpleicons.org/gusto",
153
+ miro: "https://cdn.simpleicons.org/miro",
154
+ sanity: "https://cdn.simpleicons.org/sanity",
155
+ sentry: "https://cdn.simpleicons.org/sentry",
156
+ opsgenie: "https://cdn.simpleicons.org/opsgenie",
157
+ phony: "https://www.google.com/s2/favicons?sz=64&domain_url=https://ph0ny.com",
158
+ docuseal: "https://www.google.com/s2/favicons?sz=64&domain_url=https://docuseal.com",
159
+ braze: "https://www.google.com/s2/favicons?sz=64&domain_url=https://braze.com",
160
+ pipedream: "https://www.google.com/s2/favicons?sz=64&domain_url=https://pipedream.com",
161
+ weaviate: "https://www.google.com/s2/favicons?sz=64&domain_url=https://weaviate.io",
162
+ "adobe-creative-cloud": "https://www.google.com/s2/favicons?sz=64&domain_url=https://adobe.com",
163
+ clio: "https://www.google.com/s2/favicons?sz=64&domain_url=https://clio.com",
164
+ marketo: "https://www.google.com/s2/favicons?sz=64&domain_url=https://marketo.com",
165
+ rippling: "https://www.google.com/s2/favicons?sz=64&domain_url=https://rippling.com",
166
+ "microsoft-graph": "https://www.google.com/s2/favicons?sz=64&domain_url=https://graph.microsoft.com"
167
+ };
100
168
  var PROVIDER_VECTOR_LOGOS = {
101
169
  slack: "slack",
102
170
  salesforce: "salesforce",
@@ -121,6 +189,9 @@ function providerLogoCandidates(opts) {
121
189
  const curated = PROVIDER_LOGO_SLUGS[raw] ?? PROVIDER_LOGO_SLUGS[norm];
122
190
  const vectorName = PROVIDER_VECTOR_LOGOS[raw] ?? PROVIDER_VECTOR_LOGOS[norm] ?? (curated ? PROVIDER_VECTOR_LOGOS[curated] : void 0);
123
191
  if (vectorName) out.push(`https://svgl.app/library/${vectorName}.svg`);
192
+ const pinned = PROVIDER_LOGO_URLS[raw] ?? PROVIDER_LOGO_URLS[norm];
193
+ if (pinned) out.push(pinned);
194
+ if (raw) out.push(`${ACTIVEPIECES_CDN}/${encodeURIComponent(raw)}.png`);
124
195
  const slugs = /* @__PURE__ */ new Set();
125
196
  if (curated) slugs.add(curated);
126
197
  slugs.add(norm.replace(/-/g, ""));
@@ -203,7 +274,5 @@ function ProviderIcon({
203
274
 
204
275
  export {
205
276
  normalizeProviderId,
206
- providerLogoCandidates,
207
- monogramColor,
208
277
  ProviderIcon
209
278
  };
package/dist/globals.css CHANGED
@@ -2857,6 +2857,10 @@
2857
2857
  .text-\[length\:var\(--font-size-xl\,1\.25rem\)\] {
2858
2858
  font-size: var(--font-size-xl,1.25rem);
2859
2859
  }
2860
+ .leading-4 {
2861
+ --tw-leading: calc(var(--spacing) * 4);
2862
+ line-height: calc(var(--spacing) * 4);
2863
+ }
2860
2864
  .leading-6 {
2861
2865
  --tw-leading: calc(var(--spacing) * 6);
2862
2866
  line-height: calc(var(--spacing) * 6);
@@ -4555,6 +4559,11 @@
4555
4559
  }
4556
4560
  }
4557
4561
  }
4562
+ .focus-visible\:bg-background {
4563
+ &:focus-visible {
4564
+ background-color: var(--color-background);
4565
+ }
4566
+ }
4558
4567
  .focus-visible\:bg-primary\/40 {
4559
4568
  &:focus-visible {
4560
4569
  background-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
@@ -4568,6 +4577,11 @@
4568
4577
  background-color: transparent;
4569
4578
  }
4570
4579
  }
4580
+ .focus-visible\:text-foreground {
4581
+ &:focus-visible {
4582
+ color: var(--color-foreground);
4583
+ }
4584
+ }
4571
4585
  .focus-visible\:opacity-100 {
4572
4586
  &:focus-visible {
4573
4587
  opacity: 100%;
@@ -4611,6 +4625,14 @@
4611
4625
  }
4612
4626
  }
4613
4627
  }
4628
+ .focus-visible\:ring-primary\/40 {
4629
+ &:focus-visible {
4630
+ --tw-ring-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
4631
+ @supports (color: color-mix(in lab, red, red)) {
4632
+ --tw-ring-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
4633
+ }
4634
+ }
4635
+ }
4614
4636
  .focus-visible\:ring-primary\/60 {
4615
4637
  &:focus-visible {
4616
4638
  --tw-ring-color: color-mix(in srgb, hsl(var(--primary)) 60%, transparent);
@@ -13,10 +13,7 @@ interface IntegrationConnection {
13
13
  connectorId?: string;
14
14
  status: "connected" | "pending" | "revoked" | "expired" | (string & {});
15
15
  grantedScopes?: string[];
16
- account?: {
17
- identity?: string;
18
- displayName?: string;
19
- } & Record<string, unknown>;
16
+ accountDisplay?: string | null;
20
17
  expiresAt?: string | null;
21
18
  createdAt?: string;
22
19
  updatedAt?: string;
@@ -57,8 +54,10 @@ interface IntegrationsPanelProps {
57
54
  connectorId: string;
58
55
  }) => void | Promise<void>;
59
56
  /**
60
- * Invoked when the user manages (disconnects) a live connection via the
61
- * hover-revealed affordance on a connected tile.
57
+ * Invoked when the user confirms disconnecting a live connection from the
58
+ * disconnect control on a connected tile. May return a promise; the
59
+ * confirmation dialog shows a loading state until it settles and surfaces a
60
+ * thrown error inline.
62
61
  */
63
62
  onDisconnect: (connectionId: string) => void | Promise<void>;
64
63
  /** Empty-state message when the catalog hasn't loaded any providers. */
@@ -1,15 +1,25 @@
1
1
  import {
2
- monogramColor,
3
- normalizeProviderId,
4
- providerLogoCandidates
5
- } from "./chunk-CXV6X33U.js";
2
+ ProviderIcon,
3
+ normalizeProviderId
4
+ } from "./chunk-GTJ5PSK5.js";
6
5
  import "./chunk-U67V476Y.js";
7
6
 
8
7
  // src/integrations/integrations-panel.tsx
9
8
  import * as React from "react";
10
- import { Card, CardContent, EmptyState } from "@tangle-network/ui/primitives";
9
+ import {
10
+ Button,
11
+ Card,
12
+ CardContent,
13
+ Dialog,
14
+ DialogContent,
15
+ DialogDescription,
16
+ DialogFooter,
17
+ DialogHeader,
18
+ DialogTitle,
19
+ EmptyState
20
+ } from "@tangle-network/ui/primitives";
11
21
  import { cn } from "@tangle-network/ui/utils";
12
- import { Check, Search, Settings2 } from "lucide-react";
22
+ import { Check, Search, Unplug } from "lucide-react";
13
23
  import { jsx, jsxs } from "react/jsx-runtime";
14
24
  var DEFAULT_FEATURED_IDS = [
15
25
  "gmail",
@@ -49,51 +59,7 @@ var DEFAULT_FEATURED_IDS = [
49
59
  function defaultConnectorOf(provider) {
50
60
  return provider.connectors?.[0]?.connectorId ?? provider.providerId;
51
61
  }
52
- function ProviderLogo({
53
- provider,
54
- size = 56
55
- }) {
56
- const candidates = React.useMemo(
57
- () => providerLogoCandidates({
58
- id: provider.providerId,
59
- iconUrl: provider.iconUrl
60
- }),
61
- [provider]
62
- );
63
- const [index, setIndex] = React.useState(0);
64
- const label = (provider.displayName ?? provider.providerId).trim();
65
- const initial = label.charAt(0).toUpperCase() || "?";
66
- const src = candidates[index];
67
- if (!src) {
68
- return /* @__PURE__ */ jsx(
69
- "span",
70
- {
71
- className: "flex shrink-0 items-center justify-center rounded-2xl font-semibold text-white",
72
- style: {
73
- width: size,
74
- height: size,
75
- backgroundColor: monogramColor(provider.providerId),
76
- fontSize: Math.round(size * 0.42)
77
- },
78
- "aria-hidden": true,
79
- children: initial
80
- }
81
- );
82
- }
83
- return /* @__PURE__ */ jsx(
84
- "img",
85
- {
86
- src,
87
- alt: "",
88
- width: size,
89
- height: size,
90
- loading: "lazy",
91
- className: "shrink-0 object-contain",
92
- style: { width: size, height: size },
93
- onError: () => setIndex((i) => i + 1)
94
- }
95
- );
96
- }
62
+ var LOGO_SIZE = 48;
97
63
  function buildConnectionIndex(connections) {
98
64
  const index = /* @__PURE__ */ new Map();
99
65
  for (const conn of connections) {
@@ -140,6 +106,12 @@ function IntegrationsPanel({
140
106
  }) {
141
107
  const [query, setQuery] = React.useState("");
142
108
  const [sort, setSort] = React.useState(defaultSort);
109
+ const [disconnectTarget, setDisconnectTarget] = React.useState(null);
110
+ const [isDisconnecting, setIsDisconnecting] = React.useState(false);
111
+ const [disconnectError, setDisconnectError] = React.useState(
112
+ null
113
+ );
114
+ const activeDisconnect = React.useRef(0);
143
115
  const connectionIndex = React.useMemo(
144
116
  () => buildConnectionIndex(connections),
145
117
  [connections]
@@ -162,6 +134,30 @@ function IntegrationsPanel({
162
134
  });
163
135
  return sorted;
164
136
  }, [catalog, query, sort, featuredRank]);
137
+ const closeDisconnect = React.useCallback(() => {
138
+ activeDisconnect.current += 1;
139
+ setIsDisconnecting(false);
140
+ setDisconnectTarget(null);
141
+ setDisconnectError(null);
142
+ }, []);
143
+ const confirmDisconnect = React.useCallback(async () => {
144
+ if (!disconnectTarget) return;
145
+ const reqId = activeDisconnect.current += 1;
146
+ setIsDisconnecting(true);
147
+ setDisconnectError(null);
148
+ try {
149
+ await Promise.resolve(onDisconnect(disconnectTarget.connectionId));
150
+ if (activeDisconnect.current !== reqId) return;
151
+ setDisconnectTarget(null);
152
+ } catch (e) {
153
+ if (activeDisconnect.current !== reqId) return;
154
+ setDisconnectError(
155
+ e instanceof Error ? e.message : "Failed to disconnect."
156
+ );
157
+ } finally {
158
+ if (activeDisconnect.current === reqId) setIsDisconnecting(false);
159
+ }
160
+ }, [disconnectTarget, onDisconnect]);
165
161
  if (error) {
166
162
  return /* @__PURE__ */ jsx(Card, { className: cn("border-destructive/50", className), children: /* @__PURE__ */ jsx(CardContent, { className: "py-6", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-destructive", children: [
167
163
  "Failed to load integrations: ",
@@ -196,6 +192,7 @@ function IntegrationsPanel({
196
192
  }
197
193
  );
198
194
  }
195
+ const disconnectAccountLabel = disconnectTarget?.accountDisplay;
199
196
  return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
200
197
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
201
198
  /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center gap-2 rounded-lg border border-border bg-card px-3 py-2", children: [
@@ -260,8 +257,9 @@ function IntegrationsPanel({
260
257
  {
261
258
  "data-testid": `integration-${provider.providerId}`,
262
259
  "data-connected": "true",
260
+ title: live.accountDisplay ? `${name} \u2014 ${live.accountDisplay}` : name,
263
261
  className: cn(
264
- "group relative flex aspect-square flex-col items-center justify-center gap-2 rounded-xl border p-3 text-center",
262
+ "relative flex aspect-square flex-col items-center justify-center gap-2 rounded-xl border p-3 text-center",
265
263
  "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)]"
266
264
  ),
267
265
  children: [
@@ -270,16 +268,48 @@ function IntegrationsPanel({
270
268
  "button",
271
269
  {
272
270
  type: "button",
273
- onClick: () => onDisconnect(live.id),
274
- "data-testid": `manage-${provider.providerId}`,
275
- "aria-label": `Manage ${name}`,
276
- title: "Manage connection",
277
- className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-background hover:text-foreground group-hover:opacity-100",
278
- children: /* @__PURE__ */ jsx(Settings2, { className: "h-3.5 w-3.5" })
271
+ onClick: () => setDisconnectTarget({
272
+ connectionId: live.id,
273
+ name,
274
+ accountDisplay: live.accountDisplay
275
+ }),
276
+ "data-testid": `disconnect-${provider.providerId}`,
277
+ "aria-label": `Disconnect ${name}`,
278
+ title: "Disconnect",
279
+ className: "absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground/70 transition-colors hover:bg-background hover:text-foreground focus-visible:bg-background focus-visible:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40",
280
+ children: /* @__PURE__ */ jsx(Unplug, { className: "h-3.5 w-3.5" })
281
+ }
282
+ ),
283
+ /* @__PURE__ */ jsx(
284
+ ProviderIcon,
285
+ {
286
+ id: provider.providerId,
287
+ iconUrl: provider.iconUrl,
288
+ displayName: provider.displayName,
289
+ size: LOGO_SIZE,
290
+ className: "rounded-2xl"
279
291
  }
280
292
  ),
281
- /* @__PURE__ */ jsx(ProviderLogo, { provider, size: 48 }),
282
- /* @__PURE__ */ jsx("span", { className: "line-clamp-2 w-full text-xs font-medium text-foreground", children: name })
293
+ /* @__PURE__ */ jsxs("div", { className: "flex h-8 w-full flex-col justify-center leading-4", children: [
294
+ /* @__PURE__ */ jsx(
295
+ "span",
296
+ {
297
+ className: cn(
298
+ "w-full text-xs font-medium text-foreground",
299
+ live.accountDisplay ? "truncate" : "line-clamp-2"
300
+ ),
301
+ children: name
302
+ }
303
+ ),
304
+ live.accountDisplay ? /* @__PURE__ */ jsx(
305
+ "span",
306
+ {
307
+ className: "w-full truncate text-[11px] leading-4 text-muted-foreground",
308
+ "data-testid": `account-${provider.providerId}`,
309
+ children: live.accountDisplay
310
+ }
311
+ ) : null
312
+ ] })
283
313
  ]
284
314
  },
285
315
  `${provider.providerId}:${connectorId}`
@@ -298,13 +328,77 @@ function IntegrationsPanel({
298
328
  "hover:border-primary/40 hover:bg-accent/40 hover:shadow-sm focus:outline-none focus-visible:border-primary/50 focus-visible:ring-2 focus-visible:ring-primary/20"
299
329
  ),
300
330
  children: [
301
- /* @__PURE__ */ jsx(ProviderLogo, { provider, size: 56 }),
302
- /* @__PURE__ */ jsx("span", { className: "line-clamp-2 w-full text-xs font-medium text-foreground", children: name })
331
+ /* @__PURE__ */ jsx(
332
+ ProviderIcon,
333
+ {
334
+ id: provider.providerId,
335
+ iconUrl: provider.iconUrl,
336
+ displayName: provider.displayName,
337
+ size: LOGO_SIZE,
338
+ className: "rounded-2xl"
339
+ }
340
+ ),
341
+ /* @__PURE__ */ jsx("span", { className: "line-clamp-2 h-8 w-full text-xs font-medium leading-4 text-foreground", children: name })
303
342
  ]
304
343
  },
305
344
  `${provider.providerId}:${connectorId}`
306
345
  );
307
- }) })
346
+ }) }),
347
+ /* @__PURE__ */ jsx(
348
+ Dialog,
349
+ {
350
+ open: !!disconnectTarget,
351
+ onOpenChange: (open) => {
352
+ if (!open) closeDisconnect();
353
+ },
354
+ children: /* @__PURE__ */ jsxs(
355
+ DialogContent,
356
+ {
357
+ className: "max-w-sm",
358
+ onCloseAutoFocus: (e) => e.preventDefault(),
359
+ children: [
360
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
361
+ /* @__PURE__ */ jsxs(DialogTitle, { children: [
362
+ "Disconnect ",
363
+ disconnectTarget?.name ?? "integration",
364
+ "?"
365
+ ] }),
366
+ /* @__PURE__ */ jsxs(DialogDescription, { children: [
367
+ "This removes Sandbox's access to your",
368
+ " ",
369
+ disconnectTarget?.name ?? "this",
370
+ " account",
371
+ disconnectAccountLabel ? ` (${disconnectAccountLabel})` : "",
372
+ ". You can reconnect anytime."
373
+ ] })
374
+ ] }),
375
+ disconnectError ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", role: "alert", children: disconnectError }) : null,
376
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
377
+ /* @__PURE__ */ jsx(
378
+ Button,
379
+ {
380
+ variant: "outline",
381
+ onClick: closeDisconnect,
382
+ "data-testid": "cancel-disconnect",
383
+ children: "Cancel"
384
+ }
385
+ ),
386
+ /* @__PURE__ */ jsx(
387
+ Button,
388
+ {
389
+ variant: "destructive",
390
+ loading: isDisconnecting,
391
+ onClick: confirmDisconnect,
392
+ "data-testid": "confirm-disconnect",
393
+ children: "Disconnect"
394
+ }
395
+ )
396
+ ] })
397
+ ]
398
+ }
399
+ )
400
+ }
401
+ )
308
402
  ] });
309
403
  }
310
404
 
package/dist/styles.css CHANGED
@@ -2857,6 +2857,10 @@
2857
2857
  .text-\[length\:var\(--font-size-xl\,1\.25rem\)\] {
2858
2858
  font-size: var(--font-size-xl,1.25rem);
2859
2859
  }
2860
+ .leading-4 {
2861
+ --tw-leading: calc(var(--spacing) * 4);
2862
+ line-height: calc(var(--spacing) * 4);
2863
+ }
2860
2864
  .leading-6 {
2861
2865
  --tw-leading: calc(var(--spacing) * 6);
2862
2866
  line-height: calc(var(--spacing) * 6);
@@ -4555,6 +4559,11 @@
4555
4559
  }
4556
4560
  }
4557
4561
  }
4562
+ .focus-visible\:bg-background {
4563
+ &:focus-visible {
4564
+ background-color: var(--color-background);
4565
+ }
4566
+ }
4558
4567
  .focus-visible\:bg-primary\/40 {
4559
4568
  &:focus-visible {
4560
4569
  background-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
@@ -4568,6 +4577,11 @@
4568
4577
  background-color: transparent;
4569
4578
  }
4570
4579
  }
4580
+ .focus-visible\:text-foreground {
4581
+ &:focus-visible {
4582
+ color: var(--color-foreground);
4583
+ }
4584
+ }
4571
4585
  .focus-visible\:opacity-100 {
4572
4586
  &:focus-visible {
4573
4587
  opacity: 100%;
@@ -4611,6 +4625,14 @@
4611
4625
  }
4612
4626
  }
4613
4627
  }
4628
+ .focus-visible\:ring-primary\/40 {
4629
+ &:focus-visible {
4630
+ --tw-ring-color: color-mix(in srgb, hsl(var(--primary)) 40%, transparent);
4631
+ @supports (color: color-mix(in lab, red, red)) {
4632
+ --tw-ring-color: color-mix(in oklab, var(--color-primary) 40%, transparent);
4633
+ }
4634
+ }
4635
+ }
4614
4636
  .focus-visible\:ring-primary\/60 {
4615
4637
  &:focus-visible {
4616
4638
  --tw-ring-color: color-mix(in srgb, hsl(var(--primary)) 60%, transparent);
package/dist/workflows.js CHANGED
@@ -27,7 +27,7 @@ function retryImport(factory, retries = 2, delayMs = 350) {
27
27
  function lazyWorkflowGraph() {
28
28
  return lazy(
29
29
  () => retryImport(
30
- () => import("./WorkflowGraph-6IKZYPST.js").then((m) => ({ default: m.WorkflowGraph }))
30
+ () => import("./WorkflowGraph-EOV2P5AM.js").then((m) => ({ default: m.WorkflowGraph }))
31
31
  )
32
32
  );
33
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.46.0",
3
+ "version": "0.47.0",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",