layerpro 3.2.0 → 3.3.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 +78 -150
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# LayerPro
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
@@ -7,42 +7,50 @@
|
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|

|
|
10
|
-
|
|
11
10
|

|
|
12
11
|

|
|
13
12
|

|
|
14
13
|

|
|
15
|
-
|
|
16
14
|

|
|
17
15
|

|
|
18
16
|

|
|
19
|
-
|
|
20
17
|

|
|
21
18
|

|
|
22
19
|

|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
LayerPro replaces the browser's native `alert()`, `confirm()`, and `prompt()` with beautiful, fully customizable modals that work everywhere — no more blocking the main thread, no more default browser styling.
|
|
22
|
+
|
|
23
|
+
## Table of Contents
|
|
24
|
+
|
|
25
|
+
- [Features](#features)
|
|
26
|
+
- [Installation](#installation)
|
|
27
|
+
- [Quick Start](#quick-start)
|
|
28
|
+
- [Usage](#usage)
|
|
29
|
+
- [Basic Modals](#basic-modals)
|
|
30
|
+
- [Custom Popups](#custom-popups)
|
|
31
|
+
- [React Components](#react-components)
|
|
32
|
+
- [The `body` Parameter](#the-body-parameter)
|
|
33
|
+
- [Options](#options)
|
|
34
|
+
- [Global Overrides](#global-overrides)
|
|
35
|
+
- [Methods](#methods)
|
|
36
|
+
- [Styling & z-index](#styling--z-index)
|
|
37
|
+
- [Security](#security)
|
|
38
|
+
- [Browser Support](#browser-support)
|
|
39
|
+
- [Contributing](#contributing)
|
|
40
|
+
- [License](#license)
|
|
31
41
|
|
|
32
42
|
---
|
|
33
43
|
|
|
34
44
|
## Features
|
|
35
45
|
|
|
36
|
-
- **Zero runtime dependencies
|
|
37
|
-
- **Multiple modal types
|
|
38
|
-
- **Fully customizable
|
|
39
|
-
- **Dockable windows (taskbar
|
|
40
|
-
- **Draggable &
|
|
41
|
-
- **
|
|
42
|
-
- **Fade in/out
|
|
43
|
-
- **TypeScript support
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
+
- **Zero runtime dependencies** — no jQuery, pure vanilla DOM helpers; `react`/`react-dom` are peer dependencies, only loaded when React bodies are used, powered by [`reattach`](https://npmjs.com/package/reattach)
|
|
47
|
+
- **Multiple modal types** — alert, confirm, prompt, message
|
|
48
|
+
- **Fully customizable** — appearance, behavior, and content
|
|
49
|
+
- **Dockable windows** (taskbar-style) — click a dock icon to restore, focus, or minimize, just like an OS taskbar
|
|
50
|
+
- **Draggable & resizable** — instant, with no transition lag while resizing
|
|
51
|
+
- **CSS-only maximize** — uses `position: fixed` + insets, so it follows the viewport with no JS resize listeners
|
|
52
|
+
- **Fade in/out transitions** for open/close
|
|
53
|
+
- **Full TypeScript support**
|
|
46
54
|
|
|
47
55
|
## Installation
|
|
48
56
|
|
|
@@ -56,17 +64,15 @@ Or use directly in HTML:
|
|
|
56
64
|
<script src="https://cdn.jsdelivr.net/npm/layerpro"></script>
|
|
57
65
|
```
|
|
58
66
|
|
|
59
|
-
---
|
|
60
|
-
|
|
61
67
|
## Quick Start
|
|
62
68
|
|
|
63
|
-
Import LayerPro once in your app entry point:
|
|
69
|
+
Import LayerPro once, in your app's entry point:
|
|
64
70
|
|
|
65
71
|
```javascript
|
|
66
72
|
import "layerpro";
|
|
67
73
|
```
|
|
68
74
|
|
|
69
|
-
That's it
|
|
75
|
+
That's it — `alert()`, `confirm()`, `prompt()`, `message()`, and `popup()` are now available globally.
|
|
70
76
|
|
|
71
77
|
The `popup` alias is a shorthand for `layerpro.popup`:
|
|
72
78
|
|
|
@@ -78,8 +84,6 @@ layerpro.popup.open({ id: 'myPopup', body: 'Hello World' });
|
|
|
78
84
|
popup.open({ id: 'myPopup', body: 'Hello World' });
|
|
79
85
|
```
|
|
80
86
|
|
|
81
|
-
---
|
|
82
|
-
|
|
83
87
|
## Usage
|
|
84
88
|
|
|
85
89
|
### Basic Modals
|
|
@@ -100,8 +104,6 @@ message("Operation complete!");
|
|
|
100
104
|
|
|
101
105
|
### Custom Popups
|
|
102
106
|
|
|
103
|
-
You can use either `layerpro.popup.open(...)` or the shorthand `popup.open(...)`:
|
|
104
|
-
|
|
105
107
|
```javascript
|
|
106
108
|
popup.open({
|
|
107
109
|
id: 'myModal',
|
|
@@ -114,33 +116,17 @@ popup.open({
|
|
|
114
116
|
cancel: { text: "Cancel", cb: () => {} }
|
|
115
117
|
}
|
|
116
118
|
});
|
|
117
|
-
|
|
118
|
-
// Or using the global alias:
|
|
119
|
-
popup.open({
|
|
120
|
-
id: 'myModal',
|
|
121
|
-
name: 'My Modal',
|
|
122
|
-
body: '<p>Your content here</p>',
|
|
123
|
-
width: 450,
|
|
124
|
-
height: 350,
|
|
125
|
-
buttons: {
|
|
126
|
-
confirm: { text: "OK", cb: () => {} },
|
|
127
|
-
cancel: { text: "Cancel", cb: () => {} }
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
119
|
```
|
|
131
120
|
|
|
132
121
|
### React Components
|
|
133
122
|
|
|
134
|
-
LayerPro's React adapter is powered by [`reattach`](https://npmjs.com/package/reattach) —
|
|
135
|
-
zero-dependency library for mounting React components anywhere in the DOM. reattach handles
|
|
136
|
-
root creation, automatic root reuse on duplicate-id reopen, **Context Bridging** across
|
|
137
|
-
detached roots, and **Auto-healing DOM** recovery — all without you lifting a finger.
|
|
123
|
+
LayerPro's React adapter is powered by [`reattach`](https://npmjs.com/package/reattach), a zero-dependency library for mounting React components anywhere in the DOM. It handles root creation, automatic root reuse on duplicate-id reopen, **Context Bridging** across detached roots, and **auto-healing DOM** recovery — all without extra setup.
|
|
138
124
|
|
|
139
125
|
```jsx
|
|
140
126
|
popup.open({
|
|
141
127
|
id: 'reactModal',
|
|
142
128
|
name: 'React Modal',
|
|
143
|
-
body: <MyComponent />,
|
|
129
|
+
body: <MyComponent />,
|
|
144
130
|
width: 500,
|
|
145
131
|
height: 400
|
|
146
132
|
});
|
|
@@ -166,34 +152,29 @@ function App() {
|
|
|
166
152
|
popup.open({
|
|
167
153
|
id: 'contextual',
|
|
168
154
|
body: <ThemedWidget />,
|
|
169
|
-
inheritContext: true,
|
|
170
|
-
resilient: true,
|
|
155
|
+
inheritContext: true,
|
|
156
|
+
resilient: true,
|
|
171
157
|
});
|
|
172
158
|
```
|
|
173
159
|
|
|
174
160
|
### The `body` Parameter
|
|
175
161
|
|
|
176
|
-
The `body` property accepts different content types:
|
|
177
|
-
|
|
178
162
|
| Type | Example |
|
|
179
163
|
|------|---------|
|
|
180
164
|
| Plain text | `body: "Hello"` |
|
|
181
165
|
| HTML string | `body: "<p>Hello</p>"` |
|
|
182
166
|
| React element | `body: <Component />` |
|
|
183
167
|
|
|
184
|
-
> **Note**:
|
|
185
|
-
|
|
186
|
-
---
|
|
168
|
+
> **Note**: in React, always use elements (`<Component />`), not function calls (`Component()`).
|
|
187
169
|
|
|
188
170
|
## Options
|
|
189
171
|
|
|
190
172
|
```typescript
|
|
191
173
|
{
|
|
192
|
-
id: string,
|
|
193
|
-
body: any,
|
|
194
|
-
name: string,
|
|
195
|
-
icon: string,
|
|
196
|
-
// string (e.g. '<i class="fa fa-star"></i>')
|
|
174
|
+
id: string, // Unique ID (auto-generated as popup_1, popup_2, ... if omitted)
|
|
175
|
+
body: any, // Content (text, HTML, or React)
|
|
176
|
+
name: string, // Modal title
|
|
177
|
+
icon: string, // Icon glyph — HTML entity (e.g. "⚠") or HTML string
|
|
197
178
|
|
|
198
179
|
// Dimensions (defaults: width 340, height 220; minWidth 340, minHeight 220)
|
|
199
180
|
width: number,
|
|
@@ -203,36 +184,34 @@ The `body` property accepts different content types:
|
|
|
203
184
|
maxWidth: number,
|
|
204
185
|
maxHeight: number,
|
|
205
186
|
|
|
206
|
-
// Remote content (same-origin only
|
|
207
|
-
source: string,
|
|
187
|
+
// Remote content (same-origin only, enforced)
|
|
188
|
+
source: string,
|
|
208
189
|
|
|
209
190
|
// React adapter (via reattach)
|
|
210
|
-
inheritContext: boolean,
|
|
211
|
-
resilient: boolean,
|
|
191
|
+
inheritContext: boolean,
|
|
192
|
+
resilient: boolean,
|
|
212
193
|
|
|
213
194
|
// Position (numbers are px; strings applied as-is, e.g. "10%")
|
|
214
195
|
top: number | string,
|
|
215
196
|
left: number | string,
|
|
216
197
|
right: number | string,
|
|
217
198
|
bottom: number | string,
|
|
218
|
-
center: boolean,
|
|
219
|
-
// cascade offset per open window so stacks don't overlap)
|
|
199
|
+
center: boolean, // Center the popup (adds a small cascade offset per open window)
|
|
220
200
|
|
|
221
201
|
// Animation
|
|
222
|
-
fadeIn: number,
|
|
223
|
-
fadeOut: number,
|
|
224
|
-
timer: number,
|
|
202
|
+
fadeIn: number, // open fade duration (ms, default 100)
|
|
203
|
+
fadeOut: number, // close fade duration (ms, default 100)
|
|
204
|
+
timer: number, // auto-close after N ms
|
|
225
205
|
|
|
226
206
|
// Features
|
|
227
|
-
movable: boolean,
|
|
228
|
-
resizable: boolean,
|
|
229
|
-
maximize: boolean,
|
|
230
|
-
iconize: boolean,
|
|
231
|
-
dockable: boolean,
|
|
232
|
-
close: boolean,
|
|
233
|
-
raised: boolean,
|
|
234
|
-
|
|
235
|
-
modal: boolean, // alias of raised
|
|
207
|
+
movable: boolean,
|
|
208
|
+
resizable: boolean,
|
|
209
|
+
maximize: boolean, // double-click title bar to maximize
|
|
210
|
+
iconize: boolean, // allow minimize to dock
|
|
211
|
+
dockable: boolean, // show an icon in the dock bar
|
|
212
|
+
close: boolean, // show the close button
|
|
213
|
+
raised: boolean, // alias: modal — full-screen overlay that blocks pointer events beneath
|
|
214
|
+
modal: boolean, // alias of raised
|
|
236
215
|
|
|
237
216
|
// Buttons
|
|
238
217
|
buttons: {
|
|
@@ -242,19 +221,13 @@ The `body` property accepts different content types:
|
|
|
242
221
|
}
|
|
243
222
|
```
|
|
244
223
|
|
|
245
|
-
> **`raised` / `modal`** injects a full-viewport overlay (`popup_raised_<id>`) that
|
|
246
|
-
> intercepts every pointer event — the page underneath becomes unclickable until the
|
|
247
|
-
> popup closes. This is modal behavior; both names are accepted.
|
|
224
|
+
> **`raised` / `modal`** injects a full-viewport overlay (`popup_raised_<id>`) that intercepts every pointer event — the page underneath becomes unclickable until the popup closes. Both names are accepted.
|
|
248
225
|
|
|
249
|
-
> **Duplicate id** — opening a popup whose `id` already exists brings that window to
|
|
250
|
-
> the front and refreshes its `body`/`buttons` instead of doing nothing.
|
|
251
|
-
|
|
252
|
-
---
|
|
226
|
+
> **Duplicate id** — opening a popup whose `id` already exists brings that window to the front and refreshes its `body`/`buttons` instead of doing nothing.
|
|
253
227
|
|
|
254
228
|
## Global Overrides
|
|
255
229
|
|
|
256
|
-
Importing LayerPro replaces the native `alert`, `confirm`, and `prompt` globals with
|
|
257
|
-
callback-based versions, and adds a `message` global:
|
|
230
|
+
Importing LayerPro replaces the native `alert`, `confirm`, and `prompt` globals with callback-based versions, and adds a `message` global:
|
|
258
231
|
|
|
259
232
|
```javascript
|
|
260
233
|
import "layerpro";
|
|
@@ -265,49 +238,37 @@ prompt("Name?", name => {...}); // LayerPro prompt (callback, not a string r
|
|
|
265
238
|
message("Done!"); // LayerPro message
|
|
266
239
|
```
|
|
267
240
|
|
|
268
|
-
> **⚠️ Important:** the overridden `confirm()` no longer returns a `boolean` and
|
|
269
|
-
> `prompt()` no longer returns a `string`. They are callback-based and return
|
|
270
|
-
> `undefined`. Any third-party code that does `if (confirm("..."))` will silently
|
|
271
|
-
> fall into the falsy branch. If your codebase depends on the native synchronous
|
|
272
|
-
> return values, call **`layerpro.noGlobals()`** right after importing LayerPro to
|
|
273
|
-
> restore the originals:
|
|
241
|
+
> **⚠️ Important:** the overridden `confirm()` no longer returns a `boolean`, and `prompt()` no longer returns a `string` — they are callback-based and return `undefined`. Any third-party code that does `if (confirm("..."))` will silently fall into the falsy branch. If your codebase depends on native synchronous return values, call **`layerpro.noGlobals()`** right after importing LayerPro to restore the originals:
|
|
274
242
|
>
|
|
275
243
|
> ```javascript
|
|
276
244
|
> import "layerpro";
|
|
277
245
|
> layerpro.noGlobals(); // restores native alert/confirm/prompt, drops `message`
|
|
278
246
|
> ```
|
|
279
247
|
|
|
280
|
-
---
|
|
281
|
-
|
|
282
248
|
## Methods
|
|
283
249
|
|
|
284
250
|
| Method | Description |
|
|
285
251
|
|--------|-------------|
|
|
286
|
-
| `popup.open(props)` | Open a modal; returns the props. Re-opens a same-id window to front
|
|
252
|
+
| `popup.open(props)` | Open a modal; returns the props. Re-opens a same-id window to front and refreshes its body. |
|
|
287
253
|
| `popup.close(id)` | Close (and unmount) a modal. |
|
|
288
|
-
| `popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset |
|
|
289
|
-
| `popup.maximize(props)` | Toggle maximize (pure CSS) |
|
|
290
|
-
| `popup.iconize(id)` | Toggle minimize to the dock |
|
|
291
|
-
| `popup.index(id)` | Bring a modal to the front (select) |
|
|
292
|
-
| `popup.zIndex()` | Get the next z-index counter value |
|
|
293
|
-
| `popup.movable(props)` | Enable dragging |
|
|
294
|
-
| `popup.resizable(props)` | Enable resizing |
|
|
295
|
-
| `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message
|
|
296
|
-
|
|
297
|
-
---
|
|
254
|
+
| `popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset. |
|
|
255
|
+
| `popup.maximize(props)` | Toggle maximize (pure CSS). |
|
|
256
|
+
| `popup.iconize(id)` | Toggle minimize to the dock. |
|
|
257
|
+
| `popup.index(id)` | Bring a modal to the front (select). |
|
|
258
|
+
| `popup.zIndex()` | Get the next z-index counter value. |
|
|
259
|
+
| `popup.movable(props)` | Enable dragging. |
|
|
260
|
+
| `popup.resizable(props)` | Enable resizing. |
|
|
261
|
+
| `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message`. |
|
|
298
262
|
|
|
299
263
|
## Styling & z-index
|
|
300
264
|
|
|
301
|
-
Popups live in a `#popup` container whose base z-index comes from the
|
|
302
|
-
`--popup-z-index` CSS variable (default `1000`). Apps with their own stacking
|
|
303
|
-
contexts can override it to shift the whole stack:
|
|
265
|
+
Popups live in a `#popup` container whose base z-index comes from the `--popup-z-index` CSS variable (default `1000`). Apps with their own stacking contexts can override it to shift the whole stack:
|
|
304
266
|
|
|
305
267
|
```scss
|
|
306
268
|
:root { --popup-z-index: 100000; }
|
|
307
269
|
```
|
|
308
270
|
|
|
309
|
-
The title bar, window surface, internal area, and body all read from CSS custom
|
|
310
|
-
properties, so theming needs no `!important` or `[class^=popup_…]` selectors:
|
|
271
|
+
The title bar, window surface, internal area, and body all read from CSS custom properties, so theming needs no `!important` or fragile class selectors:
|
|
311
272
|
|
|
312
273
|
| Variable | Applies to |
|
|
313
274
|
|----------|-----------|
|
|
@@ -322,58 +283,25 @@ properties, so theming needs no `!important` or `[class^=popup_…]` selectors:
|
|
|
322
283
|
| `--raised-background` | modal overlay |
|
|
323
284
|
| `--popup-z-index` | base z-index for the stack |
|
|
324
285
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
## Methods
|
|
328
|
-
|
|
329
|
-
| Method | Description |
|
|
330
|
-
|--------|-------------|
|
|
331
|
-
| `popup.open(props)` | Open a modal |
|
|
332
|
-
| `popup.close(id)` | Close a modal |
|
|
333
|
-
| `popup.center(id)` | Center modal |
|
|
334
|
-
| `popup.maximize(id)` | Maximize modal |
|
|
335
|
-
| `popup.iconize(id)` | Minimize to dock |
|
|
336
|
-
| `popup.movable(id)` | Enable drag |
|
|
337
|
-
| `popup.resizable(id)` | Enable resize |
|
|
286
|
+
## Security
|
|
338
287
|
|
|
339
|
-
|
|
288
|
+
- **Same-origin fetch guard** — the `source` prop only accepts same-origin URLs; cross-origin requests are rejected before any network call is made, preventing SSRF and data exfiltration.
|
|
289
|
+
- **HTML escaping** — all user-provided text content (button labels, body content, titles) is automatically escaped via `escapeHtml()` to prevent XSS.
|
|
290
|
+
- **CSP-friendly** — no inline scripts or `eval()` are used. React components are rendered via `reattach.mount()` (backed by `createRoot()`).
|
|
291
|
+
- **Opt-out of global overrides** — call `layerpro.noGlobals()` after import to restore native `alert`, `confirm`, `prompt`, and remove the `message` global if your codebase depends on synchronous return values.
|
|
340
292
|
|
|
341
293
|
## Browser Support
|
|
342
294
|
|
|
343
295
|
Chrome 80+ • Firefox 75+ • Safari 13+ • Edge 80+
|
|
344
296
|
|
|
345
|
-
---
|
|
346
|
-
|
|
347
|
-
## Security
|
|
348
|
-
|
|
349
|
-
LayerPro includes several security measures:
|
|
350
|
-
|
|
351
|
-
- **Same-origin fetch guard**: The `source` prop only accepts same-origin URLs. Cross-origin requests are rejected before any network call is made, preventing SSRF and data exfiltration.
|
|
352
|
-
|
|
353
|
-
- **HTML escaping**: All user-provided text content (button labels, body content, titles) is automatically escaped via `escapeHtml()` to prevent XSS. HTML entities like `<`, `>`, `&`, `"` are converted to their safe equivalents.
|
|
354
|
-
|
|
355
|
-
- **Content Security Policy friendly**: No inline scripts or `eval()` are used. React components are rendered via `reattach.mount()` (backed by `createRoot()`) with proper sanitization.
|
|
356
|
-
|
|
357
|
-
- **No global pollution option**: Call `layerpro.noGlobals()` after import to restore native `alert`, `confirm`, `prompt` and remove the `message` global if your codebase depends on synchronous return values.
|
|
358
|
-
|
|
359
|
-
---
|
|
360
|
-
|
|
361
297
|
## Contributing
|
|
362
298
|
|
|
363
|
-
LayerPro is
|
|
364
|
-
but **anyone is welcome to join**. If you'd like to contribute, propose changes,
|
|
365
|
-
or just talk about the project, get in touch:
|
|
299
|
+
LayerPro's source is currently private, but contributions and discussion are welcome. Get in touch:
|
|
366
300
|
|
|
367
301
|
- **Dario Passariello** — https://dario.passariello.ca/ — dariopassariello@gmail.com
|
|
368
302
|
|
|
369
|
-
Participation is voluntary and free — everyone is free to take part.
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
303
|
## License
|
|
374
304
|
|
|
375
305
|
MIT License
|
|
376
306
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
Copyrigth (c) [Dario Passariello](https://dario.passariello.ca/)
|
|
307
|
+
Copyright (c) [Dario Passariello](https://dario.passariello.ca/)
|