@tangle-network/sandbox-ui 0.20.1 → 0.20.3

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.
@@ -127,8 +127,8 @@ function resolveModelBrandIdentity(model) {
127
127
  const labKey = normalizeBrandKey(model.logos?.lab ?? model.modelLab ?? inferModelLab(model, canonical, hostKey));
128
128
  const hostBase = brandInfo(hostKey);
129
129
  const labBase = brandInfo(labKey);
130
- const host = { ...hostBase, logoUrl: model.logos?.hostUrl ?? hostBase.logoUrl };
131
- const lab = { ...labBase, logoUrl: model.logos?.labUrl ?? labBase.logoUrl };
130
+ const host = model.logos?.hostUrl ? { ...hostBase, logoUrl: model.logos.hostUrl, monochrome: false } : hostBase;
131
+ const lab = model.logos?.labUrl ? { ...labBase, logoUrl: model.logos.labUrl, monochrome: false } : labBase;
132
132
  return {
133
133
  host,
134
134
  lab,
@@ -468,13 +468,33 @@ function BrandLogo({ brand, size, className }) {
468
468
  size === "md" && "h-7 w-7",
469
469
  className
470
470
  ),
471
- children: brand.logo === "tangle" ? /* @__PURE__ */ jsx(TangleKnot, { size: pixelSize, className: "h-full w-full" }) : brand.logoUrl ? /* @__PURE__ */ jsx("img", { src: brand.logoUrl, alt: "", className: "h-[72%] w-[72%] object-contain" }) : null
471
+ children: brand.logo === "tangle" ? /* @__PURE__ */ jsx(TangleKnot, { size: pixelSize, className: "h-full w-full" }) : brand.logoUrl && brand.monochrome ? /* @__PURE__ */ jsx(
472
+ "span",
473
+ {
474
+ "aria-hidden": true,
475
+ className: "h-[72%] w-[72%]",
476
+ style: {
477
+ backgroundColor: "hsl(var(--foreground))",
478
+ maskImage: cssUrl(brand.logoUrl),
479
+ maskSize: "contain",
480
+ maskRepeat: "no-repeat",
481
+ maskPosition: "center",
482
+ WebkitMaskImage: cssUrl(brand.logoUrl),
483
+ WebkitMaskSize: "contain",
484
+ WebkitMaskRepeat: "no-repeat",
485
+ WebkitMaskPosition: "center"
486
+ }
487
+ }
488
+ ) : brand.logoUrl ? /* @__PURE__ */ jsx("img", { src: brand.logoUrl, alt: "", className: "h-[72%] w-[72%] object-contain" }) : null
472
489
  }
473
490
  );
474
491
  }
475
492
  function hasRealLogo(brand) {
476
493
  return Boolean(brand.logoUrl || brand.logo);
477
494
  }
495
+ function cssUrl(url) {
496
+ return `url("${url.replace(/[\\"'#\n]/g, (char) => encodeURIComponent(char))}")`;
497
+ }
478
498
  function modelLogo(path) {
479
499
  return path;
480
500
  }
@@ -548,7 +568,7 @@ function brandLogo(key) {
548
568
  function brandMark(key) {
549
569
  if (key === "tangle" || key === "tcloud") return { logo: "tangle" };
550
570
  const logoUrl = brandLogo(key);
551
- return logoUrl ? { logoUrl } : {};
571
+ return logoUrl ? { logoUrl, monochrome: true } : {};
552
572
  }
553
573
  function inferModelLab(model, canonical, hostKey) {
554
574
  const name = model.name ?? "";
package/dist/dashboard.js CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  formatContext,
59
59
  formatPrice,
60
60
  formatPricing
61
- } from "./chunk-N5RYCDLD.js";
61
+ } from "./chunk-QNVVKMEW.js";
62
62
  import "./chunk-7ZA5SEK3.js";
63
63
  import "./chunk-EI44GEQ5.js";
