@meetreeve/ui 0.11.0 → 0.13.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.
- package/README.md +29 -0
- package/dist/index.d.mts +67 -1
- package/dist/index.d.ts +67 -1
- package/dist/index.js +308 -165
- package/dist/index.mjs +307 -165
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ __export(src_exports, {
|
|
|
37
37
|
ContextSwitcher: () => ContextSwitcher,
|
|
38
38
|
Flyout: () => Flyout,
|
|
39
39
|
GLYPH_CANVAS_FILL: () => GLYPH_CANVAS_FILL,
|
|
40
|
+
InfoTip: () => InfoTip,
|
|
40
41
|
LOCKUP_GAP: () => LOCKUP_GAP,
|
|
41
42
|
LOCKUP_ROW: () => LOCKUP_ROW,
|
|
42
43
|
MARK_CAP_RATIO: () => MARK_CAP_RATIO,
|
|
@@ -472,6 +473,44 @@ function useResponsivePlaceholder(desktop, mobile) {
|
|
|
472
473
|
return isDesktop ? desktop : mobile ?? desktop;
|
|
473
474
|
}
|
|
474
475
|
|
|
476
|
+
// src/info-tip.tsx
|
|
477
|
+
var import_popover = require("@base-ui/react/popover");
|
|
478
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
479
|
+
function InfoTip({ children, label = "More information", side = "top", align = "center", className }) {
|
|
480
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_popover.Popover.Root, { children: [
|
|
481
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
482
|
+
import_popover.Popover.Trigger,
|
|
483
|
+
{
|
|
484
|
+
openOnHover: true,
|
|
485
|
+
delay: 150,
|
|
486
|
+
closeDelay: 100,
|
|
487
|
+
"aria-label": label,
|
|
488
|
+
style: TOUCH_TARGET_STYLE,
|
|
489
|
+
className: cn(
|
|
490
|
+
"group -my-3.5 inline-flex shrink-0 cursor-help items-center justify-center rounded-full align-middle text-muted-foreground outline-none transition-colors hover:text-foreground data-[popup-open]:text-foreground",
|
|
491
|
+
className
|
|
492
|
+
),
|
|
493
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
494
|
+
"span",
|
|
495
|
+
{
|
|
496
|
+
"aria-hidden": "true",
|
|
497
|
+
className: "inline-flex size-4 items-center justify-center rounded-full border border-current text-[0.625rem] font-semibold leading-none group-focus-visible:ring-2 group-focus-visible:ring-ring/50",
|
|
498
|
+
children: "?"
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
}
|
|
502
|
+
),
|
|
503
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_popover.Popover.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_popover.Popover.Positioner, { side, align, sideOffset: 8, collisionPadding: 16, className: "z-50", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
504
|
+
import_popover.Popover.Popup,
|
|
505
|
+
{
|
|
506
|
+
"aria-label": label,
|
|
507
|
+
className: "max-w-[min(20rem,calc(100vw-2rem))] origin-[var(--transform-origin)] rounded-md border border-border bg-popover px-3 py-2 text-left text-xs font-normal leading-relaxed text-popover-foreground shadow-md outline-none transition-[opacity,transform] duration-150 ease-out data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0 motion-reduce:transition-none",
|
|
508
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_popover.Popover.Description, { children })
|
|
509
|
+
}
|
|
510
|
+
) }) })
|
|
511
|
+
] });
|
|
512
|
+
}
|
|
513
|
+
|
|
475
514
|
// src/app-sidebar.tsx
|
|
476
515
|
var import_react8 = require("react");
|
|
477
516
|
var import_lucide_react2 = require("lucide-react");
|
|
@@ -754,7 +793,7 @@ function useLadderRung(ladder, containerRef, options = {}) {
|
|
|
754
793
|
|
|
755
794
|
// src/ladder/flyout.tsx
|
|
756
795
|
var import_react7 = require("react");
|
|
757
|
-
var
|
|
796
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
758
797
|
var PANEL_GAP = 4;
|
|
759
798
|
function Flyout({
|
|
760
799
|
label,
|
|
@@ -818,7 +857,7 @@ function Flyout({
|
|
|
818
857
|
(0, import_react7.useEffect)(() => {
|
|
819
858
|
if (clickOpen && panelPosition) firstItemRef.current?.focus();
|
|
820
859
|
}, [clickOpen, panelPosition]);
|
|
821
|
-
return /* @__PURE__ */ (0,
|
|
860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
822
861
|
"div",
|
|
823
862
|
{
|
|
824
863
|
"data-testid": "ladder-flyout",
|
|
@@ -826,7 +865,7 @@ function Flyout({
|
|
|
826
865
|
onMouseEnter: () => setHoverOpen(true),
|
|
827
866
|
onMouseLeave: () => setHoverOpen(false),
|
|
828
867
|
children: [
|
|
829
|
-
/* @__PURE__ */ (0,
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
830
869
|
"button",
|
|
831
870
|
{
|
|
832
871
|
ref: triggerRef,
|
|
@@ -849,7 +888,7 @@ function Flyout({
|
|
|
849
888
|
active ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:bg-sidebar-foreground/5 hover:text-sidebar-foreground"
|
|
850
889
|
),
|
|
851
890
|
children: [
|
|
852
|
-
/* @__PURE__ */ (0,
|
|
891
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
853
892
|
Icon,
|
|
854
893
|
{
|
|
855
894
|
className: cn(
|
|
@@ -860,11 +899,11 @@ function Flyout({
|
|
|
860
899
|
"aria-hidden": "true"
|
|
861
900
|
}
|
|
862
901
|
),
|
|
863
|
-
/* @__PURE__ */ (0,
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: cn("truncate", collapsed && "sr-only"), children: label })
|
|
864
903
|
]
|
|
865
904
|
}
|
|
866
905
|
),
|
|
867
|
-
open && panelPosition && /* @__PURE__ */ (0,
|
|
906
|
+
open && panelPosition && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
868
907
|
"div",
|
|
869
908
|
{
|
|
870
909
|
ref: panelRef,
|
|
@@ -886,7 +925,7 @@ function Flyout({
|
|
|
886
925
|
// silently loses the focus-on-open behavior (a console ref
|
|
887
926
|
// warning, not a crash) — same tradeoff any Link-injection
|
|
888
927
|
// pattern accepts; not a regression from today's plain `<a>`.
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
890
929
|
LinkEl,
|
|
891
930
|
{
|
|
892
931
|
ref: i === 0 ? firstItemRef : void 0,
|
|
@@ -910,7 +949,7 @@ function Flyout({
|
|
|
910
949
|
}
|
|
911
950
|
|
|
912
951
|
// src/app-sidebar.tsx
|
|
913
|
-
var
|
|
952
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
914
953
|
var DEFAULT_COLLAPSE_STORAGE_KEY = "reeve-sidebar-collapsed";
|
|
915
954
|
var COLLAPSED_WIDTH_CLASS = "w-14";
|
|
916
955
|
var EXPANDED_WIDTH_CLASS = "w-64";
|
|
@@ -928,7 +967,7 @@ function NavLink({
|
|
|
928
967
|
}) {
|
|
929
968
|
const Icon = resolveIcon(icon);
|
|
930
969
|
const LinkEl = linkComponent ?? "a";
|
|
931
|
-
return /* @__PURE__ */ (0,
|
|
970
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
932
971
|
LinkEl,
|
|
933
972
|
{
|
|
934
973
|
href,
|
|
@@ -948,7 +987,7 @@ function NavLink({
|
|
|
948
987
|
active ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:bg-sidebar-foreground/5 hover:text-sidebar-foreground"
|
|
949
988
|
),
|
|
950
989
|
children: [
|
|
951
|
-
/* @__PURE__ */ (0,
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
952
991
|
Icon,
|
|
953
992
|
{
|
|
954
993
|
className: cn(
|
|
@@ -959,7 +998,7 @@ function NavLink({
|
|
|
959
998
|
"aria-hidden": "true"
|
|
960
999
|
}
|
|
961
1000
|
),
|
|
962
|
-
/* @__PURE__ */ (0,
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("truncate", collapsed && "sr-only"), children: label })
|
|
963
1002
|
]
|
|
964
1003
|
}
|
|
965
1004
|
);
|
|
@@ -1047,7 +1086,7 @@ function AppSidebar({
|
|
|
1047
1086
|
function renderAppItem(item, testIdPrefix, collapsedRow = false) {
|
|
1048
1087
|
const def = moduleMap.get(item.moduleId);
|
|
1049
1088
|
if (!def) return null;
|
|
1050
|
-
return /* @__PURE__ */ (0,
|
|
1089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1051
1090
|
NavLink,
|
|
1052
1091
|
{
|
|
1053
1092
|
href: def.href,
|
|
@@ -1073,7 +1112,7 @@ function AppSidebar({
|
|
|
1073
1112
|
};
|
|
1074
1113
|
});
|
|
1075
1114
|
const active = children.some((c) => c.active);
|
|
1076
|
-
return /* @__PURE__ */ (0,
|
|
1115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1077
1116
|
Flyout,
|
|
1078
1117
|
{
|
|
1079
1118
|
label: item.label,
|
|
@@ -1091,7 +1130,7 @@ function AppSidebar({
|
|
|
1091
1130
|
function brandBlockFor(collapsedMode) {
|
|
1092
1131
|
if (!brand) return null;
|
|
1093
1132
|
if (collapsedMode) {
|
|
1094
|
-
return /* @__PURE__ */ (0,
|
|
1133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1095
1134
|
"a",
|
|
1096
1135
|
{
|
|
1097
1136
|
href: brand.href,
|
|
@@ -1099,28 +1138,28 @@ function AppSidebar({
|
|
|
1099
1138
|
title: brand.label,
|
|
1100
1139
|
className: "flex items-center justify-center border-b border-sidebar-border px-1 py-4",
|
|
1101
1140
|
children: [
|
|
1102
|
-
/* @__PURE__ */ (0,
|
|
1103
|
-
/* @__PURE__ */ (0,
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "sr-only", children: brand.label }),
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(BrandGlyph, { brand: { name: brand.label }, size: "xl" })
|
|
1104
1143
|
]
|
|
1105
1144
|
}
|
|
1106
1145
|
);
|
|
1107
1146
|
}
|
|
1108
|
-
return /* @__PURE__ */ (0,
|
|
1147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1109
1148
|
"a",
|
|
1110
1149
|
{
|
|
1111
1150
|
href: brand.href,
|
|
1112
1151
|
"data-testid": "app-sidebar-brand",
|
|
1113
1152
|
className: "flex items-center gap-2.5 border-b border-sidebar-border px-5 py-4 text-sidebar-foreground",
|
|
1114
1153
|
children: [
|
|
1115
|
-
/* @__PURE__ */ (0,
|
|
1116
|
-
/* @__PURE__ */ (0,
|
|
1154
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "grid size-7 place-items-center rounded-md bg-sidebar-primary text-sidebar-primary-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-mono text-sm font-bold", children: (brand.label[0] ?? "r").toUpperCase() }) }),
|
|
1155
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate text-sm font-semibold tracking-tight", children: brand.label })
|
|
1117
1156
|
]
|
|
1118
1157
|
}
|
|
1119
1158
|
);
|
|
1120
1159
|
}
|
|
1121
1160
|
function topItemBlock(testId, collapsedMode = false) {
|
|
1122
1161
|
if (!topItem) return null;
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: cn("px-3 pt-4", collapsedMode && "flex justify-center px-0"), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1124
1163
|
NavLink,
|
|
1125
1164
|
{
|
|
1126
1165
|
href: topItem.href,
|
|
@@ -1133,8 +1172,8 @@ function AppSidebar({
|
|
|
1133
1172
|
}
|
|
1134
1173
|
) });
|
|
1135
1174
|
}
|
|
1136
|
-
return /* @__PURE__ */ (0,
|
|
1137
|
-
!isDesktop && /* @__PURE__ */ (0,
|
|
1175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1176
|
+
!isDesktop && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1138
1177
|
"button",
|
|
1139
1178
|
{
|
|
1140
1179
|
ref: mobileTriggerRef,
|
|
@@ -1146,11 +1185,11 @@ function AppSidebar({
|
|
|
1146
1185
|
onClick: () => setMobileOpen((v) => !v),
|
|
1147
1186
|
style: TOUCH_TARGET_STYLE,
|
|
1148
1187
|
className: "flex items-center justify-center rounded-md border border-border p-2 text-foreground",
|
|
1149
|
-
children: mobileOpen ? /* @__PURE__ */ (0,
|
|
1188
|
+
children: mobileOpen ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.X, { className: "h-5 w-5", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.Menu, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
1150
1189
|
}
|
|
1151
1190
|
),
|
|
1152
|
-
!isDesktop && mobileOpen && /* @__PURE__ */ (0,
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1191
|
+
!isDesktop && mobileOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "fixed inset-0 z-50", children: [
|
|
1192
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1154
1193
|
"div",
|
|
1155
1194
|
{
|
|
1156
1195
|
"data-testid": "app-sidebar-mobile-scrim",
|
|
@@ -1159,7 +1198,7 @@ function AppSidebar({
|
|
|
1159
1198
|
onClick: () => setMobileOpen(false)
|
|
1160
1199
|
}
|
|
1161
1200
|
),
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1163
1202
|
"div",
|
|
1164
1203
|
{
|
|
1165
1204
|
ref: mobileDrawerRef,
|
|
@@ -1170,7 +1209,7 @@ function AppSidebar({
|
|
|
1170
1209
|
"data-testid": "app-sidebar-mobile-drawer",
|
|
1171
1210
|
className: "absolute inset-y-0 left-0 flex w-72 flex-col overflow-y-auto border-r border-sidebar-border bg-sidebar",
|
|
1172
1211
|
children: [
|
|
1173
|
-
/* @__PURE__ */ (0,
|
|
1212
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "sticky top-0 z-10 flex justify-end bg-sidebar p-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1174
1213
|
"button",
|
|
1175
1214
|
{
|
|
1176
1215
|
ref: mobileCloseRef,
|
|
@@ -1180,19 +1219,19 @@ function AppSidebar({
|
|
|
1180
1219
|
onClick: () => setMobileOpen(false),
|
|
1181
1220
|
style: TOUCH_TARGET_STYLE,
|
|
1182
1221
|
className: "flex items-center justify-center rounded-md p-2 text-sidebar-foreground/70 hover:bg-sidebar-foreground/5 hover:text-sidebar-foreground",
|
|
1183
|
-
children: /* @__PURE__ */ (0,
|
|
1222
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.X, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
1184
1223
|
}
|
|
1185
1224
|
) }),
|
|
1186
1225
|
brandBlockFor(false),
|
|
1187
1226
|
topItemBlock("app-sidebar-mobile-top-item"),
|
|
1188
|
-
/* @__PURE__ */ (0,
|
|
1227
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "flex-1 px-3 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex flex-col gap-0.5", children: rung0.items.map(
|
|
1189
1228
|
(item) => item.type === "app" ? renderAppItem(item, "app-sidebar-mobile-navlink") : null
|
|
1190
1229
|
) }) })
|
|
1191
1230
|
]
|
|
1192
1231
|
}
|
|
1193
1232
|
)
|
|
1194
1233
|
] }),
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1196
1235
|
"aside",
|
|
1197
1236
|
{
|
|
1198
1237
|
"data-testid": "app-sidebar-desktop",
|
|
@@ -1207,18 +1246,18 @@ function AppSidebar({
|
|
|
1207
1246
|
children: [
|
|
1208
1247
|
brandBlockFor(collapsed),
|
|
1209
1248
|
topItemBlock("app-sidebar-top-item", collapsed),
|
|
1210
|
-
/* @__PURE__ */ (0,
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1211
1250
|
"nav",
|
|
1212
1251
|
{
|
|
1213
1252
|
ref: containerRef,
|
|
1214
1253
|
"data-testid": "app-sidebar-nav",
|
|
1215
1254
|
className: "flex-1 overflow-y-auto px-3 py-4",
|
|
1216
|
-
children: /* @__PURE__ */ (0,
|
|
1255
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex flex-col gap-0.5", children: rung.items.map(
|
|
1217
1256
|
(item) => item.type === "app" ? renderAppItem(item, "app-sidebar-navlink", collapsed) : renderGroupItem(item, collapsed)
|
|
1218
1257
|
) })
|
|
1219
1258
|
}
|
|
1220
1259
|
),
|
|
1221
|
-
collapsible && /* @__PURE__ */ (0,
|
|
1260
|
+
collapsible && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "border-t border-sidebar-border px-2 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1222
1261
|
"button",
|
|
1223
1262
|
{
|
|
1224
1263
|
type: "button",
|
|
@@ -1232,8 +1271,8 @@ function AppSidebar({
|
|
|
1232
1271
|
collapsed && "justify-center px-0"
|
|
1233
1272
|
),
|
|
1234
1273
|
children: [
|
|
1235
|
-
collapsed ? /* @__PURE__ */ (0,
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1274
|
+
collapsed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.PanelLeftOpen, { className: "size-4 shrink-0", strokeWidth: 1.5, "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react2.PanelLeftClose, { className: "size-4 shrink-0", strokeWidth: 1.5, "aria-hidden": "true" }),
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: cn("truncate", collapsed && "sr-only"), children: collapsed ? "Expand sidebar" : "Collapse sidebar" })
|
|
1237
1276
|
]
|
|
1238
1277
|
}
|
|
1239
1278
|
) })
|
|
@@ -1272,19 +1311,19 @@ function groupItemsByOrg(rows, get) {
|
|
|
1272
1311
|
|
|
1273
1312
|
// src/lib/dropdown-menu.tsx
|
|
1274
1313
|
var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
|
|
1275
|
-
var
|
|
1314
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1276
1315
|
function DropdownMenu(props) {
|
|
1277
|
-
return /* @__PURE__ */ (0,
|
|
1316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1278
1317
|
}
|
|
1279
1318
|
function DropdownMenuTrigger(props) {
|
|
1280
|
-
return /* @__PURE__ */ (0,
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1281
1320
|
}
|
|
1282
1321
|
function DropdownMenuContent({
|
|
1283
1322
|
className,
|
|
1284
1323
|
sideOffset = 4,
|
|
1285
1324
|
...props
|
|
1286
1325
|
}) {
|
|
1287
|
-
return /* @__PURE__ */ (0,
|
|
1326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1288
1327
|
DropdownMenuPrimitive.Content,
|
|
1289
1328
|
{
|
|
1290
1329
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1301,7 +1340,7 @@ function DropdownMenuItem({
|
|
|
1301
1340
|
className,
|
|
1302
1341
|
...props
|
|
1303
1342
|
}) {
|
|
1304
|
-
return /* @__PURE__ */ (0,
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1305
1344
|
DropdownMenuPrimitive.Item,
|
|
1306
1345
|
{
|
|
1307
1346
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1317,7 +1356,7 @@ function DropdownMenuLabel({
|
|
|
1317
1356
|
className,
|
|
1318
1357
|
...props
|
|
1319
1358
|
}) {
|
|
1320
|
-
return /* @__PURE__ */ (0,
|
|
1359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1321
1360
|
DropdownMenuPrimitive.Label,
|
|
1322
1361
|
{
|
|
1323
1362
|
"data-slot": "dropdown-menu-label",
|
|
@@ -1328,7 +1367,7 @@ function DropdownMenuLabel({
|
|
|
1328
1367
|
}
|
|
1329
1368
|
|
|
1330
1369
|
// src/context-switcher.tsx
|
|
1331
|
-
var
|
|
1370
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1332
1371
|
function groupByOrg(items) {
|
|
1333
1372
|
return groupItemsByOrg(items, {
|
|
1334
1373
|
orgId: (it) => it.orgId,
|
|
@@ -1359,29 +1398,29 @@ function ContextSwitcher({
|
|
|
1359
1398
|
const active = items.find((it) => it.refId === activeRefId) ?? null;
|
|
1360
1399
|
const groups = groupByOrg(items);
|
|
1361
1400
|
const showOrgHeaders = groups.length > 1;
|
|
1362
|
-
return /* @__PURE__ */ (0,
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(DropdownMenu, { children: [
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DropdownMenuTrigger, { asChild: true, children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1364
1403
|
"button",
|
|
1365
1404
|
{
|
|
1366
1405
|
type: "button",
|
|
1367
1406
|
title: active?.name || placeholder,
|
|
1368
1407
|
"aria-label": active?.name || placeholder,
|
|
1369
1408
|
className: "flex h-10 w-10 items-center justify-center rounded-lg text-sidebar-foreground/70 transition-colors hover:bg-sidebar-foreground/5 hover:text-sidebar-foreground",
|
|
1370
|
-
children: /* @__PURE__ */ (0,
|
|
1409
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BrandGlyph, { brand: toBrand(active ?? { name: "" }), size: "lg" })
|
|
1371
1410
|
}
|
|
1372
|
-
) : /* @__PURE__ */ (0,
|
|
1411
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1373
1412
|
"button",
|
|
1374
1413
|
{
|
|
1375
1414
|
type: "button",
|
|
1376
1415
|
className: "group flex items-center gap-2 rounded-md border border-sidebar-border bg-sidebar-accent/60 px-2.5 py-1.5 text-sm font-medium transition-colors hover:bg-sidebar",
|
|
1377
1416
|
children: [
|
|
1378
|
-
/* @__PURE__ */ (0,
|
|
1379
|
-
/* @__PURE__ */ (0,
|
|
1380
|
-
/* @__PURE__ */ (0,
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BrandGlyph, { brand: toBrand(active ?? { name: "" }) }),
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "max-w-[140px] truncate text-sidebar-accent-foreground", children: active?.name || placeholder }),
|
|
1419
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.ChevronDown, { className: "h-3.5 w-3.5 text-sidebar-foreground/70 transition-transform group-data-[state=open]:rotate-180" })
|
|
1381
1420
|
]
|
|
1382
1421
|
}
|
|
1383
1422
|
) }),
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1385
1424
|
DropdownMenuContent,
|
|
1386
1425
|
{
|
|
1387
1426
|
side,
|
|
@@ -1390,31 +1429,31 @@ function ContextSwitcher({
|
|
|
1390
1429
|
collisionPadding: 8,
|
|
1391
1430
|
className: cn("w-60 overflow-hidden p-0", contentClassName),
|
|
1392
1431
|
children: [
|
|
1393
|
-
groups.map((group) => /* @__PURE__ */ (0,
|
|
1394
|
-
showOrgHeaders && /* @__PURE__ */ (0,
|
|
1395
|
-
/* @__PURE__ */ (0,
|
|
1432
|
+
groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1433
|
+
showOrgHeaders && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DropdownMenuLabel, { className: "px-3 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: group.orgName ?? "Other" }),
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn(showOrgHeaders && "ml-5 border-l border-border/60"), children: group.items.map((item) => {
|
|
1396
1435
|
const isActive = item.refId === activeRefId;
|
|
1397
|
-
return /* @__PURE__ */ (0,
|
|
1436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1398
1437
|
DropdownMenuItem,
|
|
1399
1438
|
{
|
|
1400
1439
|
"data-active": isActive || void 0,
|
|
1401
1440
|
onSelect: () => onSelect(item),
|
|
1402
1441
|
className: "flex w-full items-center gap-2.5 rounded-none px-3 py-2 text-sm",
|
|
1403
1442
|
children: [
|
|
1404
|
-
/* @__PURE__ */ (0,
|
|
1405
|
-
/* @__PURE__ */ (0,
|
|
1406
|
-
item.kindLabel && /* @__PURE__ */ (0,
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BrandGlyph, { brand: toBrand(item), subtle: true }),
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "flex-1 truncate text-left text-foreground/90", children: item.name }),
|
|
1445
|
+
item.kindLabel && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1407
1446
|
" ",
|
|
1408
|
-
/* @__PURE__ */ (0,
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: item.kindLabel })
|
|
1409
1448
|
] }),
|
|
1410
|
-
isActive && /* @__PURE__ */ (0,
|
|
1449
|
+
isActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.Check, { className: "size-3.5 text-emerald-500" })
|
|
1411
1450
|
]
|
|
1412
1451
|
},
|
|
1413
1452
|
item.refId
|
|
1414
1453
|
);
|
|
1415
1454
|
}) })
|
|
1416
1455
|
] }, group.orgId ?? "unattributed")),
|
|
1417
|
-
footer && /* @__PURE__ */ (0,
|
|
1456
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "sticky bottom-0 border-t border-border bg-popover", children: footer })
|
|
1418
1457
|
]
|
|
1419
1458
|
}
|
|
1420
1459
|
)
|
|
@@ -1423,8 +1462,10 @@ function ContextSwitcher({
|
|
|
1423
1462
|
|
|
1424
1463
|
// src/connector-picker.tsx
|
|
1425
1464
|
var import_react9 = require("react");
|
|
1426
|
-
var
|
|
1465
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1427
1466
|
var DEFAULT_CONNECT_ERROR = "Couldn't start the connection. Please try again.";
|
|
1467
|
+
var MAX_RECONNECT_REFOCUS_CHECKS = 3;
|
|
1468
|
+
var RECONNECT_UNCONFIRMED_ERROR = "Couldn't confirm the reconnect \u2014 the connection still reports unhealthy. Try again, or disconnect and reconnect.";
|
|
1428
1469
|
var DEFAULT_DISCONNECT_ERROR = "Couldn't disconnect. Please try again.";
|
|
1429
1470
|
var DEFAULT_LOAD_ERROR = "Couldn't load connections. Please try again.";
|
|
1430
1471
|
var DEFAULT_GRANTS_LOAD_ERROR = "Couldn't load sharing. Please try again.";
|
|
@@ -1433,6 +1474,8 @@ var DEFAULT_REVOKE_ERROR = "Couldn't revoke access. Please try again.";
|
|
|
1433
1474
|
var DEFAULT_ORG_DISABLED_REASON = "Org-wide connections aren't available to you.";
|
|
1434
1475
|
var DEFAULT_CREDENTIAL_ERROR = "Couldn't save that credential. Please try again.";
|
|
1435
1476
|
var DEFAULT_CREDENTIAL_TEST_ERROR = "Couldn't test that credential. Please try again.";
|
|
1477
|
+
var DEFAULT_RECONNECT_MESSAGE = "This connection needs to be reconnected to keep working.";
|
|
1478
|
+
var DISCONNECT_REVOKES_HINT = "Disconnecting revokes Reeve's access to this account.";
|
|
1436
1479
|
var UNVERIFIABLE_CREDENTIAL_NOTE = "We can't verify this automatically \u2014 saving it is safe, but nothing has checked it yet.";
|
|
1437
1480
|
var SKELETON_COUNT = 3;
|
|
1438
1481
|
var UNGROUNDED_PLACEHOLDER = /\{\{[^}]*\}\}/;
|
|
@@ -1466,6 +1509,9 @@ function ownerLabel(entry) {
|
|
|
1466
1509
|
function isSharedWithViewer(entry) {
|
|
1467
1510
|
return entry.connection.status === "connected" && Boolean(entry.connection.shared_by) && !entry.connection.owned_by_viewer;
|
|
1468
1511
|
}
|
|
1512
|
+
function isUnhealthy(entry) {
|
|
1513
|
+
return entry.connection.status === "connected" && entry.connection.health?.status === "unhealthy";
|
|
1514
|
+
}
|
|
1469
1515
|
function ConnectorPicker({
|
|
1470
1516
|
client,
|
|
1471
1517
|
purpose,
|
|
@@ -1477,6 +1523,9 @@ function ConnectorPicker({
|
|
|
1477
1523
|
const [entries, setEntries] = (0, import_react9.useState)(null);
|
|
1478
1524
|
const [loadError, setLoadError] = (0, import_react9.useState)(null);
|
|
1479
1525
|
const [uiState, setUiState] = (0, import_react9.useState)({});
|
|
1526
|
+
const reconnectingRef = (0, import_react9.useRef)(/* @__PURE__ */ new Set());
|
|
1527
|
+
const reconnectChecksRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
1528
|
+
const refreshInFlightRef = (0, import_react9.useRef)(false);
|
|
1480
1529
|
const grantsSupported = typeof client.listGrants === "function" && typeof client.grant === "function" && typeof client.revokeGrant === "function";
|
|
1481
1530
|
const credentialsSupported = typeof client.submitCredentials === "function";
|
|
1482
1531
|
const credentialTestSupported = typeof client.testCredentials === "function";
|
|
@@ -1505,20 +1554,45 @@ function ConnectorPicker({
|
|
|
1505
1554
|
void load();
|
|
1506
1555
|
}, [gated, load, purpose]);
|
|
1507
1556
|
const refreshAfterReturn = (0, import_react9.useCallback)(async () => {
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1557
|
+
if (refreshInFlightRef.current) return;
|
|
1558
|
+
refreshInFlightRef.current = true;
|
|
1559
|
+
try {
|
|
1560
|
+
const list = await load();
|
|
1561
|
+
if (!list) return;
|
|
1562
|
+
const stillUnhealthyChecks = /* @__PURE__ */ new Map();
|
|
1513
1563
|
for (const entry of list) {
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1564
|
+
const stillUnhealthy = reconnectingRef.current.has(entry.slug) && entry.connection.health?.status === "unhealthy";
|
|
1565
|
+
if (!stillUnhealthy) continue;
|
|
1566
|
+
const checks = (reconnectChecksRef.current.get(entry.slug) ?? 0) + 1;
|
|
1567
|
+
reconnectChecksRef.current.set(entry.slug, checks);
|
|
1568
|
+
stillUnhealthyChecks.set(entry.slug, checks);
|
|
1519
1569
|
}
|
|
1520
|
-
|
|
1521
|
-
|
|
1570
|
+
setUiState((prev) => {
|
|
1571
|
+
let changed = false;
|
|
1572
|
+
const next = { ...prev };
|
|
1573
|
+
for (const entry of list) {
|
|
1574
|
+
if (next[entry.slug]?.kind !== "connecting" || entry.connection.status !== "connected") {
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const checks = stillUnhealthyChecks.get(entry.slug);
|
|
1578
|
+
if (checks !== void 0 && checks >= MAX_RECONNECT_REFOCUS_CHECKS) {
|
|
1579
|
+
changed = true;
|
|
1580
|
+
reconnectingRef.current.delete(entry.slug);
|
|
1581
|
+
reconnectChecksRef.current.delete(entry.slug);
|
|
1582
|
+
next[entry.slug] = { kind: "error", message: RECONNECT_UNCONFIRMED_ERROR };
|
|
1583
|
+
} else if (checks === void 0) {
|
|
1584
|
+
changed = true;
|
|
1585
|
+
delete next[entry.slug];
|
|
1586
|
+
reconnectingRef.current.delete(entry.slug);
|
|
1587
|
+
reconnectChecksRef.current.delete(entry.slug);
|
|
1588
|
+
onConnectedRef.current?.(entry);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return changed ? next : prev;
|
|
1592
|
+
});
|
|
1593
|
+
} finally {
|
|
1594
|
+
refreshInFlightRef.current = false;
|
|
1595
|
+
}
|
|
1522
1596
|
}, [load]);
|
|
1523
1597
|
(0, import_react9.useEffect)(() => {
|
|
1524
1598
|
if (gated) return;
|
|
@@ -1539,6 +1613,12 @@ function ConnectorPicker({
|
|
|
1539
1613
|
}, [gated, refreshAfterReturn]);
|
|
1540
1614
|
const handleConnect = (0, import_react9.useCallback)(
|
|
1541
1615
|
async (entry, kind) => {
|
|
1616
|
+
if (isUnhealthy(entry)) {
|
|
1617
|
+
reconnectingRef.current.add(entry.slug);
|
|
1618
|
+
} else {
|
|
1619
|
+
reconnectingRef.current.delete(entry.slug);
|
|
1620
|
+
}
|
|
1621
|
+
reconnectChecksRef.current.delete(entry.slug);
|
|
1542
1622
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "connecting" } }));
|
|
1543
1623
|
try {
|
|
1544
1624
|
const result = await clientRef.current.connect(entry, { kind });
|
|
@@ -1548,6 +1628,8 @@ function ConnectorPicker({
|
|
|
1548
1628
|
}
|
|
1549
1629
|
const list = await load();
|
|
1550
1630
|
const updated = list?.find((e) => e.slug === entry.slug) ?? null;
|
|
1631
|
+
reconnectingRef.current.delete(entry.slug);
|
|
1632
|
+
reconnectChecksRef.current.delete(entry.slug);
|
|
1551
1633
|
setUiState((prev) => {
|
|
1552
1634
|
const next = { ...prev };
|
|
1553
1635
|
delete next[entry.slug];
|
|
@@ -1557,6 +1639,8 @@ function ConnectorPicker({
|
|
|
1557
1639
|
onConnectedRef.current?.(updated);
|
|
1558
1640
|
}
|
|
1559
1641
|
} catch (err) {
|
|
1642
|
+
reconnectingRef.current.delete(entry.slug);
|
|
1643
|
+
reconnectChecksRef.current.delete(entry.slug);
|
|
1560
1644
|
const message = errorMessageFrom(err, DEFAULT_CONNECT_ERROR);
|
|
1561
1645
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "error", message } }));
|
|
1562
1646
|
}
|
|
@@ -1632,35 +1716,35 @@ function ConnectorPicker({
|
|
|
1632
1716
|
);
|
|
1633
1717
|
const ownEntries = entries?.filter((entry) => !isSharedWithViewer(entry)) ?? null;
|
|
1634
1718
|
const sharedEntries = entries?.filter(isSharedWithViewer) ?? [];
|
|
1635
|
-
return /* @__PURE__ */ (0,
|
|
1636
|
-
/* @__PURE__ */ (0,
|
|
1637
|
-
entries === null && !loadError && Array.from({ length: SKELETON_COUNT }).map((_, i) => /* @__PURE__ */ (0,
|
|
1719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-testid": "connector-picker", "data-layout": layout, className: "flex flex-col gap-4", children: [
|
|
1720
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: containerClassName, children: [
|
|
1721
|
+
entries === null && !loadError && Array.from({ length: SKELETON_COUNT }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1638
1722
|
"div",
|
|
1639
1723
|
{
|
|
1640
1724
|
"data-testid": "connector-picker-skeleton-item",
|
|
1641
1725
|
"aria-hidden": "true",
|
|
1642
1726
|
className: "flex items-center gap-3 rounded-lg border border-border p-3",
|
|
1643
1727
|
children: [
|
|
1644
|
-
/* @__PURE__ */ (0,
|
|
1645
|
-
/* @__PURE__ */ (0,
|
|
1728
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "h-8 w-8 shrink-0 animate-pulse rounded bg-foreground/10" }),
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "h-3 flex-1 animate-pulse rounded bg-foreground/10" })
|
|
1646
1730
|
]
|
|
1647
1731
|
},
|
|
1648
1732
|
i
|
|
1649
1733
|
)),
|
|
1650
|
-
loadError && /* @__PURE__ */ (0,
|
|
1734
|
+
loadError && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1651
1735
|
"div",
|
|
1652
1736
|
{
|
|
1653
1737
|
role: "alert",
|
|
1654
1738
|
"data-testid": "connector-picker-load-error",
|
|
1655
1739
|
className: "flex items-center justify-between gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive",
|
|
1656
1740
|
children: [
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1741
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: loadError }),
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", onClick: () => void load(), className: "shrink-0 underline", children: "Retry" })
|
|
1659
1743
|
]
|
|
1660
1744
|
}
|
|
1661
1745
|
),
|
|
1662
|
-
entries !== null && entries.length === 0 && !loadError && /* @__PURE__ */ (0,
|
|
1663
|
-
ownEntries?.map((entry) => /* @__PURE__ */ (0,
|
|
1746
|
+
entries !== null && entries.length === 0 && !loadError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { "data-testid": "connector-picker-empty", className: "text-sm text-muted-foreground", children: "No connections available." }),
|
|
1747
|
+
ownEntries?.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1664
1748
|
ConnectorTile,
|
|
1665
1749
|
{
|
|
1666
1750
|
entry,
|
|
@@ -1680,9 +1764,9 @@ function ConnectorPicker({
|
|
|
1680
1764
|
entry.slug
|
|
1681
1765
|
))
|
|
1682
1766
|
] }),
|
|
1683
|
-
sharedEntries.length > 0 && /* @__PURE__ */ (0,
|
|
1684
|
-
/* @__PURE__ */ (0,
|
|
1685
|
-
/* @__PURE__ */ (0,
|
|
1767
|
+
sharedEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { "data-testid": "connector-picker-shared-with-me", className: "flex flex-col gap-2", children: [
|
|
1768
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Shared with me" }),
|
|
1769
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: containerClassName, children: sharedEntries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1686
1770
|
ConnectorTile,
|
|
1687
1771
|
{
|
|
1688
1772
|
entry,
|
|
@@ -1725,6 +1809,7 @@ function ConnectorTile({
|
|
|
1725
1809
|
const isConnecting = ui?.kind === "connecting";
|
|
1726
1810
|
const isDisconnecting = ui?.kind === "disconnecting";
|
|
1727
1811
|
const errorMessage = ui?.kind === "error" ? ui.message : null;
|
|
1812
|
+
const unhealthy = isUnhealthy(entry);
|
|
1728
1813
|
const [kind, setKind] = (0, import_react9.useState)("personal");
|
|
1729
1814
|
const [sharingOpen, setSharingOpen] = (0, import_react9.useState)(false);
|
|
1730
1815
|
const [setupOpen, setSetupOpen] = (0, import_react9.useState)(false);
|
|
@@ -1737,7 +1822,7 @@ function ConnectorTile({
|
|
|
1737
1822
|
const attribution = ownerLabel(entry);
|
|
1738
1823
|
const canDisconnect = isConnected && !shared;
|
|
1739
1824
|
const canManageSharing = isConnected && entry.connection.owned_by_viewer === true && grantsSupported;
|
|
1740
|
-
return /* @__PURE__ */ (0,
|
|
1825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1741
1826
|
"div",
|
|
1742
1827
|
{
|
|
1743
1828
|
"data-testid": `connector-tile-${entry.slug}`,
|
|
@@ -1745,12 +1830,12 @@ function ConnectorTile({
|
|
|
1745
1830
|
"data-deprecated": entry.deprecated || void 0,
|
|
1746
1831
|
className: cn("flex flex-col p-3", layout === "tiles" && "rounded-lg border border-border"),
|
|
1747
1832
|
children: [
|
|
1748
|
-
/* @__PURE__ */ (0,
|
|
1749
|
-
/* @__PURE__ */ (0,
|
|
1750
|
-
/* @__PURE__ */ (0,
|
|
1751
|
-
/* @__PURE__ */ (0,
|
|
1752
|
-
/* @__PURE__ */ (0,
|
|
1753
|
-
entry.deprecated && /* @__PURE__ */ (0,
|
|
1833
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BrandGlyph, { brand: { name: entry.name, logo: entry.logo }, size: "lg" }),
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
1836
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1837
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "truncate text-sm font-medium", children: entry.name }),
|
|
1838
|
+
entry.deprecated && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1754
1839
|
"span",
|
|
1755
1840
|
{
|
|
1756
1841
|
"data-testid": `connector-deprecated-${entry.slug}`,
|
|
@@ -1759,14 +1844,14 @@ function ConnectorTile({
|
|
|
1759
1844
|
}
|
|
1760
1845
|
)
|
|
1761
1846
|
] }),
|
|
1762
|
-
/* @__PURE__ */ (0,
|
|
1763
|
-
/* @__PURE__ */ (0,
|
|
1764
|
-
entry.category && /* @__PURE__ */ (0,
|
|
1765
|
-
/* @__PURE__ */ (0,
|
|
1766
|
-
/* @__PURE__ */ (0,
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-testid": `connector-capability-${entry.slug}`, children: capabilityLabel(entry.capability) }),
|
|
1849
|
+
entry.category && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1850
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
1851
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate", children: entry.category })
|
|
1767
1852
|
] })
|
|
1768
1853
|
] }),
|
|
1769
|
-
isConnected && /* @__PURE__ */ (0,
|
|
1854
|
+
isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1770
1855
|
"p",
|
|
1771
1856
|
{
|
|
1772
1857
|
"data-testid": `connector-connected-since-${entry.slug}`,
|
|
@@ -1774,7 +1859,35 @@ function ConnectorTile({
|
|
|
1774
1859
|
children: entry.connection.since ? `Connected since ${formatSince(entry.connection.since)}` : "Connected"
|
|
1775
1860
|
}
|
|
1776
1861
|
),
|
|
1777
|
-
|
|
1862
|
+
isConnected && !shared && entry.connection.account_label && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1863
|
+
"p",
|
|
1864
|
+
{
|
|
1865
|
+
"data-testid": `connector-account-${entry.slug}`,
|
|
1866
|
+
className: "text-xs text-muted-foreground",
|
|
1867
|
+
children: [
|
|
1868
|
+
"Connected as ",
|
|
1869
|
+
entry.connection.account_label
|
|
1870
|
+
]
|
|
1871
|
+
}
|
|
1872
|
+
),
|
|
1873
|
+
isConnected && entry.access_summary && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1874
|
+
"p",
|
|
1875
|
+
{
|
|
1876
|
+
"data-testid": `connector-access-summary-${entry.slug}`,
|
|
1877
|
+
className: "text-xs text-muted-foreground",
|
|
1878
|
+
children: entry.access_summary
|
|
1879
|
+
}
|
|
1880
|
+
),
|
|
1881
|
+
unhealthy && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1882
|
+
"p",
|
|
1883
|
+
{
|
|
1884
|
+
role: "alert",
|
|
1885
|
+
"data-testid": `connector-unhealthy-${entry.slug}`,
|
|
1886
|
+
className: "text-xs font-medium text-destructive",
|
|
1887
|
+
children: DEFAULT_RECONNECT_MESSAGE
|
|
1888
|
+
}
|
|
1889
|
+
),
|
|
1890
|
+
attribution && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1778
1891
|
"p",
|
|
1779
1892
|
{
|
|
1780
1893
|
"data-testid": `connector-owner-${entry.slug}`,
|
|
@@ -1782,7 +1895,7 @@ function ConnectorTile({
|
|
|
1782
1895
|
children: attribution
|
|
1783
1896
|
}
|
|
1784
1897
|
),
|
|
1785
|
-
!isConnected && /* @__PURE__ */ (0,
|
|
1898
|
+
!isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1786
1899
|
"div",
|
|
1787
1900
|
{
|
|
1788
1901
|
"data-testid": `connector-kind-toggle-${entry.slug}`,
|
|
@@ -1790,7 +1903,7 @@ function ConnectorTile({
|
|
|
1790
1903
|
"aria-label": "Connect as",
|
|
1791
1904
|
className: "mt-1 flex items-center gap-1",
|
|
1792
1905
|
children: [
|
|
1793
|
-
/* @__PURE__ */ (0,
|
|
1906
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1794
1907
|
"button",
|
|
1795
1908
|
{
|
|
1796
1909
|
type: "button",
|
|
@@ -1806,7 +1919,7 @@ function ConnectorTile({
|
|
|
1806
1919
|
children: "Personal"
|
|
1807
1920
|
}
|
|
1808
1921
|
),
|
|
1809
|
-
/* @__PURE__ */ (0,
|
|
1922
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1810
1923
|
"button",
|
|
1811
1924
|
{
|
|
1812
1925
|
type: "button",
|
|
@@ -1822,7 +1935,7 @@ function ConnectorTile({
|
|
|
1822
1935
|
),
|
|
1823
1936
|
children: [
|
|
1824
1937
|
"Org",
|
|
1825
|
-
!orgPermitted && /* @__PURE__ */ (0,
|
|
1938
|
+
!orgPermitted && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "sr-only", children: [
|
|
1826
1939
|
" (",
|
|
1827
1940
|
orgDisabledReason,
|
|
1828
1941
|
")"
|
|
@@ -1833,21 +1946,50 @@ function ConnectorTile({
|
|
|
1833
1946
|
]
|
|
1834
1947
|
}
|
|
1835
1948
|
),
|
|
1836
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
1949
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { role: "alert", "data-testid": `connector-error-${entry.slug}`, className: "text-xs text-destructive", children: errorMessage })
|
|
1837
1950
|
] }),
|
|
1838
|
-
isConnected ? /* @__PURE__ */ (0,
|
|
1839
|
-
|
|
1951
|
+
isConnected ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
1952
|
+
unhealthy && !shared && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1953
|
+
"button",
|
|
1954
|
+
{
|
|
1955
|
+
type: "button",
|
|
1956
|
+
"data-testid": `connector-reconnect-${entry.slug}`,
|
|
1957
|
+
onClick: () => onConnect(entry, entry.connection.kind ?? "personal"),
|
|
1958
|
+
disabled: isConnecting || isDisconnecting,
|
|
1959
|
+
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1960
|
+
children: isConnecting ? "Reconnecting\u2026" : "Reconnect"
|
|
1961
|
+
}
|
|
1962
|
+
),
|
|
1963
|
+
canDisconnect && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1840
1964
|
"button",
|
|
1841
1965
|
{
|
|
1842
1966
|
type: "button",
|
|
1843
1967
|
"data-testid": `connector-disconnect-${entry.slug}`,
|
|
1968
|
+
title: DISCONNECT_REVOKES_HINT,
|
|
1844
1969
|
onClick: () => onDisconnect(entry),
|
|
1845
|
-
disabled: isDisconnecting,
|
|
1970
|
+
disabled: isDisconnecting || isConnecting,
|
|
1846
1971
|
className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-medium text-destructive hover:bg-destructive/10 disabled:opacity-50",
|
|
1847
1972
|
children: isDisconnecting ? "Disconnecting\u2026" : "Disconnect"
|
|
1848
1973
|
}
|
|
1849
1974
|
),
|
|
1850
|
-
|
|
1975
|
+
canDisconnect && // Outcome-eval finding (DEV-7873): with no width cap, this
|
|
1976
|
+
// paragraph's one long sentence forced the WHOLE shrink-0
|
|
1977
|
+
// button column to grow to its natural (unwrapped) width,
|
|
1978
|
+
// squeezing the sibling `min-w-0 flex-1` text column down to
|
|
1979
|
+
// one word per line at any realistic tile width. RTL's jsdom
|
|
1980
|
+
// tests never caught it — jsdom doesn't lay out real flexbox
|
|
1981
|
+
// sizing, so every textContent assertion still passed. A
|
|
1982
|
+
// narrow max-width forces the hint to wrap within the same
|
|
1983
|
+
// footprint as the button above it instead.
|
|
1984
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1985
|
+
"p",
|
|
1986
|
+
{
|
|
1987
|
+
"data-testid": `connector-disconnect-hint-${entry.slug}`,
|
|
1988
|
+
className: "max-w-28 text-right text-[11px] text-muted-foreground",
|
|
1989
|
+
children: DISCONNECT_REVOKES_HINT
|
|
1990
|
+
}
|
|
1991
|
+
),
|
|
1992
|
+
canManageSharing && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1851
1993
|
"button",
|
|
1852
1994
|
{
|
|
1853
1995
|
type: "button",
|
|
@@ -1858,8 +2000,8 @@ function ConnectorTile({
|
|
|
1858
2000
|
children: sharingOpen ? "Hide sharing" : "Manage sharing"
|
|
1859
2001
|
}
|
|
1860
2002
|
)
|
|
1861
|
-
] }) : /* @__PURE__ */ (0,
|
|
1862
|
-
/* @__PURE__ */ (0,
|
|
2003
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-1", children: [
|
|
2004
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1863
2005
|
"button",
|
|
1864
2006
|
{
|
|
1865
2007
|
type: "button",
|
|
@@ -1870,7 +2012,7 @@ function ConnectorTile({
|
|
|
1870
2012
|
children: isConnecting ? "Connecting\u2026" : "Connect"
|
|
1871
2013
|
}
|
|
1872
2014
|
),
|
|
1873
|
-
canSetUp && /* @__PURE__ */ (0,
|
|
2015
|
+
canSetUp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1874
2016
|
"button",
|
|
1875
2017
|
{
|
|
1876
2018
|
type: "button",
|
|
@@ -1884,15 +2026,15 @@ function ConnectorTile({
|
|
|
1884
2026
|
)
|
|
1885
2027
|
] })
|
|
1886
2028
|
] }),
|
|
1887
|
-
canSetUp && setupOpen && /* @__PURE__ */ (0,
|
|
2029
|
+
canSetUp && setupOpen && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1888
2030
|
"div",
|
|
1889
2031
|
{
|
|
1890
2032
|
id: `connector-setup-panel-${entry.slug}`,
|
|
1891
2033
|
"data-testid": `connector-setup-panel-${entry.slug}`,
|
|
1892
2034
|
className: "mt-2 flex flex-col gap-3 rounded-md border border-border bg-foreground/5 p-2",
|
|
1893
2035
|
children: [
|
|
1894
|
-
guide && /* @__PURE__ */ (0,
|
|
1895
|
-
pasteSupported && /* @__PURE__ */ (0,
|
|
2036
|
+
guide && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SetupGuidePanel, { entry, guide, showVerify: !pasteSupported }),
|
|
2037
|
+
pasteSupported && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1896
2038
|
CredentialForm,
|
|
1897
2039
|
{
|
|
1898
2040
|
entry,
|
|
@@ -1907,7 +2049,7 @@ function ConnectorTile({
|
|
|
1907
2049
|
]
|
|
1908
2050
|
}
|
|
1909
2051
|
),
|
|
1910
|
-
canManageSharing && sharingOpen && /* @__PURE__ */ (0,
|
|
2052
|
+
canManageSharing && sharingOpen && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1911
2053
|
ManageSharing,
|
|
1912
2054
|
{
|
|
1913
2055
|
entry,
|
|
@@ -1957,8 +2099,8 @@ function CopyableValue({ value, testId }) {
|
|
|
1957
2099
|
setCopied(false);
|
|
1958
2100
|
}
|
|
1959
2101
|
}, [value]);
|
|
1960
|
-
return /* @__PURE__ */ (0,
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
2102
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "mt-1 flex items-center gap-1.5", children: [
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1962
2104
|
"code",
|
|
1963
2105
|
{
|
|
1964
2106
|
"data-testid": `${testId}-value`,
|
|
@@ -1966,7 +2108,7 @@ function CopyableValue({ value, testId }) {
|
|
|
1966
2108
|
children: value
|
|
1967
2109
|
}
|
|
1968
2110
|
),
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
2111
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1970
2112
|
"button",
|
|
1971
2113
|
{
|
|
1972
2114
|
type: "button",
|
|
@@ -1992,8 +2134,8 @@ function SetupGuidePanel({
|
|
|
1992
2134
|
ungrounded
|
|
1993
2135
|
);
|
|
1994
2136
|
}, [entry.slug, guide, leaked]);
|
|
1995
|
-
return /* @__PURE__ */ (0,
|
|
1996
|
-
leaked && isDevEnvironment() && /* @__PURE__ */ (0,
|
|
2137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-testid": `connector-guide-${entry.slug}`, className: "flex flex-col gap-2", children: [
|
|
2138
|
+
leaked && isDevEnvironment() && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1997
2139
|
"p",
|
|
1998
2140
|
{
|
|
1999
2141
|
role: "alert",
|
|
@@ -2005,25 +2147,25 @@ function SetupGuidePanel({
|
|
|
2005
2147
|
]
|
|
2006
2148
|
}
|
|
2007
2149
|
),
|
|
2008
|
-
prerequisites.length > 0 && /* @__PURE__ */ (0,
|
|
2009
|
-
/* @__PURE__ */ (0,
|
|
2010
|
-
/* @__PURE__ */ (0,
|
|
2150
|
+
prerequisites.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "text-xs font-medium", children: "Before you start" }),
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2011
2153
|
"ul",
|
|
2012
2154
|
{
|
|
2013
2155
|
"data-testid": `connector-guide-prerequisites-${entry.slug}`,
|
|
2014
2156
|
className: "mt-1 list-disc pl-4 text-xs text-muted-foreground",
|
|
2015
|
-
children: prerequisites.map((item) => /* @__PURE__ */ (0,
|
|
2157
|
+
children: prerequisites.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("li", { children: item }, item))
|
|
2016
2158
|
}
|
|
2017
2159
|
)
|
|
2018
2160
|
] }),
|
|
2019
|
-
steps.length > 0 && /* @__PURE__ */ (0,
|
|
2161
|
+
steps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2020
2162
|
"ol",
|
|
2021
2163
|
{
|
|
2022
2164
|
"data-testid": `connector-guide-steps-${entry.slug}`,
|
|
2023
2165
|
className: "list-decimal pl-4 text-xs",
|
|
2024
|
-
children: steps.map((step, index) => /* @__PURE__ */ (0,
|
|
2025
|
-
/* @__PURE__ */ (0,
|
|
2026
|
-
step.copyable && /* @__PURE__ */ (0,
|
|
2166
|
+
children: steps.map((step, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { className: "mt-1 first:mt-0", children: [
|
|
2167
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: step.text }),
|
|
2168
|
+
step.copyable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2027
2169
|
CopyableValue,
|
|
2028
2170
|
{
|
|
2029
2171
|
value: step.copyable,
|
|
@@ -2033,7 +2175,7 @@ function SetupGuidePanel({
|
|
|
2033
2175
|
] }, step.text))
|
|
2034
2176
|
}
|
|
2035
2177
|
),
|
|
2036
|
-
scopeNote && /* @__PURE__ */ (0,
|
|
2178
|
+
scopeNote && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2037
2179
|
"p",
|
|
2038
2180
|
{
|
|
2039
2181
|
"data-testid": `connector-guide-scope-note-${entry.slug}`,
|
|
@@ -2041,7 +2183,7 @@ function SetupGuidePanel({
|
|
|
2041
2183
|
children: scopeNote
|
|
2042
2184
|
}
|
|
2043
2185
|
),
|
|
2044
|
-
showVerify && verify && /* @__PURE__ */ (0,
|
|
2186
|
+
showVerify && verify && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2045
2187
|
"p",
|
|
2046
2188
|
{
|
|
2047
2189
|
"data-testid": `connector-guide-verify-${entry.slug}`,
|
|
@@ -2105,7 +2247,7 @@ function CredentialForm({
|
|
|
2105
2247
|
setBusy(false);
|
|
2106
2248
|
}
|
|
2107
2249
|
}, [kind, onSubmitCredentials, values]);
|
|
2108
|
-
return /* @__PURE__ */ (0,
|
|
2250
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2109
2251
|
"form",
|
|
2110
2252
|
{
|
|
2111
2253
|
"data-testid": `connector-credential-form-${entry.slug}`,
|
|
@@ -2119,12 +2261,12 @@ function CredentialForm({
|
|
|
2119
2261
|
fields.map((field) => {
|
|
2120
2262
|
const inputId = `connector-credential-${entry.slug}-${field.key}`;
|
|
2121
2263
|
const fieldError = fieldErrors?.[field.key] ?? null;
|
|
2122
|
-
return /* @__PURE__ */ (0,
|
|
2123
|
-
/* @__PURE__ */ (0,
|
|
2264
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
2265
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { htmlFor: inputId, className: "text-xs font-medium", children: [
|
|
2124
2266
|
field.label,
|
|
2125
|
-
field.required !== false && /* @__PURE__ */ (0,
|
|
2267
|
+
field.required !== false && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", className: "ml-0.5 text-destructive", children: "*" })
|
|
2126
2268
|
] }),
|
|
2127
|
-
/* @__PURE__ */ (0,
|
|
2269
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2128
2270
|
"input",
|
|
2129
2271
|
{
|
|
2130
2272
|
id: inputId,
|
|
@@ -2144,7 +2286,7 @@ function CredentialForm({
|
|
|
2144
2286
|
)
|
|
2145
2287
|
}
|
|
2146
2288
|
),
|
|
2147
|
-
fieldError && /* @__PURE__ */ (0,
|
|
2289
|
+
fieldError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2148
2290
|
"p",
|
|
2149
2291
|
{
|
|
2150
2292
|
id: `${inputId}-error`,
|
|
@@ -2155,7 +2297,7 @@ function CredentialForm({
|
|
|
2155
2297
|
)
|
|
2156
2298
|
] }, field.key);
|
|
2157
2299
|
}),
|
|
2158
|
-
verify && /* @__PURE__ */ (0,
|
|
2300
|
+
verify && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2159
2301
|
"p",
|
|
2160
2302
|
{
|
|
2161
2303
|
"data-testid": `connector-guide-verify-${entry.slug}`,
|
|
@@ -2163,8 +2305,8 @@ function CredentialForm({
|
|
|
2163
2305
|
children: verify
|
|
2164
2306
|
}
|
|
2165
2307
|
),
|
|
2166
|
-
result && /* @__PURE__ */ (0,
|
|
2167
|
-
error && /* @__PURE__ */ (0,
|
|
2308
|
+
result && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CredentialTestResult, { entry, result }),
|
|
2309
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2168
2310
|
"p",
|
|
2169
2311
|
{
|
|
2170
2312
|
role: "alert",
|
|
@@ -2173,8 +2315,8 @@ function CredentialForm({
|
|
|
2173
2315
|
children: error
|
|
2174
2316
|
}
|
|
2175
2317
|
),
|
|
2176
|
-
/* @__PURE__ */ (0,
|
|
2177
|
-
testSupported && /* @__PURE__ */ (0,
|
|
2318
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-end gap-1.5", children: [
|
|
2319
|
+
testSupported && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2178
2320
|
"button",
|
|
2179
2321
|
{
|
|
2180
2322
|
type: "button",
|
|
@@ -2185,7 +2327,7 @@ function CredentialForm({
|
|
|
2185
2327
|
children: testing ? "Testing\u2026" : "Test connection"
|
|
2186
2328
|
}
|
|
2187
2329
|
),
|
|
2188
|
-
/* @__PURE__ */ (0,
|
|
2330
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2189
2331
|
"button",
|
|
2190
2332
|
{
|
|
2191
2333
|
type: "submit",
|
|
@@ -2206,15 +2348,15 @@ function CredentialTestResult({
|
|
|
2206
2348
|
result
|
|
2207
2349
|
}) {
|
|
2208
2350
|
if (result.valid === true) {
|
|
2209
|
-
return /* @__PURE__ */ (0,
|
|
2351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2210
2352
|
"div",
|
|
2211
2353
|
{
|
|
2212
2354
|
role: "status",
|
|
2213
2355
|
"data-testid": `connector-credential-test-pass-${entry.slug}`,
|
|
2214
2356
|
className: "rounded-md border border-primary/30 bg-primary/5 px-2 py-1 text-xs",
|
|
2215
2357
|
children: [
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2217
|
-
result.permissions_note && /* @__PURE__ */ (0,
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: result.account_name ? `Verified \u2014 connected as ${result.account_name}.` : "Verified \u2014 these credentials work." }),
|
|
2359
|
+
result.permissions_note && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2218
2360
|
"p",
|
|
2219
2361
|
{
|
|
2220
2362
|
"data-testid": `connector-credential-permissions-${entry.slug}`,
|
|
@@ -2227,7 +2369,7 @@ function CredentialTestResult({
|
|
|
2227
2369
|
);
|
|
2228
2370
|
}
|
|
2229
2371
|
if (result.valid === false) {
|
|
2230
|
-
return /* @__PURE__ */ (0,
|
|
2372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2231
2373
|
"p",
|
|
2232
2374
|
{
|
|
2233
2375
|
role: "alert",
|
|
@@ -2237,7 +2379,7 @@ function CredentialTestResult({
|
|
|
2237
2379
|
}
|
|
2238
2380
|
);
|
|
2239
2381
|
}
|
|
2240
|
-
return /* @__PURE__ */ (0,
|
|
2382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2241
2383
|
"p",
|
|
2242
2384
|
{
|
|
2243
2385
|
role: "status",
|
|
@@ -2300,13 +2442,13 @@ function ManageSharing({
|
|
|
2300
2442
|
},
|
|
2301
2443
|
[load, revokeGrant]
|
|
2302
2444
|
);
|
|
2303
|
-
return /* @__PURE__ */ (0,
|
|
2445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2304
2446
|
"div",
|
|
2305
2447
|
{
|
|
2306
2448
|
"data-testid": `connector-sharing-panel-${entry.slug}`,
|
|
2307
2449
|
className: "mt-2 flex flex-col gap-2 rounded-md border border-border bg-foreground/5 p-2",
|
|
2308
2450
|
children: [
|
|
2309
|
-
grants === null && !error && /* @__PURE__ */ (0,
|
|
2451
|
+
grants === null && !error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2310
2452
|
"p",
|
|
2311
2453
|
{
|
|
2312
2454
|
"data-testid": `connector-grants-loading-${entry.slug}`,
|
|
@@ -2314,7 +2456,7 @@ function ManageSharing({
|
|
|
2314
2456
|
children: "Loading sharing\u2026"
|
|
2315
2457
|
}
|
|
2316
2458
|
),
|
|
2317
|
-
error && /* @__PURE__ */ (0,
|
|
2459
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2318
2460
|
"p",
|
|
2319
2461
|
{
|
|
2320
2462
|
role: "alert",
|
|
@@ -2323,7 +2465,7 @@ function ManageSharing({
|
|
|
2323
2465
|
children: error
|
|
2324
2466
|
}
|
|
2325
2467
|
),
|
|
2326
|
-
grants !== null && grants.length === 0 && /* @__PURE__ */ (0,
|
|
2468
|
+
grants !== null && grants.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2327
2469
|
"p",
|
|
2328
2470
|
{
|
|
2329
2471
|
"data-testid": `connector-grants-empty-${entry.slug}`,
|
|
@@ -2331,21 +2473,21 @@ function ManageSharing({
|
|
|
2331
2473
|
children: "Not shared with anyone yet."
|
|
2332
2474
|
}
|
|
2333
2475
|
),
|
|
2334
|
-
grants?.map((grant) => /* @__PURE__ */ (0,
|
|
2476
|
+
grants?.map((grant) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2335
2477
|
"div",
|
|
2336
2478
|
{
|
|
2337
2479
|
"data-testid": `connector-grant-${entry.slug}-${grant.id}`,
|
|
2338
2480
|
className: "flex items-center justify-between gap-2 text-xs",
|
|
2339
2481
|
children: [
|
|
2340
|
-
/* @__PURE__ */ (0,
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "truncate", children: [
|
|
2341
2483
|
grant.grantee_name || grant.grantee_id,
|
|
2342
|
-
/* @__PURE__ */ (0,
|
|
2484
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
2343
2485
|
" ",
|
|
2344
2486
|
"\xB7 ",
|
|
2345
2487
|
grant.grantee_type === "role" ? "Role" : "User"
|
|
2346
2488
|
] })
|
|
2347
2489
|
] }),
|
|
2348
|
-
/* @__PURE__ */ (0,
|
|
2490
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2349
2491
|
"button",
|
|
2350
2492
|
{
|
|
2351
2493
|
type: "button",
|
|
@@ -2360,8 +2502,8 @@ function ManageSharing({
|
|
|
2360
2502
|
},
|
|
2361
2503
|
grant.id
|
|
2362
2504
|
)),
|
|
2363
|
-
/* @__PURE__ */ (0,
|
|
2364
|
-
/* @__PURE__ */ (0,
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2365
2507
|
"select",
|
|
2366
2508
|
{
|
|
2367
2509
|
"data-testid": `connector-grant-type-${entry.slug}`,
|
|
@@ -2374,12 +2516,12 @@ function ManageSharing({
|
|
|
2374
2516
|
disabled: busy,
|
|
2375
2517
|
className: "rounded-md border border-border bg-transparent px-1.5 py-1 text-xs disabled:opacity-50",
|
|
2376
2518
|
children: [
|
|
2377
|
-
/* @__PURE__ */ (0,
|
|
2378
|
-
/* @__PURE__ */ (0,
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "user", children: "User" }),
|
|
2520
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "role", children: "Role" })
|
|
2379
2521
|
]
|
|
2380
2522
|
}
|
|
2381
2523
|
),
|
|
2382
|
-
granteeType === "user" ? /* @__PURE__ */ (0,
|
|
2524
|
+
granteeType === "user" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2383
2525
|
"input",
|
|
2384
2526
|
{
|
|
2385
2527
|
"data-testid": `connector-grant-grantee-${entry.slug}`,
|
|
@@ -2390,7 +2532,7 @@ function ManageSharing({
|
|
|
2390
2532
|
disabled: busy,
|
|
2391
2533
|
className: "min-w-0 flex-1 rounded-md border border-border bg-transparent px-1.5 py-1 text-xs disabled:opacity-50"
|
|
2392
2534
|
}
|
|
2393
|
-
) : /* @__PURE__ */ (0,
|
|
2535
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2394
2536
|
"select",
|
|
2395
2537
|
{
|
|
2396
2538
|
"data-testid": `connector-grant-role-${entry.slug}`,
|
|
@@ -2400,12 +2542,12 @@ function ManageSharing({
|
|
|
2400
2542
|
disabled: busy,
|
|
2401
2543
|
className: "min-w-0 flex-1 rounded-md border border-border bg-transparent px-1.5 py-1 text-xs disabled:opacity-50",
|
|
2402
2544
|
children: [
|
|
2403
|
-
/* @__PURE__ */ (0,
|
|
2404
|
-
roleOptions.map((role) => /* @__PURE__ */ (0,
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Select a role\u2026" }),
|
|
2546
|
+
roleOptions.map((role) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: role.id, children: role.name }, role.id))
|
|
2405
2547
|
]
|
|
2406
2548
|
}
|
|
2407
2549
|
),
|
|
2408
|
-
/* @__PURE__ */ (0,
|
|
2550
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2409
2551
|
"button",
|
|
2410
2552
|
{
|
|
2411
2553
|
type: "button",
|
|
@@ -2429,6 +2571,7 @@ function ManageSharing({
|
|
|
2429
2571
|
ContextSwitcher,
|
|
2430
2572
|
Flyout,
|
|
2431
2573
|
GLYPH_CANVAS_FILL,
|
|
2574
|
+
InfoTip,
|
|
2432
2575
|
LOCKUP_GAP,
|
|
2433
2576
|
LOCKUP_ROW,
|
|
2434
2577
|
MARK_CAP_RATIO,
|