@the-portland-company/shell 0.76.7 → 0.76.9
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/app-chrome.cjs +141 -129
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.js +10 -3
- package/dist/app-chrome.js.map +1 -1
- package/dist/chrome.css +13 -4
- package/dist/{chunk-LIBRFEDD.js → chunk-RBJGWQJX.js} +10 -4
- package/dist/chunk-RBJGWQJX.js.map +1 -0
- package/dist/native.cjs +16 -2
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +2 -1
- package/package.json +1 -1
- package/dist/chunk-LIBRFEDD.js.map +0 -1
package/dist/app-chrome.cjs
CHANGED
|
@@ -89,6 +89,132 @@ function normalize(s) {
|
|
|
89
89
|
return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// src/active-org.ts
|
|
93
|
+
var ACTIVE_ORG_COOKIE = "politogy_active_org";
|
|
94
|
+
var ACTIVE_ORG_QUERY_PARAM = "org";
|
|
95
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
96
|
+
function isOrgId(v) {
|
|
97
|
+
return typeof v === "string" && UUID_RE.test(v.trim());
|
|
98
|
+
}
|
|
99
|
+
function readActiveOrgCookie() {
|
|
100
|
+
if (typeof document === "undefined") return null;
|
|
101
|
+
try {
|
|
102
|
+
const m = document.cookie.match(
|
|
103
|
+
new RegExp(`(?:^|;\\s*)${ACTIVE_ORG_COOKIE}=([^;]+)`)
|
|
104
|
+
);
|
|
105
|
+
const v = m ? decodeURIComponent(m[1]) : null;
|
|
106
|
+
return isOrgId(v) ? v : null;
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function writeActiveOrgCookie(orgId) {
|
|
112
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
113
|
+
if (!isOrgId(orgId)) return;
|
|
114
|
+
const host = window.location.hostname;
|
|
115
|
+
const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
|
|
116
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
117
|
+
document.cookie = `${ACTIVE_ORG_COOKIE}=${encodeURIComponent(
|
|
118
|
+
orgId
|
|
119
|
+
)}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
120
|
+
}
|
|
121
|
+
function readActiveOrgFromUrl(search) {
|
|
122
|
+
if (!search) return null;
|
|
123
|
+
try {
|
|
124
|
+
const qs = search.includes("?") ? search.slice(search.indexOf("?") + 1) : search;
|
|
125
|
+
const v = new URLSearchParams(qs).get(ACTIVE_ORG_QUERY_PARAM);
|
|
126
|
+
return isOrgId(v) ? v : null;
|
|
127
|
+
} catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function resolveActiveOrg(search) {
|
|
132
|
+
const fromUrl = readActiveOrgFromUrl(
|
|
133
|
+
(typeof window !== "undefined" ? window.location.search : null)
|
|
134
|
+
);
|
|
135
|
+
if (fromUrl) return fromUrl;
|
|
136
|
+
return readActiveOrgCookie();
|
|
137
|
+
}
|
|
138
|
+
var ORG_ID_QUERY_PARAM = "org_id";
|
|
139
|
+
var ORG_ID_TAIL_LENGTH = 7;
|
|
140
|
+
var LEGACY_ORG_TAIL_LENGTH = 6;
|
|
141
|
+
var TAIL_RE = /^[0-9a-f]{6,7}$/i;
|
|
142
|
+
var AUTH_BASE_URL = "https://auth.politogyvrm.com";
|
|
143
|
+
var AUTH_BASE_URL_STAGING = "https://auth-staging.politogyvrm.com";
|
|
144
|
+
function orgIdTail(orgId) {
|
|
145
|
+
return isOrgId(orgId) ? orgId.trim().toLowerCase().slice(-ORG_ID_TAIL_LENGTH) : null;
|
|
146
|
+
}
|
|
147
|
+
function isOrgSelector(v) {
|
|
148
|
+
return typeof v === "string" && (UUID_RE.test(v.trim()) || TAIL_RE.test(v.trim()));
|
|
149
|
+
}
|
|
150
|
+
function matchOrgSelector(selector, orgs) {
|
|
151
|
+
if (!isOrgSelector(selector)) return null;
|
|
152
|
+
const sel = selector.trim().toLowerCase();
|
|
153
|
+
if (UUID_RE.test(sel)) return orgs.find((o) => o.id.toLowerCase() === sel) ?? null;
|
|
154
|
+
if (sel.length !== ORG_ID_TAIL_LENGTH && sel.length !== LEGACY_ORG_TAIL_LENGTH) return null;
|
|
155
|
+
const hits = orgs.filter((o) => o.id.toLowerCase().endsWith(sel));
|
|
156
|
+
return hits.length === 1 ? hits[0] : null;
|
|
157
|
+
}
|
|
158
|
+
function readOrgSelectorFromUrl(search) {
|
|
159
|
+
if (!search) return null;
|
|
160
|
+
try {
|
|
161
|
+
const qs = search.includes("?") ? search.slice(search.indexOf("?") + 1) : search;
|
|
162
|
+
const params = new URLSearchParams(qs);
|
|
163
|
+
for (const key of [ORG_ID_QUERY_PARAM, ACTIVE_ORG_QUERY_PARAM]) {
|
|
164
|
+
const v = params.get(key);
|
|
165
|
+
if (isOrgSelector(v)) return v.trim().toLowerCase();
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
} catch {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function orgClaimsFrom(claims) {
|
|
173
|
+
if (!claims || typeof claims !== "object") return null;
|
|
174
|
+
const c = claims;
|
|
175
|
+
if (!isOrgId(c.org_id)) return null;
|
|
176
|
+
return {
|
|
177
|
+
orgId: c.org_id.trim().toLowerCase(),
|
|
178
|
+
orgRole: typeof c.org_role === "string" ? c.org_role : null
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function authBaseUrl() {
|
|
182
|
+
if (typeof window !== "undefined" && window.location.hostname.toLowerCase().includes("staging")) {
|
|
183
|
+
return AUTH_BASE_URL_STAGING;
|
|
184
|
+
}
|
|
185
|
+
return AUTH_BASE_URL;
|
|
186
|
+
}
|
|
187
|
+
var ActiveOrgSwitchError = class extends Error {
|
|
188
|
+
constructor(status, message) {
|
|
189
|
+
super(message);
|
|
190
|
+
this.status = status;
|
|
191
|
+
this.name = "ActiveOrgSwitchError";
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
async function switchActiveOrg(orgId, opts = {}) {
|
|
195
|
+
if (!isOrgId(orgId)) throw new ActiveOrgSwitchError(400, "org_id must be a full uuid");
|
|
196
|
+
const doFetch = opts.fetch ?? fetch;
|
|
197
|
+
const res = await doFetch(`${opts.authBaseUrl ?? authBaseUrl()}/api/active-org`, {
|
|
198
|
+
method: "POST",
|
|
199
|
+
credentials: "include",
|
|
200
|
+
headers: { "Content-Type": "application/json" },
|
|
201
|
+
body: JSON.stringify({ org_id: orgId })
|
|
202
|
+
});
|
|
203
|
+
if (!res.ok) {
|
|
204
|
+
let msg = `active-org switch failed (${res.status})`;
|
|
205
|
+
try {
|
|
206
|
+
const body = await res.json();
|
|
207
|
+
if (body?.error) msg = body.error;
|
|
208
|
+
} catch {
|
|
209
|
+
}
|
|
210
|
+
throw new ActiveOrgSwitchError(res.status, msg);
|
|
211
|
+
}
|
|
212
|
+
const claims = orgClaimsFrom(await res.json().catch(() => null));
|
|
213
|
+
if (!claims) throw new ActiveOrgSwitchError(502, "active-org switch returned no org_id");
|
|
214
|
+
writeActiveOrgCookie(claims.orgId);
|
|
215
|
+
return claims;
|
|
216
|
+
}
|
|
217
|
+
|
|
92
218
|
// src/nav-preference.ts
|
|
93
219
|
var NAV_DISPLAY_STORAGE_KEY = "politogy_nav_display";
|
|
94
220
|
var NAV_DISPLAY_COOKIE = "politogy_nav_display";
|
|
@@ -2456,6 +2582,11 @@ function useRailCollapse() {
|
|
|
2456
2582
|
const collapsible = react.useContext(RailCollapsibleContext);
|
|
2457
2583
|
return (cls) => collapsible ? cls : "";
|
|
2458
2584
|
}
|
|
2585
|
+
function orgPillLabel(org) {
|
|
2586
|
+
if (org.name) return org.name;
|
|
2587
|
+
if (org.id) return orgIdTail(org.id) ?? "Organization";
|
|
2588
|
+
return "No organizations";
|
|
2589
|
+
}
|
|
2459
2590
|
function OrgIconMark({ org, logoSrc }) {
|
|
2460
2591
|
const rc = useRailCollapse();
|
|
2461
2592
|
const src = resolveOrgLogoUrl(org.iconUrl) ?? logoSrc;
|
|
@@ -2697,7 +2828,7 @@ function NavSidebar({
|
|
|
2697
2828
|
{
|
|
2698
2829
|
title: org.name ?? void 0,
|
|
2699
2830
|
className: "truncate text-[12px] font-semibold leading-[1.2]",
|
|
2700
|
-
children: org
|
|
2831
|
+
children: orgPillLabel(org)
|
|
2701
2832
|
}
|
|
2702
2833
|
),
|
|
2703
2834
|
org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
|
|
@@ -2799,7 +2930,7 @@ function NavSidebar({
|
|
|
2799
2930
|
{
|
|
2800
2931
|
title: org.name ?? void 0,
|
|
2801
2932
|
className: "truncate text-[12px] font-semibold leading-[1.2]",
|
|
2802
|
-
children: org
|
|
2933
|
+
children: orgPillLabel(org)
|
|
2803
2934
|
}
|
|
2804
2935
|
),
|
|
2805
2936
|
org.id && !org.loading ? /* @__PURE__ */ jsxRuntime.jsx(OrgIdCopyButton, { id: org.id }) : null
|
|
@@ -3850,132 +3981,6 @@ function NavAppShell({
|
|
|
3850
3981
|
);
|
|
3851
3982
|
}
|
|
3852
3983
|
|
|
3853
|
-
// src/active-org.ts
|
|
3854
|
-
var ACTIVE_ORG_COOKIE = "politogy_active_org";
|
|
3855
|
-
var ACTIVE_ORG_QUERY_PARAM = "org";
|
|
3856
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3857
|
-
function isOrgId(v) {
|
|
3858
|
-
return typeof v === "string" && UUID_RE.test(v.trim());
|
|
3859
|
-
}
|
|
3860
|
-
function readActiveOrgCookie() {
|
|
3861
|
-
if (typeof document === "undefined") return null;
|
|
3862
|
-
try {
|
|
3863
|
-
const m = document.cookie.match(
|
|
3864
|
-
new RegExp(`(?:^|;\\s*)${ACTIVE_ORG_COOKIE}=([^;]+)`)
|
|
3865
|
-
);
|
|
3866
|
-
const v = m ? decodeURIComponent(m[1]) : null;
|
|
3867
|
-
return isOrgId(v) ? v : null;
|
|
3868
|
-
} catch {
|
|
3869
|
-
return null;
|
|
3870
|
-
}
|
|
3871
|
-
}
|
|
3872
|
-
function writeActiveOrgCookie(orgId) {
|
|
3873
|
-
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
3874
|
-
if (!isOrgId(orgId)) return;
|
|
3875
|
-
const host = window.location.hostname;
|
|
3876
|
-
const domainAttr = /(^|\.)politogyvrm\.com$/i.test(host) ? "; Domain=.politogyvrm.com" : "";
|
|
3877
|
-
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
3878
|
-
document.cookie = `${ACTIVE_ORG_COOKIE}=${encodeURIComponent(
|
|
3879
|
-
orgId
|
|
3880
|
-
)}; Path=/; Max-Age=31536000; SameSite=Lax${domainAttr}${secure}`;
|
|
3881
|
-
}
|
|
3882
|
-
function readActiveOrgFromUrl(search) {
|
|
3883
|
-
if (!search) return null;
|
|
3884
|
-
try {
|
|
3885
|
-
const qs = search.includes("?") ? search.slice(search.indexOf("?") + 1) : search;
|
|
3886
|
-
const v = new URLSearchParams(qs).get(ACTIVE_ORG_QUERY_PARAM);
|
|
3887
|
-
return isOrgId(v) ? v : null;
|
|
3888
|
-
} catch {
|
|
3889
|
-
return null;
|
|
3890
|
-
}
|
|
3891
|
-
}
|
|
3892
|
-
function resolveActiveOrg(search) {
|
|
3893
|
-
const fromUrl = readActiveOrgFromUrl(
|
|
3894
|
-
(typeof window !== "undefined" ? window.location.search : null)
|
|
3895
|
-
);
|
|
3896
|
-
if (fromUrl) return fromUrl;
|
|
3897
|
-
return readActiveOrgCookie();
|
|
3898
|
-
}
|
|
3899
|
-
var ORG_ID_QUERY_PARAM = "org_id";
|
|
3900
|
-
var ORG_ID_TAIL_LENGTH = 7;
|
|
3901
|
-
var LEGACY_ORG_TAIL_LENGTH = 6;
|
|
3902
|
-
var TAIL_RE = /^[0-9a-f]{6,7}$/i;
|
|
3903
|
-
var AUTH_BASE_URL = "https://auth.politogyvrm.com";
|
|
3904
|
-
var AUTH_BASE_URL_STAGING = "https://auth-staging.politogyvrm.com";
|
|
3905
|
-
function orgIdTail(orgId) {
|
|
3906
|
-
return isOrgId(orgId) ? orgId.trim().toLowerCase().slice(-ORG_ID_TAIL_LENGTH) : null;
|
|
3907
|
-
}
|
|
3908
|
-
function isOrgSelector(v) {
|
|
3909
|
-
return typeof v === "string" && (UUID_RE.test(v.trim()) || TAIL_RE.test(v.trim()));
|
|
3910
|
-
}
|
|
3911
|
-
function matchOrgSelector(selector, orgs) {
|
|
3912
|
-
if (!isOrgSelector(selector)) return null;
|
|
3913
|
-
const sel = selector.trim().toLowerCase();
|
|
3914
|
-
if (UUID_RE.test(sel)) return orgs.find((o) => o.id.toLowerCase() === sel) ?? null;
|
|
3915
|
-
if (sel.length !== ORG_ID_TAIL_LENGTH && sel.length !== LEGACY_ORG_TAIL_LENGTH) return null;
|
|
3916
|
-
const hits = orgs.filter((o) => o.id.toLowerCase().endsWith(sel));
|
|
3917
|
-
return hits.length === 1 ? hits[0] : null;
|
|
3918
|
-
}
|
|
3919
|
-
function readOrgSelectorFromUrl(search) {
|
|
3920
|
-
if (!search) return null;
|
|
3921
|
-
try {
|
|
3922
|
-
const qs = search.includes("?") ? search.slice(search.indexOf("?") + 1) : search;
|
|
3923
|
-
const params = new URLSearchParams(qs);
|
|
3924
|
-
for (const key of [ORG_ID_QUERY_PARAM, ACTIVE_ORG_QUERY_PARAM]) {
|
|
3925
|
-
const v = params.get(key);
|
|
3926
|
-
if (isOrgSelector(v)) return v.trim().toLowerCase();
|
|
3927
|
-
}
|
|
3928
|
-
return null;
|
|
3929
|
-
} catch {
|
|
3930
|
-
return null;
|
|
3931
|
-
}
|
|
3932
|
-
}
|
|
3933
|
-
function orgClaimsFrom(claims) {
|
|
3934
|
-
if (!claims || typeof claims !== "object") return null;
|
|
3935
|
-
const c = claims;
|
|
3936
|
-
if (!isOrgId(c.org_id)) return null;
|
|
3937
|
-
return {
|
|
3938
|
-
orgId: c.org_id.trim().toLowerCase(),
|
|
3939
|
-
orgRole: typeof c.org_role === "string" ? c.org_role : null
|
|
3940
|
-
};
|
|
3941
|
-
}
|
|
3942
|
-
function authBaseUrl() {
|
|
3943
|
-
if (typeof window !== "undefined" && window.location.hostname.toLowerCase().includes("staging")) {
|
|
3944
|
-
return AUTH_BASE_URL_STAGING;
|
|
3945
|
-
}
|
|
3946
|
-
return AUTH_BASE_URL;
|
|
3947
|
-
}
|
|
3948
|
-
var ActiveOrgSwitchError = class extends Error {
|
|
3949
|
-
constructor(status, message) {
|
|
3950
|
-
super(message);
|
|
3951
|
-
this.status = status;
|
|
3952
|
-
this.name = "ActiveOrgSwitchError";
|
|
3953
|
-
}
|
|
3954
|
-
};
|
|
3955
|
-
async function switchActiveOrg(orgId, opts = {}) {
|
|
3956
|
-
if (!isOrgId(orgId)) throw new ActiveOrgSwitchError(400, "org_id must be a full uuid");
|
|
3957
|
-
const doFetch = opts.fetch ?? fetch;
|
|
3958
|
-
const res = await doFetch(`${opts.authBaseUrl ?? authBaseUrl()}/api/active-org`, {
|
|
3959
|
-
method: "POST",
|
|
3960
|
-
credentials: "include",
|
|
3961
|
-
headers: { "Content-Type": "application/json" },
|
|
3962
|
-
body: JSON.stringify({ org_id: orgId })
|
|
3963
|
-
});
|
|
3964
|
-
if (!res.ok) {
|
|
3965
|
-
let msg = `active-org switch failed (${res.status})`;
|
|
3966
|
-
try {
|
|
3967
|
-
const body = await res.json();
|
|
3968
|
-
if (body?.error) msg = body.error;
|
|
3969
|
-
} catch {
|
|
3970
|
-
}
|
|
3971
|
-
throw new ActiveOrgSwitchError(res.status, msg);
|
|
3972
|
-
}
|
|
3973
|
-
const claims = orgClaimsFrom(await res.json().catch(() => null));
|
|
3974
|
-
if (!claims) throw new ActiveOrgSwitchError(502, "active-org switch returned no org_id");
|
|
3975
|
-
writeActiveOrgCookie(claims.orgId);
|
|
3976
|
-
return claims;
|
|
3977
|
-
}
|
|
3978
|
-
|
|
3979
3984
|
// src/lib/breadcrumbs.ts
|
|
3980
3985
|
function deriveBreadcrumbs(items, pathname, opts) {
|
|
3981
3986
|
const search = opts?.search ?? (typeof window !== "undefined" ? window.location.search : "");
|
|
@@ -4959,9 +4964,15 @@ function TokenChromeStateProvider({
|
|
|
4959
4964
|
})),
|
|
4960
4965
|
[tokenOrg.orgs, fetchedOrgs]
|
|
4961
4966
|
);
|
|
4962
|
-
const [urlSelector] = react.useState(
|
|
4967
|
+
const [urlSelector, setUrlSelector] = react.useState(
|
|
4963
4968
|
() => typeof window === "undefined" ? null : readOrgSelectorFromUrl(window.location.search)
|
|
4964
4969
|
);
|
|
4970
|
+
react.useEffect(() => {
|
|
4971
|
+
if (typeof window === "undefined") return;
|
|
4972
|
+
const onLocationChange = () => setUrlSelector(readOrgSelectorFromUrl(window.location.search));
|
|
4973
|
+
window.addEventListener("popstate", onLocationChange);
|
|
4974
|
+
return () => window.removeEventListener("popstate", onLocationChange);
|
|
4975
|
+
}, []);
|
|
4965
4976
|
const overrideOrg = react.useMemo(
|
|
4966
4977
|
() => urlSelector ? matchOrgSelector(urlSelector, orgs)?.id ?? null : null,
|
|
4967
4978
|
[urlSelector, orgs]
|
|
@@ -4987,6 +4998,7 @@ function TokenChromeStateProvider({
|
|
|
4987
4998
|
void (async () => {
|
|
4988
4999
|
try {
|
|
4989
5000
|
const claims = await switchActiveOrg(id, { authBaseUrl: current.authBaseUrl });
|
|
5001
|
+
setUrlSelector(null);
|
|
4990
5002
|
try {
|
|
4991
5003
|
const url = new URL(window.location.href);
|
|
4992
5004
|
url.searchParams.delete(ACTIVE_ORG_QUERY_PARAM);
|