64
64
  export {
package/dist/globals.css CHANGED
@@ -601,6 +601,10 @@
601
601
  .aspect-square {
602
602
  aspect-ratio: 1 / 1;
603
603
  }
604
+ .size-6 {
605
+ width: calc(var(--spacing) * 6);
606
+ height: calc(var(--spacing) * 6);
607
+ }
604
608
  .h-0\.5 {
605
609
  height: calc(var(--spacing) * 0.5);
606
610
  }
package/dist/index.js CHANGED
@@ -194,7 +194,7 @@ import {
194
194
  formatContext,
195
195
  formatPrice,
196
196
  formatPricing
197
- } from "./chunk-N5RYCDLD.js";
197
+ } from "./chunk-QNVVKMEW.js";
198
198
  import {
199
199
  Avatar,
200
200
  AvatarFallback,
@@ -20,6 +20,86 @@ function statusVariant(status) {
20
20
  function defaultConnectorOf(provider) {
21
21
  return provider.connectors?.[0]?.connectorId ?? provider.providerId;
22
22
  }
23
+ var PROVIDER_LOGO_SLUGS = {
24
+ gmail: "gmail",
25
+ googlemail: "gmail",
26
+ google: "google",
27
+ "google-drive": "googledrive",
28
+ googledrive: "googledrive",
29
+ drive: "googledrive",
30
+ "google-calendar": "googlecalendar",
31
+ googlecalendar: "googlecalendar",
32
+ calendar: "googlecalendar",
33
+ "google-sheets": "googlesheets",
34
+ instagram: "instagram",
35
+ facebook: "facebook",
36
+ meta: "meta",
37
+ linkedin: "linkedin",
38
+ twitter: "x",
39
+ x: "x",
40
+ tiktok: "tiktok",
41
+ youtube: "youtube",
42
+ slack: "slack",
43
+ discord: "discord",
44
+ notion: "notion",
45
+ hubspot: "hubspot",
46
+ salesforce: "salesforce",
47
+ stripe: "stripe",
48
+ github: "github",
49
+ gitlab: "gitlab",
50
+ linear: "linear",
51
+ jira: "jira",
52
+ asana: "asana",
53
+ trello: "trello",
54
+ dropbox: "dropbox",
55
+ box: "box",
56
+ outlook: "microsoftoutlook",
57
+ "microsoft-outlook": "microsoftoutlook",
58
+ "microsoft-teams": "microsoftteams",
59
+ zoom: "zoom",
60
+ shopify: "shopify",
61
+ mailchimp: "mailchimp",
62
+ airtable: "airtable",
63
+ zendesk: "zendesk",
64
+ intercom: "intercom"
65
+ };
66
+ function normalizeProviderId(id) {
67
+ return id.toLowerCase().replace(/[_\s]+/g, "-").replace(/-(business|oauth|api|app|v\d+)$/g, "");
68
+ }
69
+ function providerLogoUrl(provider) {
70
+ if (provider.iconUrl) return provider.iconUrl;
71
+ const id = provider.providerId.toLowerCase();
72
+ const slug = PROVIDER_LOGO_SLUGS[id] ?? PROVIDER_LOGO_SLUGS[normalizeProviderId(id)];
73
+ return slug ? `https://cdn.simpleicons.org/${slug}` : void 0;
74
+ }
75
+ function ProviderLogo({ provider }) {
76
+ const [failed, setFailed] = React.useState(false);
77
+ const url = providerLogoUrl(provider);
78
+ const label = (provider.displayName ?? provider.providerId).trim();
79
+ const initial = label.charAt(0).toUpperCase() || "?";
80
+ if (!url || failed) {
81
+ return /* @__PURE__ */ jsx(
82
+ "span",
83
+ {
84
+ className: "flex size-6 shrink-0 items-center justify-center rounded bg-muted text-[11px] font-semibold text-muted-foreground",
85
+ "aria-hidden": true,
86
+ children: initial
87
+ }
88
+ );
89
+ }
90
+ return /* @__PURE__ */ jsx(
91
+ "img",
92
+ {
93
+ src: url,
94
+ alt: "",
95
+ width: 24,
96
+ height: 24,
97
+ loading: "lazy",
98
+ className: "size-6 shrink-0 rounded object-contain",
99
+ onError: () => setFailed(true)
100
+ }
101
+ );
102
+ }
23
103
  function buildConnectionIndex(connections) {
24
104
  const index = /* @__PURE__ */ new Map();
25
105
  for (const conn of connections) {
@@ -78,6 +158,7 @@ function IntegrationsPanel({
78
158
  /* @__PURE__ */ jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-2 space-y-0", children: [
79
159
  /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
80
160
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
161
+ /* @__PURE__ */ jsx(ProviderLogo, { provider }),
81
162
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold capitalize text-foreground", children: headline }),
82
163
  live ? /* @__PURE__ */ jsx(Badge, { variant: statusVariant(live.status), className: "text-xs", children: live.status }) : null
83
164
  ] }),
package/dist/pages.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  TemplateCard,
7
7
  UsageChart,
8
8
  canonicalModelId
9
- } from "./chunk-N5RYCDLD.js";
9
+ } from "./chunk-QNVVKMEW.js";
10
10
  import {
11
11
  Badge,
12
12
  Button,
package/dist/styles.css CHANGED
@@ -601,6 +601,10 @@
601
601
  .aspect-square {
602
602
  aspect-ratio: 1 / 1;
603
603
  }
604
+ .size-6 {
605
+ width: calc(var(--spacing) * 6);
606
+ height: calc(var(--spacing) * 6);
607
+ }
604
608
  .h-0\.5 {
605
609
  height: calc(var(--spacing) * 0.5);
606
610
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
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",