@sigmela/router 0.8.0 → 0.9.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 +20 -1
- package/README.md +30 -0
- package/dist/Router.d.ts.map +1 -1
- package/dist/components/Modal.d.ts +6 -2
- package/dist/components/Modal.d.ts.map +1 -1
- package/dist/components/SheetSurface.d.ts +4 -1
- package/dist/components/SheetSurface.d.ts.map +1 -1
- package/dist/index.js +102 -40
- package/dist/index.js.map +1 -1
- package/dist/router.css +34 -0
- package/dist/utils/useMediaQuery.d.ts +5 -0
- package/dist/utils/useMediaQuery.d.ts.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,26 @@ 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
|
-
##
|
|
7
|
+
## 0.9.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `presentation="right"` on `Modal`: a right-side panel at 640px and wider.
|
|
12
|
+
It anchors to the viewport's right edge in either shell mode, fills the
|
|
13
|
+
height minus an 18px margin, slides in and out from the right (300ms) over
|
|
14
|
+
the dimmed backdrop, and closes on backdrop click, Escape or the header
|
|
15
|
+
button. `width` sets its width (default 393px, clamped to the viewport).
|
|
16
|
+
Below 640px it is the regular fullscreen modal, swipe-down included. Modal
|
|
17
|
+
flows (`Router.Modal` with child screens) push inside the panel. With
|
|
18
|
+
`prefers-reduced-motion` it appears and leaves without sliding. This brings
|
|
19
|
+
back the `modalRight` presentation dropped in the 0.4.0 rewrite.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- The modal backdrop positions itself in `router.css` instead of relying on
|
|
24
|
+
Tailwind utility classes, so it covers the shell in apps without Tailwind.
|
|
25
|
+
|
|
26
|
+
## 0.8.0
|
|
8
27
|
|
|
9
28
|
### Added
|
|
10
29
|
|
package/README.md
CHANGED
|
@@ -128,6 +128,36 @@ content overflow a fixed 600px or 860px frame:
|
|
|
128
128
|
</Modal>
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
### Right-side panel
|
|
132
|
+
|
|
133
|
+
`presentation="right"` turns the modal into a side panel at 640px and wider:
|
|
134
|
+
anchored to the right edge of the viewport (in either shell mode), full height
|
|
135
|
+
with an 18px margin, sliding in and out from the right over a dimmed backdrop.
|
|
136
|
+
`width` sets the panel width (default 393px, clamped to the viewport); `height`
|
|
137
|
+
and `size` are ignored. Backdrop click, Escape and the header close button
|
|
138
|
+
dismiss it; there is no swipe. Below 640px it is the regular fullscreen modal,
|
|
139
|
+
swipe-down included. With reduced motion the panel appears and leaves without
|
|
140
|
+
sliding.
|
|
141
|
+
|
|
142
|
+
Declare it from any screen's content. In a modal flow every step declares its
|
|
143
|
+
own options, so give each step the same presentation:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
<Router.Modal path="cart">
|
|
147
|
+
<Router.Screen element={CartScreen} />
|
|
148
|
+
<Router.Screen path="checkout" element={CheckoutScreen} />
|
|
149
|
+
</Router.Modal>
|
|
150
|
+
|
|
151
|
+
function CartScreen() {
|
|
152
|
+
return (
|
|
153
|
+
<Modal presentation="right" width={460} ariaLabel="Cart">
|
|
154
|
+
<Modal.Header title="Cart" />
|
|
155
|
+
{/* … */}
|
|
156
|
+
</Modal>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
131
161
|
### Guards that are not decided yet
|
|
132
162
|
|
|
133
163
|
`Router.Protected` answers three states, not two. A guard whose `when` is
|
package/dist/Router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,EAeL,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,GAAG,EAER,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../src/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,EAeL,KAAK,aAAa,EAElB,KAAK,WAAW,EAChB,KAAK,GAAG,EAER,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,QAAQ,CAAC;AAUhB,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,cAAc,CAAC;AAGtB,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAC3D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAgBjE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AASD,MAAM,MAAM,sBAAsB,GAAG,CACnC,EAAE,EAAE,MAAM,GAAG,MAAM,EACnB,OAAO,CAAC,EAAE,qBAAqB,KAC5B,IAAI,CAAC;AACV,MAAM,MAAM,qBAAqB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAC1F,KAAK,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,sBAAsB,KAAK,CAAC,CAAC,CAAC;AACtE;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAC;AACnD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,WAAW,CAAC;AA6BtD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,iBAAiB,CAAC;IAChC,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,YAAY,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GACxB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,CAAC;AAExB,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,eAAe,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,KAAK,mBAAmB,GAAG,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,sBAAsB,KAAK,SAAS,CAAC,CAAC;AAEtF,KAAK,kBAAkB,GAAG,SAAS,GAAG,WAAW,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,sBAAsB,KAAK,MAAM,CAAC,CAAC;IAChE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC,sBAAsB,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC1C,2EAA2E;IAC3E,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,wBAAwB,GAAG,gBAAgB,CAAC;AAExD,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC5D,IAAI,EAAE,gBAAgB,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;IACrD,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC,iEAAiE;IACjE,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,EAAE,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,sBAAsB,CAAC;IACjC,mFAAmF;IACnF,OAAO,EAAE,qBAAqB,CAAC;IAC/B,gFAAgF;IAChF,KAAK,EAAE,qBAAqB,CAAC;IAC7B,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,WAAW,GAAG,MAAM,CAAC;IACzC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAUD,UAAU,eAAe;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AA4xDD,wBAAgB,QAAQ,IAAI,uBAAuB,CAMlD;AAED,wBAAgB,eAAe,IAAI,uBAAuB,CAEzD;AAED,wBAAgB,SAAS,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,KAAK,OAAO,CAElF;AAED,wBAAgB,eAAe,IAAI,eAAe,CAEjD;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAG,OAAO,KAAK,MAAM,CAE1D;AAED,wBAAgB,SAAS,IAAI,SAAS,CAoCrC;AAED,wBAAgB,SAAS,IAAI,eAAe,CAM3C;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,0GAA0G;IAC1G,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,6GAA6G;IAC7G,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,wBAAgB,eAAe,IAAI,eAAe,CAMjD;AAwnED,iBAAS,UAAU,CAAC,KAAK,EAAE,eAAe,2CAUzC;AAiCD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;CAcjB,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
2
|
import type { RouterShellMode } from '../types';
|
|
3
3
|
export declare function useModalSwipeTarget(): (el: HTMLElement | null) => void;
|
|
4
|
-
type ModalPresentation = 'fullscreen' | 'content';
|
|
4
|
+
type ModalPresentation = 'fullscreen' | 'content' | 'right';
|
|
5
5
|
interface ModalProps {
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
swipeToClose?: boolean;
|
|
@@ -10,7 +10,11 @@ interface ModalProps {
|
|
|
10
10
|
/** Desired desktop surface size; the viewport still constrains it. */
|
|
11
11
|
width?: number;
|
|
12
12
|
height?: number;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* 'content' sizes the surface to its content, floored at half the viewport.
|
|
15
|
+
* 'right' is a full-height side panel on desktop (>= 640px); below that it
|
|
16
|
+
* is the regular fullscreen modal.
|
|
17
|
+
*/
|
|
14
18
|
presentation?: ModalPresentation;
|
|
15
19
|
}
|
|
16
20
|
interface ModalFrameProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/components/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAQf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAqBhD,wBAAgB,mBAAmB,IAAI,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAOtE;AAED,KAAK,iBAAiB,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5D,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAgBD,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,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,cAAc,EACd,MAAM,EACN,KAA0B,EAC1B,YAAoB,EACpB,gBAA8C,GAC/C,EAAE,eAAe,2CA+FjB;AAED,iBAAS,SAAS,CAAC,EACjB,QAAQ,EACR,YAAmB,EACnB,SAAS,EACT,IAAgB,EAChB,KAAK,EACL,MAAM,EACN,YAA2B,GAC5B,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;CAClB;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,UAAU,EACV,WAAW,EACX,eAAe,EACf,MAAa,GACd,EAAE,gBAAgB,2CAelB;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,2CAI/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,2CAW5E;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,2CAQ7D;AAED,eAAO,MAAM,KAAK;;;;;CAKhB,CAAC"}
|
|
@@ -2,6 +2,8 @@ import { type CSSProperties, type ReactNode } from 'react';
|
|
|
2
2
|
import type { RouterShellMode } from '../types';
|
|
3
3
|
export type SheetSurfaceMode = 'content' | 'fullscreen';
|
|
4
4
|
export type SheetSurfaceCloseTarget = 'surface' | 'viewport';
|
|
5
|
+
/** The viewport edge the surface slides in from. Only 'bottom' can be swiped. */
|
|
6
|
+
export type SheetSurfaceEdge = 'bottom' | 'right';
|
|
5
7
|
interface SheetSurfaceProps {
|
|
6
8
|
children: ReactNode;
|
|
7
9
|
open: boolean;
|
|
@@ -21,7 +23,8 @@ interface SheetSurfaceProps {
|
|
|
21
23
|
ariaLabel?: string;
|
|
22
24
|
shell?: RouterShellMode;
|
|
23
25
|
closeTarget?: SheetSurfaceCloseTarget;
|
|
26
|
+
edge?: SheetSurfaceEdge;
|
|
24
27
|
}
|
|
25
|
-
export declare function SheetSurface({ children, open, onRequestClose, onExitComplete, zIndex, mode, canDismiss, swipeToClose, backdrop, backdropClassName, backdropStyle, shellClassName, surfaceClassName, surfaceStyle, scrollElement, ariaLabel, shell, closeTarget, }: SheetSurfaceProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export declare function SheetSurface({ children, open, onRequestClose, onExitComplete, zIndex, mode, canDismiss, swipeToClose, backdrop, backdropClassName, backdropStyle, shellClassName, surfaceClassName, surfaceStyle, scrollElement, ariaLabel, shell, closeTarget, edge, }: SheetSurfaceProps): import("react/jsx-runtime").JSX.Element;
|
|
26
29
|
export {};
|
|
27
30
|
//# sourceMappingURL=SheetSurface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SheetSurface.d.ts","sourceRoot":"","sources":["../../src/components/SheetSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SheetSurface.d.ts","sourceRoot":"","sources":["../../src/components/SheetSurface.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAUf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAUhD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,YAAY,CAAC;AACxD,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,UAAU,CAAC;AAC7D,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElD,UAAU,iBAAiB;IACzB,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,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAcD,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,IAAI,EACJ,cAAc,EACd,cAAc,EACd,MAAM,EACN,IAAI,EACJ,UAAiB,EACjB,YAAmB,EACnB,QAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,KAA0B,EAC1B,WAAuB,EACvB,IAAe,GAChB,EAAE,iBAAiB,2CA+LnB"}
|
package/dist/index.js
CHANGED
|
@@ -236,15 +236,52 @@ function useSheetDragEngine({
|
|
|
236
236
|
targetRef
|
|
237
237
|
]);
|
|
238
238
|
}
|
|
239
|
+
function useMediaQuery(query) {
|
|
240
|
+
const [matches, setMatches] = useState(() => {
|
|
241
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
return window.matchMedia(query).matches;
|
|
245
|
+
});
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const mediaQuery = window.matchMedia(query);
|
|
251
|
+
const handleChange = (event) => setMatches(event.matches);
|
|
252
|
+
setMatches(mediaQuery.matches);
|
|
253
|
+
if (typeof mediaQuery.addEventListener === "function") {
|
|
254
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
255
|
+
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
256
|
+
}
|
|
257
|
+
const mediaQueryWithListener = mediaQuery;
|
|
258
|
+
mediaQueryWithListener.addListener?.(handleChange);
|
|
259
|
+
return () => mediaQueryWithListener.removeListener?.(handleChange);
|
|
260
|
+
}, [query]);
|
|
261
|
+
return matches;
|
|
262
|
+
}
|
|
263
|
+
function useMinWidth(minWidth) {
|
|
264
|
+
return useMediaQuery(`(min-width: ${minWidth}px)`);
|
|
265
|
+
}
|
|
266
|
+
function prefersReducedMotion() {
|
|
267
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
268
|
+
}
|
|
239
269
|
var SHEET_SPRING = { type: "spring", bounce: 0, duration: 0.38 };
|
|
240
270
|
var CLOSE_DISTANCE = 112;
|
|
241
271
|
var CLOSE_VELOCITY = 850;
|
|
242
272
|
var DRAG_START_DISTANCE = 6;
|
|
243
273
|
var PROJECT_VELOCITY_FACTOR = 0.18;
|
|
274
|
+
var SIDE_PANEL_TWEEN = { duration: 0.3, ease: [0.22, 0.61, 0.36, 1] };
|
|
275
|
+
var INSTANT = { duration: 0 };
|
|
244
276
|
function closeTargetY(surface, target) {
|
|
245
277
|
if (target === "viewport") return window.innerHeight + 32;
|
|
246
278
|
return (surface?.getBoundingClientRect().height || window.innerHeight) + 32;
|
|
247
279
|
}
|
|
280
|
+
function closeTargetX(surface, currentX) {
|
|
281
|
+
if (!surface) return window.innerWidth;
|
|
282
|
+
const left = surface.getBoundingClientRect().left - currentX;
|
|
283
|
+
return Math.max(0, window.innerWidth - left) + 32;
|
|
284
|
+
}
|
|
248
285
|
function SheetSurface({
|
|
249
286
|
children,
|
|
250
287
|
open,
|
|
@@ -263,15 +300,20 @@ function SheetSurface({
|
|
|
263
300
|
scrollElement,
|
|
264
301
|
ariaLabel,
|
|
265
302
|
shell = "mobile-contained",
|
|
266
|
-
closeTarget = "surface"
|
|
303
|
+
closeTarget = "surface",
|
|
304
|
+
edge = "bottom"
|
|
267
305
|
}) {
|
|
268
306
|
const surfaceRef = useRef(null);
|
|
269
307
|
const removeRef = useRef(onExitComplete);
|
|
270
308
|
const requestCloseRef = useRef(onRequestClose);
|
|
271
309
|
const closingOffsetRef = useRef(0);
|
|
272
310
|
const closingRef = useRef(false);
|
|
273
|
-
const
|
|
311
|
+
const edgeRef = useRef(edge);
|
|
312
|
+
const enteredRef = useRef(false);
|
|
313
|
+
const y = useMotionValue(edge === "bottom" ? window.innerHeight : 0);
|
|
314
|
+
const x = useMotionValue(edge === "right" ? window.innerWidth : 0);
|
|
274
315
|
removeRef.current = onExitComplete;
|
|
316
|
+
edgeRef.current = edge;
|
|
275
317
|
requestCloseRef.current = onRequestClose;
|
|
276
318
|
usePageScrollLock(true);
|
|
277
319
|
const requestClose = useCallback(
|
|
@@ -286,10 +328,18 @@ function SheetSurface({
|
|
|
286
328
|
(offset = 0) => {
|
|
287
329
|
if (closingRef.current) return;
|
|
288
330
|
closingRef.current = true;
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
331
|
+
const reduced = prefersReducedMotion();
|
|
332
|
+
let controls;
|
|
333
|
+
if (edgeRef.current === "right") {
|
|
334
|
+
x.stop();
|
|
335
|
+
const target = closeTargetX(surfaceRef.current, x.get());
|
|
336
|
+
controls = animate(x, target, reduced ? INSTANT : SIDE_PANEL_TWEEN);
|
|
337
|
+
} else {
|
|
338
|
+
const target = closeTargetY(surfaceRef.current, closeTarget);
|
|
339
|
+
y.stop();
|
|
340
|
+
y.set(Math.max(0, offset));
|
|
341
|
+
controls = animate(y, target, SHEET_SPRING);
|
|
342
|
+
}
|
|
293
343
|
void controls.finished.then(
|
|
294
344
|
() => {
|
|
295
345
|
removeRef.current();
|
|
@@ -299,17 +349,43 @@ function SheetSurface({
|
|
|
299
349
|
}
|
|
300
350
|
);
|
|
301
351
|
},
|
|
302
|
-
[closeTarget, y]
|
|
352
|
+
[closeTarget, x, y]
|
|
303
353
|
);
|
|
304
354
|
useEffect(() => {
|
|
305
355
|
if (!open) {
|
|
306
356
|
closeWithAnimation(closingOffsetRef.current);
|
|
307
357
|
return;
|
|
308
358
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
359
|
+
if (enteredRef.current) {
|
|
360
|
+
x.stop();
|
|
361
|
+
y.stop();
|
|
362
|
+
x.set(0);
|
|
363
|
+
y.set(0);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
let controls;
|
|
367
|
+
if (edge === "right") {
|
|
368
|
+
y.set(0);
|
|
369
|
+
x.set(closeTargetX(surfaceRef.current, 0));
|
|
370
|
+
controls = animate(x, 0, prefersReducedMotion() ? INSTANT : SIDE_PANEL_TWEEN);
|
|
371
|
+
} else {
|
|
372
|
+
x.set(0);
|
|
373
|
+
y.set(window.innerHeight);
|
|
374
|
+
controls = animate(y, 0, SHEET_SPRING);
|
|
375
|
+
}
|
|
376
|
+
let cancelled = false;
|
|
377
|
+
void controls.finished.then(
|
|
378
|
+
() => {
|
|
379
|
+
if (!cancelled) enteredRef.current = true;
|
|
380
|
+
},
|
|
381
|
+
() => {
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
return () => {
|
|
385
|
+
cancelled = true;
|
|
386
|
+
controls.stop();
|
|
387
|
+
};
|
|
388
|
+
}, [closeWithAnimation, edge, open, x, y]);
|
|
313
389
|
useEffect(() => {
|
|
314
390
|
if (!canDismiss || !open) return;
|
|
315
391
|
const handler = (event) => {
|
|
@@ -351,7 +427,7 @@ function SheetSurface({
|
|
|
351
427
|
);
|
|
352
428
|
useSheetDragEngine({
|
|
353
429
|
targetRef: surfaceRef,
|
|
354
|
-
enabled: swipeToClose && canDismiss,
|
|
430
|
+
enabled: swipeToClose && canDismiss && edge === "bottom",
|
|
355
431
|
minDragDistance: DRAG_START_DISTANCE,
|
|
356
432
|
ignoreStartTarget: sheetDragStartsInTextInput,
|
|
357
433
|
shouldStart: shouldStartDrag,
|
|
@@ -387,7 +463,7 @@ function SheetSurface({
|
|
|
387
463
|
{
|
|
388
464
|
ref: surfaceRef,
|
|
389
465
|
className: surfaceClassName,
|
|
390
|
-
style: { ...surfaceStyle, y },
|
|
466
|
+
style: { ...surfaceStyle, x, y },
|
|
391
467
|
role: "dialog",
|
|
392
468
|
"aria-modal": "true",
|
|
393
469
|
"aria-label": ariaLabel,
|
|
@@ -445,6 +521,7 @@ function OverlayContentScope({
|
|
|
445
521
|
function useOverlayContentKey() {
|
|
446
522
|
return useContext(OverlayContentKeyContext);
|
|
447
523
|
}
|
|
524
|
+
var DESKTOP_MIN_WIDTH = 640;
|
|
448
525
|
var ModalContext = createContext(null);
|
|
449
526
|
function useModalContext() {
|
|
450
527
|
const ctx = useContext(ModalContext);
|
|
@@ -509,7 +586,15 @@ function ModalFrame({
|
|
|
509
586
|
const options = activeRegistration?.options;
|
|
510
587
|
const swipeToClose = options?.swipeToClose ?? true;
|
|
511
588
|
const ariaLabel = options?.ariaLabel;
|
|
512
|
-
const
|
|
589
|
+
const isDesktop = useMinWidth(DESKTOP_MIN_WIDTH);
|
|
590
|
+
const isRightPanel = isDesktop && options?.presentation === "right";
|
|
591
|
+
const isContentSized = !isRightPanel && (contentSized || options?.presentation === "content");
|
|
592
|
+
const surfaceClassName = [
|
|
593
|
+
"router-modal-surface",
|
|
594
|
+
isContentSized && "router-modal-surface--content-sized",
|
|
595
|
+
isRightPanel && "router-modal-surface--right",
|
|
596
|
+
!isRightPanel && options?.size === "wide" && "router-modal-surface--wide"
|
|
597
|
+
].filter(Boolean).join(" ");
|
|
513
598
|
const requestClose = useCallback(() => {
|
|
514
599
|
onRequestClose();
|
|
515
600
|
}, [onRequestClose]);
|
|
@@ -529,8 +614,8 @@ function ModalFrame({
|
|
|
529
614
|
shell,
|
|
530
615
|
backdrop: true,
|
|
531
616
|
backdropClassName: `router-modal-backdrop${isContentSized ? " router-modal-backdrop--transparent" : ""}`,
|
|
532
|
-
shellClassName: "router-modal-shell"
|
|
533
|
-
surfaceClassName
|
|
617
|
+
shellClassName: `router-modal-shell${isRightPanel ? " router-modal-shell--right" : ""}`,
|
|
618
|
+
surfaceClassName,
|
|
534
619
|
surfaceStyle: {
|
|
535
620
|
"--router-modal-width": options?.width ? `${options.width}px` : void 0,
|
|
536
621
|
"--router-modal-height": options?.height ? `${options.height}px` : void 0
|
|
@@ -538,6 +623,7 @@ function ModalFrame({
|
|
|
538
623
|
scrollElement: swipeTarget,
|
|
539
624
|
ariaLabel,
|
|
540
625
|
closeTarget: isContentSized ? "surface" : "viewport",
|
|
626
|
+
edge: isRightPanel ? "right" : "bottom",
|
|
541
627
|
children
|
|
542
628
|
}
|
|
543
629
|
) });
|
|
@@ -1999,30 +2085,6 @@ function pathnameForRouteContext(route, fallbackPathname) {
|
|
|
1999
2085
|
}
|
|
2000
2086
|
return normalizedPath(routePath);
|
|
2001
2087
|
}
|
|
2002
|
-
function useMinWidth(minWidth) {
|
|
2003
|
-
const [matches, setMatches] = useState(() => {
|
|
2004
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
2005
|
-
return false;
|
|
2006
|
-
}
|
|
2007
|
-
return window.matchMedia(`(min-width: ${minWidth}px)`).matches;
|
|
2008
|
-
});
|
|
2009
|
-
useEffect(() => {
|
|
2010
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
2011
|
-
return;
|
|
2012
|
-
}
|
|
2013
|
-
const mediaQuery = window.matchMedia(`(min-width: ${minWidth}px)`);
|
|
2014
|
-
const handleChange = (event) => setMatches(event.matches);
|
|
2015
|
-
setMatches(mediaQuery.matches);
|
|
2016
|
-
if (typeof mediaQuery.addEventListener === "function") {
|
|
2017
|
-
mediaQuery.addEventListener("change", handleChange);
|
|
2018
|
-
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
2019
|
-
}
|
|
2020
|
-
const mediaQueryWithListener = mediaQuery;
|
|
2021
|
-
mediaQueryWithListener.addListener?.(handleChange);
|
|
2022
|
-
return () => mediaQueryWithListener.removeListener?.(handleChange);
|
|
2023
|
-
}, [minWidth]);
|
|
2024
|
-
return matches;
|
|
2025
|
-
}
|
|
2026
2088
|
function measuredElementWidth(element) {
|
|
2027
2089
|
return element.getBoundingClientRect().width || element.clientWidth || 0;
|
|
2028
2090
|
}
|