@tangle-network/sandbox-ui 0.19.0 → 0.20.2

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.
@@ -149,6 +149,54 @@ interface CreditBalanceProps {
149
149
  }
150
150
  declare function CreditBalance({ amount, description, onTopUp, quickAmounts, className, }: CreditBalanceProps): react_jsx_runtime.JSX.Element;
151
151
 
152
+ /**
153
+ * Canonical "out of credits" UX, shared across every Tangle product.
154
+ *
155
+ * Backends emit a 402 with `{ error, code: "insufficient_balance", manageUrl,
156
+ * plan?, remainingBalanceUsd? }` when a billable action can't be funded. The
157
+ * frontend catches it, calls {@link parseInsufficientBalance} to extract the
158
+ * shape, and renders {@link OutOfCreditsModal} — a single "add credits /
159
+ * subscribe" CTA that links to the platform billing page (`manageUrl`).
160
+ *
161
+ * This replaces the per-app bespoke handling (silent failures, raw errors,
162
+ * un-clickable text) with one component so the funnel is uniform + testable.
163
+ */
164
+ declare const INSUFFICIENT_BALANCE_CODE = "insufficient_balance";
165
+ interface InsufficientBalance {
166
+ /** Platform billing URL to add credits / subscribe / connect a card. */
167
+ manageUrl: string;
168
+ /** Current plan, when the backend includes it. */
169
+ plan?: string;
170
+ /** Remaining balance (USD), when included. */
171
+ remainingBalanceUsd?: number;
172
+ /** Backend-supplied human message, when included. */
173
+ message?: string;
174
+ }
175
+ /**
176
+ * Detect + parse an insufficient-balance 402 from a parsed JSON body. Returns
177
+ * the typed shape when the body is an insufficient-balance error, else `null`.
178
+ * Falls back to the platform default billing URL when the backend omits
179
+ * `manageUrl` so the CTA is never dead.
180
+ */
181
+ declare function parseInsufficientBalance(payload: unknown, opts?: {
182
+ defaultManageUrl?: string;
183
+ }): InsufficientBalance | null;
184
+ interface OutOfCreditsModalProps {
185
+ /** Parsed insufficient-balance details (from {@link parseInsufficientBalance}). */
186
+ balance: InsufficientBalance | null;
187
+ /** Dismiss handler. When omitted the modal cannot be closed (hard paywall). */
188
+ onClose?: () => void;
189
+ /** Override the primary CTA label. Default "Add credits". */
190
+ ctaLabel?: string;
191
+ className?: string;
192
+ }
193
+ /**
194
+ * Modal shown when a user runs out of credits. Renders nothing when
195
+ * `balance` is null. The primary CTA opens the platform billing page where
196
+ * the user can add credits, subscribe, or connect a card for pay-per-use.
197
+ */
198
+ declare function OutOfCreditsModal({ balance, onClose, ctaLabel, className, }: OutOfCreditsModalProps): react_jsx_runtime.JSX.Element | null;
199
+
152
200
  interface ClusterStatusItem {
153
201
  icon?: React.ReactNode;
154
202
  label: string;
@@ -622,4 +670,4 @@ interface InfoPanelProps {
622
670
  }
623
671
  declare function InfoPanel({ label, title, description, className }: InfoPanelProps): react_jsx_runtime.JSX.Element;
624
672
 
625
- export { type Backend, BackendConfig, type BackendConfigProps, BackendSelector, type BackendSelectorProps, type BackendStatusData, ClusterStatusBar, type ClusterStatusBarProps, type ClusterStatusItem, CreditBalance, type CreditBalanceProps, DashboardLayout, type DashboardLayoutProps, type Profile as DashboardProfile, type SnapshotInfo as DashboardSnapshotInfo, type DashboardUser, type ExposedPort, type GitCommitData, GitPanel, type GitPanelProps, type GitStatusData, HARNESS_OPTIONS, HarnessPicker, type HarnessPickerProps, type HarnessType, InfoPanel, type InfoPanelProps, type Invoice, InvoiceTable, type InvoiceTableProps, type McpServer, type NavItem, NetworkConfig, type NetworkConfigData, type NetworkConfigProps, NewSandboxCard, type NewSandboxCardProps, type PlanCardData, PlanCards, type PlanCardsProps, type PlanFeature, PortsList, type PortsListProps, type ProcessInfo, ProcessList, type ProcessListProps, type ProductVariant, ProfileAvatar, type ProfileAvatarProps, ProfileComparison, type ProfileComparisonProps, ProfileSelector, type ProfileSelectorProps, PromoBanner, type PromoBannerProps, RailButton, type RailButtonProps, RailModeButton, type RailModeButtonProps, RailSeparator, type RailSeparatorProps, ResourceMeter, type ResourceMeterProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, type SandboxCardData, type SandboxCardProps, type SandboxStatus, SandboxTable, type SandboxTableProps, Sidebar, SidebarContent, type SidebarContentProps, SidebarPanel, SidebarPanelContent, type SidebarPanelContentProps, SidebarPanelHeader, type SidebarPanelHeaderProps, type SidebarPanelProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailFooter, type SidebarRailFooterProps, SidebarRailHeader, type SidebarRailHeaderProps, SidebarRailNav, type SidebarRailNavProps, type SidebarRailProps, type SidebarUser, SnapshotList, type SnapshotListProps, SystemLogsViewer, type SystemLogsViewerProps, type TeamRole, UsageSummary, type UsageSummaryData, type UsageSummaryProps, type Variant, VariantList, type VariantListProps, type VariantOutcome, type VariantStatus, canAdminSandbox, useSidebar };
673
+ export { type Backend, BackendConfig, type BackendConfigProps, BackendSelector, type BackendSelectorProps, type BackendStatusData, ClusterStatusBar, type ClusterStatusBarProps, type ClusterStatusItem, CreditBalance, type CreditBalanceProps, DashboardLayout, type DashboardLayoutProps, type Profile as DashboardProfile, type SnapshotInfo as DashboardSnapshotInfo, type DashboardUser, type ExposedPort, type GitCommitData, GitPanel, type GitPanelProps, type GitStatusData, HARNESS_OPTIONS, HarnessPicker, type HarnessPickerProps, type HarnessType, INSUFFICIENT_BALANCE_CODE, InfoPanel, type InfoPanelProps, type InsufficientBalance, type Invoice, InvoiceTable, type InvoiceTableProps, type McpServer, type NavItem, NetworkConfig, type NetworkConfigData, type NetworkConfigProps, NewSandboxCard, type NewSandboxCardProps, OutOfCreditsModal, type OutOfCreditsModalProps, type PlanCardData, PlanCards, type PlanCardsProps, type PlanFeature, PortsList, type PortsListProps, type ProcessInfo, ProcessList, type ProcessListProps, type ProductVariant, ProfileAvatar, type ProfileAvatarProps, ProfileComparison, type ProfileComparisonProps, ProfileSelector, type ProfileSelectorProps, PromoBanner, type PromoBannerProps, RailButton, type RailButtonProps, RailModeButton, type RailModeButtonProps, RailSeparator, type RailSeparatorProps, ResourceMeter, type ResourceMeterProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, type SandboxCardData, type SandboxCardProps, type SandboxStatus, SandboxTable, type SandboxTableProps, Sidebar, SidebarContent, type SidebarContentProps, SidebarPanel, SidebarPanelContent, type SidebarPanelContentProps, SidebarPanelHeader, type SidebarPanelHeaderProps, type SidebarPanelProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarRail, SidebarRailFooter, type SidebarRailFooterProps, SidebarRailHeader, type SidebarRailHeaderProps, SidebarRailNav, type SidebarRailNavProps, type SidebarRailProps, type SidebarUser, SnapshotList, type SnapshotListProps, SystemLogsViewer, type SystemLogsViewerProps, type TeamRole, UsageSummary, type UsageSummaryData, type UsageSummaryProps, type Variant, VariantList, type VariantListProps, type VariantOutcome, type VariantStatus, canAdminSandbox, parseInsufficientBalance, useSidebar };
package/dist/dashboard.js CHANGED
@@ -7,9 +7,11 @@ import {
7
7
  GitPanel,
8
8
  HARNESS_OPTIONS,
9
9
  HarnessPicker,
10
+ INSUFFICIENT_BALANCE_CODE,
10
11
  InvoiceTable,
11
12
  NetworkConfig,
12
13
  NewSandboxCard,
14
+ OutOfCreditsModal,
13
15
  PlanCards,
14
16
  PortsList,
15
17
  ProcessList,
@@ -42,8 +44,9 @@ import {
42
44
  UsageSummary,
43
45
  VariantList,
44
46
  canAdminSandbox,
47
+ parseInsufficientBalance,
45
48
  useSidebar
46
- } from "./chunk-5I363RL7.js";
49
+ } from "./chunk-R6QNJQRH.js";
47
50
  import {
48
51
  BillingDashboard,
49
52
  InfoPanel,
@@ -68,11 +71,13 @@ export {
68
71
  GitPanel,
69
72
  HARNESS_OPTIONS,
70
73
  HarnessPicker,
74
+ INSUFFICIENT_BALANCE_CODE,
71
75
  InfoPanel,
72
76
  InvoiceTable,
73
77
  ModelPicker,
74
78
  NetworkConfig,
75
79
  NewSandboxCard,
80
+ OutOfCreditsModal,
76
81
  PlanCards,
77
82
  PortsList,
78
83
  PricingPage,
@@ -112,5 +117,6 @@ export {
112
117
  formatContext,
113
118
  formatPrice,
114
119
  formatPricing,
120
+ parseInsufficientBalance,
115
121
  useSidebar
116
122
  };
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.d.ts CHANGED
@@ -8,7 +8,7 @@ export { ArtifactAgentDock, ArtifactAgentDockProps, ArtifactAgentDockTransport,
8
8
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from '@tangle-network/ui/run';
9
9
  export { CommandPreview, DiffPreview, GlobResultsPreview, GrepResultsPreview, QuestionPreview, WebSearchPreview, WriteFilePreview } from '@tangle-network/ui/tool-previews';
10
10
  export { FileArtifactPane, FileArtifactPaneProps, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, filterFileTree } from '@tangle-network/ui/files';
11
- export { Backend, BackendConfig, BackendConfigProps, BackendSelector, BackendSelectorProps, BackendStatusData, ClusterStatusBar, ClusterStatusBarProps, ClusterStatusItem, CreditBalance, CreditBalanceProps, DashboardLayout, DashboardLayoutProps, DashboardProfile, DashboardSnapshotInfo, DashboardUser, ExposedPort, GitCommitData, GitPanel, GitPanelProps, GitStatusData, HARNESS_OPTIONS, HarnessPicker, HarnessPickerProps, HarnessType, InfoPanel, InfoPanelProps, Invoice, InvoiceTable, InvoiceTableProps, McpServer, NavItem, NetworkConfig, NetworkConfigData, NetworkConfigProps, NewSandboxCard, NewSandboxCardProps, PlanCardData, PlanCards, PlanCardsProps, PlanFeature, PortsList, PortsListProps, ProcessInfo, ProcessList, ProcessListProps, ProductVariant, ProfileAvatar, ProfileAvatarProps, ProfileComparison, ProfileComparisonProps, ProfileSelector, ProfileSelectorProps, PromoBanner, PromoBannerProps, RailButton, RailButtonProps, RailModeButton, RailModeButtonProps, RailSeparator, RailSeparatorProps, ResourceMeter, ResourceMeterProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxCardData, SandboxCardProps, SandboxStatus, SandboxTable, SandboxTableProps, Sidebar, SidebarContent, SidebarContentProps, SidebarPanel, SidebarPanelContent, SidebarPanelContentProps, SidebarPanelHeader, SidebarPanelHeaderProps, SidebarPanelProps, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailFooter, SidebarRailFooterProps, SidebarRailHeader, SidebarRailHeaderProps, SidebarRailNav, SidebarRailNavProps, SidebarRailProps, SidebarUser, SnapshotList, SnapshotListProps, SystemLogsViewer, SystemLogsViewerProps, TeamRole, UsageSummary, UsageSummaryData, UsageSummaryProps, Variant, VariantList, VariantListProps, VariantOutcome, VariantStatus, canAdminSandbox, useSidebar } from './dashboard.js';
11
+ export { Backend, BackendConfig, BackendConfigProps, BackendSelector, BackendSelectorProps, BackendStatusData, ClusterStatusBar, ClusterStatusBarProps, ClusterStatusItem, CreditBalance, CreditBalanceProps, DashboardLayout, DashboardLayoutProps, DashboardProfile, DashboardSnapshotInfo, DashboardUser, ExposedPort, GitCommitData, GitPanel, GitPanelProps, GitStatusData, HARNESS_OPTIONS, HarnessPicker, HarnessPickerProps, HarnessType, INSUFFICIENT_BALANCE_CODE, InfoPanel, InfoPanelProps, InsufficientBalance, Invoice, InvoiceTable, InvoiceTableProps, McpServer, NavItem, NetworkConfig, NetworkConfigData, NetworkConfigProps, NewSandboxCard, NewSandboxCardProps, OutOfCreditsModal, OutOfCreditsModalProps, PlanCardData, PlanCards, PlanCardsProps, PlanFeature, PortsList, PortsListProps, ProcessInfo, ProcessList, ProcessListProps, ProductVariant, ProfileAvatar, ProfileAvatarProps, ProfileComparison, ProfileComparisonProps, ProfileSelector, ProfileSelectorProps, PromoBanner, PromoBannerProps, RailButton, RailButtonProps, RailModeButton, RailModeButtonProps, RailSeparator, RailSeparatorProps, ResourceMeter, ResourceMeterProps, SIDEBAR_MOBILE_WIDTH, SIDEBAR_PANEL_WIDTH, SIDEBAR_RAIL_WIDTH, SIDEBAR_TOTAL_WIDTH, SandboxCard, SandboxCardData, SandboxCardProps, SandboxStatus, SandboxTable, SandboxTableProps, Sidebar, SidebarContent, SidebarContentProps, SidebarPanel, SidebarPanelContent, SidebarPanelContentProps, SidebarPanelHeader, SidebarPanelHeaderProps, SidebarPanelProps, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarRail, SidebarRailFooter, SidebarRailFooterProps, SidebarRailHeader, SidebarRailHeaderProps, SidebarRailNav, SidebarRailNavProps, SidebarRailProps, SidebarUser, SnapshotList, SnapshotListProps, SystemLogsViewer, SystemLogsViewerProps, TeamRole, UsageSummary, UsageSummaryData, UsageSummaryProps, Variant, VariantList, VariantListProps, VariantOutcome, VariantStatus, canAdminSandbox, parseInsufficientBalance, useSidebar } from './dashboard.js';
12
12
  export { B as BillingBalance, a as BillingDashboard, b as BillingDashboardProps, c as BillingSubscription, d as BillingUsage, M as ModelInfo, e as ModelPicker, f as ModelPickerProps, g as ModelPickerVariant, P as PricingPage, h as PricingPageProps, i as PricingTier, T as TemplateCard, j as TemplateCardData, k as TemplateCardProps, U as UsageChart, l as UsageChartProps, m as UsageDataPoint, n as canonicalModelId, o as formatContext, p as formatPrice, q as formatPricing } from './template-card-gf-InrfN.js';
13
13
  export { AuthHeader, AuthHeaderProps, GitHubLoginButton, GitHubLoginButtonProps, LoginLayout, LoginLayoutProps, SessionUser, UserMenu, UserMenuProps } from '@tangle-network/ui/auth';
14
14
  export { TangleLoginButton, TangleLoginButtonProps } from './auth.js';
package/dist/index.js CHANGED
@@ -143,9 +143,11 @@ import {
143
143
  GitPanel,
144
144
  HARNESS_OPTIONS,
145
145
  HarnessPicker,
146
+ INSUFFICIENT_BALANCE_CODE,
146
147
  InvoiceTable,
147
148
  NetworkConfig,
148
149
  NewSandboxCard,
150
+ OutOfCreditsModal,
149
151
  PlanCards,
150
152
  PortsList,
151
153
  ProcessList,
@@ -178,8 +180,9 @@ import {
178
180
  UsageSummary,
179
181
  VariantList,
180
182
  canAdminSandbox,
183
+ parseInsufficientBalance,
181
184
  useSidebar
182
- } from "./chunk-5I363RL7.js";
185
+ } from "./chunk-R6QNJQRH.js";
183
186
  import {
184
187
  BillingDashboard,
185
188
  InfoPanel,
@@ -372,6 +375,7 @@ export {
372
375
  GrepResultsPreview,
373
376
  HARNESS_OPTIONS,
374
377
  HarnessPicker,
378
+ INSUFFICIENT_BALANCE_CODE,
375
379
  InfoPanel,
376
380
  InlineCode,
377
381
  InlineThinkingItem,
@@ -388,6 +392,7 @@ export {
388
392
  NetworkConfig,
389
393
  NewSandboxCard,
390
394
  OpenUIArtifactRenderer,
395
+ OutOfCreditsModal,
391
396
  PlanCards,
392
397
  PortsList,
393
398
  PricingPage,
@@ -518,6 +523,7 @@ export {
518
523
  hasBackgroundRunningSessions,
519
524
  isStreamingAtom,
520
525
  messagesAtom,
526
+ parseInsufficientBalance,
521
527
  partMapAtom,
522
528
  registerActiveSession,
523
529
  resetActiveSessions,
@@ -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/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.19.0",
3
+ "version": "0.20.2",
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",