layerpro 3.0.1 → 3.1.1
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 +151 -24
- package/index.cjs +355 -324
- package/index.css +63 -45
- package/index.js +355 -322
- package/llms.txt +2 -2
- package/markdown/GUIDE.md +367 -315
- package/package.json +1 -1
- package/types/layerpro.d.ts +39 -25
package/README.md
CHANGED
|
@@ -66,7 +66,17 @@ Import LayerPro once in your app entry point:
|
|
|
66
66
|
import "layerpro";
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
That's it. Now you have `alert()`, `confirm()`, `prompt()`, and `
|
|
69
|
+
That's it. Now you have `alert()`, `confirm()`, `prompt()`, `message()`, and `popup()` globally available.
|
|
70
|
+
|
|
71
|
+
The `popup` alias is a shorthand for `layerpro.popup`:
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
import "layerpro";
|
|
75
|
+
|
|
76
|
+
// Both work identically:
|
|
77
|
+
layerpro.popup.open({ id: 'myPopup', body: 'Hello World' });
|
|
78
|
+
popup.open({ id: 'myPopup', body: 'Hello World' });
|
|
79
|
+
```
|
|
70
80
|
|
|
71
81
|
---
|
|
72
82
|
|
|
@@ -90,8 +100,23 @@ message("Operation complete!");
|
|
|
90
100
|
|
|
91
101
|
### Custom Popups
|
|
92
102
|
|
|
103
|
+
You can use either `layerpro.popup.open(...)` or the shorthand `popup.open(...)`:
|
|
104
|
+
|
|
93
105
|
```javascript
|
|
94
|
-
|
|
106
|
+
popup.open({
|
|
107
|
+
id: 'myModal',
|
|
108
|
+
name: 'My Modal',
|
|
109
|
+
body: '<p>Your content here</p>',
|
|
110
|
+
width: 450,
|
|
111
|
+
height: 350,
|
|
112
|
+
buttons: {
|
|
113
|
+
confirm: { text: "OK", cb: () => {} },
|
|
114
|
+
cancel: { text: "Cancel", cb: () => {} }
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Or using the global alias:
|
|
119
|
+
popup.open({
|
|
95
120
|
id: 'myModal',
|
|
96
121
|
name: 'My Modal',
|
|
97
122
|
body: '<p>Your content here</p>',
|
|
@@ -109,7 +134,7 @@ layerpro.popup.open({
|
|
|
109
134
|
In a React environment, you can pass React components directly:
|
|
110
135
|
|
|
111
136
|
```jsx
|
|
112
|
-
|
|
137
|
+
popup.open({
|
|
113
138
|
id: 'reactModal',
|
|
114
139
|
name: 'React Modal',
|
|
115
140
|
body: <MyComponent />, // React element
|
|
@@ -136,12 +161,13 @@ The `body` property accepts different content types:
|
|
|
136
161
|
|
|
137
162
|
```typescript
|
|
138
163
|
{
|
|
139
|
-
id: string, // Unique ID
|
|
164
|
+
id: string, // Unique ID (auto-generated as popup_1, popup_2, ... if omitted)
|
|
140
165
|
body: any, // Content (text, HTML, or React)
|
|
141
166
|
name: string, // Modal title
|
|
142
|
-
icon: string, // Icon
|
|
167
|
+
icon: string, // Icon glyph — HTML entity (e.g. "⚠") or an HTML
|
|
168
|
+
// string (e.g. '<i class="fa fa-star"></i>')
|
|
143
169
|
|
|
144
|
-
// Dimensions
|
|
170
|
+
// Dimensions (defaults: width 340, height 220; minWidth 340, minHeight 220)
|
|
145
171
|
width: number,
|
|
146
172
|
height: number,
|
|
147
173
|
minWidth: number,
|
|
@@ -149,25 +175,32 @@ The `body` property accepts different content types:
|
|
|
149
175
|
maxWidth: number,
|
|
150
176
|
maxHeight: number,
|
|
151
177
|
|
|
152
|
-
//
|
|
178
|
+
// Remote content (same-origin only for security)
|
|
179
|
+
source: string, // URL to fetch HTML content from (same-origin enforced)
|
|
180
|
+
|
|
181
|
+
// Position (numbers are px; strings applied as-is, e.g. "10%")
|
|
153
182
|
top: number | string,
|
|
154
183
|
left: number | string,
|
|
155
184
|
right: number | string,
|
|
156
185
|
bottom: number | string,
|
|
186
|
+
center: boolean, // Center the popup in the viewport (adds a small
|
|
187
|
+
// cascade offset per open window so stacks don't overlap)
|
|
157
188
|
|
|
158
189
|
// Animation
|
|
159
|
-
fadeIn: number,
|
|
160
|
-
fadeOut: number,
|
|
161
|
-
timer: number,
|
|
190
|
+
fadeIn: number, // open fade duration (ms, default 100)
|
|
191
|
+
fadeOut: number, // close fade duration (ms, default 100)
|
|
192
|
+
timer: number, // auto-close after N ms
|
|
162
193
|
|
|
163
194
|
// Features
|
|
164
|
-
movable: boolean,
|
|
165
|
-
resizable: boolean,
|
|
166
|
-
maximize: boolean,
|
|
167
|
-
iconize: boolean,
|
|
168
|
-
dockable: boolean,
|
|
169
|
-
close: boolean,
|
|
170
|
-
raised: boolean,
|
|
195
|
+
movable: boolean, // draggable by the title bar
|
|
196
|
+
resizable: boolean, // resize handles
|
|
197
|
+
maximize: boolean, // double-click title bar to maximize
|
|
198
|
+
iconize: boolean, // allow minimize to dock
|
|
199
|
+
dockable: boolean, // show an icon in the dock bar
|
|
200
|
+
close: boolean, // show the close button
|
|
201
|
+
raised: boolean, // alias: modal — show a full-screen overlay that blocks
|
|
202
|
+
// pointer events to the page underneath
|
|
203
|
+
modal: boolean, // alias of raised
|
|
171
204
|
|
|
172
205
|
// Buttons
|
|
173
206
|
buttons: {
|
|
@@ -177,19 +210,99 @@ The `body` property accepts different content types:
|
|
|
177
210
|
}
|
|
178
211
|
```
|
|
179
212
|
|
|
213
|
+
> **`raised` / `modal`** injects a full-viewport overlay (`popup_raised_<id>`) that
|
|
214
|
+
> intercepts every pointer event — the page underneath becomes unclickable until the
|
|
215
|
+
> popup closes. This is modal behavior; both names are accepted.
|
|
216
|
+
|
|
217
|
+
> **Duplicate id** — opening a popup whose `id` already exists brings that window to
|
|
218
|
+
> the front and refreshes its `body`/`buttons` instead of doing nothing.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Global Overrides
|
|
223
|
+
|
|
224
|
+
Importing LayerPro replaces the native `alert`, `confirm`, and `prompt` globals with
|
|
225
|
+
callback-based versions, and adds a `message` global:
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
import "layerpro";
|
|
229
|
+
|
|
230
|
+
alert("Hello World!"); // LayerPro alert
|
|
231
|
+
confirm("Sure?", yes => {...}); // LayerPro confirm (callback, not a boolean return!)
|
|
232
|
+
prompt("Name?", name => {...}); // LayerPro prompt (callback, not a string return!)
|
|
233
|
+
message("Done!"); // LayerPro message
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
> **⚠️ Important:** the overridden `confirm()` no longer returns a `boolean` and
|
|
237
|
+
> `prompt()` no longer returns a `string`. They are callback-based and return
|
|
238
|
+
> `undefined`. Any third-party code that does `if (confirm("..."))` will silently
|
|
239
|
+
> fall into the falsy branch. If your codebase depends on the native synchronous
|
|
240
|
+
> return values, call **`layerpro.noGlobals()`** right after importing LayerPro to
|
|
241
|
+
> restore the originals:
|
|
242
|
+
>
|
|
243
|
+
> ```javascript
|
|
244
|
+
> import "layerpro";
|
|
245
|
+
> layerpro.noGlobals(); // restores native alert/confirm/prompt, drops `message`
|
|
246
|
+
> ```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Methods
|
|
251
|
+
|
|
252
|
+
| Method | Description |
|
|
253
|
+
|--------|-------------|
|
|
254
|
+
| `popup.open(props)` | Open a modal; returns the props. Re-opens a same-id window to front + refreshes body. |
|
|
255
|
+
| `popup.close(id)` | Close (and unmount) a modal. |
|
|
256
|
+
| `popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset |
|
|
257
|
+
| `popup.maximize(props)` | Toggle maximize (pure CSS) |
|
|
258
|
+
| `popup.iconize(id)` | Toggle minimize to the dock |
|
|
259
|
+
| `popup.index(id)` | Bring a modal to the front (select) |
|
|
260
|
+
| `popup.zIndex()` | Get the next z-index counter value |
|
|
261
|
+
| `popup.movable(props)` | Enable dragging |
|
|
262
|
+
| `popup.resizable(props)` | Enable resizing |
|
|
263
|
+
| `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message` |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Styling & z-index
|
|
268
|
+
|
|
269
|
+
Popups live in a `#popup` container whose base z-index comes from the
|
|
270
|
+
`--popup-z-index` CSS variable (default `1000`). Apps with their own stacking
|
|
271
|
+
contexts can override it to shift the whole stack:
|
|
272
|
+
|
|
273
|
+
```scss
|
|
274
|
+
:root { --popup-z-index: 100000; }
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The title bar, window surface, internal area, and body all read from CSS custom
|
|
278
|
+
properties, so theming needs no `!important` or `[class^=popup_…]` selectors:
|
|
279
|
+
|
|
280
|
+
| Variable | Applies to |
|
|
281
|
+
|----------|-----------|
|
|
282
|
+
| `--bar-background` | title bar |
|
|
283
|
+
| `--bar-selected-background` | active/selected title bar |
|
|
284
|
+
| `--bar-color` | title bar text |
|
|
285
|
+
| `--window-background` | popup surface |
|
|
286
|
+
| `--window-shadow` | popup shadow |
|
|
287
|
+
| `--window-border-radius` | popup border radius |
|
|
288
|
+
| `--internal-background` | body wrapper |
|
|
289
|
+
| `--body-color` | body text color |
|
|
290
|
+
| `--raised-background` | modal overlay |
|
|
291
|
+
| `--popup-z-index` | base z-index for the stack |
|
|
292
|
+
|
|
180
293
|
---
|
|
181
294
|
|
|
182
295
|
## Methods
|
|
183
296
|
|
|
184
297
|
| Method | Description |
|
|
185
298
|
|--------|-------------|
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
299
|
+
| `popup.open(props)` | Open a modal |
|
|
300
|
+
| `popup.close(id)` | Close a modal |
|
|
301
|
+
| `popup.center(id)` | Center modal |
|
|
302
|
+
| `popup.maximize(id)` | Maximize modal |
|
|
303
|
+
| `popup.iconize(id)` | Minimize to dock |
|
|
304
|
+
| `popup.movable(id)` | Enable drag |
|
|
305
|
+
| `popup.resizable(id)` | Enable resize |
|
|
193
306
|
|
|
194
307
|
---
|
|
195
308
|
|
|
@@ -199,6 +312,20 @@ Chrome 80+ • Firefox 75+ • Safari 13+ • Edge 80+
|
|
|
199
312
|
|
|
200
313
|
---
|
|
201
314
|
|
|
315
|
+
## Security
|
|
316
|
+
|
|
317
|
+
LayerPro includes several security measures:
|
|
318
|
+
|
|
319
|
+
- **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.
|
|
320
|
+
|
|
321
|
+
- **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.
|
|
322
|
+
|
|
323
|
+
- **Content Security Policy friendly**: No inline scripts or `eval()` are used. React components are rendered via `createRoot()` with proper sanitization.
|
|
324
|
+
|
|
325
|
+
- **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.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
202
329
|
## Contributing
|
|
203
330
|
|
|
204
331
|
LayerPro is **open source** and free for everyone. The current source is private,
|