layerpro 3.1.0 → 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 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 `message()` globally.
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
- layerpro.popup.open({
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
- layerpro.popup.open({
137
+ popup.open({
113
138
  id: 'reactModal',
114
139
  name: 'React Modal',
115
140
  body: <MyComponent />, // React element
@@ -226,15 +251,15 @@ message("Done!"); // LayerPro message
226
251
 
227
252
  | Method | Description |
228
253
  |--------|-------------|
229
- | `layerpro.popup.open(props)` | Open a modal; returns the props. Re-opens a same-id window to front + refreshes body |
230
- | `layerpro.popup.close(id)` | Close (and unmount) a modal |
231
- | `layerpro.popup.center(id, offset?)` | Center a modal in the viewport; optional pixel offset |
232
- | `layerpro.popup.maximize(props)` | Toggle maximize (pure CSS) |
233
- | `layerpro.popup.iconize(id)` | Toggle minimize to the dock |
234
- | `layerpro.popup.index(id)` | Bring a modal to the front (select) |
235
- | `layerpro.popup.zIndex()` | Get the next z-index counter value |
236
- | `layerpro.popup.movable(props)` | Enable dragging |
237
- | `layerpro.popup.resizable(props)` | Enable resizing |
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 |
238
263
  | `layerpro.noGlobals()` | Restore native `alert`/`confirm`/`prompt`; remove `message` |
239
264
 
240
265
  ---
@@ -271,13 +296,13 @@ properties, so theming needs no `!important` or `[class^=popup_…]` selectors:
271
296
 
272
297
  | Method | Description |
273
298
  |--------|-------------|
274
- | `layerpro.popup.open(props)` | Open a modal |
275
- | `layerpro.popup.close(id)` | Close a modal |
276
- | `layerpro.popup.center(id)` | Center modal |
277
- | `layerpro.popup.maximize(id)` | Maximize modal |
278
- | `layerpro.popup.iconize(id)` | Minimize to dock |
279
- | `layerpro.popup.movable(id)` | Enable drag |
280
- | `layerpro.popup.resizable(id)` | Enable resize |
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 |
281
306
 
282
307
  ---
283
308
 
package/index.cjs CHANGED
@@ -34,7 +34,7 @@ Object.defineProperty(i, "credits", {
34
34
  configurable: !1
35
35
  });
36
36
 
37
- var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.querySelector(e) ?? document : e instanceof HTMLElement ? e : document, r = e => e ? e.split(/\s+/).filter(e => e.length > 0) : [], a = new Set([ "opacity", "zindex", "z-index", "fontweight", "font-weight", "lineheight", "line-height", "zoom", "flex", "flexgrow", "flex-grow", "flexshrink", "flex-shrink", "order", "gridcolumn", "grid-column", "gridrow", "grid-row", "columncount", "column-count", "fontsizeadjust", "font-size-adjust", "appearance" ]), c = (e, t) => "number" != typeof t || a.has(e.toLowerCase()) ? String(t) : `${t}px`, l = (e, t, o, i) => {
37
+ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.querySelector(e) ?? document : e instanceof HTMLElement ? e : document, r = e => e ? e.split(/\s+/).filter(e => e.length > 0) : [], a = new Set([ "opacity", "zindex", "z-index", "fontweight", "font-weight", "lineheight", "line-height", "zoom", "flex", "flexgrow", "flex-grow", "flexshrink", "flex-shrink", "order", "gridcolumn", "grid-column", "gridrow", "grid-row", "columncount", "column-count", "fontsizeadjust", "font-size-adjust", "appearance" ]), l = (e, t) => "number" != typeof t || a.has(e.toLowerCase()) ? String(t) : `${t}px`, c = (e, t, o, i) => {
38
38
  const s = e => o(e), p = i?.ns ? `${t}.${i.ns}` : t;
39
39
  e.addEventListener(t, s, i);
40
40
  let r = n.get(e);
@@ -76,7 +76,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
76
76
  return this.el.textContent = e, this;
77
77
  }
78
78
  css(e, t) {
79
- if ("object" == typeof e && null !== e) for (const [t, o] of Object.entries(e)) this.el.style.setProperty(t.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), c(t, o)); else this.el.style.setProperty(e.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), c(e, t));
79
+ if ("object" == typeof e && null !== e) for (const [t, o] of Object.entries(e)) this.el.style.setProperty(t.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), l(t, o)); else this.el.style.setProperty(e.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), l(e, t));
80
80
  return this;
81
81
  }
82
82
  addClass(e) {
@@ -125,7 +125,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
125
125
  return this.el.style.display = "none" === this.el.style.display ? "" : "none", this;
126
126
  }
127
127
  on(e, t, o) {
128
- return l(this.el, e, t, o), this;
128
+ return c(this.el, e, t, o), this;
129
129
  }
130
130
  off(e, t) {
131
131
  return d(this.el, e, t), this;
@@ -189,7 +189,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
189
189
  let n = 200, s = o;
190
190
  "function" == typeof t ? s = t : n = t;
191
191
  const p = Object.keys(e), r = {};
192
- for (const t of p) r[t] = c(t, e[t]);
192
+ for (const t of p) r[t] = l(t, e[t]);
193
193
  return i.style.transition = "none", i.offsetWidth, i.style.transition = `${p.join(", ")} ${n}ms ease`,
194
194
  Object.assign(i.style, r), this.finishTransition(n, () => {
195
195
  i.style.transition = "", s?.();
@@ -223,14 +223,14 @@ var m = e => {
223
223
  return new u(o);
224
224
  }, b = {
225
225
  on(e, t, o) {
226
- l(document, e, t, o);
226
+ c(document, e, t, o);
227
227
  },
228
228
  off(e, t) {
229
229
  d(document, e, t);
230
230
  }
231
231
  }, _ = {
232
232
  on(e, t, o) {
233
- l(window, e, t, o);
233
+ c(window, e, t, o);
234
234
  },
235
235
  off(e, t) {
236
236
  d(window, e, t);
@@ -281,7 +281,7 @@ var m = e => {
281
281
  });
282
282
  }
283
283
  }
284
- }, k = () => "undefined" != typeof window && window.matchMedia("(max-width: 1024px)").matches, $ = () => {
284
+ }, k = () => "undefined" != typeof window && window.matchMedia("(max-width: 1024px)").matches, T = () => {
285
285
  if (!0 === window.__FORCE_TOUCH_MODE__) return "touch";
286
286
  const e = (() => {
287
287
  if ("undefined" == typeof navigator) return !1;
@@ -289,12 +289,12 @@ var m = e => {
289
289
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e);
290
290
  })() || k();
291
291
  return ("ontouchstart" in window || navigator.maxTouchPoints > 0) && e ? "touch" : "mouse";
292
- }, T = $(), E = !k(), C = null;
292
+ }, $ = T(), E = !k(), C = null;
293
293
 
294
294
  if ("undefined" != typeof window) {
295
295
  const e = window.matchMedia("(max-width: 1024px)"), t = () => {
296
- const e = $(), t = T, o = !k();
297
- T = e, E !== o && (E = o, C && C(e, t));
296
+ const e = T(), t = $, o = !k();
297
+ $ = e, E !== o && (E = o, C && C(e, t));
298
298
  };
299
299
  let o;
300
300
  e.addListener ? e.addListener(t) : e.addEventListener("change", t), window.addEventListener("resize", () => {
@@ -302,10 +302,10 @@ if ("undefined" != typeof window) {
302
302
  });
303
303
  }
304
304
 
305
- var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length > 0 ? e.touches[0].clientX : e.clientX, M = e => void 0 !== e.clientY ? e.clientY : e.touches && e.touches.length > 0 ? e.touches[0].clientY : e.clientY, S = 250, N = 150, O = !1, I = 1e3, A = !1, H = 0, P = 0, j = 0, W = 0, R = 0, D = 0, q = 0, B = 0, X = 0, Y = new Map, U = new Map, K = () => h("body"), F = e => "object" == typeof e && null !== e ? e.id : e, Z = {
305
+ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length > 0 ? e.touches[0].clientX : e.clientX, M = e => void 0 !== e.clientY ? e.clientY : e.touches && e.touches.length > 0 ? e.touches[0].clientY : e.clientY, S = 250, N = 150, O = !1, I = 1e3, A = !1, P = 0, H = 0, j = 0, W = 0, R = 0, D = 0, q = 0, B = 0, X = 0, Y = new Map, U = new Map, K = () => h("body"), F = e => "object" == typeof e && null !== e ? e.id : e, Z = {
306
306
  open: e => {
307
307
  if (!e) return e;
308
- e.id = e.id ?? "popup_" + ++H, e.body = e.body ?? "", e.class = e.class ?? "", e.width = e.width ?? 340,
308
+ e.id = e.id ?? "popup_" + ++P, e.body = e.body ?? "", e.class = e.class ?? "", e.width = e.width ?? 340,
309
309
  e.height = e.height ?? 220, e.minWidth = e.minWidth ?? 340, e.minHeight = e.minHeight ?? 220,
310
310
  e.name = e.name ?? "popUp_" + e.id, e.source = e.source ?? null, e.icon = e.icon ?? null,
311
311
  e.iconize = e.iconize ?? null, e.maximize = e.maximize ?? null, e.isMaximize = e.isMaximize ?? null,
@@ -565,21 +565,21 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
565
565
  if (!1 === e.movable) return;
566
566
  const t = F(e), o = String(t), i = h(".popup_overflow_" + t, "#popup"), n = i ? h(".popup_drag_" + t, i.el) : null, s = i ? h(".popup_body_" + t, i.el) : null;
567
567
  i?.css("touch-action", "none");
568
- let p = 0, r = 0, a = 0, c = 0;
569
- const l = e => {
568
+ let p = 0, r = 0, a = 0, l = 0;
569
+ const c = e => {
570
570
  e.preventDefault();
571
571
  const t = L(e), o = M(e);
572
- p = a - t, r = c - o, a = t, c = o, Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && i?.css("top", i.el.offsetTop - r),
572
+ p = a - t, r = l - o, a = t, l = o, Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && i?.css("top", i.el.offsetTop - r),
573
573
  Z.checkArea(e)[0] < Z.checkArea(e)[5] && 1 === Math.sign(Z.checkArea(e)[0]) && i?.css("left", i.el.offsetLeft - p);
574
574
  }, d = () => {
575
575
  const e = {
576
576
  passive: !1
577
577
  };
578
- document.removeEventListener("pointermove", l, e), document.removeEventListener("pointerup", d, e),
578
+ document.removeEventListener("pointermove", c, e), document.removeEventListener("pointerup", d, e),
579
579
  Y.delete(o), s?.css("pointer-events", "auto"), Z.vfx(i, !0);
580
580
  };
581
581
  Y.set(o, {
582
- move: l,
582
+ move: c,
583
583
  up: d
584
584
  });
585
585
  n?.el.addEventListener("pointerdown", e => {
@@ -591,11 +591,11 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
591
591
  layerpro.popup.maximize(e);
592
592
  });
593
593
  const u = e => {
594
- a = L(e), c = M(e);
594
+ a = L(e), l = M(e);
595
595
  const t = {
596
596
  passive: !1
597
597
  };
598
- document.addEventListener("pointermove", l, t), document.addEventListener("pointerup", d, t);
598
+ document.addEventListener("pointermove", c, t), document.addEventListener("pointerup", d, t);
599
599
  };
600
600
  },
601
601
  resizable: e => {
@@ -622,25 +622,25 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
622
622
  const p = L(e), r = M(e), a = [ p - _.scrollLeft(), r - _.scrollTop() ];
623
623
  o.minWidth, K()?.css("pointer-events", "none"), n?.css("pointer-events", "none"),
624
624
  Z.vfx(n, !1);
625
- const c = e => {
625
+ const l = e => {
626
626
  Z.doRes(e, t);
627
- }, l = () => {
627
+ }, c = () => {
628
628
  Z.stopRes(t, s);
629
629
  }, d = U.get(s) || {};
630
- d.move = c, d.up = l, U.set(s, d);
630
+ d.move = l, d.up = c, U.set(s, d);
631
631
  const f = {
632
632
  passive: !1
633
633
  };
634
- document.addEventListener("pointermove", c, f), document.addEventListener("pointerup", l, f),
635
- P = a[0], j = a[1], W = n?.width() ?? 0, R = n?.height() ?? 0, D = n?.position().left ?? 0,
634
+ document.addEventListener("pointermove", l, f), document.addEventListener("pointerup", c, f),
635
+ H = a[0], j = a[1], W = n?.width() ?? 0, R = n?.height() ?? 0, D = n?.position().left ?? 0,
636
636
  q = n?.position().top ?? 0, B = q + R + 1, X = D + W + 1, O = t;
637
637
  },
638
638
  doRes: (e, t) => {
639
639
  dispatchEvent(new Event("layerProResize"));
640
640
  const o = t instanceof HTMLElement ? new u(t) : h(t), i = o?.parent(), n = L(e), s = M(e), p = [ n - _.scrollLeft(), s - _.scrollTop() ];
641
641
  if (t === O) {
642
- let t = W + p[0] - P, n = R + p[1] - j;
643
- const s = W - p[0] + P, r = R - p[1] + j;
642
+ let t = W + p[0] - H, n = R + p[1] - j;
643
+ const s = W - p[0] + H, r = R - p[1] + j;
644
644
  t <= 0 && (t = 0), n <= 0 && (n = 0), Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && o?.hasClass("resize_0") && (i && i.height() <= N && r > N && i.css({
645
645
  height: Number(N + 1)
646
646
  }), i && i.height() > N && N <= r && i.css({
@@ -744,6 +744,8 @@ Object.defineProperty(layerpro, "popup", {
744
744
  value: Z,
745
745
  writable: !1,
746
746
  configurable: !1
747
+ }), globalThis.popup = Z, Object.defineProperty(window, "popup", {
748
+ enumerable: !1
747
749
  });
748
750
 
749
751
  var G = {
package/index.js CHANGED
@@ -36,7 +36,7 @@ Object.defineProperty(i, "credits", {
36
36
  configurable: !1
37
37
  });
38
38
 
39
- var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.querySelector(e) ?? document : e instanceof HTMLElement ? e : document, r = e => e ? e.split(/\s+/).filter(e => e.length > 0) : [], a = new Set([ "opacity", "zindex", "z-index", "fontweight", "font-weight", "lineheight", "line-height", "zoom", "flex", "flexgrow", "flex-grow", "flexshrink", "flex-shrink", "order", "gridcolumn", "grid-column", "gridrow", "grid-row", "columncount", "column-count", "fontsizeadjust", "font-size-adjust", "appearance" ]), c = (e, t) => "number" != typeof t || a.has(e.toLowerCase()) ? String(t) : `${t}px`, l = (e, t, o, i) => {
39
+ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.querySelector(e) ?? document : e instanceof HTMLElement ? e : document, r = e => e ? e.split(/\s+/).filter(e => e.length > 0) : [], a = new Set([ "opacity", "zindex", "z-index", "fontweight", "font-weight", "lineheight", "line-height", "zoom", "flex", "flexgrow", "flex-grow", "flexshrink", "flex-shrink", "order", "gridcolumn", "grid-column", "gridrow", "grid-row", "columncount", "column-count", "fontsizeadjust", "font-size-adjust", "appearance" ]), l = (e, t) => "number" != typeof t || a.has(e.toLowerCase()) ? String(t) : `${t}px`, c = (e, t, o, i) => {
40
40
  const s = e => o(e), p = i?.ns ? `${t}.${i.ns}` : t;
41
41
  e.addEventListener(t, s, i);
42
42
  let r = n.get(e);
@@ -78,7 +78,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
78
78
  return this.el.textContent = e, this;
79
79
  }
80
80
  css(e, t) {
81
- if ("object" == typeof e && null !== e) for (const [t, o] of Object.entries(e)) this.el.style.setProperty(t.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), c(t, o)); else this.el.style.setProperty(e.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), c(e, t));
81
+ if ("object" == typeof e && null !== e) for (const [t, o] of Object.entries(e)) this.el.style.setProperty(t.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), l(t, o)); else this.el.style.setProperty(e.replace(/[A-Z]/g, e => `-${e.toLowerCase()}`), l(e, t));
82
82
  return this;
83
83
  }
84
84
  addClass(e) {
@@ -127,7 +127,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
127
127
  return this.el.style.display = "none" === this.el.style.display ? "" : "none", this;
128
128
  }
129
129
  on(e, t, o) {
130
- return l(this.el, e, t, o), this;
130
+ return c(this.el, e, t, o), this;
131
131
  }
132
132
  off(e, t) {
133
133
  return d(this.el, e, t), this;
@@ -191,7 +191,7 @@ var n = new WeakMap, s = new WeakMap, p = e => "string" == typeof e ? document.q
191
191
  let n = 200, s = o;
192
192
  "function" == typeof t ? s = t : n = t;
193
193
  const p = Object.keys(e), r = {};
194
- for (const t of p) r[t] = c(t, e[t]);
194
+ for (const t of p) r[t] = l(t, e[t]);
195
195
  return i.style.transition = "none", i.offsetWidth, i.style.transition = `${p.join(", ")} ${n}ms ease`,
196
196
  Object.assign(i.style, r), this.finishTransition(n, () => {
197
197
  i.style.transition = "", s?.();
@@ -225,14 +225,14 @@ var m = e => {
225
225
  return new u(o);
226
226
  }, b = {
227
227
  on(e, t, o) {
228
- l(document, e, t, o);
228
+ c(document, e, t, o);
229
229
  },
230
230
  off(e, t) {
231
231
  d(document, e, t);
232
232
  }
233
233
  }, _ = {
234
234
  on(e, t, o) {
235
- l(window, e, t, o);
235
+ c(window, e, t, o);
236
236
  },
237
237
  off(e, t) {
238
238
  d(window, e, t);
@@ -283,7 +283,7 @@ var m = e => {
283
283
  });
284
284
  }
285
285
  }
286
- }, k = () => "undefined" != typeof window && window.matchMedia("(max-width: 1024px)").matches, $ = () => {
286
+ }, k = () => "undefined" != typeof window && window.matchMedia("(max-width: 1024px)").matches, T = () => {
287
287
  if (!0 === window.__FORCE_TOUCH_MODE__) return "touch";
288
288
  const e = (() => {
289
289
  if ("undefined" == typeof navigator) return !1;
@@ -291,12 +291,12 @@ var m = e => {
291
291
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e);
292
292
  })() || k();
293
293
  return ("ontouchstart" in window || navigator.maxTouchPoints > 0) && e ? "touch" : "mouse";
294
- }, T = $(), E = !k(), C = null;
294
+ }, $ = T(), E = !k(), C = null;
295
295
 
296
296
  if ("undefined" != typeof window) {
297
297
  const e = window.matchMedia("(max-width: 1024px)"), t = () => {
298
- const e = $(), t = T, o = !k();
299
- T = e, E !== o && (E = o, C && C(e, t));
298
+ const e = T(), t = $, o = !k();
299
+ $ = e, E !== o && (E = o, C && C(e, t));
300
300
  };
301
301
  let o;
302
302
  e.addListener ? e.addListener(t) : e.addEventListener("change", t), window.addEventListener("resize", () => {
@@ -304,10 +304,10 @@ if ("undefined" != typeof window) {
304
304
  });
305
305
  }
306
306
 
307
- var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length > 0 ? e.touches[0].clientX : e.clientX, M = e => void 0 !== e.clientY ? e.clientY : e.touches && e.touches.length > 0 ? e.touches[0].clientY : e.clientY, S = 250, N = 150, O = !1, I = 1e3, A = !1, H = 0, P = 0, j = 0, W = 0, R = 0, D = 0, q = 0, B = 0, X = 0, Y = new Map, U = new Map, K = () => h("body"), F = e => "object" == typeof e && null !== e ? e.id : e, Z = {
307
+ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length > 0 ? e.touches[0].clientX : e.clientX, M = e => void 0 !== e.clientY ? e.clientY : e.touches && e.touches.length > 0 ? e.touches[0].clientY : e.clientY, S = 250, N = 150, O = !1, I = 1e3, A = !1, P = 0, H = 0, j = 0, W = 0, R = 0, D = 0, q = 0, B = 0, X = 0, Y = new Map, U = new Map, K = () => h("body"), F = e => "object" == typeof e && null !== e ? e.id : e, Z = {
308
308
  open: e => {
309
309
  if (!e) return e;
310
- e.id = e.id ?? "popup_" + ++H, e.body = e.body ?? "", e.class = e.class ?? "", e.width = e.width ?? 340,
310
+ e.id = e.id ?? "popup_" + ++P, e.body = e.body ?? "", e.class = e.class ?? "", e.width = e.width ?? 340,
311
311
  e.height = e.height ?? 220, e.minWidth = e.minWidth ?? 340, e.minHeight = e.minHeight ?? 220,
312
312
  e.name = e.name ?? "popUp_" + e.id, e.source = e.source ?? null, e.icon = e.icon ?? null,
313
313
  e.iconize = e.iconize ?? null, e.maximize = e.maximize ?? null, e.isMaximize = e.isMaximize ?? null,
@@ -567,21 +567,21 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
567
567
  if (!1 === e.movable) return;
568
568
  const t = F(e), o = String(t), i = h(".popup_overflow_" + t, "#popup"), n = i ? h(".popup_drag_" + t, i.el) : null, s = i ? h(".popup_body_" + t, i.el) : null;
569
569
  i?.css("touch-action", "none");
570
- let p = 0, r = 0, a = 0, c = 0;
571
- const l = e => {
570
+ let p = 0, r = 0, a = 0, l = 0;
571
+ const c = e => {
572
572
  e.preventDefault();
573
573
  const t = L(e), o = M(e);
574
- p = a - t, r = c - o, a = t, c = o, Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && i?.css("top", i.el.offsetTop - r),
574
+ p = a - t, r = l - o, a = t, l = o, Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && i?.css("top", i.el.offsetTop - r),
575
575
  Z.checkArea(e)[0] < Z.checkArea(e)[5] && 1 === Math.sign(Z.checkArea(e)[0]) && i?.css("left", i.el.offsetLeft - p);
576
576
  }, d = () => {
577
577
  const e = {
578
578
  passive: !1
579
579
  };
580
- document.removeEventListener("pointermove", l, e), document.removeEventListener("pointerup", d, e),
580
+ document.removeEventListener("pointermove", c, e), document.removeEventListener("pointerup", d, e),
581
581
  Y.delete(o), s?.css("pointer-events", "auto"), Z.vfx(i, !0);
582
582
  };
583
583
  Y.set(o, {
584
- move: l,
584
+ move: c,
585
585
  up: d
586
586
  });
587
587
  n?.el.addEventListener("pointerdown", e => {
@@ -593,11 +593,11 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
593
593
  layerpro.popup.maximize(e);
594
594
  });
595
595
  const u = e => {
596
- a = L(e), c = M(e);
596
+ a = L(e), l = M(e);
597
597
  const t = {
598
598
  passive: !1
599
599
  };
600
- document.addEventListener("pointermove", l, t), document.addEventListener("pointerup", d, t);
600
+ document.addEventListener("pointermove", c, t), document.addEventListener("pointerup", d, t);
601
601
  };
602
602
  },
603
603
  resizable: e => {
@@ -624,25 +624,25 @@ var L = e => void 0 !== e.clientX ? e.clientX : e.touches && e.touches.length >
624
624
  const p = L(e), r = M(e), a = [ p - _.scrollLeft(), r - _.scrollTop() ];
625
625
  o.minWidth, K()?.css("pointer-events", "none"), n?.css("pointer-events", "none"),
626
626
  Z.vfx(n, !1);
627
- const c = e => {
627
+ const l = e => {
628
628
  Z.doRes(e, t);
629
- }, l = () => {
629
+ }, c = () => {
630
630
  Z.stopRes(t, s);
631
631
  }, d = U.get(s) || {};
632
- d.move = c, d.up = l, U.set(s, d);
632
+ d.move = l, d.up = c, U.set(s, d);
633
633
  const f = {
634
634
  passive: !1
635
635
  };
636
- document.addEventListener("pointermove", c, f), document.addEventListener("pointerup", l, f),
637
- P = a[0], j = a[1], W = n?.width() ?? 0, R = n?.height() ?? 0, D = n?.position().left ?? 0,
636
+ document.addEventListener("pointermove", l, f), document.addEventListener("pointerup", c, f),
637
+ H = a[0], j = a[1], W = n?.width() ?? 0, R = n?.height() ?? 0, D = n?.position().left ?? 0,
638
638
  q = n?.position().top ?? 0, B = q + R + 1, X = D + W + 1, O = t;
639
639
  },
640
640
  doRes: (e, t) => {
641
641
  dispatchEvent(new Event("layerProResize"));
642
642
  const o = t instanceof HTMLElement ? new u(t) : h(t), i = o?.parent(), n = L(e), s = M(e), p = [ n - _.scrollLeft(), s - _.scrollTop() ];
643
643
  if (t === O) {
644
- let t = W + p[0] - P, n = R + p[1] - j;
645
- const s = W - p[0] + P, r = R - p[1] + j;
644
+ let t = W + p[0] - H, n = R + p[1] - j;
645
+ const s = W - p[0] + H, r = R - p[1] + j;
646
646
  t <= 0 && (t = 0), n <= 0 && (n = 0), Z.checkArea(e)[1] < Z.checkArea(e)[4] && 1 === Math.sign(Z.checkArea(e)[1]) && o?.hasClass("resize_0") && (i && i.height() <= N && r > N && i.css({
647
647
  height: Number(N + 1)
648
648
  }), i && i.height() > N && N <= r && i.css({
@@ -746,6 +746,8 @@ Object.defineProperty(layerpro, "popup", {
746
746
  value: Z,
747
747
  writable: !1,
748
748
  configurable: !1
749
+ }), globalThis.popup = Z, Object.defineProperty(window, "popup", {
750
+ enumerable: !1
749
751
  });
750
752
 
751
753
  var G = {
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. "&#9888;") 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. "&#9888;") 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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "layerpro",
3
3
  "codeName": "layerpro",
4
- "version": "3.1.0",
4
+ "version": "3.1.1",
5
5
  "description": "The real custom modals, alert, confirm, prompt... for your browser",
6
6
  "main": "./index.cjs",
7
7
  "browser": "./index.js",
@@ -127,3 +127,6 @@ interface Window {
127
127
 
128
128
  declare var layerpro: _layerpro
129
129
  type layerpro = _layerpro
130
+
131
+ declare var popup: layerpro
132
+ type popup = layerpro