@the-portland-company/shell 0.16.7 → 0.17.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/index.cjs +142 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +78 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1284,6 +1284,142 @@ function resolveModeConfig(mode) {
|
|
|
1284
1284
|
}
|
|
1285
1285
|
return modes.find((m) => m.id === mode.currentMode) ?? modes[0] ?? null;
|
|
1286
1286
|
}
|
|
1287
|
+
|
|
1288
|
+
// src/theme-preference.ts
|
|
1289
|
+
var THEME_STORAGE_KEY = "politogy_theme";
|
|
1290
|
+
var THEME_COOKIE = "politogy_theme";
|
|
1291
|
+
var VALID = ["light", "dark", "system"];
|
|
1292
|
+
function isThemePreference(v) {
|
|
1293
|
+
return typeof v === "string" && VALID.includes(v);
|
|
1294
|
+
}
|
|
1295
|
+
function readThemeCookie() {
|
|
1296
|
+
if (typeof document === "undefined") return null;
|
|
1297
|
+
try {
|
|
1298
|
+
const m = document.cookie.match(
|
|
1299
|
+
new RegExp(`(?:^|;\\s*)${THEME_COOKIE}=([^;]+)`)
|
|
1300
|
+
);
|
|
1301
|
+
const v = m ? decodeURIComponent(m[1]) : null;
|
|
1302
|
+
return isThemePreference(v) ? v : null;
|
|
1303
|
+
} catch {
|
|
1304
|
+
return null;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
function writeThemeCookie(pref) {
|
|
1308
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1309
|
+
const host = window.location.hostname;
|
|
1310
|
+
const onParentDomain = /(^|\.)politogyvrm\.com$/i.test(host);
|
|
1311
|
+
const domainAttr = onParentDomain ? "; Domain=.politogyvrm.com" : "";
|
|
1312
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
1313
|
+
document.cookie = `${THEME_COOKIE}=${encodeURIComponent(
|
|
1314
|
+
pref
|
|
1315
|
+
)}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
1316
|
+
}
|
|
1317
|
+
function resolveTheme(pref) {
|
|
1318
|
+
if (pref === "system") {
|
|
1319
|
+
try {
|
|
1320
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
1321
|
+
} catch {
|
|
1322
|
+
return "light";
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return pref;
|
|
1326
|
+
}
|
|
1327
|
+
function applyThemePreference(pref) {
|
|
1328
|
+
if (typeof document === "undefined") return;
|
|
1329
|
+
const resolved = resolveTheme(pref);
|
|
1330
|
+
const d = document.documentElement;
|
|
1331
|
+
d.classList.toggle("dark", resolved === "dark");
|
|
1332
|
+
try {
|
|
1333
|
+
d.style.colorScheme = resolved;
|
|
1334
|
+
} catch {
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
`(function(){try{
|
|
1338
|
+
var KEY=${JSON.stringify(THEME_STORAGE_KEY)};
|
|
1339
|
+
var VALID=["light","dark","system"];
|
|
1340
|
+
function fromCookie(){try{var m=document.cookie.match(/(?:^|;\\s*)${THEME_COOKIE}=([^;]+)/);return m?decodeURIComponent(m[1]):null;}catch(e){return null;}}
|
|
1341
|
+
var cookie=fromCookie();
|
|
1342
|
+
var ls=null;try{ls=localStorage.getItem(KEY);}catch(e){}
|
|
1343
|
+
var pref=cookie||ls||"system";
|
|
1344
|
+
if(VALID.indexOf(pref)===-1)pref="system";
|
|
1345
|
+
if(cookie&&cookie!==ls){try{localStorage.setItem(KEY,cookie);}catch(e){}}
|
|
1346
|
+
var resolved=pref;
|
|
1347
|
+
if(pref==="system"){try{resolved=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";}catch(e){resolved="light";}}
|
|
1348
|
+
var d=document.documentElement;
|
|
1349
|
+
if(resolved==="dark"){d.classList.add("dark");}else{d.classList.remove("dark");}
|
|
1350
|
+
try{d.style.colorScheme=resolved;}catch(e){}
|
|
1351
|
+
}catch(e){}})();`;
|
|
1352
|
+
function formatFirstLast(name) {
|
|
1353
|
+
const parts = name.split(/\s+/).filter(Boolean);
|
|
1354
|
+
if (parts.length <= 1) return name;
|
|
1355
|
+
return `${parts[0]} ${parts[parts.length - 1][0].toUpperCase()}.`;
|
|
1356
|
+
}
|
|
1357
|
+
var THEME_OPTIONS = [
|
|
1358
|
+
{ value: "light", label: "Light" },
|
|
1359
|
+
{ value: "system", label: "System" },
|
|
1360
|
+
{ value: "dark", label: "Dark" }
|
|
1361
|
+
];
|
|
1362
|
+
function AppearanceControl() {
|
|
1363
|
+
const [value, setValue] = react$1.useState("system");
|
|
1364
|
+
react$1.useEffect(() => {
|
|
1365
|
+
const cookie = readThemeCookie();
|
|
1366
|
+
let ls = null;
|
|
1367
|
+
try {
|
|
1368
|
+
ls = localStorage.getItem(THEME_STORAGE_KEY);
|
|
1369
|
+
} catch {
|
|
1370
|
+
}
|
|
1371
|
+
setValue(cookie ?? (isThemePreference(ls) ? ls : null) ?? "system");
|
|
1372
|
+
}, []);
|
|
1373
|
+
const pick = (next) => {
|
|
1374
|
+
setValue(next);
|
|
1375
|
+
writeThemeCookie(next);
|
|
1376
|
+
try {
|
|
1377
|
+
localStorage.setItem(THEME_STORAGE_KEY, next);
|
|
1378
|
+
} catch {
|
|
1379
|
+
}
|
|
1380
|
+
applyThemePreference(next);
|
|
1381
|
+
try {
|
|
1382
|
+
window.dispatchEvent(
|
|
1383
|
+
new CustomEvent("politogy:theme-preference", { detail: next })
|
|
1384
|
+
);
|
|
1385
|
+
} catch {
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { px: 3, py: 2, children: [
|
|
1389
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "gray.500", fontWeight: "semibold", mb: 2, children: "APPEARANCE" }),
|
|
1390
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1391
|
+
react.HStack,
|
|
1392
|
+
{
|
|
1393
|
+
spacing: 0,
|
|
1394
|
+
borderWidth: "1px",
|
|
1395
|
+
borderColor: "var(--line, #E2E8F0)",
|
|
1396
|
+
borderRadius: "full",
|
|
1397
|
+
overflow: "hidden",
|
|
1398
|
+
children: THEME_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1399
|
+
react.Box,
|
|
1400
|
+
{
|
|
1401
|
+
as: "button",
|
|
1402
|
+
type: "button",
|
|
1403
|
+
role: "radio",
|
|
1404
|
+
"aria-checked": value === opt.value,
|
|
1405
|
+
onClick: () => pick(opt.value),
|
|
1406
|
+
flex: 1,
|
|
1407
|
+
px: 3,
|
|
1408
|
+
py: 1.5,
|
|
1409
|
+
fontSize: "xs",
|
|
1410
|
+
fontWeight: "semibold",
|
|
1411
|
+
bg: value === opt.value ? "var(--color-race-red, #E63946)" : "transparent",
|
|
1412
|
+
color: value === opt.value ? "white" : "gray.500",
|
|
1413
|
+
_hover: value === opt.value ? {} : { bg: "var(--panel, #F7FAFC)" },
|
|
1414
|
+
transition: "background 0.15s",
|
|
1415
|
+
children: opt.label
|
|
1416
|
+
},
|
|
1417
|
+
opt.value
|
|
1418
|
+
))
|
|
1419
|
+
}
|
|
1420
|
+
)
|
|
1421
|
+
] });
|
|
1422
|
+
}
|
|
1287
1423
|
function avatarUrlFromUser(user) {
|
|
1288
1424
|
if (!user) return void 0;
|
|
1289
1425
|
const meta = user.raw.user_metadata;
|
|
@@ -1306,7 +1442,9 @@ function UserMenu() {
|
|
|
1306
1442
|
const menuListBg = "var(--topbar-bg, #FFFFFF)";
|
|
1307
1443
|
const menuListBorderColor = react.useColorModeValue("gray.200", "gray.700");
|
|
1308
1444
|
if (status !== "authenticated" || !user) return null;
|
|
1309
|
-
const
|
|
1445
|
+
const rawDisplayName = getUserDisplayName(user.raw);
|
|
1446
|
+
const hasRealName = !!rawDisplayName && !rawDisplayName.includes("@");
|
|
1447
|
+
const displayName = hasRealName ? formatFirstLast(rawDisplayName) : user.email ?? rawDisplayName;
|
|
1310
1448
|
const avatarUrl = userAvatarUrl ?? avatarUrlFromUser(user);
|
|
1311
1449
|
const modeConfig = resolveModeConfig(mode);
|
|
1312
1450
|
const currentOrg = org?.currentOrg ?? null;
|
|
@@ -1332,7 +1470,7 @@ function UserMenu() {
|
|
|
1332
1470
|
ml: "2",
|
|
1333
1471
|
children: [
|
|
1334
1472
|
/* @__PURE__ */ jsxRuntime.jsx(react.HStack, { spacing: 2, children: /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "sm", children: displayName }) }),
|
|
1335
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "gray.500", children: user.email })
|
|
1473
|
+
hasRealName ? /* @__PURE__ */ jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "gray.500", children: user.email }) : null
|
|
1336
1474
|
]
|
|
1337
1475
|
}
|
|
1338
1476
|
),
|
|
@@ -1452,6 +1590,8 @@ function UserMenu() {
|
|
|
1452
1590
|
)
|
|
1453
1591
|
] }),
|
|
1454
1592
|
/* @__PURE__ */ jsxRuntime.jsx(react.MenuDivider, {}),
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx(AppearanceControl, {}),
|
|
1594
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.MenuDivider, {}),
|
|
1455
1595
|
/* @__PURE__ */ jsxRuntime.jsx(react.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(fi.FiLogOut, {}), onClick: () => void signOut(), children: "Sign out" })
|
|
1456
1596
|
] }) })
|
|
1457
1597
|
] }) });
|