@the-portland-company/shell 0.76.18 → 0.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/app-chrome.cjs +3 -184
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +2 -2
- package/dist/app-chrome.d.ts +2 -2
- package/dist/app-chrome.js +4 -3
- package/dist/app-chrome.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.77.0
|
|
2
|
+
|
|
3
|
+
No theme control in the account menu. Specs cited: Reference/UI-Platform "Theme — light only (Dark Mode retired)" and "There is no theme control … Apps must not render any theme control"; Reference/Global-Rules "Theming — Light Only".
|
|
4
|
+
|
|
5
|
+
- **Breaking for the eye only.** `PolitogyAppFrame` no longer passes `theme` to the account menu, so the "Appearance" radio group (one option, "Light", since 0.73.0 made the theme light only) is gone from every app. `NavUserMenu.theme` stays optional for a caller that still passes it; nothing in the shell does.
|
|
6
|
+
- `./theme-preference` and `useThemePreference` are unchanged: they still resolve every stored preference to light and keep the cross-app cookie contract for the apps that import them.
|
|
7
|
+
- **Audit note (closeout 2026-10-12, item 1).** The "Known shell defect — dark theme restored in 0.68.0" paragraph in Reference/UI-Platform is stale: 0.73.0 (#116, 2026-10-06) removed dark rendering, `chrome.css` ships no `.dark` block (the remaining mentions are comments), and the pre-paint script hardcodes light. The runtime Brand token sheet (specs app, `lib/brand-authoring.ts`) still emits `.dark {}` blocks that nothing applies.
|
|
8
|
+
|
|
1
9
|
## 0.76.18
|
|
2
10
|
|
|
3
11
|
Consolidates 0.76.16 and 0.76.17, neither of which reached npm (their publish gates failed). Specs cited: Global-Rules v38, UI-Platform v46, Specs/Left-Navigation (no Tribes row, §9.1), Specs/System-Communications §6.3 and §12.2 (Binding, 2026-10-03).
|
package/dist/app-chrome.cjs
CHANGED
|
@@ -487,92 +487,6 @@ function notificationsFeedToPayload(feed, orgId) {
|
|
|
487
487
|
badge: feed.badge
|
|
488
488
|
};
|
|
489
489
|
}
|
|
490
|
-
|
|
491
|
-
// src/theme-preference.ts
|
|
492
|
-
var THEME_STORAGE_KEY = "politogy_theme";
|
|
493
|
-
var THEME_COOKIE = "politogy_theme";
|
|
494
|
-
var THEME_PENDING_COOKIE = "politogy_theme_pending";
|
|
495
|
-
var VALID2 = ["light", "dark", "system"];
|
|
496
|
-
function isThemePreference(v) {
|
|
497
|
-
return typeof v === "string" && VALID2.includes(v);
|
|
498
|
-
}
|
|
499
|
-
function readThemeCookie() {
|
|
500
|
-
if (typeof document === "undefined") return null;
|
|
501
|
-
try {
|
|
502
|
-
const m = document.cookie.match(
|
|
503
|
-
new RegExp(`(?:^|;\\s*)${THEME_COOKIE}=([^;]+)`)
|
|
504
|
-
);
|
|
505
|
-
const v = m ? decodeURIComponent(m[1]) : null;
|
|
506
|
-
return isThemePreference(v) ? v : null;
|
|
507
|
-
} catch {
|
|
508
|
-
return null;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
function writeThemeCookie(pref) {
|
|
512
|
-
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
513
|
-
const host = window.location.hostname;
|
|
514
|
-
const onParentDomain = /(^|\.)politogyvrm\.com$/i.test(host);
|
|
515
|
-
const domainAttr = onParentDomain ? "; Domain=.politogyvrm.com" : "";
|
|
516
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
517
|
-
document.cookie = `${THEME_COOKIE}=${encodeURIComponent(
|
|
518
|
-
pref
|
|
519
|
-
)}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
520
|
-
}
|
|
521
|
-
function writeSharedCookie(name, value, maxAgeSeconds) {
|
|
522
|
-
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
523
|
-
const host = window.location.hostname;
|
|
524
|
-
const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
|
|
525
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
526
|
-
document.cookie = `${name}=${encodeURIComponent(
|
|
527
|
-
value
|
|
528
|
-
)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax${domainAttr}${secure}`;
|
|
529
|
-
}
|
|
530
|
-
function markThemeChoicePending(pref) {
|
|
531
|
-
writeSharedCookie(THEME_PENDING_COOKIE, pref, 31536e3);
|
|
532
|
-
}
|
|
533
|
-
function readPendingThemeChoice() {
|
|
534
|
-
if (typeof document === "undefined") return null;
|
|
535
|
-
try {
|
|
536
|
-
const m = document.cookie.match(
|
|
537
|
-
new RegExp(`(?:^|;\\s*)${THEME_PENDING_COOKIE}=([^;]+)`)
|
|
538
|
-
);
|
|
539
|
-
const v = m ? decodeURIComponent(m[1]) : null;
|
|
540
|
-
return isThemePreference(v) ? v : null;
|
|
541
|
-
} catch {
|
|
542
|
-
return null;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
function clearPendingThemeChoice() {
|
|
546
|
-
writeSharedCookie(THEME_PENDING_COOKIE, "", 0);
|
|
547
|
-
}
|
|
548
|
-
function resolveTheme(_pref) {
|
|
549
|
-
return "light";
|
|
550
|
-
}
|
|
551
|
-
function applyThemePreference(pref) {
|
|
552
|
-
if (typeof document === "undefined") return;
|
|
553
|
-
const resolved = resolveTheme();
|
|
554
|
-
const d = document.documentElement;
|
|
555
|
-
d.classList.toggle("dark", resolved === "dark");
|
|
556
|
-
try {
|
|
557
|
-
d.setAttribute("data-theme", resolved);
|
|
558
|
-
d.style.colorScheme = resolved;
|
|
559
|
-
} catch {
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
`(function(){try{
|
|
563
|
-
var KEY=${JSON.stringify(THEME_STORAGE_KEY)};
|
|
564
|
-
var VALID=["light","dark","system"];
|
|
565
|
-
function fromCookie(){try{var m=document.cookie.match(/(?:^|;\\s*)${THEME_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}
|
|
566
|
-
var cookie=fromCookie();
|
|
567
|
-
var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}
|
|
568
|
-
var pref=cookie||ls||"system";
|
|
569
|
-
if(VALID.indexOf(pref)===-1)pref="system";
|
|
570
|
-
if(cookie&&cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}
|
|
571
|
-
var dark=false;
|
|
572
|
-
var d=document.documentElement;
|
|
573
|
-
if(dark)d.classList.add("dark");else d.classList.remove("dark");
|
|
574
|
-
try{d.setAttribute("data-theme",dark?"dark":"light");d.style.colorScheme=dark?"dark":"light";}catch(e){}
|
|
575
|
-
}catch(e){}})();`;
|
|
576
490
|
var CORE_APP_ORIGIN = "https://app.politogyvrm.com";
|
|
577
491
|
var CORE_BILLING_PATH = "/organization-settings/subscription-billing/text-email";
|
|
578
492
|
var CORE_BILLING_URL = `${CORE_APP_ORIGIN}${CORE_BILLING_PATH}`;
|
|
@@ -2201,102 +2115,6 @@ var NAV_DISPLAY_OPTIONS = [
|
|
|
2201
2115
|
{ value: "tabs", label: "Tabs Only" },
|
|
2202
2116
|
{ value: "both", label: "Both" }
|
|
2203
2117
|
];
|
|
2204
|
-
function useThemePreference() {
|
|
2205
|
-
const ctx = react.useContext(NavChromeContext);
|
|
2206
|
-
const fetchJson = ctx?.fetchJson ?? null;
|
|
2207
|
-
const [value, setValueState] = react.useState("system");
|
|
2208
|
-
const reconciled = react.useRef(false);
|
|
2209
|
-
react.useEffect(() => {
|
|
2210
|
-
const cookie = readThemeCookie();
|
|
2211
|
-
let ls = null;
|
|
2212
|
-
try {
|
|
2213
|
-
ls = localStorage.getItem(THEME_STORAGE_KEY);
|
|
2214
|
-
} catch {
|
|
2215
|
-
}
|
|
2216
|
-
const pref = cookie ?? (isThemePreference(ls) ? ls : null) ?? "system";
|
|
2217
|
-
setValueState(pref);
|
|
2218
|
-
applyThemePreference();
|
|
2219
|
-
}, []);
|
|
2220
|
-
const meCtx = react.useContext(NavChromeContext);
|
|
2221
|
-
react.useEffect(() => {
|
|
2222
|
-
if (reconciled.current) return;
|
|
2223
|
-
const pending = readPendingThemeChoice();
|
|
2224
|
-
if (pending) {
|
|
2225
|
-
if (meCtx?.me) reconciled.current = true;
|
|
2226
|
-
setValueState(pending);
|
|
2227
|
-
applyThemePreference();
|
|
2228
|
-
writeThemeCookie(pending);
|
|
2229
|
-
try {
|
|
2230
|
-
localStorage.setItem(THEME_STORAGE_KEY, pending);
|
|
2231
|
-
} catch {
|
|
2232
|
-
}
|
|
2233
|
-
if (!meCtx?.me) return;
|
|
2234
|
-
fetchJson?.("me/preferences", {
|
|
2235
|
-
method: "PATCH",
|
|
2236
|
-
headers: { "Content-Type": "application/json" },
|
|
2237
|
-
body: JSON.stringify({ themePreference: pending })
|
|
2238
|
-
}).then(() => clearPendingThemeChoice()).catch(() => {
|
|
2239
|
-
});
|
|
2240
|
-
return;
|
|
2241
|
-
}
|
|
2242
|
-
const pref = meCtx?.me?.themePreference;
|
|
2243
|
-
if (isThemePreference(pref)) {
|
|
2244
|
-
reconciled.current = true;
|
|
2245
|
-
setValueState(pref);
|
|
2246
|
-
applyThemePreference();
|
|
2247
|
-
writeThemeCookie(pref);
|
|
2248
|
-
try {
|
|
2249
|
-
localStorage.setItem(THEME_STORAGE_KEY, pref);
|
|
2250
|
-
} catch {
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
}, [meCtx?.me]);
|
|
2254
|
-
react.useEffect(() => {
|
|
2255
|
-
const onStorage = (e) => {
|
|
2256
|
-
if (e.key === THEME_STORAGE_KEY && isThemePreference(e.newValue)) {
|
|
2257
|
-
setValueState(e.newValue);
|
|
2258
|
-
applyThemePreference(e.newValue);
|
|
2259
|
-
}
|
|
2260
|
-
};
|
|
2261
|
-
const onWake = () => {
|
|
2262
|
-
const cookie = readThemeCookie();
|
|
2263
|
-
if (cookie) {
|
|
2264
|
-
setValueState((prev) => {
|
|
2265
|
-
if (cookie !== prev) applyThemePreference();
|
|
2266
|
-
return cookie;
|
|
2267
|
-
});
|
|
2268
|
-
}
|
|
2269
|
-
};
|
|
2270
|
-
window.addEventListener("storage", onStorage);
|
|
2271
|
-
window.addEventListener("focus", onWake);
|
|
2272
|
-
document.addEventListener("visibilitychange", onWake);
|
|
2273
|
-
return () => {
|
|
2274
|
-
window.removeEventListener("storage", onStorage);
|
|
2275
|
-
window.removeEventListener("focus", onWake);
|
|
2276
|
-
document.removeEventListener("visibilitychange", onWake);
|
|
2277
|
-
};
|
|
2278
|
-
}, []);
|
|
2279
|
-
const setValue = react.useCallback(
|
|
2280
|
-
(next) => {
|
|
2281
|
-
setValueState(next);
|
|
2282
|
-
applyThemePreference();
|
|
2283
|
-
writeThemeCookie(next);
|
|
2284
|
-
try {
|
|
2285
|
-
localStorage.setItem(THEME_STORAGE_KEY, next);
|
|
2286
|
-
} catch {
|
|
2287
|
-
}
|
|
2288
|
-
markThemeChoicePending(next);
|
|
2289
|
-
fetchJson?.("me/preferences", {
|
|
2290
|
-
method: "PATCH",
|
|
2291
|
-
headers: { "Content-Type": "application/json" },
|
|
2292
|
-
body: JSON.stringify({ themePreference: next })
|
|
2293
|
-
}).then(() => clearPendingThemeChoice()).catch(() => {
|
|
2294
|
-
});
|
|
2295
|
-
},
|
|
2296
|
-
[fetchJson]
|
|
2297
|
-
);
|
|
2298
|
-
return { value, setValue };
|
|
2299
|
-
}
|
|
2300
2118
|
var standardNavIcons = {
|
|
2301
2119
|
home: lu.LuHouse,
|
|
2302
2120
|
users: lu.LuUsers,
|
|
@@ -5597,7 +5415,6 @@ function useChromeUserMenu({
|
|
|
5597
5415
|
email
|
|
5598
5416
|
}) {
|
|
5599
5417
|
const state = useChromeState();
|
|
5600
|
-
const theme = useThemePreference();
|
|
5601
5418
|
const activeOrg = state?.orgs.find((o) => o.id === state.orgId) ?? null;
|
|
5602
5419
|
const orgSuffix = activeOrg ? `?org=${activeOrg.id}` : "";
|
|
5603
5420
|
const coreBase = getCoreBaseUrl();
|
|
@@ -5608,7 +5425,9 @@ function useChromeUserMenu({
|
|
|
5608
5425
|
roles: (state?.orgs ?? []).filter((o) => o.rawRole || o.role).map((o) => ({ role: o.rawRole ?? o.role, orgName: o.name })),
|
|
5609
5426
|
accounts: [{ id: userId, name: userName, email, avatarUrl: null, active: true }],
|
|
5610
5427
|
addAccountHref: `${coreBase}/my-profile#accounts`,
|
|
5611
|
-
theme:
|
|
5428
|
+
// No theme control: the product is light only (Reference/UI-Platform
|
|
5429
|
+
// "Theme — light only"; shell 0.73.0 stopped applying dark). The account
|
|
5430
|
+
// menu rendered an "Appearance" radio with one option until 0.77.0.
|
|
5612
5431
|
navDisplay: state ? { value: state.navDisplay, onChange: state.setNavDisplay } : void 0
|
|
5613
5432
|
};
|
|
5614
5433
|
}
|