@the-portland-company/shell 0.2.1 → 0.3.1

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.cts CHANGED
@@ -101,8 +101,13 @@ interface AppRegistryEntry {
101
101
  * fuel/modal/notification components into the relevant slots.
102
102
  */
103
103
  interface ShellSlots {
104
- /** Right side of the header (next to user menu). */
105
- headerExtrasSlot?: ReactNode;
104
+ /**
105
+ * Right side of the header — rendered in the icon row of the header (next
106
+ * to user menu). Used by the legacy app to mount FuelPopover,
107
+ * NewTextBellPopup, SystemAlertsMenu, NavigationToggleMenu, and
108
+ * ImportProgressIndicator. Replaces the older `headerExtrasSlot`.
109
+ */
110
+ headerIconsSlot?: ReactNode;
106
111
  /** Modal layer rendered above everything (positioned absolute). */
107
112
  modalsSlot?: ReactNode;
108
113
  /** Notifications layer (toasts, popovers, badges). */
@@ -112,6 +117,138 @@ interface ShellSlots {
112
117
  /** Overlay always-on-top components (e.g., import progress indicator). */
113
118
  overlaySlot?: ReactNode;
114
119
  }
120
+ /** ---------------- Mode ---------------- */
121
+ /**
122
+ * Per-mode visual / display config supplied by the app. Mirrors the legacy
123
+ * `MODE_CONFIG[mode]` shape from `react/app/src/contexts/ModeContext.tsx`.
124
+ *
125
+ * `icon` is an already-resolved ReactNode (e.g., <FiUsers />) so the shell
126
+ * doesn't need to know about react-icons. `iconName` is kept around as an
127
+ * informational string for tooling that wants to look up the icon component
128
+ * by name.
129
+ */
130
+ interface ShellModeConfig {
131
+ /** Stable mode identifier, e.g., 'relationship'. */
132
+ id: string;
133
+ /** Display name, e.g., 'Relationship Mode'. */
134
+ name: string;
135
+ /** Mode primary color (hex). */
136
+ primaryColor: string;
137
+ /** Mode accent color (hex). */
138
+ accentColor: string;
139
+ /** Mode background color (hex). */
140
+ bgColor: string;
141
+ /** Mode secondary color (hex) — typically muted text. */
142
+ secondaryColor: string;
143
+ /** Mode white color (hex), usually '#FFFFFF'. */
144
+ white: string;
145
+ /** Pre-resolved icon element for the mode pill leftIcon. */
146
+ icon?: ReactNode;
147
+ /** Informational icon name (for debugging or tooling). */
148
+ iconName?: string;
149
+ }
150
+ interface ShellModeValue {
151
+ /** Current mode id, e.g., 'relationship'. */
152
+ currentMode: string;
153
+ /** All available modes for the current org/user. */
154
+ modes: ShellModeConfig[];
155
+ /** Switch to a different mode. App owns side effects. */
156
+ switchMode: (modeId: string) => void;
157
+ /** Returns the config for the current mode (convenience). */
158
+ getModeConfig: () => ShellModeConfig;
159
+ }
160
+ /** ---------------- Nav items ---------------- */
161
+ /**
162
+ * One sidebar nav item. Apps build this list themselves (via
163
+ * `getLinkItemsForMode` + `applySidebarChildAccessState` etc.) and pass it
164
+ * through to <ShellChrome navItems={...}>. The shell renders the rows.
165
+ */
166
+ interface ShellNavItem {
167
+ name: string;
168
+ /** A react-icons component (e.g., FiHome). Either icon or brandIcon set. */
169
+ icon?: unknown;
170
+ /** Brand-icon name keyed off `/brand/icons/<name>.svg`. */
171
+ brandIcon?: string;
172
+ /** Route the row navigates to. */
173
+ href?: string;
174
+ /** Nested rows. Renders an accordion when set. */
175
+ children?: ShellNavItem[];
176
+ /** Small badge shown next to the label (e.g., 'In Development'). */
177
+ badge?: string;
178
+ /** Secondary label rendered below the main label. */
179
+ subLabel?: string;
180
+ /** When true, the row is rendered disabled/non-interactive. */
181
+ disabled?: boolean;
182
+ /** Optional click handler (overrides href). */
183
+ action?: () => void;
184
+ }
185
+ interface ShellNavItemsValue {
186
+ items: ShellNavItem[];
187
+ }
188
+ /** ---------------- Nav preference ---------------- */
189
+ /**
190
+ * User preference for nav rendering — whether sub-menus (accordion children)
191
+ * are shown in the sidebar.
192
+ */
193
+ interface ShellNavigationPreferenceValue {
194
+ showSubMenu: boolean;
195
+ }
196
+ /** ---------------- Role ---------------- */
197
+ /**
198
+ * Active-role display info for the user-menu role badge. App supplies the
199
+ * resolved values; shell renders the badge.
200
+ */
201
+ interface ShellActiveRoleConfig {
202
+ name: string;
203
+ color: string;
204
+ }
205
+ interface ShellRoleValue {
206
+ activeRoleConfig: ShellActiveRoleConfig | null;
207
+ isSuperAdmin: boolean;
208
+ }
209
+ /** ---------------- Footer ---------------- */
210
+ interface ShellFooterLink {
211
+ label: string;
212
+ href: string;
213
+ /** When true, the link opens in a new tab (target='_blank'). */
214
+ external?: boolean;
215
+ }
216
+ /**
217
+ * Footer / sidebar-footer data shipped from the app. The legacy footer
218
+ * row shows Privacy / Terms / Subscriptions links plus a CommitCopyButton
219
+ * with version + commit metadata. All fields are optional so apps can
220
+ * supply only what they have.
221
+ */
222
+ interface ShellFooterValue {
223
+ links: ShellFooterLink[];
224
+ commit?: string;
225
+ commitFull?: string;
226
+ commitDate?: string;
227
+ commitAuthor?: string;
228
+ commitLog?: string;
229
+ version?: string;
230
+ releaseName?: string;
231
+ /**
232
+ * Environment label rendered as a colored chip in the sidebar
233
+ * footer (e.g., 'production' = red, 'staging' = orange,
234
+ * 'local'/'development' = green).
235
+ */
236
+ environmentLabel?: string;
237
+ /**
238
+ * Optional pre-rendered environment chip element. When supplied,
239
+ * <CommitCopyButton> renders this instead of building a default chip
240
+ * from `environmentLabel`. Use this when the app already has an
241
+ * <EnvironmentBanner> component it wants to drop in unchanged.
242
+ */
243
+ envNode?: ReactNode;
244
+ /**
245
+ * When set, <CommitCopyButton> renders a diagnostics icon next to
246
+ * the version that, when clicked, fires this handler. The shell
247
+ * does not navigate or open anything — apps wire whatever they want
248
+ * (modal, route, console dump).
249
+ */
250
+ onDiagnosticsClick?: () => void;
251
+ }
115
252
  /** Props for the top-level ShellProvider. */
116
253
  interface ShellProviderProps {
117
254
  children: ReactNode;
@@ -123,11 +260,11 @@ interface ShellProviderProps {
123
260
  appRegistry?: AppRegistryEntry[];
124
261
  /** Optional override for the base path if the app is mounted under a sub-path (e.g., '/contacts'). */
125
262
  basename?: string;
126
- /** If provided, shell renders <OrgSelector /> in the header. */
263
+ /** If provided, shell renders <OrgPill /> in the sidebar. */
127
264
  organization?: ShellOrganizationValue;
128
265
  /** If provided, UserMenu shows account switcher + add-account button. */
129
266
  linkedAccounts?: ShellLinkedAccountsValue;
130
- /** If provided, shell renders <SupportRequestButton /> in the header. */
267
+ /** Drives the modal submission flow used by app-supplied support widgets. */
131
268
  support?: ShellSupportValue;
132
269
  /** Optional element rendered in the header (typically <DevNotesMenu /> from @the-portland-company/devnotes). */
133
270
  devNotesMenu?: ReactNode;
@@ -143,7 +280,7 @@ interface ShellAuthValue {
143
280
  }
144
281
  /**
145
282
  * Organization that the current user belongs to. Apps supply this via
146
- * ShellProvider so the shell can render <OrgSelector /> in the header.
283
+ * ShellProvider so the shell can render <OrgPill /> in the sidebar.
147
284
  */
148
285
  interface ShellOrganization {
149
286
  id: string;
@@ -151,6 +288,8 @@ interface ShellOrganization {
151
288
  logoUrl?: string | null;
152
289
  /** Brand color as a hex string (e.g., '#0066cc'). Used for the org badge fallback. */
153
290
  brandColor?: string | null;
291
+ /** Optional user-facing role label in this organization ('owner' | 'admin' | etc.). */
292
+ role?: string | null;
154
293
  }
155
294
  interface ShellOrganizationValue {
156
295
  currentOrg: ShellOrganization | null;
@@ -160,6 +299,8 @@ interface ShellOrganizationValue {
160
299
  switchOrganization: (orgId: string) => Promise<void> | void;
161
300
  /** Optional link rendered at the bottom of the org menu, e.g., '/organizations/new'. */
162
301
  createOrgHref?: string;
302
+ /** True while the app is still resolving the org list (renders a skeleton). */
303
+ loadingOrgs?: boolean;
163
304
  }
164
305
  /**
165
306
  * An alternate user account the current user can switch into without signing
@@ -202,11 +343,27 @@ interface ShellSupportValue {
202
343
  declare const ShellOrgContext: react.Context<ShellOrganizationValue | null>;
203
344
  declare const ShellLinkedAccountsContext: react.Context<ShellLinkedAccountsValue | null>;
204
345
  declare const ShellSupportProviderContext: react.Context<ShellSupportValue | null>;
205
- interface ShellChromeValue$1 {
346
+ declare const ShellModeContext: react.Context<ShellModeValue | null>;
347
+ declare const ShellNavItemsContext: react.Context<ShellNavItemsValue | null>;
348
+ declare const ShellNavigationPreferenceContext: react.Context<ShellNavigationPreferenceValue | null>;
349
+ declare const ShellRoleContext: react.Context<ShellRoleValue | null>;
350
+ declare const ShellFooterContext: react.Context<ShellFooterValue | null>;
351
+ interface ShellChromeValue {
206
352
  devNotesMenu: ReactNode | null;
207
353
  myProfileHref: string;
354
+ brandLogoSrc?: string;
355
+ headerIconsSlot?: ReactNode;
356
+ organizationSettingsHref?: string;
357
+ showContinueOnboarding?: boolean;
358
+ onContinueOnboarding?: () => void;
359
+ pageTitle?: string;
360
+ breadcrumbs?: Array<{
361
+ label: string;
362
+ href?: string;
363
+ }>;
364
+ headerActions?: ReactNode;
208
365
  }
209
- declare const ShellChromeContext: react.Context<ShellChromeValue$1 | null>;
366
+ declare const ShellChromeContext: react.Context<ShellChromeValue | null>;
210
367
  declare function ShellProvider({ children, supabaseClient, currentApp, appRegistry, basename, organization, linkedAccounts, support, devNotesMenu, myProfileHref, }: ShellProviderProps): react_jsx_runtime.JSX.Element;
211
368
 
212
369
  declare function useShellAuth(): ShellAuthValue;
@@ -234,33 +391,108 @@ declare function useShellLinkedAccounts(): ShellLinkedAccountsValue | null;
234
391
  */
235
392
  declare function useShellSupport(): ShellSupportValue | null;
236
393
 
237
- interface ShellChromeValue {
238
- devNotesMenu: ReactNode | null;
239
- myProfileHref: string;
240
- }
241
394
  /**
242
- * Returns chrome-level options supplied to ShellProvider (devNotesMenu slot,
243
- * myProfileHref). Throws if used outside <ShellProvider>.
395
+ * Returns chrome-level options supplied to ShellProvider/ShellChrome
396
+ * (devNotesMenu slot, myProfileHref, header data, brand logo src, etc.).
397
+ * Throws if used outside <ShellProvider>.
244
398
  */
245
399
  declare function useShellChrome(): ShellChromeValue;
246
400
 
401
+ /**
402
+ * Returns the mode value supplied to ShellProvider/ShellChrome, or null if
403
+ * the host app didn't pass a `mode` prop. Components like <ModePill /> use
404
+ * this to conditionally render.
405
+ */
406
+ declare function useShellMode(): ShellModeValue | null;
407
+
408
+ /**
409
+ * Returns the nav items value supplied to ShellChrome, or null if the host
410
+ * app didn't pass a `navItems` prop. The sidebar uses this to decide what
411
+ * rows to render.
412
+ */
413
+ declare function useShellNavItems(): ShellNavItemsValue | null;
414
+
415
+ /**
416
+ * Returns the user's navigation rendering preference supplied to
417
+ * ShellChrome, or null if not provided. NavItem uses this to decide
418
+ * whether to expand sub-menus.
419
+ */
420
+ declare function useShellNavigationPreference(): ShellNavigationPreferenceValue | null;
421
+
422
+ /**
423
+ * Returns the active-role info supplied to ShellChrome, or null if not
424
+ * provided. UserMenu uses this to render the ROLES & ORGANIZATIONS badge.
425
+ */
426
+ declare function useShellRole(): ShellRoleValue | null;
427
+
428
+ /**
429
+ * Returns the footer data supplied to ShellChrome (links, commit/version
430
+ * info), or null if not provided. The Sidebar footer reads this to render
431
+ * Privacy / Terms / Subscriptions + commit copy button.
432
+ */
433
+ declare function useShellFooter(): ShellFooterValue | null;
434
+
247
435
  interface AppLayoutProps extends ShellSlots {
248
436
  children: ReactNode;
249
437
  buildInfo?: string;
250
438
  }
251
- declare function AppLayout({ children, buildInfo, headerExtrasSlot, modalsSlot, notificationsSlot, sidebarFooterSlot, overlaySlot, }: AppLayoutProps): react_jsx_runtime.JSX.Element;
439
+ /**
440
+ * Authenticated app shell composition: <Sidebar> on the left, <Header> on
441
+ * top, <main> for routed children, optional <Footer>, plus modal + overlay
442
+ * slots. All chrome data flows through ShellProvider/ShellChrome contexts —
443
+ * AppLayout itself takes only optional slots for modals/overlays/notifs.
444
+ */
445
+ declare function AppLayout({ children, buildInfo, modalsSlot, notificationsSlot, overlaySlot, }: AppLayoutProps): react_jsx_runtime.JSX.Element;
252
446
 
253
447
  interface HeaderProps {
254
- extrasSlot?: ReactNode;
448
+ /** Mobile menu open handler (renders the hamburger icon on mobile). */
449
+ onOpen?: () => void;
450
+ /** DOM id (defaults to 'mobile-nav-container'). */
451
+ id?: string;
255
452
  }
256
- declare function Header({ extrasSlot }: HeaderProps): react_jsx_runtime.JSX.Element;
453
+ /**
454
+ * Politogy header (top bar). Ported from
455
+ * react/app/src/layouts/AuthenticatedLayout.tsx lines 2545–2924 (2026-05-13).
456
+ *
457
+ * Composition (left → right):
458
+ * 1. Hamburger (mobile only) + small brand logo (mobile only) + title +
459
+ * breadcrumbs.
460
+ * 2. headerActions (app-supplied React node, e.g., page action buttons).
461
+ * 3. headerIconsSlot (app-supplied React node, e.g., FuelPopover,
462
+ * NewTextBellPopup, SystemAlertsMenu, NavigationToggleMenu,
463
+ * ImportProgressIndicator, DevNotesMenu, SupportRequestAction).
464
+ * 4. UserMenu (avatar + name/email VStack + chevron).
465
+ *
466
+ * NOTE: app-specific widgets stay in the app. The shell only renders
467
+ * what the app passes through `headerActions` + `headerIconsSlot`. As of
468
+ * v0.3.1, the shell no longer renders a separate `devNotesMenu` slot
469
+ * after `headerIconsSlot` — apps must inline DevNotesMenu inside
470
+ * `headerIconsSlot` so they have full control of icon ordering. The
471
+ * `devNotesMenu` prop on <ShellChrome> is still accepted for backward
472
+ * compat but is ignored.
473
+ */
474
+ declare function Header({ onOpen, id }: HeaderProps): react_jsx_runtime.JSX.Element;
257
475
 
258
476
  interface SidebarProps {
259
- entries: AppRegistryEntry[];
260
- currentApp: string;
261
- footerSlot?: ReactNode;
477
+ /** Mobile close handler (renders the X button on mobile when set). */
478
+ onClose?: () => void;
479
+ /** DOM id for the sidebar root (defaults to 'sidebar-container'). */
480
+ id?: string;
262
481
  }
263
- declare function Sidebar({ entries, currentApp, footerSlot }: SidebarProps): react_jsx_runtime.JSX.Element;
482
+ /**
483
+ * Politogy sidebar. Ported from
484
+ * react/app/src/layouts/AuthenticatedLayout.tsx lines 3289–4192 (2026-05-13)
485
+ * but stripped of the AI-sidebar block (moved to app's navItems pipeline).
486
+ *
487
+ * Renders, top to bottom:
488
+ * - Brand logo + (mobile) close button
489
+ * - Org logo (large) if present
490
+ * - <OrgPill /> — organization switcher
491
+ * - <ModePill /> — mode switcher
492
+ * - Nav items (from useShellNavItems)
493
+ * - Footer (Privacy / Terms / Subscriptions links + commit/version display)
494
+ */
495
+ declare function Sidebar({ onClose, id }: SidebarProps): react_jsx_runtime.JSX.Element;
264
496
 
265
497
  interface FooterProps {
266
498
  buildInfo?: string;
@@ -268,17 +500,111 @@ interface FooterProps {
268
500
  declare function Footer({ buildInfo }: FooterProps): react_jsx_runtime.JSX.Element;
269
501
 
270
502
  /**
271
- * Avatar dropdown rendered at the right side of the header. Reads auth,
272
- * linked-accounts, and chrome context from ShellProvider.
503
+ * Avatar dropdown rendered on the right of the header. Ported to match the
504
+ * legacy menu in react/app/src/layouts/AuthenticatedLayout.tsx lines
505
+ * 2680–2898 (2026-05-13).
506
+ *
507
+ * Sections (in order):
508
+ * 1. Trigger — avatar + name/email VStack + chevron (md+ only).
509
+ * 2. My Profile / Continue Onboarding (gated) / Organization Settings.
510
+ * 3. ROLES & ORGANIZATIONS — current-org role Badge OR activeRoleConfig.
511
+ * 4. ACCOUNTS — current account indicator + linkedAccounts list with
512
+ * inline FiTrash2 remove + "Add Account" item.
513
+ * 5. Sign out.
273
514
  */
274
515
  declare function UserMenu(): react_jsx_runtime.JSX.Element | null;
275
516
 
276
517
  /**
277
- * Organization switcher rendered in the header. Reads from
278
- * useShellOrganization(); renders nothing when no `organization` prop was
279
- * supplied to ShellProvider.
518
+ * Sidebar organization switcher pill. Ported from
519
+ * react/app/src/layouts/AuthenticatedLayout.tsx lines 3795–3957 (2026-05-13).
520
+ *
521
+ * Reads useShellOrganization + useShellAuth. Renders nothing when there's
522
+ * no organization context.
523
+ */
524
+ declare function OrgPill(): react_jsx_runtime.JSX.Element | null;
525
+
526
+ /**
527
+ * Sidebar mode selector pill. Ported from
528
+ * react/app/src/layouts/AuthenticatedLayout.tsx lines 3959–4006 (2026-05-13).
529
+ *
530
+ * Reads useShellMode. Renders nothing when no mode context is supplied or
531
+ * when the app has only one mode available.
532
+ */
533
+ declare function ModePill(): react_jsx_runtime.JSX.Element | null;
534
+
535
+ interface NavItemSubItem {
536
+ name: string;
537
+ icon?: unknown;
538
+ brandIcon?: string;
539
+ href?: string;
540
+ badge?: string;
541
+ subLabel?: string;
542
+ disabled?: boolean;
543
+ }
544
+ interface NavItemProps {
545
+ icon?: unknown;
546
+ brandIcon?: string;
547
+ children: ReactNode;
548
+ href?: string;
549
+ action?: () => void;
550
+ subItems?: NavItemSubItem[];
551
+ badge?: string;
552
+ subLabel?: string;
553
+ isSubItem?: boolean;
554
+ isExpanded?: boolean;
555
+ onToggle?: (menuKey?: string | null) => void;
556
+ menuKey?: string;
557
+ isDisabled?: boolean;
558
+ disabled?: boolean;
559
+ /** Catch-all for one-off Chakra Box overrides passed by callers. */
560
+ [key: string]: unknown;
561
+ }
562
+ /**
563
+ * Single sidebar nav row. Ported verbatim from
564
+ * react/app/src/layouts/AuthenticatedLayout.tsx lines 1292–1730 (2026-05-13)
565
+ * with mode + navigation-preference context reads swapped for shell hooks.
566
+ *
567
+ * Renders:
568
+ * - Top-level rows with optional children (accordion).
569
+ * - Sub-items inside an expanded parent (children list).
570
+ * - Active state via `data-nav-item-active` and primary-color fill.
571
+ * - Mode-aware hover gradient that sweeps left-to-right.
280
572
  */
281
- declare function OrgSelector(): react_jsx_runtime.JSX.Element | null;
573
+ declare function NavItem({ icon, brandIcon, children, href, action, subItems, badge, subLabel, isSubItem, isExpanded, onToggle, menuKey, isDisabled: navIsDisabled, disabled, ...rest }: NavItemProps): react_jsx_runtime.JSX.Element;
574
+
575
+ interface BrandLogoProps {
576
+ src?: string;
577
+ alt?: string;
578
+ className?: string;
579
+ style?: CSSProperties;
580
+ }
581
+ /**
582
+ * Mode-aware brand logo rendered in the sidebar header. The host app
583
+ * supplies `src` (e.g., a different image per mode); the shell wraps it
584
+ * in a non-draggable <img> so it never accidentally drags on click.
585
+ *
586
+ * Render returns null when no src is supplied so consuming chrome can
587
+ * gracefully omit the slot.
588
+ */
589
+ declare function BrandLogo({ src, alt, className, style }: BrandLogoProps): react_jsx_runtime.JSX.Element | null;
590
+
591
+ interface BrandIconProps {
592
+ /** Brand-icon name keyed off `/brand/icons/<name>.svg` in the app's public dir. */
593
+ name: string;
594
+ /** Pixel size shorthand — sets both width and height. */
595
+ size?: number;
596
+ className?: string;
597
+ style?: CSSProperties;
598
+ alt?: string;
599
+ /** Optional prefix for the icon path. Defaults to '/brand/icons/'. */
600
+ basePath?: string;
601
+ }
602
+ /**
603
+ * Brand-icon component used by sidebar NavItems. The actual SVG assets live
604
+ * in the consuming app's `public/brand/icons/<name>.svg` — shell never
605
+ * imports them directly, only references them by URL.
606
+ */
607
+ declare function BrandIcon({ name, size, className, style, alt, basePath, }: BrandIconProps): react_jsx_runtime.JSX.Element;
282
608
 
283
609
  /**
284
610
  * Support icon + modal rendered in the header. Reads auth, org, and support
@@ -287,9 +613,53 @@ declare function OrgSelector(): react_jsx_runtime.JSX.Element | null;
287
613
  */
288
614
  declare function SupportRequestButton(): react_jsx_runtime.JSX.Element | null;
289
615
 
616
+ interface CommitCopyButtonProps {
617
+ /**
618
+ * Pre-rendered environment chip (e.g., the app's own `EnvironmentBanner`).
619
+ * Takes precedence over `environmentLabel`. Click anywhere on the chip
620
+ * copies the full commit SHA.
621
+ */
622
+ envNode?: ReactNode;
623
+ /**
624
+ * Environment label (e.g., 'staging', 'production', 'local'). When
625
+ * `envNode` is not supplied, the component renders a default chip
626
+ * keyed off this label with appropriate background/border color.
627
+ */
628
+ environmentLabel?: string;
629
+ /** Full git commit SHA. Last 4 characters are rendered; click copies the full SHA. */
630
+ commit?: string;
631
+ /** App version, e.g., '2.34.1'. Renders as `v{version}`. */
632
+ version?: string;
633
+ /** ISO date string of the commit. Formatted as 'Mon D'. */
634
+ commitDate?: string;
635
+ /** Commit author name (e.g., 'Leland Smith'). First name is shown. */
636
+ commitAuthor?: string;
637
+ /** Full commit message body — shown as a tooltip over the env chip. */
638
+ commitLog?: string;
639
+ /**
640
+ * Optional click handler for the diagnostics icon. When unset, the
641
+ * icon is not rendered.
642
+ */
643
+ onDiagnosticsClick?: () => void;
644
+ }
645
+ /**
646
+ * Footer commit info pill. Ported from
647
+ * `react/app/src/layouts/AuthenticatedLayout.tsx::CommitCopyButton`
648
+ * (lines 3017–3284, 2026-05-13).
649
+ *
650
+ * Visual: two stacked rows.
651
+ * Row 1: [env chip] | {last4 SHA} | v{version} | [diagnostics icon]
652
+ * Row 2: | {Mon D} | {firstName} | (only when date or author present)
653
+ *
654
+ * Clicking the env chip copies the full SHA via `useClipboard`, with a
655
+ * brief "Copied" toast that fades up. Hovering the env chip shows the
656
+ * full commit log in a tooltip.
657
+ */
658
+ declare function CommitCopyButton({ envNode, environmentLabel, commit, version, commitDate, commitAuthor, commitLog, onDiagnosticsClick, }: CommitCopyButtonProps): react_jsx_runtime.JSX.Element;
659
+
290
660
  interface ShellChromeProps {
291
661
  children: ReactNode;
292
- /** Drives <OrgSelector /> in the header. */
662
+ /** Drives <OrgPill /> in the sidebar. */
293
663
  organization?: ShellOrganizationValue | null;
294
664
  /** Drives the UserMenu Switch-account section. */
295
665
  linkedAccounts?: ShellLinkedAccountsValue | null;
@@ -299,6 +669,35 @@ interface ShellChromeProps {
299
669
  devNotesMenu?: ReactNode;
300
670
  /** UserMenu profile link target. Defaults to '/my-profile'. */
301
671
  myProfileHref?: string;
672
+ /** Drives <ModePill /> + active row colors. */
673
+ mode?: ShellModeValue | null;
674
+ /** The sidebar nav rows. */
675
+ navItems?: ShellNavItem[];
676
+ /** User's nav-rendering preference. */
677
+ navigationPreference?: ShellNavigationPreferenceValue | null;
678
+ /** Active-role display info for the UserMenu role badge. */
679
+ role?: ShellRoleValue | null;
680
+ /** Footer data for the sidebar bottom row. */
681
+ footer?: ShellFooterValue | null;
682
+ /** Image src for the sidebar BrandLogo (top-left). */
683
+ brandLogoSrc?: string;
684
+ /** Header right-side icon stack (Fuel, NewTextBell, Alerts, Toggle, ImportProgress, etc). */
685
+ headerIconsSlot?: ReactNode;
686
+ /** href used by the UserMenu "Organization Settings" item. */
687
+ organizationSettingsHref?: string;
688
+ /** When true, UserMenu shows "Continue Onboarding" item. */
689
+ showContinueOnboarding?: boolean;
690
+ /** Click handler for UserMenu "Continue Onboarding". */
691
+ onContinueOnboarding?: () => void;
692
+ /** Header page title text. */
693
+ pageTitle?: string;
694
+ /** Header breadcrumb chips. */
695
+ breadcrumbs?: Array<{
696
+ label: string;
697
+ href?: string;
698
+ }>;
699
+ /** Header right-side action buttons (rendered before the icon row). */
700
+ headerActions?: ReactNode;
302
701
  }
303
702
  /**
304
703
  * Drop-in chrome binding for apps where the org/linked-account/support data
@@ -312,7 +711,56 @@ interface ShellChromeProps {
312
711
  * Apps that have all the data available at the ShellProvider construction
313
712
  * site can pass the same props to <ShellProvider> directly instead.
314
713
  */
315
- declare function ShellChrome({ children, organization, linkedAccounts, support, devNotesMenu, myProfileHref, }: ShellChromeProps): react_jsx_runtime.JSX.Element;
714
+ declare function ShellChrome({ children, organization, linkedAccounts, support, devNotesMenu, myProfileHref, mode, navItems, navigationPreference, role, footer, brandLogoSrc, headerIconsSlot, organizationSettingsHref, showContinueOnboarding, onContinueOnboarding, pageTitle, breadcrumbs, headerActions, }: ShellChromeProps): react_jsx_runtime.JSX.Element;
715
+
716
+ /** Returns a normalized 7-char hex color, or null if the input isn't valid. */
717
+ declare function normalizeHexColor(value?: string | null): string | null;
718
+ /**
719
+ * Returns an `rgba(...)` string lightened toward white by `amount` (0–1),
720
+ * or null if the input isn't a valid hex.
721
+ */
722
+ declare function hexToRgba(hex: string, alpha: number): string | null;
723
+ /**
724
+ * Returns a hex color that is `amount` (0–1) blended from `hex` toward
725
+ * white. Used for the org-menu hover background.
726
+ */
727
+ declare function lightenHexColor(hex: string, amount: number): string | null;
728
+ /**
729
+ * Reads `settings.brand_colors[0].value` off an org-like input and returns
730
+ * the first valid normalized hex. Returns null if the input doesn't have
731
+ * a usable brand color.
732
+ */
733
+ declare function getOrganizationBrandColor(organization?: {
734
+ brandColor?: string | null;
735
+ settings?: {
736
+ brand_colors?: Array<{
737
+ value?: string | null;
738
+ }> | null;
739
+ } | null;
740
+ } | null): string | null;
741
+ /**
742
+ * Returns the two-letter badge for an organization name (e.g., "The Portland
743
+ * Company" -> "TP"). Falls back to "OR" when the input has no letters.
744
+ */
745
+ declare function getOrganizationBadgeLetters(name?: string | null): string;
746
+
747
+ interface UserLike {
748
+ profile?: {
749
+ full_name?: string | null;
750
+ name?: string | null;
751
+ } | null;
752
+ user_metadata?: {
753
+ full_name?: string | null;
754
+ name?: string | null;
755
+ } | null;
756
+ email?: string | null;
757
+ }
758
+ /**
759
+ * Resolves a user-facing display name from a user object. Tries profile
760
+ * fields first, then user_metadata, then the email local-part, then the
761
+ * raw email, finally falling back to "User".
762
+ */
763
+ declare function getUserDisplayName(user: UserLike | null | undefined): string;
316
764
 
317
765
  interface RegisterShellPrecacheOptions {
318
766
  /** Path the host app serves the SW from. Default: '/sw-shell.js'. */
@@ -340,4 +788,4 @@ declare function registerShellPrecache(opts?: RegisterShellPrecacheOptions): Pro
340
788
  */
341
789
  declare function buildSpeculationRules(currentApp: string, registry: AppRegistryEntry[]): string | null;
342
790
 
343
- export { AppLayout, type AppRegistryEntry, BreadcrumbBar, Card, Footer, GlobalUiIdProvider, Header, HeaderTabBar, type HeaderTabBarItem, OrgSelector, PageContainer, PageHeader, type ShellAuthStatus, type ShellAuthValue, ShellChrome, ShellChromeContext, type ShellChromeProps, type ShellLinkedAccount, ShellLinkedAccountsContext, type ShellLinkedAccountsValue, ShellOrgContext, type ShellOrganization, type ShellOrganizationValue, ShellProvider, type ShellProviderProps, type ShellSlots, type ShellSupportContext, ShellSupportProviderContext, type ShellSupportValue, type ShellUser, Sidebar, SupportRequestButton, UserMenu, buildSpeculationRules, politogyTheme, registerShellPrecache, useAppRegistry, useCurrentApp, useShellAuth, useShellChrome, useShellLinkedAccounts, useShellOrganization, useShellSupport };
791
+ export { AppLayout, type AppRegistryEntry, BrandIcon, BrandLogo, BreadcrumbBar, Card, CommitCopyButton, type CommitCopyButtonProps, Footer, GlobalUiIdProvider, Header, HeaderTabBar, type HeaderTabBarItem, ModePill, NavItem, OrgPill, OrgPill as OrgSelector, PageContainer, PageHeader, type ShellActiveRoleConfig, type ShellAuthStatus, type ShellAuthValue, ShellChrome, ShellChromeContext, type ShellChromeProps, type ShellChromeValue, ShellFooterContext, type ShellFooterLink, type ShellFooterValue, type ShellLinkedAccount, ShellLinkedAccountsContext, type ShellLinkedAccountsValue, type ShellModeConfig, ShellModeContext, type ShellModeValue, type ShellNavItem, ShellNavItemsContext, type ShellNavItemsValue, ShellNavigationPreferenceContext, type ShellNavigationPreferenceValue, ShellOrgContext, type ShellOrganization, type ShellOrganizationValue, ShellProvider, type ShellProviderProps, ShellRoleContext, type ShellRoleValue, type ShellSlots, type ShellSupportContext, ShellSupportProviderContext, type ShellSupportValue, type ShellUser, Sidebar, SupportRequestButton, UserMenu, buildSpeculationRules, getOrganizationBadgeLetters, getOrganizationBrandColor, getUserDisplayName, hexToRgba, lightenHexColor, normalizeHexColor, politogyTheme, registerShellPrecache, useAppRegistry, useCurrentApp, useShellAuth, useShellChrome, useShellFooter, useShellLinkedAccounts, useShellMode, useShellNavItems, useShellNavigationPreference, useShellOrganization, useShellRole, useShellSupport };