layerpro 4.0.1 → 4.1.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/llms.txt CHANGED
@@ -12,9 +12,10 @@
12
12
  ## Source
13
13
 
14
14
  - [index.ts](index.ts): Entry point. Sets `window.layerpro` (frozen, non-enumerable), imports SCSS, initializes mode.
15
- - [core/dom.ts](core/dom.ts): jQuery-free chainable DOM helper (`LpEl`, `lp`, `lpAll`, `lpCreate`, `lpDoc`, `lpWin`) - the replacement for jQuery.
15
+ - [core/dom.ts](core/dom.ts): jQuery-free chainable DOM helper (`LpEl`, `lp`, `lpAll`, `lpCreate`, `lpDoc`, `lpWin`) - the replacement for jQuery. Document aware: elements are created and resolved in the document of the scope they belong to.
16
+ - [core/scope.ts](core/scope.ts): The scope of a layer - the (window, document) pair it is drawn in. Resolves a target (native window id, Window, scope) into a scope and keeps the scope of every open layer.
16
17
  - [core/properties.ts](core/properties.ts): The `popup` object - `open`, `close`, `center`, `maximize`, `iconize`, `index`, `zIndex`, `movable`, `resizable`, `cleanupEvents`, `unmount`.
17
- - [core/genLayer.ts](core/genLayer.ts): DOM builder for a popup, dock/buttons wiring, pointer/click/dblclick handlers.
18
+ - [core/genLayer.ts](core/genLayer.ts): DOM builder for a popup, dock/buttons wiring, pointer/click/dblclick handlers. The window surface is a native `<dialog>`, shown with `show()`; the confirm/cancel row lives in `.popup_internal` (not in the body), so a React body cannot wipe it.
18
19
  - [core/accessibility.ts](core/accessibility.ts): ARIA attributes, focus save/restore, Tab focus trap.
19
20
  - [core/message.ts](core/message.ts): `alert`/`confirm`/`message`/`prompt` - Promise-based (resolve on close); in 4.0 globals are opt-in via `layerpro/global`, `noGlobals` is removed.
20
21
  - [core/mode.ts](core/mode.ts): Close popups on orientation/size mode switch.
@@ -45,6 +46,9 @@
45
46
  ## Key behaviors
46
47
 
47
48
  - **jQuery removed** - all DOM via `core/dom.ts`; public API unchanged.
49
+ - **Windows are native `<dialog>` elements** - shown with `show()` (not `showModal()`), so the element stays in the normal flow and the LayerPro geometry, drag, resize and stacking order are unchanged. The UA look (canvas background, padding, border, auto margin) is reset by the stylesheet.
50
+ - **The button row is outside the body** - the `buttons` option renders its row in `.popup_internal`, next to the body, and reuses it on every re-open. React owns the body container and empties it on commit, so a row inside the body would be wiped.
51
+ - **Target window** - `props.target` names the window a layer is drawn in (native window id, Window, or scope); `layerpro.window(target)` returns a handle bound to that window; the modals accept `{ target }`. Without a target a layer is drawn in the document of the realm that loaded LayerPro.
48
52
  - **React external** - only the modal `body` is rendered with `react-dom` `createRoot`.
49
53
  - **Instant resize** - CSS `transition` disabled on the popup while resizing (no lag).
50
54
  - **Maximize is pure CSS** - `position: fixed` + insets; follows viewport with no JS listeners.
