@sigmela/router 0.4.0 → 0.6.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 CHANGED
@@ -4,6 +4,37 @@ All notable changes to this package are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
5
5
  [semantic versioning](https://semver.org/).
6
6
 
7
+ ## 0.6.0
8
+
9
+ ### Added
10
+
11
+ - `Router.Protected` supports an undecided guard: `when` accepts `'pending'`
12
+ (and `undefined`), which holds the matched URL and renders the new `pending`
13
+ node instead of redirecting. Apps that gate routes on asynchronously loaded
14
+ context can now keep deep links through boot; previously the only way to say
15
+ "not yet" was `false`, which redirected the visitor away.
16
+ - `RouterGuardState` is exported for typing guard values.
17
+
18
+ ### Notes
19
+
20
+ - Existing `when={boolean}` guards are unaffected: `true` renders, `false`
21
+ redirects, exactly as before.
22
+
23
+ ## 0.5.0
24
+
25
+ ### Added
26
+
27
+ - `Sheet` accepts `presentation="fullscreen"`, turning a bottom sheet into a
28
+ full-height surface (header switches to the modal shape, dismissal measures
29
+ the viewport). Sheets stay content-sized by default.
30
+
31
+ - Public exports for the overlay surface: `Sheet`, `SheetFrame`,
32
+ `useModalSwipeTarget`, `useSheetDragEngine`, `sheetDragStartsInInteractiveControl`,
33
+ `sheetScrollAtTop` and `SheetDragUpdate`. Previously only `Modal`/`ModalFrame`
34
+ were reachable, so apps could route to a sheet but not build its body.
35
+ - `example/`: a Vite sandbox covering stacks, overlays, tab bar, drawer,
36
+ split view and guards (`npm run example`).
37
+
7
38
  ## 0.1.0
8
39
 
9
40
  First standalone release, extracted from the Sigmela merchant web app.
package/README.md CHANGED
@@ -42,15 +42,24 @@ Styles ship with the bundle: `dist/index.js` imports `router.css`, so bundlers
42
42
  that handle CSS from dependencies (Vite, webpack, Next, Parcel) pick it up
43
43
  automatically — no extra import needed.
44
44
 
45
- Environments without a CSS loader — plain Node, `vitest` with the `node`
46
- environment, some SSR pipelines — cannot resolve that import. Alias or stub
47
- `@sigmela/router/router.css` there, and load the stylesheet explicitly on the
48
- client:
45
+ Environments without a CSS loader — plain Node, some SSR pipelines — cannot
46
+ resolve that import. Load the stylesheet explicitly there:
49
47
 
50
48
  ```ts
51
49
  import '@sigmela/router/router.css';
52
50
  ```
53
51
 
52
+ For Vitest with the `node` environment, inline the package so Vite handles the
53
+ CSS import instead of Node:
54
+
55
+ ```ts
56
+ // vitest.config.ts
57
+ test: {
58
+ environment: 'node',
59
+ server: { deps: { inline: [/@sigmela\/router/] } },
60
+ }
61
+ ```
62
+
54
63
  ## Route primitives
55
64
 
56
65
  | Element | Purpose |
@@ -60,7 +69,7 @@ import '@sigmela/router/router.css';
60
69
  | `Router.Redirect` | Declarative redirect |
61
70
  | `Router.Modal` | Full-cover or content-sized overlay above the current screen |
62
71
  | `Router.Sheet` | Bottom sheet, content-sized or fullscreen |
63
- | `Router.TabBar` / `Router.TabBarItem` | Tab navigation with per-tab stacks |
72
+ | `Router.TabBar` / `Router.TabBarItem` | Tab navigation; selecting a tab routes to its root path |
64
73
  | `Router.Drawer` / `Router.DrawerGroup` / `Router.DrawerSection` / `Router.DrawerItem` | Persistent side navigation |
65
74
  | `Router.SplitView` | Primary/secondary panes above a width breakpoint |
66
75
  | `Router.Protected` | Guarded subtree with a redirect target |
@@ -101,6 +110,38 @@ function ProductDetail({ product }) {
101
110
  }
102
111
  ```
103
112
 
113
+ ### Guards that are not decided yet
114
+
115
+ `Router.Protected` answers three states, not two. A guard whose `when` is
116
+ `false` redirects; a guard that is still resolving — `'pending'`, or
117
+ `undefined` so `when={user?.isAdmin}` works before the user loads — **holds the
118
+ URL** and renders its `pending` node instead of the subtree:
119
+
120
+ ```tsx
121
+ <Router.Protected
122
+ when={contextLoading ? 'pending' : isReady}
123
+ redirectTo="/home"
124
+ pending={<AppLoadingScreen />}
125
+ >
126
+ <Router.Screen path="/catalog/products" element={ProductsScreen} />
127
+ </Router.Protected>
128
+ ```
129
+
130
+ This is what keeps deep links alive while an app boots. Without it a guard has
131
+ to answer `false` while it is still loading, which redirects the visitor away
132
+ from the URL they opened — and a catch-all loading screen cannot rescue it,
133
+ because the guarded route is the more specific match.
134
+
135
+ Semantics worth knowing:
136
+
137
+ - Guards resolve outside-in; the first one that is not `true` decides. An
138
+ undecided outer guard defers a later denial, since it is not yet known
139
+ whether that guard would even be reached.
140
+ - A denial always wins immediately, including on a screen that is already
141
+ open — revoking access redirects right away.
142
+ - A guard that turns undecided again while its screen is on-screen keeps that
143
+ screen rendered rather than flashing the pending node.
144
+
104
145
  ## Hooks
105
146
 
106
147
  | Hook | Returns |
@@ -150,6 +191,23 @@ The router owns navigation, overlay surfaces and their gestures. It never
150
191
  imports application features, i18n, data layers or design-system components —
151
192
  screens and layouts are supplied by the host app as JSX.
152
193
 
194
+ ## Sandbox
195
+
196
+ `example/` is a Vite playground that exercises every primitive against the
197
+ router source, with hot reload:
198
+
199
+ ```bash
200
+ npm install
201
+ npm run example # http://localhost:5180
202
+ ```
203
+
204
+ It has three shells you can switch between: **Stack & overlays** (pushes,
205
+ params, search params, fullscreen and content-sized modals, a sheet, and a
206
+ modal owning its own three-step stack), **Tab bar** (per-tab routes, history
207
+ state), and **Drawer & split** (drawer groups and sections, a split view, and a
208
+ guarded route). `example/src/theme.css` shows the `--router-*` tokens driving
209
+ the whole look.
210
+
153
211
  ## Development
154
212
 
155
213
  ```bash
@@ -158,6 +216,7 @@ npm run typecheck
158
216
  npm test # 58 contract tests
159
217
  npm run lint
160
218
  npm run build # dist/index.js + dist/router.css + type declarations
219
+ npm run example # Vite sandbox on the source
161
220
  ```
162
221
 
163
222
  `ROUTER_CONTRACT.md` documents the invariants the contract tests protect.
package/dist/Router.d.ts CHANGED
@@ -10,6 +10,13 @@ export interface RouterNavigateOptions {
10
10
  export type RouterNavigateFunction = (to: string | number, options?: RouterNavigateOptions) => void;
11
11
  export type RouterReplaceFunction = (to: string, options?: RouterNavigateOptions) => void;
12
12
  type RouterGuardValue<T> = T | ((props: RouterRouteRenderProps) => T);
13
+ /**
14
+ * A guard answers one of three things: allowed, denied, or not decided yet.
15
+ * `'pending'` (and `undefined`, so `when={user?.isAdmin}` works before the user
16
+ * loads) holds the URL and renders the guard's `pending` node — it must not
17
+ * redirect, or every deep link would be lost while the app boots.
18
+ */
19
+ export type RouterGuardState = boolean | 'pending';
13
20
  export type RouterSplitPane = 'primary' | 'secondary';
14
21
  export interface RouterRouteRenderProps {
15
22
  params: DefaultParams;
@@ -124,8 +131,10 @@ export interface RouterSplitViewProps extends RouterRouteProps {
124
131
  }
125
132
  export type RouterSplitViewSlotProps = RouterRouteProps;
126
133
  export interface RouterProtectedProps extends RouterRouteProps {
127
- when: RouterGuardValue<boolean>;
134
+ when: RouterGuardValue<RouterGuardState | undefined>;
128
135
  redirectTo: RouterGuardValue<string>;
136
+ /** Rendered instead of the subtree while `when` is undecided. */
137
+ pending?: ReactNode;
129
138
  }
130
139
  export interface RouterRedirectProps extends RouterRouteProps {
131
140
  to: RouterGuardValue<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  import { type CSSProperties, type ReactNode } from 'react';
2
2
  import type { RouterShellMode } from '../types';
3
3
  type SheetVariant = 'attached' | 'detached';
4
+ type SheetPresentation = 'content' | 'fullscreen';
4
5
  interface SheetProps {
5
6
  children: ReactNode;
6
7
  disableDismiss?: boolean;
7
8
  onRequestClose?: () => void;
8
9
  variant?: SheetVariant;
10
+ /** 'fullscreen' turns the sheet into a full-height surface. */
11
+ presentation?: SheetPresentation;
9
12
  }
10
13
  interface SheetFrameProps {
11
14
  children: ReactNode;
@@ -17,7 +20,7 @@ interface SheetFrameProps {
17
20
  activeContentKey?: string;
18
21
  }
19
22
  export declare function SheetFrame({ children, open, onRequestClose, onExitComplete, zIndex, shell, activeContentKey, }: SheetFrameProps): import("react/jsx-runtime").JSX.Element;
20
- declare function SheetRoot({ children, disableDismiss, onRequestClose, variant, }: SheetProps): import("react/jsx-runtime").JSX.Element;
23
+ declare function SheetRoot({ children, disableDismiss, onRequestClose, variant, presentation, }: SheetProps): import("react/jsx-runtime").JSX.Element;
21
24
  interface SheetHeaderProps {
22
25
  title?: string;
23
26
  leftAction?: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"Sheet.d.ts","sourceRoot":"","sources":["../../src/components/Sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,KAAK,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AA0B5C,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAOD,UAAU,eAAe;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,cAAc,EACd,MAAM,EACN,KAA0B,EAC1B,gBAA8C,GAC/C,EAAE,eAAe,2CAkJjB;AAED,iBAAS,SAAS,CAAC,EACjB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,OAAoB,GACrB,EAAE,UAAU,2CAUZ;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,UAAU,EACV,WAAW,EACX,eAAe,EACf,MAAa,EACb,KAAe,GAChB,EAAE,gBAAgB,2CAuBlB;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAE/D;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,iBAAS,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,oBAAoB,2CAgB5E;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAa7D;AAED,eAAO,MAAM,KAAK;;;;;CAKhB,CAAC"}
1
+ {"version":3,"file":"Sheet.d.ts","sourceRoot":"","sources":["../../src/components/Sheet.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,KAAK,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAC5C,KAAK,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;AA4BlD,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAOD,UAAU,eAAe;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,cAAc,EACd,MAAM,EACN,KAA0B,EAC1B,gBAA8C,GAC/C,EAAE,eAAe,2CA+KjB;AAED,iBAAS,SAAS,CAAC,EACjB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,OAAoB,EACpB,YAAwB,GACzB,EAAE,UAAU,2CAsBZ;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC5B;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,UAAU,EACV,WAAW,EACX,eAAe,EACf,MAAa,EACb,KAAe,GAChB,EAAE,gBAAgB,2CA2BlB;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,iBAAiB,2CAE/D;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,iBAAS,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,oBAAoB,2CAgB5E;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAa7D;AAED,eAAO,MAAM,KAAK;;;;;CAKhB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { Router, useCurrentModal, useCurrentRoute, useDrawer, useHistoryState, useParams, useRoute, useRouter, useSearchParams, type CurrentModalApi, type RouterDrawerApi, type RouterDrawerGroup, type RouterDrawerGroupProps, type RouterDrawerItem, type RouterDrawerItemProps, type RouterDrawerNode, type RouterDrawerSection, type RouterDrawerSectionProps, type RouterDrawerProps, type RouterApi, type RouterNavigateFunction, type RouterReplaceFunction, type RouterRedirectProps, type RouterRouteContextValue, type RouterRouteLayoutProps, type RouterProtectedProps, type RouterRouteRenderProps, type RouterScreenAnimation, type RouterSplitPane, type RouterSplitViewProps, type RouterSplitViewSlotProps, type RouterTabBarTab, } from './Router';
1
+ export { Router, useCurrentModal, useCurrentRoute, useDrawer, useHistoryState, useParams, useRoute, useRouter, useSearchParams, type CurrentModalApi, type RouterDrawerApi, type RouterDrawerGroup, type RouterDrawerGroupProps, type RouterDrawerItem, type RouterDrawerItemProps, type RouterDrawerNode, type RouterDrawerSection, type RouterDrawerSectionProps, type RouterDrawerProps, type RouterGuardState, type RouterApi, type RouterNavigateFunction, type RouterReplaceFunction, type RouterRedirectProps, type RouterRouteContextValue, type RouterRouteLayoutProps, type RouterProtectedProps, type RouterRouteRenderProps, type RouterScreenAnimation, type RouterSplitPane, type RouterSplitViewProps, type RouterSplitViewSlotProps, type RouterTabBarTab, } from './Router';
2
2
  export type { RouterShellMode } from './types';
3
3
  export type { RouterOverlayLayout } from './types';
4
- export { Modal, ModalFrame } from './components';
4
+ export { Modal, ModalFrame, Sheet, SheetFrame, useModalSwipeTarget, useSheetDragEngine, sheetDragStartsInInteractiveControl, sheetScrollAtTop, type SheetDragUpdate, } from './components';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,eAAe,EACf,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,eAAe,EACf,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,GACrB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mCAAmC,EACnC,gBAAgB,EAChB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -35,6 +35,14 @@ var SHEET_DRAG_START_DISTANCE = 2;
35
35
  function sheetScrollAtTop(el) {
36
36
  return !el || el.scrollTop <= SHEET_DRAG_EPS;
37
37
  }
38
+ function sheetDragStartsInInteractiveControl(target) {
39
+ if (!(target instanceof Element)) return false;
40
+ return Boolean(
41
+ target.closest(
42
+ 'button,a,input,textarea,select,[role="button"],[data-sheet-drag-ignore="true"]'
43
+ )
44
+ );
45
+ }
38
46
  function sheetDragStartsInTextInput(target) {
39
47
  if (!(target instanceof Element)) return false;
40
48
  return Boolean(
@@ -643,6 +651,8 @@ function SheetFrame({
643
651
  const disableDismiss = options?.disableDismiss ?? false;
644
652
  const customRequestClose = options?.onRequestClose;
645
653
  const variant = options?.variant ?? "detached";
654
+ const presentation = options?.presentation ?? "content";
655
+ const fullscreen = presentation === "fullscreen";
646
656
  const requestClose = useCallback(() => {
647
657
  if (disableDismiss) return;
648
658
  if (customRequestClose) {
@@ -657,12 +667,34 @@ function SheetFrame({
657
667
  close: requestClose,
658
668
  canClose: !disableDismiss,
659
669
  variant,
670
+ presentation,
660
671
  setOptions
661
672
  }),
662
- [requestClose, disableDismiss, setScrollElement, setOptions, variant]
673
+ [
674
+ requestClose,
675
+ disableDismiss,
676
+ presentation,
677
+ setScrollElement,
678
+ setOptions,
679
+ variant
680
+ ]
663
681
  );
664
682
  const surfaceStyle = useMemo(
665
- () => variant === "detached" ? {
683
+ () => fullscreen ? {
684
+ backgroundColor: "var(--router-bg)",
685
+ borderRadius: "33px 33px 0 0",
686
+ boxShadow: "var(--router-card-shadow)",
687
+ color: "var(--router-text)",
688
+ overflow: "hidden",
689
+ bottom: 0,
690
+ left: 0,
691
+ right: 0,
692
+ width: "100%",
693
+ maxWidth: "var(--router-container)",
694
+ height: "calc(100dvh - env(safe-area-inset-top, 0px))",
695
+ maxHeight: "none",
696
+ marginInline: "auto"
697
+ } : variant === "detached" ? {
666
698
  backgroundColor: "var(--router-bg)",
667
699
  borderRadius: "28px 28px 32px 32px",
668
700
  boxShadow: "var(--router-card-shadow)",
@@ -690,7 +722,7 @@ function SheetFrame({
690
722
  bottom: 0,
691
723
  maxHeight: "calc(100dvh - env(safe-area-inset-top, 0px))"
692
724
  },
693
- [variant]
725
+ [fullscreen, variant]
694
726
  );
695
727
  const backdropStyle = useMemo(
696
728
  () => shell === "desktop-fullscreen" ? {
@@ -721,11 +753,12 @@ function SheetFrame({
721
753
  surfaceClassName: "router-sheet-surface",
722
754
  surfaceStyle,
723
755
  scrollElement,
756
+ closeTarget: fullscreen ? "viewport" : "surface",
724
757
  children: /* @__PURE__ */ jsx(
725
758
  "div",
726
759
  {
727
760
  ref: setFrameScrollElement,
728
- className: "router-scroll router-sheet-frame-scroll",
761
+ className: `router-scroll router-sheet-frame-scroll${fullscreen ? " router-sheet-frame-scroll--fullscreen" : ""}`,
729
762
  children
730
763
  }
731
764
  )
@@ -736,14 +769,27 @@ function SheetRoot({
736
769
  children,
737
770
  disableDismiss,
738
771
  onRequestClose,
739
- variant = "detached"
772
+ variant = "detached",
773
+ presentation = "content"
740
774
  }) {
741
775
  const { setOptions } = useSheetContext();
742
776
  const contentKey = useOverlayContentKey();
743
777
  useLayoutEffect(() => {
744
- setOptions(contentKey, { disableDismiss, onRequestClose, variant });
778
+ setOptions(contentKey, {
779
+ disableDismiss,
780
+ onRequestClose,
781
+ variant,
782
+ presentation
783
+ });
745
784
  return () => setOptions(contentKey, null);
746
- }, [contentKey, disableDismiss, onRequestClose, setOptions, variant]);
785
+ }, [
786
+ contentKey,
787
+ disableDismiss,
788
+ onRequestClose,
789
+ presentation,
790
+ setOptions,
791
+ variant
792
+ ]);
747
793
  return /* @__PURE__ */ jsx(Fragment, { children });
748
794
  }
749
795
  function SheetHeader({
@@ -754,8 +800,9 @@ function SheetHeader({
754
800
  sticky = true,
755
801
  align = "start"
756
802
  }) {
757
- const { close, canClose } = useSheetContext();
758
- const headerClassName = `router-sheet-header${sticky ? " router-sheet-header--sticky" : ""}`;
803
+ const { close, canClose, presentation } = useSheetContext();
804
+ const headerBaseClassName = presentation === "fullscreen" ? "router-modal-header" : "router-sheet-header";
805
+ const headerClassName = `${headerBaseClassName}${sticky ? ` ${headerBaseClassName}--sticky` : ""}`;
759
806
  const titleClassName = `router-sheet-title${align === "center" ? " router-sheet-title--center" : ""}`;
760
807
  return /* @__PURE__ */ jsxs("div", { className: headerClassName, children: [
761
808
  leftAction != null && /* @__PURE__ */ jsx("div", { className: "router-sheet-header-side", children: leftAction }),
@@ -795,7 +842,7 @@ function SheetFooter({ children, className }) {
795
842
  }
796
843
  );
797
844
  }
798
- Object.assign(SheetRoot, {
845
+ var Sheet = Object.assign(SheetRoot, {
799
846
  Header: SheetHeader,
800
847
  Content: SheetContent,
801
848
  ScrollView: SheetScrollView,
@@ -1188,7 +1235,8 @@ function compileStackRoutes(children, parentPath, parentId = "root", inheritedGu
1188
1235
  const guard = {
1189
1236
  id: props.id ?? routeId,
1190
1237
  when: child.props.when,
1191
- redirectTo: child.props.redirectTo
1238
+ redirectTo: child.props.redirectTo,
1239
+ pending: child.props.pending
1192
1240
  };
1193
1241
  if (routeChildren.length > 0) {
1194
1242
  routes.push(
@@ -1587,16 +1635,25 @@ function routeRenderPropsForMatch(pathname, search, historyState, match) {
1587
1635
  function resolveGuardValue(value, props) {
1588
1636
  return typeof value === "function" ? value(props) : value;
1589
1637
  }
1590
- function guardRedirectForMatch(match, pathname, search, historyState) {
1638
+ var GUARD_ALLOW = { status: "allow" };
1639
+ function resolveRouteGuard(match, pathname, search, historyState) {
1591
1640
  const props = routeRenderPropsForMatch(pathname, search, historyState, match);
1592
1641
  for (const guard of match.route.guards) {
1593
- if (resolveGuardValue(guard.when, props)) continue;
1594
- return resolveGuardValue(guard.redirectTo, props);
1642
+ const value = resolveGuardValue(guard.when, props);
1643
+ if (value === true) continue;
1644
+ if (value === false) {
1645
+ return { status: "redirect", to: resolveGuardValue(guard.redirectTo, props) };
1646
+ }
1647
+ return { status: "pending", element: guard.pending ?? null };
1595
1648
  }
1596
1649
  if (match.route.redirectTo) {
1597
- return resolveGuardValue(match.route.redirectTo, props);
1650
+ return { status: "redirect", to: resolveGuardValue(match.route.redirectTo, props) };
1598
1651
  }
1599
- return null;
1652
+ return GUARD_ALLOW;
1653
+ }
1654
+ function guardRedirectForMatch(match, pathname, search, historyState) {
1655
+ const outcome = resolveRouteGuard(match, pathname, search, historyState);
1656
+ return outcome.status === "redirect" ? outcome.to : null;
1600
1657
  }
1601
1658
  var PUSH_PRESENTATIONS = /* @__PURE__ */ new Set(["push"]);
1602
1659
  var OVERLAY_PRESENTATIONS = /* @__PURE__ */ new Set(["modal", "sheet"]);
@@ -3011,11 +3068,27 @@ function RouterRuntime({
3011
3068
  };
3012
3069
  }, [shell]);
3013
3070
  const searchPath = search ? `?${search}` : "";
3014
- const guardRedirect = useMemo(
3015
- () => rawMatch ? guardRedirectForMatch(rawMatch, pathname, searchPath, historyState) : null,
3071
+ const guardOutcome = useMemo(
3072
+ () => rawMatch ? resolveRouteGuard(rawMatch, pathname, searchPath, historyState) : null,
3016
3073
  [historyState, pathname, rawMatch, searchPath]
3017
3074
  );
3018
- const match = guardRedirect ? null : rawMatch;
3075
+ const guardRedirect = guardOutcome?.status === "redirect" ? guardOutcome.to : null;
3076
+ const matchedRoute = guardRedirect ? null : rawMatch;
3077
+ const match = useMemo(() => {
3078
+ if (!matchedRoute) return null;
3079
+ if (guardOutcome?.status !== "pending") return matchedRoute;
3080
+ return {
3081
+ ...matchedRoute,
3082
+ route: {
3083
+ ...matchedRoute.route,
3084
+ element: guardOutcome.element,
3085
+ elementType: void 0,
3086
+ component: void 0,
3087
+ layout: void 0,
3088
+ overlayLayout: void 0
3089
+ }
3090
+ };
3091
+ }, [guardOutcome, matchedRoute]);
3019
3092
  useLayoutEffect(() => {
3020
3093
  if (!guardRedirect) return;
3021
3094
  const target = parseNavigationTarget(guardRedirect, pathname);
@@ -3644,6 +3717,6 @@ var Router = Object.assign(RouterRoot, {
3644
3717
  Protected: RouterProtected
3645
3718
  });
3646
3719
 
3647
- export { Modal, ModalFrame, Router, useCurrentModal, useCurrentRoute, useDrawer, useHistoryState, useParams, useRoute, useRouter, useSearchParams };
3720
+ export { Modal, ModalFrame, Router, Sheet, SheetFrame, sheetDragStartsInInteractiveControl, sheetScrollAtTop, useCurrentModal, useCurrentRoute, useDrawer, useHistoryState, useModalSwipeTarget, useParams, useRoute, useRouter, useSearchParams, useSheetDragEngine };
3648
3721
  //# sourceMappingURL=index.js.map
3649
3722
  //# sourceMappingURL=index.js.map