@the-portland-company/shell 0.52.0 → 0.53.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 +19 -0
- package/dist/app-chrome.cjs +278 -62
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +55 -2
- package/dist/app-chrome.d.ts +55 -2
- package/dist/app-chrome.js +280 -65
- package/dist/app-chrome.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## 0.53.0 — 2026-09-29
|
|
2
|
+
|
|
3
|
+
### Added — Loading Screen boot surface (Specs/Loading-Screen)
|
|
4
|
+
|
|
5
|
+
`PolitogyAppFrame` now renders the platform's boot screen: a full-screen
|
|
6
|
+
`ink-900` surface with the Politogy VRM lockup, a determinate/monotonic
|
|
7
|
+
gradient progress bar (Race Blue → Race Red), and a throttled monospace
|
|
8
|
+
status line, shown on cold start / hard reload / organization switch / mode
|
|
9
|
+
switch — the four events Global-Rules' Boot Screen Exception names — and
|
|
10
|
+
never for an in-page fetch or navigation. New export
|
|
11
|
+
`LoadingScreen`/`BootProgress` from `@the-portland-company/shell/app-chrome`
|
|
12
|
+
lets an app report real pipeline stages; a new `PolitogyAppFrame` prop
|
|
13
|
+
`appReady` lets an app dismiss the screen explicitly. Neither is required:
|
|
14
|
+
an app that passes nothing gets a truthful two-stage report driven by the
|
|
15
|
+
same org/nav resolution signal the frame already computes, so all 14
|
|
16
|
+
consumer apps keep working unchanged. `prefers-reduced-motion` skips the
|
|
17
|
+
exit transition; the bar is `role="progressbar"` with `aria-live` announced
|
|
18
|
+
copy throttled to one per 1.5s (final "Ready." always announced).
|
|
19
|
+
|
|
1
20
|
## 0.52.0 — 2026-09-12
|
|
2
21
|
|
|
3
22
|
### Added — mobile navigation (GLOBAL)
|
package/dist/app-chrome.cjs
CHANGED
|
@@ -3256,6 +3256,182 @@ function watchLogout(onLogout, options = {}) {
|
|
|
3256
3256
|
}
|
|
3257
3257
|
return cleanup;
|
|
3258
3258
|
}
|
|
3259
|
+
var SYNTHETIC_STAGES = [
|
|
3260
|
+
{ pct: 20, label: "Connecting to your organization\u2026" },
|
|
3261
|
+
{ pct: 100, label: "Ready." }
|
|
3262
|
+
];
|
|
3263
|
+
var ANNOUNCE_THROTTLE_MS = 1500;
|
|
3264
|
+
var MIN_DWELL_MS = 450;
|
|
3265
|
+
var FILL_EASE_MS = 380;
|
|
3266
|
+
var HOLD_MS = 240;
|
|
3267
|
+
var FADE_MS = 300;
|
|
3268
|
+
function usePrefersReducedMotion() {
|
|
3269
|
+
const [reduced, setReduced] = react.useState(false);
|
|
3270
|
+
react.useEffect(() => {
|
|
3271
|
+
if (typeof window === "undefined" || !window.matchMedia) return;
|
|
3272
|
+
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
3273
|
+
setReduced(mq.matches);
|
|
3274
|
+
const onChange = () => setReduced(mq.matches);
|
|
3275
|
+
mq.addEventListener("change", onChange);
|
|
3276
|
+
return () => mq.removeEventListener("change", onChange);
|
|
3277
|
+
}, []);
|
|
3278
|
+
return reduced;
|
|
3279
|
+
}
|
|
3280
|
+
function useThrottledAnnouncement(label, isFinal) {
|
|
3281
|
+
const [announced, setAnnounced] = react.useState(label);
|
|
3282
|
+
const lastAtRef = react.useRef(0);
|
|
3283
|
+
react.useEffect(() => {
|
|
3284
|
+
const now = Date.now();
|
|
3285
|
+
if (isFinal || now - lastAtRef.current >= ANNOUNCE_THROTTLE_MS) {
|
|
3286
|
+
lastAtRef.current = now;
|
|
3287
|
+
setAnnounced(label);
|
|
3288
|
+
return;
|
|
3289
|
+
}
|
|
3290
|
+
const wait = ANNOUNCE_THROTTLE_MS - (now - lastAtRef.current);
|
|
3291
|
+
const t = setTimeout(() => {
|
|
3292
|
+
lastAtRef.current = Date.now();
|
|
3293
|
+
setAnnounced(label);
|
|
3294
|
+
}, wait);
|
|
3295
|
+
return () => clearTimeout(t);
|
|
3296
|
+
}, [label, isFinal]);
|
|
3297
|
+
return announced;
|
|
3298
|
+
}
|
|
3299
|
+
function useDwelledLabel(label) {
|
|
3300
|
+
const [displayed, setDisplayed] = react.useState(label);
|
|
3301
|
+
const shownAtRef = react.useRef(0);
|
|
3302
|
+
const pendingRef = react.useRef(null);
|
|
3303
|
+
react.useEffect(() => {
|
|
3304
|
+
if (label === displayed) return;
|
|
3305
|
+
const elapsed = Date.now() - shownAtRef.current;
|
|
3306
|
+
if (pendingRef.current) clearTimeout(pendingRef.current);
|
|
3307
|
+
if (elapsed >= MIN_DWELL_MS) {
|
|
3308
|
+
shownAtRef.current = Date.now();
|
|
3309
|
+
setDisplayed(label);
|
|
3310
|
+
} else {
|
|
3311
|
+
pendingRef.current = setTimeout(() => {
|
|
3312
|
+
shownAtRef.current = Date.now();
|
|
3313
|
+
setDisplayed(label);
|
|
3314
|
+
}, MIN_DWELL_MS - elapsed);
|
|
3315
|
+
}
|
|
3316
|
+
return () => {
|
|
3317
|
+
if (pendingRef.current) clearTimeout(pendingRef.current);
|
|
3318
|
+
};
|
|
3319
|
+
}, [label]);
|
|
3320
|
+
return displayed;
|
|
3321
|
+
}
|
|
3322
|
+
function LoadingScreen({
|
|
3323
|
+
bootProgress,
|
|
3324
|
+
syntheticReady,
|
|
3325
|
+
visible,
|
|
3326
|
+
onExitComplete
|
|
3327
|
+
}) {
|
|
3328
|
+
const reducedMotion = usePrefersReducedMotion();
|
|
3329
|
+
const synthetic = react.useMemo(() => {
|
|
3330
|
+
const stage = syntheticReady ? SYNTHETIC_STAGES[1] : SYNTHETIC_STAGES[0];
|
|
3331
|
+
return {
|
|
3332
|
+
pct: stage.pct,
|
|
3333
|
+
label: stage.label,
|
|
3334
|
+
phase: syntheticReady ? "done" : "booting"
|
|
3335
|
+
};
|
|
3336
|
+
}, [syntheticReady]);
|
|
3337
|
+
const pct = bootProgress?.pct ?? synthetic.pct;
|
|
3338
|
+
const rawLabel = bootProgress?.label ?? synthetic.label;
|
|
3339
|
+
const phase = bootProgress?.phase ?? synthetic.phase;
|
|
3340
|
+
const isFinal = phase === "done" && pct >= 100;
|
|
3341
|
+
const highWaterRef = react.useRef(0);
|
|
3342
|
+
const clampedPct = Math.max(pct, highWaterRef.current);
|
|
3343
|
+
react.useEffect(() => {
|
|
3344
|
+
highWaterRef.current = clampedPct;
|
|
3345
|
+
}, [clampedPct]);
|
|
3346
|
+
const displayedLabel = useDwelledLabel(rawLabel);
|
|
3347
|
+
const announced = useThrottledAnnouncement(displayedLabel, isFinal);
|
|
3348
|
+
const [fading, setFading] = react.useState(false);
|
|
3349
|
+
react.useEffect(() => {
|
|
3350
|
+
if (!isFinal) return;
|
|
3351
|
+
const holdMs = reducedMotion ? 0 : HOLD_MS;
|
|
3352
|
+
const fadeMs = reducedMotion ? 0 : FADE_MS;
|
|
3353
|
+
const holdTimer = setTimeout(() => {
|
|
3354
|
+
setFading(true);
|
|
3355
|
+
const fadeTimer = setTimeout(onExitComplete, fadeMs);
|
|
3356
|
+
return () => clearTimeout(fadeTimer);
|
|
3357
|
+
}, holdMs);
|
|
3358
|
+
return () => clearTimeout(holdTimer);
|
|
3359
|
+
}, [isFinal, reducedMotion]);
|
|
3360
|
+
if (!visible) return null;
|
|
3361
|
+
const isError = phase === "error";
|
|
3362
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3363
|
+
"div",
|
|
3364
|
+
{
|
|
3365
|
+
"data-testid": "politogy-loading-screen",
|
|
3366
|
+
style: {
|
|
3367
|
+
position: "fixed",
|
|
3368
|
+
inset: 0,
|
|
3369
|
+
zIndex: 2147483e3,
|
|
3370
|
+
display: "flex",
|
|
3371
|
+
flexDirection: "column",
|
|
3372
|
+
alignItems: "center",
|
|
3373
|
+
justifyContent: "center",
|
|
3374
|
+
gap: "2rem",
|
|
3375
|
+
background: "var(--color-ink-900, #0a0a0c)",
|
|
3376
|
+
color: "#fff",
|
|
3377
|
+
opacity: fading ? 0 : 1,
|
|
3378
|
+
transition: reducedMotion ? void 0 : `opacity ${FADE_MS}ms ease-out`
|
|
3379
|
+
},
|
|
3380
|
+
children: [
|
|
3381
|
+
/* @__PURE__ */ jsxRuntime.jsx("img", { src: "/politogy-lockup-white.svg", alt: "Politogy VRM", style: { width: 220, height: "auto" } }),
|
|
3382
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width: 320, maxWidth: "80vw" }, children: [
|
|
3383
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3384
|
+
"div",
|
|
3385
|
+
{
|
|
3386
|
+
role: "progressbar",
|
|
3387
|
+
"aria-valuemin": 0,
|
|
3388
|
+
"aria-valuemax": 100,
|
|
3389
|
+
"aria-valuenow": Math.round(clampedPct),
|
|
3390
|
+
"aria-label": "Loading your workspace",
|
|
3391
|
+
style: {
|
|
3392
|
+
height: 3,
|
|
3393
|
+
width: "100%",
|
|
3394
|
+
borderRadius: 2,
|
|
3395
|
+
background: "rgba(255,255,255,0.12)",
|
|
3396
|
+
overflow: "hidden"
|
|
3397
|
+
},
|
|
3398
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3399
|
+
"div",
|
|
3400
|
+
{
|
|
3401
|
+
style: {
|
|
3402
|
+
height: "100%",
|
|
3403
|
+
width: `${clampedPct}%`,
|
|
3404
|
+
background: "linear-gradient(90deg, var(--color-race-blue, #1d4ed8), var(--color-race-red, #dc2626))",
|
|
3405
|
+
transition: reducedMotion ? void 0 : `width ${FILL_EASE_MS}ms ease-out`
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
)
|
|
3409
|
+
}
|
|
3410
|
+
),
|
|
3411
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3412
|
+
"div",
|
|
3413
|
+
{
|
|
3414
|
+
role: "status",
|
|
3415
|
+
"aria-live": "polite",
|
|
3416
|
+
style: {
|
|
3417
|
+
marginTop: "0.75rem",
|
|
3418
|
+
fontFamily: "var(--font-mono, ui-monospace, monospace)",
|
|
3419
|
+
fontSize: "0.8125rem",
|
|
3420
|
+
color: isError ? "var(--color-race-red, #dc2626)" : "rgba(255,255,255,0.72)",
|
|
3421
|
+
textAlign: "center"
|
|
3422
|
+
},
|
|
3423
|
+
children: announced
|
|
3424
|
+
}
|
|
3425
|
+
),
|
|
3426
|
+
isError && (bootProgress?.onRetry || bootProgress?.onSignOut) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: "1rem", display: "flex", gap: "0.75rem", justifyContent: "center" }, children: [
|
|
3427
|
+
bootProgress?.onRetry && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: bootProgress.onRetry, children: "Retry" }),
|
|
3428
|
+
bootProgress?.onSignOut && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: bootProgress.onSignOut, children: "Sign out" })
|
|
3429
|
+
] })
|
|
3430
|
+
] })
|
|
3431
|
+
]
|
|
3432
|
+
}
|
|
3433
|
+
);
|
|
3434
|
+
}
|
|
3259
3435
|
var CORE_APP = "vrm";
|
|
3260
3436
|
var DEFAULT_SIGN_OUT_URL = "/auth/signout";
|
|
3261
3437
|
var DEFAULT_BRAND_LOGO = "/brand/logos/relationship-mode-logo.png";
|
|
@@ -3306,6 +3482,8 @@ function PolitogyAppFrame({
|
|
|
3306
3482
|
signOutUrl = DEFAULT_SIGN_OUT_URL,
|
|
3307
3483
|
buildMeta,
|
|
3308
3484
|
data,
|
|
3485
|
+
bootProgress,
|
|
3486
|
+
appReady,
|
|
3309
3487
|
children
|
|
3310
3488
|
}) {
|
|
3311
3489
|
const meta = POLITOGY_APPS[app];
|
|
@@ -3334,6 +3512,8 @@ function PolitogyAppFrame({
|
|
|
3334
3512
|
signOutUrl,
|
|
3335
3513
|
buildMeta,
|
|
3336
3514
|
data,
|
|
3515
|
+
bootProgress,
|
|
3516
|
+
appReady,
|
|
3337
3517
|
children
|
|
3338
3518
|
}
|
|
3339
3519
|
)
|
|
@@ -3350,10 +3530,33 @@ function FrameBody({
|
|
|
3350
3530
|
signOutUrl,
|
|
3351
3531
|
buildMeta,
|
|
3352
3532
|
data,
|
|
3533
|
+
bootProgress,
|
|
3534
|
+
appReady,
|
|
3353
3535
|
children
|
|
3354
3536
|
}) {
|
|
3355
3537
|
const meta = POLITOGY_APPS[app];
|
|
3356
3538
|
const chrome = useChromeState();
|
|
3539
|
+
const bootAppMode = meta.mode;
|
|
3540
|
+
const bootOrgId = chrome?.orgId ?? null;
|
|
3541
|
+
const [bootVisible, setBootVisible] = react.useState(true);
|
|
3542
|
+
const [bootGeneration, setBootGeneration] = react.useState(0);
|
|
3543
|
+
const seenOrgRef = react.useRef(bootOrgId);
|
|
3544
|
+
const seenModeRef = react.useRef(bootAppMode);
|
|
3545
|
+
react.useEffect(() => {
|
|
3546
|
+
if (seenOrgRef.current !== null && seenOrgRef.current !== bootOrgId) {
|
|
3547
|
+
setBootVisible(true);
|
|
3548
|
+
setBootGeneration((g) => g + 1);
|
|
3549
|
+
}
|
|
3550
|
+
seenOrgRef.current = bootOrgId;
|
|
3551
|
+
}, [bootOrgId]);
|
|
3552
|
+
react.useEffect(() => {
|
|
3553
|
+
if (seenModeRef.current !== void 0 && seenModeRef.current !== bootAppMode) {
|
|
3554
|
+
setBootVisible(true);
|
|
3555
|
+
setBootGeneration((g) => g + 1);
|
|
3556
|
+
}
|
|
3557
|
+
seenModeRef.current = bootAppMode;
|
|
3558
|
+
}, [bootAppMode]);
|
|
3559
|
+
const chromeResolved = chrome == null || !chrome.orgsLoading;
|
|
3357
3560
|
const signOutRef = react.useRef(onSignOut);
|
|
3358
3561
|
signOutRef.current = onSignOut;
|
|
3359
3562
|
const signingOutRef = react.useRef(false);
|
|
@@ -3428,70 +3631,82 @@ function FrameBody({
|
|
|
3428
3631
|
[navItems, pathname, search, meta.origin]
|
|
3429
3632
|
);
|
|
3430
3633
|
const breadcrumbs = core ? core.page?.breadcrumbs : grants?.includes("breadcrumbs") ? granted("breadcrumbs") : derivedBreadcrumbs;
|
|
3431
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
badgeLabel: "P",
|
|
3440
|
-
title: "Politogy"
|
|
3441
|
-
},
|
|
3442
|
-
nav: {
|
|
3443
|
-
// A flat rail's sub-menu IS the nav, so the 'tabs only' preference
|
|
3444
|
-
// (which strips children) would leave one childless parent row —
|
|
3445
|
-
// flat apps ignore the stripping.
|
|
3446
|
-
items: navDisplay === "tabs" && meta.navShape !== "flat" ? navItems.map(({ children: _sub, ...item }) => item) : navItems,
|
|
3447
|
-
flatten: meta.navShape === "flat"
|
|
3448
|
-
},
|
|
3449
|
-
// The app's own workspace is NOT the organization — it is a per-app
|
|
3450
|
-
// bootstrap account with a different id in every app. Showing it while
|
|
3451
|
-
// the chrome API resolves flashed the wrong org on every load ("not
|
|
3452
|
-
// connected to the account"). Shimmer while in flight; only fall back
|
|
3453
|
-
// to the app label once the chrome lookup has actually failed.
|
|
3454
|
-
org: activeCoreOrg ? {
|
|
3455
|
-
name: activeCoreOrg.name,
|
|
3456
|
-
id: activeCoreOrg.id,
|
|
3457
|
-
logoUrl: activeCoreOrg.logoUrl,
|
|
3458
|
-
brandColor: activeCoreOrg.brandColor,
|
|
3459
|
-
organizations: coreOrgs,
|
|
3460
|
-
onSwitch: chrome?.setOrgId
|
|
3461
|
-
} : chrome?.orgsLoading ? { name: null, id: null, loading: true } : { name: session.accountName, id: session.accountId },
|
|
3462
|
-
mode,
|
|
3463
|
-
footer,
|
|
3464
|
-
linkComponent
|
|
3634
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3636
|
+
LoadingScreen,
|
|
3637
|
+
{
|
|
3638
|
+
visible: bootVisible,
|
|
3639
|
+
bootProgress,
|
|
3640
|
+
syntheticReady: appReady ?? chromeResolved,
|
|
3641
|
+
onExitComplete: () => setBootVisible(false)
|
|
3465
3642
|
},
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3643
|
+
bootGeneration
|
|
3644
|
+
),
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3646
|
+
NavAppShell,
|
|
3647
|
+
{
|
|
3648
|
+
sidebar: {
|
|
3649
|
+
pathname,
|
|
3650
|
+
brand: {
|
|
3651
|
+
logoSrc: core?.brandLogoSrc ?? modeBrandLogo(appMode),
|
|
3652
|
+
logoAlt: "Politogy",
|
|
3653
|
+
badgeLabel: "P",
|
|
3654
|
+
title: "Politogy"
|
|
3655
|
+
},
|
|
3656
|
+
nav: {
|
|
3657
|
+
// A flat rail's sub-menu IS the nav, so the 'tabs only' preference
|
|
3658
|
+
// (which strips children) would leave one childless parent row —
|
|
3659
|
+
// flat apps ignore the stripping.
|
|
3660
|
+
items: navDisplay === "tabs" && meta.navShape !== "flat" ? navItems.map(({ children: _sub, ...item }) => item) : navItems,
|
|
3661
|
+
flatten: meta.navShape === "flat"
|
|
3662
|
+
},
|
|
3663
|
+
// The app's own workspace is NOT the organization — it is a per-app
|
|
3664
|
+
// bootstrap account with a different id in every app. Showing it while
|
|
3665
|
+
// the chrome API resolves flashed the wrong org on every load ("not
|
|
3666
|
+
// connected to the account"). Shimmer while in flight; only fall back
|
|
3667
|
+
// to the app label once the chrome lookup has actually failed.
|
|
3668
|
+
org: activeCoreOrg ? {
|
|
3669
|
+
name: activeCoreOrg.name,
|
|
3670
|
+
id: activeCoreOrg.id,
|
|
3671
|
+
logoUrl: activeCoreOrg.logoUrl,
|
|
3672
|
+
brandColor: activeCoreOrg.brandColor,
|
|
3673
|
+
organizations: coreOrgs,
|
|
3674
|
+
onSwitch: chrome?.setOrgId
|
|
3675
|
+
} : chrome?.orgsLoading ? { name: null, id: null, loading: true } : { name: session.accountName, id: session.accountId },
|
|
3676
|
+
mode,
|
|
3677
|
+
footer,
|
|
3678
|
+
linkComponent
|
|
3481
3679
|
},
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
core?.page?.
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3680
|
+
betaBanner: meta.beta === false ? void 0 : {},
|
|
3681
|
+
modeId: appMode,
|
|
3682
|
+
contentWrapper: core?.contentWrapper ?? granted("contentWrapper"),
|
|
3683
|
+
topBar: {
|
|
3684
|
+
// Core's pages publish their own identity; every other app is one
|
|
3685
|
+
// product surface and takes its registry title.
|
|
3686
|
+
title: core?.page?.title ?? (grants?.includes("title") ? data?.frame?.title : void 0) ?? meta.title,
|
|
3687
|
+
breadcrumbs,
|
|
3688
|
+
user: {
|
|
3689
|
+
name: identity.userName,
|
|
3690
|
+
email: identity.email,
|
|
3691
|
+
// The chrome API's avatar wins; the app may supply a fallback chain
|
|
3692
|
+
// (e.g. a stored memoji) for users with no uploaded photo.
|
|
3693
|
+
avatarUrl: identity.avatarUrl ?? data?.fallbackAvatarUrl ?? null,
|
|
3694
|
+
role: session.role
|
|
3695
|
+
},
|
|
3696
|
+
userMenu,
|
|
3697
|
+
onSignOut: handleSignOut,
|
|
3698
|
+
// The action cluster is IDENTICAL everywhere — core included. Page
|
|
3699
|
+
// actions sit BEFORE it, never inside it, so the Alerts bell keeps its
|
|
3700
|
+
// required position: farthest right, immediately before My Account.
|
|
3701
|
+
actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3702
|
+
core?.page?.actions,
|
|
3703
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChromeTopBarActions, {})
|
|
3704
|
+
] })
|
|
3705
|
+
},
|
|
3706
|
+
children
|
|
3707
|
+
}
|
|
3708
|
+
)
|
|
3709
|
+
] });
|
|
3495
3710
|
}
|
|
3496
3711
|
var standardNavIcons = {
|
|
3497
3712
|
home: fi.FiHome,
|
|
@@ -3969,6 +4184,7 @@ function useChromeMode(arg = {}) {
|
|
|
3969
4184
|
}
|
|
3970
4185
|
|
|
3971
4186
|
exports.ChromeTopBarActions = ChromeTopBarActions;
|
|
4187
|
+
exports.LoadingScreen = LoadingScreen;
|
|
3972
4188
|
exports.POLITOGY_APPS = POLITOGY_APPS;
|
|
3973
4189
|
exports.PolitogyAppChrome = PolitogyAppChrome;
|
|
3974
4190
|
exports.PolitogyAppFrame = PolitogyAppFrame;
|