@the-portland-company/shell 0.71.0 → 0.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/chrome.css CHANGED
@@ -421,9 +421,16 @@
421
421
  --sidebar-mode-selected-bg: #2F3136;
422
422
  }
423
423
 
424
+ /* Left-Navigation §5/§12: Campaign rail is Deep Race Red, raised wells
425
+ #A12430, inactive row text #F0CFD2, eyebrow #F6DADD. */
424
426
  [data-politogy-mode="campaign"] {
425
427
  --sidebar-bg: #8F1F2A;
426
428
  --sidebar-hover-bg: #7A1A23;
429
+ --sidebar-card-bg: #A12430;
430
+ --mode-track-bg: #A12430;
431
+ --sidebar-mode-selected-bg: #B32B38;
432
+ --sidebar-row-text: #F0CFD2;
433
+ --sidebar-eyebrow: #F6DADD;
427
434
  }
428
435
 
429
436
 
@@ -6,6 +6,7 @@ import clsx from 'clsx';
6
6
  import { FiUser, FiSettings, FiMessageSquare, FiMail, FiInfo, FiSun, FiMoon, FiHelpCircle, FiLifeBuoy, FiAlertCircle, FiAlertTriangle, FiBell, FiGrid, FiZap, FiBatteryCharging, FiBattery } from 'react-icons/fi';
7
7
  import { createPortal } from 'react-dom';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+ import { LuSignpost, LuDoorOpen, LuChartNoAxesColumn, LuLandmark, LuCrosshair, LuCircleUser, LuClipboardList, LuMousePointerClick, LuUsersRound, LuLayoutDashboard, LuFlag, LuTarget, LuMapPin, LuMap, LuPhone, LuShare2, LuDollarSign, LuCreditCard, LuSettings, LuBriefcase, LuChartColumn, LuUser, LuClock, LuSend, LuFileText, LuPencil, LuUpload, LuList, LuLayoutGrid, LuLifeBuoy, LuActivity, LuMessageSquare, LuMail, LuUsers, LuHouse } from 'react-icons/lu';
9
10
 
10
11
  function useTopBarIconSlotGlyph(slot) {
11
12
  const [name, setName] = useState(null);
@@ -1749,6 +1750,45 @@ function useThemePreference() {
1749
1750
  );
1750
1751
  return { value, setValue };
1751
1752
  }
1753
+ var standardNavIcons = {
1754
+ home: LuHouse,
1755
+ users: LuUsers,
1756
+ mail: LuMail,
1757
+ messageSquare: LuMessageSquare,
1758
+ layout: LuLayoutDashboard,
1759
+ activity: LuActivity,
1760
+ lifeBuoy: LuLifeBuoy,
1761
+ grid: LuLayoutGrid,
1762
+ list: LuList,
1763
+ upload: LuUpload,
1764
+ edit: LuPencil,
1765
+ fileText: LuFileText,
1766
+ send: LuSend,
1767
+ clock: LuClock,
1768
+ user: LuUser,
1769
+ barChart: LuChartColumn,
1770
+ briefcase: LuBriefcase,
1771
+ settings: LuSettings,
1772
+ creditCard: LuCreditCard,
1773
+ dollarSign: LuDollarSign,
1774
+ share: LuShare2,
1775
+ // Campaign / Petition mode slots.
1776
+ phone: LuPhone,
1777
+ map: LuMap,
1778
+ mapPin: LuMapPin,
1779
+ target: LuTarget,
1780
+ flag: LuFlag,
1781
+ layoutDashboard: LuLayoutDashboard,
1782
+ usersRound: LuUsersRound,
1783
+ mousePointerClick: LuMousePointerClick,
1784
+ clipboardList: LuClipboardList,
1785
+ circleUser: LuCircleUser,
1786
+ crosshair: LuCrosshair,
1787
+ landmark: LuLandmark,
1788
+ chartNoAxes: LuChartNoAxesColumn,
1789
+ doorOpen: LuDoorOpen,
1790
+ signpost: LuSignpost
1791
+ };
1752
1792
 
1753
1793
  // src/native/standardNav.ts
