@the-portland-company/shell 0.71.1 → 0.72.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 +10 -0
- package/dist/app-chrome.cjs +65 -189
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +8 -7
- package/dist/app-chrome.d.ts +8 -7
- package/dist/app-chrome.js +4 -42
- package/dist/app-chrome.js.map +1 -1
- package/dist/chrome.css +7 -0
- package/dist/{chunk-JBPJOPLW.js → chunk-6OM62ZTK.js} +68 -152
- package/dist/chunk-6OM62ZTK.js.map +1 -0
- package/dist/native.cjs +67 -149
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +6 -5
- package/dist/native.d.ts +6 -5
- package/dist/native.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-JBPJOPLW.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 0.72.0
|
|
2
|
+
|
|
3
|
+
Left-Navigation §5, §10 and §12.
|
|
4
|
+
- The rail takes its mode colour from the current mode label when no registry modeId is passed, as in VRM core. Campaign Mode is now Deep Race Red, not ink.
|
|
5
|
+
- The Campaign rail tokens are #A12430 for raised wells, #F0CFD2 for inactive row text and #F6DADD for the eyebrow.
|
|
6
|
+
- The footer user row shows the name as "First L.", with two-letter initials.
|
|
7
|
+
- Flat bar per §8.2: a row with children is drawn as one link with no chevron and no accordion. It points to its own page or its first child's, and it is active on any route beneath it. The children stay in the tree for breadcrumbs and tabs.
|
|
8
|
+
- Icons per §8.1: standardPolitogyNav falls back to the shared Lucide map when no `icons` are passed, so VRM core rows get icons. The map moved to native/standardNavIcons and app-chrome re-exports it.
|
|
9
|
+
- Removed the tests for the retired accordion and Navigation Display sub-menu, and added §8.2 tests.
|
|
10
|
+
|
|
1
11
|
## 0.71.1
|
|
2
12
|
|
|
3
13
|
Build line in the rail footer follows Specs/Left-Navigation §9 and Reference/UI-Platform Meta.
|
package/dist/app-chrome.cjs
CHANGED
|
@@ -6,8 +6,8 @@ var clsx = require('clsx');
|
|
|
6
6
|
var fi = require('react-icons/fi');
|
|
7
7
|
var reactDom = require('react-dom');
|
|
8
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
-
var devnotes = require('@the-portland-company/devnotes');
|
|
10
9
|
var lu = require('react-icons/lu');
|
|
10
|
+
var devnotes = require('@the-portland-company/devnotes');
|
|
11
11
|
|
|
12
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
13
|
|
|
@@ -1931,6 +1931,45 @@ function useThemePreference() {
|
|
|
1931
1931
|
);
|
|
1932
1932
|
return { value, setValue };
|
|
1933
1933
|
}
|
|
1934
|
+
var standardNavIcons = {
|
|
1935
|
+
home: lu.LuHouse,
|
|
1936
|
+
users: lu.LuUsers,
|
|
1937
|
+
mail: lu.LuMail,
|
|
1938
|
+
messageSquare: lu.LuMessageSquare,
|
|
1939
|
+
layout: lu.LuLayoutDashboard,
|
|
1940
|
+
activity: lu.LuActivity,
|
|
1941
|
+
lifeBuoy: lu.LuLifeBuoy,
|
|
1942
|
+
grid: lu.LuLayoutGrid,
|
|
1943
|
+
list: lu.LuList,
|
|
1944
|
+
upload: lu.LuUpload,
|
|
1945
|
+
edit: lu.LuPencil,
|
|
1946
|
+
fileText: lu.LuFileText,
|
|
1947
|
+
send: lu.LuSend,
|
|
1948
|
+
clock: lu.LuClock,
|
|
1949
|
+
user: lu.LuUser,
|
|
1950
|
+
barChart: lu.LuChartColumn,
|
|
1951
|
+
briefcase: lu.LuBriefcase,
|
|
1952
|
+
settings: lu.LuSettings,
|
|
1953
|
+
creditCard: lu.LuCreditCard,
|
|
1954
|
+
dollarSign: lu.LuDollarSign,
|
|
1955
|
+
share: lu.LuShare2,
|
|
1956
|
+
// Campaign / Petition mode slots.
|
|
1957
|
+
phone: lu.LuPhone,
|
|
1958
|
+
map: lu.LuMap,
|
|
1959
|
+
mapPin: lu.LuMapPin,
|
|
1960
|
+
target: lu.LuTarget,
|
|
1961
|
+
flag: lu.LuFlag,
|
|
1962
|
+
layoutDashboard: lu.LuLayoutDashboard,
|
|
1963
|
+
usersRound: lu.LuUsersRound,
|
|
1964
|
+
mousePointerClick: lu.LuMousePointerClick,
|
|
1965
|
+
clipboardList: lu.LuClipboardList,
|
|
1966
|
+
circleUser: lu.LuCircleUser,
|
|
1967
|
+
crosshair: lu.LuCrosshair,
|
|
1968
|
+
landmark: lu.LuLandmark,
|
|
1969
|
+
chartNoAxes: lu.LuChartNoAxesColumn,
|
|
1970
|
+
doorOpen: lu.LuDoorOpen,
|
|
1971
|
+
signpost: lu.LuSignpost
|
|
1972
|
+
};
|
|
1934
1973
|
|
|
1935
1974
|
// src/native/standardNav.ts
|
|
1936
1975
|
var CAMPAIGN_FEATURE_AVAILABILITY = {
|
|
@@ -2044,7 +2083,7 @@ var APP_SIGNS_CHILDREN = [
|
|
|
2044
2083
|
function standardPolitogyNav(opts) {
|
|
2045
2084
|
const base = opts.coreBaseUrl.replace(/\/+$/, "");
|
|
2046
2085
|
const abs = (path) => `${base}${path.startsWith("/") ? path : `/${path}`}`;
|
|
2047
|
-
const icon = (key) => opts.icons?.[key];
|
|
2086
|
+
const icon = (key) => opts.icons?.[key] ?? standardNavIcons[key];
|
|
2048
2087
|
const orgParam = opts.activeOrgId ? `org=${opts.activeOrgId}` : "";
|
|
2049
2088
|
const withOrg = (url) => orgParam ? `${url}${url.includes("?") ? "&" : "?"}${orgParam}` : url;
|
|
2050
2089
|
const leaves = (children) => children.map((c) => ({ label: c.label, icon: icon(c.icon), href: withOrg(abs(c.path)) }));
|
|
@@ -2256,6 +2295,24 @@ function hasActiveChild(item, pathname, activeFn) {
|
|
|
2256
2295
|
)
|
|
2257
2296
|
);
|
|
2258
2297
|
}
|
|
2298
|
+
function firstLeafHref(item) {
|
|
2299
|
+
for (const c of item.children ?? []) {
|
|
2300
|
+
if (c.kind === "section") continue;
|
|
2301
|
+
if (c.href) return c.href;
|
|
2302
|
+
const deep = firstLeafHref(c);
|
|
2303
|
+
if (deep) return deep;
|
|
2304
|
+
}
|
|
2305
|
+
return void 0;
|
|
2306
|
+
}
|
|
2307
|
+
function modeIdFromLabel(label) {
|
|
2308
|
+
const l = label?.trim().toLowerCase();
|
|
2309
|
+
return l ? l.replace(/\s+mode$/, "") : void 0;
|
|
2310
|
+
}
|
|
2311
|
+
function shortUserName(name) {
|
|
2312
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
2313
|
+
if (parts.length < 2) return parts[0] ?? "";
|
|
2314
|
+
return `${parts[0]} ${parts[parts.length - 1][0].toUpperCase()}.`;
|
|
2315
|
+
}
|
|
2259
2316
|
function shortEnvLabel(label) {
|
|
2260
2317
|
const l = label.trim().toLowerCase();
|
|
2261
2318
|
if (l === "production") return "prod";
|
|
@@ -2362,7 +2419,6 @@ function NavSidebar({
|
|
|
2362
2419
|
react.useEffect(() => {
|
|
2363
2420
|
setOpenGroup(activeGroupKey);
|
|
2364
2421
|
}, [activeGroupKey]);
|
|
2365
|
-
const toggleGroup = (key) => setOpenGroup((prev) => prev === key ? null : key);
|
|
2366
2422
|
return /* @__PURE__ */ jsxRuntime.jsxs(RailCollapsibleContext.Provider, { value: collapsible, children: [
|
|
2367
2423
|
open ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2368
2424
|
"div",
|
|
@@ -2702,21 +2758,16 @@ function NavSidebar({
|
|
|
2702
2758
|
});
|
|
2703
2759
|
}
|
|
2704
2760
|
if (item.children && item.children.length > 0) {
|
|
2705
|
-
const key = groupKeyOf(item, idx);
|
|
2706
2761
|
const selfActive = item.href ? activeFn(pathname, item.href) : false;
|
|
2707
2762
|
const parentActive = selfActive || hasActiveChild(item, pathname, activeFn);
|
|
2708
2763
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2709
|
-
|
|
2764
|
+
NavRow,
|
|
2710
2765
|
{
|
|
2711
|
-
item,
|
|
2766
|
+
item: { ...item, href: item.href ?? firstLeafHref(item), children: void 0 },
|
|
2712
2767
|
active: parentActive,
|
|
2713
|
-
open: openGroup === key,
|
|
2714
|
-
onToggle: () => toggleGroup(key),
|
|
2715
|
-
pathname,
|
|
2716
|
-
activeFn,
|
|
2717
2768
|
Link
|
|
2718
2769
|
},
|
|
2719
|
-
|
|
2770
|
+
item.href ?? groupKeyOf(item, idx)
|
|
2720
2771
|
);
|
|
2721
2772
|
}
|
|
2722
2773
|
const active = item.href ? activeFn(pathname, item.href) : false;
|
|
@@ -3004,142 +3055,6 @@ function NavRow({
|
|
|
3004
3055
|
}
|
|
3005
3056
|
);
|
|
3006
3057
|
}
|
|
3007
|
-
function NavGroup({
|
|
3008
|
-
item,
|
|
3009
|
-
active,
|
|
3010
|
-
open,
|
|
3011
|
-
onToggle,
|
|
3012
|
-
pathname,
|
|
3013
|
-
activeFn,
|
|
3014
|
-
Link
|
|
3015
|
-
}) {
|
|
3016
|
-
const rc = useRailCollapse();
|
|
3017
|
-
const Icon = item.icon;
|
|
3018
|
-
const headerClasses = [
|
|
3019
|
-
"group relative block w-full overflow-hidden text-left transition",
|
|
3020
|
-
open ? "rounded-t-[5px]" : "rounded-[5px]",
|
|
3021
|
-
active ? NAV_TOP_ACTIVE_CLASS : open ? "bg-[color:var(--sidebar-row-hover-bg,var(--panel))] text-[color:var(--sidebar-text,var(--foreground))]" : NAV_TOP_INACTIVE_CLASS
|
|
3022
|
-
].join(" ");
|
|
3023
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3024
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3025
|
-
"button",
|
|
3026
|
-
{
|
|
3027
|
-
type: "button",
|
|
3028
|
-
onClick: () => {
|
|
3029
|
-
onToggle();
|
|
3030
|
-
item.onClick?.();
|
|
3031
|
-
},
|
|
3032
|
-
"aria-expanded": open,
|
|
3033
|
-
title: item.label,
|
|
3034
|
-
className: headerClasses,
|
|
3035
|
-
children: [
|
|
3036
|
-
active ? /* @__PURE__ */ jsxRuntime.jsx(NavActiveRail, {}) : null,
|
|
3037
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: `relative z-10 flex items-center ${NAV_TOP_ROW_CLASS(active)} ${rc("max-md:justify-center max-md:px-0")}`, children: [
|
|
3038
|
-
Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: NAV_TOP_ICON_SIZE, className: "shrink-0 text-current" }) : null,
|
|
3039
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `min-w-0 flex-1 truncate ${rc("max-md:hidden")}`, children: item.label }),
|
|
3040
|
-
/* @__PURE__ */ jsxRuntime.jsx(NavRowBadge, { value: item.badge }),
|
|
3041
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3042
|
-
ChevronDown,
|
|
3043
|
-
{
|
|
3044
|
-
className: [
|
|
3045
|
-
"shrink-0 opacity-80 transition-transform duration-200",
|
|
3046
|
-
open ? "rotate-180" : "",
|
|
3047
|
-
rc("max-md:hidden")
|
|
3048
|
-
].join(" ")
|
|
3049
|
-
}
|
|
3050
|
-
)
|
|
3051
|
-
] })
|
|
3052
|
-
]
|
|
3053
|
-
}
|
|
3054
|
-
),
|
|
3055
|
-
open ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `overflow-hidden rounded-b-md bg-[color:var(--nav-submenu-bg)] p-1 ${rc("max-md:hidden")}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-0.5", children: item.children.map((child, i) => {
|
|
3056
|
-
if (child.kind === "section") {
|
|
3057
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3058
|
-
NavSectionRow,
|
|
3059
|
-
{
|
|
3060
|
-
label: child.label,
|
|
3061
|
-
first: i === 0,
|
|
3062
|
-
variant: "sub"
|
|
3063
|
-
},
|
|
3064
|
-
`sub-section-${i}-${child.label}`
|
|
3065
|
-
);
|
|
3066
|
-
}
|
|
3067
|
-
const childActive = child.href ? activeFn(pathname, child.href) : false;
|
|
3068
|
-
if (child.children && child.children.length > 0) {
|
|
3069
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3070
|
-
NavSubGroup,
|
|
3071
|
-
{
|
|
3072
|
-
item: child,
|
|
3073
|
-
pathname,
|
|
3074
|
-
activeFn,
|
|
3075
|
-
Link
|
|
3076
|
-
},
|
|
3077
|
-
child.href ?? `subgrp-${i}-${child.label}`
|
|
3078
|
-
);
|
|
3079
|
-
}
|
|
3080
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3081
|
-
NavRow,
|
|
3082
|
-
{
|
|
3083
|
-
item: child,
|
|
3084
|
-
active: childActive,
|
|
3085
|
-
Link,
|
|
3086
|
-
variant: "sub"
|
|
3087
|
-
},
|
|
3088
|
-
child.href ?? `sub-${i}-${child.label}`
|
|
3089
|
-
);
|
|
3090
|
-
}) }) }) : null
|
|
3091
|
-
] });
|
|
3092
|
-
}
|
|
3093
|
-
function NavSubGroup({
|
|
3094
|
-
item,
|
|
3095
|
-
pathname,
|
|
3096
|
-
activeFn,
|
|
3097
|
-
Link
|
|
3098
|
-
}) {
|
|
3099
|
-
const ownsActive = (item.href ? activeFn(pathname, item.href) : false) || (item.children ?? []).some((c) => c.href ? activeFn(pathname, c.href) : false);
|
|
3100
|
-
const [open, setOpen] = react.useState(ownsActive);
|
|
3101
|
-
react.useEffect(() => {
|
|
3102
|
-
if (ownsActive) setOpen(true);
|
|
3103
|
-
}, [ownsActive]);
|
|
3104
|
-
const Icon = item.icon;
|
|
3105
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3106
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3107
|
-
"button",
|
|
3108
|
-
{
|
|
3109
|
-
type: "button",
|
|
3110
|
-
onClick: () => setOpen((v) => !v),
|
|
3111
|
-
"aria-expanded": open,
|
|
3112
|
-
className: [
|
|
3113
|
-
"flex w-full items-center gap-2.5 rounded px-3 py-1.5 text-left text-[13px] font-medium transition",
|
|
3114
|
-
ownsActive ? "text-[color:var(--color-accent)]" : "text-[color:var(--sidebar-text,var(--muted))] hover:bg-[color:var(--nav-row-hover)] hover:text-[color:var(--foreground)]"
|
|
3115
|
-
].join(" "),
|
|
3116
|
-
children: [
|
|
3117
|
-
Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: 15, className: "shrink-0 text-current" }) : null,
|
|
3118
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
|
|
3119
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3120
|
-
ChevronDown,
|
|
3121
|
-
{
|
|
3122
|
-
className: [
|
|
3123
|
-
"shrink-0 opacity-70 transition-transform duration-200",
|
|
3124
|
-
open ? "rotate-180" : ""
|
|
3125
|
-
].join(" ")
|
|
3126
|
-
}
|
|
3127
|
-
)
|
|
3128
|
-
]
|
|
3129
|
-
}
|
|
3130
|
-
),
|
|
3131
|
-
open ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4 flex flex-col gap-0.5 border-l border-[color:var(--line)] pl-2", children: item.children.map((leaf, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3132
|
-
NavRow,
|
|
3133
|
-
{
|
|
3134
|
-
item: leaf,
|
|
3135
|
-
active: leaf.href ? activeFn(pathname, leaf.href) : false,
|
|
3136
|
-
Link,
|
|
3137
|
-
variant: "sub"
|
|
3138
|
-
},
|
|
3139
|
-
leaf.href ?? `subsub-${i}-${leaf.label}`
|
|
3140
|
-
)) }) : null
|
|
3141
|
-
] });
|
|
3142
|
-
}
|
|
3143
3058
|
function OrgIdCopyButton({ id }) {
|
|
3144
3059
|
const [copied, setCopied] = react.useState(false);
|
|
3145
3060
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3439,8 +3354,8 @@ function NavSidebarUserCard({
|
|
|
3439
3354
|
}) {
|
|
3440
3355
|
const rawName = user.name?.trim() || "";
|
|
3441
3356
|
const hasRealName = rawName.length > 0 && !rawName.includes("@");
|
|
3442
|
-
const displayName = hasRealName ? rawName : user.email ?? "Signed in";
|
|
3443
|
-
const initials =
|
|
3357
|
+
const displayName = hasRealName ? shortUserName(rawName) : user.email ?? "Signed in";
|
|
3358
|
+
const initials = hasRealName ? rawName.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0]).join("").toUpperCase() : (user.email ?? "P").slice(0, 2).toUpperCase();
|
|
3444
3359
|
const secondary = hasRealName ? user.email || [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member" : [user.tier, user.role].filter(Boolean).join(" \xB7 ") || "member";
|
|
3445
3360
|
const rc = useRailCollapse();
|
|
3446
3361
|
return /* @__PURE__ */ jsxRuntime.jsxs("details", { "data-nav-details": true, className: "group/acct relative", children: [
|
|
@@ -3756,7 +3671,7 @@ function NavAppShell({
|
|
|
3756
3671
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3757
3672
|
"div",
|
|
3758
3673
|
{
|
|
3759
|
-
"data-politogy-mode": modeId,
|
|
3674
|
+
"data-politogy-mode": modeId ?? modeIdFromLabel(sidebar.mode?.label),
|
|
3760
3675
|
className: "min-h-screen bg-[color:var(--background)] text-[color:var(--foreground)]",
|
|
3761
3676
|
children: [
|
|
3762
3677
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4772,45 +4687,6 @@ function FrameBody({
|
|
|
4772
4687
|
)
|
|
4773
4688
|
] });
|
|
4774
4689
|
}
|
|
4775
|
-
var standardNavIcons = {
|
|
4776
|
-
home: lu.LuHouse,
|
|
4777
|
-
users: lu.LuUsers,
|
|
4778
|
-
mail: lu.LuMail,
|
|
4779
|
-
messageSquare: lu.LuMessageSquare,
|
|
4780
|
-
layout: lu.LuLayoutDashboard,
|
|
4781
|
-
activity: lu.LuActivity,
|
|
4782
|
-
lifeBuoy: lu.LuLifeBuoy,
|
|
4783
|
-
grid: lu.LuLayoutGrid,
|
|
4784
|
-
list: lu.LuList,
|
|
4785
|
-
upload: lu.LuUpload,
|
|
4786
|
-
edit: lu.LuPencil,
|
|
4787
|
-
fileText: lu.LuFileText,
|
|
4788
|
-
send: lu.LuSend,
|
|
4789
|
-
clock: lu.LuClock,
|
|
4790
|
-
user: lu.LuUser,
|
|
4791
|
-
barChart: lu.LuChartColumn,
|
|
4792
|
-
briefcase: lu.LuBriefcase,
|
|
4793
|
-
settings: lu.LuSettings,
|
|
4794
|
-
creditCard: lu.LuCreditCard,
|
|
4795
|
-
dollarSign: lu.LuDollarSign,
|
|
4796
|
-
share: lu.LuShare2,
|
|
4797
|
-
// Campaign / Petition mode slots.
|
|
4798
|
-
phone: lu.LuPhone,
|
|
4799
|
-
map: lu.LuMap,
|
|
4800
|
-
mapPin: lu.LuMapPin,
|
|
4801
|
-
target: lu.LuTarget,
|
|
4802
|
-
flag: lu.LuFlag,
|
|
4803
|
-
layoutDashboard: lu.LuLayoutDashboard,
|
|
4804
|
-
usersRound: lu.LuUsersRound,
|
|
4805
|
-
mousePointerClick: lu.LuMousePointerClick,
|
|
4806
|
-
clipboardList: lu.LuClipboardList,
|
|
4807
|
-
circleUser: lu.LuCircleUser,
|
|
4808
|
-
crosshair: lu.LuCrosshair,
|
|
4809
|
-
landmark: lu.LuLandmark,
|
|
4810
|
-
chartNoAxes: lu.LuChartNoAxesColumn,
|
|
4811
|
-
doorOpen: lu.LuDoorOpen,
|
|
4812
|
-
signpost: lu.LuSignpost
|
|
4813
|
-
};
|
|
4814
4690
|
var ORG_STORAGE_KEY = "vrm.activeOrg";
|
|
4815
4691
|
var MODE_STORAGE_KEY = "vrm.activeMode";
|
|
4816
4692
|
var CORE_BASE_URL = "https://app.politogyvrm.com";
|