framepexls-ui-lib 0.1.30 → 0.1.32

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.
@@ -11,7 +11,7 @@ type CheckboxProps = Omit<React__default.InputHTMLAttributes<HTMLInputElement>,
11
11
  className?: string;
12
12
  inputClassName?: string;
13
13
  };
14
- declare const Checkbox: React__default.ForwardRefExoticComponent<Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & {
14
+ declare const Checkbox: React__default.ForwardRefExoticComponent<Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "size" | "type"> & {
15
15
  label?: React__default.ReactNode;
16
16
  description?: React__default.ReactNode;
17
17
  error?: boolean;
@@ -11,7 +11,7 @@ type CheckboxProps = Omit<React__default.InputHTMLAttributes<HTMLInputElement>,
11
11
  className?: string;
12
12
  inputClassName?: string;
13
13
  };
14
- declare const Checkbox: React__default.ForwardRefExoticComponent<Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & {
14
+ declare const Checkbox: React__default.ForwardRefExoticComponent<Omit<React__default.InputHTMLAttributes<HTMLInputElement>, "size" | "type"> & {
15
15
  label?: React__default.ReactNode;
16
16
  description?: React__default.ReactNode;
17
17
  error?: boolean;
package/dist/Dialog.js CHANGED
@@ -41,6 +41,7 @@ __export(Dialog_exports, {
41
41
  module.exports = __toCommonJS(Dialog_exports);
42
42
  var import_jsx_runtime = require("react/jsx-runtime");
43
43
  var import_react = __toESM(require("react"));
44
+ var import_react_dom = require("react-dom");
44
45
  var import_framer_motion = require("framer-motion");
45
46
  var import_ActionIconButton = __toESM(require("./ActionIconButton"));
46
47
  var import_Button = __toESM(require("./Button"));
@@ -55,6 +56,26 @@ const sizeToMaxW = {
55
56
  "5xl": "max-w-5xl",
56
57
  full: "max-w-[min(96vw,1200px)]"
57
58
  };
59
+ const zManager = /* @__PURE__ */ (() => {
60
+ const stack = [];
61
+ const BASE = 1e3;
62
+ const STEP = 10;
63
+ return {
64
+ acquire() {
65
+ const z = BASE + stack.length * STEP;
66
+ stack.push(z);
67
+ return z;
68
+ },
69
+ release(z) {
70
+ const i = stack.indexOf(z);
71
+ if (i !== -1) stack.splice(i, 1);
72
+ },
73
+ isTop(z) {
74
+ if (z == null) return false;
75
+ return stack.length > 0 && stack[stack.length - 1] === z;
76
+ }
77
+ };
78
+ })();
58
79
  function useLockBodyScroll(open) {
59
80
  (0, import_react.useEffect)(() => {
60
81
  if (!open) return;
@@ -79,15 +100,16 @@ function useLockBodyScroll(open) {
79
100
  };
80
101
  }, [open]);
81
102
  }
82
- function useEscToClose(open, onClose, disabled) {
103
+ function useEscToClose(open, onClose, disabled, onlyTop) {
83
104
  (0, import_react.useEffect)(() => {
84
105
  if (!open || disabled) return;
106
+ if (onlyTop === false) return;
85
107
  const onKey = (e) => {
86
108
  if (e.key === "Escape") onClose();
87
109
  };
88
110
  window.addEventListener("keydown", onKey);
89
111
  return () => window.removeEventListener("keydown", onKey);
90
- }, [open, onClose, disabled]);
112
+ }, [open, onClose, disabled, onlyTop]);
91
113
  }
92
114
  function cx(...a) {
93
115
  return a.filter(Boolean).join(" ");
@@ -110,8 +132,21 @@ function DialogBase({
110
132
  const containerRef = (0, import_react.useRef)(null);
111
133
  const closeBtnRef = (0, import_react.useRef)(null);
112
134
  const lastFocusedRef = (0, import_react.useRef)(null);
135
+ const [zIndexBase, setZIndexBase] = (0, import_react.useState)(null);
113
136
  useLockBodyScroll(open);
114
- useEscToClose(open, onClose, disableEscClose);
137
+ useEscToClose(open, onClose, disableEscClose, zManager.isTop(zIndexBase));
138
+ (0, import_react.useEffect)(() => {
139
+ if (open) {
140
+ const z = zManager.acquire();
141
+ setZIndexBase(z);
142
+ return () => {
143
+ zManager.release(z);
144
+ setZIndexBase(null);
145
+ };
146
+ } else {
147
+ setZIndexBase(null);
148
+ }
149
+ }, [open]);
115
150
  (0, import_react.useEffect)(() => {
116
151
  var _a, _b, _c;
117
152
  if (open) {
@@ -127,59 +162,64 @@ function DialogBase({
127
162
  if (!dismissibleBackdrop) return;
128
163
  if (e.target === e.currentTarget) onClose();
129
164
  };
130
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { children: open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
131
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
132
- import_framer_motion.motion.div,
133
- {
134
- className: "fixed inset-0 z-[100] bg-black/45 backdrop-blur-sm",
135
- initial: { opacity: 0 },
136
- animate: { opacity: 1 },
137
- exit: { opacity: 0 }
138
- }
139
- ),
140
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
141
- import_framer_motion.motion.div,
142
- {
143
- role: "dialog",
144
- "aria-modal": "true",
145
- "aria-labelledby": title ? "dialog-title" : void 0,
146
- "aria-describedby": description ? "dialog-desc" : void 0,
147
- className: "fixed inset-0 z-[101] grid place-items-center p-4",
148
- initial: { opacity: 0, scale: 0.98, y: 8 },
149
- animate: { opacity: 1, scale: 1, y: 0 },
150
- exit: { opacity: 0, scale: 0.98, y: 8 },
151
- onMouseDown: handleBackdropMouseDown,
152
- children: [
153
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
154
- "div",
155
- {
156
- ref: containerRef,
157
- className: cx(
158
- "w-full overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-xl",
159
- "dark:border-white/10 dark:bg-[#0b0a0a]",
160
- "flex max-h-[88vh] flex-col",
161
- sizeToMaxW[size],
162
- className
163
- ),
164
- onMouseDown: (e) => e.stopPropagation(),
165
- children: children != null ? children : null
166
- }
167
- ),
168
- showClose && !children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute right-5 top-5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
169
- import_ActionIconButton.default,
170
- {
171
- title: "Cerrar",
172
- size: "lg",
173
- onClick: onClose,
174
- ref: closeBtnRef,
175
- className: "shadow-sm",
176
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
177
- }
178
- ) })
179
- ]
180
- }
181
- )
182
- ] }) });
165
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { children: open && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
166
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
168
+ import_framer_motion.motion.div,
169
+ {
170
+ className: "fixed inset-0 bg-black/45 backdrop-blur-sm",
171
+ style: { zIndex: zIndexBase != null ? zIndexBase : 1e3 },
172
+ initial: { opacity: 0 },
173
+ animate: { opacity: 1 },
174
+ exit: { opacity: 0 }
175
+ }
176
+ ),
177
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
178
+ import_framer_motion.motion.div,
179
+ {
180
+ role: "dialog",
181
+ "aria-modal": "true",
182
+ "aria-labelledby": title ? "dialog-title" : void 0,
183
+ "aria-describedby": description ? "dialog-desc" : void 0,
184
+ className: "fixed inset-0 grid place-items-center p-4",
185
+ style: { zIndex: (zIndexBase != null ? zIndexBase : 1e3) + 1 },
186
+ initial: { opacity: 0, scale: 0.98, y: 8 },
187
+ animate: { opacity: 1, scale: 1, y: 0 },
188
+ exit: { opacity: 0, scale: 0.98, y: 8 },
189
+ onMouseDown: handleBackdropMouseDown,
190
+ children: [
191
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
192
+ "div",
193
+ {
194
+ ref: containerRef,
195
+ className: cx(
196
+ "w-full overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-xl",
197
+ "dark:border-white/10 dark:bg-[#0b0a0a]",
198
+ "flex max-h-[88vh] flex-col",
199
+ sizeToMaxW[size],
200
+ className
201
+ ),
202
+ onMouseDown: (e) => e.stopPropagation(),
203
+ children: children != null ? children : null
204
+ }
205
+ ),
206
+ showClose && !children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute right-5 top-5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
207
+ import_ActionIconButton.default,
208
+ {
209
+ title: "Cerrar",
210
+ size: "lg",
211
+ onClick: onClose,
212
+ ref: closeBtnRef,
213
+ className: "shadow-sm",
214
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
215
+ }
216
+ ) })
217
+ ]
218
+ }
219
+ )
220
+ ] }),
221
+ document.body
222
+ ) });
183
223
  }
