@the-portland-company/shell 0.69.0 → 0.71.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/CHANGELOG.md +25 -0
- package/dist/app-chrome.cjs +261 -175
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.js +44 -37
- package/dist/app-chrome.js.map +1 -1
- package/dist/chrome.css +2 -2
- package/dist/{chunk-6UHJV2FH.js → chunk-7YVJ7HQG.js} +41 -3
- package/dist/chunk-7YVJ7HQG.js.map +1 -0
- package/dist/{chunk-WFUWFMCA.js → chunk-B2AQL37X.js} +123 -82
- package/dist/chunk-B2AQL37X.js.map +1 -0
- package/dist/native.cjs +169 -79
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +13 -2
- package/dist/native.d.ts +13 -2
- package/dist/native.js +2 -1
- package/dist/nav-preference.cjs +44 -0
- package/dist/nav-preference.cjs.map +1 -1
- package/dist/nav-preference.d.cts +8 -1
- package/dist/nav-preference.d.ts +8 -1
- package/dist/nav-preference.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-6UHJV2FH.js.map +0 -1
- package/dist/chunk-WFUWFMCA.js.map +0 -1
package/dist/native.d.cts
CHANGED
|
@@ -252,7 +252,7 @@ declare function useThemePreference(): {
|
|
|
252
252
|
* callers map each key to their own icon components (lucide, react-icons, …).
|
|
253
253
|
* A missing key simply renders that row without an icon.
|
|
254
254
|
*/
|
|
255
|
-
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';
|
|
255
|
+
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';
|
|
256
256
|
/** The operating Mode whose nav tree to build. Defaults to `relationship`. */
|
|
257
257
|
type StandardNavMode = 'relationship' | 'campaign' | 'petition';
|
|
258
258
|
/**
|
|
@@ -594,8 +594,19 @@ type NavSidebarProps = {
|
|
|
594
594
|
*/
|
|
595
595
|
open?: boolean;
|
|
596
596
|
onClose?: () => void;
|
|
597
|
+
/**
|
|
598
|
+
* Expands the collapsed (below `md`) rail. When set, the square logo tile at
|
|
599
|
+
* the top of the collapsed rail becomes the "Expand navigation" control —
|
|
600
|
+
* the Left-Navigation Design draws no other toggle and no top-bar hamburger.
|
|
601
|
+
*/
|
|
602
|
+
onOpen?: () => void;
|
|
603
|
+
/**
|
|
604
|
+
* Closes the expanded rail after a nav-link click without counting as the
|
|
605
|
+
* user's Collapse choice. Defaults to `onClose`.
|
|
606
|
+
*/
|
|
607
|
+
onNavigate?: () => void;
|
|
597
608
|
};
|
|
598
|
-
declare function NavSidebar({ pathname, brand, nav, org, mode, footer, linkComponent, open, onClose, }: NavSidebarProps): react_jsx_runtime.JSX.Element;
|
|
609
|
+
declare function NavSidebar({ pathname, brand, nav, org, mode, footer, linkComponent, open, onClose, onOpen, onNavigate, }: NavSidebarProps): react_jsx_runtime.JSX.Element;
|
|
599
610
|
type NavUser = {
|
|
600
611
|
name: string | null;
|
|
601
612
|
email?: string | null;
|
package/dist/native.d.ts
CHANGED
|
@@ -252,7 +252,7 @@ declare function useThemePreference(): {
|
|
|
252
252
|
* callers map each key to their own icon components (lucide, react-icons, …).
|
|
253
253
|
* A missing key simply renders that row without an icon.
|
|
254
254
|
*/
|
|
255
|
-
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';
|
|
255
|
+
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';
|
|
256
256
|
/** The operating Mode whose nav tree to build. Defaults to `relationship`. */
|
|
257
257
|
type StandardNavMode = 'relationship' | 'campaign' | 'petition';
|
|
258
258
|
/**
|
|
@@ -594,8 +594,19 @@ type NavSidebarProps = {
|
|
|
594
594
|
*/
|
|
595
595
|
open?: boolean;
|
|
596
596
|
onClose?: () => void;
|
|
597
|
+
/**
|
|
598
|
+
* Expands the collapsed (below `md`) rail. When set, the square logo tile at
|
|
599
|
+
* the top of the collapsed rail becomes the "Expand navigation" control —
|
|
600
|
+
* the Left-Navigation Design draws no other toggle and no top-bar hamburger.
|
|
601
|
+
*/
|
|
602
|
+
onOpen?: () => void;
|
|
603
|
+
/**
|
|
604
|
+
* Closes the expanded rail after a nav-link click without counting as the
|
|
605
|
+
* user's Collapse choice. Defaults to `onClose`.
|
|
606
|
+
*/
|
|
607
|
+
onNavigate?: () => void;
|
|
597
608
|
};
|
|
598
|
-
declare function NavSidebar({ pathname, brand, nav, org, mode, footer, linkComponent, open, onClose, }: NavSidebarProps): react_jsx_runtime.JSX.Element;
|
|
609
|
+
declare function NavSidebar({ pathname, brand, nav, org, mode, footer, linkComponent, open, onClose, onOpen, onNavigate, }: NavSidebarProps): react_jsx_runtime.JSX.Element;
|
|
599
610
|
type NavUser = {
|
|
600
611
|
name: string | null;
|
|
601
612
|
email?: string | null;
|
package/dist/native.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
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 } from './chunk-
|
|
2
|
+
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 } from './chunk-B2AQL37X.js';
|
|
3
3
|
export { FormColumn } from './chunk-LPSBSAF3.js';
|
|
4
4
|
import './chunk-NHBNM5P3.js';
|
|
5
|
+
import './chunk-7YVJ7HQG.js';
|
|
5
6
|
//# sourceMappingURL=native.js.map
|
|
6
7
|
//# sourceMappingURL=native.js.map
|
package/dist/nav-preference.cjs
CHANGED
|
@@ -59,17 +59,61 @@ var cookie=fromCookie();
|
|
|
59
59
|
if(cookie&&VALID.indexOf(cookie)!==-1){var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}
|
|
60
60
|
if(cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}}
|
|
61
61
|
}catch(e){}})();`;
|
|
62
|
+
var RAIL_STORAGE_KEY = "politogy_rail";
|
|
63
|
+
var RAIL_COOKIE = "politogy_rail";
|
|
64
|
+
var RAIL_DEFAULT = "collapsed";
|
|
65
|
+
function isRailPreference(v) {
|
|
66
|
+
return v === "expanded" || v === "collapsed";
|
|
67
|
+
}
|
|
68
|
+
function readRailPreference() {
|
|
69
|
+
if (typeof document !== "undefined") {
|
|
70
|
+
try {
|
|
71
|
+
const m = document.cookie.match(new RegExp(`(?:^|;\\s*)${RAIL_COOKIE}=([^;]+)`));
|
|
72
|
+
const v = m ? decodeURIComponent(m[1]) : null;
|
|
73
|
+
if (isRailPreference(v)) return v;
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (typeof localStorage !== "undefined") {
|
|
78
|
+
try {
|
|
79
|
+
const v = localStorage.getItem(RAIL_STORAGE_KEY);
|
|
80
|
+
if (isRailPreference(v)) return v;
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return RAIL_DEFAULT;
|
|
85
|
+
}
|
|
86
|
+
function writeRailPreference(pref) {
|
|
87
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
88
|
+
const host = window.location.hostname;
|
|
89
|
+
const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
|
|
90
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
91
|
+
try {
|
|
92
|
+
document.cookie = `${RAIL_COOKIE}=${pref}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
localStorage.setItem(RAIL_STORAGE_KEY, pref);
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
}
|
|
62
100
|
|
|
63
101
|
exports.LEGACY_NAV_DISPLAY_KEY = LEGACY_NAV_DISPLAY_KEY;
|
|
64
102
|
exports.NAV_DISPLAY_COOKIE = NAV_DISPLAY_COOKIE;
|
|
65
103
|
exports.NAV_DISPLAY_DEFAULT = NAV_DISPLAY_DEFAULT;
|
|
66
104
|
exports.NAV_DISPLAY_PREPAINT_SCRIPT = NAV_DISPLAY_PREPAINT_SCRIPT;
|
|
67
105
|
exports.NAV_DISPLAY_STORAGE_KEY = NAV_DISPLAY_STORAGE_KEY;
|
|
106
|
+
exports.RAIL_COOKIE = RAIL_COOKIE;
|
|
107
|
+
exports.RAIL_DEFAULT = RAIL_DEFAULT;
|
|
108
|
+
exports.RAIL_STORAGE_KEY = RAIL_STORAGE_KEY;
|
|
68
109
|
exports.isNavDisplayPreference = isNavDisplayPreference;
|
|
110
|
+
exports.isRailPreference = isRailPreference;
|
|
69
111
|
exports.readNavDisplayCookie = readNavDisplayCookie;
|
|
70
112
|
exports.readNavDisplayLocal = readNavDisplayLocal;
|
|
113
|
+
exports.readRailPreference = readRailPreference;
|
|
71
114
|
exports.resolveNavDisplay = resolveNavDisplay;
|
|
72
115
|
exports.writeNavDisplayCookie = writeNavDisplayCookie;
|
|
73
116
|
exports.writeNavDisplayLocal = writeNavDisplayLocal;
|
|
117
|
+
exports.writeRailPreference = writeRailPreference;
|
|
74
118
|
//# sourceMappingURL=nav-preference.cjs.map
|
|
75
119
|
//# sourceMappingURL=nav-preference.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nav-preference.ts"],"names":[],"mappings":";;;AAwBO,IAAM,uBAAA,GAA0B;AAChC,IAAM,kBAAA,GAAqB;AAG3B,IAAM,sBAAA,GAAyB;AAE/B,IAAM,mBAAA,GAA4C;AAEzD,IAAM,KAAA,GAAyC,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAA;AAE/D,SAAS,uBAAuB,CAAA,EAAuC;AAC5E,EAAA,OAAO,OAAO,CAAA,KAAM,QAAA,IAAa,KAAA,CAA4B,SAAS,CAAC,CAAA;AACzE;AAGO,SAAS,oBAAA,GAAoD;AAClE,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,SAAS,MAAA,CAAO,KAAA;AAAA,MACxB,IAAI,MAAA,CAAO,CAAA,WAAA,EAAc,kBAAkB,CAAA,QAAA,CAAU;AAAA,KACvD;AACA,IAAA,MAAM,IAAI,CAAA,GAAI,kBAAA,CAAmB,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA;AACzC,IAAA,OAAO,sBAAA,CAAuB,CAAC,CAAA,GAAI,CAAA,GAAI,IAAA;AAAA,EACzC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMO,SAAS,sBAAsB,IAAA,EAAkC;AACtE,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,OAAO,WAAW,WAAA,EAAa;AACtE,EAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,QAAA;AAC7B,EAAA,MAAM,UAAA,GAAa,0BAAA,CAA2B,IAAA,CAAK,IAAI,IAAI,2BAAA,GAA8B,EAAA;AACzF,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,QAAA,CAAS,QAAA,KAAa,WAAW,UAAA,GAAa,EAAA;AACpE,EAAA,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,kBAAkB,CAAA,CAAA,EAAI,kBAAA;AAAA,IACzC;AAAA,GACD,CAAA,wCAAA,EAA2C,UAAU,CAAA,EAAG,MAAM,CAAA,CAAA;AACjE;AAGO,SAAS,mBAAA,GAAmD;AACjE,EAAA,IAAI,OAAO,YAAA,KAAiB,WAAA,EAAa,OAAO,IAAA;AAChD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,YAAA,CAAa,OAAA,CAAQ,uBAAuB,CAAA;AAC5D,IAAA,IAAI,sBAAA,CAAuB,OAAO,CAAA,EAAG,OAAO,OAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,sBAAsB,CAAA;AAC1D,IAAA,OAAO,sBAAA,CAAuB,MAAM,CAAA,GAAI,MAAA,GAAS,IAAA;AAAA,EACnD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB,IAAA,EAAkC;AACrE,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACzC,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,OAAA,CAAQ,yBAAyB,IAAI,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGO,SAAS,iBAAA,GAA0C;AACxD,EAAA,OAAO,oBAAA,EAAqB,IAAK,mBAAA,EAAoB,IAAK,mBAAA;AAC5D;AAMO,IAAM,2BAAA,GAA8B,CAAA;AAAA,QAAA,EACjC,IAAA,CAAK,SAAA,CAAU,uBAAuB,CAAC,CAAA;AAAA;AAAA,kEAAA,EAEmB,kBAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,gBAAA","file":"nav-preference.cjs","sourcesContent":["// Universal navigation-display preference — the same cross-app contract as the\n// theme (see ./theme-preference, which this deliberately mirrors).\n//\n// The user's choice of how navigation renders (Menu / Tabs / Both) follows the\n// authenticated user across every Politogy app + subdomain. Three layers:\n// 1. VRM Core `profiles.nav_display_preference` — source of truth, persisted\n// via the chrome API (`PATCH me/preferences { navDisplay }`) and read back\n// from `GET me` (`navDisplay`).\n// 2. `.politogyvrm.com` cookie `politogy_nav_display` — the cross-subdomain\n// vehicle (app session cookies are host-only, and so is localStorage).\n// 3. localStorage — same-app fast reads and cross-tab `storage` events.\n//\n// Before this existed the preference lived ONLY in localStorage under\n// `vrm.navDisplay`, which is per-ORIGIN: every app subdomain kept its own copy\n// and a freshly opened app booted the default, so the setting appeared not to\n// hold when moving between apps. The legacy key is still read as a fallback so\n// an existing local choice survives the upgrade.\n//\n// Server-safe (no 'use client'): layouts may import NAV_DISPLAY_PREPAINT_SCRIPT.\n\nexport type NavDisplayPreference = 'menu' | 'tabs' | 'both'\n\n// One key for BOTH the localStorage store and the cross-subdomain cookie, so a\n// choice in one app is the same key in the next.\nexport const NAV_DISPLAY_STORAGE_KEY = 'politogy_nav_display'\nexport const NAV_DISPLAY_COOKIE = 'politogy_nav_display'\n\n/** Pre-0.37 host-only key. Read for migration; never written. */\nexport const LEGACY_NAV_DISPLAY_KEY = 'vrm.navDisplay'\n\nexport const NAV_DISPLAY_DEFAULT: NavDisplayPreference = 'both'\n\nconst VALID: readonly NavDisplayPreference[] = ['menu', 'tabs', 'both']\n\nexport function isNavDisplayPreference(v: unknown): v is NavDisplayPreference {\n return typeof v === 'string' && (VALID as readonly string[]).includes(v)\n}\n\n/** Read the shared cookie (browser only; null on the server or when unset). */\nexport function readNavDisplayCookie(): NavDisplayPreference | null {\n if (typeof document === 'undefined') return null\n try {\n const m = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)`),\n )\n const v = m ? decodeURIComponent(m[1]) : null\n return isNavDisplayPreference(v) ? v : null\n } catch {\n return null\n }\n}\n\n// Same host-aware scoping as the theme cookie: parent domain on\n// *.politogyvrm.com so every app subdomain reads it, host-only elsewhere\n// (localhost, *.pages.dev preview) because browsers silently drop a mismatched\n// Domain attribute. 1-year, SameSite=Lax, Secure on https.\nexport function writeNavDisplayCookie(pref: NavDisplayPreference): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return\n const host = window.location.hostname\n const domainAttr = /(^|\\.)politogyvrm\\.com$/i.test(host) ? '; Domain=.politogyvrm.com' : ''\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${NAV_DISPLAY_COOKIE}=${encodeURIComponent(\n pref,\n )}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`\n}\n\n/** Read the local store, falling back to the legacy host-only key. */\nexport function readNavDisplayLocal(): NavDisplayPreference | null {\n if (typeof localStorage === 'undefined') return null\n try {\n const current = localStorage.getItem(NAV_DISPLAY_STORAGE_KEY)\n if (isNavDisplayPreference(current)) return current\n const legacy = localStorage.getItem(LEGACY_NAV_DISPLAY_KEY)\n return isNavDisplayPreference(legacy) ? legacy : null\n } catch {\n return null\n }\n}\n\nexport function writeNavDisplayLocal(pref: NavDisplayPreference): void {\n if (typeof localStorage === 'undefined') return\n try {\n localStorage.setItem(NAV_DISPLAY_STORAGE_KEY, pref)\n } catch {\n /* storage unavailable */\n }\n}\n\n/** Boot precedence: cookie → localStorage (incl. legacy) → default. */\nexport function resolveNavDisplay(): NavDisplayPreference {\n return readNavDisplayCookie() ?? readNavDisplayLocal() ?? NAV_DISPLAY_DEFAULT\n}\n\n// Inline pre-paint script — optional, and the mirror of THEME_PREPAINT_SCRIPT.\n// Nav display has no paint-blocking visual (the frame is client-rendered), but\n// seeding localStorage from the cookie before hydration keeps the first render\n// on the synced value instead of the default. Self-contained and silent.\nexport const NAV_DISPLAY_PREPAINT_SCRIPT = `(function(){try{\nvar KEY=${JSON.stringify(NAV_DISPLAY_STORAGE_KEY)};\nvar VALID=[\"menu\",\"tabs\",\"both\"];\nfunction fromCookie(){try{var m=document.cookie.match(/(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}\nvar cookie=fromCookie();\nif(cookie&&VALID.indexOf(cookie)!==-1){var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}\nif(cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}}\n}catch(e){}})();`\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/nav-preference.ts"],"names":[],"mappings":"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","file":"nav-preference.cjs","sourcesContent":["// Universal navigation-display preference — the same cross-app contract as the\n// theme (see ./theme-preference, which this deliberately mirrors).\n//\n// The user's choice of how navigation renders (Menu / Tabs / Both) follows the\n// authenticated user across every Politogy app + subdomain. Three layers:\n// 1. VRM Core `profiles.nav_display_preference` — source of truth, persisted\n// via the chrome API (`PATCH me/preferences { navDisplay }`) and read back\n// from `GET me` (`navDisplay`).\n// 2. `.politogyvrm.com` cookie `politogy_nav_display` — the cross-subdomain\n// vehicle (app session cookies are host-only, and so is localStorage).\n// 3. localStorage — same-app fast reads and cross-tab `storage` events.\n//\n// Before this existed the preference lived ONLY in localStorage under\n// `vrm.navDisplay`, which is per-ORIGIN: every app subdomain kept its own copy\n// and a freshly opened app booted the default, so the setting appeared not to\n// hold when moving between apps. The legacy key is still read as a fallback so\n// an existing local choice survives the upgrade.\n//\n// Server-safe (no 'use client'): layouts may import NAV_DISPLAY_PREPAINT_SCRIPT.\n\nexport type NavDisplayPreference = 'menu' | 'tabs' | 'both'\n\n// One key for BOTH the localStorage store and the cross-subdomain cookie, so a\n// choice in one app is the same key in the next.\nexport const NAV_DISPLAY_STORAGE_KEY = 'politogy_nav_display'\nexport const NAV_DISPLAY_COOKIE = 'politogy_nav_display'\n\n/** Pre-0.37 host-only key. Read for migration; never written. */\nexport const LEGACY_NAV_DISPLAY_KEY = 'vrm.navDisplay'\n\nexport const NAV_DISPLAY_DEFAULT: NavDisplayPreference = 'both'\n\nconst VALID: readonly NavDisplayPreference[] = ['menu', 'tabs', 'both']\n\nexport function isNavDisplayPreference(v: unknown): v is NavDisplayPreference {\n return typeof v === 'string' && (VALID as readonly string[]).includes(v)\n}\n\n/** Read the shared cookie (browser only; null on the server or when unset). */\nexport function readNavDisplayCookie(): NavDisplayPreference | null {\n if (typeof document === 'undefined') return null\n try {\n const m = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)`),\n )\n const v = m ? decodeURIComponent(m[1]) : null\n return isNavDisplayPreference(v) ? v : null\n } catch {\n return null\n }\n}\n\n// Same host-aware scoping as the theme cookie: parent domain on\n// *.politogyvrm.com so every app subdomain reads it, host-only elsewhere\n// (localhost, *.pages.dev preview) because browsers silently drop a mismatched\n// Domain attribute. 1-year, SameSite=Lax, Secure on https.\nexport function writeNavDisplayCookie(pref: NavDisplayPreference): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return\n const host = window.location.hostname\n const domainAttr = /(^|\\.)politogyvrm\\.com$/i.test(host) ? '; Domain=.politogyvrm.com' : ''\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${NAV_DISPLAY_COOKIE}=${encodeURIComponent(\n pref,\n )}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`\n}\n\n/** Read the local store, falling back to the legacy host-only key. */\nexport function readNavDisplayLocal(): NavDisplayPreference | null {\n if (typeof localStorage === 'undefined') return null\n try {\n const current = localStorage.getItem(NAV_DISPLAY_STORAGE_KEY)\n if (isNavDisplayPreference(current)) return current\n const legacy = localStorage.getItem(LEGACY_NAV_DISPLAY_KEY)\n return isNavDisplayPreference(legacy) ? legacy : null\n } catch {\n return null\n }\n}\n\nexport function writeNavDisplayLocal(pref: NavDisplayPreference): void {\n if (typeof localStorage === 'undefined') return\n try {\n localStorage.setItem(NAV_DISPLAY_STORAGE_KEY, pref)\n } catch {\n /* storage unavailable */\n }\n}\n\n/** Boot precedence: cookie → localStorage (incl. legacy) → default. */\nexport function resolveNavDisplay(): NavDisplayPreference {\n return readNavDisplayCookie() ?? readNavDisplayLocal() ?? NAV_DISPLAY_DEFAULT\n}\n\n// Inline pre-paint script — optional, and the mirror of THEME_PREPAINT_SCRIPT.\n// Nav display has no paint-blocking visual (the frame is client-rendered), but\n// seeding localStorage from the cookie before hydration keeps the first render\n// on the synced value instead of the default. Self-contained and silent.\nexport const NAV_DISPLAY_PREPAINT_SCRIPT = `(function(){try{\nvar KEY=${JSON.stringify(NAV_DISPLAY_STORAGE_KEY)};\nvar VALID=[\"menu\",\"tabs\",\"both\"];\nfunction fromCookie(){try{var m=document.cookie.match(/(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}\nvar cookie=fromCookie();\nif(cookie&&VALID.indexOf(cookie)!==-1){var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}\nif(cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}}\n}catch(e){}})();`\n\n// ---------------------------------------------------------------------------\n// Rail expand preference — Left-Navigation §11.6: below `md` the rail\n// collapses to the 64px icon rail; \"the user can also collapse and expand it;\n// the choice is remembered per user\". Same cookie + localStorage layers as the\n// nav-display preference above (no server column yet), so the choice follows\n// the user across every app subdomain and survives reloads. Only an explicit\n// Expand / Collapse writes it; a route change that closes the overlay does not.\n// ---------------------------------------------------------------------------\n\nexport type RailPreference = 'expanded' | 'collapsed'\n\nexport const RAIL_STORAGE_KEY = 'politogy_rail'\nexport const RAIL_COOKIE = 'politogy_rail'\nexport const RAIL_DEFAULT: RailPreference = 'collapsed'\n\nexport function isRailPreference(v: unknown): v is RailPreference {\n return v === 'expanded' || v === 'collapsed'\n}\n\nexport function readRailPreference(): RailPreference {\n if (typeof document !== 'undefined') {\n try {\n const m = document.cookie.match(new RegExp(`(?:^|;\\\\s*)${RAIL_COOKIE}=([^;]+)`))\n const v = m ? decodeURIComponent(m[1]) : null\n if (isRailPreference(v)) return v\n } catch {\n /* ignore */\n }\n }\n if (typeof localStorage !== 'undefined') {\n try {\n const v = localStorage.getItem(RAIL_STORAGE_KEY)\n if (isRailPreference(v)) return v\n } catch {\n /* ignore */\n }\n }\n return RAIL_DEFAULT\n}\n\nexport function writeRailPreference(pref: RailPreference): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return\n const host = window.location.hostname\n const domainAttr = /(^|\\.)politogyvrm\\.com$/i.test(host) ? '; Domain=.politogyvrm.com' : ''\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n try {\n document.cookie = `${RAIL_COOKIE}=${pref}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`\n } catch {\n /* ignore */\n }\n try {\n localStorage.setItem(RAIL_STORAGE_KEY, pref)\n } catch {\n /* storage unavailable */\n }\n}\n"]}
|
|
@@ -14,5 +14,12 @@ declare function writeNavDisplayLocal(pref: NavDisplayPreference): void;
|
|
|
14
14
|
/** Boot precedence: cookie → localStorage (incl. legacy) → default. */
|
|
15
15
|
declare function resolveNavDisplay(): NavDisplayPreference;
|
|
16
16
|
declare const NAV_DISPLAY_PREPAINT_SCRIPT: string;
|
|
17
|
+
type RailPreference = 'expanded' | 'collapsed';
|
|
18
|
+
declare const RAIL_STORAGE_KEY = "politogy_rail";
|
|
19
|
+
declare const RAIL_COOKIE = "politogy_rail";
|
|
20
|
+
declare const RAIL_DEFAULT: RailPreference;
|
|
21
|
+
declare function isRailPreference(v: unknown): v is RailPreference;
|
|
22
|
+
declare function readRailPreference(): RailPreference;
|
|
23
|
+
declare function writeRailPreference(pref: RailPreference): void;
|
|
17
24
|
|
|
18
|
-
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, type NavDisplayPreference, isNavDisplayPreference, readNavDisplayCookie, readNavDisplayLocal, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal };
|
|
25
|
+
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, type NavDisplayPreference, RAIL_COOKIE, RAIL_DEFAULT, RAIL_STORAGE_KEY, type RailPreference, isNavDisplayPreference, isRailPreference, readNavDisplayCookie, readNavDisplayLocal, readRailPreference, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal, writeRailPreference };
|
package/dist/nav-preference.d.ts
CHANGED
|
@@ -14,5 +14,12 @@ declare function writeNavDisplayLocal(pref: NavDisplayPreference): void;
|
|
|
14
14
|
/** Boot precedence: cookie → localStorage (incl. legacy) → default. */
|
|
15
15
|
declare function resolveNavDisplay(): NavDisplayPreference;
|
|
16
16
|
declare const NAV_DISPLAY_PREPAINT_SCRIPT: string;
|
|
17
|
+
type RailPreference = 'expanded' | 'collapsed';
|
|
18
|
+
declare const RAIL_STORAGE_KEY = "politogy_rail";
|
|
19
|
+
declare const RAIL_COOKIE = "politogy_rail";
|
|
20
|
+
declare const RAIL_DEFAULT: RailPreference;
|
|
21
|
+
declare function isRailPreference(v: unknown): v is RailPreference;
|
|
22
|
+
declare function readRailPreference(): RailPreference;
|
|
23
|
+
declare function writeRailPreference(pref: RailPreference): void;
|
|
17
24
|
|
|
18
|
-
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, type NavDisplayPreference, isNavDisplayPreference, readNavDisplayCookie, readNavDisplayLocal, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal };
|
|
25
|
+
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, type NavDisplayPreference, RAIL_COOKIE, RAIL_DEFAULT, RAIL_STORAGE_KEY, type RailPreference, isNavDisplayPreference, isRailPreference, readNavDisplayCookie, readNavDisplayLocal, readRailPreference, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal, writeRailPreference };
|
package/dist/nav-preference.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, isNavDisplayPreference, readNavDisplayCookie, readNavDisplayLocal, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal } from './chunk-
|
|
1
|
+
export { LEGACY_NAV_DISPLAY_KEY, NAV_DISPLAY_COOKIE, NAV_DISPLAY_DEFAULT, NAV_DISPLAY_PREPAINT_SCRIPT, NAV_DISPLAY_STORAGE_KEY, RAIL_COOKIE, RAIL_DEFAULT, RAIL_STORAGE_KEY, isNavDisplayPreference, isRailPreference, readNavDisplayCookie, readNavDisplayLocal, readRailPreference, resolveNavDisplay, writeNavDisplayCookie, writeNavDisplayLocal, writeRailPreference } from './chunk-7YVJ7HQG.js';
|
|
2
2
|
//# sourceMappingURL=nav-preference.js.map
|
|
3
3
|
//# sourceMappingURL=nav-preference.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@the-portland-company/shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.0",
|
|
4
4
|
"description": "Shared chrome (header, sidebar, footer, theme, auth) for politogy apps. Drop into any Vite SPA to inherit the politogy look and signed-in user.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/nav-preference.ts"],"names":[],"mappings":";AAwBO,IAAM,uBAAA,GAA0B;AAChC,IAAM,kBAAA,GAAqB;AAG3B,IAAM,sBAAA,GAAyB;AAE/B,IAAM,mBAAA,GAA4C;AAEzD,IAAM,KAAA,GAAyC,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM,CAAA;AAE/D,SAAS,uBAAuB,CAAA,EAAuC;AAC5E,EAAA,OAAO,OAAO,CAAA,KAAM,QAAA,IAAa,KAAA,CAA4B,SAAS,CAAC,CAAA;AACzE;AAGO,SAAS,oBAAA,GAAoD;AAClE,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,SAAS,MAAA,CAAO,KAAA;AAAA,MACxB,IAAI,MAAA,CAAO,CAAA,WAAA,EAAc,kBAAkB,CAAA,QAAA,CAAU;AAAA,KACvD;AACA,IAAA,MAAM,IAAI,CAAA,GAAI,kBAAA,CAAmB,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA;AACzC,IAAA,OAAO,sBAAA,CAAuB,CAAC,CAAA,GAAI,CAAA,GAAI,IAAA;AAAA,EACzC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMO,SAAS,sBAAsB,IAAA,EAAkC;AACtE,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,IAAe,OAAO,WAAW,WAAA,EAAa;AACtE,EAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,QAAA;AAC7B,EAAA,MAAM,UAAA,GAAa,0BAAA,CAA2B,IAAA,CAAK,IAAI,IAAI,2BAAA,GAA8B,EAAA;AACzF,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,QAAA,CAAS,QAAA,KAAa,WAAW,UAAA,GAAa,EAAA;AACpE,EAAA,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,kBAAkB,CAAA,CAAA,EAAI,kBAAA;AAAA,IACzC;AAAA,GACD,CAAA,wCAAA,EAA2C,UAAU,CAAA,EAAG,MAAM,CAAA,CAAA;AACjE;AAGO,SAAS,mBAAA,GAAmD;AACjE,EAAA,IAAI,OAAO,YAAA,KAAiB,WAAA,EAAa,OAAO,IAAA;AAChD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,YAAA,CAAa,OAAA,CAAQ,uBAAuB,CAAA;AAC5D,IAAA,IAAI,sBAAA,CAAuB,OAAO,CAAA,EAAG,OAAO,OAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,sBAAsB,CAAA;AAC1D,IAAA,OAAO,sBAAA,CAAuB,MAAM,CAAA,GAAI,MAAA,GAAS,IAAA;AAAA,EACnD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB,IAAA,EAAkC;AACrE,EAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACzC,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,OAAA,CAAQ,yBAAyB,IAAI,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGO,SAAS,iBAAA,GAA0C;AACxD,EAAA,OAAO,oBAAA,EAAqB,IAAK,mBAAA,EAAoB,IAAK,mBAAA;AAC5D;AAMO,IAAM,2BAAA,GAA8B,CAAA;AAAA,QAAA,EACjC,IAAA,CAAK,SAAA,CAAU,uBAAuB,CAAC,CAAA;AAAA;AAAA,kEAAA,EAEmB,kBAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,gBAAA","file":"chunk-6UHJV2FH.js","sourcesContent":["// Universal navigation-display preference — the same cross-app contract as the\n// theme (see ./theme-preference, which this deliberately mirrors).\n//\n// The user's choice of how navigation renders (Menu / Tabs / Both) follows the\n// authenticated user across every Politogy app + subdomain. Three layers:\n// 1. VRM Core `profiles.nav_display_preference` — source of truth, persisted\n// via the chrome API (`PATCH me/preferences { navDisplay }`) and read back\n// from `GET me` (`navDisplay`).\n// 2. `.politogyvrm.com` cookie `politogy_nav_display` — the cross-subdomain\n// vehicle (app session cookies are host-only, and so is localStorage).\n// 3. localStorage — same-app fast reads and cross-tab `storage` events.\n//\n// Before this existed the preference lived ONLY in localStorage under\n// `vrm.navDisplay`, which is per-ORIGIN: every app subdomain kept its own copy\n// and a freshly opened app booted the default, so the setting appeared not to\n// hold when moving between apps. The legacy key is still read as a fallback so\n// an existing local choice survives the upgrade.\n//\n// Server-safe (no 'use client'): layouts may import NAV_DISPLAY_PREPAINT_SCRIPT.\n\nexport type NavDisplayPreference = 'menu' | 'tabs' | 'both'\n\n// One key for BOTH the localStorage store and the cross-subdomain cookie, so a\n// choice in one app is the same key in the next.\nexport const NAV_DISPLAY_STORAGE_KEY = 'politogy_nav_display'\nexport const NAV_DISPLAY_COOKIE = 'politogy_nav_display'\n\n/** Pre-0.37 host-only key. Read for migration; never written. */\nexport const LEGACY_NAV_DISPLAY_KEY = 'vrm.navDisplay'\n\nexport const NAV_DISPLAY_DEFAULT: NavDisplayPreference = 'both'\n\nconst VALID: readonly NavDisplayPreference[] = ['menu', 'tabs', 'both']\n\nexport function isNavDisplayPreference(v: unknown): v is NavDisplayPreference {\n return typeof v === 'string' && (VALID as readonly string[]).includes(v)\n}\n\n/** Read the shared cookie (browser only; null on the server or when unset). */\nexport function readNavDisplayCookie(): NavDisplayPreference | null {\n if (typeof document === 'undefined') return null\n try {\n const m = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)`),\n )\n const v = m ? decodeURIComponent(m[1]) : null\n return isNavDisplayPreference(v) ? v : null\n } catch {\n return null\n }\n}\n\n// Same host-aware scoping as the theme cookie: parent domain on\n// *.politogyvrm.com so every app subdomain reads it, host-only elsewhere\n// (localhost, *.pages.dev preview) because browsers silently drop a mismatched\n// Domain attribute. 1-year, SameSite=Lax, Secure on https.\nexport function writeNavDisplayCookie(pref: NavDisplayPreference): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return\n const host = window.location.hostname\n const domainAttr = /(^|\\.)politogyvrm\\.com$/i.test(host) ? '; Domain=.politogyvrm.com' : ''\n const secure = window.location.protocol === 'https:' ? '; Secure' : ''\n document.cookie = `${NAV_DISPLAY_COOKIE}=${encodeURIComponent(\n pref,\n )}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`\n}\n\n/** Read the local store, falling back to the legacy host-only key. */\nexport function readNavDisplayLocal(): NavDisplayPreference | null {\n if (typeof localStorage === 'undefined') return null\n try {\n const current = localStorage.getItem(NAV_DISPLAY_STORAGE_KEY)\n if (isNavDisplayPreference(current)) return current\n const legacy = localStorage.getItem(LEGACY_NAV_DISPLAY_KEY)\n return isNavDisplayPreference(legacy) ? legacy : null\n } catch {\n return null\n }\n}\n\nexport function writeNavDisplayLocal(pref: NavDisplayPreference): void {\n if (typeof localStorage === 'undefined') return\n try {\n localStorage.setItem(NAV_DISPLAY_STORAGE_KEY, pref)\n } catch {\n /* storage unavailable */\n }\n}\n\n/** Boot precedence: cookie → localStorage (incl. legacy) → default. */\nexport function resolveNavDisplay(): NavDisplayPreference {\n return readNavDisplayCookie() ?? readNavDisplayLocal() ?? NAV_DISPLAY_DEFAULT\n}\n\n// Inline pre-paint script — optional, and the mirror of THEME_PREPAINT_SCRIPT.\n// Nav display has no paint-blocking visual (the frame is client-rendered), but\n// seeding localStorage from the cookie before hydration keeps the first render\n// on the synced value instead of the default. Self-contained and silent.\nexport const NAV_DISPLAY_PREPAINT_SCRIPT = `(function(){try{\nvar KEY=${JSON.stringify(NAV_DISPLAY_STORAGE_KEY)};\nvar VALID=[\"menu\",\"tabs\",\"both\"];\nfunction fromCookie(){try{var m=document.cookie.match(/(?:^|;\\\\s*)${NAV_DISPLAY_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}\nvar cookie=fromCookie();\nif(cookie&&VALID.indexOf(cookie)!==-1){var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}\nif(cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}}\n}catch(e){}})();`\n"]}
|