@the-portland-company/shell 0.97.1 → 0.99.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.
@@ -78,6 +78,54 @@ declare function RowMenuItem({ onSelect, disabled, danger, className, style, chi
78
78
  children: ReactNode;
79
79
  }): react_jsx_runtime.JSX.Element;
80
80
 
81
+ type VrmVerifiedTier = 'verified' | 'identified' | 'anonymous' | 'stale' | 'inactive';
82
+ declare const VRM_VERIFIED_TOOLTIP = "Politogy has confirmed this is a real, registered voter.";
83
+ declare const VRM_TIER_LABELS: Record<VrmVerifiedTier, string>;
84
+ interface VrmVerifiedBadgeProps {
85
+ /** The person's tier; null draws "Not yet computed". */
86
+ tier: VrmVerifiedTier | null | undefined;
87
+ /**
88
+ * `pill` (default): a dot and the tier name. `icon`: the Brand verifiedIcon
89
+ * alone, for a contact view's name line; renders nothing unless Verified.
90
+ */
91
+ variant?: 'pill' | 'icon';
92
+ /** Icon / dot size in px. Default 16 (icon) / 8 (dot). */
93
+ size?: number;
94
+ /** Pill only: show the tier name beside the dot. Default true. */
95
+ showLabel?: boolean;
96
+ className?: string;
97
+ style?: CSSProperties;
98
+ }
99
+ declare function VrmVerifiedBadge({ tier, variant, size, showLabel, className, style }: VrmVerifiedBadgeProps): react_jsx_runtime.JSX.Element | null;
100
+
101
+ declare const CONTACTS_ORIGIN = "https://contacts.politogyvrm.com";
102
+ interface ContactSlideInProps {
103
+ /** UVP id to show; null keeps the panel closed. */
104
+ contactId: string | null;
105
+ /** The active organization's id (full uuid), passed to Contacts as `?org=`. */
106
+ orgId?: string | null;
107
+ onClose: () => void;
108
+ /** Contacts origin. Default https://contacts.politogyvrm.com. */
109
+ contactsOrigin?: string;
110
+ }
111
+ /** The chrome-less Card view the panel frames. */
112
+ declare function contactEmbedUrl(contactId: string, orgId?: string | null, origin?: string): string;
113
+ /** The Card's full page in Contacts ("Open in Contacts"). */
114
+ declare function contactPageUrl(contactId: string, orgId?: string | null, origin?: string): string;
115
+ declare function ContactSlideIn({ contactId, orgId, onClose, contactsOrigin }: ContactSlideInProps): react_jsx_runtime.JSX.Element | null;
116
+ /**
117
+ * Panel state for any page that lists contacts:
118
+ *
119
+ * const slideIn = useContactSlideIn()
120
+ * <button onClick={() => slideIn.open(row.uvpId)}>Open contact</button>
121
+ * <ContactSlideIn contactId={slideIn.contactId} orgId={orgId} onClose={slideIn.close} />
122
+ */
123
+ declare function useContactSlideIn(): {
124
+ contactId: string | null;
125
+ open: (id: string) => void;
126
+ close: () => void;
127
+ };
128
+
81
129
  type FormColumnProps = {
82
130
  children: ReactNode;
83
131
  className?: string;
@@ -1288,4 +1336,4 @@ type NavAppShellProps = {
1288
1336
  };
1289
1337
  declare function NavAppShell({ sidebar, topBar, betaBanner, contentWrapper, accountMenuPlacement, modeId, children, }: NavAppShellProps): react_jsx_runtime.JSX.Element;
1290
1338
 
1291
- export { type CreditHealthState as $, AI_CREDITS_STATE_TITLES as A, type BreadcrumbBarProps as B, Card as C, BETA_BANNER_DISMISS_KEY as D, BreadcrumbBar as E, FormColumn as F, CAMPAIGN_FEATURE_AVAILABILITY as G, HeaderTabBar as H, CORE_APP_ORIGIN as I, CORE_BILLING_PATH as J, KNOWN_TAB_GLYPHS as K, CREDIT_TYPE_LABELS as L, CREDIT_TYPE_ORDER as M, type NavItem as N, type CampaignFeatureAvailability as O, type PageHeaderProps as P, type ChromeMe as Q, RowMenu as R, type StandardNavIconKey as S, type TabGlyphComponent as T, type ChromeNotificationAlert as U, type ChromeNotificationImport as V, type ChromeNotificationQuarantine as W, type ChromeNotificationReply as X, type ChromeNotificationsPayload as Y, type ChromeOrgSummary as Z, type CommunicationsFuelStatus as _, AiCreditsState as a, useNavChromeFetcher as a$, type CreditTypeKey as a0, CreditsAction as a1, type CreditsIconState as a2, FuelAction as a3, type FuelChannelStatus as a4, MyProfileAction as a5, NavAppShell as a6, type NavAppShellProps as a7, NavBetaBanner as a8, type NavBetaBannerProps as a9, type ThemePreference as aA, TopBarCountBadge as aB, type TopBarIconTone as aC, TopBarLinkAction as aD, type TopBarLinkActionProps as aE, TopBarPanelArrow as aF, TopBarPopover as aG, TopBarTooltip as aH, TopBarWidgetSlot as aI, buildLineParts as aJ, clearBetaBannerDismissal as aK, creditGaugeRatio as aL, creditStateWord as aM, creditTooltipLine as aN, creditsAriaLabel as aO, creditsIconState as aP, envChipClasses as aQ, isNavItemActive as aR, modeIdFromLabel as aS, resolveOrgLogoUrl as aT, shortEnvLabel as aU, shortUserName as aV, standardPolitogyNav as aW, topBarIconButtonClass as aX, useChromeMe as aY, useChromeOrgs as aZ, useNavChromeDedupedFetch as a_, type NavBrand as aa, NavChromeProvider as ab, NavDisplayAction as ac, type NavLinkProps as ad, type NavLinkedAccount as ae, type NavModeOption as af, type NavOrg as ag, type NavRoleBadge as ah, NavSidebar as ai, type NavSidebarProps as aj, type NavTab as ak, NavTabStrip as al, type NavTabStripProps as am, NavThemeControl as an, NavTopBar as ao, type NavTopBarAction as ap, type NavTopBarProps as aq, type NavUser as ar, NotificationsAction as as, OrganizationSettingsAction as at, PageHeader as au, type PageHeaderMode as av, SPECS_ORIGIN as aw, SpecOverlayAction as ax, type StandardNavOptions as ay, SupportAction as az, type AiCreditsStateKind as b, useThemePreference as b0, type CommsNotification as c, type CommsNotificationKind as d, type HeaderTabBarItem as e, type NotificationsAdapter as f, type NotificationsFeed as g, RowMenuItem as h, type RowMenuPlacement as i, aiCreditsWalletUrl as j, createCommsNotificationsAdapter as k, emptyNotificationsFeed as l, rowMenuPosition as m, normalizeNotificationsFeed as n, type NavIcon as o, type NavBreadcrumb as p, type StandardNavMode as q, resolveTabGlyph as r, type NavLinkComponent as s, type NavChromeFetcher as t, type NavMode as u, type NavUserMenu as v, type NavOrgOption as w, type NavFooterLink as x, type NavFooter as y, type NavDisplayMode as z };
1339
+ export { CREDIT_TYPE_LABELS as $, AI_CREDITS_STATE_TITLES as A, type BreadcrumbBarProps as B, CONTACTS_ORIGIN as C, type NavBreadcrumb as D, type StandardNavMode as E, FormColumn as F, type NavLinkComponent as G, HeaderTabBar as H, type NavChromeFetcher as I, type NavMode as J, KNOWN_TAB_GLYPHS as K, type NavUserMenu as L, type NavOrgOption as M, type NavItem as N, type NavFooterLink as O, type PageHeaderProps as P, type NavFooter as Q, RowMenu as R, type StandardNavIconKey as S, type TabGlyphComponent as T, type NavDisplayMode as U, VRM_TIER_LABELS as V, BETA_BANNER_DISMISS_KEY as W, BreadcrumbBar as X, CAMPAIGN_FEATURE_AVAILABILITY as Y, CORE_APP_ORIGIN as Z, CORE_BILLING_PATH as _, AiCreditsState as a, envChipClasses as a$, CREDIT_TYPE_ORDER as a0, type CampaignFeatureAvailability as a1, type ChromeMe as a2, type ChromeNotificationAlert as a3, type ChromeNotificationImport as a4, type ChromeNotificationQuarantine as a5, type ChromeNotificationReply as a6, type ChromeNotificationsPayload as a7, type ChromeOrgSummary as a8, type CommunicationsFuelStatus as a9, type NavTopBarAction as aA, type NavTopBarProps as aB, type NavUser as aC, NotificationsAction as aD, OrganizationSettingsAction as aE, PageHeader as aF, type PageHeaderMode as aG, SPECS_ORIGIN as aH, SpecOverlayAction as aI, type StandardNavOptions as aJ, SupportAction as aK, type ThemePreference as aL, TopBarCountBadge as aM, type TopBarIconTone as aN, TopBarLinkAction as aO, type TopBarLinkActionProps as aP, TopBarPanelArrow as aQ, TopBarPopover as aR, TopBarTooltip as aS, TopBarWidgetSlot as aT, buildLineParts as aU, clearBetaBannerDismissal as aV, creditGaugeRatio as aW, creditStateWord as aX, creditTooltipLine as aY, creditsAriaLabel as aZ, creditsIconState as a_, type CreditHealthState as aa, type CreditTypeKey as ab, CreditsAction as ac, type CreditsIconState as ad, FuelAction as ae, type FuelChannelStatus as af, MyProfileAction as ag, NavAppShell as ah, type NavAppShellProps as ai, NavBetaBanner as aj, type NavBetaBannerProps as ak, type NavBrand as al, NavChromeProvider as am, NavDisplayAction as an, type NavLinkProps as ao, type NavLinkedAccount as ap, type NavModeOption as aq, type NavOrg as ar, type NavRoleBadge as as, NavSidebar as at, type NavSidebarProps as au, type NavTab as av, NavTabStrip as aw, type NavTabStripProps as ax, NavThemeControl as ay, NavTopBar as az, type AiCreditsStateKind as b, isNavItemActive as b0, modeIdFromLabel as b1, resolveOrgLogoUrl as b2, shortEnvLabel as b3, shortUserName as b4, standardPolitogyNav as b5, topBarIconButtonClass as b6, useChromeMe as b7, useChromeOrgs as b8, useNavChromeDedupedFetch as b9, useNavChromeFetcher as ba, useThemePreference as bb, Card as c, type CommsNotification as d, type CommsNotificationKind as e, ContactSlideIn as f, type ContactSlideInProps as g, type HeaderTabBarItem as h, type NotificationsAdapter as i, type NotificationsFeed as j, RowMenuItem as k, type RowMenuPlacement as l, VRM_VERIFIED_TOOLTIP as m, VrmVerifiedBadge as n, type VrmVerifiedBadgeProps as o, type VrmVerifiedTier as p, aiCreditsWalletUrl as q, contactEmbedUrl as r, contactPageUrl as s, createCommsNotificationsAdapter as t, emptyNotificationsFeed as u, normalizeNotificationsFeed as v, resolveTabGlyph as w, rowMenuPosition as x, useContactSlideIn as y, type NavIcon as z };
@@ -78,6 +78,54 @@ declare function RowMenuItem({ onSelect, disabled, danger, className, style, chi
78
78
  children: ReactNode;
79
79
  }): react_jsx_runtime.JSX.Element;
80
80
 
81
+ type VrmVerifiedTier = 'verified' | 'identified' | 'anonymous' | 'stale' | 'inactive';
82
+ declare const VRM_VERIFIED_TOOLTIP = "Politogy has confirmed this is a real, registered voter.";
83
+ declare const VRM_TIER_LABELS: Record<VrmVerifiedTier, string>;
84
+ interface VrmVerifiedBadgeProps {
85
+ /** The person's tier; null draws "Not yet computed". */
86
+ tier: VrmVerifiedTier | null | undefined;
87
+ /**
88
+ * `pill` (default): a dot and the tier name. `icon`: the Brand verifiedIcon
89
+ * alone, for a contact view's name line; renders nothing unless Verified.
90
+ */
91
+ variant?: 'pill' | 'icon';
92
+ /** Icon / dot size in px. Default 16 (icon) / 8 (dot). */
93
+ size?: number;
94
+ /** Pill only: show the tier name beside the dot. Default true. */
95
+ showLabel?: boolean;
96
+ className?: string;
97
+ style?: CSSProperties;
98
+ }
99
+ declare function VrmVerifiedBadge({ tier, variant, size, showLabel, className, style }: VrmVerifiedBadgeProps): react_jsx_runtime.JSX.Element | null;
100
+
101
+ declare const CONTACTS_ORIGIN = "https://contacts.politogyvrm.com";
102
+ interface ContactSlideInProps {
103
+ /** UVP id to show; null keeps the panel closed. */
104
+ contactId: string | null;
105
+ /** The active organization's id (full uuid), passed to Contacts as `?org=`. */
106
+ orgId?: string | null;
107
+ onClose: () => void;
108
+ /** Contacts origin. Default https://contacts.politogyvrm.com. */
109
+ contactsOrigin?: string;
110
+ }
111
+ /** The chrome-less Card view the panel frames. */
112
+ declare function contactEmbedUrl(contactId: string, orgId?: string | null, origin?: string): string;
113
+ /** The Card's full page in Contacts ("Open in Contacts"). */
114
+ declare function contactPageUrl(contactId: string, orgId?: string | null, origin?: string): string;
115
+ declare function ContactSlideIn({ contactId, orgId, onClose, contactsOrigin }: ContactSlideInProps): react_jsx_runtime.JSX.Element | null;
116
+ /**
117
+ * Panel state for any page that lists contacts:
118
+ *
119
+ * const slideIn = useContactSlideIn()
120
+ * <button onClick={() => slideIn.open(row.uvpId)}>Open contact</button>
121
+ * <ContactSlideIn contactId={slideIn.contactId} orgId={orgId} onClose={slideIn.close} />
122
+ */
123
+ declare function useContactSlideIn(): {
124
+ contactId: string | null;
125
+ open: (id: string) => void;
126
+ close: () => void;
127
+ };
128
+
81
129
  type FormColumnProps = {
82
130
  children: ReactNode;
83
131
  className?: string;
@@ -1288,4 +1336,4 @@ type NavAppShellProps = {
1288
1336
  };
1289
1337
  declare function NavAppShell({ sidebar, topBar, betaBanner, contentWrapper, accountMenuPlacement, modeId, children, }: NavAppShellProps): react_jsx_runtime.JSX.Element;
1290
1338
 
1291
- export { type CreditHealthState as $, AI_CREDITS_STATE_TITLES as A, type BreadcrumbBarProps as B, Card as C, BETA_BANNER_DISMISS_KEY as D, BreadcrumbBar as E, FormColumn as F, CAMPAIGN_FEATURE_AVAILABILITY as G, HeaderTabBar as H, CORE_APP_ORIGIN as I, CORE_BILLING_PATH as J, KNOWN_TAB_GLYPHS as K, CREDIT_TYPE_LABELS as L, CREDIT_TYPE_ORDER as M, type NavItem as N, type CampaignFeatureAvailability as O, type PageHeaderProps as P, type ChromeMe as Q, RowMenu as R, type StandardNavIconKey as S, type TabGlyphComponent as T, type ChromeNotificationAlert as U, type ChromeNotificationImport as V, type ChromeNotificationQuarantine as W, type ChromeNotificationReply as X, type ChromeNotificationsPayload as Y, type ChromeOrgSummary as Z, type CommunicationsFuelStatus as _, AiCreditsState as a, useNavChromeFetcher as a$, type CreditTypeKey as a0, CreditsAction as a1, type CreditsIconState as a2, FuelAction as a3, type FuelChannelStatus as a4, MyProfileAction as a5, NavAppShell as a6, type NavAppShellProps as a7, NavBetaBanner as a8, type NavBetaBannerProps as a9, type ThemePreference as aA, TopBarCountBadge as aB, type TopBarIconTone as aC, TopBarLinkAction as aD, type TopBarLinkActionProps as aE, TopBarPanelArrow as aF, TopBarPopover as aG, TopBarTooltip as aH, TopBarWidgetSlot as aI, buildLineParts as aJ, clearBetaBannerDismissal as aK, creditGaugeRatio as aL, creditStateWord as aM, creditTooltipLine as aN, creditsAriaLabel as aO, creditsIconState as aP, envChipClasses as aQ, isNavItemActive as aR, modeIdFromLabel as aS, resolveOrgLogoUrl as aT, shortEnvLabel as aU, shortUserName as aV, standardPolitogyNav as aW, topBarIconButtonClass as aX, useChromeMe as aY, useChromeOrgs as aZ, useNavChromeDedupedFetch as a_, type NavBrand as aa, NavChromeProvider as ab, NavDisplayAction as ac, type NavLinkProps as ad, type NavLinkedAccount as ae, type NavModeOption as af, type NavOrg as ag, type NavRoleBadge as ah, NavSidebar as ai, type NavSidebarProps as aj, type NavTab as ak, NavTabStrip as al, type NavTabStripProps as am, NavThemeControl as an, NavTopBar as ao, type NavTopBarAction as ap, type NavTopBarProps as aq, type NavUser as ar, NotificationsAction as as, OrganizationSettingsAction as at, PageHeader as au, type PageHeaderMode as av, SPECS_ORIGIN as aw, SpecOverlayAction as ax, type StandardNavOptions as ay, SupportAction as az, type AiCreditsStateKind as b, useThemePreference as b0, type CommsNotification as c, type CommsNotificationKind as d, type HeaderTabBarItem as e, type NotificationsAdapter as f, type NotificationsFeed as g, RowMenuItem as h, type RowMenuPlacement as i, aiCreditsWalletUrl as j, createCommsNotificationsAdapter as k, emptyNotificationsFeed as l, rowMenuPosition as m, normalizeNotificationsFeed as n, type NavIcon as o, type NavBreadcrumb as p, type StandardNavMode as q, resolveTabGlyph as r, type NavLinkComponent as s, type NavChromeFetcher as t, type NavMode as u, type NavUserMenu as v, type NavOrgOption as w, type NavFooterLink as x, type NavFooter as y, type NavDisplayMode as z };
1339
+ export { CREDIT_TYPE_LABELS as $, AI_CREDITS_STATE_TITLES as A, type BreadcrumbBarProps as B, CONTACTS_ORIGIN as C, type NavBreadcrumb as D, type StandardNavMode as E, FormColumn as F, type NavLinkComponent as G, HeaderTabBar as H, type NavChromeFetcher as I, type NavMode as J, KNOWN_TAB_GLYPHS as K, type NavUserMenu as L, type NavOrgOption as M, type NavItem as N, type NavFooterLink as O, type PageHeaderProps as P, type NavFooter as Q, RowMenu as R, type StandardNavIconKey as S, type TabGlyphComponent as T, type NavDisplayMode as U, VRM_TIER_LABELS as V, BETA_BANNER_DISMISS_KEY as W, BreadcrumbBar as X, CAMPAIGN_FEATURE_AVAILABILITY as Y, CORE_APP_ORIGIN as Z, CORE_BILLING_PATH as _, AiCreditsState as a, envChipClasses as a$, CREDIT_TYPE_ORDER as a0, type CampaignFeatureAvailability as a1, type ChromeMe as a2, type ChromeNotificationAlert as a3, type ChromeNotificationImport as a4, type ChromeNotificationQuarantine as a5, type ChromeNotificationReply as a6, type ChromeNotificationsPayload as a7, type ChromeOrgSummary as a8, type CommunicationsFuelStatus as a9, type NavTopBarAction as aA, type NavTopBarProps as aB, type NavUser as aC, NotificationsAction as aD, OrganizationSettingsAction as aE, PageHeader as aF, type PageHeaderMode as aG, SPECS_ORIGIN as aH, SpecOverlayAction as aI, type StandardNavOptions as aJ, SupportAction as aK, type ThemePreference as aL, TopBarCountBadge as aM, type TopBarIconTone as aN, TopBarLinkAction as aO, type TopBarLinkActionProps as aP, TopBarPanelArrow as aQ, TopBarPopover as aR, TopBarTooltip as aS, TopBarWidgetSlot as aT, buildLineParts as aU, clearBetaBannerDismissal as aV, creditGaugeRatio as aW, creditStateWord as aX, creditTooltipLine as aY, creditsAriaLabel as aZ, creditsIconState as a_, type CreditHealthState as aa, type CreditTypeKey as ab, CreditsAction as ac, type CreditsIconState as ad, FuelAction as ae, type FuelChannelStatus as af, MyProfileAction as ag, NavAppShell as ah, type NavAppShellProps as ai, NavBetaBanner as aj, type NavBetaBannerProps as ak, type NavBrand as al, NavChromeProvider as am, NavDisplayAction as an, type NavLinkProps as ao, type NavLinkedAccount as ap, type NavModeOption as aq, type NavOrg as ar, type NavRoleBadge as as, NavSidebar as at, type NavSidebarProps as au, type NavTab as av, NavTabStrip as aw, type NavTabStripProps as ax, NavThemeControl as ay, NavTopBar as az, type AiCreditsStateKind as b, isNavItemActive as b0, modeIdFromLabel as b1, resolveOrgLogoUrl as b2, shortEnvLabel as b3, shortUserName as b4, standardPolitogyNav as b5, topBarIconButtonClass as b6, useChromeMe as b7, useChromeOrgs as b8, useNavChromeDedupedFetch as b9, useNavChromeFetcher as ba, useThemePreference as bb, Card as c, type CommsNotification as d, type CommsNotificationKind as e, ContactSlideIn as f, type ContactSlideInProps as g, type HeaderTabBarItem as h, type NotificationsAdapter as i, type NotificationsFeed as j, RowMenuItem as k, type RowMenuPlacement as l, VRM_VERIFIED_TOOLTIP as m, VrmVerifiedBadge as n, type VrmVerifiedBadgeProps as o, type VrmVerifiedTier as p, aiCreditsWalletUrl as q, contactEmbedUrl as r, contactPageUrl as s, createCommsNotificationsAdapter as t, emptyNotificationsFeed as u, normalizeNotificationsFeed as v, resolveTabGlyph as w, rowMenuPosition as x, useContactSlideIn as y, type NavIcon as z };
package/dist/index.cjs CHANGED
@@ -1172,6 +1172,297 @@ function RowMenuItem({
1172
1172
  }
1173
1173
  );
1174
1174
  }
1175
+ function parseCssUrl(value) {
1176
+ if (!value) return null;
1177
+ const m = /^url\(\s*(['"]?)(.*?)\1\s*\)$/i.exec(value.trim());
1178
+ const url = m?.[2]?.trim();
1179
+ return url && /^https:\/\//i.test(url) ? url : null;
1180
+ }
1181
+ function readBrandAsset(kind) {
1182
+ if (typeof document === "undefined") return null;
1183
+ try {
1184
+ return parseCssUrl(
1185
+ window.getComputedStyle(document.documentElement).getPropertyValue(`--asset-${kind}`)
1186
+ );
1187
+ } catch {
1188
+ return null;
1189
+ }
1190
+ }
1191
+ var RETRY_MS = [0, 250, 1e3, 3e3];
1192
+ function useBrandAsset(kind) {
1193
+ const [url, setUrl] = react$1.useState(null);
1194
+ react$1.useEffect(() => {
1195
+ let done = false;
1196
+ const read = () => {
1197
+ if (done) return;
1198
+ const next = readBrandAsset(kind);
1199
+ setUrl((prev) => prev === next ? prev : next);
1200
+ };
1201
+ const links = Array.from(
1202
+ document.querySelectorAll('link[rel="stylesheet"][href*="api/tokens"]')
1203
+ );
1204
+ links.forEach((l) => l.addEventListener("load", read));
1205
+ const timers = RETRY_MS.map((ms) => window.setTimeout(read, ms));
1206
+ read();
1207
+ return () => {
1208
+ done = true;
1209
+ links.forEach((l) => l.removeEventListener("load", read));
1210
+ timers.forEach((t) => window.clearTimeout(t));
1211
+ };
1212
+ }, [kind]);
1213
+ return url;
1214
+ }
1215
+ var VRM_VERIFIED_TOOLTIP = "Politogy has confirmed this is a real, registered voter.";
1216
+ var VRM_TIER_LABELS = {
1217
+ verified: "VRM Verified",
1218
+ identified: "Identified",
1219
+ anonymous: "Anonymous",
1220
+ stale: "Stale",
1221
+ inactive: "Inactive"
1222
+ };
1223
+ var TIER_TOOLTIPS = {
1224
+ verified: VRM_VERIFIED_TOOLTIP,
1225
+ identified: "Identified: we know who this is, but Politogy has not verified them.",
1226
+ anonymous: "Anonymous: nothing identifying has been captured yet.",
1227
+ stale: "Stale: was VRM Verified, but the proof is more than 12 months old.",
1228
+ inactive: "Inactive: the voter file marks this registration inactive or canceled."
1229
+ };
1230
+ var DOT_FALLBACK = {
1231
+ verified: "#00A651",
1232
+ identified: "#a855f7",
1233
+ anonymous: "var(--color-graphite, #2b2b2b)",
1234
+ stale: "#eab308",
1235
+ inactive: "var(--muted, #8a8a8a)"
1236
+ };
1237
+ function VrmVerifiedBadge({ tier, variant = "pill", size, showLabel = true, className, style }) {
1238
+ const known = tier && tier in VRM_TIER_LABELS ? tier : null;
1239
+ if (variant === "icon") {
1240
+ return known === "verified" ? /* @__PURE__ */ jsxRuntime.jsx(VerifiedIcon, { size: size ?? 16, className, style }) : null;
1241
+ }
1242
+ const label = known ? VRM_TIER_LABELS[known] : "Not yet computed";
1243
+ const title = known ? TIER_TOOLTIPS[known] : "The VRM Verified tier has not been worked out yet.";
1244
+ const dotSize = size ?? 8;
1245
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1246
+ "span",
1247
+ {
1248
+ "data-vrm-tier": known ?? "none",
1249
+ title,
1250
+ "aria-label": showLabel ? void 0 : label,
1251
+ role: showLabel ? void 0 : "img",
1252
+ className,
1253
+ style: {
1254
+ display: "inline-flex",
1255
+ alignItems: "center",
1256
+ gap: 6,
1257
+ borderRadius: 9999,
1258
+ border: "1px solid var(--line, #e5e5e5)",
1259
+ padding: "2px 10px",
1260
+ fontSize: 12,
1261
+ fontWeight: 600,
1262
+ lineHeight: 1.4,
1263
+ whiteSpace: "nowrap",
1264
+ ...style
1265
+ },
1266
+ children: [
1267
+ /* @__PURE__ */ jsxRuntime.jsx(
1268
+ "span",
1269
+ {
1270
+ "aria-hidden": true,
1271
+ "data-vrm-dot": true,
1272
+ style: {
1273
+ display: "inline-block",
1274
+ width: dotSize,
1275
+ height: dotSize,
1276
+ borderRadius: 9999,
1277
+ flexShrink: 0,
1278
+ background: known ? `var(--vrm-tier-${known}, ${DOT_FALLBACK[known]})` : "transparent",
1279
+ border: known ? void 0 : "1px dashed var(--muted, #8a8a8a)"
1280
+ }
1281
+ }
1282
+ ),
1283
+ showLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
1284
+ ]
1285
+ }
1286
+ );
1287
+ }
1288
+ function VerifiedIcon({ size, className, style }) {
1289
+ const icon = useBrandAsset("verified-icon");
1290
+ return (
1291
+ // The box is reserved while the Brand sheet loads; nothing stands in.
1292
+ /* @__PURE__ */ jsxRuntime.jsx(
1293
+ "span",
1294
+ {
1295
+ "data-vrm-tier": "verified",
1296
+ "data-vrm-variant": "icon",
1297
+ role: "img",
1298
+ "aria-label": VRM_TIER_LABELS.verified,
1299
+ title: VRM_VERIFIED_TOOLTIP,
1300
+ className,
1301
+ style: { display: "inline-block", width: size, height: size, flexShrink: 0, verticalAlign: "middle", ...style },
1302
+ children: icon ? /* @__PURE__ */ jsxRuntime.jsx(
1303
+ "img",
1304
+ {
1305
+ src: icon,
1306
+ alt: "",
1307
+ width: size,
1308
+ height: size,
1309
+ draggable: false,
1310
+ "data-testid": "vrm-verified-icon",
1311
+ style: { display: "block", width: size, height: size }
1312
+ }
1313
+ ) : null
1314
+ }
1315
+ )
1316
+ );
1317
+ }
1318
+ var CONTACTS_ORIGIN = "https://contacts.politogyvrm.com";
1319
+ function withOrg(path, orgId) {
1320
+ return orgId ? `${path}?org=${encodeURIComponent(orgId)}` : path;
1321
+ }
1322
+ function contactEmbedUrl(contactId, orgId, origin = CONTACTS_ORIGIN) {
1323
+ return withOrg(`${origin}/contacts/embed/${encodeURIComponent(contactId)}`, orgId);
1324
+ }
1325
+ function contactPageUrl(contactId, orgId, origin = CONTACTS_ORIGIN) {
1326
+ return withOrg(`${origin}/contacts/${encodeURIComponent(contactId)}`, orgId);
1327
+ }
1328
+ function prefersReducedMotion() {
1329
+ try {
1330
+ return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
1331
+ } catch {
1332
+ return false;
1333
+ }
1334
+ }
1335
+ var iconButton = {
1336
+ display: "inline-flex",
1337
+ alignItems: "center",
1338
+ justifyContent: "center",
1339
+ borderRadius: 9999,
1340
+ border: "1px solid var(--line, #d7dadf)",
1341
+ padding: 6,
1342
+ background: "transparent",
1343
+ color: "var(--muted, #5c6b80)",
1344
+ cursor: "pointer"
1345
+ };
1346
+ function ContactSlideIn({ contactId, orgId, onClose, contactsOrigin = CONTACTS_ORIGIN }) {
1347
+ const [shown, setShown] = react$1.useState(false);
1348
+ react$1.useEffect(() => {
1349
+ if (!contactId) {
1350
+ setShown(false);
1351
+ return;
1352
+ }
1353
+ if (prefersReducedMotion()) {
1354
+ setShown(true);
1355
+ return;
1356
+ }
1357
+ const id = requestAnimationFrame(() => setShown(true));
1358
+ return () => cancelAnimationFrame(id);
1359
+ }, [contactId]);
1360
+ react$1.useEffect(() => {
1361
+ if (!contactId) return;
1362
+ const onKey = (event) => {
1363
+ if (event.key === "Escape") onClose();
1364
+ };
1365
+ document.addEventListener("keydown", onKey);
1366
+ return () => document.removeEventListener("keydown", onKey);
1367
+ }, [contactId, onClose]);
1368
+ if (!contactId) return null;
1369
+ return /* @__PURE__ */ jsxRuntime.jsx(
1370
+ "div",
1371
+ {
1372
+ "data-testid": "contact-slide-in-overlay",
1373
+ onClick: onClose,
1374
+ style: { position: "fixed", inset: 0, zIndex: 60, background: "rgba(0, 0, 0, 0.4)" },
1375
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
1376
+ "aside",
1377
+ {
1378
+ role: "dialog",
1379
+ "aria-modal": "true",
1380
+ "aria-label": "Contact card",
1381
+ "data-testid": "contact-slide-in",
1382
+ onClick: (event) => event.stopPropagation(),
1383
+ style: {
1384
+ position: "absolute",
1385
+ top: 0,
1386
+ right: 0,
1387
+ bottom: 0,
1388
+ width: "100%",
1389
+ maxWidth: 672,
1390
+ display: "flex",
1391
+ flexDirection: "column",
1392
+ background: "var(--panel, #ffffff)",
1393
+ color: "var(--foreground, #2f3136)",
1394
+ borderLeft: "1px solid var(--line, #d7dadf)",
1395
+ boxShadow: "var(--shadow-soft, 0 10px 28px rgba(27, 28, 32, 0.14))",
1396
+ transform: shown ? "translateX(0)" : "translateX(100%)",
1397
+ transition: "transform 220ms cubic-bezier(0.16, 1, 0.3, 1)"
1398
+ },
1399
+ children: [
1400
+ /* @__PURE__ */ jsxRuntime.jsxs(
1401
+ "div",
1402
+ {
1403
+ style: {
1404
+ display: "flex",
1405
+ alignItems: "center",
1406
+ justifyContent: "space-between",
1407
+ gap: 12,
1408
+ borderBottom: "1px solid var(--line, #d7dadf)",
1409
+ padding: "12px 24px"
1410
+ },
1411
+ children: [
1412
+ /* @__PURE__ */ jsxRuntime.jsx(
1413
+ "p",
1414
+ {
1415
+ style: {
1416
+ margin: 0,
1417
+ fontSize: 12,
1418
+ fontWeight: 600,
1419
+ letterSpacing: "0.18em",
1420
+ textTransform: "uppercase",
1421
+ color: "var(--muted, #5c6b80)"
1422
+ },
1423
+ children: "Contact Card"
1424
+ }
1425
+ ),
1426
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
1427
+ /* @__PURE__ */ jsxRuntime.jsx(
1428
+ "a",
1429
+ {
1430
+ href: contactPageUrl(contactId, orgId, contactsOrigin),
1431
+ target: "_top",
1432
+ style: { fontSize: 13, fontWeight: 600, color: "var(--color-race-blue-500, #007bff)", textDecoration: "none" },
1433
+ children: "Open in Contacts"
1434
+ }
1435
+ ),
1436
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Close contact card", title: "Close", onClick: onClose, style: iconButton, children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": true, width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
1437
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
1438
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
1439
+ ] }) })
1440
+ ] })
1441
+ ]
1442
+ }
1443
+ ),
1444
+ /* @__PURE__ */ jsxRuntime.jsx(
1445
+ "iframe",
1446
+ {
1447
+ title: "Contact card",
1448
+ src: contactEmbedUrl(contactId, orgId, contactsOrigin),
1449
+ "data-testid": "contact-slide-in-frame",
1450
+ style: { flex: 1, minHeight: 0, width: "100%", border: 0, background: "var(--panel, #ffffff)" }
1451
+ },
1452
+ contactId
1453
+ )
1454
+ ]
1455
+ }
1456
+ )
1457
+ }
1458
+ );
1459
+ }
1460
+ function useContactSlideIn() {
1461
+ const [contactId, setContactId] = react$1.useState(null);
1462
+ const open = react$1.useCallback((id) => setContactId(id), []);
1463
+ const close = react$1.useCallback(() => setContactId(null), []);
1464
+ return { contactId, open, close };
1465
+ }
1175
1466
  function FormColumn({ children, className }) {
1176
1467
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-shell-form-column": "", className: clsx5__default.default("w-full max-w-[960px]", className), children });
1177
1468
  }
