layerpro 3.2.0 → 3.4.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 CHANGED
@@ -1,4 +1,4 @@
1
- # [LayerPro](https://npmjs.com/package/layerpro)
1
+ # LayerPro
2
2
 
3
3
  ![layerpro](https://raw.githubusercontent.com/passariello/container/be0611e9bead336dcec32d522d103e7e3661f502/layerpro/assets/logos/logo.svg)
4
4
 
@@ -7,42 +7,50 @@
7
7
 
8
8
  ![Snyk](https://img.shields.io/badge/Snyk-gray?logo=Snyk)
9
9
  ![Socket](https://img.shields.io/badge/Socket-gray?logo=Socket)
10
-
11
10
  ![Node.js](https://img.shields.io/badge/Node.js-gray?logo=node.js)
12
11
  ![Browser](https://img.shields.io/badge/Browser-gray?logo=google-chrome)
13
12
  ![Deno](https://img.shields.io/badge/Deno-gray?logo=deno)
14
13
  ![tsup](https://img.shields.io/badge/tsup-gray?logo=esbuild)
15
-
16
14
  ![React](https://img.shields.io/badge/React-gray?logo=React)
17
15
  ![TypeScript](https://img.shields.io/badge/TypeScript-gray?logo=typescript)
18
16
  ![Javascript](https://img.shields.io/badge/Javascript-gray?logo=Javascript)
19
-
20
17
  ![Vitest](https://img.shields.io/badge/Vitest-gray?logo=vitest)
21
18
  ![OXlint](https://img.shields.io/badge/Oxlint-gray?logo=oxc)
22
19
  ![Playwright](https://img.shields.io/badge/Playwright-gray?logo=playwright)
23
20
 
24
- ---
25
-
26
- ## What is LayerPro?
27
-
28
- LayerPro replaces the boring browser `alert()`, `confirm()`, and `prompt()` with beautiful, customizable modals that work everywhere.
29
-
30
- No more ugly popup boxes. No more blocking the main thread. Just clean, modern modals that your users will love.
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**: 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))
37
- - **Multiple modal types**: alert, confirm, prompt, message
38
- - **Fully customizable**: appearance, behavior, and content
39
- - **Dockable windows (taskbar style)**: click a dock icon to restore, focus, or minimize — just like an OS taskbar
40
- - **Draggable & Resizable**: instant, with no transition lag while resizing
41
- - **Maximize is pure CSS**: uses `position: fixed` + insets, so it follows the viewport with no JS resize listeners
42
- - **Fade in/out** transitions for open/close
43
- - **TypeScript support**: full type definitions
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. Now you have `alert()`, `confirm()`, `prompt()`, `message()`, and `popup()` globally available.
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) — a
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 />, // React element
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, // ContextBridge: ThèmeContext is bridged
170
- resilient: true, // Auto-heals if the container is replaced
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**: In React, always use elements (`<Component />`), not function calls (`Component()`).
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, // Unique ID (auto-generated as popup_1, popup_2, ... if omitted)
193
- body: any, // Content (text, HTML, or React)
194
- name: string, // Modal title
195
- icon: string, // Icon glyph — HTML entity (e.g. "&#9888;") or an HTML
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. "&#9888;") 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 for security)
207
- source: string, // URL to fetch HTML content from (same-origin enforced)
187
+ // Remote content (same-origin only, enforced)
188
+ source: string,
208
189
 
209
190
  // React adapter (via reattach)
210
- inheritContext: boolean, // reattach Context Bridge — replay host React Context into the popup root
211
- resilient: boolean, // reattach Auto-healing DOM — MutationObserver recovery from external DOM mutations
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, // Center the popup in the viewport (adds a small
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, // open fade duration (ms, default 100)
223
- fadeOut: number, // close fade duration (ms, default 100)
224
- timer: number, // auto-close after N ms
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, // draggable by the title bar
228
- resizable: boolean, // resize handles
229
- maximize: boolean, // double-click title bar to maximize
230
- iconize: boolean, // allow minimize to dock
231
- dockable: boolean, // show an icon in the dock bar
232
- close: boolean, // show the close button
233
- raised: boolean, // alias: modal — show a full-screen overlay that blocks
234
- // pointer events to the page underneath
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 + refreshes body. |
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 **open source** and free for everyone. The current source is private,
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:
366
-
367
- - **Dario Passariello** — https://dario.passariello.ca/ — dariopassariello@gmail.com
299
+ LayerPro's source is currently private, but contributions and discussion are welcome. Get in touch:
368
300
 
369
- Participation is voluntary and free — everyone is free to take part.
370
-
371
- ---
301
+ - **Dario Passariello** - https://dario.passariello.ca/ - dariopassariello@gmail.com
372
302
 
373
303
  ## License
374
304
 
375
305
  MIT License
376
306
 
377
- ## Credits
378
-
379
- Copyrigth (c) [Dario Passariello](https://dario.passariello.ca/)
307
+ Copyright (c) [Dario Passariello](https://dario.passariello.ca/)