@meetreeve/ui 0.13.0 → 0.15.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/dist/index.d.mts +33 -3
- package/dist/index.d.ts +33 -3
- package/dist/index.js +78 -57
- package/dist/index.mjs +77 -57
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -632,7 +632,7 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
632
632
|
* errors, and a return-from-OAuth refresh). Every label is derived from the
|
|
633
633
|
* entry data the client returns — this file must never hardcode a specific
|
|
634
634
|
* provider's name (an explicit acceptance criterion); a host app supplies
|
|
635
|
-
* that entirely through `ConnectableEntry.name` / `.logo
|
|
635
|
+
* that entirely through `ConnectableEntry.name` / `.logo`.
|
|
636
636
|
*
|
|
637
637
|
* Transport-injection precedent: `linkComponent` (DEV-4429/DEV-4391) —
|
|
638
638
|
* inject the transport, keep behavior in the package. Here the "transport"
|
|
@@ -649,7 +649,17 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
649
649
|
* optional grant methods, so a pre-CD-5 client keeps working unchanged.
|
|
650
650
|
*/
|
|
651
651
|
type ConnectableTransport = "composio" | "native";
|
|
652
|
+
/**
|
|
653
|
+
* The widest access an entry offers. "write" is retired (DEV-13661: no
|
|
654
|
+
* provider ever only acted, so its old label was never true); it stays in the
|
|
655
|
+
* union so an older server payload still type-checks, and it renders as
|
|
656
|
+
* "Read + write".
|
|
657
|
+
*/
|
|
652
658
|
type ConnectableCapability = "read" | "write" | "readwrite";
|
|
659
|
+
/** What a connection lets Reeve do: ingest/query, or also act (DEV-13661). */
|
|
660
|
+
type ConnectableAccess = "read" | "readwrite";
|
|
661
|
+
/** The ONE access -> words mapping; nothing is labeled as acting alone (DEV-13661). */
|
|
662
|
+
declare function accessLabel(access: ConnectableCapability): string;
|
|
653
663
|
type ConnectionKind = "personal" | "org";
|
|
654
664
|
type ConnectorGranteeType = "user" | "role";
|
|
655
665
|
/** An RBAC role a grant can target, injected via the entry data (CD-2). */
|
|
@@ -664,7 +674,7 @@ interface ConnectorRoleOption {
|
|
|
664
674
|
*/
|
|
665
675
|
interface OrgConnectPolicy {
|
|
666
676
|
permitted: boolean;
|
|
667
|
-
/**
|
|
677
|
+
/** Why org connect isn't permitted (server-authored). */
|
|
668
678
|
reason?: string | null;
|
|
669
679
|
/** Role options offered by manage-sharing's "role" grantee type. */
|
|
670
680
|
role_options?: ConnectorRoleOption[];
|
|
@@ -806,7 +816,24 @@ interface ConnectableEntry {
|
|
|
806
816
|
* picker never assumes an email shape or synthesizes this itself.
|
|
807
817
|
*/
|
|
808
818
|
account_label?: string | null;
|
|
819
|
+
/**
|
|
820
|
+
* What this live connection lets Reeve do (DEV-13661). Absent on a
|
|
821
|
+
* pre-DEV-13661 payload, where the entry's `capability` stands in.
|
|
822
|
+
*/
|
|
823
|
+
access?: ConnectableAccess | null;
|
|
809
824
|
};
|
|
825
|
+
/**
|
|
826
|
+
* The accesses this entry may be connected as (DEV-13661), in
|
|
827
|
+
* ("read", "readwrite") order. More than one renders a Read / Read + write
|
|
828
|
+
* choice whose pick reaches `client.connect` as `opts.access`.
|
|
829
|
+
*/
|
|
830
|
+
access_options?: ConnectableAccess[] | null;
|
|
831
|
+
/**
|
|
832
|
+
* Every connection provider key that belongs to this entry's provider
|
|
833
|
+
* (its own slug first), so a host can group stored connections onto one
|
|
834
|
+
* row per provider (DEV-13661).
|
|
835
|
+
*/
|
|
836
|
+
provider_keys?: string[] | null;
|
|
810
837
|
/** true = tenant has a live connection but the entry left the allowlist. */
|
|
811
838
|
deprecated: boolean;
|
|
812
839
|
/** Org-connect permission + role options for this entry (CD-4). */
|
|
@@ -841,9 +868,12 @@ interface ConnectorPickerClient {
|
|
|
841
868
|
* composio -> open the returned connect_url; native may resolve with none.
|
|
842
869
|
* `opts.kind` is additive (DEV-5654): a pre-CD-5 client declaring only
|
|
843
870
|
* `connect(entry)` still satisfies this signature and simply ignores it.
|
|
871
|
+
* `opts.access` (DEV-13661) is the row's Read / Read + write pick, sent
|
|
872
|
+
* only when the entry offers a choice.
|
|
844
873
|
*/
|
|
845
874
|
connect(entry: ConnectableEntry, opts?: {
|
|
846
875
|
kind: ConnectionKind;
|
|
876
|
+
access?: ConnectableAccess;
|
|
847
877
|
}): Promise<{
|
|
848
878
|
connect_url?: string;
|
|
849
879
|
}>;
|
|
@@ -895,4 +925,4 @@ interface ConnectorPickerProps {
|
|
|
895
925
|
}
|
|
896
926
|
declare function ConnectorPicker({ client, purpose, lens, layout, onConnected, }: ConnectorPickerProps): react.JSX.Element | null;
|
|
897
927
|
|
|
898
|
-
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
|
928
|
+
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableAccess, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, accessLabel, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
package/dist/index.d.ts
CHANGED
|
@@ -632,7 +632,7 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
632
632
|
* errors, and a return-from-OAuth refresh). Every label is derived from the
|
|
633
633
|
* entry data the client returns — this file must never hardcode a specific
|
|
634
634
|
* provider's name (an explicit acceptance criterion); a host app supplies
|
|
635
|
-
* that entirely through `ConnectableEntry.name` / `.logo
|
|
635
|
+
* that entirely through `ConnectableEntry.name` / `.logo`.
|
|
636
636
|
*
|
|
637
637
|
* Transport-injection precedent: `linkComponent` (DEV-4429/DEV-4391) —
|
|
638
638
|
* inject the transport, keep behavior in the package. Here the "transport"
|
|
@@ -649,7 +649,17 @@ declare function ContextSwitcher({ items, activeRefId, onSelect, footer, placeho
|
|
|
649
649
|
* optional grant methods, so a pre-CD-5 client keeps working unchanged.
|
|
650
650
|
*/
|
|
651
651
|
type ConnectableTransport = "composio" | "native";
|
|
652
|
+
/**
|
|
653
|
+
* The widest access an entry offers. "write" is retired (DEV-13661: no
|
|
654
|
+
* provider ever only acted, so its old label was never true); it stays in the
|
|
655
|
+
* union so an older server payload still type-checks, and it renders as
|
|
656
|
+
* "Read + write".
|
|
657
|
+
*/
|
|
652
658
|
type ConnectableCapability = "read" | "write" | "readwrite";
|
|
659
|
+
/** What a connection lets Reeve do: ingest/query, or also act (DEV-13661). */
|
|
660
|
+
type ConnectableAccess = "read" | "readwrite";
|
|
661
|
+
/** The ONE access -> words mapping; nothing is labeled as acting alone (DEV-13661). */
|
|
662
|
+
declare function accessLabel(access: ConnectableCapability): string;
|
|
653
663
|
type ConnectionKind = "personal" | "org";
|
|
654
664
|
type ConnectorGranteeType = "user" | "role";
|
|
655
665
|
/** An RBAC role a grant can target, injected via the entry data (CD-2). */
|
|
@@ -664,7 +674,7 @@ interface ConnectorRoleOption {
|
|
|
664
674
|
*/
|
|
665
675
|
interface OrgConnectPolicy {
|
|
666
676
|
permitted: boolean;
|
|
667
|
-
/**
|
|
677
|
+
/** Why org connect isn't permitted (server-authored). */
|
|
668
678
|
reason?: string | null;
|
|
669
679
|
/** Role options offered by manage-sharing's "role" grantee type. */
|
|
670
680
|
role_options?: ConnectorRoleOption[];
|
|
@@ -806,7 +816,24 @@ interface ConnectableEntry {
|
|
|
806
816
|
* picker never assumes an email shape or synthesizes this itself.
|
|
807
817
|
*/
|
|
808
818
|
account_label?: string | null;
|
|
819
|
+
/**
|
|
820
|
+
* What this live connection lets Reeve do (DEV-13661). Absent on a
|
|
821
|
+
* pre-DEV-13661 payload, where the entry's `capability` stands in.
|
|
822
|
+
*/
|
|
823
|
+
access?: ConnectableAccess | null;
|
|
809
824
|
};
|
|
825
|
+
/**
|
|
826
|
+
* The accesses this entry may be connected as (DEV-13661), in
|
|
827
|
+
* ("read", "readwrite") order. More than one renders a Read / Read + write
|
|
828
|
+
* choice whose pick reaches `client.connect` as `opts.access`.
|
|
829
|
+
*/
|
|
830
|
+
access_options?: ConnectableAccess[] | null;
|
|
831
|
+
/**
|
|
832
|
+
* Every connection provider key that belongs to this entry's provider
|
|
833
|
+
* (its own slug first), so a host can group stored connections onto one
|
|
834
|
+
* row per provider (DEV-13661).
|
|
835
|
+
*/
|
|
836
|
+
provider_keys?: string[] | null;
|
|
810
837
|
/** true = tenant has a live connection but the entry left the allowlist. */
|
|
811
838
|
deprecated: boolean;
|
|
812
839
|
/** Org-connect permission + role options for this entry (CD-4). */
|
|
@@ -841,9 +868,12 @@ interface ConnectorPickerClient {
|
|
|
841
868
|
* composio -> open the returned connect_url; native may resolve with none.
|
|
842
869
|
* `opts.kind` is additive (DEV-5654): a pre-CD-5 client declaring only
|
|
843
870
|
* `connect(entry)` still satisfies this signature and simply ignores it.
|
|
871
|
+
* `opts.access` (DEV-13661) is the row's Read / Read + write pick, sent
|
|
872
|
+
* only when the entry offers a choice.
|
|
844
873
|
*/
|
|
845
874
|
connect(entry: ConnectableEntry, opts?: {
|
|
846
875
|
kind: ConnectionKind;
|
|
876
|
+
access?: ConnectableAccess;
|
|
847
877
|
}): Promise<{
|
|
848
878
|
connect_url?: string;
|
|
849
879
|
}>;
|
|
@@ -895,4 +925,4 @@ interface ConnectorPickerProps {
|
|
|
895
925
|
}
|
|
896
926
|
declare function ConnectorPicker({ client, purpose, lens, layout, onConnected, }: ConnectorPickerProps): react.JSX.Element | null;
|
|
897
927
|
|
|
898
|
-
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
|
928
|
+
export { type AppRungItem, AppSidebar, type AppSidebarBrand, type AppSidebarModuleDef, type AppSidebarProps, type AppSidebarTopItem, type Brand, BrandGlyph, type BrandGlyphProps, type ConnectableAccess, type ConnectableCapability, type ConnectableEntry, type ConnectableTransport, type ConnectionKind, type ConnectorConnectionHealth, type ConnectorCredentialField, type ConnectorCredentialTestResult, type ConnectorGrant, type ConnectorGrantInput, type ConnectorGranteeType, type ConnectorGuideStep, ConnectorPicker, type ConnectorPickerClient, type ConnectorPickerLens, type ConnectorPickerProps, type ConnectorRoleOption, type ConnectorSetupGuide, type ContextOrgGroup, ContextSwitcher, type ContextSwitcherItem, type ContextSwitcherProps, type FallbackModuleDef, Flyout, type FlyoutChild, type FlyoutProps, GLYPH_CANVAS_FILL, type GroupRungItem, type HeaderNavItem, InfoTip, type InfoTipProps, LOCKUP_GAP, LOCKUP_ROW, MARK_CAP_RATIO, MARK_WEIGHT, type OrgConnectPolicy, REEVE_ACCENT, ResponsiveHeader, type ResponsiveHeaderProps, type RungItem, type SidebarLadder, type SidebarLadderParsed, type SidebarRung, type UseLadderRungOptions, WORDMARK_WEIGHT, accessLabel, deriveFallbackLadder, faviconUrl, groupByOrg, reconcileLadder, resolveLadder, useLadderRung, useResponsivePlaceholder, zSidebarLadder };
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(src_exports, {
|
|
|
45
45
|
REEVE_ACCENT: () => REEVE_ACCENT,
|
|
46
46
|
ResponsiveHeader: () => ResponsiveHeader,
|
|
47
47
|
WORDMARK_WEIGHT: () => WORDMARK_WEIGHT,
|
|
48
|
+
accessLabel: () => accessLabel,
|
|
48
49
|
deriveFallbackLadder: () => deriveFallbackLadder,
|
|
49
50
|
faviconUrl: () => faviconUrl,
|
|
50
51
|
groupByOrg: () => groupByOrg,
|
|
@@ -1463,6 +1464,9 @@ function ContextSwitcher({
|
|
|
1463
1464
|
// src/connector-picker.tsx
|
|
1464
1465
|
var import_react9 = require("react");
|
|
1465
1466
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1467
|
+
function accessLabel(access) {
|
|
1468
|
+
return access === "read" ? "Read" : "Read + write";
|
|
1469
|
+
}
|
|
1466
1470
|
var DEFAULT_CONNECT_ERROR = "Couldn't start the connection. Please try again.";
|
|
1467
1471
|
var MAX_RECONNECT_REFOCUS_CHECKS = 3;
|
|
1468
1472
|
var RECONNECT_UNCONFIRMED_ERROR = "Couldn't confirm the reconnect \u2014 the connection still reports unhealthy. Try again, or disconnect and reconnect.";
|
|
@@ -1471,7 +1475,6 @@ var DEFAULT_LOAD_ERROR = "Couldn't load connections. Please try again.";
|
|
|
1471
1475
|
var DEFAULT_GRANTS_LOAD_ERROR = "Couldn't load sharing. Please try again.";
|
|
1472
1476
|
var DEFAULT_GRANT_ERROR = "Couldn't share. Please try again.";
|
|
1473
1477
|
var DEFAULT_REVOKE_ERROR = "Couldn't revoke access. Please try again.";
|
|
1474
|
-
var DEFAULT_ORG_DISABLED_REASON = "Org-wide connections aren't available to you.";
|
|
1475
1478
|
var DEFAULT_CREDENTIAL_ERROR = "Couldn't save that credential. Please try again.";
|
|
1476
1479
|
var DEFAULT_CREDENTIAL_TEST_ERROR = "Couldn't test that credential. Please try again.";
|
|
1477
1480
|
var DEFAULT_RECONNECT_MESSAGE = "This connection needs to be reconnected to keep working.";
|
|
@@ -1485,15 +1488,17 @@ function hasUngroundedPlaceholder(text) {
|
|
|
1485
1488
|
function isDevEnvironment() {
|
|
1486
1489
|
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1487
1490
|
}
|
|
1488
|
-
function
|
|
1489
|
-
if (
|
|
1490
|
-
|
|
1491
|
-
|
|
1491
|
+
function tileAccess(entry) {
|
|
1492
|
+
if (entry.connection.status === "connected" && entry.connection.access) {
|
|
1493
|
+
return entry.connection.access;
|
|
1494
|
+
}
|
|
1495
|
+
return entry.capability;
|
|
1492
1496
|
}
|
|
1493
|
-
function
|
|
1494
|
-
const
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
+
function accessChoices(entry) {
|
|
1498
|
+
const options = (entry.access_options ?? []).filter(
|
|
1499
|
+
(a) => a === "read" || a === "readwrite"
|
|
1500
|
+
);
|
|
1501
|
+
return options.length > 1 ? options : [];
|
|
1497
1502
|
}
|
|
1498
1503
|
function errorMessageFrom(err, fallback) {
|
|
1499
1504
|
return err instanceof Error && err.message ? err.message : fallback;
|
|
@@ -1612,7 +1617,7 @@ function ConnectorPicker({
|
|
|
1612
1617
|
};
|
|
1613
1618
|
}, [gated, refreshAfterReturn]);
|
|
1614
1619
|
const handleConnect = (0, import_react9.useCallback)(
|
|
1615
|
-
async (entry, kind) => {
|
|
1620
|
+
async (entry, kind, access) => {
|
|
1616
1621
|
if (isUnhealthy(entry)) {
|
|
1617
1622
|
reconnectingRef.current.add(entry.slug);
|
|
1618
1623
|
} else {
|
|
@@ -1621,7 +1626,10 @@ function ConnectorPicker({
|
|
|
1621
1626
|
reconnectChecksRef.current.delete(entry.slug);
|
|
1622
1627
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "connecting" } }));
|
|
1623
1628
|
try {
|
|
1624
|
-
const result = await clientRef.current.connect(
|
|
1629
|
+
const result = await clientRef.current.connect(
|
|
1630
|
+
entry,
|
|
1631
|
+
access ? { kind, access } : { kind }
|
|
1632
|
+
);
|
|
1625
1633
|
if (result?.connect_url) {
|
|
1626
1634
|
window.open(result.connect_url, "_blank", "noopener,noreferrer");
|
|
1627
1635
|
return;
|
|
@@ -1811,6 +1819,9 @@ function ConnectorTile({
|
|
|
1811
1819
|
const errorMessage = ui?.kind === "error" ? ui.message : null;
|
|
1812
1820
|
const unhealthy = isUnhealthy(entry);
|
|
1813
1821
|
const [kind, setKind] = (0, import_react9.useState)("personal");
|
|
1822
|
+
const choices = accessChoices(entry);
|
|
1823
|
+
const [access, setAccess] = (0, import_react9.useState)(null);
|
|
1824
|
+
const connectAccess = choices.length ? access && choices.includes(access) ? access : choices[choices.length - 1] : void 0;
|
|
1814
1825
|
const [sharingOpen, setSharingOpen] = (0, import_react9.useState)(false);
|
|
1815
1826
|
const [setupOpen, setSetupOpen] = (0, import_react9.useState)(false);
|
|
1816
1827
|
const credentialFields = entry.credential_fields ?? [];
|
|
@@ -1818,7 +1829,7 @@ function ConnectorTile({
|
|
|
1818
1829
|
const guide = entry.guide ?? null;
|
|
1819
1830
|
const canSetUp = !isConnected && (pasteSupported || guide !== null);
|
|
1820
1831
|
const orgPermitted = entry.org_connect?.permitted === true;
|
|
1821
|
-
const
|
|
1832
|
+
const connectKind = orgPermitted ? kind : "personal";
|
|
1822
1833
|
const attribution = ownerLabel(entry);
|
|
1823
1834
|
const canDisconnect = isConnected && !shared;
|
|
1824
1835
|
const canManageSharing = isConnected && entry.connection.owned_by_viewer === true && grantsSupported;
|
|
@@ -1845,20 +1856,22 @@ function ConnectorTile({
|
|
|
1845
1856
|
)
|
|
1846
1857
|
] }),
|
|
1847
1858
|
/* @__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:
|
|
1849
|
-
|
|
1859
|
+
(isConnected || choices.length === 0) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-testid": `connector-capability-${entry.slug}`, children: accessLabel(tileAccess(entry)) }),
|
|
1860
|
+
isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1850
1861
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
1851
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
1862
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1863
|
+
"span",
|
|
1864
|
+
{
|
|
1865
|
+
"data-testid": `connector-connected-${entry.slug}`,
|
|
1866
|
+
className: "inline-flex items-center gap-1",
|
|
1867
|
+
children: [
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", className: "h-1.5 w-1.5 rounded-full bg-emerald-500" }),
|
|
1869
|
+
"Connected"
|
|
1870
|
+
]
|
|
1871
|
+
}
|
|
1872
|
+
)
|
|
1852
1873
|
] })
|
|
1853
1874
|
] }),
|
|
1854
|
-
isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1855
|
-
"p",
|
|
1856
|
-
{
|
|
1857
|
-
"data-testid": `connector-connected-since-${entry.slug}`,
|
|
1858
|
-
className: "text-xs text-muted-foreground",
|
|
1859
|
-
children: entry.connection.since ? `Connected since ${formatSince(entry.connection.since)}` : "Connected"
|
|
1860
|
-
}
|
|
1861
|
-
),
|
|
1862
1875
|
isConnected && !shared && entry.connection.account_label && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1863
1876
|
"p",
|
|
1864
1877
|
{
|
|
@@ -1895,7 +1908,33 @@ function ConnectorTile({
|
|
|
1895
1908
|
children: attribution
|
|
1896
1909
|
}
|
|
1897
1910
|
),
|
|
1898
|
-
!isConnected && /* @__PURE__ */ (0, import_jsx_runtime8.
|
|
1911
|
+
!isConnected && choices.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1912
|
+
"div",
|
|
1913
|
+
{
|
|
1914
|
+
"data-testid": `connector-access-choice-${entry.slug}`,
|
|
1915
|
+
role: "group",
|
|
1916
|
+
"aria-label": "Access",
|
|
1917
|
+
className: "mt-1 flex items-center gap-1",
|
|
1918
|
+
children: choices.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1919
|
+
"button",
|
|
1920
|
+
{
|
|
1921
|
+
type: "button",
|
|
1922
|
+
"data-testid": `connector-access-${option}-${entry.slug}`,
|
|
1923
|
+
"aria-pressed": connectAccess === option,
|
|
1924
|
+
disabled: isConnecting,
|
|
1925
|
+
onClick: () => setAccess(option),
|
|
1926
|
+
className: cn(
|
|
1927
|
+
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1928
|
+
connectAccess === option ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1929
|
+
"disabled:opacity-50"
|
|
1930
|
+
),
|
|
1931
|
+
children: accessLabel(option)
|
|
1932
|
+
},
|
|
1933
|
+
option
|
|
1934
|
+
))
|
|
1935
|
+
}
|
|
1936
|
+
),
|
|
1937
|
+
!isConnected && orgPermitted && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1899
1938
|
"div",
|
|
1900
1939
|
{
|
|
1901
1940
|
"data-testid": `connector-kind-toggle-${entry.slug}`,
|
|
@@ -1910,6 +1949,7 @@ function ConnectorTile({
|
|
|
1910
1949
|
"data-testid": `connector-kind-personal-${entry.slug}`,
|
|
1911
1950
|
"aria-pressed": kind === "personal",
|
|
1912
1951
|
disabled: isConnecting,
|
|
1952
|
+
title: "Just for you",
|
|
1913
1953
|
onClick: () => setKind("personal"),
|
|
1914
1954
|
className: cn(
|
|
1915
1955
|
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
@@ -1919,28 +1959,21 @@ function ConnectorTile({
|
|
|
1919
1959
|
children: "Personal"
|
|
1920
1960
|
}
|
|
1921
1961
|
),
|
|
1922
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1923
1963
|
"button",
|
|
1924
1964
|
{
|
|
1925
1965
|
type: "button",
|
|
1926
1966
|
"data-testid": `connector-kind-org-${entry.slug}`,
|
|
1927
1967
|
"aria-pressed": kind === "org",
|
|
1928
|
-
disabled: isConnecting
|
|
1929
|
-
title:
|
|
1968
|
+
disabled: isConnecting,
|
|
1969
|
+
title: "For your whole org",
|
|
1930
1970
|
onClick: () => setKind("org"),
|
|
1931
1971
|
className: cn(
|
|
1932
1972
|
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1933
1973
|
kind === "org" ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1934
1974
|
"disabled:opacity-50"
|
|
1935
1975
|
),
|
|
1936
|
-
children:
|
|
1937
|
-
"Org",
|
|
1938
|
-
!orgPermitted && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "sr-only", children: [
|
|
1939
|
-
" (",
|
|
1940
|
-
orgDisabledReason,
|
|
1941
|
-
")"
|
|
1942
|
-
] })
|
|
1943
|
-
]
|
|
1976
|
+
children: "Org"
|
|
1944
1977
|
}
|
|
1945
1978
|
)
|
|
1946
1979
|
]
|
|
@@ -1954,13 +1987,17 @@ function ConnectorTile({
|
|
|
1954
1987
|
{
|
|
1955
1988
|
type: "button",
|
|
1956
1989
|
"data-testid": `connector-reconnect-${entry.slug}`,
|
|
1957
|
-
onClick: () => onConnect(entry, entry.connection.kind ?? "personal"),
|
|
1990
|
+
onClick: () => onConnect(entry, entry.connection.kind ?? "personal", entry.connection.access ?? void 0),
|
|
1958
1991
|
disabled: isConnecting || isDisconnecting,
|
|
1959
1992
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1960
1993
|
children: isConnecting ? "Reconnecting\u2026" : "Reconnect"
|
|
1961
1994
|
}
|
|
1962
1995
|
),
|
|
1963
|
-
canDisconnect &&
|
|
1996
|
+
canDisconnect && // DEV-11580: the revoke reassurance lives in the title only —
|
|
1997
|
+
// as an always-visible paragraph it wrapped to four lines
|
|
1998
|
+
// beside every connected tile. Muted until hover so a
|
|
1999
|
+
// destructive action isn't the loudest thing on the tile.
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1964
2001
|
"button",
|
|
1965
2002
|
{
|
|
1966
2003
|
type: "button",
|
|
@@ -1968,27 +2005,10 @@ function ConnectorTile({
|
|
|
1968
2005
|
title: DISCONNECT_REVOKES_HINT,
|
|
1969
2006
|
onClick: () => onDisconnect(entry),
|
|
1970
2007
|
disabled: isDisconnecting || isConnecting,
|
|
1971
|
-
className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-medium text-
|
|
2008
|
+
className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-medium text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:opacity-50",
|
|
1972
2009
|
children: isDisconnecting ? "Disconnecting\u2026" : "Disconnect"
|
|
1973
2010
|
}
|
|
1974
2011
|
),
|
|
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
2012
|
canManageSharing && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1993
2013
|
"button",
|
|
1994
2014
|
{
|
|
@@ -2006,7 +2026,7 @@ function ConnectorTile({
|
|
|
2006
2026
|
{
|
|
2007
2027
|
type: "button",
|
|
2008
2028
|
"data-testid": `connector-connect-${entry.slug}`,
|
|
2009
|
-
onClick: () => onConnect(entry,
|
|
2029
|
+
onClick: () => onConnect(entry, connectKind, connectAccess),
|
|
2010
2030
|
disabled: isConnecting,
|
|
2011
2031
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
2012
2032
|
children: isConnecting ? "Connecting\u2026" : "Connect"
|
|
@@ -2039,7 +2059,7 @@ function ConnectorTile({
|
|
|
2039
2059
|
{
|
|
2040
2060
|
entry,
|
|
2041
2061
|
fields: credentialFields,
|
|
2042
|
-
kind,
|
|
2062
|
+
kind: connectKind,
|
|
2043
2063
|
verify: guide?.verify ?? null,
|
|
2044
2064
|
testSupported: credentialTestSupported,
|
|
2045
2065
|
onSubmitCredentials,
|
|
@@ -2579,6 +2599,7 @@ function ManageSharing({
|
|
|
2579
2599
|
REEVE_ACCENT,
|
|
2580
2600
|
ResponsiveHeader,
|
|
2581
2601
|
WORDMARK_WEIGHT,
|
|
2602
|
+
accessLabel,
|
|
2582
2603
|
deriveFallbackLadder,
|
|
2583
2604
|
faviconUrl,
|
|
2584
2605
|
groupByOrg,
|
package/dist/index.mjs
CHANGED
|
@@ -1407,6 +1407,9 @@ function ContextSwitcher({
|
|
|
1407
1407
|
// src/connector-picker.tsx
|
|
1408
1408
|
import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef5, useState as useState7 } from "react";
|
|
1409
1409
|
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1410
|
+
function accessLabel(access) {
|
|
1411
|
+
return access === "read" ? "Read" : "Read + write";
|
|
1412
|
+
}
|
|
1410
1413
|
var DEFAULT_CONNECT_ERROR = "Couldn't start the connection. Please try again.";
|
|
1411
1414
|
var MAX_RECONNECT_REFOCUS_CHECKS = 3;
|
|
1412
1415
|
var RECONNECT_UNCONFIRMED_ERROR = "Couldn't confirm the reconnect \u2014 the connection still reports unhealthy. Try again, or disconnect and reconnect.";
|
|
@@ -1415,7 +1418,6 @@ var DEFAULT_LOAD_ERROR = "Couldn't load connections. Please try again.";
|
|
|
1415
1418
|
var DEFAULT_GRANTS_LOAD_ERROR = "Couldn't load sharing. Please try again.";
|
|
1416
1419
|
var DEFAULT_GRANT_ERROR = "Couldn't share. Please try again.";
|
|
1417
1420
|
var DEFAULT_REVOKE_ERROR = "Couldn't revoke access. Please try again.";
|
|
1418
|
-
var DEFAULT_ORG_DISABLED_REASON = "Org-wide connections aren't available to you.";
|
|
1419
1421
|
var DEFAULT_CREDENTIAL_ERROR = "Couldn't save that credential. Please try again.";
|
|
1420
1422
|
var DEFAULT_CREDENTIAL_TEST_ERROR = "Couldn't test that credential. Please try again.";
|
|
1421
1423
|
var DEFAULT_RECONNECT_MESSAGE = "This connection needs to be reconnected to keep working.";
|
|
@@ -1429,15 +1431,17 @@ function hasUngroundedPlaceholder(text) {
|
|
|
1429
1431
|
function isDevEnvironment() {
|
|
1430
1432
|
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1431
1433
|
}
|
|
1432
|
-
function
|
|
1433
|
-
if (
|
|
1434
|
-
|
|
1435
|
-
|
|
1434
|
+
function tileAccess(entry) {
|
|
1435
|
+
if (entry.connection.status === "connected" && entry.connection.access) {
|
|
1436
|
+
return entry.connection.access;
|
|
1437
|
+
}
|
|
1438
|
+
return entry.capability;
|
|
1436
1439
|
}
|
|
1437
|
-
function
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1440
|
+
function accessChoices(entry) {
|
|
1441
|
+
const options = (entry.access_options ?? []).filter(
|
|
1442
|
+
(a) => a === "read" || a === "readwrite"
|
|
1443
|
+
);
|
|
1444
|
+
return options.length > 1 ? options : [];
|
|
1441
1445
|
}
|
|
1442
1446
|
function errorMessageFrom(err, fallback) {
|
|
1443
1447
|
return err instanceof Error && err.message ? err.message : fallback;
|
|
@@ -1556,7 +1560,7 @@ function ConnectorPicker({
|
|
|
1556
1560
|
};
|
|
1557
1561
|
}, [gated, refreshAfterReturn]);
|
|
1558
1562
|
const handleConnect = useCallback4(
|
|
1559
|
-
async (entry, kind) => {
|
|
1563
|
+
async (entry, kind, access) => {
|
|
1560
1564
|
if (isUnhealthy(entry)) {
|
|
1561
1565
|
reconnectingRef.current.add(entry.slug);
|
|
1562
1566
|
} else {
|
|
@@ -1565,7 +1569,10 @@ function ConnectorPicker({
|
|
|
1565
1569
|
reconnectChecksRef.current.delete(entry.slug);
|
|
1566
1570
|
setUiState((prev) => ({ ...prev, [entry.slug]: { kind: "connecting" } }));
|
|
1567
1571
|
try {
|
|
1568
|
-
const result = await clientRef.current.connect(
|
|
1572
|
+
const result = await clientRef.current.connect(
|
|
1573
|
+
entry,
|
|
1574
|
+
access ? { kind, access } : { kind }
|
|
1575
|
+
);
|
|
1569
1576
|
if (result?.connect_url) {
|
|
1570
1577
|
window.open(result.connect_url, "_blank", "noopener,noreferrer");
|
|
1571
1578
|
return;
|
|
@@ -1755,6 +1762,9 @@ function ConnectorTile({
|
|
|
1755
1762
|
const errorMessage = ui?.kind === "error" ? ui.message : null;
|
|
1756
1763
|
const unhealthy = isUnhealthy(entry);
|
|
1757
1764
|
const [kind, setKind] = useState7("personal");
|
|
1765
|
+
const choices = accessChoices(entry);
|
|
1766
|
+
const [access, setAccess] = useState7(null);
|
|
1767
|
+
const connectAccess = choices.length ? access && choices.includes(access) ? access : choices[choices.length - 1] : void 0;
|
|
1758
1768
|
const [sharingOpen, setSharingOpen] = useState7(false);
|
|
1759
1769
|
const [setupOpen, setSetupOpen] = useState7(false);
|
|
1760
1770
|
const credentialFields = entry.credential_fields ?? [];
|
|
@@ -1762,7 +1772,7 @@ function ConnectorTile({
|
|
|
1762
1772
|
const guide = entry.guide ?? null;
|
|
1763
1773
|
const canSetUp = !isConnected && (pasteSupported || guide !== null);
|
|
1764
1774
|
const orgPermitted = entry.org_connect?.permitted === true;
|
|
1765
|
-
const
|
|
1775
|
+
const connectKind = orgPermitted ? kind : "personal";
|
|
1766
1776
|
const attribution = ownerLabel(entry);
|
|
1767
1777
|
const canDisconnect = isConnected && !shared;
|
|
1768
1778
|
const canManageSharing = isConnected && entry.connection.owned_by_viewer === true && grantsSupported;
|
|
@@ -1789,20 +1799,22 @@ function ConnectorTile({
|
|
|
1789
1799
|
)
|
|
1790
1800
|
] }),
|
|
1791
1801
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1792
|
-
/* @__PURE__ */ jsx8("span", { "data-testid": `connector-capability-${entry.slug}`, children:
|
|
1793
|
-
|
|
1802
|
+
(isConnected || choices.length === 0) && /* @__PURE__ */ jsx8("span", { "data-testid": `connector-capability-${entry.slug}`, children: accessLabel(tileAccess(entry)) }),
|
|
1803
|
+
isConnected && /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1794
1804
|
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
1795
|
-
/* @__PURE__ */
|
|
1805
|
+
/* @__PURE__ */ jsxs7(
|
|
1806
|
+
"span",
|
|
1807
|
+
{
|
|
1808
|
+
"data-testid": `connector-connected-${entry.slug}`,
|
|
1809
|
+
className: "inline-flex items-center gap-1",
|
|
1810
|
+
children: [
|
|
1811
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "h-1.5 w-1.5 rounded-full bg-emerald-500" }),
|
|
1812
|
+
"Connected"
|
|
1813
|
+
]
|
|
1814
|
+
}
|
|
1815
|
+
)
|
|
1796
1816
|
] })
|
|
1797
1817
|
] }),
|
|
1798
|
-
isConnected && /* @__PURE__ */ jsx8(
|
|
1799
|
-
"p",
|
|
1800
|
-
{
|
|
1801
|
-
"data-testid": `connector-connected-since-${entry.slug}`,
|
|
1802
|
-
className: "text-xs text-muted-foreground",
|
|
1803
|
-
children: entry.connection.since ? `Connected since ${formatSince(entry.connection.since)}` : "Connected"
|
|
1804
|
-
}
|
|
1805
|
-
),
|
|
1806
1818
|
isConnected && !shared && entry.connection.account_label && /* @__PURE__ */ jsxs7(
|
|
1807
1819
|
"p",
|
|
1808
1820
|
{
|
|
@@ -1839,7 +1851,33 @@ function ConnectorTile({
|
|
|
1839
1851
|
children: attribution
|
|
1840
1852
|
}
|
|
1841
1853
|
),
|
|
1842
|
-
!isConnected && /* @__PURE__ */
|
|
1854
|
+
!isConnected && choices.length > 0 && /* @__PURE__ */ jsx8(
|
|
1855
|
+
"div",
|
|
1856
|
+
{
|
|
1857
|
+
"data-testid": `connector-access-choice-${entry.slug}`,
|
|
1858
|
+
role: "group",
|
|
1859
|
+
"aria-label": "Access",
|
|
1860
|
+
className: "mt-1 flex items-center gap-1",
|
|
1861
|
+
children: choices.map((option) => /* @__PURE__ */ jsx8(
|
|
1862
|
+
"button",
|
|
1863
|
+
{
|
|
1864
|
+
type: "button",
|
|
1865
|
+
"data-testid": `connector-access-${option}-${entry.slug}`,
|
|
1866
|
+
"aria-pressed": connectAccess === option,
|
|
1867
|
+
disabled: isConnecting,
|
|
1868
|
+
onClick: () => setAccess(option),
|
|
1869
|
+
className: cn(
|
|
1870
|
+
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1871
|
+
connectAccess === option ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1872
|
+
"disabled:opacity-50"
|
|
1873
|
+
),
|
|
1874
|
+
children: accessLabel(option)
|
|
1875
|
+
},
|
|
1876
|
+
option
|
|
1877
|
+
))
|
|
1878
|
+
}
|
|
1879
|
+
),
|
|
1880
|
+
!isConnected && orgPermitted && /* @__PURE__ */ jsxs7(
|
|
1843
1881
|
"div",
|
|
1844
1882
|
{
|
|
1845
1883
|
"data-testid": `connector-kind-toggle-${entry.slug}`,
|
|
@@ -1854,6 +1892,7 @@ function ConnectorTile({
|
|
|
1854
1892
|
"data-testid": `connector-kind-personal-${entry.slug}`,
|
|
1855
1893
|
"aria-pressed": kind === "personal",
|
|
1856
1894
|
disabled: isConnecting,
|
|
1895
|
+
title: "Just for you",
|
|
1857
1896
|
onClick: () => setKind("personal"),
|
|
1858
1897
|
className: cn(
|
|
1859
1898
|
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
@@ -1863,28 +1902,21 @@ function ConnectorTile({
|
|
|
1863
1902
|
children: "Personal"
|
|
1864
1903
|
}
|
|
1865
1904
|
),
|
|
1866
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ jsx8(
|
|
1867
1906
|
"button",
|
|
1868
1907
|
{
|
|
1869
1908
|
type: "button",
|
|
1870
1909
|
"data-testid": `connector-kind-org-${entry.slug}`,
|
|
1871
1910
|
"aria-pressed": kind === "org",
|
|
1872
|
-
disabled: isConnecting
|
|
1873
|
-
title:
|
|
1911
|
+
disabled: isConnecting,
|
|
1912
|
+
title: "For your whole org",
|
|
1874
1913
|
onClick: () => setKind("org"),
|
|
1875
1914
|
className: cn(
|
|
1876
1915
|
"rounded-full border px-2 py-0.5 text-[11px]",
|
|
1877
1916
|
kind === "org" ? "border-primary bg-primary/10 font-medium" : "border-border text-muted-foreground",
|
|
1878
1917
|
"disabled:opacity-50"
|
|
1879
1918
|
),
|
|
1880
|
-
children:
|
|
1881
|
-
"Org",
|
|
1882
|
-
!orgPermitted && /* @__PURE__ */ jsxs7("span", { className: "sr-only", children: [
|
|
1883
|
-
" (",
|
|
1884
|
-
orgDisabledReason,
|
|
1885
|
-
")"
|
|
1886
|
-
] })
|
|
1887
|
-
]
|
|
1919
|
+
children: "Org"
|
|
1888
1920
|
}
|
|
1889
1921
|
)
|
|
1890
1922
|
]
|
|
@@ -1898,13 +1930,17 @@ function ConnectorTile({
|
|
|
1898
1930
|
{
|
|
1899
1931
|
type: "button",
|
|
1900
1932
|
"data-testid": `connector-reconnect-${entry.slug}`,
|
|
1901
|
-
onClick: () => onConnect(entry, entry.connection.kind ?? "personal"),
|
|
1933
|
+
onClick: () => onConnect(entry, entry.connection.kind ?? "personal", entry.connection.access ?? void 0),
|
|
1902
1934
|
disabled: isConnecting || isDisconnecting,
|
|
1903
1935
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1904
1936
|
children: isConnecting ? "Reconnecting\u2026" : "Reconnect"
|
|
1905
1937
|
}
|
|
1906
1938
|
),
|
|
1907
|
-
canDisconnect &&
|
|
1939
|
+
canDisconnect && // DEV-11580: the revoke reassurance lives in the title only —
|
|
1940
|
+
// as an always-visible paragraph it wrapped to four lines
|
|
1941
|
+
// beside every connected tile. Muted until hover so a
|
|
1942
|
+
// destructive action isn't the loudest thing on the tile.
|
|
1943
|
+
/* @__PURE__ */ jsx8(
|
|
1908
1944
|
"button",
|
|
1909
1945
|
{
|
|
1910
1946
|
type: "button",
|
|
@@ -1912,27 +1948,10 @@ function ConnectorTile({
|
|
|
1912
1948
|
title: DISCONNECT_REVOKES_HINT,
|
|
1913
1949
|
onClick: () => onDisconnect(entry),
|
|
1914
1950
|
disabled: isDisconnecting || isConnecting,
|
|
1915
|
-
className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-medium text-
|
|
1951
|
+
className: "shrink-0 rounded-md px-2.5 py-1 text-xs font-medium text-muted-foreground hover:bg-destructive/10 hover:text-destructive disabled:opacity-50",
|
|
1916
1952
|
children: isDisconnecting ? "Disconnecting\u2026" : "Disconnect"
|
|
1917
1953
|
}
|
|
1918
1954
|
),
|
|
1919
|
-
canDisconnect && // Outcome-eval finding (DEV-7873): with no width cap, this
|
|
1920
|
-
// paragraph's one long sentence forced the WHOLE shrink-0
|
|
1921
|
-
// button column to grow to its natural (unwrapped) width,
|
|
1922
|
-
// squeezing the sibling `min-w-0 flex-1` text column down to
|
|
1923
|
-
// one word per line at any realistic tile width. RTL's jsdom
|
|
1924
|
-
// tests never caught it — jsdom doesn't lay out real flexbox
|
|
1925
|
-
// sizing, so every textContent assertion still passed. A
|
|
1926
|
-
// narrow max-width forces the hint to wrap within the same
|
|
1927
|
-
// footprint as the button above it instead.
|
|
1928
|
-
/* @__PURE__ */ jsx8(
|
|
1929
|
-
"p",
|
|
1930
|
-
{
|
|
1931
|
-
"data-testid": `connector-disconnect-hint-${entry.slug}`,
|
|
1932
|
-
className: "max-w-28 text-right text-[11px] text-muted-foreground",
|
|
1933
|
-
children: DISCONNECT_REVOKES_HINT
|
|
1934
|
-
}
|
|
1935
|
-
),
|
|
1936
1955
|
canManageSharing && /* @__PURE__ */ jsx8(
|
|
1937
1956
|
"button",
|
|
1938
1957
|
{
|
|
@@ -1950,7 +1969,7 @@ function ConnectorTile({
|
|
|
1950
1969
|
{
|
|
1951
1970
|
type: "button",
|
|
1952
1971
|
"data-testid": `connector-connect-${entry.slug}`,
|
|
1953
|
-
onClick: () => onConnect(entry,
|
|
1972
|
+
onClick: () => onConnect(entry, connectKind, connectAccess),
|
|
1954
1973
|
disabled: isConnecting,
|
|
1955
1974
|
className: "shrink-0 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground disabled:opacity-50",
|
|
1956
1975
|
children: isConnecting ? "Connecting\u2026" : "Connect"
|
|
@@ -1983,7 +2002,7 @@ function ConnectorTile({
|
|
|
1983
2002
|
{
|
|
1984
2003
|
entry,
|
|
1985
2004
|
fields: credentialFields,
|
|
1986
|
-
kind,
|
|
2005
|
+
kind: connectKind,
|
|
1987
2006
|
verify: guide?.verify ?? null,
|
|
1988
2007
|
testSupported: credentialTestSupported,
|
|
1989
2008
|
onSubmitCredentials,
|
|
@@ -2522,6 +2541,7 @@ export {
|
|
|
2522
2541
|
REEVE_ACCENT,
|
|
2523
2542
|
ResponsiveHeader,
|
|
2524
2543
|
WORDMARK_WEIGHT,
|
|
2544
|
+
accessLabel,
|
|
2525
2545
|
deriveFallbackLadder,
|
|
2526
2546
|
faviconUrl,
|
|
2527
2547
|
groupByOrg,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetreeve/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Shared brand-adaptive UI primitives for MindFortress frontends — min-size tokens, a favicon→logo→monogram BrandGlyph, a responsive header that keeps the search bar usable on mobile, and AppSidebar's viewport-driven auto-collapse ladder.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "./dist/index.js",
|