1754
1794
  var CAMPAIGN_FEATURE_AVAILABILITY = {
@@ -1862,7 +1902,7 @@ var APP_SIGNS_CHILDREN = [
1862
1902
  function standardPolitogyNav(opts) {
1863
1903
  const base = opts.coreBaseUrl.replace(/\/+$/, "");
1864
1904
  const abs = (path) => `${base}${path.startsWith("/") ? path : `/${path}`}`;
1865
- const icon = (key) => opts.icons?.[key];
1905
+ const icon = (key) => opts.icons?.[key] ?? standardNavIcons[key];
1866
1906
  const orgParam = opts.activeOrgId ? `org=${opts.activeOrgId}` : "";
1867
1907
  const withOrg = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
1868
1908
  const leaves = (children) => children.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(abs(c.path)) }));
@@ -2074,6 +2114,30 @@ function hasActiveChild(item, pathname, activeFn) {
2074
2114
  )
2075
2115
  );
2076
2116
  }
2117
+ function firstLeafHref(item) {
2118
+ for (const c of item.children ?? []) {
2119
+ if (c.kind === "section") continue;
2120
+ if (c.href) return c.href;
2121
+ const deep = firstLeafHref(c);
2122
+ if (deep) return deep;
2123
+ }
2124
+ return void 0;
2125
+ }
2126
+ function modeIdFromLabel(label) {
2127
+ const l = label?.trim().toLowerCase();
2128
+ return l ? l.replace(/\s+mode$/, "") : void 0;
2129
+ }
2130
+ function shortUserName(name) {
2131
+ const parts = name.trim().split(/\s+/).filter(Boolean);
2132
+ if (parts.length < 2) return parts[0] ?? "";
2133
+ return `${parts[0]} ${parts[parts.length - 1][0].toUpperCase()}.`;
2134
+ }
2135
+ function shortEnvLabel(label) {
2136
+ const l = label.trim().toLowerCase();
2137
+ if (l === "production") return "prod";
2138
+ if (l === "development") return "dev";
2139
+ return l;
2140
+ }
2077
2141
  function envChipClasses(label) {
2078
2142
  const l = label.toLowerCase();
2079
2143
  if (l === "production" || l === "prod")
@@ -2184,7 +2248,6 @@ function NavSidebar({
2184
2248
  useEffect(() => {
2185
2249
  setOpenGroup(activeGroupKey);
2186
2250
  }, [activeGroupKey]);
2187
- const toggleGroup = (key) => setOpenGroup((prev) => prev === key ? null : key);
2188
2251
  return /* @__PURE__ */ jsxs(RailCollapsibleContext.Provider, { value: collapsible, children: [
2189
2252
  open ? /* @__PURE__ */ jsx(
2190
2253
  "div",
@@ -2524,21 +2587,16 @@ function NavSidebar({
2524
2587
  });
2525
2588
  }
2526
2589
  if (item.children && item.children.length > 0) {
2527
- const key = groupKeyOf(item, idx);
2528
2590
  const selfActive = item.href ? activeFn(pathname, item.href) : false;
2529
2591
  const parentActive = selfActive || hasActiveChild(item, pathname, activeFn);
2530
2592
  return /* @__PURE__ */ jsx(
2531
- NavGroup,
2593
+ NavRow,
2532
2594
  {
2533
- item,
2595
+ item: { ...item, href: item.href ?? firstLeafHref(item), children: void 0 },
2534
2596
  active: parentActive,
2535
- open: openGroup === key,
2536
- onToggle: () => toggleGroup(key),
2537
- pathname,
2538
- activeFn,
2539
2597
  Link
2540
2598
  },
2541
- key
2599
+ item.href ?? groupKeyOf(item, idx)
2542
2600
  );
2543
2601
  }
2544
2602
  const active = item.href ? activeFn(pathname, item.href) : false;
@@ -2573,41 +2631,26 @@ function NavSidebar({
2573
2631
  }
2574
2632
  )
2575
2633
  ] }, l.label)) }) : null,
