@the-portland-company/shell 0.16.4 → 0.16.5

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/native.cjs CHANGED
@@ -1225,8 +1225,11 @@ function NavTopBar({
1225
1225
  actions,
1226
1226
  themeToggle
1227
1227
  }) {
1228
- const initials = (user?.name ?? "Politogy").slice(0, 2).toUpperCase();
1229
- const secondary = user?.email || [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member";
1228
+ const rawName = user?.name?.trim() || "";
1229
+ const hasRealName = rawName.length > 0 && !rawName.includes("@");
1230
+ const displayName = hasRealName ? formatFirstLast(rawName) : user?.email ?? "Signed in";
1231
+ const initials = (hasRealName ? rawName : user?.email ?? "P").slice(0, 2).toUpperCase();
1232
+ const secondary = hasRealName ? user?.email || [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member" : [user?.tier, user?.role].filter(Boolean).join(" \xB7 ") || "member";
1230
1233
  return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "sticky top-0 z-20 flex h-20 items-center justify-between gap-4 border-b border-[color:var(--line)] bg-[color:var(--panel)] px-4 backdrop-blur-xl", children: [
1231
1234
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1232
1235
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1239,7 +1242,7 @@ function NavTopBar({
1239
1242
  ),
1240
1243
  subtitle ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm text-[color:var(--muted)]", children: subtitle }) : null
1241
1244
  ] }),
1242
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-[var(--topbar-icon-gap,8px)]", children: [
1245
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex shrink-0 items-center gap-[var(--topbar-icon-gap,8px)]", children: [
1243
1246
  actionsList && actionsList.length > 0 ? actionsList.map((action) => /* @__PURE__ */ jsxRuntime.jsx(NavTopBarActionButton, { action }, action.key)) : null,
1244
1247
  actions,
1245
1248
  themeToggle,
@@ -1254,7 +1257,7 @@ function NavTopBar({
1254
1257
  }
1255
1258
  ) : initials }),
1256
1259
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden flex-col leading-tight md:flex", children: [
1257
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: user?.name ?? "Signed in" }),
1260
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: displayName }),
1258
1261
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-[color:var(--muted)]", children: secondary })
1259
1262
  ] }),
1260
1263
  /* @__PURE__ */ jsxRuntime.jsx(ChevronDown, {}),
@@ -1263,7 +1266,7 @@ function NavTopBar({
1263
1266
  {
1264
1267
  title: "My Account",
1265
1268
  description: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1266
- user?.name ?? "Signed in",
1269
+ hasRealName ? rawName : user?.email ?? "Signed in",
1267
1270
  user?.email ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1268
1271
  /* @__PURE__ */ jsxRuntime.jsx("br", {}),
1269
1272
  user.email
@@ -1391,10 +1394,64 @@ function NavTopBar({
1391
1394
  }
1392
1395
  ) : null
1393
1396
  ] })
1394
- ] })
1397
+ ] }),
1398
+ !hasRealName && user ? /* @__PURE__ */ jsxRuntime.jsx(NamePromptBubble, { profileHref: userMenu?.myProfileHref }) : null
1395
1399
  ] })
1396
1400
  ] });
1397
1401
  }
1402
+ function NamePromptBubble({ profileHref }) {
1403
+ const KEY = "politogy_name_prompt_dismissed";
1404
+ const [dismissed, setDismissed] = react.useState(true);
1405
+ react.useEffect(() => {
1406
+ try {
1407
+ setDismissed(sessionStorage.getItem(KEY) === "1");
1408
+ } catch {
1409
+ setDismissed(false);
1410
+ }
1411
+ }, []);
1412
+ if (dismissed) return null;
1413
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-4 top-full z-30 mt-2 w-64 rounded-xl border border-[color:var(--line)] bg-[color:var(--panel-elevated)] p-3 shadow-[var(--shadow-soft)]", children: [
1414
+ /* @__PURE__ */ jsxRuntime.jsx(
1415
+ "span",
1416
+ {
1417
+ "aria-hidden": true,
1418
+ className: "absolute -top-[5px] right-[11px] h-2.5 w-2.5 rotate-45 border-l border-t border-[color:var(--line)] bg-[color:var(--panel-elevated)]"
1419
+ }
1420
+ ),
1421
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-[color:var(--foreground)]", children: "Add your name" }),
1422
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-snug text-[color:var(--muted)]", children: "Set your first and last name so teammates see you \u2014 not your email." }),
1423
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center gap-2", children: [
1424
+ profileHref ? /* @__PURE__ */ jsxRuntime.jsx(
1425
+ "a",
1426
+ {
1427
+ href: safeHref(profileHref),
1428
+ className: "rounded-full bg-[color:var(--color-race-red)] px-3 py-1 text-xs font-semibold text-white hover:opacity-90",
1429
+ children: "Set name"
1430
+ }
1431
+ ) : null,
1432
+ /* @__PURE__ */ jsxRuntime.jsx(
1433
+ "button",
1434
+ {
1435
+ type: "button",
1436
+ onClick: () => {
1437
+ setDismissed(true);
1438
+ try {
1439
+ sessionStorage.setItem(KEY, "1");
1440
+ } catch {
1441
+ }
1442
+ },
1443
+ className: "rounded-full border border-[color:var(--line)] px-3 py-1 text-xs font-semibold text-[color:var(--foreground)] hover:bg-[color:var(--panel)]",
1444
+ children: "Dismiss"
1445
+ }
1446
+ )
1447
+ ] })
1448
+ ] });
1449
+ }
1450
+ function formatFirstLast(name) {
1451
+ const parts = name.split(/\s+/).filter(Boolean);
1452
+ if (parts.length === 1) return parts[0];
1453
+ return `${parts[0]} ${parts[parts.length - 1][0].toUpperCase()}.`;
1454
+ }
1398
1455
  function ProfileIcon() {
1399
1456
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
1400
1457
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),