package/markdown/GUIDE.md CHANGED
@@ -20,15 +20,16 @@ body when you pass a React element.
20
20
  3. [Basic Modals](#basic-modals)
21
21
  4. [Custom Popups](#custom-popups)
22
22
  5. [OS-style Windows](#os-style-windows)
23
- 6. [Options Reference](#options-reference)
24
- 7. [Dock & Taskbar](#dock--taskbar)
25
- 8. [Maximize & Minimize](#maximize--minimize)
26
- 9. [Dragging & Resizing](#dragging--resizing)
27
- 10. [React Body](#react-body)
28
- 11. [Selection & z-index](#selection--z-index)
29
- 12. [API Methods](#api-methods)
30
- 13. [Styling & z-index](#styling--z-index)
31
- 14. [Notes & Migration](#notes--migration)
23
+ 6. [Targeting a window](#targeting-a-window)
24
+ 7. [Options Reference](#options-reference)
25
+ 8. [Dock & Taskbar](#dock--taskbar)
26
+ 9. [Maximize & Minimize](#maximize--minimize)
27
+ 10. [Dragging & Resizing](#dragging--resizing)
28
+ 11. [React Body](#react-body)
29
+ 12. [Selection & z-index](#selection--z-index)
30
+ 13. [API Methods](#api-methods)
31
+ 14. [Styling & z-index](#styling--z-index)
32
+ 15. [Notes & Migration](#notes--migration)
32
33
 
33
34
  ---
34
35
 
@@ -183,6 +184,51 @@ layerpro.popup.open({
183
184
 
184
185
  ---
185
186
 
187
+ ## Targeting a window
188
+
189
+ Every layer belongs to one window: the document it is drawn in. By default
190
+ that is the document of the page that loaded LayerPro. The `target` option
191
+ names another window, so a window opened with `native: true` can host its
192
+ own layers instead of seeing them land on the opener.
193
+
194
+ ```javascript
195
+ // A real browser window
196
+ await layerpro.popup.open({
197
+ id: "desk",
198
+ name: "Desktop",
199
+ native: true
200
+ });
201
+
202
+ // A layer inside that window
203
+ await layerpro.popup.open({
204
+ id: "detail",
205
+ body: "<p>Inside the desk</p>",
206
+ target: "desk"
207
+ });
208
+
209
+ // The handle bound to that window does the same
210
+ const desk = layerpro.window("desk");
211
+ await desk.popup.open({ id: "detail2", body: "<p>Also inside</p>" });
212
+
213
+ // The modals accept a target too
214
+ await layerpro.confirm("Save the changes?", { target: "desk" });
215
+ ```
216
+
217
+ A target is one of:
218
+
219
+ | Target | Meaning |
220
+ |--------|---------|
221
+ | `string` / `number` | the id of a native window opened by LayerPro |
222
+ | `Window` | that browser window, when it is reachable (same origin) |
223
+ | `{ win, doc }` | an explicit scope |
224
+
225
+ The target window carries the LayerPro stylesheet, so a layer drawn there
226
+ looks exactly like a layer drawn on the page. A target that cannot be
227
+ reached (unknown id, closed window, another origin) produces a warning and
228
+ the layer is drawn in the current document.
229
+
230
+ ---
231
+
186
232
  ## Options Reference
187
233
 
188
234
  ```typescript
@@ -223,8 +269,13 @@ layerpro.popup.open({
223
269
  dockable?: boolean, // show an icon in the dock bar
224
270
  close?: boolean, // show the close button
225
271
  modal?: boolean, // show a full-screen overlay that blocks pointer events beneath
226
- }
227
- ```
272
+
273
+ // The window the layer is drawn in: the id of a native window, a Window
274
+ // object, or a { win, doc } scope. Without it the layer is drawn in the
275
+ // document of the page that loaded LayerPro.
276
+ target?: string | number | Window | LayerScope,
277
+ }
278
+ ```
228
279
 
229
280
  If `top/left/right/bottom` are all `0` (or unset) the popup is auto-centered.
230
281
  Pass `center: true` to force centering regardless of the position props.
@@ -334,6 +385,11 @@ layerpro.popup.open({
334
385
 
335
386
  React state, effects, and context all work normally inside the body.
336
387
 
388
+ The body container belongs to React: React empties it when it commits the first
389
+ render. Anything LayerPro needs to keep inside the window is therefore drawn in
390
+ the internal area (`.popup_internal`), next to the body - this is where the
391
+ confirm/cancel row lives, so a React body can never wipe it.
392
+
337
393
  ---
338
394
 
339
395
  ## Selection & z-index
@@ -366,6 +422,7 @@ layerpro.popup.index({ id: "myModal" });
366
422
  | `layerpro.popup.cleanupEvents(id)` | Remove dock/button/esc listeners |
367
423
  | `layerpro.popup.unmount(id)` | Unmount the React root (memory cleanup) |
368
424
  | `layerpro.config(opts)` | Runtime config. Supports `{ nonce: string }` for CSP; sets `window.__layerproNonce`. Call before importing LayerPro for the nonce to be present at CSS injection time |
425
+ | `layerpro.window(target)` | A handle bound to one window: `win`, `doc` and a `popup` API whose layers are drawn in that window |
369
426
  | `layerpro.installGlobals()` | Explicitly install global `alert`/`confirm`/`prompt`/`message` overrides (opt-in in 4.0) |
370
427
 
371
428
  ---
@@ -401,6 +458,20 @@ Stable class names (`.popup_bar`, `.popup_window`, `.popup_overflow`,
401
458
  `.popup_modal`) are emitted alongside the per-id classes so themes can target
402
459
  elements without attribute selectors.
403
460
 
461
+ The window surface itself is a native `<dialog>` element: it is shown with
462
+ `show()` (not `showModal()`), so it stays in the normal flow and the LayerPro
463
+ geometry and stacking order keep working. The native look of the element
464
+ (canvas background, padding, border, auto margin) is reset by the LayerPro
465
+ stylesheet, so a theme keeps painting the window exactly as before.
466
+
467
+ The confirm/cancel row built from the `buttons` option is a child of
468
+ `.popup_internal`, **next to** the body and not inside it: React owns the body
469
+ container and empties it when it commits, so a row kept inside the body was
470
+ wiped by the first render. Target it with `.buttons` (or `.lp_confirm` /
471
+ `.lp_cancel`), never with `.popup_body .buttons`. The built-in
472
+ `alert` / `confirm` / `prompt` / `message` modals carry their own row inside
473
+ their body markup.
474
+
404
475
  ### Overriding the CSS
405
476
 
406
477
  LayerPro never writes a plain inline style: every declaration lives in the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "layerpro",
3
3
  "codeName": "layerpro",
4
- "version": "4.0.1",
4
+ "version": "4.1.0",
5
5
  "description": "The real custom modals, alert, confirm, prompt... for your browser",
6
6
  "main": "./index.cjs",
7
7
  "module": "./index.js",
@@ -18,6 +18,49 @@ interface LayerButtonsConfig {
18
18
  cancel?: LayerButtonConfig
19
19
  }
20
20
 
21
+ /**
22
+ * The window and the document a layer is drawn in.
23
+ * A layer always belongs to one scope: the document of the window it was
24
+ * opened in.
25
+ */
26
+ interface LayerScope {
27
+ win: Window
28
+ doc: Document
29
+ }
30
+
31
+ /**
32
+ * Everything that can name the window a layer is drawn in:
33
+ * - a popup id -> the native browser window opened with that id
34
+ * - a Window -> that window, when it is reachable (same origin)
35
+ * - a LayerScope -> that scope
36
+ */
37
+ type LayerTarget = string | number | Window | LayerScope
38
+
39
+ /** Options accepted by the modals. */
40
+ interface LayerModalOptions {
41
+ /** The window the modal is drawn in. */
42
+ target?: LayerTarget
43
+ }
44
+
45
+ /** A handle bound to one window, used to open layers in that window. */
46
+ interface LayerWindow {
47
+ /** The target this handle is bound to. */
48
+ readonly id: string | number | Window
49
+ /** The browser window, when it can be reached. */
50
+ readonly win: Window | null
51
+ /** The document of the window, when it can be reached. */
52
+ readonly doc: Document | null
53
+ /** The popup API, bound to that window. */
54
+ readonly popup: {
55
+ open: (props: GenLayerProps) => Promise<GenLayerProps>
56
+ close: (id: string | number | GenLayerProps | null | undefined) => void
57
+ center: (id: string | number | GenLayerProps, offset?: number) => void
58
+ maximize: (props: GenLayerProps) => void
59
+ iconize: (id: string | number | GenLayerProps) => void
60
+ index: (id: string | number | GenLayerProps) => void
61
+ }
62
+ }
63
+
21
64
  interface GenLayerProps {
22
65
  id: string | number
23
66
  body?: React.ReactElement | string | HTMLElement
@@ -78,6 +121,11 @@ interface GenLayerProps {
78
121
  * A reload/refresh of the opener does NOT close the native window.
79
122
  */
80
123
  closeWithOpener?: boolean
124
+ /**
125
+ * The window this layer is drawn in. Without a target the layer is drawn
126
+ * in the document of the realm that loaded LayerPro.
127
+ */
128
+ target?: LayerTarget
81
129
  }
82
130
 
83
131
  /**
@@ -95,15 +143,21 @@ interface GenLayerProps {
95
143
  config: (opts: { nonce?: string }) => void
96
144
 
97
145
  /** Open a LayerPro alert. Returns a Promise that resolves when the popup closes. */
98
- readonly alert: (txt: string) => Promise<void>
146
+ readonly alert: (txt: string, opts?: LayerModalOptions) => Promise<void>
99
147
  /** Open a LayerPro prompt. Returns a Promise that resolves to the input string. */
100
- readonly prompt: (txt: string, defaultValue?: string) => Promise<string>
148
+ readonly prompt: (txt: string, defaultValue?: string, opts?: LayerModalOptions) => Promise<string>
101
149
  /** Open a LayerPro message popup. Returns a Promise that resolves when it closes. */
102
- readonly message: (txt: string) => Promise<void>
150
+ readonly message: (txt: string, opts?: LayerModalOptions) => Promise<void>
103
151
  /** Open a LayerPro confirm. Returns a Promise that resolves to a boolean. */
104
- readonly confirm: (txt: string) => Promise<boolean>
152
+ readonly confirm: (txt: string, opts?: LayerModalOptions) => Promise<boolean>
105
153
  readonly credits: (props: { name: string, version: string, description: string, license: string, author: { name: string, email: string } }) => void
106
154
 
155
+ /**
156
+ * A handle bound to one window. Every layer opened through the handle is
157
+ * drawn in that window, not in the one that loaded LayerPro.
158
+ */
159
+ readonly window: (target: string | number | Window) => LayerWindow
160
+
107
161
  setProps: (obj: Record<string, unknown>, options?: { enumerable?: boolean, writable?: boolean, configurable?: boolean }) => void
108
162
 
109
163
  /** Opt-in to override the browser's native `alert`/`confirm`/`prompt`/`message`
@@ -129,7 +183,7 @@ interface GenLayerProps {
129
183
  cleanupEvents: (id: string) => void
130
184
  abortSource: (id: string) => void
131
185
  /** @internal - managed internally for stacking order; do not call. */
132
- zIndex: (props?: GenLayerProps) => number
186
+ zIndex: (scope?: LayerScope) => number
133
187
  useReactAdapter?: (props: GenLayerProps, container: HTMLElement) => void
134
188
  }
135
189