2576
- footer.envLabel && footer.envLabel.trim().toLowerCase() !== "production" ? /* @__PURE__ */ jsxs(
2634
+ footer.envLabel || footer.commit || footer.version ? /* @__PURE__ */ jsxs(
2577
2635
  "div",
2578
2636
  {
2579
2637
  "data-shell-meta": true,
2580
- className: `mt-1.5 flex flex-col items-start gap-0.5 font-[family-name:var(--font-plex-mono)] text-[10px] text-[color:var(--sidebar-meta-text,var(--sidebar-text))] ${rc("max-md:hidden")}`,
2638
+ className: `mt-1.5 flex flex-col items-center gap-0.5 font-[family-name:var(--font-plex-mono)] text-[11px] text-[color:var(--sidebar-meta-text,rgba(255,255,255,0.4))] ${rc("max-md:hidden")}`,
2581
2639
  children: [
2582
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
2583
- /* @__PURE__ */ jsx(
2584
- "span",
2585
- {
2586
- className: [
2587
- "rounded-md px-1.5 py-0.5 text-[10px] font-semibold",
2588
- envChipClasses(footer.envLabel)
2589
- ].join(" "),
2590
- children: footer.envLabel
2591
- }
2592
- ),
2593
- footer.commit ? /* @__PURE__ */ jsxs(Fragment, { children: [
2594
- /* @__PURE__ */ jsx("span", { className: "text-[color:var(--muted)]", children: "|" }),
2595
- /* @__PURE__ */ jsx("span", { children: footer.commit.slice(-4) })
2596
- ] }) : null,
2597
- footer.version ? /* @__PURE__ */ jsxs(Fragment, { children: [
2598
- /* @__PURE__ */ jsx("span", { className: "text-[color:var(--muted)]", children: "|" }),
2599
- /* @__PURE__ */ jsxs("span", { children: [
2600
- "v",
2601
- footer.version
2602
- ] })
2603
- ] }) : null
2604
- ] }),
2640
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: [
2641
+ footer.envLabel ? shortEnvLabel(footer.envLabel) : null,
2642
+ footer.commit ? footer.commit.slice(-4) : null,
2643
+ footer.version ? `v${footer.version.replace(/^v/, "")}` : null
2644
+ ].filter((v) => Boolean(v)).map((v, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
2645
+ i > 0 ? /* @__PURE__ */ jsx("span", { children: "|" }) : null,
2646
+ /* @__PURE__ */ jsx("span", { children: v })
2647
+ ] }, i)) }),
2605
2648
  footer.commitDate || footer.commitAuthor ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
2606
2649
  footer.commitDate ? /* @__PURE__ */ jsx("span", { children: new Date(footer.commitDate).toLocaleDateString(void 0, {
2607
2650
  month: "short",
2608
2651
  day: "numeric"
2609
2652
  }) }) : null,
2610
- footer.commitDate && footer.commitAuthor ? /* @__PURE__ */ jsx("span", { className: "text-[color:var(--muted)]", children: "|" }) : null,
2653
+ footer.commitDate && footer.commitAuthor ? /* @__PURE__ */ jsx("span", { children: "|" }) : null,
2611
2654
  footer.commitAuthor ? /* @__PURE__ */ jsx("span", { children: footer.commitAuthor.split(/\s+/)[0] }) : null
2612
2655
  ] }) : null
2613
2656
  ]
@@ -2841,142 +2884,6 @@ function NavRow({
2841
2884
  }
2842
2885
  );
2843
2886
  }
