@agent-native/dispatch 0.19.2 → 0.20.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.
Files changed (85) hide show
  1. package/dist/actions/provider-api-register.d.ts +5 -5
  2. package/dist/components/admin-navigation.d.ts +2 -1
  3. package/dist/components/admin-navigation.d.ts.map +1 -1
  4. package/dist/components/admin-navigation.js +10 -7
  5. package/dist/components/admin-navigation.js.map +1 -1
  6. package/dist/components/app-icon.d.ts +9 -0
  7. package/dist/components/app-icon.d.ts.map +1 -0
  8. package/dist/components/app-icon.js +85 -0
  9. package/dist/components/app-icon.js.map +1 -0
  10. package/dist/components/app-list-row.d.ts +12 -0
  11. package/dist/components/app-list-row.d.ts.map +1 -0
  12. package/dist/components/app-list-row.js +11 -0
  13. package/dist/components/app-list-row.js.map +1 -0
  14. package/dist/components/app-open-actions.d.ts +17 -0
  15. package/dist/components/app-open-actions.d.ts.map +1 -0
  16. package/dist/components/app-open-actions.js +20 -0
  17. package/dist/components/app-open-actions.js.map +1 -0
  18. package/dist/components/connected-app-card.d.ts +2 -1
  19. package/dist/components/connected-app-card.d.ts.map +1 -1
  20. package/dist/components/connected-app-card.js +8 -8
  21. package/dist/components/connected-app-card.js.map +1 -1
  22. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  23. package/dist/components/dispatch-control-plane.js +21 -14
  24. package/dist/components/dispatch-control-plane.js.map +1 -1
  25. package/dist/components/layout/Layout.d.ts.map +1 -1
  26. package/dist/components/layout/Layout.js +40 -19
  27. package/dist/components/layout/Layout.js.map +1 -1
  28. package/dist/components/layout/workspace-apps-rail.d.ts.map +1 -1
  29. package/dist/components/layout/workspace-apps-rail.js +10 -10
  30. package/dist/components/layout/workspace-apps-rail.js.map +1 -1
  31. package/dist/components/other-apps-section.d.ts +31 -0
  32. package/dist/components/other-apps-section.d.ts.map +1 -0
  33. package/dist/components/other-apps-section.js +59 -0
  34. package/dist/components/other-apps-section.js.map +1 -0
  35. package/dist/components/workspace-app-card.d.ts.map +1 -1
  36. package/dist/components/workspace-app-card.js +38 -28
  37. package/dist/components/workspace-app-card.js.map +1 -1
  38. package/dist/components/workspace-template-card.d.ts +8 -2
  39. package/dist/components/workspace-template-card.d.ts.map +1 -1
  40. package/dist/components/workspace-template-card.js +17 -13
  41. package/dist/components/workspace-template-card.js.map +1 -1
  42. package/dist/lib/other-apps.d.ts.map +1 -1
  43. package/dist/lib/other-apps.js +5 -1
  44. package/dist/lib/other-apps.js.map +1 -1
  45. package/dist/lib/workspace-apps.d.ts +1 -0
  46. package/dist/lib/workspace-apps.d.ts.map +1 -1
  47. package/dist/lib/workspace-apps.js +3 -0
  48. package/dist/lib/workspace-apps.js.map +1 -1
  49. package/dist/routes/index.d.ts.map +1 -1
  50. package/dist/routes/index.js +0 -2
  51. package/dist/routes/index.js.map +1 -1
  52. package/dist/routes/pages/admin._index.d.ts.map +1 -1
  53. package/dist/routes/pages/admin._index.js +32 -7
  54. package/dist/routes/pages/admin._index.js.map +1 -1
  55. package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
  56. package/dist/routes/pages/apps.$appId.js +62 -13
  57. package/dist/routes/pages/apps.$appId.js.map +1 -1
  58. package/dist/routes/pages/apps.d.ts +1 -1
  59. package/dist/routes/pages/apps.d.ts.map +1 -1
  60. package/dist/routes/pages/apps.js +21 -30
  61. package/dist/routes/pages/apps.js.map +1 -1
  62. package/package.json +2 -2
  63. package/src/components/admin-navigation.tsx +21 -16
  64. package/src/components/app-icon.tsx +149 -0
  65. package/src/components/app-list-row.tsx +40 -0
  66. package/src/components/app-open-actions.tsx +111 -0
  67. package/src/components/connected-app-card.tsx +30 -34
  68. package/src/components/dispatch-control-plane.spec.tsx +28 -1
  69. package/src/components/dispatch-control-plane.tsx +122 -48
  70. package/src/components/layout/Layout.spec.tsx +4 -4
  71. package/src/components/layout/Layout.tsx +86 -55
  72. package/src/components/layout/workspace-apps-rail.tsx +20 -21
  73. package/src/components/other-apps-section.tsx +195 -0
  74. package/src/components/workspace-app-card.spec.tsx +58 -32
  75. package/src/components/workspace-app-card.tsx +222 -158
  76. package/src/components/workspace-template-card.spec.tsx +45 -7
  77. package/src/components/workspace-template-card.tsx +74 -81
  78. package/src/lib/other-apps.spec.ts +31 -0
  79. package/src/lib/other-apps.ts +9 -1
  80. package/src/lib/workspace-apps.ts +4 -0
  81. package/src/routes/index.spec.ts +2 -1
  82. package/src/routes/index.ts +0 -2
  83. package/src/routes/pages/admin._index.tsx +85 -17
  84. package/src/routes/pages/apps.$appId.tsx +144 -57
  85. package/src/routes/pages/apps.tsx +76 -147
@@ -47,8 +47,8 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
47
47
  notes?: string | undefined;
48
48
  scope?: "org" | "user" | undefined;
