@the-portland-company/shell 0.55.0 → 0.56.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 +22 -0
- package/dist/app-chrome.cjs +90 -17
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +13 -0
- package/dist/app-chrome.d.ts +13 -0
- package/dist/app-chrome.js +75 -3
- package/dist/app-chrome.js.map +1 -1
- package/dist/{chunk-K5GWJSHE.js → chunk-MR6TLHEE.js} +18 -17
- package/dist/chunk-MR6TLHEE.js.map +1 -0
- package/dist/native.cjs +16 -15
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-K5GWJSHE.js.map +0 -1
package/dist/app-chrome.d.cts
CHANGED
|
@@ -119,6 +119,19 @@ declare const POLITOGY_APPS: Record<PolitogyAppKey, {
|
|
|
119
119
|
origin: string;
|
|
120
120
|
storagePrefix: string;
|
|
121
121
|
mode?: PolitogyAppMode;
|
|
122
|
+
/**
|
|
123
|
+
* DUAL-MODE apps (today: a2p — Specs/A2P: "the SMS/MMS delivery engine
|
|
124
|
+
* for Relationship Mode and Campaign Mode") have no single fixed mode.
|
|
125
|
+
* `mode` above stays the fallback/default identity for any code that
|
|
126
|
+
* still reads `meta.mode` directly; FrameBody instead resolves the
|
|
127
|
+
* EFFECTIVE mode via `resolveActiveMode` (?mode= query → the
|
|
128
|
+
* `politogy_active_mode` cookie → `defaultMode`) and uses that for the
|
|
129
|
+
* nav tree, the Mode pill, and the brand lockup.
|
|
130
|
+
*/
|
|
131
|
+
dual?: {
|
|
132
|
+
modes: readonly StandardNavMode[];
|
|
133
|
+
defaultMode: StandardNavMode;
|
|
134
|
+
};
|
|
122
135
|
/** See PolitogyFrameGrant. Omitted => the app may pass no frame input. */
|
|
123
136
|
grants?: readonly PolitogyFrameGrant[];
|
|
124
137
|
/**
|
package/dist/app-chrome.d.ts
CHANGED
|
@@ -119,6 +119,19 @@ declare const POLITOGY_APPS: Record<PolitogyAppKey, {
|
|
|
119
119
|
origin: string;
|
|
120
120
|
storagePrefix: string;
|
|
121
121
|
mode?: PolitogyAppMode;
|
|
122
|
+
/**
|
|
123
|
+
* DUAL-MODE apps (today: a2p — Specs/A2P: "the SMS/MMS delivery engine
|
|
124
|
+
* for Relationship Mode and Campaign Mode") have no single fixed mode.
|
|
125
|
+
* `mode` above stays the fallback/default identity for any code that
|
|
126
|
+
* still reads `meta.mode` directly; FrameBody instead resolves the
|
|
127
|
+
* EFFECTIVE mode via `resolveActiveMode` (?mode= query → the
|
|
128
|
+
* `politogy_active_mode` cookie → `defaultMode`) and uses that for the
|
|
129
|
+
* nav tree, the Mode pill, and the brand lockup.
|
|
130
|
+
*/
|
|
131
|
+
dual?: {
|
|
132
|
+
modes: readonly StandardNavMode[];
|
|
133
|
+
defaultMode: StandardNavMode;
|
|
134
|
+
};
|
|
122
135
|
/** See PolitogyFrameGrant. Omitted => the app may pass no frame input. */
|
|
123
136
|
grants?: readonly PolitogyFrameGrant[];
|
|
124
137
|
/**
|
package/dist/app-chrome.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { broadcastLogout, watchLogout } from './chunk-LL6LSJAH.js';
|
|
3
|
-
import { clearBetaBannerDismissal, standardPolitogyNav, NavAppShell, NavChromeProvider, FuelAction, NavDisplayAction, TopBarWidgetSlot, SupportAction, NotificationsAction, useChromeMe, useThemePreference, useNavChromeFetcher, useChromeOrgs } from './chunk-
|
|
3
|
+
import { clearBetaBannerDismissal, standardPolitogyNav, NavAppShell, NavChromeProvider, FuelAction, NavDisplayAction, TopBarWidgetSlot, SupportAction, NotificationsAction, useChromeMe, useThemePreference, useNavChromeFetcher, useChromeOrgs } from './chunk-MR6TLHEE.js';
|
|
4
4
|
import './chunk-U4RZPZET.js';
|
|
5
5
|
import { NAV_DISPLAY_DEFAULT, resolveNavDisplay, isNavDisplayPreference, writeNavDisplayCookie, writeNavDisplayLocal, NAV_DISPLAY_STORAGE_KEY, readNavDisplayCookie } from './chunk-6UHJV2FH.js';
|
|
6
6
|
import { resolveActiveOrg, isOrgId, writeActiveOrgCookie, ACTIVE_ORG_QUERY_PARAM, readActiveOrgCookie } from './chunk-W2HITMV5.js';
|
|
@@ -78,6 +78,58 @@ function resolveIdentity(input) {
|
|
|
78
78
|
loaded: input.loaded ?? false
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
|
+
|
|
82
|
+
// src/mode-preference.ts
|
|
83
|
+
var ACTIVE_MODE_COOKIE = "politogy_active_mode";
|
|
84
|
+
var VALID_MODES = ["relationship", "campaign", "petition"];
|
|
85
|
+
function isStandardNavMode(v) {
|
|
86
|
+
return typeof v === "string" && VALID_MODES.includes(v);
|
|
87
|
+
}
|
|
88
|
+
function readActiveModeCookie() {
|
|
89
|
+
if (typeof document === "undefined") return null;
|
|
90
|
+
try {
|
|
91
|
+
const m = document.cookie.match(
|
|
92
|
+
new RegExp(`(?:^|;\\s*)${ACTIVE_MODE_COOKIE}=([^;]+)`)
|
|
93
|
+
);
|
|
94
|
+
const v = m ? decodeURIComponent(m[1]) : null;
|
|
95
|
+
return isStandardNavMode(v) ? v : null;
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function writeActiveModeCookie(mode) {
|
|
101
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
102
|
+
const host = window.location.hostname;
|
|
103
|
+
const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
|
|
104
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
105
|
+
document.cookie = `${ACTIVE_MODE_COOKIE}=${encodeURIComponent(
|
|
106
|
+
mode
|
|
107
|
+
)}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
108
|
+
}
|
|
109
|
+
function modeFromSearch(search) {
|
|
110
|
+
if (!search) return null;
|
|
111
|
+
try {
|
|
112
|
+
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
113
|
+
return params.get("mode");
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function resolveActiveMode({
|
|
119
|
+
search,
|
|
120
|
+
modes,
|
|
121
|
+
defaultMode
|
|
122
|
+
}) {
|
|
123
|
+
const fromQuery = modeFromSearch(search);
|
|
124
|
+
if (fromQuery && isStandardNavMode(fromQuery) && modes.includes(fromQuery)) {
|
|
125
|
+
return fromQuery;
|
|
126
|
+
}
|
|
127
|
+
const fromCookie = readActiveModeCookie();
|
|
128
|
+
if (fromCookie && modes.includes(fromCookie)) {
|
|
129
|
+
return fromCookie;
|
|
130
|
+
}
|
|
131
|
+
return defaultMode;
|
|
132
|
+
}
|
|
81
133
|
var BOOT_STAGE_TABLE = [
|
|
82
134
|
{ id: "s0_session", weight: 5, critical: true, waitsOn: "Politogy ID session resolution" },
|
|
83
135
|
{ id: "s1_org", weight: 10, critical: true, waitsOn: "Chrome API /api/chrome/me + orgs" },
|
|
@@ -447,7 +499,17 @@ var POLITOGY_APPS = {
|
|
|
447
499
|
// Campaign Mode apps — each scoped to Campaign, so they render the Campaign
|
|
448
500
|
// tree and a static Campaign pill. Not yet deployed; hidden from the Campaign
|
|
449
501
|
// nav by CAMPAIGN_FEATURE_AVAILABILITY until their launch flips the flag.
|
|
450
|
-
|
|
502
|
+
// Dual-mode: a2p is the SMS/MMS delivery engine for BOTH Relationship Mode
|
|
503
|
+
// and Campaign Mode (Specs/A2P). `mode: 'campaign'` stays the fallback for
|
|
504
|
+
// anything reading `meta.mode` directly; the effective mode a user sees is
|
|
505
|
+
// resolved per-visit (see `dual`, resolveActiveMode).
|
|
506
|
+
a2p: {
|
|
507
|
+
title: "A2P Messaging",
|
|
508
|
+
origin: "https://a2p.politogyvrm.com",
|
|
509
|
+
storagePrefix: "a2p",
|
|
510
|
+
mode: "campaign",
|
|
511
|
+
dual: { modes: ["relationship", "campaign"], defaultMode: "campaign" }
|
|
512
|
+
},
|
|
451
513
|
phonebank: { title: "Phone Banking", origin: "https://phonebank.politogyvrm.com", storagePrefix: "phonebank", mode: "campaign" },
|
|
452
514
|
canvass: { title: "Field Canvassing", origin: "https://canvass.politogyvrm.com", storagePrefix: "canvass", mode: "campaign" },
|
|
453
515
|
signs: { title: "Sign Mapping", origin: "https://signs.politogyvrm.com", storagePrefix: "signs", mode: "campaign" }
|
|
@@ -584,9 +646,19 @@ function FrameBody({
|
|
|
584
646
|
});
|
|
585
647
|
const userMenu = core?.userMenu ?? derivedUserMenu;
|
|
586
648
|
const footer = useChromeFooter(buildMeta ?? {});
|
|
587
|
-
const
|
|
649
|
+
const resolvedDualMode = meta.dual ? resolveActiveMode({
|
|
650
|
+
search: search ?? (typeof window !== "undefined" ? window.location.search : void 0),
|
|
651
|
+
modes: meta.dual.modes,
|
|
652
|
+
defaultMode: meta.dual.defaultMode
|
|
653
|
+
}) : void 0;
|
|
654
|
+
const appMode = resolvedDualMode ?? meta.mode;
|
|
588
655
|
const derivedMode = useChromeMode(appMode ? { pinnedModeId: appMode } : void 0);
|
|
589
656
|
const mode = core?.mode ?? derivedMode;
|
|
657
|
+
const coreLiveMode = app === CORE_APP ? pathname.startsWith("/campaign") ? "campaign" : pathname.startsWith("/relationship") ? "relationship" : void 0 : void 0;
|
|
658
|
+
const cookieMode = coreLiveMode ?? (meta.dual ? void 0 : meta.mode);
|
|
659
|
+
useEffect(() => {
|
|
660
|
+
if (cookieMode) writeActiveModeCookie(cookieMode);
|
|
661
|
+
}, [cookieMode]);
|
|
590
662
|
const coreOrgs = chrome?.orgs ?? [];
|
|
591
663
|
const activeCoreOrg = coreOrgs.find((o) => o.id === chrome?.orgId) ?? null;
|
|
592
664
|
const navDisplay = chrome?.navDisplay ?? "both";
|