2844
- function NavGroup({
2845
- item,
2846
- active,
2847
- open,
2848
- onToggle,
2849
- pathname,
2850
- activeFn,
2851
- Link
2852
- }) {
2853
- const rc = useRailCollapse();
2854
- const Icon = item.icon;
2855
- const headerClasses = [
2856
- "group relative block w-full overflow-hidden text-left transition",
2857
- open ? "rounded-t-[5px]" : "rounded-[5px]",
2858
- active ? NAV_TOP_ACTIVE_CLASS : open ? "bg-[color:var(--sidebar-row-hover-bg,var(--panel))] text-[color:var(--sidebar-text,var(--foreground))]" : NAV_TOP_INACTIVE_CLASS
2859
- ].join(" ");
2860
- return /* @__PURE__ */ jsxs("div", { children: [
2861
- /* @__PURE__ */ jsxs(
2862
- "button",
2863
- {
2864
- type: "button",
2865
- onClick: () => {
2866
- onToggle();
2867
- item.onClick?.();
2868
- },
2869
- "aria-expanded": open,
2870
- title: item.label,
2871
- className: headerClasses,
2872
- children: [
2873
- active ? /* @__PURE__ */ jsx(NavActiveRail, {}) : null,
2874
- /* @__PURE__ */ jsxs("span", { className: `relative z-10 flex items-center ${NAV_TOP_ROW_CLASS(active)} ${rc("max-md:justify-center max-md:px-0")}`, children: [
2875
- Icon ? /* @__PURE__ */ jsx(Icon, { size: NAV_TOP_ICON_SIZE, className: "shrink-0 text-current" }) : null,
2876
- /* @__PURE__ */ jsx("span", { className: `min-w-0 flex-1 truncate ${rc("max-md:hidden")}`, children: item.label }),
2877
- /* @__PURE__ */ jsx(NavRowBadge, { value: item.badge }),
2878
- /* @__PURE__ */ jsx(
2879
- ChevronDown,
2880
- {
2881
- className: [
2882
- "shrink-0 opacity-80 transition-transform duration-200",
2883
- open ? "rotate-180" : "",
2884
- rc("max-md:hidden")
2885
- ].join(" ")
2886
- }
2887
- )
2888
- ] })
2889
- ]
2890
- }
2891
- ),
2892
- open ? /* @__PURE__ */ jsx("div", { className: `overflow-hidden rounded-b-md bg-[color:var(--nav-submenu-bg)] p-1 ${rc("max-md:hidden")}`, children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: item.children.map((child, i) => {
2893
- if (child.kind === "section") {
2894
- return /* @__PURE__ */ jsx(
2895
- NavSectionRow,
2896
- {
2897
- label: child.label,
2898
- first: i === 0,
2899
- variant: "sub"
2900
- },
2901
- `sub-section-${i}-${child.label}`
2902
- );
2903
- }
2904
- const childActive = child.href ? activeFn(pathname, child.href) : false;
2905
- if (child.children && child.children.length > 0) {
2906
- return /* @__PURE__ */ jsx(
2907
- NavSubGroup,
2908
- {
2909
- item: child,
2910
- pathname,
2911
- activeFn,
2912
- Link
2913
- },
2914
- child.href ?? `subgrp-${i}-${child.label}`
2915
- );
2916
- }
2917
- return /* @__PURE__ */ jsx(
2918
- NavRow,
2919
- {
2920
- item: child,
2921
- active: childActive,
2922
- Link,
2923
- variant: "sub"
2924
- },
2925
- child.href ?? `sub-${i}-${child.label}`
2926
- );
2927
- }) }) }) : null
2928
- ] });
2929
- }
2930
- function NavSubGroup({
2931
- item,
2932
- pathname,
2933
- activeFn,
2934
- Link
2935
- }) {
2936
- const ownsActive = (item.href ? activeFn(pathname, item.href) : false) || (item.children ?? []).some((c) => c.href ? activeFn(pathname, c.href) : false);
2937
- const [open, setOpen] = useState(ownsActive);
2938
- useEffect(() => {
2939
- if (ownsActive) setOpen(true);
2940
- }, [ownsActive]);
2941
- const Icon = item.icon;
2942
- return /* @__PURE__ */ jsxs("div", { children: [
2943
- /* @__PURE__ */ jsxs(
2944
- "button",
2945
- {
2946
- type: "button",
2947
- onClick: () => setOpen((v) => !v),
2948
- "aria-expanded": open,
2949
- className: [
2950
- "flex w-full items-center gap-2.5 rounded px-3 py-1.5 text-left text-[13px] font-medium transition",
2951
- ownsActive ? "text-[color:var(--color-accent)]" : "text-[color:var(--sidebar-text,var(--muted))] hover:bg-[color:var(--nav-row-hover)] hover:text-[color:var(--foreground)]"
2952
- ].join(" "),
2953
- children: [
2954
- Icon ? /* @__PURE__ */ jsx(Icon, { size: 15, className: "shrink-0 text-current" }) : null,
2955
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: item.label }),
2956
- /* @__PURE__ */ jsx(
2957
- ChevronDown,
2958
- {
2959
- className: [
2960
- "shrink-0 opacity-70 transition-transform duration-200",
2961
- open ? "rotate-180" : ""
2962
- ].join(" ")
2963
- }
2964
- )
2965
- ]
2966
- }
2967
- ),
2968
- open ? /* @__PURE__ */ jsx("div", { className: "ml-4 flex flex-col gap-0.5 border-l border-[color:var(--line)] pl-2", children: item.children.map((leaf, i) => /* @__PURE__ */ jsx(
2969
- NavRow,
2970
- {
2971
- item: leaf,
2972
- active: leaf.href ? activeFn(pathname, leaf.href) : false,
2973
- Link,
2974
- variant: "sub"
2975
- },
2976
- leaf.href ?? `subsub-${i}-${leaf.label}`
2977
- )) }) : null
2978
- ] });
2979
- }
2980
2887
  function OrgIdCopyButton({ id }) {
2981
2888
  const [copied, setCopied] = useState(false);
2982
2889
  return /* @__PURE__ */ jsx(
@@ -3276,8 +3183,8 @@ function NavSidebarUserCard({
3276
3183
  }) {
3277
3184
  const rawName = user.name?.trim() || "";
3278
3185
  const hasRealName = rawName.length > 0 && !rawName.includes("@");
3279
- const displayName = hasRealName ? rawName : user.email ?? "Signed in";
3280
- const initials = (hasRealName ? rawName : user.email ?? "P").slice(0, 2).toUpperCase();
3186
+ const displayName = hasRealName ? shortUserName(rawName) : user.email ?? "Signed in";
3187
+ const initials = hasRealName ? rawName.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0]).join("").toUpperCase() : (user.email ?? "P").slice(0, 2).toUpperCase();
3281
3188
  const secondary = hasRealName ? user.email || [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member" : [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member";
3282
3189
  const rc = useRailCollapse();
3283
3190
  return /* @__PURE__ */ jsxs("details", { "data-nav-details": true, className: "group/acct relative", children: [
@@ -3677,7 +3584,7 @@ function NavAppShell({
3677
3584
  return /* @__PURE__ */ jsxs(
3678
3585
  "div",
3679
3586
  {
3680
- "data-politogy-mode": modeId,
3587
+ "data-politogy-mode": modeId ?? modeIdFromLabel(sidebar.mode?.label),
3681
3588
  className: "min-h-screen bg-[color:var(--background)] text-[color:var(--foreground)]",
3682
3589
  children: [
3683
3590
  /* @__PURE__ */ jsx(
@@ -3724,6 +3631,6 @@ function NavAppShell({
3724
3631
  );
3725
3632
  }
3726
3633
 
3727
- export { BETA_BANNER_DISMISS_KEY, CAMPAIGN_FEATURE_AVAILABILITY, CORE_APP_ORIGIN, CORE_BILLING_PATH, FuelAction, NavAppShell, NavBetaBanner, NavChromeProvider, NavDisplayAction, NavSidebar, NavTabStrip, NavThemeControl, NavTopBar, NotificationsAction, SPECS_ORIGIN, SpecOverlayAction, SupportAction, TopBarCountBadge, TopBarPanelArrow, TopBarPopover, TopBarTooltip, TopBarWidgetSlot, clearBetaBannerDismissal, envChipClasses, isNavItemActive, resolveOrgLogoUrl, standardPolitogyNav, topBarIconButtonClass, useChromeMe, useChromeOrgs, useNavChromeFetcher, useThemePreference };
3728
- //# sourceMappingURL=chunk-B2AQL37X.js.map
3729
- //# sourceMappingURL=chunk-B2AQL37X.js.map
3634
+ export { BETA_BANNER_DISMISS_KEY, CAMPAIGN_FEATURE_AVAILABILITY, CORE_APP_ORIGIN, CORE_BILLING_PATH, FuelAction, NavAppShell, NavBetaBanner, NavChromeProvider, NavDisplayAction, NavSidebar, NavTabStrip, NavThemeControl, NavTopBar, NotificationsAction, SPECS_ORIGIN, SpecOverlayAction, SupportAction, TopBarCountBadge, TopBarPanelArrow, TopBarPopover, TopBarTooltip, TopBarWidgetSlot, clearBetaBannerDismissal, envChipClasses, isNavItemActive, modeIdFromLabel, resolveOrgLogoUrl, shortEnvLabel, shortUserName, standardNavIcons, standardPolitogyNav, topBarIconButtonClass, useChromeMe, useChromeOrgs, useNavChromeFetcher, useThemePreference };
3635
+ //# sourceMappingURL=chunk-6OM62ZTK.js.map
3636
+ //# sourceMappingURL=chunk-6OM62ZTK.js.map