49
49
  }, {
50
+ id?: undefined;
50
51
  deleted?: undefined;
51
- found?: undefined;
52
52
  providers: {
53
53
  id: string;
54
54
  label: string;
@@ -60,18 +60,18 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
60
60
  }[];
61
61
  count: number;
62
62
  provider?: undefined;
63
+ found?: undefined;
63
64
  registered?: undefined;
64
- id?: undefined;
65
65
  label?: undefined;
66
66
  message?: undefined;
67
67
  } | {
68
+ id?: undefined;
68
69
  deleted?: undefined;
69
70
  providers?: undefined;
70
71
  count?: undefined;
71
72
  found: boolean;
72
73
  provider: import("node_modules/@agent-native/core/dist/provider-api").CustomProviderConfig;
73
74
  registered?: undefined;
74
- id?: undefined;
75
75
  label?: undefined;
76
76
  message?: undefined;
77
77
  } | {
@@ -85,10 +85,10 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
85
85
  label?: undefined;
86
86
  message?: undefined;
87
87
  } | {
88
- found?: undefined;
89
88
  providers?: undefined;
90
89
  count?: undefined;
91
90
  provider?: undefined;
91
+ found?: undefined;
92
92
  deleted: boolean;
93
93
  id: string;
94
94
  registered?: undefined;
@@ -96,10 +96,10 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
96
96
  message?: undefined;
97
97
  } | {
98
98
  deleted?: undefined;
99
- found?: undefined;
100
99
  providers?: undefined;
101
100
  count?: undefined;
102
101
  provider?: undefined;
102
+ found?: undefined;
103
103
  registered: boolean;
104
104
  id: string;
105
105
  label: string;
@@ -1,6 +1,6 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { type DispatchNavItem } from "./layout/Layout.js";
3
- interface AdminNavGroup {
3
+ export interface AdminNavGroup {
4
4
  id: string;
5
5
  label: string;
6
6
  labelKey: string;
@@ -12,4 +12,5 @@ export declare function AdminShell({ children, onNavigate, }: {
12
12
  onNavigate?: () => void;
13
13
  }): import("node_modules/@types/react").JSX.Element;
14
14
  export { BUILT_IN_ADMIN_NAV_GROUPS };
15
+ export declare function useAdminNavGroups(): readonly AdminNavGroup[];
15
16
  //# sourceMappingURL=admin-navigation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-navigation.d.ts","sourceRoot":"","sources":["../../src/components/admin-navigation.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE9E,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CACnC;AAED,QAAA,MAAM,yBAAyB,EAAE,SAAS,aAAa,EAoItD,CAAC;AAwCF,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,mDAiEA;AAED,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
1
+ {"version":3,"file":"admin-navigation.d.ts","sourceRoot":"","sources":["../../src/components/admin-navigation.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CACnC;AAED,QAAA,MAAM,yBAAyB,EAAE,SAAS,aAAa,EAoItD,CAAC;AAwCF,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,mDAmDA;AAED,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAErC,wBAAgB,iBAAiB,IAAI,SAAS,aAAa,EAAE,CAiB5D"}
@@ -151,9 +151,18 @@ function AdminNavLink({ item, onNavigate, }) {
151
151
  }
152
152
  export function AdminShell({ children, onNavigate, }) {
153
153
  const t = useT();
154
+ const groups = useAdminNavGroups();
155
+ return (_jsxs("div", { className: "grid min-w-0 gap-6 lg:grid-cols-[13rem_minmax(0,1fr)]", "data-dispatch-admin-shell": true, children: [_jsxs("aside", { className: "min-w-0 border-b pb-5 lg:sticky lg:top-2 lg:self-start lg:border-b-0 lg:border-e lg:pe-6", children: [_jsxs("div", { className: "px-2", children: [_jsx("div", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: t("dispatch.nav.admin", { defaultValue: "Admin" }) }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: t("dispatch.pages.adminDescription", {
156
+ defaultValue: "Workspace controls and operations",
157
+ }) })] }), _jsx("nav", { "aria-label": t("dispatch.pages.adminNavigation", {
158
+ defaultValue: "Admin navigation",
159
+ }), className: "mt-5 space-y-5", children: groups.map((group) => (_jsxs("section", { children: [_jsx("h2", { className: "px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70", children: t(group.labelKey, { defaultValue: group.label }) }), _jsx("ul", { className: "mt-1 space-y-0.5", children: group.items.map((item) => (_jsx(AdminNavLink, { item: item, onNavigate: onNavigate }, item.id))) })] }, group.id))) })] }), _jsx("section", { className: "min-w-0", "data-dispatch-admin-content": true, children: children })] }));
160
+ }
161
+ export { BUILT_IN_ADMIN_NAV_GROUPS };
162
+ export function useAdminNavGroups() {
154
163
  const extensions = useDispatchExtensions();
155
164
  const extensionItems = (extensions?.navItems ?? []).filter((item) => item.section === "operations");
156
- const groups = extensionItems.length
165
+ return extensionItems.length
157
166
  ? [
158
167
  ...BUILT_IN_ADMIN_NAV_GROUPS,
159
168
  {
@@ -164,11 +173,5 @@ export function AdminShell({ children, onNavigate, }) {
164
173
  },
165
174
  ]
166
175
  : BUILT_IN_ADMIN_NAV_GROUPS;
167
- return (_jsxs("div", { className: "grid min-w-0 gap-6 lg:grid-cols-[13rem_minmax(0,1fr)]", "data-dispatch-admin-shell": true, children: [_jsxs("aside", { className: "min-w-0 border-b pb-5 lg:sticky lg:top-2 lg:self-start lg:border-b-0 lg:border-e lg:pe-6", children: [_jsxs("div", { className: "px-2", children: [_jsx("div", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: t("dispatch.nav.admin", { defaultValue: "Admin" }) }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: t("dispatch.pages.adminDescription", {
168
- defaultValue: "Workspace controls and operations",
169
- }) })] }), _jsx("nav", { "aria-label": t("dispatch.pages.adminNavigation", {
170
- defaultValue: "Admin navigation",
171
- }), className: "mt-5 space-y-5", children: groups.map((group) => (_jsxs("section", { children: [_jsx("h2", { className: "px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70", children: t(group.labelKey, { defaultValue: group.label }) }), _jsx("ul", { className: "mt-1 space-y-0.5", children: group.items.map((item) => (_jsx(AdminNavLink, { item: item, onNavigate: onNavigate }, item.id))) })] }, group.id))) })] }), _jsx("section", { className: "min-w-0", "data-dispatch-admin-content": true, children: children })] }));
172
176
  }
173
- export { BUILT_IN_ADMIN_NAV_GROUPS };
174
177
  //# sourceMappingURL=admin-navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-navigation.js","sourceRoot":"","sources":["../../src/components/admin-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport {\n IconActivity,\n IconArrowUpRight,\n IconBrain,\n IconBrandTelegram,\n IconChartBar,\n IconFingerprint,\n IconHistory,\n IconKey,\n IconLayersSubtract,\n IconMail,\n IconMessages,\n IconPlugConnected,\n IconPuzzle,\n IconSettingsAutomation,\n IconShield,\n IconShieldCheck,\n} from \"@tabler/icons-react\";\nimport { type ReactNode } from \"react\";\nimport { NavLink } from \"react-router\";\n\nimport { cn } from \"../lib/utils\";\nimport { useDispatchExtensions, type DispatchNavItem } from \"./layout/Layout\";\n\ninterface AdminNavGroup {\n id: string;\n label: string;\n labelKey: string;\n items: readonly DispatchNavItem[];\n}\n\nconst BUILT_IN_ADMIN_NAV_GROUPS: readonly AdminNavGroup[] = [\n {\n id: \"workspace\",\n label: \"Workspace\",\n labelKey: \"dispatch.pages.adminWorkspace\",\n items: [\n {\n id: \"admin-overview\",\n to: \"/admin\",\n label: \"Overview\",\n icon: IconShield,\n },\n {\n id: \"admin-resources\",\n to: \"/admin/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n },\n ],\n },\n {\n id: \"operations\",\n label: \"Operations\",\n labelKey: \"dispatch.pages.adminOperations\",\n items: [\n {\n id: \"operations\",\n to: \"/admin/operations\",\n label: \"Operations\",\n icon: IconActivity,\n },\n {\n id: \"metrics\",\n to: \"/admin/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n },\n {\n id: \"audit\",\n to: \"/admin/audit\",\n label: \"Audit\",\n icon: IconHistory,\n },\n {\n id: \"thread-debug\",\n to: \"/admin/thread-debug\",\n label: \"Thread Debug\",\n icon: IconMessages,\n },\n ],\n },\n {\n id: \"automation\",\n label: \"Automation & delivery\",\n labelKey: \"dispatch.pages.adminAutomation\",\n items: [\n {\n id: \"automations\",\n to: \"/admin/automations\",\n label: \"Automations\",\n icon: IconSettingsAutomation,\n },\n {\n id: \"approvals\",\n to: \"/admin/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n },\n {\n id: \"destinations\",\n to: \"/admin/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n },\n {\n id: \"transactional-email\",\n to: \"/admin/transactional-email\",\n label: \"Transactional email\",\n icon: IconMail,\n },\n ],\n },\n {\n id: \"connections\",\n label: \"Connections\",\n labelKey: \"dispatch.pages.adminConnections\",\n items: [\n {\n id: \"integrations\",\n to: \"/admin/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n },\n {\n id: \"vault\",\n to: \"/admin/vault\",\n label: \"Vault\",\n icon: IconKey,\n },\n {\n id: \"messaging\",\n to: \"/admin/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n },\n {\n id: \"identities\",\n to: \"/admin/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n },\n ],\n },\n {\n id: \"agent-platform\",\n label: \"Agent platform\",\n labelKey: \"dispatch.pages.adminAgentPlatform\",\n items: [\n {\n id: \"agents\",\n to: \"/admin/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n },\n {\n id: \"dreams\",\n to: \"/admin/dreams\",\n label: \"Dreams\",\n icon: IconBrain,\n },\n ],\n },\n];\n\nfunction itemLabel(t: ReturnType<typeof useT>, item: DispatchNavItem) {\n return t(`dispatch.nav.${item.id}`, { defaultValue: item.label });\n}\n\nfunction AdminNavLink({\n item,\n onNavigate,\n}: {\n item: DispatchNavItem;\n onNavigate?: () => void;\n}) {\n const t = useT();\n const to = item.adminTo ?? item.to;\n const label = itemLabel(t, item);\n const Icon = item.icon;\n\n return (\n <li>\n <NavLink\n to={to}\n end={item.id === \"admin-overview\"}\n onClick={onNavigate}\n className={({ isActive }) =>\n cn(\n \"flex min-h-8 items-center gap-2 rounded-md px-2 text-sm transition-colors\",\n isActive\n ? \"bg-accent font-medium text-accent-foreground\"\n : \"text-muted-foreground hover:bg-accent/60 hover:text-foreground\",\n )\n }\n >\n {Icon ? <Icon size={15} className=\"shrink-0\" /> : null}\n <span className=\"truncate\">{label}</span>\n </NavLink>\n </li>\n );\n}\n\nexport function AdminShell({\n children,\n onNavigate,\n}: {\n children: ReactNode;\n onNavigate?: () => void;\n}) {\n const t = useT();\n const extensions = useDispatchExtensions();\n const extensionItems = (extensions?.navItems ?? []).filter(\n (item) => item.section === \"operations\",\n );\n const groups = extensionItems.length\n ? [\n ...BUILT_IN_ADMIN_NAV_GROUPS,\n {\n id: \"workspace-extensions\",\n label: \"Workspace extensions\",\n labelKey: \"dispatch.pages.adminWorkspaceExtensions\",\n items: extensionItems,\n },\n ]\n : BUILT_IN_ADMIN_NAV_GROUPS;\n\n return (\n <div\n className=\"grid min-w-0 gap-6 lg:grid-cols-[13rem_minmax(0,1fr)]\"\n data-dispatch-admin-shell\n >\n <aside className=\"min-w-0 border-b pb-5 lg:sticky lg:top-2 lg:self-start lg:border-b-0 lg:border-e lg:pe-6\">\n <div className=\"px-2\">\n <div className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" })}\n </div>\n <p className=\"mt-1 text-xs leading-5 text-muted-foreground\">\n {t(\"dispatch.pages.adminDescription\", {\n defaultValue: \"Workspace controls and operations\",\n })}\n </p>\n </div>\n\n <nav\n aria-label={t(\"dispatch.pages.adminNavigation\", {\n defaultValue: \"Admin navigation\",\n })}\n className=\"mt-5 space-y-5\"\n >\n {groups.map((group) => (\n <section key={group.id}>\n <h2 className=\"px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70\">\n {t(group.labelKey, { defaultValue: group.label })}\n </h2>\n <ul className=\"mt-1 space-y-0.5\">\n {group.items.map((item) => (\n <AdminNavLink\n key={item.id}\n item={item}\n onNavigate={onNavigate}\n />\n ))}\n </ul>\n </section>\n ))}\n </nav>\n </aside>\n\n <section className=\"min-w-0\" data-dispatch-admin-content>\n {children}\n </section>\n </div>\n );\n}\n\nexport { BUILT_IN_ADMIN_NAV_GROUPS };\n"]}
1
+ {"version":3,"file":"admin-navigation.js","sourceRoot":"","sources":["../../src/components/admin-navigation.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,OAAO,EACP,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,sBAAsB,EACtB,UAAU,EACV,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAwB,MAAM,iBAAiB,CAAC;AAS9E,MAAM,yBAAyB,GAA6B;IAC1D;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,+BAA+B;QACzC,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,gBAAgB;gBACpB,EAAE,EAAE,QAAQ;gBACZ,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,UAAU;aACjB;YACD;gBACE,EAAE,EAAE,iBAAiB;gBACrB,EAAE,EAAE,kBAAkB;gBACtB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,kBAAkB;aACzB;SACF;KACF;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,gCAAgC;QAC1C,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,YAAY;gBAChB,EAAE,EAAE,mBAAmB;gBACvB,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,YAAY;aACnB;YACD;gBACE,EAAE,EAAE,SAAS;gBACb,EAAE,EAAE,gBAAgB;gBACpB,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,YAAY;aACnB;YACD;gBACE,EAAE,EAAE,OAAO;gBACX,EAAE,EAAE,cAAc;gBAClB,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,WAAW;aAClB;YACD;gBACE,EAAE,EAAE,cAAc;gBAClB,EAAE,EAAE,qBAAqB;gBACzB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,YAAY;aACnB;SACF;KACF;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,uBAAuB;QAC9B,QAAQ,EAAE,gCAAgC;QAC1C,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,aAAa;gBACjB,EAAE,EAAE,oBAAoB;gBACxB,KAAK,EAAE,aAAa;gBACpB,IAAI,EAAE,sBAAsB;aAC7B;YACD;gBACE,EAAE,EAAE,WAAW;gBACf,EAAE,EAAE,kBAAkB;gBACtB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,eAAe;aACtB;YACD;gBACE,EAAE,EAAE,cAAc;gBAClB,EAAE,EAAE,qBAAqB;gBACzB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,gBAAgB;aACvB;YACD;gBACE,EAAE,EAAE,qBAAqB;gBACzB,EAAE,EAAE,4BAA4B;gBAChC,KAAK,EAAE,qBAAqB;gBAC5B,IAAI,EAAE,QAAQ;aACf;SACF;KACF;IACD;QACE,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,aAAa;QACpB,QAAQ,EAAE,iCAAiC;QAC3C,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,cAAc;gBAClB,EAAE,EAAE,qBAAqB;gBACzB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,UAAU;aACjB;YACD;gBACE,EAAE,EAAE,OAAO;gBACX,EAAE,EAAE,cAAc;gBAClB,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,OAAO;aACd;YACD;gBACE,EAAE,EAAE,WAAW;gBACf,EAAE,EAAE,kBAAkB;gBACtB,KAAK,EAAE,WAAW;gBAClB,IAAI,EAAE,iBAAiB;aACxB;YACD;gBACE,EAAE,EAAE,YAAY;gBAChB,EAAE,EAAE,mBAAmB;gBACvB,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,eAAe;aACtB;SACF;KACF;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,gBAAgB;QACvB,QAAQ,EAAE,mCAAmC;QAC7C,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,QAAQ;gBACZ,EAAE,EAAE,eAAe;gBACnB,KAAK,EAAE,QAAQ;gBACf,IAAI,EAAE,iBAAiB;aACxB;YACD;gBACE,EAAE,EAAE,QAAQ;gBACZ,EAAE,EAAE,eAAe;gBACnB,KAAK,EAAE,QAAQ;gBACf,IAAI,EAAE,SAAS;aAChB;SACF;KACF;CACF,CAAC;AAEF,SAAS,SAAS,CAAC,CAA0B,EAAE,IAAqB;IAClE,OAAO,CAAC,CAAC,gBAAgB,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,YAAY,CAAC,EACpB,IAAI,EACJ,UAAU,GAIX;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IAEvB,OAAO,CACL,uBACE,MAAC,OAAO,IACN,EAAE,EAAE,EAAE,EACN,GAAG,EAAE,IAAI,CAAC,EAAE,KAAK,gBAAgB,EACjC,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC1B,EAAE,CACA,2EAA2E,EAC3E,QAAQ;gBACN,CAAC,CAAC,8CAA8C;gBAChD,CAAC,CAAC,gEAAgE,CACrE,aAGF,IAAI,CAAC,CAAC,CAAC,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,EACtD,eAAM,SAAS,EAAC,UAAU,YAAE,KAAK,GAAQ,IACjC,GACP,CACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,UAAU,GAIX;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAEnC,OAAO,CACL,eACE,SAAS,EAAC,uDAAuD,gDAGjE,iBAAO,SAAS,EAAC,0FAA0F,aACzG,eAAK,SAAS,EAAC,MAAM,aACnB,cAAK,SAAS,EAAC,uEAAuE,YACnF,CAAC,CAAC,oBAAoB,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,GAC/C,EACN,YAAG,SAAS,EAAC,8CAA8C,YACxD,CAAC,CAAC,iCAAiC,EAAE;oCACpC,YAAY,EAAE,mCAAmC;iCAClD,CAAC,GACA,IACA,EAEN,4BACc,CAAC,CAAC,gCAAgC,EAAE;4BAC9C,YAAY,EAAE,kBAAkB;yBACjC,CAAC,EACF,SAAS,EAAC,gBAAgB,YAEzB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACrB,8BACE,aAAI,SAAS,EAAC,+EAA+E,YAC1F,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAC9C,EACL,aAAI,SAAS,EAAC,kBAAkB,YAC7B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,KAAC,YAAY,IAEX,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,UAAU,IAFjB,IAAI,CAAC,EAAE,CAGZ,CACH,CAAC,GACC,KAZO,KAAK,CAAC,EAAE,CAaZ,CACX,CAAC,GACE,IACA,EAER,kBAAS,SAAS,EAAC,SAAS,iDACzB,QAAQ,GACD,IACN,CACP,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAErC,MAAM,UAAU,iBAAiB;IAC/B,MAAM,UAAU,GAAG,qBAAqB,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CACxD,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,YAAY,CACxC,CAAC;IAEF,OAAO,cAAc,CAAC,MAAM;QAC1B,CAAC,CAAC;YACE,GAAG,yBAAyB;YAC5B;gBACE,EAAE,EAAE,sBAAsB;gBAC1B,KAAK,EAAE,sBAAsB;gBAC7B,QAAQ,EAAE,yCAAyC;gBACnD,KAAK,EAAE,cAAc;aACtB;SACF;QACH,CAAC,CAAC,yBAAyB,CAAC;AAChC,CAAC","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport {\n IconActivity,\n IconArrowUpRight,\n IconBrain,\n IconBrandTelegram,\n IconChartBar,\n IconFingerprint,\n IconHistory,\n IconKey,\n IconLayersSubtract,\n IconMail,\n IconMessages,\n IconPlugConnected,\n IconPuzzle,\n IconSettingsAutomation,\n IconShield,\n IconShieldCheck,\n} from \"@tabler/icons-react\";\nimport { type ReactNode } from \"react\";\nimport { NavLink } from \"react-router\";\n\nimport { cn } from \"../lib/utils\";\nimport { useDispatchExtensions, type DispatchNavItem } from \"./layout/Layout\";\n\nexport interface AdminNavGroup {\n id: string;\n label: string;\n labelKey: string;\n items: readonly DispatchNavItem[];\n}\n\nconst BUILT_IN_ADMIN_NAV_GROUPS: readonly AdminNavGroup[] = [\n {\n id: \"workspace\",\n label: \"Workspace\",\n labelKey: \"dispatch.pages.adminWorkspace\",\n items: [\n {\n id: \"admin-overview\",\n to: \"/admin\",\n label: \"Overview\",\n icon: IconShield,\n },\n {\n id: \"admin-resources\",\n to: \"/admin/workspace\",\n label: \"Resources\",\n icon: IconLayersSubtract,\n },\n ],\n },\n {\n id: \"operations\",\n label: \"Operations\",\n labelKey: \"dispatch.pages.adminOperations\",\n items: [\n {\n id: \"operations\",\n to: \"/admin/operations\",\n label: \"Operations\",\n icon: IconActivity,\n },\n {\n id: \"metrics\",\n to: \"/admin/metrics\",\n label: \"Metrics\",\n icon: IconChartBar,\n },\n {\n id: \"audit\",\n to: \"/admin/audit\",\n label: \"Audit\",\n icon: IconHistory,\n },\n {\n id: \"thread-debug\",\n to: \"/admin/thread-debug\",\n label: \"Thread Debug\",\n icon: IconMessages,\n },\n ],\n },\n {\n id: \"automation\",\n label: \"Automation & delivery\",\n labelKey: \"dispatch.pages.adminAutomation\",\n items: [\n {\n id: \"automations\",\n to: \"/admin/automations\",\n label: \"Automations\",\n icon: IconSettingsAutomation,\n },\n {\n id: \"approvals\",\n to: \"/admin/approvals\",\n label: \"Approvals\",\n icon: IconShieldCheck,\n },\n {\n id: \"destinations\",\n to: \"/admin/destinations\",\n label: \"Destinations\",\n icon: IconArrowUpRight,\n },\n {\n id: \"transactional-email\",\n to: \"/admin/transactional-email\",\n label: \"Transactional email\",\n icon: IconMail,\n },\n ],\n },\n {\n id: \"connections\",\n label: \"Connections\",\n labelKey: \"dispatch.pages.adminConnections\",\n items: [\n {\n id: \"integrations\",\n to: \"/admin/integrations\",\n label: \"Integrations\",\n icon: IconPuzzle,\n },\n {\n id: \"vault\",\n to: \"/admin/vault\",\n label: \"Vault\",\n icon: IconKey,\n },\n {\n id: \"messaging\",\n to: \"/admin/messaging\",\n label: \"Messaging\",\n icon: IconBrandTelegram,\n },\n {\n id: \"identities\",\n to: \"/admin/identities\",\n label: \"Identities\",\n icon: IconFingerprint,\n },\n ],\n },\n {\n id: \"agent-platform\",\n label: \"Agent platform\",\n labelKey: \"dispatch.pages.adminAgentPlatform\",\n items: [\n {\n id: \"agents\",\n to: \"/admin/agents\",\n label: \"Agents\",\n icon: IconPlugConnected,\n },\n {\n id: \"dreams\",\n to: \"/admin/dreams\",\n label: \"Dreams\",\n icon: IconBrain,\n },\n ],\n },\n];\n\nfunction itemLabel(t: ReturnType<typeof useT>, item: DispatchNavItem) {\n return t(`dispatch.nav.${item.id}`, { defaultValue: item.label });\n}\n\nfunction AdminNavLink({\n item,\n onNavigate,\n}: {\n item: DispatchNavItem;\n onNavigate?: () => void;\n}) {\n const t = useT();\n const to = item.adminTo ?? item.to;\n const label = itemLabel(t, item);\n const Icon = item.icon;\n\n return (\n <li>\n <NavLink\n to={to}\n end={item.id === \"admin-overview\"}\n onClick={onNavigate}\n className={({ isActive }) =>\n cn(\n \"flex min-h-8 items-center gap-2 rounded-md px-2 text-sm transition-colors\",\n isActive\n ? \"bg-accent font-medium text-accent-foreground\"\n : \"text-muted-foreground hover:bg-accent/60 hover:text-foreground\",\n )\n }\n >\n {Icon ? <Icon size={15} className=\"shrink-0\" /> : null}\n <span className=\"truncate\">{label}</span>\n </NavLink>\n </li>\n );\n}\n\nexport function AdminShell({\n children,\n onNavigate,\n}: {\n children: ReactNode;\n onNavigate?: () => void;\n}) {\n const t = useT();\n const groups = useAdminNavGroups();\n\n return (\n <div\n className=\"grid min-w-0 gap-6 lg:grid-cols-[13rem_minmax(0,1fr)]\"\n data-dispatch-admin-shell\n >\n <aside className=\"min-w-0 border-b pb-5 lg:sticky lg:top-2 lg:self-start lg:border-b-0 lg:border-e lg:pe-6\">\n <div className=\"px-2\">\n <div className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" })}\n </div>\n <p className=\"mt-1 text-xs leading-5 text-muted-foreground\">\n {t(\"dispatch.pages.adminDescription\", {\n defaultValue: \"Workspace controls and operations\",\n })}\n </p>\n </div>\n\n <nav\n aria-label={t(\"dispatch.pages.adminNavigation\", {\n defaultValue: \"Admin navigation\",\n })}\n className=\"mt-5 space-y-5\"\n >\n {groups.map((group) => (\n <section key={group.id}>\n <h2 className=\"px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground/70\">\n {t(group.labelKey, { defaultValue: group.label })}\n </h2>\n <ul className=\"mt-1 space-y-0.5\">\n {group.items.map((item) => (\n <AdminNavLink\n key={item.id}\n item={item}\n onNavigate={onNavigate}\n />\n ))}\n </ul>\n </section>\n ))}\n </nav>\n </aside>\n\n <section className=\"min-w-0\" data-dispatch-admin-content>\n {children}\n </section>\n </div>\n );\n}\n\nexport { BUILT_IN_ADMIN_NAV_GROUPS };\n\nexport function useAdminNavGroups(): readonly AdminNavGroup[] {\n const extensions = useDispatchExtensions();\n const extensionItems = (extensions?.navItems ?? []).filter(\n (item) => item.section === \"operations\",\n );\n\n return extensionItems.length\n ? [\n ...BUILT_IN_ADMIN_NAV_GROUPS,\n {\n id: \"workspace-extensions\",\n label: \"Workspace extensions\",\n labelKey: \"dispatch.pages.adminWorkspaceExtensions\",\n items: extensionItems,\n },\n ]\n : BUILT_IN_ADMIN_NAV_GROUPS;\n}\n"]}
@@ -0,0 +1,9 @@
1
+ export declare function AppIcon({ id, name, icon, color, className, size, }: {
2
+ id: string;
3
+ name: string;
4
+ icon?: string;
5
+ color?: string;
6
+ className?: string;
7
+ size?: "sm" | "md";
8
+ }): import("node_modules/@types/react").JSX.Element;
9
+ //# sourceMappingURL=app-icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-icon.d.ts","sourceRoot":"","sources":["../../src/components/app-icon.tsx"],"names":[],"mappings":"AA0FA,wBAAgB,OAAO,CAAC,EACtB,EAAE,EACF,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,IAAW,GACZ,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACpB,mDAgCA"}
@@ -0,0 +1,85 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { IconActivity, IconApps, IconBrain, IconBrush, IconCalendar, IconChartBar, IconClipboardList, IconFileText, IconMail, IconPhoto, IconPlugConnected, IconPresentation, IconPuzzle, IconScreenShare, } from "@tabler/icons-react";
3
+ import { cn } from "../lib/utils.js";
4
+ const FALLBACK_ICONS = [
5
+ IconApps,
6
+ IconPuzzle,
7
+ IconActivity,
8
+ IconPlugConnected,
9
+ ];
10
+ const APP_ICON_TONES = [
11
+ "bg-primary/10 text-primary",
12
+ "bg-secondary text-secondary-foreground",
13
+ "bg-accent text-accent-foreground",
14
+ "bg-muted text-foreground",
15
+ ];
16
+ const ICONS_BY_KEY = {
17
+ barchart2: IconChartBar,
18
+ brain: IconBrain,
19
+ brush: IconBrush,
20
+ calendardays: IconCalendar,
21
+ chartbar: IconChartBar,
22
+ clipboardlist: IconClipboardList,
23
+ filetext: IconFileText,
24
+ galleryhorizontal: IconPresentation,
25
+ mail: IconMail,
26
+ photo: IconPhoto,
27
+ presentation: IconPresentation,
28
+ screenshare: IconScreenShare,
29
+ };
30
+ function appIconComponent(id, name, iconKey) {
31
+ const normalizedIconKey = iconKey?.trim().toLowerCase();
32
+ if (normalizedIconKey && ICONS_BY_KEY[normalizedIconKey]) {
33
+ return ICONS_BY_KEY[normalizedIconKey];
34
+ }
35
+ const haystack = `${id} ${name}`.toLowerCase();
36
+ if (haystack.includes("mail") || haystack.includes("email")) {
37
+ return IconMail;
38
+ }
39
+ if (haystack.includes("analytics") ||
40
+ haystack.includes("metric") ||
41
+ haystack.includes("indicator") ||
42
+ haystack.includes("gtm")) {
43
+ return IconChartBar;
44
+ }
45
+ if (haystack.includes("coach") || haystack.includes("agent")) {
46
+ return IconBrain;
47
+ }
48
+ let hash = 0;
49
+ for (const character of `${id}:${name}`) {
50
+ hash = (hash * 31 + character.charCodeAt(0)) | 0;
51
+ }
52
+ return FALLBACK_ICONS[Math.abs(hash) % FALLBACK_ICONS.length] ?? IconApps;
53
+ }
54
+ function safeHexColor(color) {
55
+ const normalized = color?.trim();
56
+ return normalized && /^#[0-9a-f]{6}$/i.test(normalized) ? normalized : null;
57
+ }
58
+ export function AppIcon({ id, name, icon, color, className, size = "md", }) {
59
+ const Icon = appIconComponent(id, name, icon);
60
+ const customColor = safeHexColor(color);
61
+ const tone = APP_ICON_TONES[Math.abs(hashForApp(id, name)) % APP_ICON_TONES.length];
62
+ const style = customColor
63
+ ? {
64
+ "--dispatch-app-icon-color": customColor,
65
+ backgroundColor: "color-mix(in srgb, var(--dispatch-app-icon-color) 14%, transparent)",
66
+ color: "var(--dispatch-app-icon-color)",
67
+ }
68
+ : {
69
+ "--dispatch-app-icon-hue": `${appHue(id, name)} 72% 44%`,
70
+ backgroundColor: "hsl(var(--dispatch-app-icon-hue) / 0.14)",
71
+ color: "hsl(var(--dispatch-app-icon-hue))",
72
+ };
73
+ return (_jsx("span", { "aria-hidden": "true", className: cn("flex shrink-0 items-center justify-center rounded-xl", size === "sm" ? "size-8" : "size-10", !customColor && tone, className), style: style, children: _jsx(Icon, { size: size === "sm" ? 16 : 19, stroke: 1.8 }) }));
74
+ }
75
+ function hashForApp(id, name) {
76
+ let hash = 0;
77
+ for (const character of `${id}:${name}`) {
78
+ hash = (hash * 31 + character.charCodeAt(0)) | 0;
79
+ }
80
+ return hash;
81
+ }
82
+ function appHue(id, name) {
83
+ return 20 + (Math.abs(hashForApp(id, name)) % 320);
84
+ }
85
+ //# sourceMappingURL=app-icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-icon.js","sourceRoot":"","sources":["../../src/components/app-icon.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n IconActivity,\n IconApps,\n IconBrain,\n IconBrush,\n IconCalendar,\n IconChartBar,\n IconClipboardList,\n IconFileText,\n IconMail,\n IconPhoto,\n IconPlugConnected,\n IconPresentation,\n IconPuzzle,\n IconScreenShare,\n} from \"@tabler/icons-react\";\nimport type { CSSProperties } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\ntype AppIconComponent = typeof IconApps;\n\nconst FALLBACK_ICONS: AppIconComponent[] = [\n IconApps,\n IconPuzzle,\n IconActivity,\n IconPlugConnected,\n];\n\nconst APP_ICON_TONES = [\n \"bg-primary/10 text-primary\",\n \"bg-secondary text-secondary-foreground\",\n \"bg-accent text-accent-foreground\",\n \"bg-muted text-foreground\",\n] as const;\n\nconst ICONS_BY_KEY: Record<string, AppIconComponent> = {\n barchart2: IconChartBar,\n brain: IconBrain,\n brush: IconBrush,\n calendardays: IconCalendar,\n chartbar: IconChartBar,\n clipboardlist: IconClipboardList,\n filetext: IconFileText,\n galleryhorizontal: IconPresentation,\n mail: IconMail,\n photo: IconPhoto,\n presentation: IconPresentation,\n screenshare: IconScreenShare,\n};\n\nfunction appIconComponent(\n id: string,\n name: string,\n iconKey?: string,\n): AppIconComponent {\n const normalizedIconKey = iconKey?.trim().toLowerCase();\n if (normalizedIconKey && ICONS_BY_KEY[normalizedIconKey]) {\n return ICONS_BY_KEY[normalizedIconKey];\n }\n\n const haystack = `${id} ${name}`.toLowerCase();\n\n if (haystack.includes(\"mail\") || haystack.includes(\"email\")) {\n return IconMail;\n }\n if (\n haystack.includes(\"analytics\") ||\n haystack.includes(\"metric\") ||\n haystack.includes(\"indicator\") ||\n haystack.includes(\"gtm\")\n ) {\n return IconChartBar;\n }\n if (haystack.includes(\"coach\") || haystack.includes(\"agent\")) {\n return IconBrain;\n }\n\n let hash = 0;\n for (const character of `${id}:${name}`) {\n hash = (hash * 31 + character.charCodeAt(0)) | 0;\n }\n return FALLBACK_ICONS[Math.abs(hash) % FALLBACK_ICONS.length] ?? IconApps;\n}\n\nfunction safeHexColor(color: string | undefined): string | null {\n const normalized = color?.trim();\n return normalized && /^#[0-9a-f]{6}$/i.test(normalized) ? normalized : null;\n}\n\nexport function AppIcon({\n id,\n name,\n icon,\n color,\n className,\n size = \"md\",\n}: {\n id: string;\n name: string;\n icon?: string;\n color?: string;\n className?: string;\n size?: \"sm\" | \"md\";\n}) {\n const Icon = appIconComponent(id, name, icon);\n const customColor = safeHexColor(color);\n const tone =\n APP_ICON_TONES[Math.abs(hashForApp(id, name)) % APP_ICON_TONES.length];\n const style = customColor\n ? ({\n \"--dispatch-app-icon-color\": customColor,\n backgroundColor:\n \"color-mix(in srgb, var(--dispatch-app-icon-color) 14%, transparent)\",\n color: \"var(--dispatch-app-icon-color)\",\n } as CSSProperties)\n : ({\n \"--dispatch-app-icon-hue\": `${appHue(id, name)} 72% 44%`,\n backgroundColor: \"hsl(var(--dispatch-app-icon-hue) / 0.14)\",\n color: \"hsl(var(--dispatch-app-icon-hue))\",\n } as CSSProperties);\n\n return (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"flex shrink-0 items-center justify-center rounded-xl\",\n size === \"sm\" ? \"size-8\" : \"size-10\",\n !customColor && tone,\n className,\n )}\n style={style}\n >\n <Icon size={size === \"sm\" ? 16 : 19} stroke={1.8} />\n </span>\n );\n}\n\nfunction hashForApp(id: string, name: string): number {\n let hash = 0;\n for (const character of `${id}:${name}`) {\n hash = (hash * 31 + character.charCodeAt(0)) | 0;\n }\n return hash;\n}\n\nfunction appHue(id: string, name: string): number {\n return 20 + (Math.abs(hashForApp(id, name)) % 320);\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from "react";
2
+ export declare const APP_LIST_GRID_CLASS = "xl:grid xl:grid-cols-2 xl:gap-3 xl:overflow-visible xl:rounded-none xl:bg-transparent";
3
+ export declare const APP_LIST_GRID_ROW_CLASS = "xl:rounded-2xl xl:border-0 xl:bg-card";
4
+ export declare function AppList({ children, className, }: {
5
+ children: ReactNode;
6
+ className?: string;
7
+ }): import("node_modules/@types/react").JSX.Element;
8
+ export declare function AppListRow({ children, className, }: {
9
+ children: ReactNode;
10
+ className?: string;
11
+ }): import("node_modules/@types/react").JSX.Element;
12
+ //# sourceMappingURL=app-list-row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-list-row.d.ts","sourceRoot":"","sources":["../../src/components/app-list-row.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,eAAO,MAAM,mBAAmB,0FACyD,CAAC;AAC1F,eAAO,MAAM,uBAAuB,0CAA0C,CAAC;AAE/E,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,mDAMA;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,mDAWA"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils.js";
3
+ export const APP_LIST_GRID_CLASS = "xl:grid xl:grid-cols-2 xl:gap-3 xl:overflow-visible xl:rounded-none xl:bg-transparent";
4
+ export const APP_LIST_GRID_ROW_CLASS = "xl:rounded-2xl xl:border-0 xl:bg-card";
5
+ export function AppList({ children, className, }) {
6
+ return (_jsx("div", { className: cn("overflow-hidden rounded-2xl bg-card", className), children: children }));
7
+ }
8
+ export function AppListRow({ children, className, }) {
9
+ return (_jsx("div", { className: cn("group flex min-w-0 items-center gap-3 border-b px-4 py-3.5 last:border-b-0 transition-[background-color] hover:bg-muted/30 focus-within:bg-muted/30", className), children: children }));
10
+ }
11
+ //# sourceMappingURL=app-list-row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-list-row.js","sourceRoot":"","sources":["../../src/components/app-list-row.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,MAAM,mBAAmB,GAC9B,uFAAuF,CAAC;AAC1F,MAAM,CAAC,MAAM,uBAAuB,GAAG,uCAAuC,CAAC;AAE/E,MAAM,UAAU,OAAO,CAAC,EACtB,QAAQ,EACR,SAAS,GAIV;IACC,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,qCAAqC,EAAE,SAAS,CAAC,YACjE,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,GAIV;IACC,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,qJAAqJ,EACrJ,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type { ReactNode } from \"react\";\n\nimport { cn } from \"../lib/utils\";\n\nexport const APP_LIST_GRID_CLASS =\n \"xl:grid xl:grid-cols-2 xl:gap-3 xl:overflow-visible xl:rounded-none xl:bg-transparent\";\nexport const APP_LIST_GRID_ROW_CLASS = \"xl:rounded-2xl xl:border-0 xl:bg-card\";\n\nexport function AppList({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn(\"overflow-hidden rounded-2xl bg-card\", className)}>\n {children}\n </div>\n );\n}\n\nexport function AppListRow({\n children,\n className,\n}: {\n children: ReactNode;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n \"group flex min-w-0 items-center gap-3 border-b px-4 py-3.5 last:border-b-0 transition-[background-color] hover:bg-muted/30 focus-within:bg-muted/30\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n"]}
@@ -0,0 +1,17 @@
1
+ export interface AppOpenActionLabels {
2
+ addApp: string;
3
+ openApp: string;
4
+ openInline: string;
5
+ openInNewTab: string;
6
+ }
7
+ export declare function AppOpenActions({ name, href, target, rel, labels: labelOverrides, onAddApp, showInlineOption, showNewTabOption, }: {
8
+ name: string;
9
+ href: string | null;
10
+ target?: "_blank";
11
+ rel?: string;
12
+ labels?: Partial<AppOpenActionLabels>;
13
+ onAddApp?: () => void;
14
+ showInlineOption?: boolean;
15
+ showNewTabOption?: boolean;
16
+ }): import("node_modules/@types/react").JSX.Element;
17
+ //# sourceMappingURL=app-open-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-open-actions.d.ts","sourceRoot":"","sources":["../../src/components/app-open-actions.tsx"],"names":[],"mappings":"AAUA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AASD,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,GAAG,EACH,MAAM,EAAE,cAAc,EACtB,QAAQ,EACR,gBAAwB,EACxB,gBAAwB,GACzB,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,mDAoEA"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { IconChevronDown, IconPlus } from "@tabler/icons-react";
3
+ import { Button } from "./ui/button.js";
4
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "./ui/dropdown-menu.js";
5
+ const DEFAULT_LABELS = {
6
+ addApp: "Add app",
7
+ openApp: "Open app",
8
+ openInline: "Open inline",
9
+ openInNewTab: "Open in new tab",
10
+ };
11
+ export function AppOpenActions({ name, href, target, rel, labels: labelOverrides, onAddApp, showInlineOption = false, showNewTabOption = false, }) {
12
+ const labels = { ...DEFAULT_LABELS, ...labelOverrides };
13
+ const hasMenu = Boolean(onAddApp) ||
14
+ (Boolean(href) && (showInlineOption || showNewTabOption));
15
+ if (!href && !hasMenu) {
16
+ return (_jsx(Button, { size: "sm", variant: "outline", disabled: true, children: labels.openApp }));
17
+ }
18
+ return (_jsxs("div", { className: "flex shrink-0 overflow-hidden rounded-md border border-border focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2", children: [_jsx(Button, { asChild: Boolean(href), size: "sm", variant: "outline", className: "rounded-none border-0 border-e border-border", disabled: !href, children: href ? (_jsx("a", { href: href, target: target, rel: rel, children: labels.openApp })) : (_jsx("span", { children: labels.openApp })) }), hasMenu ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "size-9 rounded-none border-0 p-0", "aria-label": `Open options for ${name}`, children: _jsx(IconChevronDown, { size: 15 }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "min-w-40", children: [onAddApp ? (_jsxs(DropdownMenuItem, { onSelect: onAddApp, children: [_jsx(IconPlus, { size: 14, className: "mr-2" }), labels.addApp] })) : null, showInlineOption && href ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsx("a", { href: href, children: labels.openInline }) })) : null, showNewTabOption && href ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsx("a", { href: href, target: "_blank", rel: "noreferrer", children: labels.openInNewTab }) })) : null] })] })) : null] }));
19
+ }
20
+ //# sourceMappingURL=app-open-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-open-actions.js","sourceRoot":"","sources":["../../src/components/app-open-actions.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconChevronDown, IconPlus } from \"@tabler/icons-react\";\n\nimport { Button } from \"./ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"./ui/dropdown-menu\";\n\nexport interface AppOpenActionLabels {\n addApp: string;\n openApp: string;\n openInline: string;\n openInNewTab: string;\n}\n\nconst DEFAULT_LABELS: AppOpenActionLabels = {\n addApp: \"Add app\",\n openApp: \"Open app\",\n openInline: \"Open inline\",\n openInNewTab: \"Open in new tab\",\n};\n\nexport function AppOpenActions({\n name,\n href,\n target,\n rel,\n labels: labelOverrides,\n onAddApp,\n showInlineOption = false,\n showNewTabOption = false,\n}: {\n name: string;\n href: string | null;\n target?: \"_blank\";\n rel?: string;\n labels?: Partial<AppOpenActionLabels>;\n onAddApp?: () => void;\n showInlineOption?: boolean;\n showNewTabOption?: boolean;\n}) {\n const labels = { ...DEFAULT_LABELS, ...labelOverrides };\n const hasMenu =\n Boolean(onAddApp) ||\n (Boolean(href) && (showInlineOption || showNewTabOption));\n\n if (!href && !hasMenu) {\n return (\n <Button size=\"sm\" variant=\"outline\" disabled>\n {labels.openApp}\n </Button>\n );\n }\n\n return (\n <div className=\"flex shrink-0 overflow-hidden rounded-md border border-border focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\">\n <Button\n asChild={Boolean(href)}\n size=\"sm\"\n variant=\"outline\"\n className=\"rounded-none border-0 border-e border-border\"\n disabled={!href}\n >\n {href ? (\n <a href={href} target={target} rel={rel}>\n {labels.openApp}\n </a>\n ) : (\n <span>{labels.openApp}</span>\n )}\n </Button>\n {hasMenu ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"size-9 rounded-none border-0 p-0\"\n aria-label={`Open options for ${name}`}\n >\n <IconChevronDown size={15} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-40\">\n {onAddApp ? (\n <DropdownMenuItem onSelect={onAddApp}>\n <IconPlus size={14} className=\"mr-2\" />\n {labels.addApp}\n </DropdownMenuItem>\n ) : null}\n {showInlineOption && href ? (\n <DropdownMenuItem asChild>\n <a href={href}>{labels.openInline}</a>\n </DropdownMenuItem>\n ) : null}\n {showNewTabOption && href ? (\n <DropdownMenuItem asChild>\n <a href={href} target=\"_blank\" rel=\"noreferrer\">\n {labels.openInNewTab}\n </a>\n </DropdownMenuItem>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n );\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import type { ConnectedAppSummary } from "../lib/other-apps.js";
2
- export declare function ConnectedAppCard({ app }: {
2
+ export declare function ConnectedAppCard({ app, className, }: {
3
3
  app: ConnectedAppSummary;
4
+ className?: string;
4
5
  }): import("node_modules/@types/react").JSX.Element;
5
6
  //# sourceMappingURL=connected-app-card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connected-app-card.d.ts","sourceRoot":"","sources":["../../src/components/connected-app-card.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,mBAAmB,CAAA;CAAE,mDAmCrE"}
1
+ {"version":3,"file":"connected-app-card.d.ts","sourceRoot":"","sources":["../../src/components/connected-app-card.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAK7D,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,SAAS,GACV,EAAE;IACD,GAAG,EAAE,mBAAmB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,mDAwBA"}
@@ -1,12 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useT } from "@agent-native/core/client/i18n";
3
2
  import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
4
- import { IconArrowUpRight } from "@tabler/icons-react";
5
- export function ConnectedAppCard({ app }) {
6
- const t = useT();
7
- return (_jsxs("a", { href: withBuilderUtmTrackingParams(app.url, {
8
- campaign: "product",
9
- content: "dispatch_app",
10
- }), target: "_blank", rel: "noopener noreferrer", className: "group flex min-h-[116px] items-start gap-3 rounded-xl bg-card/40 p-4 transition-[background-color] hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground", children: app.name.charAt(0).toUpperCase() }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-start justify-between gap-3", children: [_jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), _jsx(IconArrowUpRight, { size: 15, className: "shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5" })] }), _jsx("span", { className: "mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground", children: app.description || app.url }), _jsx("span", { className: "mt-3 block text-xs font-medium text-foreground", children: t("dispatch.pages.openApp") })] })] }));
3
+ import { AppIcon } from "./app-icon.js";
4
+ import { AppListRow } from "./app-list-row.js";
5
+ import { AppOpenActions } from "./app-open-actions.js";
6
+ export function ConnectedAppCard({ app, className, }) {
7
+ return (_jsxs(AppListRow, { className: className, children: [_jsx(AppIcon, { id: app.id, name: app.name, color: app.color, size: "sm" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), _jsx("div", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: app.description || app.url })] }), _jsx(AppOpenActions, { name: app.name, href: withBuilderUtmTrackingParams(app.url, {
8
+ campaign: "product",
9
+ content: "dispatch_app",
10
+ }), target: "_blank", rel: "noopener noreferrer", showNewTabOption: true })] }));
11
11
  }
12
12
  //# sourceMappingURL=connected-app-card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connected-app-card.js","sourceRoot":"","sources":["../../src/components/connected-app-card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAIvD,MAAM,UAAU,gBAAgB,CAAC,EAAE,GAAG,EAAgC;IACpE,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IAEjB,OAAO,CACL,aACE,IAAI,EAAE,4BAA4B,CAAC,GAAG,CAAC,GAAG,EAAE;YAC1C,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,cAAc;SACxB,CAAC,EACF,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAC,+LAA+L,aAEzM,eAAM,SAAS,EAAC,kHAAkH,YAC/H,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAC5B,EACP,gBAAM,SAAS,EAAC,gBAAgB,aAC9B,gBAAM,SAAS,EAAC,wCAAwC,aACtD,eAAM,SAAS,EAAC,gDAAgD,YAC7D,GAAG,CAAC,IAAI,GACJ,EACP,KAAC,gBAAgB,IACf,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,8GAA8G,GACxH,IACG,EACP,eAAM,SAAS,EAAC,qEAAqE,YAClF,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,GACtB,EACP,eAAM,SAAS,EAAC,gDAAgD,YAC7D,CAAC,CAAC,wBAAwB,CAAC,GACvB,IACF,IACL,CACL,CAAC;AACJ,CAAC","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\nimport { IconArrowUpRight } from \"@tabler/icons-react\";\n\nimport type { ConnectedAppSummary } from \"../lib/other-apps\";\n\nexport function ConnectedAppCard({ app }: { app: ConnectedAppSummary }) {\n const t = useT();\n\n return (\n <a\n href={withBuilderUtmTrackingParams(app.url, {\n campaign: \"product\",\n content: \"dispatch_app\",\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"group flex min-h-[116px] items-start gap-3 rounded-xl bg-card/40 p-4 transition-[background-color] hover:bg-accent/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-semibold text-muted-foreground\">\n {app.name.charAt(0).toUpperCase()}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-start justify-between gap-3\">\n <span className=\"truncate text-sm font-semibold text-foreground\">\n {app.name}\n </span>\n <IconArrowUpRight\n size={15}\n className=\"shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5\"\n />\n </span>\n <span className=\"mt-2 line-clamp-2 block text-[13px] leading-5 text-muted-foreground\">\n {app.description || app.url}\n </span>\n <span className=\"mt-3 block text-xs font-medium text-foreground\">\n {t(\"dispatch.pages.openApp\")}\n </span>\n </span>\n </a>\n );\n}\n"]}
1
+ {"version":3,"file":"connected-app-card.js","sourceRoot":"","sources":["../../src/components/connected-app-card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,iDAAiD,CAAC;AAG/F,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,UAAU,gBAAgB,CAAC,EAC/B,GAAG,EACH,SAAS,GAIV;IACC,OAAO,CACL,MAAC,UAAU,IAAC,SAAS,EAAE,SAAS,aAC9B,KAAC,OAAO,IAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAC,IAAI,GAAG,EACnE,eAAK,SAAS,EAAC,gBAAgB,aAC7B,cAAK,SAAS,EAAC,gDAAgD,YAC5D,GAAG,CAAC,IAAI,GACL,EACN,cAAK,SAAS,EAAC,+CAA+C,YAC3D,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,GAAG,GACvB,IACF,EACN,KAAC,cAAc,IACb,IAAI,EAAE,GAAG,CAAC,IAAI,EACd,IAAI,EAAE,4BAA4B,CAAC,GAAG,CAAC,GAAG,EAAE;oBAC1C,QAAQ,EAAE,SAAS;oBACnB,OAAO,EAAE,cAAc;iBACxB,CAAC,EACF,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,EACzB,gBAAgB,SAChB,IACS,CACd,CAAC;AACJ,CAAC","sourcesContent":["import { withBuilderUtmTrackingParams } from \"@agent-native/core/shared/builder-link-tracking\";\n\nimport type { ConnectedAppSummary } from \"../lib/other-apps\";\nimport { AppIcon } from \"./app-icon\";\nimport { AppListRow } from \"./app-list-row\";\nimport { AppOpenActions } from \"./app-open-actions\";\n\nexport function ConnectedAppCard({\n app,\n className,\n}: {\n app: ConnectedAppSummary;\n className?: string;\n}) {\n return (\n <AppListRow className={className}>\n <AppIcon id={app.id} name={app.name} color={app.color} size=\"sm\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-semibold text-foreground\">\n {app.name}\n </div>\n <div className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {app.description || app.url}\n </div>\n </div>\n <AppOpenActions\n name={app.name}\n href={withBuilderUtmTrackingParams(app.url, {\n campaign: \"product\",\n content: \"dispatch_app\",\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n showNewTabOption\n />\n </AppListRow>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-control-plane.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-control-plane.tsx"],"names":[],"mappings":"AAsQA,wBAAgB,oBAAoB,oDAoCnC"}
1
+ {"version":3,"file":"dispatch-control-plane.d.ts","sourceRoot":"","sources":["../../src/components/dispatch-control-plane.tsx"],"names":[],"mappings":"AA4UA,wBAAgB,oBAAoB,oDAwCnC"}
@@ -1,18 +1,19 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { navigateWithAgentChatViewTransition, useChatModels, } from "@agent-native/core/client/agent-chat";
3
3
  import { PromptComposer } from "@agent-native/core/client/composer";
4
4
  import { useActionQuery } from "@agent-native/core/client/hooks";
5
5
  import { isInBuilderFrame } from "@agent-native/core/client/host";
6
6
  import { useT } from "@agent-native/core/client/i18n";
7
- import { IconArrowUpRight, IconChevronDown, IconClockHour4, } from "@tabler/icons-react";
7
+ import { IconArrowUpRight, IconChevronDown, IconClockHour4, IconApps, } from "@tabler/icons-react";
8
8
  import { useState } from "react";
9
9
  import { Link, useNavigate } from "react-router";
10
- import { filterOtherApps } from "../lib/other-apps.js";
11
10
  import { submitOverviewPrompt } from "../lib/overview-chat.js";
11
+ import { cn } from "../lib/utils.js";
12
12
  import { ActionQueryError } from "./action-query-error.js";
13
- import { ConnectedAppCard } from "./connected-app-card.js";
13
+ import { APP_LIST_GRID_CLASS, AppList, APP_LIST_GRID_ROW_CLASS, } from "./app-list-row.js";
14
14
  import { CreateAppPopover } from "./create-app-popover.js";
15
15
  import { useSetPageTitle } from "./layout/HeaderActions.js";
16
+ import { OtherAppsSection } from "./other-apps-section.js";
16
17
  import { Button } from "./ui/button.js";
17
18
  import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "./ui/collapsible.js";
18
19
  import { Skeleton } from "./ui/skeleton.js";
@@ -20,6 +21,9 @@ import { WorkspaceAppCard } from "./workspace-app-card.js";
20
21
  function SectionHeader({ title, action, }) {
21
22
  return (_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3", children: [_jsx("h2", { className: "truncate text-sm font-semibold text-foreground", children: title }), action ? _jsx("div", { className: "shrink-0", children: action }) : null] }));
22
23
  }
24
+ function AppGroupHeader({ title, description, }) {
25
+ return (_jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [_jsx(IconApps, { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: title }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description })] })] }));
26
+ }
23
27
  function CommandPanel() {
24
28
  const t = useT();
25
29
  const { availableModels, isLoading: modelListLoading, onEffortChange, onModelChange, selectedEffort, selectedEngine, selectedModel, } = useChatModels({ storageKey: "dispatch" });
@@ -63,29 +67,32 @@ function CommandPanel() {
63
67
  defaultValue: "Ask Dispatch anything...",
64
68
  }), selectedEffort: selectedEffort, selectedEngine: selectedEngine, selectedModel: selectedModel, onEffortChange: onEffortChange, onModelChange: onModelChange, onSubmit: (text) => send(text) }), _jsx("div", { className: "mt-3 flex flex-wrap justify-center gap-2", children: promptSuggestions.map((suggestion) => (_jsx("button", { type: "button", onClick: () => send(suggestion), className: "cursor-pointer rounded-md border border-transparent bg-muted/60 px-2.5 py-1.5 text-xs text-muted-foreground transition-[background-color,color] hover:bg-muted hover:text-foreground", children: suggestion }, suggestion))) })] }) }));
