react-layer-kit 1.0.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/README.md +165 -0
- package/dist/components/LayerContext.d.ts +56 -0
- package/dist/components/LayerRenderer.d.ts +2 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.esm.js +262 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +266 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# react-layer-kit 🪟
|
|
2
|
+
|
|
3
|
+
Zero-dependency React library for stacking modals and drawers with smooth animations, full TypeScript support, and complete style control.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-layer-kit)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🪟 **Modals** — centered overlays with fade + scale animation
|
|
10
|
+
- 🗂️ **Drawers** — slide in from left, right, top, or bottom
|
|
11
|
+
- 📚 **Stacking** — open multiple layers on top of each other
|
|
12
|
+
- ⌨️ **Keyboard** — Escape closes the top layer
|
|
13
|
+
- 🔒 **Body scroll lock** — automatically locks scroll when open
|
|
14
|
+
- 🎨 **Fully customizable** — theme every property
|
|
15
|
+
- 🔷 **TypeScript** — fully typed API
|
|
16
|
+
- 📦 **Zero dependencies** — only React required
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install react-layer-kit
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { LayerProvider, LayerRenderer, useLayer } from "react-layer-kit";
|
|
28
|
+
|
|
29
|
+
// 1. Wrap your app
|
|
30
|
+
function App() {
|
|
31
|
+
return (
|
|
32
|
+
<LayerProvider>
|
|
33
|
+
<MyPage />
|
|
34
|
+
<LayerRenderer />
|
|
35
|
+
</LayerProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 2. Open modals and drawers from anywhere
|
|
40
|
+
function MyPage() {
|
|
41
|
+
const { openModal, openDrawer } = useLayer();
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<button onClick={() =>
|
|
46
|
+
openModal({
|
|
47
|
+
title: "Confirm Action",
|
|
48
|
+
content: <p>Are you sure you want to proceed?</p>,
|
|
49
|
+
size: "sm",
|
|
50
|
+
})
|
|
51
|
+
}>
|
|
52
|
+
Open Modal
|
|
53
|
+
</button>
|
|
54
|
+
|
|
55
|
+
<button onClick={() =>
|
|
56
|
+
openDrawer({
|
|
57
|
+
title: "Settings",
|
|
58
|
+
content: <p>Drawer content here</p>,
|
|
59
|
+
placement: "right",
|
|
60
|
+
})
|
|
61
|
+
}>
|
|
62
|
+
Open Drawer
|
|
63
|
+
</button>
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## API
|
|
70
|
+
|
|
71
|
+
### `<LayerProvider>`
|
|
72
|
+
|
|
73
|
+
Wrap your app with `LayerProvider`.
|
|
74
|
+
|
|
75
|
+
| Prop | Type | Description |
|
|
76
|
+
|------|------|-------------|
|
|
77
|
+
| `theme` | `LayerTheme` | Global style overrides |
|
|
78
|
+
|
|
79
|
+
### `<LayerRenderer>`
|
|
80
|
+
|
|
81
|
+
Place once near the root. Renders all active layers into a portal.
|
|
82
|
+
|
|
83
|
+
### `useLayer()`
|
|
84
|
+
|
|
85
|
+
| Method / Property | Type | Description |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `openModal(options)` | `(OpenModalOptions) => string` | Opens a modal, returns its ID |
|
|
88
|
+
| `openDrawer(options)` | `(OpenDrawerOptions) => string` | Opens a drawer, returns its ID |
|
|
89
|
+
| `close(id)` | `(string) => void` | Closes a specific layer by ID |
|
|
90
|
+
| `closeTop()` | `() => void` | Closes the topmost layer |
|
|
91
|
+
| `closeAll()` | `() => void` | Closes all layers |
|
|
92
|
+
| `layers` | `LayerEntry[]` | Currently open layers |
|
|
93
|
+
|
|
94
|
+
### `OpenModalOptions`
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Default | Description |
|
|
97
|
+
|------|------|---------|-------------|
|
|
98
|
+
| `content` | `ReactNode` | required | Modal body content |
|
|
99
|
+
| `title` | `string` | — | Optional header title |
|
|
100
|
+
| `size` | `"sm" \| "md" \| "lg" \| "xl" \| "full"` | `"md"` | Modal width |
|
|
101
|
+
| `closeOnBackdrop` | `boolean` | `true` | Close when clicking backdrop |
|
|
102
|
+
| `closeOnEsc` | `boolean` | `true` | Close on Escape key |
|
|
103
|
+
| `onClose` | `() => void` | — | Called when modal closes |
|
|
104
|
+
|
|
105
|
+
### `OpenDrawerOptions`
|
|
106
|
+
|
|
107
|
+
| Prop | Type | Default | Description |
|
|
108
|
+
|------|------|---------|-------------|
|
|
109
|
+
| `content` | `ReactNode` | required | Drawer body content |
|
|
110
|
+
| `title` | `string` | — | Optional header title |
|
|
111
|
+
| `placement` | `"left" \| "right" \| "top" \| "bottom"` | `"right"` | Slide direction |
|
|
112
|
+
| `size` | `string` | `"380px"` / `"50vh"` | Width or height |
|
|
113
|
+
| `closeOnBackdrop` | `boolean` | `true` | Close when clicking backdrop |
|
|
114
|
+
| `closeOnEsc` | `boolean` | `true` | Close on Escape key |
|
|
115
|
+
| `onClose` | `() => void` | — | Called when drawer closes |
|
|
116
|
+
|
|
117
|
+
### `LayerTheme`
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
interface LayerTheme {
|
|
121
|
+
backdropColor?: string; // default: "rgba(0,0,0,0.5)"
|
|
122
|
+
backdropBlur?: string; // default: "4px"
|
|
123
|
+
modalBackground?: string; // default: "#ffffff"
|
|
124
|
+
modalBorderRadius?: string; // default: "16px"
|
|
125
|
+
modalShadow?: string;
|
|
126
|
+
modalPadding?: string; // default: "28px"
|
|
127
|
+
drawerBackground?: string; // default: "#ffffff"
|
|
128
|
+
drawerShadow?: string;
|
|
129
|
+
drawerPadding?: string; // default: "28px"
|
|
130
|
+
zIndexBase?: number; // default: 1000
|
|
131
|
+
animationDuration?: number; // default: 250 (ms)
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Stacking Example
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
const { openModal } = useLayer();
|
|
139
|
+
|
|
140
|
+
// Open a modal that opens another modal on top
|
|
141
|
+
openModal({
|
|
142
|
+
title: "First Modal",
|
|
143
|
+
content: (
|
|
144
|
+
<button onClick={() =>
|
|
145
|
+
openModal({
|
|
146
|
+
title: "Second Modal",
|
|
147
|
+
content: <p>Stacked on top!</p>,
|
|
148
|
+
size: "sm",
|
|
149
|
+
})
|
|
150
|
+
}>
|
|
151
|
+
Open Another
|
|
152
|
+
</button>
|
|
153
|
+
),
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Keyboard Support
|
|
158
|
+
|
|
159
|
+
| Key | Action |
|
|
160
|
+
|-----|--------|
|
|
161
|
+
| `Esc` | Close topmost layer |
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type LayerType = "modal" | "drawer";
|
|
3
|
+
export type DrawerPlacement = "left" | "right" | "top" | "bottom";
|
|
4
|
+
export interface LayerTheme {
|
|
5
|
+
backdropColor?: string;
|
|
6
|
+
backdropBlur?: string;
|
|
7
|
+
modalBackground?: string;
|
|
8
|
+
modalBorderRadius?: string;
|
|
9
|
+
modalShadow?: string;
|
|
10
|
+
modalPadding?: string;
|
|
11
|
+
drawerBackground?: string;
|
|
12
|
+
drawerShadow?: string;
|
|
13
|
+
drawerPadding?: string;
|
|
14
|
+
zIndexBase?: number;
|
|
15
|
+
animationDuration?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface OpenModalOptions {
|
|
18
|
+
title?: string;
|
|
19
|
+
content: React.ReactNode;
|
|
20
|
+
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
21
|
+
closeOnBackdrop?: boolean;
|
|
22
|
+
closeOnEsc?: boolean;
|
|
23
|
+
onClose?: () => void;
|
|
24
|
+
}
|
|
25
|
+
export interface OpenDrawerOptions {
|
|
26
|
+
title?: string;
|
|
27
|
+
content: React.ReactNode;
|
|
28
|
+
placement?: DrawerPlacement;
|
|
29
|
+
size?: string;
|
|
30
|
+
closeOnBackdrop?: boolean;
|
|
31
|
+
closeOnEsc?: boolean;
|
|
32
|
+
onClose?: () => void;
|
|
33
|
+
}
|
|
34
|
+
export interface LayerEntry {
|
|
35
|
+
id: string;
|
|
36
|
+
type: LayerType;
|
|
37
|
+
modalOptions?: OpenModalOptions;
|
|
38
|
+
drawerOptions?: OpenDrawerOptions;
|
|
39
|
+
isClosing: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface LayerContextValue {
|
|
42
|
+
layers: LayerEntry[];
|
|
43
|
+
theme: LayerTheme;
|
|
44
|
+
openModal: (options: OpenModalOptions) => string;
|
|
45
|
+
openDrawer: (options: OpenDrawerOptions) => string;
|
|
46
|
+
close: (id: string) => void;
|
|
47
|
+
closeAll: () => void;
|
|
48
|
+
closeTop: () => void;
|
|
49
|
+
}
|
|
50
|
+
export interface LayerProviderProps {
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
theme?: LayerTheme;
|
|
53
|
+
}
|
|
54
|
+
export declare function LayerProvider({ children, theme }: LayerProviderProps): React.JSX.Element;
|
|
55
|
+
export declare function useLayer(): LayerContextValue;
|
|
56
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type LayerType = "modal" | "drawer";
|
|
4
|
+
type DrawerPlacement = "left" | "right" | "top" | "bottom";
|
|
5
|
+
interface LayerTheme {
|
|
6
|
+
backdropColor?: string;
|
|
7
|
+
backdropBlur?: string;
|
|
8
|
+
modalBackground?: string;
|
|
9
|
+
modalBorderRadius?: string;
|
|
10
|
+
modalShadow?: string;
|
|
11
|
+
modalPadding?: string;
|
|
12
|
+
drawerBackground?: string;
|
|
13
|
+
drawerShadow?: string;
|
|
14
|
+
drawerPadding?: string;
|
|
15
|
+
zIndexBase?: number;
|
|
16
|
+
animationDuration?: number;
|
|
17
|
+
}
|
|
18
|
+
interface OpenModalOptions {
|
|
19
|
+
title?: string;
|
|
20
|
+
content: React.ReactNode;
|
|
21
|
+
size?: "sm" | "md" | "lg" | "xl" | "full";
|
|
22
|
+
closeOnBackdrop?: boolean;
|
|
23
|
+
closeOnEsc?: boolean;
|
|
24
|
+
onClose?: () => void;
|
|
25
|
+
}
|
|
26
|
+
interface OpenDrawerOptions {
|
|
27
|
+
title?: string;
|
|
28
|
+
content: React.ReactNode;
|
|
29
|
+
placement?: DrawerPlacement;
|
|
30
|
+
size?: string;
|
|
31
|
+
closeOnBackdrop?: boolean;
|
|
32
|
+
closeOnEsc?: boolean;
|
|
33
|
+
onClose?: () => void;
|
|
34
|
+
}
|
|
35
|
+
interface LayerEntry {
|
|
36
|
+
id: string;
|
|
37
|
+
type: LayerType;
|
|
38
|
+
modalOptions?: OpenModalOptions;
|
|
39
|
+
drawerOptions?: OpenDrawerOptions;
|
|
40
|
+
isClosing: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface LayerContextValue {
|
|
43
|
+
layers: LayerEntry[];
|
|
44
|
+
theme: LayerTheme;
|
|
45
|
+
openModal: (options: OpenModalOptions) => string;
|
|
46
|
+
openDrawer: (options: OpenDrawerOptions) => string;
|
|
47
|
+
close: (id: string) => void;
|
|
48
|
+
closeAll: () => void;
|
|
49
|
+
closeTop: () => void;
|
|
50
|
+
}
|
|
51
|
+
interface LayerProviderProps {
|
|
52
|
+
children: React.ReactNode;
|
|
53
|
+
theme?: LayerTheme;
|
|
54
|
+
}
|
|
55
|
+
declare function LayerProvider({ children, theme }: LayerProviderProps): React.JSX.Element;
|
|
56
|
+
declare function useLayer(): LayerContextValue;
|
|
57
|
+
|
|
58
|
+
declare function LayerRenderer(): React.ReactPortal | null;
|
|
59
|
+
|
|
60
|
+
export { DrawerPlacement, LayerEntry, LayerProvider, LayerProviderProps, LayerRenderer, LayerTheme, OpenDrawerOptions, OpenModalOptions, useLayer };
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import React, { createContext, useState, useCallback, useContext, useRef, useEffect } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
|
|
4
|
+
const LayerContext = createContext(null);
|
|
5
|
+
function LayerProvider({ children, theme = {} }) {
|
|
6
|
+
const [layers, setLayers] = useState([]);
|
|
7
|
+
const generateId = () => `layer-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
8
|
+
const openModal = useCallback((options) => {
|
|
9
|
+
const id = generateId();
|
|
10
|
+
setLayers((prev) => [
|
|
11
|
+
...prev,
|
|
12
|
+
{ id, type: "modal", modalOptions: options, isClosing: false },
|
|
13
|
+
]);
|
|
14
|
+
return id;
|
|
15
|
+
}, []);
|
|
16
|
+
const openDrawer = useCallback((options) => {
|
|
17
|
+
const id = generateId();
|
|
18
|
+
setLayers((prev) => [
|
|
19
|
+
...prev,
|
|
20
|
+
{ id, type: "drawer", drawerOptions: options, isClosing: false },
|
|
21
|
+
]);
|
|
22
|
+
return id;
|
|
23
|
+
}, []);
|
|
24
|
+
const close = useCallback((id) => {
|
|
25
|
+
var _a;
|
|
26
|
+
setLayers((prev) => prev.map((l) => (l.id === id ? Object.assign(Object.assign({}, l), { isClosing: true }) : l)));
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
setLayers((prev) => {
|
|
29
|
+
var _a, _b, _c, _d;
|
|
30
|
+
const layer = prev.find((l) => l.id === id);
|
|
31
|
+
(_b = (_a = layer === null || layer === void 0 ? void 0 : layer.modalOptions) === null || _a === void 0 ? void 0 : _a.onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
32
|
+
(_d = (_c = layer === null || layer === void 0 ? void 0 : layer.drawerOptions) === null || _c === void 0 ? void 0 : _c.onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
33
|
+
return prev.filter((l) => l.id !== id);
|
|
34
|
+
});
|
|
35
|
+
}, ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
36
|
+
}, [theme.animationDuration]);
|
|
37
|
+
const closeAll = useCallback(() => {
|
|
38
|
+
var _a;
|
|
39
|
+
setLayers((prev) => prev.map((l) => (Object.assign(Object.assign({}, l), { isClosing: true }))));
|
|
40
|
+
setTimeout(() => setLayers([]), ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
41
|
+
}, [theme.animationDuration]);
|
|
42
|
+
const closeTop = useCallback(() => {
|
|
43
|
+
var _a;
|
|
44
|
+
setLayers((prev) => {
|
|
45
|
+
if (prev.length === 0)
|
|
46
|
+
return prev;
|
|
47
|
+
const topId = prev[prev.length - 1].id;
|
|
48
|
+
return prev.map((l) => (l.id === topId ? Object.assign(Object.assign({}, l), { isClosing: true }) : l));
|
|
49
|
+
});
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
setLayers((prev) => {
|
|
52
|
+
var _a, _b, _c, _d;
|
|
53
|
+
if (prev.length === 0)
|
|
54
|
+
return prev;
|
|
55
|
+
const top = prev[prev.length - 1];
|
|
56
|
+
(_b = (_a = top === null || top === void 0 ? void 0 : top.modalOptions) === null || _a === void 0 ? void 0 : _a.onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
57
|
+
(_d = (_c = top === null || top === void 0 ? void 0 : top.drawerOptions) === null || _c === void 0 ? void 0 : _c.onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
58
|
+
return prev.slice(0, -1);
|
|
59
|
+
});
|
|
60
|
+
}, ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
61
|
+
}, [theme.animationDuration]);
|
|
62
|
+
return (React.createElement(LayerContext.Provider, { value: { layers, theme, openModal, openDrawer, close, closeAll, closeTop } }, children));
|
|
63
|
+
}
|
|
64
|
+
function useLayer() {
|
|
65
|
+
const ctx = useContext(LayerContext);
|
|
66
|
+
if (!ctx)
|
|
67
|
+
throw new Error("useLayer must be used within a LayerProvider");
|
|
68
|
+
return ctx;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const defaultTheme = {
|
|
72
|
+
backdropColor: "rgba(0, 0, 0, 0.5)",
|
|
73
|
+
backdropBlur: "4px",
|
|
74
|
+
modalBackground: "#ffffff",
|
|
75
|
+
modalBorderRadius: "16px",
|
|
76
|
+
modalShadow: "0 25px 60px rgba(0,0,0,0.2)",
|
|
77
|
+
modalPadding: "28px",
|
|
78
|
+
drawerBackground: "#ffffff",
|
|
79
|
+
drawerShadow: "0 8px 40px rgba(0,0,0,0.18)",
|
|
80
|
+
drawerPadding: "28px",
|
|
81
|
+
zIndexBase: 1000,
|
|
82
|
+
animationDuration: 250,
|
|
83
|
+
};
|
|
84
|
+
const MODAL_SIZES = {
|
|
85
|
+
sm: "360px",
|
|
86
|
+
md: "520px",
|
|
87
|
+
lg: "720px",
|
|
88
|
+
xl: "960px",
|
|
89
|
+
full: "100vw",
|
|
90
|
+
};
|
|
91
|
+
const DRAWER_AXIS = {
|
|
92
|
+
right: { inset: { top: 0, right: 0, bottom: 0 } },
|
|
93
|
+
left: { inset: { top: 0, left: 0, bottom: 0 } },
|
|
94
|
+
bottom: { inset: { left: 0, right: 0, bottom: 0 } },
|
|
95
|
+
top: { inset: { left: 0, right: 0, top: 0 } },
|
|
96
|
+
};
|
|
97
|
+
function getDrawerTransform(placement, isClosing, isEntering) {
|
|
98
|
+
var _a;
|
|
99
|
+
const hidden = (_a = {
|
|
100
|
+
right: "translateX(100%)",
|
|
101
|
+
left: "translateX(-100%)",
|
|
102
|
+
bottom: "translateY(100%)",
|
|
103
|
+
top: "translateY(-100%)",
|
|
104
|
+
}[placement]) !== null && _a !== void 0 ? _a : "translateX(100%)";
|
|
105
|
+
return isClosing || isEntering ? hidden : "translate(0,0)";
|
|
106
|
+
}
|
|
107
|
+
function ModalLayer({ layer, index, theme, entering, }) {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
const { close } = useLayer();
|
|
110
|
+
const opts = layer.modalOptions;
|
|
111
|
+
const zIndex = theme.zIndexBase + index * 10;
|
|
112
|
+
const isVisible = !layer.isClosing && !entering;
|
|
113
|
+
const dur = `${theme.animationDuration}ms`;
|
|
114
|
+
const size = (_b = MODAL_SIZES[(_a = opts.size) !== null && _a !== void 0 ? _a : "md"]) !== null && _b !== void 0 ? _b : MODAL_SIZES.md;
|
|
115
|
+
return (React.createElement("div", { style: {
|
|
116
|
+
position: "fixed",
|
|
117
|
+
inset: 0,
|
|
118
|
+
zIndex,
|
|
119
|
+
display: "flex",
|
|
120
|
+
alignItems: "center",
|
|
121
|
+
justifyContent: "center",
|
|
122
|
+
transition: `opacity ${dur} ease`,
|
|
123
|
+
opacity: isVisible ? 1 : 0,
|
|
124
|
+
} },
|
|
125
|
+
React.createElement("div", { style: {
|
|
126
|
+
position: "absolute",
|
|
127
|
+
inset: 0,
|
|
128
|
+
background: theme.backdropColor,
|
|
129
|
+
backdropFilter: `blur(${theme.backdropBlur})`,
|
|
130
|
+
}, onClick: () => opts.closeOnBackdrop !== false && close(layer.id) }),
|
|
131
|
+
React.createElement("div", { role: "dialog", "aria-modal": "true", style: {
|
|
132
|
+
position: "relative",
|
|
133
|
+
width: size === "100vw" ? "100%" : size,
|
|
134
|
+
maxWidth: "calc(100vw - 32px)",
|
|
135
|
+
maxHeight: "calc(100vh - 64px)",
|
|
136
|
+
background: theme.modalBackground,
|
|
137
|
+
borderRadius: opts.size === "full" ? 0 : theme.modalBorderRadius,
|
|
138
|
+
boxShadow: theme.modalShadow,
|
|
139
|
+
padding: theme.modalPadding,
|
|
140
|
+
overflowY: "auto",
|
|
141
|
+
transition: `transform ${dur} cubic-bezier(0.34, 1.56, 0.64, 1), opacity ${dur} ease`,
|
|
142
|
+
transform: isVisible ? "scale(1)" : "scale(0.92)",
|
|
143
|
+
}, onClick: (e) => e.stopPropagation() },
|
|
144
|
+
opts.title && (React.createElement("div", { style: {
|
|
145
|
+
display: "flex",
|
|
146
|
+
justifyContent: "space-between",
|
|
147
|
+
alignItems: "center",
|
|
148
|
+
marginBottom: 20,
|
|
149
|
+
} },
|
|
150
|
+
React.createElement("h2", { style: { margin: 0, fontSize: 18, fontWeight: 700 } }, opts.title),
|
|
151
|
+
React.createElement("button", { onClick: () => close(layer.id), "aria-label": "Close", style: {
|
|
152
|
+
background: "none",
|
|
153
|
+
border: "none",
|
|
154
|
+
fontSize: 20,
|
|
155
|
+
cursor: "pointer",
|
|
156
|
+
opacity: 0.4,
|
|
157
|
+
padding: "0 4px",
|
|
158
|
+
lineHeight: 1,
|
|
159
|
+
} }, "\u2715"))),
|
|
160
|
+
opts.content)));
|
|
161
|
+
}
|
|
162
|
+
function DrawerLayer({ layer, index, theme, entering, }) {
|
|
163
|
+
var _a, _b;
|
|
164
|
+
const { close } = useLayer();
|
|
165
|
+
const opts = layer.drawerOptions;
|
|
166
|
+
const placement = (_a = opts.placement) !== null && _a !== void 0 ? _a : "right";
|
|
167
|
+
const zIndex = theme.zIndexBase + index * 10;
|
|
168
|
+
const isVisible = !layer.isClosing && !entering;
|
|
169
|
+
const dur = `${theme.animationDuration}ms`;
|
|
170
|
+
const isHorizontal = placement === "left" || placement === "right";
|
|
171
|
+
const defaultSize = isHorizontal ? "380px" : "50vh";
|
|
172
|
+
const size = (_b = opts.size) !== null && _b !== void 0 ? _b : defaultSize;
|
|
173
|
+
const axis = DRAWER_AXIS[placement];
|
|
174
|
+
const sizeStyle = isHorizontal
|
|
175
|
+
? { width: size, height: "100%" }
|
|
176
|
+
: { height: size, width: "100%" };
|
|
177
|
+
return (React.createElement("div", { style: { position: "fixed", inset: 0, zIndex, pointerEvents: "none" } },
|
|
178
|
+
React.createElement("div", { style: {
|
|
179
|
+
position: "absolute",
|
|
180
|
+
inset: 0,
|
|
181
|
+
background: theme.backdropColor,
|
|
182
|
+
backdropFilter: `blur(${theme.backdropBlur})`,
|
|
183
|
+
pointerEvents: "all",
|
|
184
|
+
transition: `opacity ${dur} ease`,
|
|
185
|
+
opacity: isVisible ? 1 : 0,
|
|
186
|
+
}, onClick: () => opts.closeOnBackdrop !== false && close(layer.id) }),
|
|
187
|
+
React.createElement("div", { role: "dialog", "aria-modal": "true", style: Object.assign(Object.assign(Object.assign({ position: "absolute" }, axis.inset), sizeStyle), { background: theme.drawerBackground, boxShadow: theme.drawerShadow, padding: theme.drawerPadding, overflowY: "auto", pointerEvents: "all", transition: `transform ${dur} cubic-bezier(0.4, 0, 0.2, 1)`, transform: getDrawerTransform(placement, layer.isClosing, entering) }), onClick: (e) => e.stopPropagation() },
|
|
188
|
+
React.createElement("div", { style: {
|
|
189
|
+
display: "flex",
|
|
190
|
+
justifyContent: "space-between",
|
|
191
|
+
alignItems: "center",
|
|
192
|
+
marginBottom: opts.title ? 20 : 0,
|
|
193
|
+
} },
|
|
194
|
+
opts.title && (React.createElement("h2", { style: { margin: 0, fontSize: 18, fontWeight: 700 } }, opts.title)),
|
|
195
|
+
React.createElement("button", { onClick: () => close(layer.id), "aria-label": "Close", style: {
|
|
196
|
+
background: "none",
|
|
197
|
+
border: "none",
|
|
198
|
+
fontSize: 20,
|
|
199
|
+
cursor: "pointer",
|
|
200
|
+
opacity: 0.4,
|
|
201
|
+
marginLeft: "auto",
|
|
202
|
+
padding: "0 4px",
|
|
203
|
+
lineHeight: 1,
|
|
204
|
+
} }, "\u2715")),
|
|
205
|
+
opts.content)));
|
|
206
|
+
}
|
|
207
|
+
function LayerRenderer() {
|
|
208
|
+
const { layers, theme: userTheme, close, closeTop } = useLayer();
|
|
209
|
+
const theme = Object.assign(Object.assign({}, defaultTheme), userTheme);
|
|
210
|
+
const [enteringIds, setEnteringIds] = React.useState(new Set());
|
|
211
|
+
const prevLayerIds = useRef(new Set());
|
|
212
|
+
// Track newly added layers for enter animation
|
|
213
|
+
useEffect(() => {
|
|
214
|
+
const newIds = new Set();
|
|
215
|
+
layers.forEach((l) => {
|
|
216
|
+
if (!prevLayerIds.current.has(l.id))
|
|
217
|
+
newIds.add(l.id);
|
|
218
|
+
});
|
|
219
|
+
if (newIds.size > 0) {
|
|
220
|
+
setEnteringIds((prev) => new Set([...prev, ...newIds]));
|
|
221
|
+
requestAnimationFrame(() => {
|
|
222
|
+
requestAnimationFrame(() => {
|
|
223
|
+
setEnteringIds((prev) => {
|
|
224
|
+
const next = new Set(prev);
|
|
225
|
+
newIds.forEach((id) => next.delete(id));
|
|
226
|
+
return next;
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
prevLayerIds.current = new Set(layers.map((l) => l.id));
|
|
232
|
+
}, [layers]);
|
|
233
|
+
// Keyboard Escape handler
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
if (layers.length === 0)
|
|
236
|
+
return;
|
|
237
|
+
const handler = (e) => {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
if (e.key !== "Escape")
|
|
240
|
+
return;
|
|
241
|
+
const top = layers[layers.length - 1];
|
|
242
|
+
const esc = top.type === "modal"
|
|
243
|
+
? ((_a = top.modalOptions) === null || _a === void 0 ? void 0 : _a.closeOnEsc) !== false
|
|
244
|
+
: ((_b = top.drawerOptions) === null || _b === void 0 ? void 0 : _b.closeOnEsc) !== false;
|
|
245
|
+
if (esc)
|
|
246
|
+
closeTop();
|
|
247
|
+
};
|
|
248
|
+
window.addEventListener("keydown", handler);
|
|
249
|
+
return () => window.removeEventListener("keydown", handler);
|
|
250
|
+
}, [layers, closeTop]);
|
|
251
|
+
// Lock body scroll when layers are open
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
document.body.style.overflow = layers.length > 0 ? "hidden" : "";
|
|
254
|
+
return () => { document.body.style.overflow = ""; };
|
|
255
|
+
}, [layers.length]);
|
|
256
|
+
if (layers.length === 0)
|
|
257
|
+
return null;
|
|
258
|
+
return createPortal(React.createElement(React.Fragment, null, layers.map((layer, index) => layer.type === "modal" ? (React.createElement(ModalLayer, { key: layer.id, layer: layer, index: index, theme: theme, entering: enteringIds.has(layer.id) })) : (React.createElement(DrawerLayer, { key: layer.id, layer: layer, index: index, theme: theme, entering: enteringIds.has(layer.id) })))), document.body);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export { LayerProvider, LayerRenderer, useLayer };
|
|
262
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/components/LayerContext.tsx","../src/components/LayerRenderer.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useId,\n} from \"react\";\n\nexport type LayerType = \"modal\" | \"drawer\";\nexport type DrawerPlacement = \"left\" | \"right\" | \"top\" | \"bottom\";\n\nexport interface LayerTheme {\n backdropColor?: string;\n backdropBlur?: string;\n modalBackground?: string;\n modalBorderRadius?: string;\n modalShadow?: string;\n modalPadding?: string;\n drawerBackground?: string;\n drawerShadow?: string;\n drawerPadding?: string;\n zIndexBase?: number;\n animationDuration?: number;\n}\n\nexport interface OpenModalOptions {\n title?: string;\n content: React.ReactNode;\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n onClose?: () => void;\n}\n\nexport interface OpenDrawerOptions {\n title?: string;\n content: React.ReactNode;\n placement?: DrawerPlacement;\n size?: string;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n onClose?: () => void;\n}\n\nexport interface LayerEntry {\n id: string;\n type: LayerType;\n modalOptions?: OpenModalOptions;\n drawerOptions?: OpenDrawerOptions;\n isClosing: boolean;\n}\n\ninterface LayerContextValue {\n layers: LayerEntry[];\n theme: LayerTheme;\n openModal: (options: OpenModalOptions) => string;\n openDrawer: (options: OpenDrawerOptions) => string;\n close: (id: string) => void;\n closeAll: () => void;\n closeTop: () => void;\n}\n\nconst LayerContext = createContext<LayerContextValue | null>(null);\n\nexport interface LayerProviderProps {\n children: React.ReactNode;\n theme?: LayerTheme;\n}\n\nexport function LayerProvider({ children, theme = {} }: LayerProviderProps) {\n const [layers, setLayers] = useState<LayerEntry[]>([]);\n\n const generateId = () =>\n `layer-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n\n const openModal = useCallback((options: OpenModalOptions): string => {\n const id = generateId();\n setLayers((prev) => [\n ...prev,\n { id, type: \"modal\", modalOptions: options, isClosing: false },\n ]);\n return id;\n }, []);\n\n const openDrawer = useCallback((options: OpenDrawerOptions): string => {\n const id = generateId();\n setLayers((prev) => [\n ...prev,\n { id, type: \"drawer\", drawerOptions: options, isClosing: false },\n ]);\n return id;\n }, []);\n\n const close = useCallback((id: string) => {\n setLayers((prev) =>\n prev.map((l) => (l.id === id ? { ...l, isClosing: true } : l))\n );\n setTimeout(() => {\n setLayers((prev) => {\n const layer = prev.find((l) => l.id === id);\n layer?.modalOptions?.onClose?.();\n layer?.drawerOptions?.onClose?.();\n return prev.filter((l) => l.id !== id);\n });\n }, (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n const closeAll = useCallback(() => {\n setLayers((prev) => prev.map((l) => ({ ...l, isClosing: true })));\n setTimeout(() => setLayers([]), (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n const closeTop = useCallback(() => {\n setLayers((prev) => {\n if (prev.length === 0) return prev;\n const topId = prev[prev.length - 1].id;\n return prev.map((l) => (l.id === topId ? { ...l, isClosing: true } : l));\n });\n setTimeout(() => {\n setLayers((prev) => {\n if (prev.length === 0) return prev;\n const top = prev[prev.length - 1];\n top?.modalOptions?.onClose?.();\n top?.drawerOptions?.onClose?.();\n return prev.slice(0, -1);\n });\n }, (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n return (\n <LayerContext.Provider\n value={{ layers, theme, openModal, openDrawer, close, closeAll, closeTop }}\n >\n {children}\n </LayerContext.Provider>\n );\n}\n\nexport function useLayer() {\n const ctx = useContext(LayerContext);\n if (!ctx) throw new Error(\"useLayer must be used within a LayerProvider\");\n return ctx;\n}\n","import React, { useEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useLayer, LayerEntry, LayerTheme } from \"./LayerContext\";\n\nconst defaultTheme: Required<LayerTheme> = {\n backdropColor: \"rgba(0, 0, 0, 0.5)\",\n backdropBlur: \"4px\",\n modalBackground: \"#ffffff\",\n modalBorderRadius: \"16px\",\n modalShadow: \"0 25px 60px rgba(0,0,0,0.2)\",\n modalPadding: \"28px\",\n drawerBackground: \"#ffffff\",\n drawerShadow: \"0 8px 40px rgba(0,0,0,0.18)\",\n drawerPadding: \"28px\",\n zIndexBase: 1000,\n animationDuration: 250,\n};\n\nconst MODAL_SIZES: Record<string, string> = {\n sm: \"360px\",\n md: \"520px\",\n lg: \"720px\",\n xl: \"960px\",\n full: \"100vw\",\n};\n\nconst DRAWER_AXIS: Record<string, { width?: string; height?: string; inset: React.CSSProperties }> = {\n right: { inset: { top: 0, right: 0, bottom: 0 } },\n left: { inset: { top: 0, left: 0, bottom: 0 } },\n bottom: { inset: { left: 0, right: 0, bottom: 0 } },\n top: { inset: { left: 0, right: 0, top: 0 } },\n};\n\nfunction getDrawerTransform(placement: string, isClosing: boolean, isEntering: boolean): string {\n const hidden = {\n right: \"translateX(100%)\",\n left: \"translateX(-100%)\",\n bottom: \"translateY(100%)\",\n top: \"translateY(-100%)\",\n }[placement] ?? \"translateX(100%)\";\n return isClosing || isEntering ? hidden : \"translate(0,0)\";\n}\n\nfunction ModalLayer({\n layer,\n index,\n theme,\n entering,\n}: {\n layer: LayerEntry;\n index: number;\n theme: Required<LayerTheme>;\n entering: boolean;\n}) {\n const { close } = useLayer();\n const opts = layer.modalOptions!;\n const zIndex = theme.zIndexBase + index * 10;\n const isVisible = !layer.isClosing && !entering;\n const dur = `${theme.animationDuration}ms`;\n const size = MODAL_SIZES[opts.size ?? \"md\"] ?? MODAL_SIZES.md;\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: `opacity ${dur} ease`,\n opacity: isVisible ? 1 : 0,\n }}\n >\n {/* Backdrop */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: theme.backdropColor,\n backdropFilter: `blur(${theme.backdropBlur})`,\n }}\n onClick={() => opts.closeOnBackdrop !== false && close(layer.id)}\n />\n\n {/* Modal box */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n style={{\n position: \"relative\",\n width: size === \"100vw\" ? \"100%\" : size,\n maxWidth: \"calc(100vw - 32px)\",\n maxHeight: \"calc(100vh - 64px)\",\n background: theme.modalBackground,\n borderRadius: opts.size === \"full\" ? 0 : theme.modalBorderRadius,\n boxShadow: theme.modalShadow,\n padding: theme.modalPadding,\n overflowY: \"auto\",\n transition: `transform ${dur} cubic-bezier(0.34, 1.56, 0.64, 1), opacity ${dur} ease`,\n transform: isVisible ? \"scale(1)\" : \"scale(0.92)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n {opts.title && (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 20,\n }}\n >\n <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>{opts.title}</h2>\n <button\n onClick={() => close(layer.id)}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n fontSize: 20,\n cursor: \"pointer\",\n opacity: 0.4,\n padding: \"0 4px\",\n lineHeight: 1,\n }}\n >\n ✕\n </button>\n </div>\n )}\n {opts.content}\n </div>\n </div>\n );\n}\n\nfunction DrawerLayer({\n layer,\n index,\n theme,\n entering,\n}: {\n layer: LayerEntry;\n index: number;\n theme: Required<LayerTheme>;\n entering: boolean;\n}) {\n const { close } = useLayer();\n const opts = layer.drawerOptions!;\n const placement = opts.placement ?? \"right\";\n const zIndex = theme.zIndexBase + index * 10;\n const isVisible = !layer.isClosing && !entering;\n const dur = `${theme.animationDuration}ms`;\n const isHorizontal = placement === \"left\" || placement === \"right\";\n const defaultSize = isHorizontal ? \"380px\" : \"50vh\";\n const size = opts.size ?? defaultSize;\n const axis = DRAWER_AXIS[placement];\n\n const sizeStyle: React.CSSProperties = isHorizontal\n ? { width: size, height: \"100%\" }\n : { height: size, width: \"100%\" };\n\n return (\n <div style={{ position: \"fixed\", inset: 0, zIndex, pointerEvents: \"none\" }}>\n {/* Backdrop */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: theme.backdropColor,\n backdropFilter: `blur(${theme.backdropBlur})`,\n pointerEvents: \"all\",\n transition: `opacity ${dur} ease`,\n opacity: isVisible ? 1 : 0,\n }}\n onClick={() => opts.closeOnBackdrop !== false && close(layer.id)}\n />\n\n {/* Drawer panel */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n style={{\n position: \"absolute\",\n ...axis.inset,\n ...sizeStyle,\n background: theme.drawerBackground,\n boxShadow: theme.drawerShadow,\n padding: theme.drawerPadding,\n overflowY: \"auto\",\n pointerEvents: \"all\",\n transition: `transform ${dur} cubic-bezier(0.4, 0, 0.2, 1)`,\n transform: getDrawerTransform(placement, layer.isClosing, entering),\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: opts.title ? 20 : 0,\n }}\n >\n {opts.title && (\n <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>{opts.title}</h2>\n )}\n <button\n onClick={() => close(layer.id)}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n fontSize: 20,\n cursor: \"pointer\",\n opacity: 0.4,\n marginLeft: \"auto\",\n padding: \"0 4px\",\n lineHeight: 1,\n }}\n >\n ✕\n </button>\n </div>\n {opts.content}\n </div>\n </div>\n );\n}\n\nexport function LayerRenderer() {\n const { layers, theme: userTheme, close, closeTop } = useLayer();\n const theme = { ...defaultTheme, ...userTheme };\n const [enteringIds, setEnteringIds] = React.useState<Set<string>>(new Set());\n const prevLayerIds = useRef<Set<string>>(new Set());\n\n // Track newly added layers for enter animation\n useEffect(() => {\n const newIds = new Set<string>();\n layers.forEach((l) => {\n if (!prevLayerIds.current.has(l.id)) newIds.add(l.id);\n });\n if (newIds.size > 0) {\n setEnteringIds((prev) => new Set([...prev, ...newIds]));\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setEnteringIds((prev) => {\n const next = new Set(prev);\n newIds.forEach((id) => next.delete(id));\n return next;\n });\n });\n });\n }\n prevLayerIds.current = new Set(layers.map((l) => l.id));\n }, [layers]);\n\n // Keyboard Escape handler\n useEffect(() => {\n if (layers.length === 0) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n const top = layers[layers.length - 1];\n const esc =\n top.type === \"modal\"\n ? top.modalOptions?.closeOnEsc !== false\n : top.drawerOptions?.closeOnEsc !== false;\n if (esc) closeTop();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [layers, closeTop]);\n\n // Lock body scroll when layers are open\n useEffect(() => {\n document.body.style.overflow = layers.length > 0 ? \"hidden\" : \"\";\n return () => { document.body.style.overflow = \"\"; };\n }, [layers.length]);\n\n if (layers.length === 0) return null;\n\n return createPortal(\n <>\n {layers.map((layer, index) =>\n layer.type === \"modal\" ? (\n <ModalLayer\n key={layer.id}\n layer={layer}\n index={index}\n theme={theme}\n entering={enteringIds.has(layer.id)}\n />\n ) : (\n <DrawerLayer\n key={layer.id}\n layer={layer}\n index={index}\n theme={theme}\n entering={enteringIds.has(layer.id)}\n />\n )\n )}\n </>,\n document.body\n );\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var reactDom = require('react-dom');
|
|
5
|
+
|
|
6
|
+
const LayerContext = React.createContext(null);
|
|
7
|
+
function LayerProvider({ children, theme = {} }) {
|
|
8
|
+
const [layers, setLayers] = React.useState([]);
|
|
9
|
+
const generateId = () => `layer-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
10
|
+
const openModal = React.useCallback((options) => {
|
|
11
|
+
const id = generateId();
|
|
12
|
+
setLayers((prev) => [
|
|
13
|
+
...prev,
|
|
14
|
+
{ id, type: "modal", modalOptions: options, isClosing: false },
|
|
15
|
+
]);
|
|
16
|
+
return id;
|
|
17
|
+
}, []);
|
|
18
|
+
const openDrawer = React.useCallback((options) => {
|
|
19
|
+
const id = generateId();
|
|
20
|
+
setLayers((prev) => [
|
|
21
|
+
...prev,
|
|
22
|
+
{ id, type: "drawer", drawerOptions: options, isClosing: false },
|
|
23
|
+
]);
|
|
24
|
+
return id;
|
|
25
|
+
}, []);
|
|
26
|
+
const close = React.useCallback((id) => {
|
|
27
|
+
var _a;
|
|
28
|
+
setLayers((prev) => prev.map((l) => (l.id === id ? Object.assign(Object.assign({}, l), { isClosing: true }) : l)));
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
setLayers((prev) => {
|
|
31
|
+
var _a, _b, _c, _d;
|
|
32
|
+
const layer = prev.find((l) => l.id === id);
|
|
33
|
+
(_b = (_a = layer === null || layer === void 0 ? void 0 : layer.modalOptions) === null || _a === void 0 ? void 0 : _a.onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
34
|
+
(_d = (_c = layer === null || layer === void 0 ? void 0 : layer.drawerOptions) === null || _c === void 0 ? void 0 : _c.onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
35
|
+
return prev.filter((l) => l.id !== id);
|
|
36
|
+
});
|
|
37
|
+
}, ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
38
|
+
}, [theme.animationDuration]);
|
|
39
|
+
const closeAll = React.useCallback(() => {
|
|
40
|
+
var _a;
|
|
41
|
+
setLayers((prev) => prev.map((l) => (Object.assign(Object.assign({}, l), { isClosing: true }))));
|
|
42
|
+
setTimeout(() => setLayers([]), ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
43
|
+
}, [theme.animationDuration]);
|
|
44
|
+
const closeTop = React.useCallback(() => {
|
|
45
|
+
var _a;
|
|
46
|
+
setLayers((prev) => {
|
|
47
|
+
if (prev.length === 0)
|
|
48
|
+
return prev;
|
|
49
|
+
const topId = prev[prev.length - 1].id;
|
|
50
|
+
return prev.map((l) => (l.id === topId ? Object.assign(Object.assign({}, l), { isClosing: true }) : l));
|
|
51
|
+
});
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
setLayers((prev) => {
|
|
54
|
+
var _a, _b, _c, _d;
|
|
55
|
+
if (prev.length === 0)
|
|
56
|
+
return prev;
|
|
57
|
+
const top = prev[prev.length - 1];
|
|
58
|
+
(_b = (_a = top === null || top === void 0 ? void 0 : top.modalOptions) === null || _a === void 0 ? void 0 : _a.onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
59
|
+
(_d = (_c = top === null || top === void 0 ? void 0 : top.drawerOptions) === null || _c === void 0 ? void 0 : _c.onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
60
|
+
return prev.slice(0, -1);
|
|
61
|
+
});
|
|
62
|
+
}, ((_a = theme.animationDuration) !== null && _a !== void 0 ? _a : 250));
|
|
63
|
+
}, [theme.animationDuration]);
|
|
64
|
+
return (React.createElement(LayerContext.Provider, { value: { layers, theme, openModal, openDrawer, close, closeAll, closeTop } }, children));
|
|
65
|
+
}
|
|
66
|
+
function useLayer() {
|
|
67
|
+
const ctx = React.useContext(LayerContext);
|
|
68
|
+
if (!ctx)
|
|
69
|
+
throw new Error("useLayer must be used within a LayerProvider");
|
|
70
|
+
return ctx;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const defaultTheme = {
|
|
74
|
+
backdropColor: "rgba(0, 0, 0, 0.5)",
|
|
75
|
+
backdropBlur: "4px",
|
|
76
|
+
modalBackground: "#ffffff",
|
|
77
|
+
modalBorderRadius: "16px",
|
|
78
|
+
modalShadow: "0 25px 60px rgba(0,0,0,0.2)",
|
|
79
|
+
modalPadding: "28px",
|
|
80
|
+
drawerBackground: "#ffffff",
|
|
81
|
+
drawerShadow: "0 8px 40px rgba(0,0,0,0.18)",
|
|
82
|
+
drawerPadding: "28px",
|
|
83
|
+
zIndexBase: 1000,
|
|
84
|
+
animationDuration: 250,
|
|
85
|
+
};
|
|
86
|
+
const MODAL_SIZES = {
|
|
87
|
+
sm: "360px",
|
|
88
|
+
md: "520px",
|
|
89
|
+
lg: "720px",
|
|
90
|
+
xl: "960px",
|
|
91
|
+
full: "100vw",
|
|
92
|
+
};
|
|
93
|
+
const DRAWER_AXIS = {
|
|
94
|
+
right: { inset: { top: 0, right: 0, bottom: 0 } },
|
|
95
|
+
left: { inset: { top: 0, left: 0, bottom: 0 } },
|
|
96
|
+
bottom: { inset: { left: 0, right: 0, bottom: 0 } },
|
|
97
|
+
top: { inset: { left: 0, right: 0, top: 0 } },
|
|
98
|
+
};
|
|
99
|
+
function getDrawerTransform(placement, isClosing, isEntering) {
|
|
100
|
+
var _a;
|
|
101
|
+
const hidden = (_a = {
|
|
102
|
+
right: "translateX(100%)",
|
|
103
|
+
left: "translateX(-100%)",
|
|
104
|
+
bottom: "translateY(100%)",
|
|
105
|
+
top: "translateY(-100%)",
|
|
106
|
+
}[placement]) !== null && _a !== void 0 ? _a : "translateX(100%)";
|
|
107
|
+
return isClosing || isEntering ? hidden : "translate(0,0)";
|
|
108
|
+
}
|
|
109
|
+
function ModalLayer({ layer, index, theme, entering, }) {
|
|
110
|
+
var _a, _b;
|
|
111
|
+
const { close } = useLayer();
|
|
112
|
+
const opts = layer.modalOptions;
|
|
113
|
+
const zIndex = theme.zIndexBase + index * 10;
|
|
114
|
+
const isVisible = !layer.isClosing && !entering;
|
|
115
|
+
const dur = `${theme.animationDuration}ms`;
|
|
116
|
+
const size = (_b = MODAL_SIZES[(_a = opts.size) !== null && _a !== void 0 ? _a : "md"]) !== null && _b !== void 0 ? _b : MODAL_SIZES.md;
|
|
117
|
+
return (React.createElement("div", { style: {
|
|
118
|
+
position: "fixed",
|
|
119
|
+
inset: 0,
|
|
120
|
+
zIndex,
|
|
121
|
+
display: "flex",
|
|
122
|
+
alignItems: "center",
|
|
123
|
+
justifyContent: "center",
|
|
124
|
+
transition: `opacity ${dur} ease`,
|
|
125
|
+
opacity: isVisible ? 1 : 0,
|
|
126
|
+
} },
|
|
127
|
+
React.createElement("div", { style: {
|
|
128
|
+
position: "absolute",
|
|
129
|
+
inset: 0,
|
|
130
|
+
background: theme.backdropColor,
|
|
131
|
+
backdropFilter: `blur(${theme.backdropBlur})`,
|
|
132
|
+
}, onClick: () => opts.closeOnBackdrop !== false && close(layer.id) }),
|
|
133
|
+
React.createElement("div", { role: "dialog", "aria-modal": "true", style: {
|
|
134
|
+
position: "relative",
|
|
135
|
+
width: size === "100vw" ? "100%" : size,
|
|
136
|
+
maxWidth: "calc(100vw - 32px)",
|
|
137
|
+
maxHeight: "calc(100vh - 64px)",
|
|
138
|
+
background: theme.modalBackground,
|
|
139
|
+
borderRadius: opts.size === "full" ? 0 : theme.modalBorderRadius,
|
|
140
|
+
boxShadow: theme.modalShadow,
|
|
141
|
+
padding: theme.modalPadding,
|
|
142
|
+
overflowY: "auto",
|
|
143
|
+
transition: `transform ${dur} cubic-bezier(0.34, 1.56, 0.64, 1), opacity ${dur} ease`,
|
|
144
|
+
transform: isVisible ? "scale(1)" : "scale(0.92)",
|
|
145
|
+
}, onClick: (e) => e.stopPropagation() },
|
|
146
|
+
opts.title && (React.createElement("div", { style: {
|
|
147
|
+
display: "flex",
|
|
148
|
+
justifyContent: "space-between",
|
|
149
|
+
alignItems: "center",
|
|
150
|
+
marginBottom: 20,
|
|
151
|
+
} },
|
|
152
|
+
React.createElement("h2", { style: { margin: 0, fontSize: 18, fontWeight: 700 } }, opts.title),
|
|
153
|
+
React.createElement("button", { onClick: () => close(layer.id), "aria-label": "Close", style: {
|
|
154
|
+
background: "none",
|
|
155
|
+
border: "none",
|
|
156
|
+
fontSize: 20,
|
|
157
|
+
cursor: "pointer",
|
|
158
|
+
opacity: 0.4,
|
|
159
|
+
padding: "0 4px",
|
|
160
|
+
lineHeight: 1,
|
|
161
|
+
} }, "\u2715"))),
|
|
162
|
+
opts.content)));
|
|
163
|
+
}
|
|
164
|
+
function DrawerLayer({ layer, index, theme, entering, }) {
|
|
165
|
+
var _a, _b;
|
|
166
|
+
const { close } = useLayer();
|
|
167
|
+
const opts = layer.drawerOptions;
|
|
168
|
+
const placement = (_a = opts.placement) !== null && _a !== void 0 ? _a : "right";
|
|
169
|
+
const zIndex = theme.zIndexBase + index * 10;
|
|
170
|
+
const isVisible = !layer.isClosing && !entering;
|
|
171
|
+
const dur = `${theme.animationDuration}ms`;
|
|
172
|
+
const isHorizontal = placement === "left" || placement === "right";
|
|
173
|
+
const defaultSize = isHorizontal ? "380px" : "50vh";
|
|
174
|
+
const size = (_b = opts.size) !== null && _b !== void 0 ? _b : defaultSize;
|
|
175
|
+
const axis = DRAWER_AXIS[placement];
|
|
176
|
+
const sizeStyle = isHorizontal
|
|
177
|
+
? { width: size, height: "100%" }
|
|
178
|
+
: { height: size, width: "100%" };
|
|
179
|
+
return (React.createElement("div", { style: { position: "fixed", inset: 0, zIndex, pointerEvents: "none" } },
|
|
180
|
+
React.createElement("div", { style: {
|
|
181
|
+
position: "absolute",
|
|
182
|
+
inset: 0,
|
|
183
|
+
background: theme.backdropColor,
|
|
184
|
+
backdropFilter: `blur(${theme.backdropBlur})`,
|
|
185
|
+
pointerEvents: "all",
|
|
186
|
+
transition: `opacity ${dur} ease`,
|
|
187
|
+
opacity: isVisible ? 1 : 0,
|
|
188
|
+
}, onClick: () => opts.closeOnBackdrop !== false && close(layer.id) }),
|
|
189
|
+
React.createElement("div", { role: "dialog", "aria-modal": "true", style: Object.assign(Object.assign(Object.assign({ position: "absolute" }, axis.inset), sizeStyle), { background: theme.drawerBackground, boxShadow: theme.drawerShadow, padding: theme.drawerPadding, overflowY: "auto", pointerEvents: "all", transition: `transform ${dur} cubic-bezier(0.4, 0, 0.2, 1)`, transform: getDrawerTransform(placement, layer.isClosing, entering) }), onClick: (e) => e.stopPropagation() },
|
|
190
|
+
React.createElement("div", { style: {
|
|
191
|
+
display: "flex",
|
|
192
|
+
justifyContent: "space-between",
|
|
193
|
+
alignItems: "center",
|
|
194
|
+
marginBottom: opts.title ? 20 : 0,
|
|
195
|
+
} },
|
|
196
|
+
opts.title && (React.createElement("h2", { style: { margin: 0, fontSize: 18, fontWeight: 700 } }, opts.title)),
|
|
197
|
+
React.createElement("button", { onClick: () => close(layer.id), "aria-label": "Close", style: {
|
|
198
|
+
background: "none",
|
|
199
|
+
border: "none",
|
|
200
|
+
fontSize: 20,
|
|
201
|
+
cursor: "pointer",
|
|
202
|
+
opacity: 0.4,
|
|
203
|
+
marginLeft: "auto",
|
|
204
|
+
padding: "0 4px",
|
|
205
|
+
lineHeight: 1,
|
|
206
|
+
} }, "\u2715")),
|
|
207
|
+
opts.content)));
|
|
208
|
+
}
|
|
209
|
+
function LayerRenderer() {
|
|
210
|
+
const { layers, theme: userTheme, close, closeTop } = useLayer();
|
|
211
|
+
const theme = Object.assign(Object.assign({}, defaultTheme), userTheme);
|
|
212
|
+
const [enteringIds, setEnteringIds] = React.useState(new Set());
|
|
213
|
+
const prevLayerIds = React.useRef(new Set());
|
|
214
|
+
// Track newly added layers for enter animation
|
|
215
|
+
React.useEffect(() => {
|
|
216
|
+
const newIds = new Set();
|
|
217
|
+
layers.forEach((l) => {
|
|
218
|
+
if (!prevLayerIds.current.has(l.id))
|
|
219
|
+
newIds.add(l.id);
|
|
220
|
+
});
|
|
221
|
+
if (newIds.size > 0) {
|
|
222
|
+
setEnteringIds((prev) => new Set([...prev, ...newIds]));
|
|
223
|
+
requestAnimationFrame(() => {
|
|
224
|
+
requestAnimationFrame(() => {
|
|
225
|
+
setEnteringIds((prev) => {
|
|
226
|
+
const next = new Set(prev);
|
|
227
|
+
newIds.forEach((id) => next.delete(id));
|
|
228
|
+
return next;
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
prevLayerIds.current = new Set(layers.map((l) => l.id));
|
|
234
|
+
}, [layers]);
|
|
235
|
+
// Keyboard Escape handler
|
|
236
|
+
React.useEffect(() => {
|
|
237
|
+
if (layers.length === 0)
|
|
238
|
+
return;
|
|
239
|
+
const handler = (e) => {
|
|
240
|
+
var _a, _b;
|
|
241
|
+
if (e.key !== "Escape")
|
|
242
|
+
return;
|
|
243
|
+
const top = layers[layers.length - 1];
|
|
244
|
+
const esc = top.type === "modal"
|
|
245
|
+
? ((_a = top.modalOptions) === null || _a === void 0 ? void 0 : _a.closeOnEsc) !== false
|
|
246
|
+
: ((_b = top.drawerOptions) === null || _b === void 0 ? void 0 : _b.closeOnEsc) !== false;
|
|
247
|
+
if (esc)
|
|
248
|
+
closeTop();
|
|
249
|
+
};
|
|
250
|
+
window.addEventListener("keydown", handler);
|
|
251
|
+
return () => window.removeEventListener("keydown", handler);
|
|
252
|
+
}, [layers, closeTop]);
|
|
253
|
+
// Lock body scroll when layers are open
|
|
254
|
+
React.useEffect(() => {
|
|
255
|
+
document.body.style.overflow = layers.length > 0 ? "hidden" : "";
|
|
256
|
+
return () => { document.body.style.overflow = ""; };
|
|
257
|
+
}, [layers.length]);
|
|
258
|
+
if (layers.length === 0)
|
|
259
|
+
return null;
|
|
260
|
+
return reactDom.createPortal(React.createElement(React.Fragment, null, layers.map((layer, index) => layer.type === "modal" ? (React.createElement(ModalLayer, { key: layer.id, layer: layer, index: index, theme: theme, entering: enteringIds.has(layer.id) })) : (React.createElement(DrawerLayer, { key: layer.id, layer: layer, index: index, theme: theme, entering: enteringIds.has(layer.id) })))), document.body);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
exports.LayerProvider = LayerProvider;
|
|
264
|
+
exports.LayerRenderer = LayerRenderer;
|
|
265
|
+
exports.useLayer = useLayer;
|
|
266
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/LayerContext.tsx","../src/components/LayerRenderer.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useId,\n} from \"react\";\n\nexport type LayerType = \"modal\" | \"drawer\";\nexport type DrawerPlacement = \"left\" | \"right\" | \"top\" | \"bottom\";\n\nexport interface LayerTheme {\n backdropColor?: string;\n backdropBlur?: string;\n modalBackground?: string;\n modalBorderRadius?: string;\n modalShadow?: string;\n modalPadding?: string;\n drawerBackground?: string;\n drawerShadow?: string;\n drawerPadding?: string;\n zIndexBase?: number;\n animationDuration?: number;\n}\n\nexport interface OpenModalOptions {\n title?: string;\n content: React.ReactNode;\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n onClose?: () => void;\n}\n\nexport interface OpenDrawerOptions {\n title?: string;\n content: React.ReactNode;\n placement?: DrawerPlacement;\n size?: string;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n onClose?: () => void;\n}\n\nexport interface LayerEntry {\n id: string;\n type: LayerType;\n modalOptions?: OpenModalOptions;\n drawerOptions?: OpenDrawerOptions;\n isClosing: boolean;\n}\n\ninterface LayerContextValue {\n layers: LayerEntry[];\n theme: LayerTheme;\n openModal: (options: OpenModalOptions) => string;\n openDrawer: (options: OpenDrawerOptions) => string;\n close: (id: string) => void;\n closeAll: () => void;\n closeTop: () => void;\n}\n\nconst LayerContext = createContext<LayerContextValue | null>(null);\n\nexport interface LayerProviderProps {\n children: React.ReactNode;\n theme?: LayerTheme;\n}\n\nexport function LayerProvider({ children, theme = {} }: LayerProviderProps) {\n const [layers, setLayers] = useState<LayerEntry[]>([]);\n\n const generateId = () =>\n `layer-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n\n const openModal = useCallback((options: OpenModalOptions): string => {\n const id = generateId();\n setLayers((prev) => [\n ...prev,\n { id, type: \"modal\", modalOptions: options, isClosing: false },\n ]);\n return id;\n }, []);\n\n const openDrawer = useCallback((options: OpenDrawerOptions): string => {\n const id = generateId();\n setLayers((prev) => [\n ...prev,\n { id, type: \"drawer\", drawerOptions: options, isClosing: false },\n ]);\n return id;\n }, []);\n\n const close = useCallback((id: string) => {\n setLayers((prev) =>\n prev.map((l) => (l.id === id ? { ...l, isClosing: true } : l))\n );\n setTimeout(() => {\n setLayers((prev) => {\n const layer = prev.find((l) => l.id === id);\n layer?.modalOptions?.onClose?.();\n layer?.drawerOptions?.onClose?.();\n return prev.filter((l) => l.id !== id);\n });\n }, (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n const closeAll = useCallback(() => {\n setLayers((prev) => prev.map((l) => ({ ...l, isClosing: true })));\n setTimeout(() => setLayers([]), (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n const closeTop = useCallback(() => {\n setLayers((prev) => {\n if (prev.length === 0) return prev;\n const topId = prev[prev.length - 1].id;\n return prev.map((l) => (l.id === topId ? { ...l, isClosing: true } : l));\n });\n setTimeout(() => {\n setLayers((prev) => {\n if (prev.length === 0) return prev;\n const top = prev[prev.length - 1];\n top?.modalOptions?.onClose?.();\n top?.drawerOptions?.onClose?.();\n return prev.slice(0, -1);\n });\n }, (theme.animationDuration ?? 250));\n }, [theme.animationDuration]);\n\n return (\n <LayerContext.Provider\n value={{ layers, theme, openModal, openDrawer, close, closeAll, closeTop }}\n >\n {children}\n </LayerContext.Provider>\n );\n}\n\nexport function useLayer() {\n const ctx = useContext(LayerContext);\n if (!ctx) throw new Error(\"useLayer must be used within a LayerProvider\");\n return ctx;\n}\n","import React, { useEffect, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useLayer, LayerEntry, LayerTheme } from \"./LayerContext\";\n\nconst defaultTheme: Required<LayerTheme> = {\n backdropColor: \"rgba(0, 0, 0, 0.5)\",\n backdropBlur: \"4px\",\n modalBackground: \"#ffffff\",\n modalBorderRadius: \"16px\",\n modalShadow: \"0 25px 60px rgba(0,0,0,0.2)\",\n modalPadding: \"28px\",\n drawerBackground: \"#ffffff\",\n drawerShadow: \"0 8px 40px rgba(0,0,0,0.18)\",\n drawerPadding: \"28px\",\n zIndexBase: 1000,\n animationDuration: 250,\n};\n\nconst MODAL_SIZES: Record<string, string> = {\n sm: \"360px\",\n md: \"520px\",\n lg: \"720px\",\n xl: \"960px\",\n full: \"100vw\",\n};\n\nconst DRAWER_AXIS: Record<string, { width?: string; height?: string; inset: React.CSSProperties }> = {\n right: { inset: { top: 0, right: 0, bottom: 0 } },\n left: { inset: { top: 0, left: 0, bottom: 0 } },\n bottom: { inset: { left: 0, right: 0, bottom: 0 } },\n top: { inset: { left: 0, right: 0, top: 0 } },\n};\n\nfunction getDrawerTransform(placement: string, isClosing: boolean, isEntering: boolean): string {\n const hidden = {\n right: \"translateX(100%)\",\n left: \"translateX(-100%)\",\n bottom: \"translateY(100%)\",\n top: \"translateY(-100%)\",\n }[placement] ?? \"translateX(100%)\";\n return isClosing || isEntering ? hidden : \"translate(0,0)\";\n}\n\nfunction ModalLayer({\n layer,\n index,\n theme,\n entering,\n}: {\n layer: LayerEntry;\n index: number;\n theme: Required<LayerTheme>;\n entering: boolean;\n}) {\n const { close } = useLayer();\n const opts = layer.modalOptions!;\n const zIndex = theme.zIndexBase + index * 10;\n const isVisible = !layer.isClosing && !entering;\n const dur = `${theme.animationDuration}ms`;\n const size = MODAL_SIZES[opts.size ?? \"md\"] ?? MODAL_SIZES.md;\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: `opacity ${dur} ease`,\n opacity: isVisible ? 1 : 0,\n }}\n >\n {/* Backdrop */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: theme.backdropColor,\n backdropFilter: `blur(${theme.backdropBlur})`,\n }}\n onClick={() => opts.closeOnBackdrop !== false && close(layer.id)}\n />\n\n {/* Modal box */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n style={{\n position: \"relative\",\n width: size === \"100vw\" ? \"100%\" : size,\n maxWidth: \"calc(100vw - 32px)\",\n maxHeight: \"calc(100vh - 64px)\",\n background: theme.modalBackground,\n borderRadius: opts.size === \"full\" ? 0 : theme.modalBorderRadius,\n boxShadow: theme.modalShadow,\n padding: theme.modalPadding,\n overflowY: \"auto\",\n transition: `transform ${dur} cubic-bezier(0.34, 1.56, 0.64, 1), opacity ${dur} ease`,\n transform: isVisible ? \"scale(1)\" : \"scale(0.92)\",\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n {opts.title && (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 20,\n }}\n >\n <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>{opts.title}</h2>\n <button\n onClick={() => close(layer.id)}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n fontSize: 20,\n cursor: \"pointer\",\n opacity: 0.4,\n padding: \"0 4px\",\n lineHeight: 1,\n }}\n >\n ✕\n </button>\n </div>\n )}\n {opts.content}\n </div>\n </div>\n );\n}\n\nfunction DrawerLayer({\n layer,\n index,\n theme,\n entering,\n}: {\n layer: LayerEntry;\n index: number;\n theme: Required<LayerTheme>;\n entering: boolean;\n}) {\n const { close } = useLayer();\n const opts = layer.drawerOptions!;\n const placement = opts.placement ?? \"right\";\n const zIndex = theme.zIndexBase + index * 10;\n const isVisible = !layer.isClosing && !entering;\n const dur = `${theme.animationDuration}ms`;\n const isHorizontal = placement === \"left\" || placement === \"right\";\n const defaultSize = isHorizontal ? \"380px\" : \"50vh\";\n const size = opts.size ?? defaultSize;\n const axis = DRAWER_AXIS[placement];\n\n const sizeStyle: React.CSSProperties = isHorizontal\n ? { width: size, height: \"100%\" }\n : { height: size, width: \"100%\" };\n\n return (\n <div style={{ position: \"fixed\", inset: 0, zIndex, pointerEvents: \"none\" }}>\n {/* Backdrop */}\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: theme.backdropColor,\n backdropFilter: `blur(${theme.backdropBlur})`,\n pointerEvents: \"all\",\n transition: `opacity ${dur} ease`,\n opacity: isVisible ? 1 : 0,\n }}\n onClick={() => opts.closeOnBackdrop !== false && close(layer.id)}\n />\n\n {/* Drawer panel */}\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n style={{\n position: \"absolute\",\n ...axis.inset,\n ...sizeStyle,\n background: theme.drawerBackground,\n boxShadow: theme.drawerShadow,\n padding: theme.drawerPadding,\n overflowY: \"auto\",\n pointerEvents: \"all\",\n transition: `transform ${dur} cubic-bezier(0.4, 0, 0.2, 1)`,\n transform: getDrawerTransform(placement, layer.isClosing, entering),\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: opts.title ? 20 : 0,\n }}\n >\n {opts.title && (\n <h2 style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>{opts.title}</h2>\n )}\n <button\n onClick={() => close(layer.id)}\n aria-label=\"Close\"\n style={{\n background: \"none\",\n border: \"none\",\n fontSize: 20,\n cursor: \"pointer\",\n opacity: 0.4,\n marginLeft: \"auto\",\n padding: \"0 4px\",\n lineHeight: 1,\n }}\n >\n ✕\n </button>\n </div>\n {opts.content}\n </div>\n </div>\n );\n}\n\nexport function LayerRenderer() {\n const { layers, theme: userTheme, close, closeTop } = useLayer();\n const theme = { ...defaultTheme, ...userTheme };\n const [enteringIds, setEnteringIds] = React.useState<Set<string>>(new Set());\n const prevLayerIds = useRef<Set<string>>(new Set());\n\n // Track newly added layers for enter animation\n useEffect(() => {\n const newIds = new Set<string>();\n layers.forEach((l) => {\n if (!prevLayerIds.current.has(l.id)) newIds.add(l.id);\n });\n if (newIds.size > 0) {\n setEnteringIds((prev) => new Set([...prev, ...newIds]));\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setEnteringIds((prev) => {\n const next = new Set(prev);\n newIds.forEach((id) => next.delete(id));\n return next;\n });\n });\n });\n }\n prevLayerIds.current = new Set(layers.map((l) => l.id));\n }, [layers]);\n\n // Keyboard Escape handler\n useEffect(() => {\n if (layers.length === 0) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n const top = layers[layers.length - 1];\n const esc =\n top.type === \"modal\"\n ? top.modalOptions?.closeOnEsc !== false\n : top.drawerOptions?.closeOnEsc !== false;\n if (esc) closeTop();\n };\n window.addEventListener(\"keydown\", handler);\n return () => window.removeEventListener(\"keydown\", handler);\n }, [layers, closeTop]);\n\n // Lock body scroll when layers are open\n useEffect(() => {\n document.body.style.overflow = layers.length > 0 ? \"hidden\" : \"\";\n return () => { document.body.style.overflow = \"\"; };\n }, [layers.length]);\n\n if (layers.length === 0) return null;\n\n return createPortal(\n <>\n {layers.map((layer, index) =>\n layer.type === \"modal\" ? (\n <ModalLayer\n key={layer.id}\n layer={layer}\n index={index}\n theme={theme}\n entering={enteringIds.has(layer.id)}\n />\n ) : (\n <DrawerLayer\n key={layer.id}\n layer={layer}\n index={index}\n theme={theme}\n entering={enteringIds.has(layer.id)}\n />\n )\n )}\n </>,\n document.body\n );\n}\n"],"names":["createContext","useState","useCallback","useContext","useRef","useEffect","createPortal"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-layer-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Zero-dependency React library for stacking modals and drawers with animations and full TypeScript support",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": ["dist", "README.md"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "rollup -c",
|
|
11
|
+
"dev": "rollup -c --watch",
|
|
12
|
+
"typecheck": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["react", "modal", "drawer", "dialog", "overlay", "stack", "animation", "typescript"],
|
|
15
|
+
"author": "Iresh Eranga",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"react": ">=17.0.0",
|
|
19
|
+
"react-dom": ">=17.0.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
23
|
+
"@rollup/plugin-typescript": "^11.0.0",
|
|
24
|
+
"rollup": "^3.0.0",
|
|
25
|
+
"rollup-plugin-dts": "^5.0.0",
|
|
26
|
+
"tslib": "^2.6.0",
|
|
27
|
+
"typescript": "^5.0.0",
|
|
28
|
+
"@types/react": "^18.0.0",
|
|
29
|
+
"@types/react-dom": "^18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/IreshEranga/react-layer-kit.git"
|
|
34
|
+
}
|
|
35
|
+
}
|