@faskai/ui-commons 0.0.0-alpha.24 → 0.0.0-alpha.25

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.
@@ -4,8 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.AppSearchGrid = AppSearchGrid;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
- const utils_1 = require("../../lib/utils");
7
+ const lucide_react_1 = require("lucide-react");
8
8
  const app_icon_1 = require("./app-icon");
9
+ const badge_1 = require("../ui/badge");
10
+ const button_1 = require("../ui/button");
9
11
  function AppSearchGrid({ connectedAppKeys, onSearch, onConnect, connecting, initialApps, }) {
10
12
  const [query, setQuery] = (0, react_1.useState)('');
11
13
  const [apps, setApps] = (0, react_1.useState)(initialApps || []);
@@ -32,5 +34,5 @@ function AppSearchGrid({ connectedAppKeys, onSearch, onConnect, connecting, init
32
34
  function isConnected(slug) {
33
35
  return connectedAppKeys.includes(slug);
34
36
  }
35
- return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-sm font-medium", children: "Connect Apps" }), (0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground text-xs", children: "Search and connect apps for your agent." })] }), (0, jsx_runtime_1.jsx)("input", { className: "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border px-3 py-1 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", placeholder: "Search apps (e.g. Slack, Google Sheets, HubSpot)...", value: query, onChange: (e) => setQuery(e.target.value) }), searching && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 py-4", children: [(0, jsx_runtime_1.jsxs)("svg", { className: "size-4 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), (0, jsx_runtime_1.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), (0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground text-sm", children: "Searching..." })] })), apps.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-3", children: apps.map((app) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 rounded-lg border p-3", children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: app.img_src, alt: app.name, className: "size-8" }), (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0 flex-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "truncate text-sm font-medium", children: app.name }), isConnected(app.name_slug) && ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground text-xs", children: "Connected" }))] }), isConnected(app.name_slug) ? ((0, jsx_runtime_1.jsx)("span", { className: "bg-primary text-primary-foreground inline-flex items-center rounded-md px-2.5 py-0.5 text-xs font-medium", children: "Connected" })) : ((0, jsx_runtime_1.jsxs)("button", { className: (0, utils_1.cn)('inline-flex items-center rounded-md border px-3 py-1.5 text-sm font-medium', 'hover:bg-accent disabled:opacity-50'), onClick: () => onConnect(app), disabled: connecting === app.name_slug, children: [connecting === app.name_slug && ((0, jsx_runtime_1.jsxs)("svg", { className: "mr-1 size-3 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [(0, jsx_runtime_1.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), (0, jsx_runtime_1.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] })), "Connect"] }))] }, app.name_slug))) }))] }));
37
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-sm font-medium", children: "Connect Apps" }), (0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground text-xs", children: "Search and connect apps for your agent." })] }), (0, jsx_runtime_1.jsx)("input", { className: "border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border px-3 py-1 text-sm shadow-sm transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", placeholder: "Search apps (e.g. Slack, Google Sheets, HubSpot)...", value: query, onChange: (e) => setQuery(e.target.value) }), searching && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 py-4", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "size-4 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground text-sm", children: "Searching..." })] })), apps.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-3", children: apps.map((app) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 rounded-lg border p-3", children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: app.img_src, alt: app.name, className: "size-8" }), (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0 flex-1", children: [(0, jsx_runtime_1.jsx)("p", { className: "truncate text-sm font-medium", children: app.name }), isConnected(app.name_slug) && ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground text-xs", children: "Connected" }))] }), isConnected(app.name_slug) ? ((0, jsx_runtime_1.jsx)(badge_1.Badge, { children: "Connected" })) : ((0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "outline", size: "sm", onClick: () => onConnect(app), disabled: connecting === app.name_slug, children: [connecting === app.name_slug && ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "animate-spin" })), "Connect"] }))] }, app.name_slug))) }))] }));
36
38
  }
@@ -3,10 +3,16 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.AvailableAppsList = AvailableAppsList;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const lucide_react_1 = require("lucide-react");
6
7
  const app_icon_1 = require("./app-icon");
8
+ const card_1 = require("../ui/card");
9
+ const button_1 = require("../ui/button");
7
10
  function AvailableAppsList({ connections, onConnect, connecting, }) {
8
11
  const available = connections.filter((c) => c.status !== 'connected');
9
12
  if (available.length === 0)
10
13
  return null;
11
- return ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: available.map((conn) => ((0, jsx_runtime_1.jsxs)("div", { className: "rounded-lg border p-4 transition-all hover:shadow-md", children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-3 flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-background flex size-12 shrink-0 items-center justify-center rounded-lg border p-2", children: (0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-full object-contain" }) }), (0, jsx_runtime_1.jsx)("div", { className: "min-w-0 flex-1", children: (0, jsx_runtime_1.jsx)("p", { className: "truncate text-base font-semibold", children: conn.app?.name }) })] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => onConnect(conn), disabled: connecting === conn.appKey, className: "bg-primary text-primary-foreground hover:bg-primary/90 flex w-full items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium disabled:opacity-50", children: [(0, jsx_runtime_1.jsx)("svg", { className: "size-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }), connecting === conn.appKey ? 'Connecting...' : 'Connect'] })] }, conn.id || conn.appKey))) }));
14
+ return ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: available.map((conn) => {
15
+ const isConnecting = connecting === conn.appKey;
16
+ return ((0, jsx_runtime_1.jsxs)(card_1.Card, { className: "gap-4 py-4", children: [(0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "flex-row items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-background flex size-12 shrink-0 items-center justify-center rounded-lg border p-2", children: (0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-full object-contain" }) }), (0, jsx_runtime_1.jsx)("p", { className: "min-w-0 flex-1 truncate text-base font-semibold", children: conn.app?.name })] }), (0, jsx_runtime_1.jsx)(card_1.CardFooter, { children: (0, jsx_runtime_1.jsxs)(button_1.Button, { className: "w-full", onClick: () => onConnect(conn), disabled: isConnecting, children: [isConnecting ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "animate-spin" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Link, {})), isConnecting ? 'Connecting...' : 'Connect'] }) })] }, conn.id || conn.appKey));
17
+ }) }));
12
18
  }
@@ -3,20 +3,22 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.ConnectedAppsList = ConnectedAppsList;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
- const utils_1 = require("../../lib/utils");
6
+ const lucide_react_1 = require("lucide-react");
7
7
  const app_icon_1 = require("./app-icon");
8
+ const card_1 = require("../ui/card");
9
+ const badge_1 = require("../ui/badge");
10
+ const button_1 = require("../ui/button");
8
11
  function ConnectedAppsList({ connections, variant, onReimport, onDisconnect, reimporting, disconnecting, }) {
9
12
  const connected = connections.filter((c) => c.status === 'connected');
10
13
  if (connected.length === 0)
11
14
  return null;
12
15
  if (variant === 'badges') {
13
- return ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2", children: connected.map((conn) => ((0, jsx_runtime_1.jsxs)("span", { className: "bg-primary text-primary-foreground inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium", children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-4" }), conn.app?.name] }, conn.appKey))) }));
16
+ return ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2", children: connected.map((conn) => ((0, jsx_runtime_1.jsxs)(badge_1.Badge, { children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-4" }), conn.app?.name] }, conn.appKey))) }));
14
17
  }