@@ -1926,24 +2217,6 @@ function BrandIcon({
1926
2217
  }
1927
2218
  );
1928
2219
  }
1929
- function parseCssUrl(value) {
1930
- if (!value) return null;
1931
- const m = /^url\(\s*(['"]?)(.*?)\1\s*\)$/i.exec(value.trim());
1932
- const url = m?.[2]?.trim();
1933
- return url && /^https:\/\//i.test(url) ? url : null;
1934
- }
1935
- function readBrandAsset(kind) {
1936
- if (typeof document === "undefined") return null;
1937
- try {
1938
- return parseCssUrl(
1939
- window.getComputedStyle(document.documentElement).getPropertyValue(`--asset-${kind}`)
1940
- );
1941
- } catch {
1942
- return null;
1943
- }
1944
- }
1945
-
1946
- // src/lib/brandFavicon.ts
1947
2220
  var BRAND_FAVICON_LINK_ID = "politogy-brand-favicon";
1948
2221
  var BRAND_APPLE_ICON_LINK_ID = "politogy-brand-apple-icon";
1949
2222
  function upsertLink(id, rel, href) {
@@ -1966,7 +2239,7 @@ function applyBrandFavicon() {
1966
2239
  if (apple) upsertLink(BRAND_APPLE_ICON_LINK_ID, "apple-touch-icon", apple);
1967
2240
  return true;
1968
2241
  }
1969
- var RETRY_MS = [0, 250, 1e3, 3e3];
2242
+ var RETRY_MS2 = [0, 250, 1e3, 3e3];
1970
2243
  function watchBrandFavicon() {
1971
2244
  if (typeof document === "undefined") return () => {
1972
2245
  };
@@ -1983,7 +2256,7 @@ function watchBrandFavicon() {
1983
2256
  });
1984
2257
  };
1985
2258
  listen();
1986
- const timers = RETRY_MS.map((ms) => window.setTimeout(apply, ms));
2259
+ const timers = RETRY_MS2.map((ms) => window.setTimeout(apply, ms));
1987
2260
  const observer = typeof MutationObserver === "undefined" ? null : new MutationObserver(() => {
1988
2261
  listen();
1989
2262
  apply();
@@ -2306,7 +2579,9 @@ exports.BrandFavicon = BrandFavicon;
2306
2579
  exports.BrandIcon = BrandIcon;
2307
2580
  exports.BrandLogo = BrandLogo;
2308
2581
  exports.BreadcrumbBar = BreadcrumbBar;
2582
+ exports.CONTACTS_ORIGIN = CONTACTS_ORIGIN;
2309
2583
  exports.Card = Card;
2584
+ exports.ContactSlideIn = ContactSlideIn;
2310
2585
  exports.FormColumn = FormColumn;
2311
2586
  exports.GlobalUiIdProvider = GlobalUiIdProvider;
2312
2587
  exports.HeaderTabBar = HeaderTabBar;
@@ -2326,11 +2601,16 @@ exports.ShellProvider = ShellProvider;
2326
2601
  exports.ShellRoleContext = ShellRoleContext;
2327
2602
  exports.ShellSupportProviderContext = ShellSupportProviderContext;
2328
2603
  exports.SpeculationRulesScript = SpeculationRulesScript;
2604
+ exports.VRM_TIER_LABELS = VRM_TIER_LABELS;
2605
+ exports.VRM_VERIFIED_TOOLTIP = VRM_VERIFIED_TOOLTIP;
2606
+ exports.VrmVerifiedBadge = VrmVerifiedBadge;
2329
2607
  exports.aiCreditsWalletUrl = aiCreditsWalletUrl;
2330
2608
  exports.applyBrandFavicon = applyBrandFavicon;
2331
2609
  exports.buildNavSpeculationRules = buildNavSpeculationRules;
2332
2610
  exports.buildSpeculationRules = buildSpeculationRules;
2333
2611
  exports.collectSiblingAppUrls = collectSiblingAppUrls;
2612
+ exports.contactEmbedUrl = contactEmbedUrl;
2613
+ exports.contactPageUrl = contactPageUrl;
2334
2614
  exports.createCommsNotificationsAdapter = createCommsNotificationsAdapter;
2335
2615
  exports.emptyNotificationsFeed = emptyNotificationsFeed;
2336
2616
  exports.getOrganizationBadgeLetters = getOrganizationBadgeLetters;
@@ -2345,6 +2625,7 @@ exports.registerShellPrecache = registerShellPrecache;
2345
2625
  exports.resolveTabGlyph = resolveTabGlyph;
2346
2626
  exports.rowMenuPosition = rowMenuPosition;
2347
2627
  exports.useAppRegistry = useAppRegistry;
2628
+ exports.useContactSlideIn = useContactSlideIn;
2348
2629
  exports.useCurrentApp = useCurrentApp;
2349
2630
  exports.useShellAuth = useShellAuth;
2350
2631
  exports.useShellChrome = useShellChrome;