layerpro 3.1.0 → 3.1.5
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/FUNDING.yml +12 -0
- package/README.md +44 -19
- package/index.cjs +338 -306
- package/index.js +336 -308
- package/markdown/GUIDE.md +367 -367
- package/package.json +35 -13
- package/react.cjs +18 -0
- package/react.js +18 -0
- package/types/layerpro.d.ts +132 -129
package/markdown/GUIDE.md
CHANGED
|
@@ -1,367 +1,367 @@
|
|
|
1
|
-
# LayerPro Guide
|
|
2
|
-
|
|
3
|
-
> A practical, example-driven guide to LayerPro — the real custom modals
|
|
4
|
-
> (alert, confirm, prompt, message) and advanced popups for the browser.
|
|
5
|
-
|
|
6
|
-
LayerPro is **dependency-free**: it no longer uses jQuery. All DOM work is done
|
|
7
|
-
with small, chainable vanilla helpers. React and react-dom are the only
|
|
8
|
-
external runtime dependencies, and they are used **only** to render the modal
|
|
9
|
-
body when you pass a React element.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Table of Contents
|
|
14
|
-
|
|
15
|
-
1. [Installation](#installation)
|
|
16
|
-
2. [Quick Start](#quick-start)
|
|
17
|
-
3. [Basic Modals](#basic-modals)
|
|
18
|
-
4. [Custom Popups](#custom-popups)
|
|
19
|
-
5. [Options Reference](#options-reference)
|
|
20
|
-
6. [Dock & Taskbar](#dock--taskbar)
|
|
21
|
-
7. [Maximize & Minimize](#maximize--minimize)
|
|
22
|
-
8. [Dragging & Resizing](#dragging--resizing)
|
|
23
|
-
9. [React Body](#react-body)
|
|
24
|
-
10. [Selection & z-index](#selection--z-index)
|
|
25
|
-
11. [API Methods](#api-methods)
|
|
26
|
-
12. [Notes & Migration](#notes--migration)
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install layerpro
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Or drop it straight into HTML (UMD build):
|
|
37
|
-
|
|
38
|
-
```html
|
|
39
|
-
<script src="https://cdn.jsdelivr.net/npm/layerpro"></script>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Quick Start
|
|
45
|
-
|
|
46
|
-
Import LayerPro once at your app entry point. It overrides the global
|
|
47
|
-
`alert`, `confirm`, `prompt`, and exposes `message` and `layerpro`:
|
|
48
|
-
|
|
49
|
-
```javascript
|
|
50
|
-
import "layerpro";
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
That single import is enough — `window.layerpro` becomes available and the
|
|
54
|
-
global `alert`/`confirm`/`prompt` are replaced, and a `message` global is added.
|
|
55
|
-
|
|
56
|
-
> **⚠️ Global override contract:** the overridden `confirm()` no longer returns a
|
|
57
|
-
> `boolean` and `prompt()` no longer returns a `string` — they are callback-based
|
|
58
|
-
> and return `undefined`. If your codebase (or a third-party dependency) relies on
|
|
59
|
-
> the native synchronous return values, call `layerpro.noGlobals()` right after
|
|
60
|
-
> importing to restore the originals:
|
|
61
|
-
>
|
|
62
|
-
> ```javascript
|
|
63
|
-
> import "layerpro";
|
|
64
|
-
> layerpro.noGlobals(); // restores native alert/confirm/prompt, drops `message`
|
|
65
|
-
> ```
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Basic Modals
|
|
70
|
-
|
|
71
|
-
```javascript
|
|
72
|
-
// Simple alert
|
|
73
|
-
alert("Hello World!");
|
|
74
|
-
|
|
75
|
-
// Confirm with YES / NO callbacks
|
|
76
|
-
confirm(
|
|
77
|
-
"Are you sure?",
|
|
78
|
-
() => console.debug("User clicked YES"),
|
|
79
|
-
() => console.debug("User clicked NO")
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
// Prompt with the typed value
|
|
83
|
-
prompt("What is your name?", (name) => {
|
|
84
|
-
console.debug("User entered:", name);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Plain message (auto-styled info box)
|
|
88
|
-
message("Operation complete!", () => console.debug("message closed"));
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
> The global functions keep the same signatures you already know, so legacy
|
|
92
|
-
> code keeps working.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Custom Popups
|
|
97
|
-
|
|
98
|
-
Use `layerpro.popup.open(props)` for full control.
|
|
99
|
-
|
|
100
|
-
```javascript
|
|
101
|
-
layerpro.popup.open({
|
|
102
|
-
id: "myModal",
|
|
103
|
-
name: "My Modal",
|
|
104
|
-
body: "<p>Your <b>content</b> here</p>",
|
|
105
|
-
width: 450,
|
|
106
|
-
height: 350,
|
|
107
|
-
movable: true,
|
|
108
|
-
resizable: true,
|
|
109
|
-
maximize: true,
|
|
110
|
-
iconize: true,
|
|
111
|
-
dockable: true,
|
|
112
|
-
close: true,
|
|
113
|
-
buttons: {
|
|
114
|
-
confirm: { text: "OK", cb: () => layerpro.popup.close("myModal") },
|
|
115
|
-
cancel: { text: "Cancel", cb: () => layerpro.popup.close("myModal") }
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### The `body` parameter
|
|
121
|
-
|
|
122
|
-
| Type | Example |
|
|
123
|
-
|------|---------|
|
|
124
|
-
| Plain text | `body: "Hello"` |
|
|
125
|
-
| HTML string | `body: "<p>Hello</p>"` |
|
|
126
|
-
| React element | `body: <MyComponent />` |
|
|
127
|
-
|
|
128
|
-
> In React, always pass an **element** (`<Component />`), never a call
|
|
129
|
-
> (`Component()`).
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Options Reference
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
{
|
|
137
|
-
id: string, // Unique id (auto-generated as popup_1, popup_2, … if omitted)
|
|
138
|
-
body: any, // text | HTML string | HTMLElement | React element
|
|
139
|
-
name: string, // Title shown in the bar
|
|
140
|
-
icon: string, // Icon glyph (HTML entity, e.g. "⚠") or HTML string
|
|
141
|
-
// (e.g. '<i class="fa fa-star"></i>')
|
|
142
|
-
class: string, // Extra CSS class on the window
|
|
143
|
-
|
|
144
|
-
// Dimensions (defaults: width 340, height 220; minWidth 340, minHeight 220)
|
|
145
|
-
width?: number | string,
|
|
146
|
-
height?: number | string,
|
|
147
|
-
minWidth?: number,
|
|
148
|
-
minHeight?: number,
|
|
149
|
-
maxWidth?: number,
|
|
150
|
-
maxHeight?: number,
|
|
151
|
-
|
|
152
|
-
// Position (numbers are px; strings are applied as-is, e.g. "10%")
|
|
153
|
-
top?: number | string,
|
|
154
|
-
left?: number | string,
|
|
155
|
-
right?: number | string,
|
|
156
|
-
bottom?: number | string,
|
|
157
|
-
center?: boolean, // Center in the viewport (adds a small cascade
|
|
158
|
-
// offset per open window so stacks don't overlap)
|
|
159
|
-
|
|
160
|
-
// Timing
|
|
161
|
-
fadeIn?: number, // open fade duration (ms, default 100)
|
|
162
|
-
fadeOut?: number, // close fade duration (ms, default 100)
|
|
163
|
-
timer?: number, // auto-close after N ms
|
|
164
|
-
|
|
165
|
-
// Behavior flags
|
|
166
|
-
movable?: boolean, // draggable by the title bar
|
|
167
|
-
resizable?: boolean, // resize handles
|
|
168
|
-
maximize?: boolean, // double-click title bar to maximize
|
|
169
|
-
iconize?: boolean, // allow minimize to dock
|
|
170
|
-
dockable?: boolean, // show an icon in the dock bar
|
|
171
|
-
close?: boolean, // show the close button
|
|
172
|
-
raised?: boolean, // alias: modal — show a full-screen overlay that
|
|
173
|
-
modal?: boolean, // blocks pointer events to the page underneath
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
If `top/left/right/bottom` are all `0` (or unset) the popup is auto-centered.
|
|
178
|
-
Pass `center: true` to force centering regardless of the position props.
|
|
179
|
-
|
|
180
|
-
> **`raised` / `modal`** injects a full-viewport overlay (`popup_raised_<id>`)
|
|
181
|
-
> that intercepts every pointer event — the page underneath becomes unclickable
|
|
182
|
-
> until the popup closes. This is modal behavior; both names are accepted.
|
|
183
|
-
|
|
184
|
-
> **Duplicate id** — opening a popup whose `id` already exists brings that window
|
|
185
|
-
> to the front and refreshes its `body`/`buttons` instead of doing nothing.
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## Dock & Taskbar
|
|
190
|
-
|
|
191
|
-
When `dockable` and `iconize` are enabled, a minimized popup becomes an icon in
|
|
192
|
-
the bottom dock bar — exactly like an OS taskbar:
|
|
193
|
-
|
|
194
|
-
```javascript
|
|
195
|
-
layerpro.popup.open({
|
|
196
|
-
id: "editor",
|
|
197
|
-
name: "Editor",
|
|
198
|
-
body: "<p>Edit something…</p>",
|
|
199
|
-
dockable: true,
|
|
200
|
-
iconize: true
|
|
201
|
-
});
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Dock interactions (taskbar style):**
|
|
205
|
-
|
|
206
|
-
- Click a dock icon of a **minimized** popup → it is restored and focused.
|
|
207
|
-
- Click a dock icon of a popup that is open but **not focused** → it is brought
|
|
208
|
-
to the front.
|
|
209
|
-
- Click a dock icon of the **focused** popup → it is minimized back to the dock.
|
|
210
|
-
|
|
211
|
-
The close `✕` on the dock icon closes the popup completely.
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Maximize & Minimize
|
|
216
|
-
|
|
217
|
-
Maximize is implemented with **pure CSS** (`position: fixed` + `inset`), so the
|
|
218
|
-
popup fills the viewport and follows window resizing automatically — no JS
|
|
219
|
-
resize listeners are involved.
|
|
220
|
-
|
|
221
|
-
```javascript
|
|
222
|
-
layerpro.popup.open({
|
|
223
|
-
id: "viewer",
|
|
224
|
-
name: "Viewer",
|
|
225
|
-
body: "<p>Big content</p>",
|
|
226
|
-
maximize: true,
|
|
227
|
-
iconize: true
|
|
228
|
-
});
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
- **Double-click the title bar** → toggle maximize / restore.
|
|
232
|
-
- **Click the dock icon** of a maximized popup → restore it.
|
|
233
|
-
|
|
234
|
-
Because maximize is CSS-driven, resizing the browser window keeps the maximized
|
|
235
|
-
popup perfectly aligned with no lag.
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## Dragging & Resizing
|
|
240
|
-
|
|
241
|
-
Dragging and resizing are **instant**: the CSS `transition` is disabled on the
|
|
242
|
-
popup while you drag a resize handle, so the popup tracks the pointer with no
|
|
243
|
-
lag (especially on the bottom edge).
|
|
244
|
-
|
|
245
|
-
```javascript
|
|
246
|
-
layerpro.popup.open({
|
|
247
|
-
id: "panel",
|
|
248
|
-
name: "Panel",
|
|
249
|
-
body: "<p>Move and resize me</p>",
|
|
250
|
-
movable: true,
|
|
251
|
-
resizable: true
|
|
252
|
-
});
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
- Drag the **title bar** to move.
|
|
256
|
-
- Drag the **edges/corners** to resize.
|
|
257
|
-
- These interactions are disabled automatically while a popup is maximized.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## React Body
|
|
262
|
-
|
|
263
|
-
Pass a React element as `body` and LayerPro mounts it with `react-dom`
|
|
264
|
-
`createRoot` inside the modal:
|
|
265
|
-
|
|
266
|
-
```jsx
|
|
267
|
-
import { useState } from "react";
|
|
268
|
-
|
|
269
|
-
function Counter() {
|
|
270
|
-
const [n, setN] = useState(0);
|
|
271
|
-
return <button onClick={() => setN(n + 1)}>Clicked {n} times</button>;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
layerpro.popup.open({
|
|
275
|
-
id: "reactModal",
|
|
276
|
-
name: "React Modal",
|
|
277
|
-
body: <Counter />,
|
|
278
|
-
width: 400,
|
|
279
|
-
height: 300
|
|
280
|
-
});
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
React state, effects, and context all work normally inside the body.
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
## Selection & z-index
|
|
288
|
-
|
|
289
|
-
Clicking anywhere on a popup (the body **or** the title bar) brings it to the
|
|
290
|
-
front and gives it the `zHigh` highlight. The dock icon is also marked as
|
|
291
|
-
selected. z-index values are unitless (set as raw numbers, never `px`).
|
|
292
|
-
|
|
293
|
-
```javascript
|
|
294
|
-
// Bring a popup to the front programmatically
|
|
295
|
-
layerpro.popup.index({ id: "myModal" });
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## API Methods
|
|
301
|
-
|
|
302
|
-
| Method | Description |
|
|
303
|
-
|--------|-------------|
|
|
304
|
-
| `layerpro.popup.open(props)` | Open a modal; returns the props. Re-opening a same-id window brings it to front + refreshes body |
|
|
305
|
-
| `layerpro.popup.close(id)` | Close (and unmount) a modal |
|
|
306
|
-
| `layerpro.popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset |
|
|
307
|
-
| `layerpro.popup.maximize(props)` | Toggle maximize (pure CSS) |
|
|
308
|
-
| `layerpro.popup.iconize(id)` | Toggle minimize to the dock |
|
|
309
|
-
| `layerpro.popup.index(id)` | Bring a modal to the front (select) |
|
|
310
|
-
| `layerpro.popup.zIndex()` | Get the next z-index counter value |
|
|
311
|
-
| `layerpro.popup.movable(props)` | Enable dragging |
|
|
312
|
-
| `layerpro.popup.resizable(props)` | Enable resizing |
|
|
313
|
-
| `layerpro.popup.store(element)` | Store a reference (placeholder/extensibility) |
|
|
314
|
-
| `layerpro.popup.cleanupEvents(id)` | Remove dock/button/esc listeners |
|
|
315
|
-
| `layerpro.popup.unmount(id)` | Unmount the React root (memory cleanup) |
|
|
316
|
-
| `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message` |
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
## Styling & z-index
|
|
321
|
-
|
|
322
|
-
Popup z-index starts from the `--popup-z-index` CSS variable (default `1000`).
|
|
323
|
-
Apps with their own stacking contexts (e.g. a tooltip at `z-index: 100000`) can
|
|
324
|
-
shift the whole stack by overriding the variable:
|
|
325
|
-
|
|
326
|
-
```scss
|
|
327
|
-
:root { --popup-z-index: 100000; }
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
The title bar, window surface, internal area, and body all read from CSS custom
|
|
331
|
-
properties, so theming needs no `!important` and no `[class^=popup_…]` selectors:
|
|
332
|
-
|
|
333
|
-
| Variable | Applies to |
|
|
334
|
-
|----------|-----------|
|
|
335
|
-
| `--bar-background` | title bar |
|
|
336
|
-
| `--bar-selected-background` | active/selected title bar |
|
|
337
|
-
| `--bar-color` | title bar text |
|
|
338
|
-
| `--window-background` | popup surface |
|
|
339
|
-
| `--window-shadow` | popup shadow |
|
|
340
|
-
| `--window-border-radius` | popup border radius |
|
|
341
|
-
| `--internal-background` | body wrapper |
|
|
342
|
-
| `--body-color` | body text color |
|
|
343
|
-
| `--raised-background` | modal overlay |
|
|
344
|
-
| `--popup-z-index` (in root.scss) | base z-index for the stack |
|
|
345
|
-
|
|
346
|
-
Stable class names (`.popup_bar`, `.popup_window`, `.popup_overflow`,
|
|
347
|
-
`.popup_internal`, `.popup_body`, `.popup_drag`, `.popup_icon`, `.popup_option`,
|
|
348
|
-
`.popup_raised`) are emitted alongside the per-id classes so themes can target
|
|
349
|
-
elements without attribute selectors.
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
## Notes & Migration
|
|
354
|
-
|
|
355
|
-
- **jQuery removed.** LayerPro no longer depends on jQuery. All DOM access uses
|
|
356
|
-
the internal `core/dom.ts` vanilla helper (`lp`, `lpAll`, `lpCreate`, `lpDoc`,
|
|
357
|
-
`lpWin`). Public behavior is unchanged.
|
|
358
|
-
- **React is external.** `react` and `react-dom` must be provided by the host
|
|
359
|
-
app and are used only to render the modal body.
|
|
360
|
-
- **Instant resize / maximize.** Transitions are disabled during resize, and
|
|
361
|
-
maximize is CSS-only, for a snappy, lag-free feel.
|
|
362
|
-
- **Vanilla pages still work.** No framework is required unless you pass a React
|
|
363
|
-
body.
|
|
364
|
-
|
|
365
|
-
---
|
|
366
|
-
|
|
367
|
-
© [Dario Passariello](https://dario.passariello.ca/) — MIT License
|
|
1
|
+
# LayerPro Guide
|
|
2
|
+
|
|
3
|
+
> A practical, example-driven guide to LayerPro — the real custom modals
|
|
4
|
+
> (alert, confirm, prompt, message) and advanced popups for the browser.
|
|
5
|
+
|
|
6
|
+
LayerPro is **dependency-free**: it no longer uses jQuery. All DOM work is done
|
|
7
|
+
with small, chainable vanilla helpers. React and react-dom are the only
|
|
8
|
+
external runtime dependencies, and they are used **only** to render the modal
|
|
9
|
+
body when you pass a React element.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
1. [Installation](#installation)
|
|
16
|
+
2. [Quick Start](#quick-start)
|
|
17
|
+
3. [Basic Modals](#basic-modals)
|
|
18
|
+
4. [Custom Popups](#custom-popups)
|
|
19
|
+
5. [Options Reference](#options-reference)
|
|
20
|
+
6. [Dock & Taskbar](#dock--taskbar)
|
|
21
|
+
7. [Maximize & Minimize](#maximize--minimize)
|
|
22
|
+
8. [Dragging & Resizing](#dragging--resizing)
|
|
23
|
+
9. [React Body](#react-body)
|
|
24
|
+
10. [Selection & z-index](#selection--z-index)
|
|
25
|
+
11. [API Methods](#api-methods)
|
|
26
|
+
12. [Notes & Migration](#notes--migration)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install layerpro
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or drop it straight into HTML (UMD build):
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<script src="https://cdn.jsdelivr.net/npm/layerpro"></script>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
Import LayerPro once at your app entry point. It overrides the global
|
|
47
|
+
`alert`, `confirm`, `prompt`, and exposes `message` and `layerpro`:
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
import "layerpro";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That single import is enough — `window.layerpro` becomes available and the
|
|
54
|
+
global `alert`/`confirm`/`prompt` are replaced, and a `message` global is added.
|
|
55
|
+
|
|
56
|
+
> **⚠️ Global override contract:** the overridden `confirm()` no longer returns a
|
|
57
|
+
> `boolean` and `prompt()` no longer returns a `string` — they are callback-based
|
|
58
|
+
> and return `undefined`. If your codebase (or a third-party dependency) relies on
|
|
59
|
+
> the native synchronous return values, call `layerpro.noGlobals()` right after
|
|
60
|
+
> importing to restore the originals:
|
|
61
|
+
>
|
|
62
|
+
> ```javascript
|
|
63
|
+
> import "layerpro";
|
|
64
|
+
> layerpro.noGlobals(); // restores native alert/confirm/prompt, drops `message`
|
|
65
|
+
> ```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Basic Modals
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// Simple alert
|
|
73
|
+
alert("Hello World!");
|
|
74
|
+
|
|
75
|
+
// Confirm with YES / NO callbacks
|
|
76
|
+
confirm(
|
|
77
|
+
"Are you sure?",
|
|
78
|
+
() => console.debug("User clicked YES"),
|
|
79
|
+
() => console.debug("User clicked NO")
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Prompt with the typed value
|
|
83
|
+
prompt("What is your name?", (name) => {
|
|
84
|
+
console.debug("User entered:", name);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Plain message (auto-styled info box)
|
|
88
|
+
message("Operation complete!", () => console.debug("message closed"));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
> The global functions keep the same signatures you already know, so legacy
|
|
92
|
+
> code keeps working.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Custom Popups
|
|
97
|
+
|
|
98
|
+
Use `layerpro.popup.open(props)` for full control.
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
layerpro.popup.open({
|
|
102
|
+
id: "myModal",
|
|
103
|
+
name: "My Modal",
|
|
104
|
+
body: "<p>Your <b>content</b> here</p>",
|
|
105
|
+
width: 450,
|
|
106
|
+
height: 350,
|
|
107
|
+
movable: true,
|
|
108
|
+
resizable: true,
|
|
109
|
+
maximize: true,
|
|
110
|
+
iconize: true,
|
|
111
|
+
dockable: true,
|
|
112
|
+
close: true,
|
|
113
|
+
buttons: {
|
|
114
|
+
confirm: { text: "OK", cb: () => layerpro.popup.close("myModal") },
|
|
115
|
+
cancel: { text: "Cancel", cb: () => layerpro.popup.close("myModal") }
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### The `body` parameter
|
|
121
|
+
|
|
122
|
+
| Type | Example |
|
|
123
|
+
|------|---------|
|
|
124
|
+
| Plain text | `body: "Hello"` |
|
|
125
|
+
| HTML string | `body: "<p>Hello</p>"` |
|
|
126
|
+
| React element | `body: <MyComponent />` |
|
|
127
|
+
|
|
128
|
+
> In React, always pass an **element** (`<Component />`), never a call
|
|
129
|
+
> (`Component()`).
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Options Reference
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
{
|
|
137
|
+
id: string, // Unique id (auto-generated as popup_1, popup_2, … if omitted)
|
|
138
|
+
body: any, // text | HTML string | HTMLElement | React element
|
|
139
|
+
name: string, // Title shown in the bar
|
|
140
|
+
icon: string, // Icon glyph (HTML entity, e.g. "⚠") or HTML string
|
|
141
|
+
// (e.g. '<i class="fa fa-star"></i>')
|
|
142
|
+
class: string, // Extra CSS class on the window
|
|
143
|
+
|
|
144
|
+
// Dimensions (defaults: width 340, height 220; minWidth 340, minHeight 220)
|
|
145
|
+
width?: number | string,
|
|
146
|
+
height?: number | string,
|
|
147
|
+
minWidth?: number,
|
|
148
|
+
minHeight?: number,
|
|
149
|
+
maxWidth?: number,
|
|
150
|
+
maxHeight?: number,
|
|
151
|
+
|
|
152
|
+
// Position (numbers are px; strings are applied as-is, e.g. "10%")
|
|
153
|
+
top?: number | string,
|
|
154
|
+
left?: number | string,
|
|
155
|
+
right?: number | string,
|
|
156
|
+
bottom?: number | string,
|
|
157
|
+
center?: boolean, // Center in the viewport (adds a small cascade
|
|
158
|
+
// offset per open window so stacks don't overlap)
|
|
159
|
+
|
|
160
|
+
// Timing
|
|
161
|
+
fadeIn?: number, // open fade duration (ms, default 100)
|
|
162
|
+
fadeOut?: number, // close fade duration (ms, default 100)
|
|
163
|
+
timer?: number, // auto-close after N ms
|
|
164
|
+
|
|
165
|
+
// Behavior flags
|
|
166
|
+
movable?: boolean, // draggable by the title bar
|
|
167
|
+
resizable?: boolean, // resize handles
|
|
168
|
+
maximize?: boolean, // double-click title bar to maximize
|
|
169
|
+
iconize?: boolean, // allow minimize to dock
|
|
170
|
+
dockable?: boolean, // show an icon in the dock bar
|
|
171
|
+
close?: boolean, // show the close button
|
|
172
|
+
raised?: boolean, // alias: modal — show a full-screen overlay that
|
|
173
|
+
modal?: boolean, // blocks pointer events to the page underneath
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
If `top/left/right/bottom` are all `0` (or unset) the popup is auto-centered.
|
|
178
|
+
Pass `center: true` to force centering regardless of the position props.
|
|
179
|
+
|
|
180
|
+
> **`raised` / `modal`** injects a full-viewport overlay (`popup_raised_<id>`)
|
|
181
|
+
> that intercepts every pointer event — the page underneath becomes unclickable
|
|
182
|
+
> until the popup closes. This is modal behavior; both names are accepted.
|
|
183
|
+
|
|
184
|
+
> **Duplicate id** — opening a popup whose `id` already exists brings that window
|
|
185
|
+
> to the front and refreshes its `body`/`buttons` instead of doing nothing.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Dock & Taskbar
|
|
190
|
+
|
|
191
|
+
When `dockable` and `iconize` are enabled, a minimized popup becomes an icon in
|
|
192
|
+
the bottom dock bar — exactly like an OS taskbar:
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
layerpro.popup.open({
|
|
196
|
+
id: "editor",
|
|
197
|
+
name: "Editor",
|
|
198
|
+
body: "<p>Edit something…</p>",
|
|
199
|
+
dockable: true,
|
|
200
|
+
iconize: true
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Dock interactions (taskbar style):**
|
|
205
|
+
|
|
206
|
+
- Click a dock icon of a **minimized** popup → it is restored and focused.
|
|
207
|
+
- Click a dock icon of a popup that is open but **not focused** → it is brought
|
|
208
|
+
to the front.
|
|
209
|
+
- Click a dock icon of the **focused** popup → it is minimized back to the dock.
|
|
210
|
+
|
|
211
|
+
The close `✕` on the dock icon closes the popup completely.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Maximize & Minimize
|
|
216
|
+
|
|
217
|
+
Maximize is implemented with **pure CSS** (`position: fixed` + `inset`), so the
|
|
218
|
+
popup fills the viewport and follows window resizing automatically — no JS
|
|
219
|
+
resize listeners are involved.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
layerpro.popup.open({
|
|
223
|
+
id: "viewer",
|
|
224
|
+
name: "Viewer",
|
|
225
|
+
body: "<p>Big content</p>",
|
|
226
|
+
maximize: true,
|
|
227
|
+
iconize: true
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- **Double-click the title bar** → toggle maximize / restore.
|
|
232
|
+
- **Click the dock icon** of a maximized popup → restore it.
|
|
233
|
+
|
|
234
|
+
Because maximize is CSS-driven, resizing the browser window keeps the maximized
|
|
235
|
+
popup perfectly aligned with no lag.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Dragging & Resizing
|
|
240
|
+
|
|
241
|
+
Dragging and resizing are **instant**: the CSS `transition` is disabled on the
|
|
242
|
+
popup while you drag a resize handle, so the popup tracks the pointer with no
|
|
243
|
+
lag (especially on the bottom edge).
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
layerpro.popup.open({
|
|
247
|
+
id: "panel",
|
|
248
|
+
name: "Panel",
|
|
249
|
+
body: "<p>Move and resize me</p>",
|
|
250
|
+
movable: true,
|
|
251
|
+
resizable: true
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
- Drag the **title bar** to move.
|
|
256
|
+
- Drag the **edges/corners** to resize.
|
|
257
|
+
- These interactions are disabled automatically while a popup is maximized.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## React Body
|
|
262
|
+
|
|
263
|
+
Pass a React element as `body` and LayerPro mounts it with `react-dom`
|
|
264
|
+
`createRoot` inside the modal:
|
|
265
|
+
|
|
266
|
+
```jsx
|
|
267
|
+
import { useState } from "react";
|
|
268
|
+
|
|
269
|
+
function Counter() {
|
|
270
|
+
const [n, setN] = useState(0);
|
|
271
|
+
return <button onClick={() => setN(n + 1)}>Clicked {n} times</button>;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
layerpro.popup.open({
|
|
275
|
+
id: "reactModal",
|
|
276
|
+
name: "React Modal",
|
|
277
|
+
body: <Counter />,
|
|
278
|
+
width: 400,
|
|
279
|
+
height: 300
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
React state, effects, and context all work normally inside the body.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Selection & z-index
|
|
288
|
+
|
|
289
|
+
Clicking anywhere on a popup (the body **or** the title bar) brings it to the
|
|
290
|
+
front and gives it the `zHigh` highlight. The dock icon is also marked as
|
|
291
|
+
selected. z-index values are unitless (set as raw numbers, never `px`).
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
// Bring a popup to the front programmatically
|
|
295
|
+
layerpro.popup.index({ id: "myModal" });
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## API Methods
|
|
301
|
+
|
|
302
|
+
| Method | Description |
|
|
303
|
+
|--------|-------------|
|
|
304
|
+
| `layerpro.popup.open(props)` | Open a modal; returns the props. Re-opening a same-id window brings it to front + refreshes body |
|
|
305
|
+
| `layerpro.popup.close(id)` | Close (and unmount) a modal |
|
|
306
|
+
| `layerpro.popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset |
|
|
307
|
+
| `layerpro.popup.maximize(props)` | Toggle maximize (pure CSS) |
|
|
308
|
+
| `layerpro.popup.iconize(id)` | Toggle minimize to the dock |
|
|
309
|
+
| `layerpro.popup.index(id)` | Bring a modal to the front (select) |
|
|
310
|
+
| `layerpro.popup.zIndex()` | Get the next z-index counter value |
|
|
311
|
+
| `layerpro.popup.movable(props)` | Enable dragging |
|
|
312
|
+
| `layerpro.popup.resizable(props)` | Enable resizing |
|
|
313
|
+
| `layerpro.popup.store(element)` | Store a reference (placeholder/extensibility) |
|
|
314
|
+
| `layerpro.popup.cleanupEvents(id)` | Remove dock/button/esc listeners |
|
|
315
|
+
| `layerpro.popup.unmount(id)` | Unmount the React root (memory cleanup) |
|
|
316
|
+
| `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message` |
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Styling & z-index
|
|
321
|
+
|
|
322
|
+
Popup z-index starts from the `--popup-z-index` CSS variable (default `1000`).
|
|
323
|
+
Apps with their own stacking contexts (e.g. a tooltip at `z-index: 100000`) can
|
|
324
|
+
shift the whole stack by overriding the variable:
|
|
325
|
+
|
|
326
|
+
```scss
|
|
327
|
+
:root { --popup-z-index: 100000; }
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
The title bar, window surface, internal area, and body all read from CSS custom
|
|
331
|
+
properties, so theming needs no `!important` and no `[class^=popup_…]` selectors:
|
|
332
|
+
|
|
333
|
+
| Variable | Applies to |
|
|
334
|
+
|----------|-----------|
|
|
335
|
+
| `--bar-background` | title bar |
|
|
336
|
+
| `--bar-selected-background` | active/selected title bar |
|
|
337
|
+
| `--bar-color` | title bar text |
|
|
338
|
+
| `--window-background` | popup surface |
|
|
339
|
+
| `--window-shadow` | popup shadow |
|
|
340
|
+
| `--window-border-radius` | popup border radius |
|
|
341
|
+
| `--internal-background` | body wrapper |
|
|
342
|
+
| `--body-color` | body text color |
|
|
343
|
+
| `--raised-background` | modal overlay |
|
|
344
|
+
| `--popup-z-index` (in root.scss) | base z-index for the stack |
|
|
345
|
+
|
|
346
|
+
Stable class names (`.popup_bar`, `.popup_window`, `.popup_overflow`,
|
|
347
|
+
`.popup_internal`, `.popup_body`, `.popup_drag`, `.popup_icon`, `.popup_option`,
|
|
348
|
+
`.popup_raised`) are emitted alongside the per-id classes so themes can target
|
|
349
|
+
elements without attribute selectors.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Notes & Migration
|
|
354
|
+
|
|
355
|
+
- **jQuery removed.** LayerPro no longer depends on jQuery. All DOM access uses
|
|
356
|
+
the internal `core/dom.ts` vanilla helper (`lp`, `lpAll`, `lpCreate`, `lpDoc`,
|
|
357
|
+
`lpWin`). Public behavior is unchanged.
|
|
358
|
+
- **React is external.** `react` and `react-dom` must be provided by the host
|
|
359
|
+
app and are used only to render the modal body.
|
|
360
|
+
- **Instant resize / maximize.** Transitions are disabled during resize, and
|
|
361
|
+
maximize is CSS-only, for a snappy, lag-free feel.
|
|
362
|
+
- **Vanilla pages still work.** No framework is required unless you pass a React
|
|
363
|
+
body.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
© [Dario Passariello](https://dario.passariello.ca/) — MIT License
|