65
69
  }
66
- function AppsPanel({ apps, isLoading, otherApps, otherAppsError, otherAppsLoading, onRetryOtherApps, }) {
70
+ function AppsPanel({ apps, isLoading, connectedApps, connectedAppsError, connectedAppsLoading, onRetryConnectedApps, curatedTemplates, curatedTemplatesError, curatedTemplatesLoading, onRetryCuratedTemplates, }) {
67
71
  const t = useT();
68
72
  const [showPending, setShowPending] = useState(false);
69
73
  const visibleApps = apps.filter((app) => !app.isDispatch && !app.archived);
70
74
  const activeApps = visibleApps.filter((app) => app.status !== "pending");
71
75
  const pendingApps = visibleApps.filter((app) => app.status === "pending");
72
- const hasActiveApps = activeApps.length > 0 || otherApps.length > 0;
73
- const showSkeletons = (isLoading || otherAppsLoading) &&
74
- activeApps.length === 0 &&
75
- otherApps.length === 0 &&
76
- pendingApps.length === 0;
77
- return (_jsxs("section", { className: "flex flex-col gap-3", children: [_jsx(SectionHeader, { title: "Apps", action: _jsx(Button, { variant: "outline", size: "sm", asChild: true, children: _jsxs(Link, { to: "/apps", children: ["View all", _jsx(IconArrowUpRight, { size: 14 })] }) }) }), showSkeletons ? (_jsx("div", { className: "grid gap-3 md:grid-cols-2", children: Array.from({ length: 4 }).map((_, index) => (_jsxs("div", { className: "rounded-xl bg-card/40 p-4", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "mt-3 h-3 w-24" }), _jsx(Skeleton, { className: "mt-3 h-3 w-full" })] }, index))) })) : hasActiveApps ? (_jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [activeApps.map((app) => (_jsx(WorkspaceAppCard, { app: app, className: "min-h-32" }, app.id))), otherApps.map((app) => (_jsx(ConnectedAppCard, { app: app }, app.id)))] })) : (_jsx(CreateAppPopover, {})), otherAppsError ? (_jsx(ActionQueryError, { error: otherAppsError, onRetry: onRetryOtherApps })) : null, pendingApps.length > 0 ? (_jsx(Collapsible, { open: showPending, onOpenChange: setShowPending, children: _jsxs("div", { className: "space-y-3 border-t pt-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(IconClockHour4, { size: 15, className: "shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-xs font-semibold text-foreground", children: t("dispatch.pages.pendingApps") }), _jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.pendingAppsDescription", {
76
+ const showSkeletons = isLoading && activeApps.length === 0 && pendingApps.length === 0;
77
+ return (_jsxs("section", { className: "flex flex-col gap-3", children: [_jsx(SectionHeader, { title: "Apps", action: _jsx(Button, { variant: "outline", size: "sm", asChild: true, children: _jsxs(Link, { to: "/apps", children: ["View all", _jsx(IconArrowUpRight, { size: 14 })] }) }) }), showSkeletons ? (_jsx(OverviewAppsSkeleton, {})) : (_jsxs(_Fragment, { children: [activeApps.length > 0 ? (_jsxs("div", { className: "space-y-3", children: [_jsx(AppGroupHeader, { title: t("dispatch.pages.yourApps", {
78
+ defaultValue: "Your apps",
79
+ }), description: t("dispatch.pages.activeCount", {
80
+ count: activeApps.length,
81
+ }) }), _jsx(AppList, { className: APP_LIST_GRID_CLASS, children: activeApps.map((app) => (_jsx(WorkspaceAppCard, { app: app, className: APP_LIST_GRID_ROW_CLASS }, app.id))) })] })) : (_jsx(CreateAppPopover, {})), _jsx(OtherAppsSection, { templates: curatedTemplates, connectedApps: connectedApps, workspaceApps: apps, templatesLoading: curatedTemplatesLoading, connectedAppsLoading: connectedAppsLoading, templatesError: curatedTemplatesError, connectedAppsError: connectedAppsError, onRetryTemplates: onRetryCuratedTemplates, onRetryConnectedApps: onRetryConnectedApps })] })), pendingApps.length > 0 ? (_jsx(Collapsible, { open: showPending, onOpenChange: setShowPending, children: _jsxs("div", { className: "space-y-3 border-t pt-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(IconClockHour4, { size: 15, className: "shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-xs font-semibold text-foreground", children: t("dispatch.pages.pendingApps") }), _jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.pendingAppsDescription", {
78
82
  count: pendingApps.length,
79
83
  }) })] })] }), _jsx(CollapsibleTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7 gap-1.5 px-2 text-xs", children: [showPending
80
84
  ? t("dispatch.pages.hidePendingApps")
81
- : t("dispatch.pages.showPendingApps"), _jsx(IconChevronDown, { size: 13, className: showPending ? "rotate-180" : undefined })] }) })] }), _jsx(CollapsibleContent, { children: _jsx("div", { className: "grid gap-3 md:grid-cols-2", children: pendingApps.map((app) => (_jsx(WorkspaceAppCard, { app: app, className: "min-h-32" }, app.id))) }) })] }) })) : null] }));
85
+ : t("dispatch.pages.showPendingApps"), _jsx(IconChevronDown, { size: 13, className: showPending ? "rotate-180" : undefined })] }) })] }), _jsx(CollapsibleContent, { children: _jsx(AppList, { className: APP_LIST_GRID_CLASS, children: pendingApps.map((app) => (_jsx(WorkspaceAppCard, { app: app, className: APP_LIST_GRID_ROW_CLASS }, app.id))) }) })] }) })) : null] }));
86
+ }
87
+ function OverviewAppsSkeleton() {
88
+ return (_jsx(AppList, { className: APP_LIST_GRID_CLASS, children: Array.from({ length: 4 }).map((_, index) => (_jsxs("div", { className: cn("flex min-w-0 items-center gap-3 border-b px-4 py-3.5 last:border-b-0", APP_LIST_GRID_ROW_CLASS), children: [_jsx(Skeleton, { className: "size-8 shrink-0 rounded-xl" }), _jsxs("div", { className: "min-w-0 flex-1 space-y-2", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] }), _jsx(Skeleton, { className: "h-9 w-24 shrink-0 rounded-md" })] }, index))) }));
82
89
  }