184
224
  function DialogHeader({
185
225
  title,
package/dist/Dialog.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import React, { useEffect, useRef } from "react";
3
+ import React, { useEffect, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
4
5
  import { motion, AnimatePresence } from "framer-motion";
5
6
  import ActionIconButton from "./ActionIconButton";
6
7
  import Button from "./Button";
@@ -15,6 +16,26 @@ const sizeToMaxW = {
15
16
  "5xl": "max-w-5xl",
16
17
  full: "max-w-[min(96vw,1200px)]"
17
18
  };
19
+ const zManager = /* @__PURE__ */ (() => {
20
+ const stack = [];
21
+ const BASE = 1e3;
22
+ const STEP = 10;
23
+ return {
24
+ acquire() {
25
+ const z = BASE + stack.length * STEP;
26
+ stack.push(z);
27
+ return z;
28
+ },
29
+ release(z) {
30
+ const i = stack.indexOf(z);
31
+ if (i !== -1) stack.splice(i, 1);
32
+ },
33
+ isTop(z) {
34
+ if (z == null) return false;
35
+ return stack.length > 0 && stack[stack.length - 1] === z;
36
+ }
37
+ };
38
+ })();
18
39
  function useLockBodyScroll(open) {
19
40
  useEffect(() => {
20
41
  if (!open) return;
@@ -39,15 +60,16 @@ function useLockBodyScroll(open) {
39
60
  };
40
61
  }, [open]);
41
62
  }
42
- function useEscToClose(open, onClose, disabled) {
63
+ function useEscToClose(open, onClose, disabled, onlyTop) {
43
64
  useEffect(() => {
44
65
  if (!open || disabled) return;
66
+ if (onlyTop === false) return;
45
67
  const onKey = (e) => {
46
68
  if (e.key === "Escape") onClose();
47
69
  };
48
70
  window.addEventListener("keydown", onKey);
49
71
  return () => window.removeEventListener("keydown", onKey);
50
- }, [open, onClose, disabled]);
72
+ }, [open, onClose, disabled, onlyTop]);
51
73
  }
52
74
  function cx(...a) {
53
75
  return a.filter(Boolean).join(" ");
@@ -70,8 +92,21 @@ function DialogBase({
70
92
  const containerRef = useRef(null);
71
93
  const closeBtnRef = useRef(null);
72
94
  const lastFocusedRef = useRef(null);
95
+ const [zIndexBase, setZIndexBase] = useState(null);
73
96
  useLockBodyScroll(open);
74
- useEscToClose(open, onClose, disableEscClose);
97
+ useEscToClose(open, onClose, disableEscClose, zManager.isTop(zIndexBase));
98
+ useEffect(() => {
99
+ if (open) {
100
+ const z = zManager.acquire();
101
+ setZIndexBase(z);
102
+ return () => {
103
+ zManager.release(z);
104
+ setZIndexBase(null);
105
+ };
106
+ } else {
107
+ setZIndexBase(null);
108
+ }
109
+ }, [open]);
75
110
  useEffect(() => {
76
111
  var _a, _b, _c;
77
112
  if (open) {
@@ -87,59 +122,64 @@ function DialogBase({
87
122
  if (!dismissibleBackdrop) return;
88
123
  if (e.target === e.currentTarget) onClose();
89
124
  };
90
- return /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsxs(Fragment, { children: [
91
- /* @__PURE__ */ jsx(
92
- motion.div,
93
- {
94
- className: "fixed inset-0 z-[100] bg-black/45 backdrop-blur-sm",
95
- initial: { opacity: 0 },
96
- animate: { opacity: 1 },
97
- exit: { opacity: 0 }
98
- }
99
- ),
100
- /* @__PURE__ */ jsxs(
101
- motion.div,
102
- {
103
- role: "dialog",
104
- "aria-modal": "true",
105
- "aria-labelledby": title ? "dialog-title" : void 0,
106
- "aria-describedby": description ? "dialog-desc" : void 0,
107
- className: "fixed inset-0 z-[101] grid place-items-center p-4",
108
- initial: { opacity: 0, scale: 0.98, y: 8 },
109
- animate: { opacity: 1, scale: 1, y: 0 },
110
- exit: { opacity: 0, scale: 0.98, y: 8 },
111
- onMouseDown: handleBackdropMouseDown,
112
- children: [
113
- /* @__PURE__ */ jsx(
114
- "div",
115
- {
116
- ref: containerRef,
117
- className: cx(
118
- "w-full overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-xl",
119
- "dark:border-white/10 dark:bg-[#0b0a0a]",
120
- "flex max-h-[88vh] flex-col",
121
- sizeToMaxW[size],
122
- className
123
- ),
124
- onMouseDown: (e) => e.stopPropagation(),
125
- children: children != null ? children : null
126
- }
127
- ),
128
- showClose && !children && /* @__PURE__ */ jsx("div", { className: "absolute right-5 top-5", children: /* @__PURE__ */ jsx(
129
- ActionIconButton,
130
- {
131
- title: "Cerrar",
132
- size: "lg",
133
- onClick: onClose,
134
- ref: closeBtnRef,
135
- className: "shadow-sm",
136
- children: /* @__PURE__ */ jsx(CloseIcon, {})
137
- }
138
- ) })
139
- ]
140
- }
141
- )
142
- ] }) });
125
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: open && typeof document !== "undefined" && createPortal(
126
+ /* @__PURE__ */ jsxs(Fragment, { children: [
127
+ /* @__PURE__ */ jsx(
128
+ motion.div,
129
+ {
130
+ className: "fixed inset-0 bg-black/45 backdrop-blur-sm",
131
+ style: { zIndex: zIndexBase != null ? zIndexBase : 1e3 },
132
+ initial: { opacity: 0 },
133
+ animate: { opacity: 1 },
134
+ exit: { opacity: 0 }
135
+ }
136
+ ),
137
+ /* @__PURE__ */ jsxs(
138
+ motion.div,
139
+ {
140
+ role: "dialog",
141
+ "aria-modal": "true",
142
+ "aria-labelledby": title ? "dialog-title" : void 0,
143
+ "aria-describedby": description ? "dialog-desc" : void 0,
144
+ className: "fixed inset-0 grid place-items-center p-4",
145
+ style: { zIndex: (zIndexBase != null ? zIndexBase : 1e3) + 1 },
146
+ initial: { opacity: 0, scale: 0.98, y: 8 },
147
+ animate: { opacity: 1, scale: 1, y: 0 },
148
+ exit: { opacity: 0, scale: 0.98, y: 8 },
149
+ onMouseDown: handleBackdropMouseDown,
150
+ children: [
151
+ /* @__PURE__ */ jsx(
152
+ "div",
153
+ {
154
+ ref: containerRef,
155
+ className: cx(
156
+ "w-full overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-xl",
157
+ "dark:border-white/10 dark:bg-[#0b0a0a]",
158
+ "flex max-h-[88vh] flex-col",
159
+ sizeToMaxW[size],
160
+ className
161
+ ),
162
+ onMouseDown: (e) => e.stopPropagation(),
163
+ children: children != null ? children : null
164
+ }
165
+ ),
166
+ showClose && !children && /* @__PURE__ */ jsx("div", { className: "absolute right-5 top-5", children: /* @__PURE__ */ jsx(
167
+ ActionIconButton,
168
+ {
169
+ title: "Cerrar",
170
+ size: "lg",
171
+ onClick: onClose,
172
+ ref: closeBtnRef,
173
+ className: "shadow-sm",
174
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
175
+ }
176
+ ) })
177
+ ]
178
+ }
179
+ )
180
+ ] }),
181
+ document.body
182
+ ) });
143
183
  }
144
184
  function DialogHeader({
145
185
  title,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framepexls-ui-lib",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "Componentes UI de Framepexls para React/Next.",