@the-portland-company/shell 0.76.15 → 0.77.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.
@@ -0,0 +1,990 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType, CSSProperties } from 'react';
3
+ import { ThemePreference as ThemePreference$1 } from './theme-preference.cjs';
4
+
5
+ type FormColumnProps = {
6
+ children: ReactNode;
7
+ className?: string;
8
+ };
9
+ /**
10
+ * The ONE constrained layout inside the frame's fluid `<main>` (Brand guideline
11
+ * "Content width is fluid"): a single left-aligned column, 960px max, for form
12
+ * and settings pages — single-record edit forms, Organization Settings tabs,
13
+ * My Profile, activation and setup flows. Data surfaces (tables, dashboards,
14
+ * maps) never use it; they take the full fluid width.
15
+ *
16
+ * It adds no gutter of its own — `<main>` already owns the 24px / 16px gutter —
17
+ * and it is never centered. There is no width prop on purpose: a per-page
18
+ * max-width is exactly what the guideline forbids.
19
+ */
20
+ declare function FormColumn({ children, className }: FormColumnProps): react_jsx_runtime.JSX.Element;
21
+
22
+ /**
23
+ * The six canonical top-bar action slots (Reference/Global-Rules v9 → top-bar
24
+ * icons). Each slot's GLYPH is unique and comes from the Brand API
25
+ * `topbarIcons.items.*` tokens, exposed as `--topbar-icon-<slot>` CSS vars
26
+ * whose value is the brand-icon NAME. Every OTHER property — size, gap, color,
27
+ * hover, selected — is universal across all six slots.
28
+ */
29
+ type TopBarIconSlot = 'comms-fuel' | 'apps' | 'notifications' | 'alerts' | 'support' | 'dark-mode';
30
+
31
+ type CommsNotificationKind = 'notification' | 'alert';
32
+ /** One row of the bell feed, as the shell reads it (camelCased). */
33
+ type CommsNotification = {
34
+ id: string;
35
+ kind: CommsNotificationKind;
36
+ title: string;
37
+ body: string;
38
+ icon: string | null;
39
+ link: string | null;
40
+ readAt: string | null;
41
+ orgId: string | null;
42
+ createdAt: string | null;
43
+ };
44
+ type NotificationsFeed = {
45
+ /** Alerts first, then notifications, newest first (Comms sorts them). */
46
+ notifications: CommsNotification[];
47
+ /** One badge number: unread notifications plus unresolved alerts (Spec §6.3). */
48
+ badge: number;
49
+ };
50
+ type NotificationsAdapter = {
51
+ /** Read the signed-in viewer's feed, scoped to an org when one is active. */
52
+ list(orgId: string | null): Promise<NotificationsFeed>;
53
+ /** Mark one row read. Resolves false on any failure, never throws. */
54
+ markRead(id: string): Promise<boolean>;
55
+ /** Archive one row (hides it from the feed). Resolves false on failure. */
56
+ archive(id: string): Promise<boolean>;
57
+ /** Resolve one alert. Comms rejects this for non-alert rows. */
58
+ resolve(id: string): Promise<boolean>;
59
+ };
60
+ /** The empty bell: what every degraded path renders. Always a fresh object. */
61
+ declare function emptyNotificationsFeed(): NotificationsFeed;
62
+ /**
63
+ * Shape a raw Comms body into the feed. Tolerant on purpose: unknown keys are
64
+ * ignored, rows without an id are dropped, and archived rows are never shown.
65
+ */
66
+ declare function normalizeNotificationsFeed(raw: unknown): NotificationsFeed;
67
+ /**
68
+ * Build the comms-backed adapter over the app's chrome fetcher. A null fetcher
69
+ * (no chrome proxy wired) yields the empty bell with no network activity.
70
+ */
71
+ declare function createCommsNotificationsAdapter(fetchJson: NavChromeFetcher | null): NotificationsAdapter;
72
+
73
+ type NavIconLike = ComponentType<{
74
+ size?: number;
75
+ className?: string;
76
+ }>;
77
+ declare const CORE_APP_ORIGIN = "https://app.politogyvrm.com";
78
+ /** Text/Email fuel top-up page (SMS Signal + Email Broadcast). */
79
+ declare const CORE_BILLING_PATH = "/organization-settings/subscription-billing/text-email";
80
+ /** Specs origin — same env-aware-constant pattern as CORE_APP_ORIGIN. */
81
+ declare const SPECS_ORIGIN = "https://specs.politogyvrm.com";
82
+ /**
83
+ * Resolve an organization logo URL for rendering in ANY app.
84
+ *
85
+ * `organizations.logo_url` is authored by VRM core and stored as a ROOT-RELATIVE
86
+ * core route — `/api/storage/public?bucket=organization-logos&path=<org>/logo.png`
87
+ * (the signed-storage proxy). VRM core renders it correctly because that path
88
+ * resolves against its own origin; every other app resolves it against its own
89
+ * origin (forms.politogyvrm.com/api/storage/public), gets a 404, and shows a
90
+ * broken image. The chrome API passes the stored value through verbatim, so the
91
+ * resolution belongs here — one definition for every app, core included.
92
+ *
93
+ * Absolute URLs (http/https/data/blob) pass through untouched.
94
+ */
95
+ declare function resolveOrgLogoUrl(url: string | null | undefined): string | undefined;
96
+ declare function topBarIconButtonClass(tone?: 'default' | 'warning' | 'danger'): string;
97
+ declare function TopBarCountBadge({ count }: {
98
+ count: number;
99
+ }): react_jsx_runtime.JSX.Element | null;
100
+ /**
101
+ * The shared hover tooltip every top-bar control renders BELOW itself: an
102
+ * up-pointing arrow at the icon, a bold title line and a muted description.
103
+ * Pure CSS (group-hover) so it works on <a>, <button> and <summary> triggers.
104
+ * The trigger must carry `group/tbtip relative` (topBarIconButtonClass does).
105
+ */
106
+ declare function TopBarTooltip({ title, description, }: {
107
+ title: string;
108
+ description?: ReactNode;
109
+ }): react_jsx_runtime.JSX.Element;
110
+ /**
111
+ * The up-pointing arrow every top-bar panel renders, anchored under its
112
+ * trigger icon (panels are right-aligned, so the arrow sits at the trigger's
113
+ * center: 16px in from the panel's right edge). One definition — every menu
114
+ * points at its own icon identically.
115
+ */
116
+ declare function TopBarPanelArrow(): react_jsx_runtime.JSX.Element;
117
+ /**
118
+ * Wrapper for third-party top-bar widgets that ship their own launcher button
119
+ * (e.g. DevNotes). Normalizes the trigger to the universal 32px circular slot
120
+ * (chrome.css `.topbar-widget-slot`) and adds the standard tooltip.
121
+ */
122
+ declare function TopBarWidgetSlot({ title, description, children, }: {
123
+ title: string;
124
+ description?: string;
125
+ children: ReactNode;
126
+ }): react_jsx_runtime.JSX.Element;
127
+ type ThemePreference = ThemePreference$1;
128
+ declare function NavThemeControl({ value, onChange, }: {
129
+ value: ThemePreference;
130
+ onChange: (next: ThemePreference) => void;
131
+ }): react_jsx_runtime.JSX.Element;
132
+ type NavChromeFetcher = (path: string, init?: {
133
+ method?: string;
134
+ headers?: Record<string, string>;
135
+ body?: string;
136
+ }) => Promise<unknown>;
137
+ /** GET me — the authenticated user's chrome identity from the shared API.
138
+ * userName prefers the VRM-core profile full name over token claims. */
139
+ type ChromeMe = {
140
+ user: string | null;
141
+ userName: string | null;
142
+ avatarUrl: string | null;
143
+ themePreference: string | null;
144
+ /** Universal navigation-display choice ('menu'|'tabs'|'both'); null when
145
+ * unset or when the profile column is absent in this environment. */
146
+ navDisplay: string | null;
147
+ /** The user's durable active-org preference (full org uuid); null when unset
148
+ * or when the profile column is absent. Adopted only when the request
149
+ * carries no `?org=`/cookie selector — URL → cookie → profile → default. */
150
+ activeOrg?: string | null;
151
+ account?: string | null;
152
+ accountName?: string | null;
153
+ role?: string | null;
154
+ /** Contact reply-to, when the profile carries them (optional/tolerant). */
155
+ email?: string | null;
156
+ phone?: string | null;
157
+ };
158
+ /**
159
+ * A shared read cache scoped to one `<NavChromeProvider>` (one fetcher, one
160
+ * page boot). Every consumer of a given (path, orgId) pair within the TTL
161
+ * window awaits the SAME promise instead of firing its own request — this is
162
+ * what collapsed `/orgs` (2-4x), `/me` (2-3x) and `/notifications` (2-3x) per
163
+ * page load, 1-3.5s each, down to one call apiece (nav-latency-report.md
164
+ * Table 2). Keying by orgId means switching the active org is itself the
165
+ * invalidation: the new org gets a fresh key, never the previous org's cached
166
+ * value. A failed request is evicted immediately so the next consumer retries
167
+ * rather than replaying the same rejection for the rest of the TTL.
168
+ */
169
+ declare function createChromeFetchCache(getFetchJson: () => NavChromeFetcher): {
170
+ dedupedFetch: (path: string, init: Parameters<NavChromeFetcher>[1] | undefined, opts?: {
171
+ orgId?: string | null;
172
+ ttlMs?: number;
173
+ }) => Promise<unknown>;
174
+ invalidate: (path: string) => void;
175
+ };
176
+ type NavChromeContextValue = {
177
+ fetchJson: NavChromeFetcher;
178
+ dedupedFetch: ReturnType<typeof createChromeFetchCache>['dedupedFetch'];
179
+ invalidateChromeCache: ReturnType<typeof createChromeFetchCache>['invalidate'];
180
+ me: ChromeMe | null;
181
+ meLoaded: boolean;
182
+ /** The bell's feed adapter; null = the legacy contacts-shaped feed. */
183
+ notificationsAdapter: NotificationsAdapter | null;
184
+ };
185
+ declare function NavChromeProvider({ fetchJson, notificationsAdapter, children, }: {
186
+ fetchJson: NavChromeFetcher;
187
+ /**
188
+ * Omitted: the bell reads the comms feed through the same proxy (default).
189
+ * An app may inject its own adapter; `null` keeps the legacy feed.
190
+ */
191
+ notificationsAdapter?: NotificationsAdapter | null;
192
+ children: ReactNode;
193
+ }): react_jsx_runtime.JSX.Element;
194
+ /** The authenticated user's chrome identity (profile name / avatar / theme). */
195
+ declare function useChromeMe(): {
196
+ me: ChromeMe | null;
197
+ loaded: boolean;
198
+ };
199
+ /** The provider's de-duped chrome read (null outside <NavChromeProvider>). */
200
+ declare function useNavChromeDedupedFetch(): NavChromeContextValue['dedupedFetch'] | null;
201
+ /** The injected chrome fetcher (null outside <NavChromeProvider>). */
202
+ declare function useNavChromeFetcher(): NavChromeFetcher | null;
203
+ type FuelChannelStatus = {
204
+ remainingUnits: number;
205
+ rawBalanceUnits: number;
206
+ usedUnits: number;
207
+ lowFuel: boolean;
208
+ lowFuelThreshold: number;
209
+ };
210
+ type CommunicationsFuelStatus = {
211
+ organizationId: string;
212
+ signal: FuelChannelStatus;
213
+ broadcast: FuelChannelStatus;
214
+ combinedAvailableCredits: number;
215
+ };
216
+ type ChromeNotificationAlert = {
217
+ id: string;
218
+ title: string;
219
+ description: string;
220
+ href: string | null;
221
+ kind: string;
222
+ /** Server read state (adapter feeds only); the local watermark still applies. */
223
+ read?: boolean;
224
+ };
225
+ type ChromeNotificationReply = {
226
+ id: string;
227
+ contactId: string | null;
228
+ name: string;
229
+ preview: string;
230
+ /** Optional deep-link to the conversation; the new-reply toast opens it. */
231
+ href?: string;
232
+ /**
233
+ * Optional arrival timestamp. Present, it lets the trigger badge count a
234
+ * reply as "unseen" only when it is newer than the last time the panel was
235
+ * opened; absent (older payloads), replies simply don't survive the first
236
+ * open as unseen. Tolerated either way.
237
+ */
238
+ createdAt?: string;
239
+ };
240
+ /** A running or finished contact import surfaced in the notifications panel. */
241
+ type ChromeNotificationImport = {
242
+ id: string;
243
+ label: string;
244
+ /** 0–100 progress, or null when indeterminate (no bar rendered). */
245
+ percent: number | null;
246
+ status: 'active' | 'completed';
247
+ href: string | null;
248
+ };
249
+ /** A cluster of quarantined contacts sharing one phone number. */
250
+ type ChromeNotificationQuarantine = {
251
+ phone: string;
252
+ count: number;
253
+ /** Upstream may omit it; the row already renders conditionally on it. */
254
+ latestAt: string | null;
255
+ };
256
+ type ChromeNotificationsPayload = {
257
+ organizationId: string;
258
+ alerts: ChromeNotificationAlert[];
259
+ replies: ChromeNotificationReply[];
260
+ /** Optional — running/finished imports (tolerant when absent). */
261
+ imports?: ChromeNotificationImport[];
262
+ /** Optional — clustered quarantined contacts (tolerant when absent). */
263
+ quarantined?: ChromeNotificationQuarantine[];
264
+ /** Optional — the server's one badge number (adapter feeds only). */
265
+ badge?: number;
266
+ };
267
+ type ChromeOrgSummary = {
268
+ id: string;
269
+ name: string | null;
270
+ logoUrl: string | null;
271
+ brandColor: string | null;
272
+ role: string | null;
273
+ /** Un-mapped VRM-core membership role (e.g. "super_admin"). */
274
+ rawRole?: string | null;
275
+ };
276
+ /**
277
+ * Fetch the signed-in user's VRM-core organizations through the injected
278
+ * fetcher. Exposed as a hook so the org switcher in the sidebar and the
279
+ * org-scoped widgets share one request.
280
+ */
281
+ declare function useChromeOrgs({ enabled }?: {
282
+ enabled?: boolean;
283
+ }): {
284
+ orgs: ChromeOrgSummary[] | null;
285
+ loading: boolean;
286
+ error: boolean;
287
+ };
288
+ /**
289
+ * A top-bar popover: the shared circular trigger + a right-aligned panel.
290
+ * Closes on outside click / Escape. Purely presentational.
291
+ *
292
+ * EXPORTED so an app with a richer panel than the stock actions can render it
293
+ * inside the SHARED chrome — same 32px trigger, same tooltip, same badge, same
294
+ * panel surface and arrow — instead of hand-rolling a trigger and drifting.
295
+ * This is the enabling step for folding VRM's Fuel breakdown, import-progress,
296
+ * alerts and reply-feed panels into the shared cluster one at a time, without
297
+ * dropping capability (shell-nav-handoff §4; UI-Platform forbids migrating an
298
+ * app to a rendering that loses an element it already ships).
299
+ */
300
+ declare function TopBarPopover({ label, description, slot, fallbackIcon, badge, tone, onOpen, openToken, onOpenChange, hideTooltip, children, panelClassName, }: {
301
+ label: string;
302
+ description?: string;
303
+ slot?: TopBarIconSlot;
304
+ fallbackIcon: NavIconLike;
305
+ badge?: number;
306
+ tone?: 'default' | 'warning' | 'danger';
307
+ onOpen?: () => void;
308
+ /**
309
+ * Imperative "open" signal: whenever this number CHANGES the panel opens
310
+ * (and `onOpen` fires). Lets a sibling — e.g. the notifications toast — open
311
+ * the panel without owning the popover's state. Undefined disables it.
312
+ */
313
+ openToken?: number;
314
+ /**
315
+ * Notified on every open/close. A sibling surface anchored to the same
316
+ * trigger (e.g. the notifications toast) must know when the panel is open so
317
+ * the two never render on top of each other — Reference/UI-Platform gives
318
+ * every top-bar panel ONE surface anchored to its trigger, so a second
319
+ * surface at the same anchor always occludes it.
320
+ */
321
+ onOpenChange?: (open: boolean) => void;
322
+ /**
323
+ * Hide the trigger's hover tooltip while a transient nudge (the new-reply
324
+ * toast, the low-fuel hint) is up under the same trigger. Both are z-50 and
325
+ * anchored to the trigger, so without this the nudge paints over the
326
+ * tooltip (measured on a2p: the reply toast covered "Alerts &
327
+ * Notifications"). Reference/UI-Platform: one surface per trigger.
328
+ */
329
+ hideTooltip?: boolean;
330
+ children: ReactNode;
331
+ panelClassName?: string;
332
+ }): react_jsx_runtime.JSX.Element;
333
+ declare function FuelAction({ orgId }: {
334
+ orgId: string | null;
335
+ }): react_jsx_runtime.JSX.Element;
336
+ declare function NotificationsAction({ orgId }: {
337
+ orgId: string | null;
338
+ }): react_jsx_runtime.JSX.Element;
339
+ declare function SupportAction({ orgId, orgs: knownOrgs, }?: {
340
+ orgId?: string | null;
341
+ orgs?: {
342
+ id: string;
343
+ name: string | null;
344
+ }[];
345
+ }): react_jsx_runtime.JSX.Element;
346
+ declare function SpecOverlayAction({ orgId, orgName }?: {
347
+ orgId?: string | null;
348
+ orgName?: string | null;
349
+ }): react_jsx_runtime.JSX.Element | null;
350
+ type NavDisplayMode = 'menu' | 'tabs' | 'both';
351
+ declare function NavDisplayAction({ value, onChange, }: {
352
+ value: NavDisplayMode;
353
+ onChange: (next: NavDisplayMode) => void;
354
+ }): react_jsx_runtime.JSX.Element;
355
+ declare function useThemePreference(): {
356
+ value: ThemePreference;
357
+ setValue: (next: ThemePreference) => void;
358
+ };
359
+
360
+ /**
361
+ * Icon slots used by the standard menus. The shell stays icon-library-agnostic:
362
+ * callers map each key to their own icon components (lucide, react-icons, …).
363
+ * A missing key simply renders that row without an icon.
364
+ */
365
+ type StandardNavIconKey = 'home' | 'users' | 'mail' | 'messageSquare' | 'layout' | 'activity' | 'lifeBuoy' | 'grid' | 'list' | 'upload' | 'edit' | 'fileText' | 'send' | 'clock' | 'user' | 'barChart' | 'briefcase' | 'settings' | 'creditCard' | 'dollarSign' | 'share' | 'phone' | 'map' | 'mapPin' | 'target' | 'flag' | 'layoutDashboard' | 'usersRound' | 'mousePointerClick' | 'clipboardList' | 'circleUser' | 'crosshair' | 'landmark' | 'chartNoAxes' | 'doorOpen' | 'signpost';
366
+ /** The operating Mode whose nav tree to build. Defaults to `relationship`. */
367
+ type StandardNavMode = 'relationship' | 'campaign' | 'petition';
368
+ /**
369
+ * Per-feature availability for the Campaign tree. Campaign Mode ships its apps
370
+ * incrementally: a disabled feature is omitted from the nav entirely (rather
371
+ * than rendered as a dead/disabled row), and its flag flips to `true` in a
372
+ * later patch release as the app goes live. Dashboard and Voter Contact are
373
+ * core-hosted and always present, so they carry no flag.
374
+ */
375
+ interface CampaignFeatureAvailability {
376
+ a2p: boolean;
377
+ phonebank: boolean;
378
+ canvass: boolean;
379
+ signs: boolean;
380
+ tribes: boolean;
381
+ polling: boolean;
382
+ }
383
+ /**
384
+ * Launch state at this shell version: every Campaign feature is deployed and
385
+ * live (a2p / phonebank / canvass / signs .politogyvrm.com all serve the app
386
+ * behind SSO as of 2026-07-24), so no row is hidden. The flags remain so a
387
+ * future feature can ship dark, and so a caller can hide one per-deployment.
388
+ */
389
+ declare const CAMPAIGN_FEATURE_AVAILABILITY: CampaignFeatureAvailability;
390
+ interface StandardNavOptions {
391
+ /**
392
+ * @deprecated app.politogyvrm.com (VRM core) is retired (Reference/UI-Platform
393
+ * → "Retirement of app.politogyvrm.com"). Every row this tree used to resolve
394
+ * against VRM core now points at its V2 host directly, so this is unused.
395
+ * Kept only so existing callers don't need to drop the field immediately.
396
+ */
397
+ coreBaseUrl?: string;
398
+ /** Icon component per slot; omitted slots render icon-less rows. */
399
+ icons?: Partial<Record<StandardNavIconKey, NavIcon>>;
400
+ /**
401
+ * App-local override for the "Contacts" item. `children` are used verbatim
402
+ * (NOT absolutized) so the owning app nests its own routes; `href` (also
403
+ * verbatim) feeds active-detection for the group header. When omitted, the
404
+ * item carries VRM core's own contacts sub-pages as absolute links.
405
+ * (Relationship tree only.)
406
+ */
407
+ contactsItem?: {
408
+ href?: string;
409
+ children?: NavItem[];
410
+ /**
411
+ * Live contact count shown right-aligned on the Contacts row, already
412
+ * formatted for display ("31.9K"). Only the owning app knows it.
413
+ * (Specs/Contacts design: `Contacts · 31.9K`.)
414
+ */
415
+ count?: string | number | null;
416
+ };
417
+ /**
418
+ * Top-level rows to OMIT, by label (case-insensitive), e.g. `['Polls','CTAs']`.
419
+ * The Specs/Contacts design rail lists Relationship → Collect → Account with
420
+ * exactly Dashboard · Contacts · Email broadcast · SMS/MMS blast / Calls to
421
+ * action · Forms · Surveys / My profile · Organization settings; apps that
422
+ * still surface Polls / CTAs keep them by default. A section row with no
423
+ * remaining items is dropped too.
424
+ */
425
+ hiddenItems?: string[];
426
+ /**
427
+ * App-local override for the Petition-mode "Dashboard" entry, same contract
428
+ * as `contactsItem`: `href`/`children` used verbatim so the Petitions app
429
+ * nests its own routes under the entry. (Petition tree only.)
430
+ */
431
+ petitionsItem?: {
432
+ href?: string;
433
+ children?: NavItem[];
434
+ };
435
+ /**
436
+ * The trailing "Support" row. VRM core opens its SupportRequestModal here;
437
+ * other apps supply their own handler (`onClick`) or a link (`href`).
438
+ * Omitted or `false` → no Support row. Appended to every mode's tree.
439
+ */
440
+ supportItem?: {
441
+ onClick?: () => void;
442
+ href?: string;
443
+ } | false;
444
+ /**
445
+ * Which mode's tree to build. Default `relationship`, whose output is
446
+ * byte-for-byte what this function produced before modes existed.
447
+ */
448
+ mode?: StandardNavMode;
449
+ /**
450
+ * Active organization id (full UUID). EVERY link in EVERY tree carries it as
451
+ * `?org=<uuid>` — the same convention the Mode switcher and My Account menu
452
+ * use — so the destination app opens on the same org instead of the user's
453
+ * default one. Omit it only when the caller genuinely has no active org yet.
454
+ */
455
+ activeOrgId?: string | null;
456
+ /**
457
+ * Per-feature Campaign availability overrides, merged over
458
+ * `CAMPAIGN_FEATURE_AVAILABILITY`. Only meaningful for the Campaign tree.
459
+ */
460
+ campaignAvailability?: Partial<CampaignFeatureAvailability>;
461
+ }
462
+ /**
463
+ * Build the standard Politogy VRM menu for the given `mode` (default
464
+ * `relationship`), in the exact order and wording the main app renders it. See
465
+ * `StandardNavOptions` for the app-specific hooks (`contactsItem`,
466
+ * `supportItem`) and the Campaign inputs (`activeOrgId`, `campaignAvailability`).
467
+ */
468
+ declare function standardPolitogyNav(opts: StandardNavOptions): NavItem[];
469
+
470
+ type NavIcon = ComponentType<{
471
+ size?: number;
472
+ className?: string;
473
+ strokeWidth?: number;
474
+ }>;
475
+ type NavItem = {
476
+ /**
477
+ * What this row IS. Defaults to `'link'` — every existing `NavItem[]` keeps
478
+ * its exact type and rendering.
479
+ *
480
+ * `'section'` is a non-interactive heading that groups the rows beneath it:
481
+ * uppercase, muted, letterspaced, not focusable, no hover. Only `label` is
482
+ * read; `href`, `icon`, `onClick` and `children` are ignored.
483
+ *
484
+ * The legacy chrome supported this and 0.43 dropped it, so apps faked it by
485
+ * passing `disabled` rows with no href — which looks approximately right and
486
+ * is wrong where it counts: a disabled row announces as an unavailable
487
+ * CONTROL to a screen reader, when it is not a control at all. A section is
488
+ * its own kind of row (Reference/UI-Platform → Left bar).
489
+ *
490
+ * Deliberately a widened field rather than a discriminated union: a union
491
+ * would make `item.href` a type error for every existing consumer that reads
492
+ * it, turning an additive feature into a breaking change.
493
+ */
494
+ kind?: 'link' | 'section';
495
+ /** Route to link to. Optional when `onClick` is supplied (renders a button). */
496
+ href?: string;
497
+ label: string;
498
+ icon?: NavIcon;
499
+ /**
500
+ * When supplied the row renders as a `<button>` (styled identically to the
501
+ * link rows) instead of a routed link — used for actions like "Support".
502
+ */
503
+ onClick?: () => void;
504
+ /**
505
+ * Disables the row: non-interactive and dimmed, with `disabledTitle` shown as
506
+ * a hover tooltip explaining why. Mirrors `NavTab`'s existing contract so a
507
+ * gated row looks the same whether it renders in the sidebar or a tab strip.
508
+ * Without this, an app that gates a section (VRM dims Email / SMS until setup
509
+ * is complete) had no way to express it and the row rendered fully clickable
510
+ * (shell-nav-handoff §3).
511
+ */
512
+ disabled?: boolean;
513
+ /** Tooltip for a disabled row — say why, and how to resolve it. */
514
+ disabledTitle?: string;
515
+ /**
516
+ * Right-aligned count/annotation on the row — e.g. the live contact count
517
+ * on "Contacts" (`31.9K`). Pre-formatted by the app; the shell only draws
518
+ * it (Specs/Contacts design rail). Omitted/null draws nothing.
519
+ */
520
+ badge?: string | number | null;
521
+ /**
522
+ * Nested sub-items. When present, the row becomes an expandable GROUP header.
523
+ * Clicking it always toggles the children open/closed and rotates the
524
+ * right-aligned chevron; if the item ALSO carries an `onClick`, that runs too,
525
+ * so a parent can navigate to its section dashboard while expanding
526
+ * (shell-nav-handoff §2). An `href` alone never navigates from a group header. The sidebar runs a single-open accordion (opening one group closes
527
+ * the others) and auto-expands whichever group contains the active route —
528
+ * mirroring the main VRM app's Chakra sidebar. Children render as smaller nav
529
+ * rows on a lighter panel and support both `href` links and `onClick` actions.
530
+ */
531
+ children?: NavItem[];
532
+ };
533
+ type NavLinkProps = {
534
+ href: string;
535
+ className?: string;
536
+ 'aria-current'?: 'page' | undefined;
537
+ children: ReactNode;
538
+ role?: string;
539
+ 'aria-selected'?: boolean;
540
+ 'aria-label'?: string;
541
+ title?: string;
542
+ style?: CSSProperties;
543
+ };
544
+ type NavLinkComponent = ComponentType<NavLinkProps>;
545
+ declare function isNavItemActive(pathname: string, href: string): boolean;
546
+ /** A multi-mode app (VRM core) renders NavAppShell without a registry modeId;
547
+ * its current mode label still decides the rail colour (Left-Navigation §5). */
548
+ declare function modeIdFromLabel(label: string | undefined): string | undefined;
549
+ /** "Ben Edtl" -> "Ben E." (Left-Navigation §10). One word stays as is. */
550
+ declare function shortUserName(name: string): string;
551
+ /** Short environment name for the rail's build line ("prod", "staging", "local"). */
552
+ declare function shortEnvLabel(label: string): string;
553
+ declare function envChipClasses(label: string): string;
554
+ type NavBrand = {
555
+ /** Where the logo links to. Defaults to "/". */
556
+ homeHref?: string;
557
+ /**
558
+ * Brand logo image src. When supplied this renders as the wordmark logo
559
+ * (matching the main app's BrandLogo), and `badgeLabel`/`title`/`subtitle`
560
+ * are used only as the no-image fallback.
561
+ */
562
+ logoSrc?: string;
563
+ logoAlt?: string;
564
+ /**
565
+ * The square mark shown at the top of the COLLAPSED rail (Left-Navigation
566
+ * §11.6) — Brand `assets.logoSquare`, the all-white vrm tile. Falls back to
567
+ * the badge when omitted.
568
+ */
569
+ logoSquareSrc?: string;
570
+ /**
571
+ * The logo URLs are still resolving from the Brand token sheet. The rail
572
+ * reserves the logo's box and draws nothing — never the badge fallback,
573
+ * which would flash a stand-in on every load.
574
+ */
575
+ logoPending?: boolean;
576
+ /** Short label shown inside the brand badge fallback (e.g. "P"). */
577
+ badgeLabel: string;
578
+ title: string;
579
+ subtitle?: string;
580
+ };
581
+ type NavOrgOption = {
582
+ id: string;
583
+ name: string | null;
584
+ logoUrl?: string | null;
585
+ /** The org's Brand Kit icon mark; falls back to `logoUrl`, then initials. */
586
+ iconUrl?: string | null;
587
+ brandColor?: string | null;
588
+ role?: string | null;
589
+ };
590
+ type NavOrg = {
591
+ name: string | null;
592
+ /** Full org id. When present, a copy affordance is shown by the label. */
593
+ id?: string | null;
594
+ /** Optional org logo for the pill badge; falls back to initials. */
595
+ logoUrl?: string | null;
596
+ /**
597
+ * The org's Brand Kit icon mark, shown on the collapsed rail (32px, on its
598
+ * white tile). Falls back to `logoUrl` scaled to fit, then initials.
599
+ */
600
+ iconUrl?: string | null;
601
+ /** Solid pill background (the org's brand color). Defaults to the accent. */
602
+ brandColor?: string | null;
603
+ /** Org's secondary Brand Kit color; the card's bottom-edge gradient runs
604
+ * primary → secondary. Falls back to the Politogy gradient when unset. */
605
+ brandColorSecondary?: string | null;
606
+ /**
607
+ * Organization Settings §7.1–§7.2: when the org has no logo yet, an Account
608
+ * Admin sees an "Upload logo" link in the band instead of the org name.
609
+ */
610
+ canUploadLogo?: boolean;
611
+ uploadLogoHref?: string;
612
+ onClick?: () => void;
613
+ /**
614
+ * The user's organizations. When present (even one), the pill renders as a
615
+ * dropdown SWITCHER (Reference/UI-Platform "Organization selector": never a
616
+ * static label in a multi-org app); selecting one calls `onSwitch(id)`.
617
+ */
618
+ organizations?: NavOrgOption[];
619
+ onSwitch?: (id: string) => void;
620
+ /**
621
+ * The active org is still resolving from the chrome API. Renders a skeleton
622
+ * pill instead of a name. Required because the app's own workspace label is
623
+ * NOT the organization: showing it while the real org loads flashes a wrong
624
+ * value (Global Rules — async values shimmer, they never render a stand-in).
625
+ */
626
+ loading?: boolean;
627
+ };
628
+ type NavModeOption = {
629
+ id: string;
630
+ label: string;
631
+ icon?: NavIcon;
632
+ /**
633
+ * Left-Navigation §7: a mode the organization does not hold is always
634
+ * shown (never hidden), dimmed, and not selectable. Defaults to true.
635
+ */
636
+ available?: boolean;
637
+ /** Tooltip for an unavailable mode, e.g. "Campaign Mode isn't active for
638
+ * this organization." Appended with "See upgrade options" for an Account
639
+ * Admin on a paid account (never during a trial). */
640
+ unavailableTooltip?: string;
641
+ };
642
+ type NavMode = {
643
+ label: string;
644
+ icon?: NavIcon;
645
+ /**
646
+ * Entitled modes for the active organization. With more than one option the
647
+ * pill renders as a SELECTOR (dropdown); with zero/one it stays the classic
648
+ * disabled single-mode pill. Selecting calls onSelect(id).
649
+ */
650
+ options?: NavModeOption[];
651
+ onSelect?: (id: string) => void;
652
+ };
653
+ type NavFooterLink = {
654
+ label: string;
655
+ href: string;
656
+ external?: boolean;
657
+ };
658
+ type NavFooter = {
659
+ /**
660
+ * Build metadata (env chip / commit / version / date / author). OPTIONAL:
661
+ * omit envLabel/version/commit to render a links-only footer — apps show
662
+ * the meta block to Super Administrators only (Reference/UI-Platform).
663
+ */
664
+ envLabel?: string;
665
+ version?: string;
666
+ commit?: string;
667
+ links?: NavFooterLink[];
668
+ /** ISO date (or any Date-parseable string) of the deployed commit. */
669
+ commitDate?: string;
670
+ /** Full name of the commit author (only the first name is shown). */
671
+ commitAuthor?: string;
672
+ /**
673
+ * The signed-in user, drawn as a card (avatar · name · email · chevron)
674
+ * ABOVE the links row. Reference/UI-Platform v30 → Left bar: "The user —
675
+ * avatar, name, email and the user menu — lives in the left bar footer."
676
+ * Clicking it opens the account menu UPWARD. `NavAppShell` fills these from
677
+ * `topBar.user` / `topBar.userMenu` / `topBar.onSignOut` automatically, so
678
+ * standalone `NavSidebar` consumers pass them only when they want the card.
679
+ */
680
+ user?: NavUser | null;
681
+ userMenu?: NavUserMenu | null;
682
+ onSignOut?: () => void;
683
+ };
684
+ type NavSidebarProps = {
685
+ pathname: string;
686
+ brand: NavBrand;
687
+ nav: {
688
+ groupLabel?: string;
689
+ items: NavItem[];
690
+ isActive?: (pathname: string, href: string) => boolean;
691
+ /**
692
+ * Render each top-level group's CHILDREN directly at the root of the rail
693
+ * — no parent header row, no accordion. For an app whose whole tree nests
694
+ * under one entry (Petitions), that parent row is pure anatomy: V1 never
695
+ * had it, it duplicates the first child's route, and it costs a level of
696
+ * indentation. Sections render as sections; rows render with the 'flat'
697
+ * variant (top-level geometry, wash active treatment). Top-level items
698
+ * WITHOUT children render unchanged, so a mixed tree degrades sanely.
699
+ */
700
+ flatten?: boolean;
701
+ };
702
+ org?: NavOrg | null;
703
+ mode?: NavMode | null;
704
+ footer?: NavFooter | null;
705
+ linkComponent?: NavLinkComponent;
706
+ /**
707
+ * Small-screen expand state (owned by `NavAppShell`). The rail is never
708
+ * hidden (Left-Navigation §11.6): at `md` and up it is the full rail, below
709
+ * `md` it collapses to the 64px icon rail. `open` expands the collapsed
710
+ * rail to the full rail as a modal drawer with a backdrop, and `onClose`
711
+ * wires the backdrop, the close button, and Escape. `md` and up ignores
712
+ * both.
713
+ */
714
+ open?: boolean;
715
+ onClose?: () => void;
716
+ /**
717
+ * Expands the collapsed (below `md`) rail. When set, the square logo tile at
718
+ * the top of the collapsed rail becomes the "Expand navigation" control —
719
+ * the Left-Navigation Design draws no other toggle and no top-bar hamburger.
720
+ */
721
+ onOpen?: () => void;
722
+ /**
723
+ * Closes the expanded rail after a nav-link click without counting as the
724
+ * user's Collapse choice. Defaults to `onClose`.
725
+ */
726
+ onNavigate?: () => void;
727
+ };
728
+ declare function NavSidebar({ pathname, brand, nav, org, mode, footer, linkComponent, open, onClose, onOpen, onNavigate, }: NavSidebarProps): react_jsx_runtime.JSX.Element;
729
+ type NavUser = {
730
+ name: string | null;
731
+ email?: string | null;
732
+ /** Profile PHOTO url — highest-precedence avatar source. */
733
+ avatarUrl?: string | null;
734
+ /** Memoji url — used when no photo is set; falls back to initials. */
735
+ memojiUrl?: string | null;
736
+ tier?: string | null;
737
+ role?: string | null;
738
+ };
739
+ type NavTopBarAction = {
740
+ key: string;
741
+ /**
742
+ * Canonical top-bar slot. When set, the glyph is sourced by NAME from the
743
+ * Brand API via `--topbar-icon-<slot>`; `icon` becomes the fallback used
744
+ * until the runtime Brand stylesheet lands (or when the token is unset).
745
+ */
746
+ slot?: TopBarIconSlot;
747
+ icon: NavIcon;
748
+ label: string;
749
+ onClick?: () => void;
750
+ href?: string;
751
+ badge?: number | null;
752
+ tone?: 'default' | 'warning' | 'danger';
753
+ /** Tooltip body shown under the icon (label is the tooltip title). */
754
+ description?: string;
755
+ };
756
+ type NavLinkedAccount = {
757
+ id: string;
758
+ name: string | null;
759
+ email?: string | null;
760
+ avatarUrl?: string | null;
761
+ active?: boolean;
762
+ };
763
+ type NavRoleBadge = {
764
+ role: string;
765
+ orgName?: string | null;
766
+ };
767
+ /**
768
+ * The My Account menu (avatar dropdown) — mirrors the main VRM app's user
769
+ * menu: My Profile / Organization Settings links, a ROLES & ORGANIZATIONS
770
+ * section, an ACCOUNTS switcher, an optional theme control, then Sign out.
771
+ * Every section renders only when its data is supplied.
772
+ */
773
+ type NavUserMenu = {
774
+ myProfileHref?: string;
775
+ organizationSettingsHref?: string;
776
+ roles?: NavRoleBadge[];
777
+ accounts?: NavLinkedAccount[];
778
+ onSwitchAccount?: (id: string) => void;
779
+ onRemoveAccount?: (id: string) => void;
780
+ addAccountHref?: string;
781
+ onAddAccount?: () => void;
782
+ /**
783
+ * Navigation display (Sub Menu / Tabs Only / Both) — lives in the account
784
+ * menu since 0.68.0; the top-bar `NavDisplayAction` popover is retired from
785
+ * the standard cluster (design: 4 icon buttons + Help).
786
+ */
787
+ navDisplay?: {
788
+ value: NavDisplayMode;
789
+ onChange: (next: NavDisplayMode) => void;
790
+ };
791
+ /** Theme preference segmented control (Light / System / Dark). */
792
+ theme?: {
793
+ value: ThemePreference;
794
+ onChange: (next: ThemePreference) => void;
795
+ };
796
+ };
797
+ type NavBreadcrumb = {
798
+ label: string;
799
+ href?: string;
800
+ };
801
+ type NavTopBarProps = {
802
+ /**
803
+ * Chrome-owned page title line (`<h1>` above main). Omit when the page body
804
+ * owns its own title (registry `pageTitle: false`, e.g. Contacts).
805
+ */
806
+ title?: string;
807
+ subtitle?: string;
808
+ /**
809
+ * Breadcrumb trail rendered UNDER the page title (Reference/UI-Platform:
810
+ * every page and sub-page/tab shows its location). Last crumb = current
811
+ * location (non-link); earlier crumbs may carry hrefs.
812
+ */
813
+ breadcrumbs?: NavBreadcrumb[];
814
+ user?: NavUser | null;
815
+ userMenu?: NavUserMenu;
816
+ onSignOut?: () => void;
817
+ /**
818
+ * Structured icon-button action cluster (32×32 circular buttons with optional
819
+ * count badges), rendered before the `actions` slot. Matches the main app's
820
+ * topbar action icons.
821
+ */
822
+ actionsList?: NavTopBarAction[];
823
+ /** App-specific action cluster rendered left of the theme toggle. */
824
+ actions?: ReactNode;
825
+ /** Theme toggle slot (injected so this package needs no theme dependency). */
826
+ themeToggle?: ReactNode;
827
+ /**
828
+ * Mobile drawer trigger (owned by `NavAppShell`). Supplying it renders a
829
+ * hamburger button, hidden at `lg` and up, as the first thing in the header
830
+ * — below `lg` the sidebar is otherwise unreachable. Omit to render no
831
+ * hamburger at all (e.g. `NavTopBar` used standalone).
832
+ */
833
+ onOpenNav?: () => void;
834
+ /** Whether the drawer `onOpenNav` opens is currently open (drives `aria-expanded`). */
835
+ navOpen?: boolean;
836
+ /**
837
+ * Universal search — Reference/UI-Platform "Top bar → required elements":
838
+ * the search field, 320px wide, at the left end of the bar; nothing else
839
+ * sits on the left. Omit `onChange`/`onSubmit` for a decorative field (an
840
+ * app that has not wired search yet still gets the correct chrome).
841
+ */
842
+ search?: {
843
+ placeholder?: string;
844
+ value?: string;
845
+ onChange?: (value: string) => void;
846
+ onSubmit?: (value: string) => void;
847
+ };
848
+ /**
849
+ * Build notes — a quiet text button that starts the right-hand group
850
+ * (Reference/UI-Platform "Top bar → required elements").
851
+ */
852
+ /**
853
+ * Where the My Account trigger lives. `'topbar'` (default for a standalone
854
+ * `NavTopBar`) keeps the avatar + name + chevron at the right end of the bar;
855
+ * `'sidebar'` / `'none'` hide it here — `NavAppShell` passes `'sidebar'` and
856
+ * draws the user card in the left-bar footer instead (UI-Platform v30:
857
+ * "There is no My Account badge in the top bar").
858
+ */
859
+ accountMenu?: 'topbar' | 'sidebar' | 'none';
860
+ buildNotes?: {
861
+ label?: string;
862
+ onOpen?: () => void;
863
+ };
864
+ };
865
+ declare function NavTopBar({ title, subtitle, breadcrumbs, user, userMenu, onSignOut, actionsList, actions, themeToggle, onOpenNav, navOpen, search, buildNotes, accountMenu, }: NavTopBarProps): react_jsx_runtime.JSX.Element;
866
+ type NavTab = {
867
+ /** Stable identity (used as the React key). */
868
+ key: string;
869
+ /** The tab's visible text. */
870
+ label: string;
871
+ /**
872
+ * A Lucide icon rendered 6px left of the label (Reference/UI-Platform →
873
+ * Tabs, decided 2026-10-06: "Icon + label. Each tab is a Lucide icon."),
874
+ * 15px / 1.75 stroke (13px on a small strip), following the label's
875
+ * selected / unselected / hover color via `currentColor`. Icon-ONLY tabs
876
+ * (no label) are retired — this always pairs with `label`.
877
+ */
878
+ icon?: NavIcon;
879
+ /** Optional count, drawn as a mono pill after the label. */
880
+ count?: string | number | null;
881
+ /** Route to link to (rendered through `linkComponent`). */
882
+ href?: string;
883
+ /** Click handler — rendered as a `<button>` when there's no `href`. */
884
+ onSelect?: () => void;
885
+ /** Whether this tab is the active one (drives the mode-color underline). */
886
+ selected?: boolean;
887
+ /**
888
+ * Non-interactive, dimmed tab (e.g. Surveys' Canvas/Results before a survey
889
+ * is chosen). Renders a non-navigating span; `disabledTitle` is the tooltip
890
+ * explaining why.
891
+ */
892
+ disabled?: boolean;
893
+ disabledTitle?: string;
894
+ };
895
+ type NavTabStripProps = {
896
+ tabs: NavTab[];
897
+ /** Accessible name for the tablist. */
898
+ 'aria-label'?: string;
899
+ /** Routing primitive for `href` tabs (Next `<Link>`, etc). Defaults to <a>. */
900
+ linkComponent?: NavLinkComponent;
901
+ /** `'sm'`: 12px text with 8px vertical padding. Default `'md'` (13px / 12px). */
902
+ size?: 'md' | 'sm';
903
+ /** Extra classes on the tablist container. */
904
+ className?: string;
905
+ /**
906
+ * Optional tab panel rendered directly below the strip, on the page
907
+ * surface with no card chrome. Omit to render only the strip and compose
908
+ * the page body yourself.
909
+ */
910
+ children?: ReactNode;
911
+ };
912
+ /**
913
+ * The canonical page tab strip: underlined text tabs on a 1px rule. Render it
914
+ * in the page body below the page header; pass the app's `Link` as
915
+ * `linkComponent` for `href` tabs.
916
+ */
917
+ declare function NavTabStrip({ tabs, 'aria-label': ariaLabel, linkComponent, size, className, children, }: NavTabStripProps): react_jsx_runtime.JSX.Element;
918
+ /**
919
+ * sessionStorage key holding the Beta-banner dismissal. sessionStorage — not
920
+ * localStorage — so the dismissal lasts only for the browser session; and it is
921
+ * additionally cleared on sign-out (see `clearBetaBannerDismissal`, called from
922
+ * the chrome frame) so a fresh LOGIN always re-shows the notice.
923
+ */
924
+ declare const BETA_BANNER_DISMISS_KEY = "politogy_beta_banner_dismissed";
925
+ /**
926
+ * Re-arm the Beta banner. The chrome frame calls this on sign-out so the notice
927
+ * reappears at the next login rather than staying hidden across the boundary
928
+ * (sessionStorage survives an in-tab logout→login round trip on its own).
929
+ */
930
+ declare function clearBetaBannerDismissal(): void;
931
+ type NavBetaBannerProps = {
932
+ /** Leading sentence(s) before the link. Defaults to the standard Beta copy. */
933
+ text?: string;
934
+ /** Bold + underlined link label. Defaults to the standard Terms copy. */
935
+ linkLabel?: string;
936
+ /** Terms & Conditions URL (opens in a new tab). Defaults to the app T&C page. */
937
+ href?: string;
938
+ /**
939
+ * Show a dismiss (×) button that hides the banner for the rest of the browser
940
+ * session. Cleared on sign-out, so it returns at the next login. Default true.
941
+ */
942
+ dismissible?: boolean;
943
+ };
944
+ declare function NavBetaBanner({ text, linkLabel, href, dismissible }: NavBetaBannerProps): react_jsx_runtime.JSX.Element | null;
945
+ type NavAppShellProps = {
946
+ sidebar: NavSidebarProps;
947
+ topBar: NavTopBarProps;
948
+ /**
949
+ * When supplied, a full-width Beta notice strip renders directly below the top
950
+ * bar. Presence of the prop enables it; all fields fall back to the standard
951
+ * Beta copy + Terms & Conditions link.
952
+ */
953
+ betaBanner?: NavBetaBannerProps;
954
+ /**
955
+ * @deprecated The frame's content area is one fluid `<main>` (Brand
956
+ * guideline "Content width is fluid"): the 24px gutter (16px below `md`),
957
+ * no max-width and no centered container. Apps never emit their own page
958
+ * container, so there is nothing left to choose here.
959
+ *
960
+ * `'bare'` is still honored — it renders `children` with no `<main>` and no
961
+ * gutter — only so VRM core, which renders `NavAppShell` directly around
962
+ * pages that still carry their own `PageContainer`, does not get a nested
963
+ * `<main>` before it migrates. It warns in development and will be removed.
964
+ * `'padded'` is now the same as omitting the prop.
965
+ */
966
+ contentWrapper?: 'padded' | 'bare';
967
+ /**
968
+ * The operating Mode this frame is scoped to, stamped on the root as
969
+ * `data-politogy-mode` so the Brand API's per-Mode chrome tokens can target
970
+ * it (Reference/UI-Platform → "Per-mode branding — one accent per Mode").
971
+ *
972
+ * This is app IDENTITY, not app configuration: `PolitogyAppFrame` passes it
973
+ * from the `POLITOGY_APPS` registry, never from a prop an app supplies, so an
974
+ * app still cannot choose its own chrome colour.
975
+ *
976
+ * Omitted (or a Mode that declares no chrome group in the Brand API) => every
977
+ * accent falls back to the global one, exactly as before 0.47.
978
+ */
979
+ modeId?: string;
980
+ /**
981
+ * Where the user card / account menu renders. `'sidebar'` (default since
982
+ * 0.68.0) draws it in the left-bar footer and hides the top-bar trigger
983
+ * (Reference/UI-Platform v30); `'topbar'` restores the 0.67 top-right badge.
984
+ */
985
+ accountMenuPlacement?: 'sidebar' | 'topbar';
986
+ children: ReactNode;
987
+ };
988
+ declare function NavAppShell({ sidebar, topBar, betaBanner, contentWrapper, accountMenuPlacement, modeId, children, }: NavAppShellProps): react_jsx_runtime.JSX.Element;
989
+
990
+ export { NavThemeControl as $, type ChromeOrgSummary as A, BETA_BANNER_DISMISS_KEY as B, type CommsNotification as C, type CommunicationsFuelStatus as D, FuelAction as E, FormColumn as F, type FuelChannelStatus as G, NavAppShell as H, type NavAppShellProps as I, NavBetaBanner as J, type NavBetaBannerProps as K, type NavBrand as L, NavChromeProvider as M, type NavItem as N, NavDisplayAction as O, type NavFooterLink as P, type NavLinkProps as Q, type NavLinkedAccount as R, type StandardNavIconKey as S, type NavModeOption as T, type NavOrg as U, type NavRoleBadge as V, NavSidebar as W, type NavSidebarProps as X, type NavTab as Y, NavTabStrip as Z, type NavTabStripProps as _, type CommsNotificationKind as a, NavTopBar as a0, type NavTopBarAction as a1, type NavTopBarProps as a2, type NavUser as a3, NotificationsAction as a4, SPECS_ORIGIN as a5, SpecOverlayAction as a6, type StandardNavOptions as a7, SupportAction as a8, type ThemePreference as a9, TopBarCountBadge as aa, TopBarPanelArrow as ab, TopBarPopover as ac, TopBarTooltip as ad, TopBarWidgetSlot as ae, clearBetaBannerDismissal as af, envChipClasses as ag, isNavItemActive as ah, modeIdFromLabel as ai, resolveOrgLogoUrl as aj, shortEnvLabel as ak, shortUserName as al, standardPolitogyNav as am, topBarIconButtonClass as an, useChromeMe as ao, useChromeOrgs as ap, useNavChromeDedupedFetch as aq, useNavChromeFetcher as ar, useThemePreference as as, type NotificationsAdapter as b, type NotificationsFeed as c, createCommsNotificationsAdapter as d, emptyNotificationsFeed as e, type NavIcon as f, type NavBreadcrumb as g, type StandardNavMode as h, type NavLinkComponent as i, type NavChromeFetcher as j, type NavMode as k, type NavUserMenu as l, type NavOrgOption as m, normalizeNotificationsFeed as n, type NavFooter as o, type NavDisplayMode as p, CAMPAIGN_FEATURE_AVAILABILITY as q, CORE_APP_ORIGIN as r, CORE_BILLING_PATH as s, type CampaignFeatureAvailability as t, type ChromeMe as u, type ChromeNotificationAlert as v, type ChromeNotificationImport as w, type ChromeNotificationQuarantine as x, type ChromeNotificationReply as y, type ChromeNotificationsPayload as z };