83
90
  export function DispatchControlPlane() {
84
91
  useSetPageTitle(_jsx("span", { "aria-hidden": true }));
85
92
  const appsQuery = useActionQuery("list-workspace-apps", { includeAgentCards: false, includeArchived: true });
86
93
  const connectedAppsQuery = useActionQuery("list-connected-agents", {});
94
+ const curatedTemplatesQuery = useActionQuery("list-curated-workspace-templates", {});
87
95
  const { data: workspaceApps = [], isLoading: appsLoading } = appsQuery;
88
- const otherApps = filterOtherApps(connectedAppsQuery.data ?? [], workspaceApps ?? []);
89
- return (_jsxs("div", { className: "flex flex-col gap-8", children: [_jsx(CommandPanel, {}), appsQuery.isError ? (_jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() })) : (_jsx(AppsPanel, { apps: workspaceApps ?? [], isLoading: appsLoading, otherApps: otherApps, otherAppsError: connectedAppsQuery.error, otherAppsLoading: connectedAppsQuery.isLoading, onRetryOtherApps: () => void connectedAppsQuery.refetch() }))] }));
96
+ return (_jsxs("div", { className: "flex flex-col gap-8", children: [_jsx(CommandPanel, {}), appsQuery.isError ? (_jsx(ActionQueryError, { error: appsQuery.error, onRetry: () => void appsQuery.refetch() })) : (_jsx(AppsPanel, { apps: workspaceApps ?? [], isLoading: appsLoading, connectedApps: connectedAppsQuery.data ?? [], connectedAppsError: connectedAppsQuery.error, connectedAppsLoading: connectedAppsQuery.isLoading, onRetryConnectedApps: () => void connectedAppsQuery.refetch(), curatedTemplates: curatedTemplatesQuery.data, curatedTemplatesError: curatedTemplatesQuery.error, curatedTemplatesLoading: curatedTemplatesQuery.isLoading, onRetryCuratedTemplates: () => void curatedTemplatesQuery.refetch() }))] }));
90
97
  }
91
98
  //# sourceMappingURL=dispatch-control-plane.js.map