15
18
  // cards variant
16
- return ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: connected.map((conn) => ((0, jsx_runtime_1.jsxs)("div", { className: "relative rounded-lg border p-4 transition-all hover:shadow-md", children: [(0, jsx_runtime_1.jsx)("div", { className: "absolute top-0 right-0", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-primary/10 rounded-bl-lg p-2", children: (0, jsx_runtime_1.jsx)("svg", { className: "text-primary size-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }) }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3 flex items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-background flex size-12 shrink-0 items-center justify-center rounded-lg border p-2", children: (0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-full object-contain" }) }), (0, jsx_runtime_1.jsx)("div", { className: "min-w-0 flex-1", children: (0, jsx_runtime_1.jsx)("p", { className: "truncate text-base font-semibold", children: conn.app?.name }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "inline-flex w-full items-center justify-center rounded-md border px-2.5 py-0.5 text-xs font-medium", children: "Connected" }), onReimport && ((0, jsx_runtime_1.jsxs)("button", { onClick: () => onReimport(conn), disabled: reimporting === (conn.providerConnectionId || conn.appKey), className: (0, utils_1.cn)('flex w-full items-center justify-center gap-2 rounded-md border px-3 py-1.5 text-sm', 'hover:bg-accent disabled:opacity-50'), children: [(0, jsx_runtime_1.jsx)("svg", { className: (0, utils_1.cn)('size-4', reimporting === (conn.providerConnectionId || conn.appKey) &&
17
- 'animate-spin'), fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) }), reimporting === (conn.providerConnectionId || conn.appKey)
18
- ? 'Reimporting...'
19
- : 'Reimport'] })), onDisconnect && ((0, jsx_runtime_1.jsxs)("button", { onClick: () => onDisconnect(conn), disabled: disconnecting === (conn.id || conn.appKey), className: (0, utils_1.cn)('text-destructive hover:text-destructive flex w-full items-center justify-center gap-2 rounded-md border px-3 py-1.5 text-sm', 'hover:bg-accent disabled:opacity-50'), children: [(0, jsx_runtime_1.jsx)("svg", { className: "size-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13.181 8.68a4 4 0 00-5.5-5.5M6.5 12.5l-2-2m8 8l-2-2m2-6l6 6m-2-6l2 2" }) }), disconnecting === (conn.id || conn.appKey)
20
- ? 'Disconnecting...'
21
- : 'Disconnect'] }))] })] }, conn.id || conn.appKey))) }));
19
+ return ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: connected.map((conn) => {
20
+ const isReimporting = reimporting === (conn.providerConnectionId || conn.appKey);
21
+ const isDisconnecting = disconnecting === (conn.id || conn.appKey);
22
+ return ((0, jsx_runtime_1.jsxs)(card_1.Card, { className: "gap-4 py-4", children: [(0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "flex-row items-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-background flex size-12 shrink-0 items-center justify-center rounded-lg border p-2", children: (0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-full object-contain" }) }), (0, jsx_runtime_1.jsx)("p", { className: "min-w-0 flex-1 truncate text-base font-semibold", children: conn.app?.name }), (0, jsx_runtime_1.jsx)(card_1.CardAction, { children: (0, jsx_runtime_1.jsxs)(badge_1.Badge, { variant: "outline", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "size-3" }), "Connected"] }) })] }), (0, jsx_runtime_1.jsxs)(card_1.CardFooter, { className: "gap-2", children: [onReimport && ((0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "outline", size: "sm", onClick: () => onReimport(conn), disabled: isReimporting, children: [isReimporting ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "animate-spin" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCw, {})), isReimporting ? 'Reimporting...' : 'Reimport'] })), onDisconnect && ((0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "outline", size: "sm", className: "text-destructive hover:text-destructive", onClick: () => onDisconnect(conn), disabled: isDisconnecting, children: [isDisconnecting ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "animate-spin" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.Unlink, {})), isDisconnecting ? 'Disconnecting...' : 'Disconnect'] }))] })] }, conn.id || conn.appKey));
23
+ }) }));
22
24
  }
@@ -2,8 +2,7 @@ import type { FaskConnection } from '../../types/connections';
2
2
  interface ConnectionsPanelProps {
3
3
  variant: 'full-page' | 'compact';
4
4
  showSearch?: boolean;
5
- showReimport?: boolean;
6
5
  onConnectionsLoaded?: (connections: FaskConnection[]) => void;
7
6
  }
8
- export declare function ConnectionsPanel({ variant, showSearch, showReimport, onConnectionsLoaded, }: ConnectionsPanelProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function ConnectionsPanel({ variant, showSearch, onConnectionsLoaded, }: ConnectionsPanelProps): import("react/jsx-runtime").JSX.Element;
9
8
  export {};
@@ -8,12 +8,14 @@ const connections_api_provider_1 = require("./connections-api-provider");
8
8
  const connected_apps_list_1 = require("./connected-apps-list");
9
9
  const available_apps_list_1 = require("./available-apps-list");
10
10
  const app_search_grid_1 = require("./app-search-grid");
11
- function ConnectionsPanel({ variant, showSearch, showReimport, onConnectionsLoaded, }) {
11
+ const app_icon_1 = require("./app-icon");
12
+ const badge_1 = require("../ui/badge");
13
+ const card_1 = require("../ui/card");
14
+ function ConnectionsPanel({ variant, showSearch, onConnectionsLoaded, }) {
12
15
  const api = (0, connections_api_provider_1.useConnectionsApi)();
13
16
  const [connections, setConnections] = (0, react_1.useState)([]);
14
17
  const [loading, setLoading] = (0, react_1.useState)(true);
15
18
  const [connecting, setConnecting] = (0, react_1.useState)(null);
16
- const [reimporting, setReimporting] = (0, react_1.useState)(null);
17
19
  const [disconnecting, setDisconnecting] = (0, react_1.useState)(null);
18
20
  const prevConnectionsRef = (0, react_1.useRef)([]);
19
21
  const pollIntervalRef = (0, react_1.useRef)(null);
@@ -66,16 +68,6 @@ function ConnectionsPanel({ variant, showSearch, showReimport, onConnectionsLoad
66
68
  setConnecting(null);
67
69
  }
68
70
  }
69
- async function handleReimport(conn) {
70
- const key = conn.providerConnectionId || conn.appKey;
71
- setReimporting(key);
72
- try {
73
- await api.reimport?.(conn.providerConnectionId, conn.appKey);
74
- }
75
- finally {
76
- setReimporting(null);
77
- }
78
- }
79
71
  async function handleDisconnect(conn) {
80
72
  const key = conn.id || conn.appKey;
81
73
  setDisconnecting(key);
@@ -91,25 +83,15 @@ function ConnectionsPanel({ variant, showSearch, showReimport, onConnectionsLoad
91
83
  await handleConnect(app);
92
84
  }
93
85
  if (loading) {
94
- return ((0, jsx_runtime_1.jsx)("div", { className: "space-y-4", children: [1, 2, 3].map((i) => ((0, jsx_runtime_1.jsx)("div", { className: "bg-muted/50 h-20 animate-pulse rounded-lg" }, i))) }));
86
+ return ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: [1, 2, 3].map((i) => ((0, jsx_runtime_1.jsx)(card_1.Card, { className: "h-28 animate-pulse bg-muted/50" }, i))) }));
95
87
  }
96
88
  if (variant === 'compact') {
97
89
  const availableAppsWithActions = connections.filter((c) => c.status !== 'connected' && c.actions && c.actions.length > 0);
98
90
  return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(connectedAppKeys.length > 0 ||
99
91
  availableAppsWithActions.length > 0) && ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-3", children: [(0, jsx_runtime_1.jsx)("h3", { className: "text-sm font-medium", children: "Connected Apps" }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-2", children: [connections
100
92
  .filter((c) => c.status === 'connected')
101
- .map((conn) => ((0, jsx_runtime_1.jsxs)("span", { className: "bg-primary text-primary-foreground inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium", children: [(0, jsx_runtime_1.jsx)(AppIconInline, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name }), conn.app?.name] }, conn.appKey))), availableAppsWithActions.map((conn) => ((0, jsx_runtime_1.jsxs)("span", { className: "bg-secondary text-secondary-foreground inline-flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs font-medium opacity-60", children: [(0, jsx_runtime_1.jsx)(AppIconInline, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name }), conn.app?.name, (0, jsx_runtime_1.jsx)("span", { className: "text-[10px]", children: "Not connected" })] }, conn.appKey)))] })] })), showSearch && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("hr", { className: "border-border" }), (0, jsx_runtime_1.jsx)(app_search_grid_1.AppSearchGrid, { connectedAppKeys: connectedAppKeys, onSearch: (q) => api.searchApps(q), onConnect: handleSearchConnect, connecting: connecting })] }))] }));
93
+ .map((conn) => ((0, jsx_runtime_1.jsxs)(badge_1.Badge, { children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-4" }), conn.app?.name] }, conn.appKey))), availableAppsWithActions.map((conn) => ((0, jsx_runtime_1.jsxs)(badge_1.Badge, { variant: "secondary", className: "opacity-60", children: [(0, jsx_runtime_1.jsx)(app_icon_1.AppIcon, { src: conn.app?.img, icon: conn.app?.icon, alt: conn.app?.name, className: "size-4" }), conn.app?.name, (0, jsx_runtime_1.jsx)("span", { className: "text-[10px]", children: "Not connected" })] }, conn.appKey)))] })] })), showSearch && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("hr", { className: "border-border" }), (0, jsx_runtime_1.jsx)(app_search_grid_1.AppSearchGrid, { connectedAppKeys: connectedAppKeys, onSearch: (q) => api.searchApps(q), onConnect: handleSearchConnect, connecting: connecting })] }))] }));
102
94
  }
103
95
  // full-page variant
104
- return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsx)(connected_apps_list_1.ConnectedAppsList, { connections: connections, variant: "cards", onReimport: showReimport ? handleReimport : undefined, onDisconnect: handleDisconnect, reimporting: reimporting, disconnecting: disconnecting }), (0, jsx_runtime_1.jsx)(available_apps_list_1.AvailableAppsList, { connections: connections, onConnect: handleConnect, connecting: connecting }), showSearch && ((0, jsx_runtime_1.jsx)(app_search_grid_1.AppSearchGrid, { connectedAppKeys: connectedAppKeys, onSearch: (q) => api.searchApps(q), onConnect: handleSearchConnect, connecting: connecting }))] }));
105
- }
106
- /**
107
- * Tiny inline icon for badge usage (avoids importing the full AppIcon component tree).
108
- */
109
- function AppIconInline({ src, icon, alt, }) {
110
- if (src) {
111
- return (0, jsx_runtime_1.jsx)("img", { src: src, alt: alt, className: "size-4 rounded" });
112
- }
113
- // For badges, just show a small placeholder square
114
- return ((0, jsx_runtime_1.jsx)("span", { className: "bg-muted-foreground/20 inline-block size-4 rounded" }));
96
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsx)(connected_apps_list_1.ConnectedAppsList, { connections: connections, variant: "cards", onDisconnect: handleDisconnect, disconnecting: disconnecting }), (0, jsx_runtime_1.jsx)(available_apps_list_1.AvailableAppsList, { connections: connections, onConnect: handleConnect, connecting: connecting }), showSearch && ((0, jsx_runtime_1.jsx)(app_search_grid_1.AppSearchGrid, { connectedAppKeys: connectedAppKeys, onSearch: (q) => api.searchApps(q), onConnect: handleSearchConnect, connecting: connecting }))] }));
115
97
  }
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const badgeVariants: (props?: ({
4
+ variant?: "default" | "secondary" | "destructive" | "outline" | null | undefined;
5
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
6
+ declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & {
7
+ asChild?: boolean;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ export { Badge, badgeVariants };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.badgeVariants = void 0;
4
+ exports.Badge = Badge;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_slot_1 = require("@radix-ui/react-slot");
7
+ const class_variance_authority_1 = require("class-variance-authority");
8
+ const utils_1 = require("../../lib/utils");
9
+ const badgeVariants = (0, class_variance_authority_1.cva)('inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', {
10
+ variants: {
11
+ variant: {
12
+ default: 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
13
+ secondary: 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
14
+ destructive: 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
15
+ outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ variant: 'default',
20
+ },
21
+ });
22
+ exports.badgeVariants = badgeVariants;
23
+ function Badge({ className, variant, asChild = false, ...props }) {
24
+ const Comp = asChild ? react_slot_1.Slot : 'span';
25
+ return ((0, jsx_runtime_1.jsx)(Comp, { "data-slot": "badge", className: (0, utils_1.cn)(badgeVariants({ variant }), className), ...props }));
26
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
5
+ size?: "icon" | "default" | "sm" | "lg" | null | undefined;
6
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
8
+ asChild?: boolean;
9
+ }): import("react/jsx-runtime").JSX.Element;
10
+ export { Button, buttonVariants };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buttonVariants = void 0;
4
+ exports.Button = Button;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_slot_1 = require("@radix-ui/react-slot");
7
+ const class_variance_authority_1 = require("class-variance-authority");
8
+ const utils_1 = require("../../lib/utils");
9
+ const buttonVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
13
+ destructive: 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
14
+ outline: 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
15
+ secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
16
+ ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
17
+ link: 'text-primary underline-offset-4 hover:underline',
18
+ },
19
+ size: {
20
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
21
+ sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
22
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
23
+ icon: 'size-9',
24
+ },
25
+ },
26
+ defaultVariants: {
27
+ variant: 'default',
28
+ size: 'default',
29
+ },
30
+ });
31
+ exports.buttonVariants = buttonVariants;
32
+ function Button({ className, variant, size, asChild = false, ...props }) {
33
+ const Comp = asChild ? react_slot_1.Slot : 'button';
34
+ return ((0, jsx_runtime_1.jsx)(Comp, { "data-slot": "button", className: (0, utils_1.cn)(buttonVariants({ variant, size, className })), ...props }));
35
+ }
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ declare function Card({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
3
+ declare function CardHeader({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
4
+ declare function CardTitle({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
5
+ declare function CardDescription({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
6
+ declare function CardAction({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
7
+ declare function CardContent({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
8
+ declare function CardFooter({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
9
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Card = Card;
4
+ exports.CardHeader = CardHeader;
5
+ exports.CardFooter = CardFooter;
6
+ exports.CardTitle = CardTitle;
7
+ exports.CardAction = CardAction;
8
+ exports.CardDescription = CardDescription;
9
+ exports.CardContent = CardContent;
10
+ const jsx_runtime_1 = require("react/jsx-runtime");
11
+ const utils_1 = require("../../lib/utils");
12
+ function Card({ className, ...props }) {
13
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card", className: (0, utils_1.cn)('bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm', className), ...props }));
14
+ }
15
+ function CardHeader({ className, ...props }) {
16
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-header", className: (0, utils_1.cn)('@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6', className), ...props }));
17
+ }
18
+ function CardTitle({ className, ...props }) {
19
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-title", className: (0, utils_1.cn)('leading-none font-semibold', className), ...props }));
20
+ }
21
+ function CardDescription({ className, ...props }) {
22
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-description", className: (0, utils_1.cn)('text-muted-foreground text-sm', className), ...props }));
23
+ }
24
+ function CardAction({ className, ...props }) {
25
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-action", className: (0, utils_1.cn)('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className), ...props }));
26
+ }
27
+ function CardContent({ className, ...props }) {
28
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-content", className: (0, utils_1.cn)('px-6', className), ...props }));
29
+ }
30
+ function CardFooter({ className, ...props }) {
31
+ return ((0, jsx_runtime_1.jsx)("div", { "data-slot": "card-footer", className: (0, utils_1.cn)('flex items-center px-6 [.border-t]:pt-6', className), ...props }));
32
+ }
package/dist/index.d.ts CHANGED
@@ -8,4 +8,7 @@ export { AppSearchGrid } from './components/connections/app-search-grid';
8
8
  export { ConnectionsPanel } from './components/connections/connections-panel';
9
9
  export type { FaskConnection, FaskSearchableApp } from './types/connections';
10
10
  export type { ConnectionsApi } from './types/connections-api';
11
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, } from './components/ui/card';
12
+ export { Badge, badgeVariants } from './components/ui/badge';
13
+ export { Button, buttonVariants } from './components/ui/button';
11
14
  export { cn } from './lib/utils';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cn = exports.ConnectionsPanel = exports.AppSearchGrid = exports.AvailableAppsList = exports.ConnectedAppsList = exports.AppIcon = exports.useConnectionsApi = exports.ConnectionsApiProvider = exports.betaOfferData = exports.GTMProvider = void 0;
3
+ exports.cn = exports.buttonVariants = exports.Button = exports.badgeVariants = exports.Badge = exports.CardContent = exports.CardDescription = exports.CardAction = exports.CardTitle = exports.CardFooter = exports.CardHeader = exports.Card = exports.ConnectionsPanel = exports.AppSearchGrid = exports.AvailableAppsList = exports.ConnectedAppsList = exports.AppIcon = exports.useConnectionsApi = exports.ConnectionsApiProvider = exports.betaOfferData = exports.GTMProvider = void 0;
4
4
  var gtm_provider_1 = require("./components/gtm/gtm-provider");
5
5
  Object.defineProperty(exports, "GTMProvider", { enumerable: true, get: function () { return gtm_provider_1.GTMProvider; } });
6
6
  var betaMarketingData_1 = require("./data/betaMarketingData");
@@ -19,6 +19,21 @@ var app_search_grid_1 = require("./components/connections/app-search-grid");
19
19
  Object.defineProperty(exports, "AppSearchGrid", { enumerable: true, get: function () { return app_search_grid_1.AppSearchGrid; } });
20
20
  var connections_panel_1 = require("./components/connections/connections-panel");
21
21
  Object.defineProperty(exports, "ConnectionsPanel", { enumerable: true, get: function () { return connections_panel_1.ConnectionsPanel; } });
22
+ // UI primitives (shadcn)
23
+ var card_1 = require("./components/ui/card");
24
+ Object.defineProperty(exports, "Card", { enumerable: true, get: function () { return card_1.Card; } });
25
+ Object.defineProperty(exports, "CardHeader", { enumerable: true, get: function () { return card_1.CardHeader; } });
26
+ Object.defineProperty(exports, "CardFooter", { enumerable: true, get: function () { return card_1.CardFooter; } });
27
+ Object.defineProperty(exports, "CardTitle", { enumerable: true, get: function () { return card_1.CardTitle; } });
28
+ Object.defineProperty(exports, "CardAction", { enumerable: true, get: function () { return card_1.CardAction; } });
29
+ Object.defineProperty(exports, "CardDescription", { enumerable: true, get: function () { return card_1.CardDescription; } });
30
+ Object.defineProperty(exports, "CardContent", { enumerable: true, get: function () { return card_1.CardContent; } });
31
+ var badge_1 = require("./components/ui/badge");
32
+ Object.defineProperty(exports, "Badge", { enumerable: true, get: function () { return badge_1.Badge; } });
33
+ Object.defineProperty(exports, "badgeVariants", { enumerable: true, get: function () { return badge_1.badgeVariants; } });
34
+ var button_1 = require("./components/ui/button");
35
+ Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return button_1.Button; } });
36
+ Object.defineProperty(exports, "buttonVariants", { enumerable: true, get: function () { return button_1.buttonVariants; } });
22
37
  // Utilities
23
38
  var utils_1 = require("./lib/utils");
24
39
  Object.defineProperty(exports, "cn", { enumerable: true, get: function () { return utils_1.cn; } });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@faskai/ui-commons",
3
3
  "author": "Fask AI <arko@fask.ai>",
4
- "version": "0.0.0-alpha.24",
4
+ "version": "0.0.0-alpha.25",
5
5
  "description": "Common UI components for Fask applications.",
6
6
  "private": false,
7
7
  "main": "dist/index.js",
@@ -14,6 +14,8 @@
14
14
  "build": "tsc"
15
15
  },
16
16
  "peerDependencies": {
17
+ "@radix-ui/react-slot": ">=1.0.0",
18
+ "class-variance-authority": ">=0.7.0",
17
19
  "clsx": ">=2.0.0",
18
20
  "lucide-react": ">=0.300.0",
19
21
  "next": ">=13.0.0",
@@ -21,7 +23,9 @@
21
23
  "tailwind-merge": ">=2.0.0"
22
24
  },
23
25
  "devDependencies": {
26
+ "@radix-ui/react-slot": "^1.1.0",
24
27
  "@types/react": "^18.0.0",
28
+ "class-variance-authority": "^0.7.0",
25
29
  "clsx": "^2.1.0",
26
30
  "lucide-react": "^0.400.0",
27
31
  "next": "^14.0.0",