@proappstore/sdk 1.16.56 → 1.16.58

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/README.md CHANGED
@@ -571,17 +571,23 @@ Pass `{ allowFree: true }` to skip the subscription check (lets free users throu
571
571
 
572
572
  ## ProShell Component
573
573
 
574
- A React component that handles auth gates, subscription checks, provider context, and optional platform chrome with topbar, user menu, text size control, and footer.
574
+ The app frame. It handles the auth gates, subscription checks, provider context, the topbar (app name, text size control, user menu), the footer, and the **main navigation**.
575
575
 
576
576
  ```tsx
577
- import { initPro } from '@proappstore/sdk'
578
- import { ProShell } from '@proappstore/sdk/shell'
577
+ import { initPro, ProShell } from '@proappstore/sdk'
579
578
 
580
579
  const app = initPro({ appId: 'meetup' })
581
580
 
582
581
  export default function App() {
583
582
  return (
584
- <ProShell app={app} appName="Meetup">
583
+ <ProShell
584
+ app={app}
585
+ appName="Meetup"
586
+ nav={[
587
+ { label: 'Events', href: '/' },
588
+ { label: 'Groups', href: '/groups' },
589
+ ]}
590
+ >
585
591
  <MeetupApp />
586
592
  </ProShell>
587
593
  )
@@ -595,32 +601,50 @@ Props:
595
601
  | `app` | `ProAppStore` | SDK instance from `initPro()` |
596
602
  | `children` | `ReactNode` | App content (rendered only when gates pass) |
597
603
  | `appName` | `string?` | Name shown in the topbar |
604
+ | `nav` | `{ label: string; href: string; icon?: ReactNode; title?: string }[]` | **The app's screens**, rendered as the main navigation in the topbar |
605
+ | `onNavigate` | `(href: string) => void` | Client-side navigation for nav clicks (e.g. a router's `navigate`); without it items are links |
606
+ | `renderNav` | `(ctx) => ReactNode` | Replace the built-in NavBar (`ctx`: `items`, `currentPath`, `onNavigate`) |
598
607
  | `allowFree` | `boolean?` | Skip subscription gate (default: `true` until platform billing is live) |
599
608
  | `showThemeToggle` | `boolean?` | Show theme toggle in the profile menu |
600
609
  | `menuItems` | `{ label: string; onClick: () => void }[]` | Extra profile dropdown items |
601
- | `hideTopbar` | `boolean?` | Omit the default topbar |
610
+ | `hideTopbar` | `boolean?` | Omit the default topbar (and the navigation) |
602
611
  | `hideFooter` | `boolean?` | Omit the default footer |
603
- | `renderTopbar` | `(ctx) => ReactNode` | Replace the default topbar |
612
+ | `renderTopbar` | `(ctx) => ReactNode` | Replace the default topbar; place `ctx.nav` in it |
604
613
  | `renderFooter` | `(ctx) => ReactNode` | Replace the default footer |
614
+ | `renderError` | `({ error, reset }) => ReactNode` | Replace the error-boundary fallback (errors are recorded via `app.logs`) |
615
+ | `renderLoading` | `() => ReactNode` | Replace the spinner shown while a lazy screen loads |
605
616
 
606
617
  ProShell handles:
607
- - Auth initialization and sign-in gate
608
- - Subscription check and upgrade wall (unless `allowFree=true`)
609
- - Topbar with avatar, app name, text size toggle, and user menu (sign out, manage billing, delete account)
610
-
611
- Apps with their own primary navigation should not stack a second navbar under the default shell. Replace the topbar while keeping ProShell gates:
618
+ - Auth initialization and the sign-in gate
619
+ - The subscription check and upgrade wall (unless `allowFree=true`)
620
+ - The topbar with app name, text size toggle and user menu (sign out, manage billing, delete account)
621
+ - The main navigation from `nav`:
622
+ - a `<nav aria-label="Main">` landmark;
623
+ - `aria-current="page"` on the current route, following `location.pathname` and back/forward;
624
+ - a menu button below 640 px (`aria-expanded`, Escape to close);
625
+ - 44 px targets and visible focus.
626
+
627
+ Its styles are injected when the navbar renders, so no setup is needed. They are also available as `@proappstore/sdk/shell.css`.
628
+ - Resilience and feedback:
629
+ - an error boundary (with a Try again fallback, errors recorded via `app.logs`) and a Suspense spinner around the content;
630
+ - `useToast()` for messages in one polite live region;
631
+ - an offline banner, plus `useOnline()`;
632
+ - tab titles from a nav item's `title` or `useDocumentTitle`;
633
+ - `PageHeader` for each screen's one `h1`;
634
+ - a skip link to `<main id="main">`;
635
+ - with `onNavigate`, scroll to top or restore on back/forward, and focus moved to the new screen's heading.
636
+
637
+ Do not build navigation into a page, and do not stack a second navbar under the shell. A custom topbar keeps the gates and places the rendered `nav`:
612
638
 
613
639
  ```tsx
614
640
  <ProShell
615
641
  app={app}
616
642
  appName="Chess Academy"
617
- renderTopbar={({ appName, profileMenu, textSizeToggle }) => (
643
+ nav={[{ label: 'Students', href: '/students' }, { label: 'Tournaments', href: '/tournaments' }]}
644
+ renderTopbar={({ appName, nav, profileMenu, textSizeToggle }) => (
618
645
  <header className="top-nav">
619
646
  <a href="/">{appName}</a>
620
- <nav>
621
- <a href="/students">Students</a>
622
- <a href="/tournaments">Tournaments</a>
623
- </nav>
647
+ {nav}
624
648
  {textSizeToggle}
625
649
  {profileMenu}
626
650
  </header>
@@ -630,7 +654,7 @@ Apps with their own primary navigation should not stack a second navbar under th
630
654
  </ProShell>
631
655
  ```
632
656
 
633
- For a fully custom layout, use `<ProShell app={app} hideTopbar hideFooter>` and compose `ProfileMenu`, `SignInButton`, `GateScreen`, and hooks from `@proappstore/sdk/ui` and `@proappstore/sdk/hooks`.
657
+ For a fully custom layout, use `<ProShell app={app} hideTopbar hideFooter>` and compose `NavBar`, `ProfileMenu`, `SignInButton`, `GateScreen`, and hooks from `@proappstore/sdk/ui` and `@proappstore/sdk/hooks`.
634
658
 
635
659
  ## UI Components
636
660
 
package/dist/index.d.ts CHANGED
@@ -47,7 +47,13 @@ export { useProAuth, useProSubscription, useProGate, useProNotifications } from
47
47
  export { ProProvider, useApp } from './provider.js';
48
48
  export type { ProProviderProps } from './provider.js';
49
49
  export { ProShell } from './shell.js';
50
- export type { ProShellProps, ProShellRenderContext, MenuItem } from './shell.js';
50
+ export type { ProShellProps, ProShellRenderContext, ProShellNavContext, MenuItem, ShellErrorContext } from './shell.js';
51
+ export { useToast, useOnline } from './shell-resilience.js';
52
+ export type { ToastApi, ToastOptions, ShellToastVariant } from './shell-resilience.js';
53
+ export { PageHeader, useDocumentTitle } from './page.js';
54
+ export type { PageHeaderProps } from './page.js';
55
+ export { NavBar } from './navbar.js';
56
+ export type { NavBarProps, NavItem } from './navbar.js';
51
57
  export { Avatar, ThemeToggle, TextSizeToggle, SignInButton, ProfileMenu, ProBadge, SubscriptionStatus, UpgradeCard, BillingButton, GateScreen, ProProfilePage, } from './ui.js';
52
58
  /**
53
59
  * Pro SDK instance — all features hit the PAS backend.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -36,6 +36,9 @@ export { useAuth, useSubscription, useGate, useNotifications, useTheme } from '.
36
36
  export { useProAuth, useProSubscription, useProGate, useProNotifications } from './hooks.js';
37
37
  export { ProProvider, useApp } from './provider.js';
38
38
  export { ProShell } from './shell.js';
39
+ export { useToast, useOnline } from './shell-resilience.js';
40
+ export { PageHeader, useDocumentTitle } from './page.js';
41
+ export { NavBar } from './navbar.js';
39
42
  export { Avatar, ThemeToggle, TextSizeToggle, SignInButton, ProfileMenu, ProBadge, SubscriptionStatus, UpgradeCard, BillingButton, GateScreen, ProProfilePage, } from './ui.js';
40
43
  /**
41
44
  * Pro SDK instance — all features hit the PAS backend.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * NavBar styles (#235) — the single source for both delivery paths:
3
+ * NavBar injects this into <head> at render (so an app needs no configuration),
4
+ * and the build writes it to dist/shell.css (`@proappstore/sdk/shell.css`) for
5
+ * apps that prefer to import it.
6
+ *
7
+ * Built on the canonical tokens only (PAS-UI-001), so it follows the app's
8
+ * light/dark theme. The Tailwind classes on NavBar's elements mirror these
9
+ * rules; Tailwind v4 emits utilities inside a cascade layer, so these unlayered
10
+ * rules win wherever the two meet and they cannot disagree.
11
+ */
12
+ export declare const NAVBAR_CSS = ".pas-nav{position:relative;display:flex;align-items:center;flex:1 1 auto;min-width:0;margin:0 .5rem}\n.pas-nav__toggle{display:none;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:1px solid var(--line);border-radius:10px;background:transparent;color:var(--ink);font:inherit;cursor:pointer}\n.pas-nav__list{display:flex;align-items:center;gap:.25rem;margin:0;padding:0;list-style:none;overflow-x:auto}\n.pas-nav__link{display:inline-flex;align-items:center;gap:.4rem;min-height:44px;padding:0 .75rem;border-radius:10px;color:var(--muted);font-size:.9rem;font-weight:600;text-decoration:none;white-space:nowrap}\n.pas-nav__link:hover{color:var(--ink);background:var(--line)}\n.pas-nav__link[aria-current=\"page\"]{color:var(--accent);background:var(--line)}\n.pas-nav__toggle:focus-visible,.pas-nav__link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n@media (max-width:639px){.pas-nav{flex:0 0 auto;margin:0}.pas-nav__toggle{display:inline-flex}.pas-nav__list{display:none;position:absolute;top:calc(100% + .5rem);left:0;z-index:60;flex-direction:column;align-items:stretch;min-width:12rem;padding:.5rem;overflow:visible;background:var(--paper);border:1px solid var(--line);border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.12)}.pas-nav[data-open=\"true\"] .pas-nav__list{display:flex}}\n";
13
+ //# sourceMappingURL=navbar-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navbar-css.d.ts","sourceRoot":"","sources":["../src/navbar-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,60CAQtB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * NavBar styles (#235) — the single source for both delivery paths:
3
+ * NavBar injects this into <head> at render (so an app needs no configuration),
4
+ * and the build writes it to dist/shell.css (`@proappstore/sdk/shell.css`) for
5
+ * apps that prefer to import it.
6
+ *
7
+ * Built on the canonical tokens only (PAS-UI-001), so it follows the app's
8
+ * light/dark theme. The Tailwind classes on NavBar's elements mirror these
9
+ * rules; Tailwind v4 emits utilities inside a cascade layer, so these unlayered
10
+ * rules win wherever the two meet and they cannot disagree.
11
+ */
12
+ export const NAVBAR_CSS = `.pas-nav{position:relative;display:flex;align-items:center;flex:1 1 auto;min-width:0;margin:0 .5rem}
13
+ .pas-nav__toggle{display:none;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:1px solid var(--line);border-radius:10px;background:transparent;color:var(--ink);font:inherit;cursor:pointer}
14
+ .pas-nav__list{display:flex;align-items:center;gap:.25rem;margin:0;padding:0;list-style:none;overflow-x:auto}
15
+ .pas-nav__link{display:inline-flex;align-items:center;gap:.4rem;min-height:44px;padding:0 .75rem;border-radius:10px;color:var(--muted);font-size:.9rem;font-weight:600;text-decoration:none;white-space:nowrap}
16
+ .pas-nav__link:hover{color:var(--ink);background:var(--line)}
17
+ .pas-nav__link[aria-current="page"]{color:var(--accent);background:var(--line)}
18
+ .pas-nav__toggle:focus-visible,.pas-nav__link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
19
+ @media (max-width:639px){.pas-nav{flex:0 0 auto;margin:0}.pas-nav__toggle{display:inline-flex}.pas-nav__list{display:none;position:absolute;top:calc(100% + .5rem);left:0;z-index:60;flex-direction:column;align-items:stretch;min-width:12rem;padding:.5rem;overflow:visible;background:var(--paper);border:1px solid var(--line);border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.12)}.pas-nav[data-open="true"] .pas-nav__list{display:flex}}
20
+ `;
21
+ //# sourceMappingURL=navbar-css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navbar-css.js","sourceRoot":"","sources":["../src/navbar-css.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;CAQzB,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { type ReactNode } from 'react';
2
+ /** One screen in the app's main navigation. */
3
+ export interface NavItem {
4
+ label: string;
5
+ /** Same-origin path, e.g. `/` or `/cases`. */
6
+ href: string;
7
+ /** Optional icon, rendered before the label (mark it `aria-hidden`). */
8
+ icon?: ReactNode;
9
+ /**
10
+ * Tab title while this item's route is current (#236, PAS-UI-003). ProShell
11
+ * applies it; a screen's own `useDocumentTitle` overrides it.
12
+ */
13
+ title?: string;
14
+ }
15
+ export interface NavBarProps {
16
+ items: NavItem[];
17
+ /**
18
+ * The route to mark as current. Defaults to `location.pathname`, kept in
19
+ * step with back/forward (`popstate`). Pass your router's location when you
20
+ * use one.
21
+ */
22
+ currentPath?: string;
23
+ /**
24
+ * Client-side navigation: called instead of a full page load on a plain
25
+ * left click. Without it the items are ordinary links.
26
+ */
27
+ onNavigate?: (href: string) => void;
28
+ }
29
+ /**
30
+ * The browser's current path, following back/forward. `initial` wins when
31
+ * given (router-driven apps, server rendering).
32
+ */
33
+ export declare function useCurrentPath(initial?: string): [string, (path: string) => void];
34
+ /** The item to mark current: an exact match, else the longest prefix (`/cases` for `/cases/42`). */
35
+ export declare function activeHref(items: NavItem[], path: string): string | null;
36
+ /**
37
+ * NavBar (#235) — the app's main navigation, rendered by ProShell's topbar
38
+ * from its `nav` prop, and usable on its own in a custom topbar.
39
+ *
40
+ * `<nav aria-label="Main">` landmark (PAS-UI-003), `aria-current="page"` on the
41
+ * current item, 44 px targets (PAS-UI-009), visible focus, and below 640 px a
42
+ * menu button (`aria-expanded` / `aria-controls`; Escape or a click outside
43
+ * closes it and returns focus). Renders nothing when there are no items.
44
+ */
45
+ export declare function NavBar({ items, currentPath, onNavigate }: NavBarProps): import("react/jsx-runtime").JSX.Element | null;
46
+ //# sourceMappingURL=navbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navbar.d.ts","sourceRoot":"","sources":["../src/navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2E,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGhH,+CAA+C;AAC/C,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,CAYjF;AAED,oGAAoG;AACpG,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxE;AAYD;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,WAAW,kDAmErE"}
package/dist/navbar.js ADDED
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useId, useInsertionEffect, useRef, useState } from 'react';
3
+ import { NAVBAR_CSS } from './navbar-css.js';
4
+ /**
5
+ * The browser's current path, following back/forward. `initial` wins when
6
+ * given (router-driven apps, server rendering).
7
+ */
8
+ export function useCurrentPath(initial) {
9
+ const [path, setPath] = useState(() => initial ?? (typeof window === 'undefined' ? '/' : window.location.pathname));
10
+ useEffect(() => {
11
+ if (initial !== undefined) {
12
+ setPath(initial);
13
+ return;
14
+ }
15
+ const sync = () => setPath(window.location.pathname);
16
+ window.addEventListener('popstate', sync);
17
+ return () => window.removeEventListener('popstate', sync);
18
+ }, [initial]);
19
+ return [path, setPath];
20
+ }
21
+ /** The item to mark current: an exact match, else the longest prefix (`/cases` for `/cases/42`). */
22
+ export function activeHref(items, path) {
23
+ let best = null;
24
+ for (const { href } of items) {
25
+ const matches = href === path || (href !== '/' && path.startsWith(`${href.replace(/\/+$/, '')}/`));
26
+ if (matches && (best === null || href.length > best.length))
27
+ best = href;
28
+ }
29
+ return best;
30
+ }
31
+ function useNavbarStyles() {
32
+ useInsertionEffect(() => {
33
+ if (document.getElementById('pas-nav-css'))
34
+ return;
35
+ const style = document.createElement('style');
36
+ style.id = 'pas-nav-css';
37
+ style.textContent = NAVBAR_CSS;
38
+ document.head.appendChild(style);
39
+ }, []);
40
+ }
41
+ /**
42
+ * NavBar (#235) — the app's main navigation, rendered by ProShell's topbar
43
+ * from its `nav` prop, and usable on its own in a custom topbar.
44
+ *
45
+ * `<nav aria-label="Main">` landmark (PAS-UI-003), `aria-current="page"` on the
46
+ * current item, 44 px targets (PAS-UI-009), visible focus, and below 640 px a
47
+ * menu button (`aria-expanded` / `aria-controls`; Escape or a click outside
48
+ * closes it and returns focus). Renders nothing when there are no items.
49
+ */
50
+ export function NavBar({ items, currentPath, onNavigate }) {
51
+ useNavbarStyles();
52
+ const [path, setPath] = useCurrentPath(currentPath);
53
+ const [open, setOpen] = useState(false);
54
+ const listId = useId();
55
+ const navRef = useRef(null);
56
+ const toggleRef = useRef(null);
57
+ useEffect(() => {
58
+ if (!open)
59
+ return;
60
+ const close = (returnFocus) => {
61
+ setOpen(false);
62
+ if (returnFocus)
63
+ toggleRef.current?.focus();
64
+ };
65
+ const onKey = (e) => { if (e.key === 'Escape')
66
+ close(true); };
67
+ const onPointer = (e) => { if (!navRef.current?.contains(e.target))
68
+ close(false); };
69
+ document.addEventListener('keydown', onKey);
70
+ document.addEventListener('pointerdown', onPointer);
71
+ return () => {
72
+ document.removeEventListener('keydown', onKey);
73
+ document.removeEventListener('pointerdown', onPointer);
74
+ };
75
+ }, [open]);
76
+ if (items.length === 0)
77
+ return null;
78
+ const current = activeHref(items, path);
79
+ const follow = (e, href) => {
80
+ setOpen(false);
81
+ if (!onNavigate || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
82
+ return;
83
+ e.preventDefault();
84
+ onNavigate(href);
85
+ if (currentPath === undefined)
86
+ setPath(href);
87
+ };
88
+ return (_jsxs("nav", { ref: navRef, "aria-label": "Main", className: "pas-nav relative flex min-w-0 flex-1 items-center", "data-open": open ? 'true' : 'false', children: [_jsx("button", { ref: toggleRef, type: "button", className: "pas-nav__toggle inline-flex min-h-11 min-w-11 items-center justify-center rounded-[10px] border border-[var(--line)] text-[var(--ink)] focus-visible:outline-2 focus-visible:outline-[var(--accent)] sm:hidden", "aria-expanded": open, "aria-controls": listId, "aria-label": "Menu", onClick: () => setOpen((o) => !o), children: _jsx("svg", { "aria-hidden": "true", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: _jsx("path", { d: open ? 'M6 6l12 12M18 6L6 18' : 'M4 7h16M4 12h16M4 17h16' }) }) }), _jsx("ul", { id: listId, className: "pas-nav__list m-0 flex list-none items-center gap-1 p-0", children: items.map((item) => (_jsx("li", { children: _jsxs("a", { href: item.href, "aria-current": item.href === current ? 'page' : undefined, className: "pas-nav__link inline-flex min-h-11 items-center gap-1.5 rounded-[10px] px-3 text-sm font-semibold whitespace-nowrap text-[var(--muted)] no-underline hover:text-[var(--ink)] focus-visible:outline-2 focus-visible:outline-[var(--accent)] aria-[current=page]:text-[var(--accent)]", onClick: (e) => follow(e, item.href), children: [item.icon, item.label] }) }, item.href))) })] }));
89
+ }
90
+ //# sourceMappingURL=navbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navbar.js","sourceRoot":"","sources":["../src/navbar.tsx"],"names":[],"mappings":"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"}
package/dist/page.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * Set the tab title for the current screen (#236, PAS-UI-003). Call it once in
4
+ * each routed screen; the title follows the value while the screen is mounted.
5
+ * Runs after ProShell applies a nav item's `title`, so the screen's own title
6
+ * wins on the same route.
7
+ *
8
+ * ```tsx
9
+ * useDocumentTitle(`${task.title} — Tasks`)
10
+ * ```
11
+ */
12
+ export declare function useDocumentTitle(title: string | null | undefined): void;
13
+ export interface PageHeaderProps {
14
+ /** The screen's heading — rendered as its single `<h1>`. */
15
+ title: ReactNode;
16
+ /** Optional line under the heading. */
17
+ description?: ReactNode;
18
+ /** Optional controls aligned with the heading (e.g. a primary button). */
19
+ actions?: ReactNode;
20
+ }
21
+ /**
22
+ * The screen's heading (#236): renders the page's one `<h1>` the same way on
23
+ * every screen (PAS-UI-003). ProShell moves focus to it after a client-side
24
+ * navigation, so keyboard and screen-reader users land on the new page.
25
+ */
26
+ export declare function PageHeader({ title, description, actions }: PageHeaderProps): import("react/jsx-runtime").JSX.Element;
27
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../src/page.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAIvE;AAED,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,KAAK,EAAE,SAAS,CAAC;IACjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,eAAe,2CAY1E"}
package/dist/page.js ADDED
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ /**
4
+ * Set the tab title for the current screen (#236, PAS-UI-003). Call it once in
5
+ * each routed screen; the title follows the value while the screen is mounted.
6
+ * Runs after ProShell applies a nav item's `title`, so the screen's own title
7
+ * wins on the same route.
8
+ *
9
+ * ```tsx
10
+ * useDocumentTitle(`${task.title} — Tasks`)
11
+ * ```
12
+ */
13
+ export function useDocumentTitle(title) {
14
+ useEffect(() => {
15
+ if (title)
16
+ document.title = title;
17
+ }, [title]);
18
+ }
19
+ /**
20
+ * The screen's heading (#236): renders the page's one `<h1>` the same way on
21
+ * every screen (PAS-UI-003). ProShell moves focus to it after a client-side
22
+ * navigation, so keyboard and screen-reader users land on the new page.
23
+ */
24
+ export function PageHeader({ title, description, actions }) {
25
+ return (_jsxs("div", { className: "pas-page-header mb-5 flex flex-wrap items-end justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h1", { className: "pas-page-header__title m-0 text-2xl font-bold text-[var(--ink)]", tabIndex: -1, "data-pas-page-heading": "", children: title }), description && _jsx("p", { className: "pas-page-header__description mt-1 text-sm text-[var(--muted)]", children: description })] }), actions && _jsx("div", { className: "flex items-center gap-2", children: actions })] }));
26
+ }
27
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAElD;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK;YAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AACd,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAmB;IACzE,OAAO,CACL,eAAK,SAAS,EAAC,qEAAqE,aAClF,0BACE,aAAI,SAAS,EAAC,iEAAiE,EAAC,QAAQ,EAAE,CAAC,CAAC,2BAAwB,EAAE,YACnH,KAAK,GACH,EACJ,WAAW,IAAI,YAAG,SAAS,EAAC,+DAA+D,YAAE,WAAW,GAAK,IAC1G,EACL,OAAO,IAAI,cAAK,SAAS,EAAC,yBAAyB,YAAE,OAAO,GAAO,IAChE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ProShell's resilience and feedback layer styles (#236): skip link, offline
3
+ * banner, toast region, error and loading fallbacks, PageHeader. Same model as
4
+ * navbar-css.ts: canonical tokens only (PAS-UI-001), injected by ProShell at
5
+ * render so an app needs no configuration, and appended to dist/shell.css.
6
+ */
7
+ export declare const SHELL_CSS = ".pas-skip-link:not(:focus){position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}\n.pas-skip-link:focus{position:fixed;top:.5rem;left:.5rem;z-index:1200;padding:.7rem 1rem;border:2px solid var(--accent);border-radius:10px;background:var(--paper);color:var(--ink);font-weight:600;text-decoration:none;outline:2px solid var(--accent);outline-offset:2px}\n.pas-main:focus{outline:none}\n.pas-offline{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.25rem .5rem .25rem 1rem;background:var(--panel);color:var(--ink);border-bottom:1px solid var(--line);border-left:3px solid var(--warning);font-size:.875rem}\n.pas-toast-region{position:fixed;bottom:1.25rem;left:50%;z-index:1100;display:flex;flex-direction:column;align-items:center;gap:.5rem;max-width:calc(100vw - 2rem);transform:translateX(-50%);pointer-events:none}\n.pas-toast{display:flex;align-items:center;gap:.75rem;padding:.25rem .25rem .25rem 1rem;background:var(--ink);color:var(--paper);border-left:3px solid var(--accent);border-radius:var(--radius,.75rem);box-shadow:0 8px 24px rgba(0,0,0,.3);font-size:.875rem;pointer-events:auto}\n.pas-toast[data-variant=\"success\"]{border-left-color:var(--success)}\n.pas-toast[data-variant=\"error\"]{border-left-color:var(--danger)}\n.pas-dismiss{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font:inherit;font-size:1.1rem;line-height:1;cursor:pointer;opacity:.75}\n.pas-dismiss:hover{opacity:1}\n.pas-shell-loading{display:flex;flex:1;align-items:center;justify-content:center;padding:3rem 1rem}\n.pas-shell-error{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;padding:3rem 1rem;text-align:center;color:var(--ink)}\n.pas-shell-error h1{margin:0;font-size:1.25rem}\n.pas-shell-error p{margin:0;max-width:32rem;color:var(--muted);font-size:.9rem}\n.pas-shell-error__retry{min-height:44px;padding:0 1.25rem;border:0;border-radius:10px;background:var(--accent);color:var(--paper);font:inherit;font-weight:600;cursor:pointer}\n.pas-page-header{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:.75rem;margin:0 0 1.25rem}\n.pas-page-header__title{margin:0;color:var(--ink);font-size:1.5rem;font-weight:700;line-height:1.2}\n.pas-page-header__title:focus{outline:none}\n.pas-page-header__description{margin:.25rem 0 0;color:var(--muted);font-size:.9rem}\n.pas-dismiss:focus-visible,.pas-shell-error__retry:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n";
8
+ //# sourceMappingURL=shell-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-css.d.ts","sourceRoot":"","sources":["../src/shell-css.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,SAAS,2oFAoBrB,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * ProShell's resilience and feedback layer styles (#236): skip link, offline
3
+ * banner, toast region, error and loading fallbacks, PageHeader. Same model as
4
+ * navbar-css.ts: canonical tokens only (PAS-UI-001), injected by ProShell at
5
+ * render so an app needs no configuration, and appended to dist/shell.css.
6
+ */
7
+ export const SHELL_CSS = `.pas-skip-link:not(:focus){position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
8
+ .pas-skip-link:focus{position:fixed;top:.5rem;left:.5rem;z-index:1200;padding:.7rem 1rem;border:2px solid var(--accent);border-radius:10px;background:var(--paper);color:var(--ink);font-weight:600;text-decoration:none;outline:2px solid var(--accent);outline-offset:2px}
9
+ .pas-main:focus{outline:none}
10
+ .pas-offline{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.25rem .5rem .25rem 1rem;background:var(--panel);color:var(--ink);border-bottom:1px solid var(--line);border-left:3px solid var(--warning);font-size:.875rem}
11
+ .pas-toast-region{position:fixed;bottom:1.25rem;left:50%;z-index:1100;display:flex;flex-direction:column;align-items:center;gap:.5rem;max-width:calc(100vw - 2rem);transform:translateX(-50%);pointer-events:none}
12
+ .pas-toast{display:flex;align-items:center;gap:.75rem;padding:.25rem .25rem .25rem 1rem;background:var(--ink);color:var(--paper);border-left:3px solid var(--accent);border-radius:var(--radius,.75rem);box-shadow:0 8px 24px rgba(0,0,0,.3);font-size:.875rem;pointer-events:auto}
13
+ .pas-toast[data-variant="success"]{border-left-color:var(--success)}
14
+ .pas-toast[data-variant="error"]{border-left-color:var(--danger)}
15
+ .pas-dismiss{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font:inherit;font-size:1.1rem;line-height:1;cursor:pointer;opacity:.75}
16
+ .pas-dismiss:hover{opacity:1}
17
+ .pas-shell-loading{display:flex;flex:1;align-items:center;justify-content:center;padding:3rem 1rem}
18
+ .pas-shell-error{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;padding:3rem 1rem;text-align:center;color:var(--ink)}
19
+ .pas-shell-error h1{margin:0;font-size:1.25rem}
20
+ .pas-shell-error p{margin:0;max-width:32rem;color:var(--muted);font-size:.9rem}
21
+ .pas-shell-error__retry{min-height:44px;padding:0 1.25rem;border:0;border-radius:10px;background:var(--accent);color:var(--paper);font:inherit;font-weight:600;cursor:pointer}
22
+ .pas-page-header{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:.75rem;margin:0 0 1.25rem}
23
+ .pas-page-header__title{margin:0;color:var(--ink);font-size:1.5rem;font-weight:700;line-height:1.2}
24
+ .pas-page-header__title:focus{outline:none}
25
+ .pas-page-header__description{margin:.25rem 0 0;color:var(--muted);font-size:.9rem}
26
+ .pas-dismiss:focus-visible,.pas-shell-error__retry:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
27
+ `;
28
+ //# sourceMappingURL=shell-css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-css.js","sourceRoot":"","sources":["../src/shell-css.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;CAoBxB,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { Component, type ErrorInfo, type ReactNode, type RefObject } from 'react';
2
+ import type { ProAppStore } from './index.js';
3
+ export interface ShellErrorContext {
4
+ error: Error;
5
+ /** Clear the error and render the screen again. */
6
+ reset: () => void;
7
+ }
8
+ interface BoundaryProps {
9
+ app: ProAppStore;
10
+ renderError: ((ctx: ShellErrorContext) => ReactNode) | undefined;
11
+ /** A change (the current route) clears a caught error, so navigating away recovers. */
12
+ resetKey: string;
13
+ children: ReactNode;
14
+ }
15
+ interface BoundaryState {
16
+ error: Error | null;
17
+ resetKey: string;
18
+ }
19
+ /**
20
+ * Catches a render error in the app's content (#236) so one broken screen
21
+ * shows a fallback instead of a white screen. The error is recorded through
22
+ * `app.logs` — an error React catches never reaches `window.onerror`, so the
23
+ * automatic capture would otherwise miss it.
24
+ */
25
+ export declare class ShellErrorBoundary extends Component<BoundaryProps, BoundaryState> {
26
+ state: BoundaryState;
27
+ static getDerivedStateFromError(error: unknown): Partial<BoundaryState>;
28
+ static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState): Partial<BoundaryState> | null;
29
+ componentDidCatch(error: unknown, info: ErrorInfo): void;
30
+ reset: () => void;
31
+ render(): ReactNode;
32
+ }
33
+ export type ShellToastVariant = 'info' | 'success' | 'error';
34
+ export interface ToastOptions {
35
+ variant?: ShellToastVariant;
36
+ /** Milliseconds before it dismisses itself; 0 keeps it until dismissed. Default 4000. */
37
+ duration?: number;
38
+ }
39
+ export interface ToastApi {
40
+ /** Show a message; returns its id. */
41
+ show: (message: string, options?: ToastOptions) => number;
42
+ dismiss: (id: number) => void;
43
+ }
44
+ /**
45
+ * Raise a message from any screen inside ProShell (#236). Messages appear in
46
+ * the shell's single polite live region.
47
+ *
48
+ * ```tsx
49
+ * const toast = useToast()
50
+ * toast.show('Saved', { variant: 'success' })
51
+ * ```
52
+ */
53
+ export declare function useToast(): ToastApi;
54
+ /**
55
+ * The shell's toast queue. The region is rendered once and always, so it is
56
+ * already in the accessibility tree when a message arrives — a live region
57
+ * created together with its first message is often not announced. Items carry
58
+ * no live-region role of their own.
59
+ */
60
+ export declare function ToastProvider({ children }: {
61
+ children: ReactNode;
62
+ }): import("react/jsx-runtime").JSX.Element;
63
+ /** `navigator.onLine`, kept current by the browser's online/offline events. */
64
+ export declare function useOnline(): boolean;
65
+ /**
66
+ * A banner under the topbar while the connection is down (#236). Its polite
67
+ * live region is always present, so the change is announced. Dismissible;
68
+ * clears itself on reconnect, and a later drop shows it again.
69
+ */
70
+ export declare function OfflineBanner(): import("react/jsx-runtime").JSX.Element;
71
+ /** The first focusable element: hidden until focused, moves focus to the shell's `<main id="main">`. */
72
+ export declare function SkipLink({ mainRef }: {
73
+ mainRef: RefObject<HTMLElement | null>;
74
+ }): import("react/jsx-runtime").JSX.Element;
75
+ /**
76
+ * Scroll and focus on client-side route changes (#236). Forward navigation
77
+ * lands at the top; back/forward returns to where that route was left. After
78
+ * either, focus moves to the new screen's PageHeader `<h1>`, else to `<main>`.
79
+ *
80
+ * Only for client-side navigation (`enabled` = the app passed `onNavigate`):
81
+ * with ordinary links every navigation is a page load, and the browser already
82
+ * restores scroll and resets focus — taking scroll restoration over there would
83
+ * break it on the way back.
84
+ *
85
+ * Returns the function to call just before a forward navigation.
86
+ */
87
+ export declare function useRouteChangeEffects(path: string, mainRef: RefObject<HTMLElement | null>, enabled: boolean): () => void;
88
+ export {};
89
+ //# sourceMappingURL=shell-resilience.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-resilience.d.ts","sourceRoot":"","sources":["../src/shell-resilience.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAQT,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,mDAAmD;IACnD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,GAAG,EAAE,WAAW,CAAC;IACjB,WAAW,EAAE,CAAC,CAAC,GAAG,EAAE,iBAAiB,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC;IACjE,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACpE,KAAK,EAAE,aAAa,CAAkD;IAE/E,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IAIvE,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAIjG,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IASjE,KAAK,QAAO,IAAI,CAAmC;IAE1C,MAAM,IAAI,SAAS;CAc7B;AAID,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,MAAM,CAAC;IAC1D,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAcD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,IAAI,QAAQ,CAInC;AAkBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAqBlE;AAID,+EAA+E;AAC/E,wBAAgB,SAAS,IAAI,OAAO,CAcnC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,4CAkB5B;AAID,wGAAwG;AACxG,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CAAE,2CAe/E;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI,CA0CxH"}
@@ -0,0 +1,178 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Component, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { describeError } from './logs.js';
4
+ /**
5
+ * Catches a render error in the app's content (#236) so one broken screen
6
+ * shows a fallback instead of a white screen. The error is recorded through
7
+ * `app.logs` — an error React catches never reaches `window.onerror`, so the
8
+ * automatic capture would otherwise miss it.
9
+ */
10
+ export class ShellErrorBoundary extends Component {
11
+ state = { error: null, resetKey: this.props.resetKey };
12
+ static getDerivedStateFromError(error) {
13
+ return { error: error instanceof Error ? error : new Error(String(error)) };
14
+ }
15
+ static getDerivedStateFromProps(props, state) {
16
+ return props.resetKey !== state.resetKey ? { error: null, resetKey: props.resetKey } : null;
17
+ }
18
+ componentDidCatch(error, info) {
19
+ const described = describeError(error);
20
+ this.props.app.logs.capture('error', 'react.error-boundary', described.message, {
21
+ stack: described.stack,
22
+ componentStack: info.componentStack ?? undefined,
23
+ path: typeof window === 'undefined' ? undefined : window.location.pathname,
24
+ });
25
+ }
26
+ reset = () => this.setState({ error: null });
27
+ render() {
28
+ const { error } = this.state;
29
+ if (!error)
30
+ return this.props.children;
31
+ if (this.props.renderError)
32
+ return this.props.renderError({ error, reset: this.reset });
33
+ return (_jsxs("div", { role: "alert", className: "pas-shell-error flex flex-1 flex-col items-center justify-center gap-3 px-4 py-12 text-center", children: [_jsx("h1", { children: "Something went wrong" }), _jsx("p", { children: "This screen hit an error and could not be shown. It has been reported. Try again, or use the navigation to go elsewhere." }), _jsx("button", { type: "button", className: "pas-shell-error__retry min-h-11 rounded-[10px] px-5 font-semibold", onClick: this.reset, children: "Try again" })] }));
34
+ }
35
+ }
36
+ /** At most this many messages at once; the oldest goes first. */
37
+ const MAX_TOASTS = 4;
38
+ const ToastContext = createContext(null);
39
+ /**
40
+ * Raise a message from any screen inside ProShell (#236). Messages appear in
41
+ * the shell's single polite live region.
42
+ *
43
+ * ```tsx
44
+ * const toast = useToast()
45
+ * toast.show('Saved', { variant: 'success' })
46
+ * ```
47
+ */
48
+ export function useToast() {
49
+ const api = useContext(ToastContext);
50
+ if (!api)
51
+ throw new Error('useToast must be used inside <ProShell>');
52
+ return api;
53
+ }
54
+ function ToastItem({ toast, onDismiss }) {
55
+ useEffect(() => {
56
+ if (toast.duration <= 0)
57
+ return;
58
+ const timer = setTimeout(() => onDismiss(toast.id), toast.duration);
59
+ return () => clearTimeout(timer);
60
+ }, [toast.id, toast.duration, onDismiss]);
61
+ return (_jsxs("div", { className: "pas-toast flex items-center gap-3 rounded-xl text-sm", "data-variant": toast.variant, children: [_jsx("span", { children: toast.message }), _jsx("button", { type: "button", className: "pas-dismiss min-h-11 min-w-11", "aria-label": "Dismiss", onClick: () => onDismiss(toast.id), children: "\u00D7" })] }));
62
+ }
63
+ /**
64
+ * The shell's toast queue. The region is rendered once and always, so it is
65
+ * already in the accessibility tree when a message arrives — a live region
66
+ * created together with its first message is often not announced. Items carry
67
+ * no live-region role of their own.
68
+ */
69
+ export function ToastProvider({ children }) {
70
+ const [toasts, setToasts] = useState([]);
71
+ const nextId = useRef(1);
72
+ const dismiss = useCallback((id) => setToasts((all) => all.filter((t) => t.id !== id)), []);
73
+ const show = useCallback((message, options = {}) => {
74
+ const id = nextId.current++;
75
+ const toast = { id, message, variant: options.variant ?? 'info', duration: options.duration ?? 4000 };
76
+ setToasts((all) => [...all, toast].slice(-MAX_TOASTS));
77
+ return id;
78
+ }, []);
79
+ const api = useMemo(() => ({ show, dismiss }), [show, dismiss]);
80
+ return (_jsxs(ToastContext.Provider, { value: api, children: [children, _jsx("div", { role: "status", "aria-live": "polite", className: "pas-toast-region fixed bottom-5 left-1/2 flex -translate-x-1/2 flex-col items-center gap-2", children: toasts.map((toast) => _jsx(ToastItem, { toast: toast, onDismiss: dismiss }, toast.id)) })] }));
81
+ }
82
+ // ── Offline ─────────────────────────────────────────────────────
83
+ /** `navigator.onLine`, kept current by the browser's online/offline events. */
84
+ export function useOnline() {
85
+ const [online, setOnline] = useState(() => (typeof navigator === 'undefined' ? true : navigator.onLine));
86
+ useEffect(() => {
87
+ const up = () => setOnline(true);
88
+ const down = () => setOnline(false);
89
+ window.addEventListener('online', up);
90
+ window.addEventListener('offline', down);
91
+ setOnline(navigator.onLine);
92
+ return () => {
93
+ window.removeEventListener('online', up);
94
+ window.removeEventListener('offline', down);
95
+ };
96
+ }, []);
97
+ return online;
98
+ }
99
+ /**
100
+ * A banner under the topbar while the connection is down (#236). Its polite
101
+ * live region is always present, so the change is announced. Dismissible;
102
+ * clears itself on reconnect, and a later drop shows it again.
103
+ */
104
+ export function OfflineBanner() {
105
+ const online = useOnline();
106
+ const [dismissed, setDismissed] = useState(false);
107
+ useEffect(() => {
108
+ if (online)
109
+ setDismissed(false);
110
+ }, [online]);
111
+ return (_jsx("div", { role: "status", "aria-live": "polite", children: !online && !dismissed && (_jsxs("div", { className: "pas-offline flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { children: "You're offline. Changes can't be saved until the connection is back." }), _jsx("button", { type: "button", className: "pas-dismiss min-h-11 min-w-11", "aria-label": "Dismiss offline notice", onClick: () => setDismissed(true), children: "\u00D7" })] })) }));
112
+ }
113
+ // ── Skip link ───────────────────────────────────────────────────
114
+ /** The first focusable element: hidden until focused, moves focus to the shell's `<main id="main">`. */
115
+ export function SkipLink({ mainRef }) {
116
+ return (_jsx("a", { href: "#main", className: "pas-skip-link", onClick: (e) => {
117
+ // Focus directly rather than following the fragment: a hash change is a
118
+ // history navigation, which a router would see as a route change.
119
+ e.preventDefault();
120
+ mainRef.current?.focus();
121
+ }, children: "Skip to content" }));
122
+ }
123
+ // ── Route changes: scroll and focus ─────────────────────────────
124
+ /**
125
+ * Scroll and focus on client-side route changes (#236). Forward navigation
126
+ * lands at the top; back/forward returns to where that route was left. After
127
+ * either, focus moves to the new screen's PageHeader `<h1>`, else to `<main>`.
128
+ *
129
+ * Only for client-side navigation (`enabled` = the app passed `onNavigate`):
130
+ * with ordinary links every navigation is a page load, and the browser already
131
+ * restores scroll and resets focus — taking scroll restoration over there would
132
+ * break it on the way back.
133
+ *
134
+ * Returns the function to call just before a forward navigation.
135
+ */
136
+ export function useRouteChangeEffects(path, mainRef, enabled) {
137
+ const positions = useRef(new Map());
138
+ const lastPath = useRef(path);
139
+ const kind = useRef('push');
140
+ useEffect(() => {
141
+ if (!enabled)
142
+ return;
143
+ const previous = window.history.scrollRestoration;
144
+ window.history.scrollRestoration = 'manual';
145
+ // Runs before the re-render the same popstate causes, while the page still
146
+ // shows the route being left.
147
+ const onPop = () => {
148
+ positions.current.set(lastPath.current, window.scrollY);
149
+ kind.current = 'pop';
150
+ };
151
+ window.addEventListener('popstate', onPop);
152
+ return () => {
153
+ window.removeEventListener('popstate', onPop);
154
+ window.history.scrollRestoration = previous;
155
+ };
156
+ }, [enabled]);
157
+ useEffect(() => {
158
+ if (!enabled || path === lastPath.current)
159
+ return;
160
+ lastPath.current = path;
161
+ const back = kind.current === 'pop';
162
+ kind.current = 'push';
163
+ // A frame later, so a router that renders the new screen in its own update
164
+ // has committed it before we scroll to it and look for its heading.
165
+ const frame = requestAnimationFrame(() => {
166
+ window.scrollTo(0, back ? positions.current.get(path) ?? 0 : 0);
167
+ const main = mainRef.current;
168
+ const target = main?.querySelector('[data-pas-page-heading]') ?? main;
169
+ target?.focus({ preventScroll: true });
170
+ });
171
+ return () => cancelAnimationFrame(frame);
172
+ }, [path, enabled, mainRef]);
173
+ return useCallback(() => {
174
+ positions.current.set(lastPath.current, window.scrollY);
175
+ kind.current = 'push';
176
+ }, []);
177
+ }
178
+ //# sourceMappingURL=shell-resilience.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-resilience.js","sourceRoot":"","sources":["../src/shell-resilience.tsx"],"names":[],"mappings":"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"}
package/dist/shell.css ADDED
@@ -0,0 +1,28 @@
1
+ .pas-nav{position:relative;display:flex;align-items:center;flex:1 1 auto;min-width:0;margin:0 .5rem}
2
+ .pas-nav__toggle{display:none;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:1px solid var(--line);border-radius:10px;background:transparent;color:var(--ink);font:inherit;cursor:pointer}
3
+ .pas-nav__list{display:flex;align-items:center;gap:.25rem;margin:0;padding:0;list-style:none;overflow-x:auto}
4
+ .pas-nav__link{display:inline-flex;align-items:center;gap:.4rem;min-height:44px;padding:0 .75rem;border-radius:10px;color:var(--muted);font-size:.9rem;font-weight:600;text-decoration:none;white-space:nowrap}
5
+ .pas-nav__link:hover{color:var(--ink);background:var(--line)}
6
+ .pas-nav__link[aria-current="page"]{color:var(--accent);background:var(--line)}
7
+ .pas-nav__toggle:focus-visible,.pas-nav__link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
8
+ @media (max-width:639px){.pas-nav{flex:0 0 auto;margin:0}.pas-nav__toggle{display:inline-flex}.pas-nav__list{display:none;position:absolute;top:calc(100% + .5rem);left:0;z-index:60;flex-direction:column;align-items:stretch;min-width:12rem;padding:.5rem;overflow:visible;background:var(--paper);border:1px solid var(--line);border-radius:12px;box-shadow:0 8px 24px rgba(0,0,0,.12)}.pas-nav[data-open="true"] .pas-nav__list{display:flex}}
9
+ .pas-skip-link:not(:focus){position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
10
+ .pas-skip-link:focus{position:fixed;top:.5rem;left:.5rem;z-index:1200;padding:.7rem 1rem;border:2px solid var(--accent);border-radius:10px;background:var(--paper);color:var(--ink);font-weight:600;text-decoration:none;outline:2px solid var(--accent);outline-offset:2px}
11
+ .pas-main:focus{outline:none}
12
+ .pas-offline{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.25rem .5rem .25rem 1rem;background:var(--panel);color:var(--ink);border-bottom:1px solid var(--line);border-left:3px solid var(--warning);font-size:.875rem}
13
+ .pas-toast-region{position:fixed;bottom:1.25rem;left:50%;z-index:1100;display:flex;flex-direction:column;align-items:center;gap:.5rem;max-width:calc(100vw - 2rem);transform:translateX(-50%);pointer-events:none}
14
+ .pas-toast{display:flex;align-items:center;gap:.75rem;padding:.25rem .25rem .25rem 1rem;background:var(--ink);color:var(--paper);border-left:3px solid var(--accent);border-radius:var(--radius,.75rem);box-shadow:0 8px 24px rgba(0,0,0,.3);font-size:.875rem;pointer-events:auto}
15
+ .pas-toast[data-variant="success"]{border-left-color:var(--success)}
16
+ .pas-toast[data-variant="error"]{border-left-color:var(--danger)}
17
+ .pas-dismiss{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0;border:0;border-radius:10px;background:transparent;color:inherit;font:inherit;font-size:1.1rem;line-height:1;cursor:pointer;opacity:.75}
18
+ .pas-dismiss:hover{opacity:1}
19
+ .pas-shell-loading{display:flex;flex:1;align-items:center;justify-content:center;padding:3rem 1rem}
20
+ .pas-shell-error{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;padding:3rem 1rem;text-align:center;color:var(--ink)}
21
+ .pas-shell-error h1{margin:0;font-size:1.25rem}
22
+ .pas-shell-error p{margin:0;max-width:32rem;color:var(--muted);font-size:.9rem}
23
+ .pas-shell-error__retry{min-height:44px;padding:0 1.25rem;border:0;border-radius:10px;background:var(--accent);color:var(--paper);font:inherit;font-weight:600;cursor:pointer}
24
+ .pas-page-header{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:.75rem;margin:0 0 1.25rem}
25
+ .pas-page-header__title{margin:0;color:var(--ink);font-size:1.5rem;font-weight:700;line-height:1.2}
26
+ .pas-page-header__title:focus{outline:none}
27
+ .pas-page-header__description{margin:.25rem 0 0;color:var(--muted);font-size:.9rem}
28
+ .pas-dismiss:focus-visible,.pas-shell-error__retry:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
package/dist/shell.d.ts CHANGED
@@ -2,6 +2,10 @@ import { type ReactNode } from 'react';
2
2
  import type { ProAppStore } from './index.js';
3
3
  import type { User } from './base-types.js';
4
4
  import type { Subscription } from './types.js';
5
+ import { type NavItem } from './navbar.js';
6
+ import { type ShellErrorContext } from './shell-resilience.js';
7
+ export type { NavItem } from './navbar.js';
8
+ export type { ShellErrorContext } from './shell-resilience.js';
5
9
  export interface MenuItem {
6
10
  label: string;
7
11
  onClick: () => void;
@@ -21,6 +25,16 @@ export interface ProShellRenderContext {
21
25
  profileMenu: ReactNode;
22
26
  /** PRO badge when the current subscription is active; otherwise null. */
23
27
  proBadge: ReactNode;
28
+ /** The app's main navigation (`nav` / `renderNav`), or null when none is declared.
29
+ * A custom `renderTopbar` should place it. */
30
+ nav: ReactNode;
31
+ }
32
+ export interface ProShellNavContext {
33
+ items: NavItem[];
34
+ /** The path the shell considers current (`location.pathname`, following back/forward). */
35
+ currentPath: string;
36
+ /** Navigate to `href`: the shell's `onNavigate`, else a full page load. */
37
+ onNavigate: (href: string) => void;
24
38
  }
25
39
  export interface ProShellProps {
26
40
  /** The ProAppStore SDK instance from initPro(). */
@@ -29,6 +43,23 @@ export interface ProShellProps {
29
43
  children: ReactNode;
30
44
  /** App name shown in the topbar. */
31
45
  appName?: string;
46
+ /**
47
+ * The app's screens — the standard way to give an app navigation (#235).
48
+ * ProShell renders them as a `<nav aria-label="Main">` in its topbar, marks
49
+ * the current route, and collapses to a menu button on small screens.
50
+ *
51
+ * ```tsx
52
+ * <ProShell app={app} appName="Cases" nav={[{ label: 'Home', href: '/' }, { label: 'Cases', href: '/cases' }]}>
53
+ * ```
54
+ */
55
+ nav?: NavItem[];
56
+ /** Replace the built-in NavBar (still placed in the topbar) with your own. */
57
+ renderNav?: (ctx: ProShellNavContext) => ReactNode;
58
+ /**
59
+ * Client-side navigation for nav clicks (e.g. your router's `navigate`).
60
+ * Without it, nav items are ordinary links (full page load).
61
+ */
62
+ onNavigate?: (href: string) => void;
32
63
  /**
33
64
  * If true, allow free users to see the app (no subscription gate).
34
65
  *
@@ -40,7 +71,7 @@ export interface ProShellProps {
40
71
  showThemeToggle?: boolean;
41
72
  /** Custom items added to the profile dropdown (above sign-out). */
42
73
  menuItems?: MenuItem[];
43
- /** Hide the default ProShell topbar. Use when the app renders its own navigation. */
74
+ /** Hide the default ProShell topbar. Prefer `nav`; this also hides the navigation. */
44
75
  hideTopbar?: boolean;
45
76
  /** Hide the default ProShell footer. */
46
77
  hideFooter?: boolean;
@@ -53,6 +84,13 @@ export interface ProShellProps {
53
84
  renderTopbar?: (ctx: ProShellRenderContext) => ReactNode;
54
85
  /** Replace the default footer. Return null to omit it. */
55
86
  renderFooter?: (ctx: ProShellRenderContext) => ReactNode;
87
+ /**
88
+ * Replace the fallback shown when a screen throws while rendering (#236).
89
+ * The error is already recorded via `app.logs`; call `reset` to retry.
90
+ */
91
+ renderError?: (ctx: ShellErrorContext) => ReactNode;
92
+ /** Replace the spinner shown while a lazy-loaded screen loads (#236). */
93
+ renderLoading?: () => ReactNode;
56
94
  }
57
95
  /**
58
96
  * ProShell — platform-level Shell for all ProAppStore apps.
@@ -61,6 +99,10 @@ export interface ProShellProps {
61
99
  * - Auth initialization + sign-in gate
62
100
  * - Subscription check + upgrade wall (unless allowFree=true)
63
101
  * - Topbar with avatar, app name, menu (sign out, delete account, manage billing)
102
+ * - Main navigation from the `nav` prop (<nav aria-label="Main">, current route, mobile menu)
103
+ * - Resilience and feedback (#236): error boundary + Suspense around the content,
104
+ * `useToast` region, offline banner, skip link, nav-item titles, and scroll +
105
+ * focus handling on client-side route changes
64
106
  * - Theme support via CSS custom properties
65
107
  * - Only renders children when all gates pass
66
108
  *
@@ -73,12 +115,12 @@ export interface ProShellProps {
73
115
  *
74
116
  * export default function App() {
75
117
  * return (
76
- * <ProShell app={app} appName="Meetup">
118
+ * <ProShell app={app} appName="Meetup" nav={[{ label: 'Events', href: '/' }, { label: 'Groups', href: '/groups' }]}>
77
119
  * <MeetupApp />
78
120
  * </ProShell>
79
121
  * )
80
122
  * }
81
123
  * ```
82
124
  */
83
- export declare function ProShell({ app, children, appName, allowFree, showThemeToggle, menuItems, hideTopbar, hideFooter, renderTopbar, renderFooter, }: ProShellProps): import("react/jsx-runtime").JSX.Element;
125
+ export declare function ProShell({ app, children, appName, nav, renderNav, onNavigate, allowFree, showThemeToggle, menuItems, hideTopbar, hideFooter, renderTopbar, renderFooter, renderError, renderLoading, }: ProShellProps): import("react/jsx-runtime").JSX.Element;
84
126
  //# sourceMappingURL=shell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,GAAG,EAAE,WAAW,CAAC;IACjB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kFAAkF;IAClF,IAAI,EAAE,IAAI,CAAC;IACX,sEAAsE;IACtE,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,mDAAmD;IACnD,cAAc,EAAE,SAAS,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,EAAE,SAAS,CAAC;IACvB,yEAAyE;IACzE,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,GAAG,EAAE,WAAW,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,SAAS,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,qFAAqF;IACrF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,SAAS,CAAC;IACzD,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,SAAS,CAAC;CAC1D;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EACH,QAAQ,EACR,OAAO,EACP,SAAgB,EAChB,eAAsB,EACtB,SAAS,EACT,UAAkB,EAClB,UAAkB,EAClB,YAAY,EACZ,YAAY,GACb,EAAE,aAAa,2CA6Ff"}
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"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"}
package/dist/shell.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect } from 'react';
3
- import { ProfileMenu, ProBadge, GateScreen, TextSizeToggle } from './ui.js';
2
+ import { Suspense, useEffect, useInsertionEffect, useLayoutEffect, useRef, useState } from 'react';
3
+ import { ProfileMenu, ProBadge, GateScreen, TextSizeToggle, Spinner } from './ui.js';
4
4
  import { ProProvider } from './provider.js';
5
+ import { activeHref, NavBar, useCurrentPath } from './navbar.js';
6
+ import { SHELL_CSS } from './shell-css.js';
7
+ import { OfflineBanner, ShellErrorBoundary, SkipLink, ToastProvider, useRouteChangeEffects, } from './shell-resilience.js';
5
8
  /**
6
9
  * ProShell — platform-level Shell for all ProAppStore apps.
7
10
  *
@@ -9,6 +12,10 @@ import { ProProvider } from './provider.js';
9
12
  * - Auth initialization + sign-in gate
10
13
  * - Subscription check + upgrade wall (unless allowFree=true)
11
14
  * - Topbar with avatar, app name, menu (sign out, delete account, manage billing)
15
+ * - Main navigation from the `nav` prop (<nav aria-label="Main">, current route, mobile menu)
16
+ * - Resilience and feedback (#236): error boundary + Suspense around the content,
17
+ * `useToast` region, offline banner, skip link, nav-item titles, and scroll +
18
+ * focus handling on client-side route changes
12
19
  * - Theme support via CSS custom properties
13
20
  * - Only renders children when all gates pass
14
21
  *
@@ -21,17 +28,37 @@ import { ProProvider } from './provider.js';
21
28
  *
22
29
  * export default function App() {
23
30
  * return (
24
- * <ProShell app={app} appName="Meetup">
31
+ * <ProShell app={app} appName="Meetup" nav={[{ label: 'Events', href: '/' }, { label: 'Groups', href: '/groups' }]}>
25
32
  * <MeetupApp />
26
33
  * </ProShell>
27
34
  * )
28
35
  * }
29
36
  * ```
30
37
  */
31
- export function ProShell({ app, children, appName, allowFree = true, showThemeToggle = true, menuItems, hideTopbar = false, hideFooter = false, renderTopbar, renderFooter, }) {
38
+ export function ProShell({ app, children, appName, nav, renderNav, onNavigate, allowFree = true, showThemeToggle = true, menuItems, hideTopbar = false, hideFooter = false, renderTopbar, renderFooter, renderError, renderLoading, }) {
32
39
  const [user, setUser] = useState(app.auth.user);
33
40
  const [subscription, setSubscription] = useState(null);
34
41
  const [gate, setGate] = useState('loading');
42
+ const [currentPath, setCurrentPath] = useCurrentPath();
43
+ const mainRef = useRef(null);
44
+ const beforeNavigate = useRouteChangeEffects(currentPath, mainRef, onNavigate !== undefined);
45
+ useInsertionEffect(() => {
46
+ if (document.getElementById('pas-shell-css'))
47
+ return;
48
+ const style = document.createElement('style');
49
+ style.id = 'pas-shell-css';
50
+ style.textContent = SHELL_CSS;
51
+ document.head.appendChild(style);
52
+ }, []);
53
+ // A nav item's `title` becomes the tab title on its route. A layout effect runs
54
+ // before every passive effect, so a screen's own useDocumentTitle still wins.
55
+ const navItems = nav ?? [];
56
+ const activeItem = navItems.find((item) => item.href === activeHref(navItems, currentPath));
57
+ const navTitle = activeItem?.title;
58
+ useLayoutEffect(() => {
59
+ if (navTitle)
60
+ document.title = navTitle;
61
+ }, [navTitle, currentPath]);
35
62
  useEffect(() => {
36
63
  app.auth.init();
37
64
  return app.auth.onChange((u) => {
@@ -65,6 +92,24 @@ export function ProShell({ app, children, appName, allowFree = true, showThemeTo
65
92
  return _jsx(GateScreen, { gate: "signed-out", app: app, appName: appName });
66
93
  }
67
94
  const profileMenu = (_jsx(ProfileMenu, { app: app, showThemeToggle: showThemeToggle, children: menuItems?.map((item, i) => (_jsx("button", { onClick: item.onClick, style: menuItemStyle, children: item.label }, i))) }));
95
+ // Client-side navigation goes through the shell, so it knows the route changed
96
+ // (scroll, focus, titles). Without onNavigate, items are plain links.
97
+ const navigate = onNavigate
98
+ ? (href) => {
99
+ beforeNavigate();
100
+ onNavigate(href);
101
+ setCurrentPath(href);
102
+ }
103
+ : undefined;
104
+ const navNode = navItems.length === 0 ? null : renderNav
105
+ ? renderNav({
106
+ items: navItems,
107
+ currentPath,
108
+ onNavigate: navigate ?? ((href) => window.location.assign(href)),
109
+ })
110
+ : navigate
111
+ ? _jsx(NavBar, { items: navItems, currentPath: currentPath, onNavigate: navigate })
112
+ : _jsx(NavBar, { items: navItems });
68
113
  const shellContext = {
69
114
  app,
70
115
  appName,
@@ -73,11 +118,13 @@ export function ProShell({ app, children, appName, allowFree = true, showThemeTo
73
118
  textSizeToggle: _jsx(TextSizeToggle, {}),
74
119
  profileMenu,
75
120
  proBadge: subscription?.status === 'active' ? _jsx(ProBadge, {}) : null,
121
+ nav: navNode,
76
122
  };
77
- const topbar = renderTopbar ? renderTopbar(shellContext) : hideTopbar ? null : (_jsxs("header", { style: styles.topbar, children: [_jsxs("div", { style: styles.topbarLeft, children: [_jsx("a", { href: "https://proappstore.online", style: styles.logoLink, children: "Pro" }), appName && _jsx("span", { style: styles.appName, children: appName }), shellContext.proBadge] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [shellContext.textSizeToggle, shellContext.profileMenu] })] }));
123
+ const topbar = renderTopbar ? renderTopbar(shellContext) : hideTopbar ? null : (_jsxs("header", { style: styles.topbar, children: [_jsxs("div", { style: styles.topbarLeft, children: [_jsx("a", { href: "https://proappstore.online", style: styles.logoLink, children: "Pro" }), appName && _jsx("span", { style: styles.appName, children: appName }), shellContext.proBadge] }), shellContext.nav, _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [shellContext.textSizeToggle, shellContext.profileMenu] })] }));
78
124
  const footer = renderFooter ? renderFooter(shellContext) : hideFooter ? null : (_jsxs("footer", { style: styles.footer, children: ["Part of", ' ', _jsx("a", { href: "https://proappstore.online", style: { color: 'var(--accent)', fontWeight: 600, textDecoration: 'none' }, children: "ProAppStore" })] }));
125
+ const loading = renderLoading ? renderLoading() : (_jsx("div", { className: "pas-shell-loading flex flex-1 items-center justify-center px-4 py-12", children: _jsx(Spinner, { size: 28 }) }));
79
126
  // --- Ready: render app with topbar ---
80
- return (_jsx(ProProvider, { app: app, children: _jsxs("div", { style: styles.shell, children: [topbar, _jsx("main", { style: styles.main, children: children }), footer] }) }));
127
+ return (_jsx(ProProvider, { app: app, children: _jsx(ToastProvider, { children: _jsxs("div", { style: styles.shell, children: [_jsx(SkipLink, { mainRef: mainRef }), topbar, _jsx(OfflineBanner, {}), _jsx("main", { id: "main", ref: mainRef, tabIndex: -1, className: "pas-main", style: styles.main, children: _jsx(ShellErrorBoundary, { app: app, renderError: renderError, resetKey: currentPath, children: _jsx(Suspense, { fallback: loading, children: children }) }) }), footer] }) }) }));
81
128
  }
82
129
  const menuItemStyle = {
83
130
  display: 'block', width: '100%', padding: '0.5rem 1rem',
package/dist/shell.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.tsx"],"names":[],"mappings":"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"}
package/dist/ui.d.ts CHANGED
@@ -17,4 +17,10 @@ export { GateScreen } from './ui-gate.js';
17
17
  export type { GateScreenProps } from './ui-gate.js';
18
18
  export { Button, Card, Input, Spinner, Modal, EmptyState, Tabs, Toast } from './ui-base.js';
19
19
  export type { ButtonProps, ButtonVariant, CardProps, InputProps, SpinnerProps, ModalProps, EmptyStateProps, TabItem, TabsProps, ToastProps, ToastVariant, } from './ui-base.js';
20
+ export { NavBar } from './navbar.js';
21
+ export type { NavBarProps, NavItem } from './navbar.js';
22
+ export { useToast, useOnline } from './shell-resilience.js';
23
+ export type { ToastApi, ToastOptions, ShellToastVariant } from './shell-resilience.js';
24
+ export { PageHeader, useDocumentTitle } from './page.js';
25
+ export type { PageHeaderProps } from './page.js';
20
26
  //# sourceMappingURL=ui.d.ts.map
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChH,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC5F,YAAY,EACV,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAC3E,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,GAC9D,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChH,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGhE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC5F,YAAY,EACV,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAC3E,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,GAC9D,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
package/dist/ui.js CHANGED
@@ -17,4 +17,9 @@ export { ProProfilePage } from './ui-profile-page.js';
17
17
  export { GateScreen } from './ui-gate.js';
18
18
  // General-purpose primitives (Button, Card, Input, Modal, Spinner, Tabs, Toast, EmptyState)
19
19
  export { Button, Card, Input, Spinner, Modal, EmptyState, Tabs, Toast } from './ui-base.js';
20
+ // NavBar (#235) — the app's main navigation; ProShell renders it from its `nav` prop
21
+ export { NavBar } from './navbar.js';
22
+ // Shell feedback + page helpers (#236) — useToast needs <ProShell>; the rest work anywhere
23
+ export { useToast, useOnline } from './shell-resilience.js';
24
+ export { PageHeader, useDocumentTitle } from './page.js';
20
25
  //# sourceMappingURL=ui.js.map
package/dist/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4BAA4B;AAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzE,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAShH,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,iBAAiB;AACjB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,4FAA4F;AAC5F,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4BAA4B;AAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzE,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAShH,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,iBAAiB;AACjB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,4FAA4F;AAC5F,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAM5F,qFAAqF;AACrF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,2FAA2F;AAC3F,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proappstore/sdk",
3
- "version": "1.16.56",
3
+ "version": "1.16.58",
4
4
  "description": "Browser SDK for paid apps on proappstore.online — subscriptions, license keys, premium modules.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,8 @@
22
22
  "./ui": {
23
23
  "types": "./dist/ui.d.ts",
24
24
  "import": "./dist/ui.js"
25
- }
25
+ },
26
+ "./shell.css": "./dist/shell.css"
26
27
  },
27
28
  "repository": {
28
29
  "type": "git",
@@ -43,12 +44,14 @@
43
44
  },
44
45
  "devDependencies": {
45
46
  "@types/react": "^19.0.0",
47
+ "@types/react-dom": "^19.3.0",
46
48
  "react": "^19.0.0",
49
+ "react-dom": "19.2.6",
47
50
  "typescript": "^5.7.0"
48
51
  },
49
52
  "sideEffects": false,
50
53
  "scripts": {
51
- "build": "tsc",
54
+ "build": "tsc && node scripts/emit-shell-css.mjs",
52
55
  "typecheck": "tsc --noEmit"
53
56
  }
54
57
  }