@the-portland-company/shell 0.67.0 → 0.68.1
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 +32 -0
- package/dist/app-chrome.cjs +588 -441
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +39 -11
- package/dist/app-chrome.d.ts +39 -11
- package/dist/app-chrome.js +33 -15
- package/dist/app-chrome.js.map +1 -1
- package/dist/chrome.css +96 -16
- package/dist/{chunk-T5ERHFNT.js → chunk-2UTIX3LI.js} +539 -387
- package/dist/chunk-2UTIX3LI.js.map +1 -0
- package/dist/{chunk-JHIFJZ73.js → chunk-NHBNM5P3.js} +17 -8
- package/dist/chunk-NHBNM5P3.js.map +1 -0
- package/dist/index.cjs +12 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/native.cjs +557 -396
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +62 -3
- package/dist/native.d.ts +62 -3
- package/dist/native.js +2 -2
- package/dist/theme-preference.cjs +15 -6
- package/dist/theme-preference.cjs.map +1 -1
- package/dist/theme-preference.d.cts +3 -3
- package/dist/theme-preference.d.ts +3 -3
- package/dist/theme-preference.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-JHIFJZ73.js.map +0 -1
- package/dist/chunk-T5ERHFNT.js.map +0 -1
package/dist/app-chrome.d.cts
CHANGED
|
@@ -147,6 +147,14 @@ declare const POLITOGY_APPS: Record<PolitogyAppKey, {
|
|
|
147
147
|
* product shows the platform's Beta notice is a platform decision.
|
|
148
148
|
*/
|
|
149
149
|
beta?: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* false: the chrome does NOT draw its own page-title line (the 56px
|
|
152
|
+
* `<h1>` above `main`); the app's page body owns its title. Specs/Contacts
|
|
153
|
+
* design: the page opens on its own "RELATIONSHIP MODE" eyebrow + H1, so
|
|
154
|
+
* a chrome-owned "Contacts" line above it was a second heading not in the
|
|
155
|
+
* design. Registry-level (platform decision), like `beta`.
|
|
156
|
+
*/
|
|
157
|
+
pageTitle?: false;
|
|
150
158
|
}>;
|
|
151
159
|
type PolitogyAppSession = {
|
|
152
160
|
/** Stable IdP subject (`sub`). */
|
|
@@ -163,14 +171,6 @@ type PolitogyAppSession = {
|
|
|
163
171
|
*/
|
|
164
172
|
userName?: string | null;
|
|
165
173
|
};
|
|
166
|
-
/**
|
|
167
|
-
* Optional DATA plumbing for apps whose session/auth differs — never styling.
|
|
168
|
-
*
|
|
169
|
-
* Everything here is about WHERE data comes from (which fetcher, which org
|
|
170
|
-
* state, which routes an app owns), not what the chrome looks like. Adding a
|
|
171
|
-
* visual option to this type would re-open the drift this component exists to
|
|
172
|
-
* close.
|
|
173
|
-
*/
|
|
174
174
|
type PolitogyFrameData = {
|
|
175
175
|
/** Chrome-API fetcher override for apps that authenticate client-side. */
|
|
176
176
|
fetchJson?: NavChromeFetcher;
|
|
@@ -178,11 +178,36 @@ type PolitogyFrameData = {
|
|
|
178
178
|
devNotes?: ChromeDevNotesConfig;
|
|
179
179
|
/** Controlled org state for apps that own active-org + switching. */
|
|
180
180
|
org?: ControlledOrgState;
|
|
181
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* App-owned children for a standard nav entry this app owns (Contacts).
|
|
183
|
+
* `count` is the live contact total, pre-formatted ("31.9K"), drawn
|
|
184
|
+
* right-aligned on the Contacts row (Specs/Contacts design rail).
|
|
185
|
+
*/
|
|
182
186
|
contactsItem?: {
|
|
183
187
|
href?: string;
|
|
184
188
|
children?: NavItem[];
|
|
189
|
+
count?: string | number | null;
|
|
185
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* Top-level standard-nav rows to omit, by label (e.g. `['Polls', 'CTAs']`).
|
|
193
|
+
* The Specs/Contacts design rail shows exactly Dashboard · Contacts · Email
|
|
194
|
+
* broadcast · SMS/MMS blast / Calls to action · Forms · Surveys / My profile
|
|
195
|
+
* · Organization settings. Default: nothing hidden.
|
|
196
|
+
*/
|
|
197
|
+
hiddenNavItems?: string[];
|
|
198
|
+
/**
|
|
199
|
+
* Universal-search placeholder. Defaults per app (Contacts: "Search
|
|
200
|
+
* contacts, segments, forms"), else "Search".
|
|
201
|
+
*/
|
|
202
|
+
searchPlaceholder?: string;
|
|
203
|
+
/**
|
|
204
|
+
* true: render the rail as flat rows — every standard entry's `children`
|
|
205
|
+
* are stripped before the sidebar draws, so no row carries an accordion
|
|
206
|
+
* chevron (Specs/Contacts design rail: nine plain rows). Routing data is
|
|
207
|
+
* untouched: active-row matching still uses the unstripped tree, exactly
|
|
208
|
+
* as the 'tabs only' preference does. Default: children kept.
|
|
209
|
+
*/
|
|
210
|
+
flatNav?: boolean;
|
|
186
211
|
/** Petitions app: nest its own routes under the Petition-mode entry. */
|
|
187
212
|
petitionsItem?: {
|
|
188
213
|
href?: string;
|
|
@@ -396,8 +421,11 @@ declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fe
|
|
|
396
421
|
identity: ChromeIdentity;
|
|
397
422
|
children: ReactNode;
|
|
398
423
|
}): react_jsx_runtime.JSX.Element;
|
|
399
|
-
/** The standard top-bar action cluster
|
|
400
|
-
*
|
|
424
|
+
/** The standard top-bar action cluster — Reference/UI-Platform v30 "Top bar":
|
|
425
|
+
* Search | Dev notes | Credits | Notifications | Help (farthest right). The
|
|
426
|
+
* Navigation Display switcher moved into the account menu (0.68.0); the Spec
|
|
427
|
+
* overlay slot still renders between Credits and Notifications when the
|
|
428
|
+
* signed-in user is allowed it (it draws nothing otherwise). */
|
|
401
429
|
declare function ChromeTopBarActions(): react_jsx_runtime.JSX.Element | null;
|
|
402
430
|
/** True when any core-org membership carries a super-admin tier. */
|
|
403
431
|
declare function useIsSuperAdmin(): boolean;
|
package/dist/app-chrome.d.ts
CHANGED
|
@@ -147,6 +147,14 @@ declare const POLITOGY_APPS: Record<PolitogyAppKey, {
|
|
|
147
147
|
* product shows the platform's Beta notice is a platform decision.
|
|
148
148
|
*/
|
|
149
149
|
beta?: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* false: the chrome does NOT draw its own page-title line (the 56px
|
|
152
|
+
* `<h1>` above `main`); the app's page body owns its title. Specs/Contacts
|
|
153
|
+
* design: the page opens on its own "RELATIONSHIP MODE" eyebrow + H1, so
|
|
154
|
+
* a chrome-owned "Contacts" line above it was a second heading not in the
|
|
155
|
+
* design. Registry-level (platform decision), like `beta`.
|
|
156
|
+
*/
|
|
157
|
+
pageTitle?: false;
|
|
150
158
|
}>;
|
|
151
159
|
type PolitogyAppSession = {
|
|
152
160
|
/** Stable IdP subject (`sub`). */
|
|
@@ -163,14 +171,6 @@ type PolitogyAppSession = {
|
|
|
163
171
|
*/
|
|
164
172
|
userName?: string | null;
|
|
165
173
|
};
|
|
166
|
-
/**
|
|
167
|
-
* Optional DATA plumbing for apps whose session/auth differs — never styling.
|
|
168
|
-
*
|
|
169
|
-
* Everything here is about WHERE data comes from (which fetcher, which org
|
|
170
|
-
* state, which routes an app owns), not what the chrome looks like. Adding a
|
|
171
|
-
* visual option to this type would re-open the drift this component exists to
|
|
172
|
-
* close.
|
|
173
|
-
*/
|
|
174
174
|
type PolitogyFrameData = {
|
|
175
175
|
/** Chrome-API fetcher override for apps that authenticate client-side. */
|
|
176
176
|
fetchJson?: NavChromeFetcher;
|
|
@@ -178,11 +178,36 @@ type PolitogyFrameData = {
|
|
|
178
178
|
devNotes?: ChromeDevNotesConfig;
|
|
179
179
|
/** Controlled org state for apps that own active-org + switching. */
|
|
180
180
|
org?: ControlledOrgState;
|
|
181
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* App-owned children for a standard nav entry this app owns (Contacts).
|
|
183
|
+
* `count` is the live contact total, pre-formatted ("31.9K"), drawn
|
|
184
|
+
* right-aligned on the Contacts row (Specs/Contacts design rail).
|
|
185
|
+
*/
|
|
182
186
|
contactsItem?: {
|
|
183
187
|
href?: string;
|
|
184
188
|
children?: NavItem[];
|
|
189
|
+
count?: string | number | null;
|
|
185
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* Top-level standard-nav rows to omit, by label (e.g. `['Polls', 'CTAs']`).
|
|
193
|
+
* The Specs/Contacts design rail shows exactly Dashboard · Contacts · Email
|
|
194
|
+
* broadcast · SMS/MMS blast / Calls to action · Forms · Surveys / My profile
|
|
195
|
+
* · Organization settings. Default: nothing hidden.
|
|
196
|
+
*/
|
|
197
|
+
hiddenNavItems?: string[];
|
|
198
|
+
/**
|
|
199
|
+
* Universal-search placeholder. Defaults per app (Contacts: "Search
|
|
200
|
+
* contacts, segments, forms"), else "Search".
|
|
201
|
+
*/
|
|
202
|
+
searchPlaceholder?: string;
|
|
203
|
+
/**
|
|
204
|
+
* true: render the rail as flat rows — every standard entry's `children`
|
|
205
|
+
* are stripped before the sidebar draws, so no row carries an accordion
|
|
206
|
+
* chevron (Specs/Contacts design rail: nine plain rows). Routing data is
|
|
207
|
+
* untouched: active-row matching still uses the unstripped tree, exactly
|
|
208
|
+
* as the 'tabs only' preference does. Default: children kept.
|
|
209
|
+
*/
|
|
210
|
+
flatNav?: boolean;
|
|
186
211
|
/** Petitions app: nest its own routes under the Petition-mode entry. */
|
|
187
212
|
petitionsItem?: {
|
|
188
213
|
href?: string;
|
|
@@ -396,8 +421,11 @@ declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fe
|
|
|
396
421
|
identity: ChromeIdentity;
|
|
397
422
|
children: ReactNode;
|
|
398
423
|
}): react_jsx_runtime.JSX.Element;
|
|
399
|
-
/** The standard top-bar action cluster
|
|
400
|
-
*
|
|
424
|
+
/** The standard top-bar action cluster — Reference/UI-Platform v30 "Top bar":
|
|
425
|
+
* Search | Dev notes | Credits | Notifications | Help (farthest right). The
|
|
426
|
+
* Navigation Display switcher moved into the account menu (0.68.0); the Spec
|
|
427
|
+
* overlay slot still renders between Credits and Notifications when the
|
|
428
|
+
* signed-in user is allowed it (it draws nothing otherwise). */
|
|
401
429
|
declare function ChromeTopBarActions(): react_jsx_runtime.JSX.Element | null;
|
|
402
430
|
/** True when any core-org membership carries a super-admin tier. */
|
|
403
431
|
declare function useIsSuperAdmin(): boolean;
|
package/dist/app-chrome.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { broadcastLogout, watchLogout } from './chunk-LL6LSJAH.js';
|
|
3
|
-
import { clearBetaBannerDismissal, standardPolitogyNav, isNavItemActive, NavAppShell, NavChromeProvider,
|
|
4
|
-
import './chunk-
|
|
3
|
+
import { clearBetaBannerDismissal, standardPolitogyNav, isNavItemActive, NavAppShell, NavChromeProvider, TopBarWidgetSlot, FuelAction, SpecOverlayAction, NotificationsAction, SupportAction, useChromeMe, useThemePreference, useNavChromeFetcher, useChromeOrgs } from './chunk-2UTIX3LI.js';
|
|
4
|
+
import './chunk-NHBNM5P3.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';
|
|
7
7
|
import { createContext, useMemo, useRef, useEffect, useState, useCallback, useContext } from 'react';
|
|
@@ -473,7 +473,12 @@ var MODE_BRAND_LOGOS = {
|
|
|
473
473
|
var modeBrandLogo = (mode) => mode && MODE_BRAND_LOGOS[mode] || DEFAULT_BRAND_LOGO;
|
|
474
474
|
var POLITOGY_APPS = {
|
|
475
475
|
vrm: { title: "Politogy VRM", origin: "https://app.politogyvrm.com", storagePrefix: "vrm" },
|
|
476
|
-
contacts: {
|
|
476
|
+
contacts: {
|
|
477
|
+
title: "Contacts",
|
|
478
|
+
origin: "https://contacts.politogyvrm.com",
|
|
479
|
+
storagePrefix: "contacts",
|
|
480
|
+
pageTitle: false
|
|
481
|
+
},
|
|
477
482
|
forms: { title: "Forms", origin: "https://forms.politogyvrm.com", storagePrefix: "forms" },
|
|
478
483
|
surveys: { title: "Surveys", origin: "https://surveys.politogyvrm.com", storagePrefix: "surveys" },
|
|
479
484
|
polls: { title: "Polls", origin: "https://polls.politogyvrm.com", storagePrefix: "polls" },
|
|
@@ -514,6 +519,9 @@ var POLITOGY_APPS = {
|
|
|
514
519
|
canvass: { title: "Field Canvassing", origin: "https://canvass.politogyvrm.com", storagePrefix: "canvass", mode: "campaign" },
|
|
515
520
|
signs: { title: "Sign Mapping", origin: "https://signs.politogyvrm.com", storagePrefix: "signs", mode: "campaign" }
|
|
516
521
|
};
|
|
522
|
+
var DEFAULT_SEARCH_PLACEHOLDER = {
|
|
523
|
+
contacts: "Search contacts, segments, forms"
|
|
524
|
+
};
|
|
517
525
|
function PolitogyAppFrame({
|
|
518
526
|
app,
|
|
519
527
|
pathname,
|
|
@@ -672,10 +680,11 @@ function FrameBody({
|
|
|
672
680
|
// under it. This is routing data, not chrome configuration.
|
|
673
681
|
contactsItem: data?.contactsItem,
|
|
674
682
|
petitionsItem: data?.petitionsItem,
|
|
683
|
+
hiddenItems: data?.hiddenNavItems,
|
|
675
684
|
mode: navMode,
|
|
676
685
|
activeOrgId
|
|
677
686
|
}),
|
|
678
|
-
[data?.contactsItem, data?.petitionsItem, navMode, activeOrgId]
|
|
687
|
+
[data?.contactsItem, data?.petitionsItem, data?.hiddenNavItems, navMode, activeOrgId]
|
|
679
688
|
);
|
|
680
689
|
const navItems = core?.nav ?? derivedNavItems;
|
|
681
690
|
const navIsActive = useMemo(() => {
|
|
@@ -724,7 +733,7 @@ function FrameBody({
|
|
|
724
733
|
// A flat rail's sub-menu IS the nav, so the 'tabs only' preference
|
|
725
734
|
// (which strips children) would leave one childless parent row —
|
|
726
735
|
// flat apps ignore the stripping.
|
|
727
|
-
items: navDisplay === "tabs" && meta.navShape !== "flat" ? navItems.map(({ children: _sub, ...item }) => item) : navItems,
|
|
736
|
+
items: (navDisplay === "tabs" || data?.flatNav === true) && meta.navShape !== "flat" ? navItems.map(({ children: _sub, ...item }) => item) : navItems,
|
|
728
737
|
isActive: navIsActive,
|
|
729
738
|
flatten: meta.navShape === "flat"
|
|
730
739
|
},
|
|
@@ -751,7 +760,7 @@ function FrameBody({
|
|
|
751
760
|
topBar: {
|
|
752
761
|
// Core's pages publish their own identity; every other app is one
|
|
753
762
|
// product surface and takes its registry title.
|
|
754
|
-
title: core?.page?.title ?? (grants?.includes("title") ? data?.frame?.title : void 0) ?? meta.title,
|
|
763
|
+
title: core?.page?.title ?? (grants?.includes("title") ? data?.frame?.title : void 0) ?? (meta.pageTitle === false ? void 0 : meta.title),
|
|
755
764
|
breadcrumbs,
|
|
756
765
|
user: {
|
|
757
766
|
name: identity.userName,
|
|
@@ -767,7 +776,7 @@ function FrameBody({
|
|
|
767
776
|
// search is the only thing on the left end of the bar. No app wires
|
|
768
777
|
// search yet, so this stays decorative (`NavTopBarProps.search` — "an
|
|
769
778
|
// app that has not wired search yet still gets the correct chrome").
|
|
770
|
-
search: {},
|
|
779
|
+
search: { placeholder: data?.searchPlaceholder ?? DEFAULT_SEARCH_PLACEHOLDER[app] ?? "Search" },
|
|
771
780
|
// "Build notes" — a quiet text button that starts the right-hand
|
|
772
781
|
// group. The spec names the element and its position but not its
|
|
773
782
|
// destination content; `onOpen` is left unset until that is defined.
|
|
@@ -1166,8 +1175,6 @@ function ChromeTopBarActions() {
|
|
|
1166
1175
|
const state = useChromeState();
|
|
1167
1176
|
if (!state) return null;
|
|
1168
1177
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1169
|
-
/* @__PURE__ */ jsx(FuelAction, { orgId: state.orgId }),
|
|
1170
|
-
/* @__PURE__ */ jsx(NavDisplayAction, { value: state.navDisplay, onChange: state.setNavDisplay }),
|
|
1171
1178
|
/* @__PURE__ */ jsx(
|
|
1172
1179
|
TopBarWidgetSlot,
|
|
1173
1180
|
{
|
|
@@ -1176,9 +1183,10 @@ function ChromeTopBarActions() {
|
|
|
1176
1183
|
children: /* @__PURE__ */ jsx(ChromeDevNotesMenu, {})
|
|
1177
1184
|
}
|
|
1178
1185
|
),
|
|
1186
|
+
/* @__PURE__ */ jsx(FuelAction, { orgId: state.orgId }),
|
|
1179
1187
|
/* @__PURE__ */ jsx(SpecOverlayAction, { orgId: state.orgId, orgName: state.orgs.find((o) => o.id === state.orgId)?.name ?? null }),
|
|
1180
|
-
/* @__PURE__ */ jsx(
|
|
1181
|
-
/* @__PURE__ */ jsx(
|
|
1188
|
+
/* @__PURE__ */ jsx(NotificationsAction, { orgId: state.orgId }),
|
|
1189
|
+
/* @__PURE__ */ jsx(SupportAction, { orgId: state.orgId })
|
|
1182
1190
|
] });
|
|
1183
1191
|
}
|
|
1184
1192
|
function ChromeDevNotesMenu() {
|
|
@@ -1232,7 +1240,8 @@ function useChromeUserMenu({
|
|
|
1232
1240
|
roles: (state?.orgs ?? []).filter((o) => o.rawRole || o.role).map((o) => ({ role: o.rawRole ?? o.role, orgName: o.name })),
|
|
1233
1241
|
accounts: [{ id: userId, name: userName, email, avatarUrl: null, active: true }],
|
|
1234
1242
|
addAccountHref: `${coreBase}/my-profile#accounts`,
|
|
1235
|
-
theme: { value: theme.value, onChange: theme.setValue }
|
|
1243
|
+
theme: { value: theme.value, onChange: theme.setValue },
|
|
1244
|
+
navDisplay: state ? { value: state.navDisplay, onChange: state.setNavDisplay } : void 0
|
|
1236
1245
|
};
|
|
1237
1246
|
}
|
|
1238
1247
|
var MODE_DEFS = [
|
|
@@ -1295,10 +1304,19 @@ function useChromeMode(arg = {}) {
|
|
|
1295
1304
|
return {
|
|
1296
1305
|
label: current.label,
|
|
1297
1306
|
icon: current.icon,
|
|
1298
|
-
|
|
1299
|
-
|
|
1307
|
+
// Left-Navigation §7 / Reference/UI-Platform: always the row of three icon
|
|
1308
|
+
// buttons. A mode the organization does not hold is shown dimmed and not
|
|
1309
|
+
// selectable, never hidden. Before entitlements land only the current mode
|
|
1310
|
+
// reads as available (no layout shift, nothing clickable it shouldn't be).
|
|
1311
|
+
options: MODE_DEFS.map((o) => ({
|
|
1312
|
+
id: o.id,
|
|
1313
|
+
label: o.label,
|
|
1314
|
+
icon: o.icon,
|
|
1315
|
+
available: entitled ? Boolean(entitled[o.id]) || o.id === current.id : o.id === current.id
|
|
1316
|
+
})),
|
|
1317
|
+
onSelect: options.length > 0 ? (id) => {
|
|
1300
1318
|
const def = MODE_DEFS.find((m) => m.id === id);
|
|
1301
|
-
if (!def) return;
|
|
1319
|
+
if (!def || !entitled?.[def.id]) return;
|
|
1302
1320
|
setSelectedModeId(id);
|
|
1303
1321
|
try {
|
|
1304
1322
|
localStorage.setItem(MODE_STORAGE_KEY, id);
|