framepexls-ui-lib 0.1.7 → 0.1.9

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.
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var TimeRangeField_exports = {};
31
+ __export(TimeRangeField_exports, {
32
+ default: () => TimeRangeField
33
+ });
34
+ module.exports = __toCommonJS(TimeRangeField_exports);
35
+ var import_jsx_runtime = require("react/jsx-runtime");
36
+ var import_react = require("react");
37
+ var import_react_dom = require("react-dom");
38
+ var import_Input = __toESM(require("./Input"));
39
+ var import_TimePopover = __toESM(require("./TimePopover"));
40
+ const pad2 = (n) => n < 10 ? `0${n}` : String(n);
41
+ function parseHHmm(v) {
42
+ if (!v) return null;
43
+ const [hh, mm] = String(v).split(":").map((x) => parseInt(x, 10));
44
+ if (Number.isNaN(hh) || Number.isNaN(mm)) return null;
45
+ return { hh: Math.max(0, Math.min(23, hh)), mm: Math.max(0, Math.min(59, mm)) };
46
+ }
47
+ function fmtHHmm(hh, mm) {
48
+ return `${pad2(hh)}:${pad2(mm)}`;
49
+ }
50
+ function TimeRangeField({ value, onValueChange, portal = true, portalId, clearable = true, step = 5, placeholder = "Selecciona rango", className, disabled }) {
51
+ var _a, _b, _c, _d, _e, _f;
52
+ const anchorRef = (0, import_react.useRef)(null);
53
+ const [open, setOpen] = (0, import_react.useState)(false);
54
+ const [portalRoot, setPortalRoot] = (0, import_react.useState)(null);
55
+ const [anchorRect, setAnchorRect] = (0, import_react.useState)(null);
56
+ const [from, setFrom] = (0, import_react.useState)(() => {
57
+ var _a2;
58
+ return (_a2 = parseHHmm(value == null ? void 0 : value.from)) != null ? _a2 : null;
59
+ });
60
+ const [to, setTo] = (0, import_react.useState)(() => {
61
+ var _a2;
62
+ return (_a2 = parseHHmm(value == null ? void 0 : value.to)) != null ? _a2 : null;
63
+ });
64
+ const fromBtnRef = (0, import_react.useRef)(null);
65
+ const toBtnRef = (0, import_react.useRef)(null);
66
+ const [showFromPop, setShowFromPop] = (0, import_react.useState)(false);
67
+ const [showToPop, setShowToPop] = (0, import_react.useState)(false);
68
+ (0, import_react.useEffect)(() => {
69
+ var _a2;
70
+ setFrom((_a2 = parseHHmm(value == null ? void 0 : value.from)) != null ? _a2 : null);
71
+ }, [value == null ? void 0 : value.from]);
72
+ (0, import_react.useEffect)(() => {
73
+ var _a2;
74
+ setTo((_a2 = parseHHmm(value == null ? void 0 : value.to)) != null ? _a2 : null);
75
+ }, [value == null ? void 0 : value.to]);
76
+ (0, import_react.useEffect)(() => {
77
+ if (!portal) return;
78
+ const el = portalId ? document.getElementById(portalId) : null;
79
+ setPortalRoot(el != null ? el : document.body);
80
+ }, [portal, portalId]);
81
+ const display = (0, import_react.useMemo)(() => {
82
+ var _a2;
83
+ const a = from ? fmtHHmm(from.hh, from.mm) : null;
84
+ const b = to ? fmtHHmm(to.hh, to.mm) : null;
85
+ if (!a && !b) return "";
86
+ if (a && b) return `${a} \u2013 ${b}`;
87
+ return (_a2 = a != null ? a : b) != null ? _a2 : "";
88
+ }, [from, to]);
89
+ const openPopover = () => {
90
+ if (disabled) return;
91
+ if (!anchorRef.current) return;
92
+ setAnchorRect(anchorRef.current.getBoundingClientRect());
93
+ setOpen(true);
94
+ };
95
+ (0, import_react.useEffect)(() => {
96
+ if (!open) return;
97
+ const onDown = (e) => {
98
+ var _a2;
99
+ const t = e.target;
100
+ if (t.closest("[data-trf-pop]")) return;
101
+ if (t.closest("[data-dtf-pop]")) return;
102
+ if ((_a2 = anchorRef.current) == null ? void 0 : _a2.contains(t)) return;
103
+ setOpen(false);
104
+ };
105
+ const update = () => {
106
+ if (!anchorRef.current) return;
107
+ setAnchorRect(anchorRef.current.getBoundingClientRect());
108
+ };
109
+ const onEsc = (e) => {
110
+ if (e.key === "Escape") setOpen(false);
111
+ };
112
+ window.addEventListener("pointerdown", onDown, true);
113
+ window.addEventListener("scroll", update, true);
114
+ window.addEventListener("resize", update);
115
+ window.addEventListener("keydown", onEsc);
116
+ return () => {
117
+ window.removeEventListener("pointerdown", onDown, true);
118
+ window.removeEventListener("scroll", update, true);
119
+ window.removeEventListener("resize", update);
120
+ window.removeEventListener("keydown", onEsc);
121
+ };
122
+ }, [open]);
123
+ const stylePop = (() => {
124
+ if (!anchorRect) return { visibility: "hidden" };
125
+ const W = 360, GAP = 8, MARGIN = 8, H = 180;
126
+ let left = anchorRect.right - W;
127
+ left = Math.max(MARGIN, Math.min(left, window.innerWidth - (W + MARGIN)));
128
+ let top = anchorRect.bottom + GAP;
129
+ if (top + H > window.innerHeight) top = Math.max(MARGIN, anchorRect.top - GAP - H);
130
+ return { position: "fixed", top, left, zIndex: 1e5 };
131
+ })();
132
+ const commit = (f, t) => {
133
+ let f2 = f, t2 = t;
134
+ if (f2 && t2) {
135
+ const a = f2.hh * 60 + f2.mm;
136
+ const b = t2.hh * 60 + t2.mm;
137
+ if (b < a) t2 = { ...f2 };
138
+ }
139
+ setFrom(f2);
140
+ setTo(t2);
141
+ onValueChange == null ? void 0 : onValueChange({ from: f2 ? fmtHHmm(f2.hh, f2.mm) : null, to: t2 ? fmtHHmm(t2.hh, t2.mm) : null });
142
+ };
143
+ const popover = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-trf-pop": true, style: stylePop, className: "w-1/3 overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-xl dark:border-white/10 dark:bg-[#0e0d0e]", children: [
144
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-2 px-3 py-2 text-sm", children: [
145
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-medium", children: "Selecciona horario" }),
146
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
147
+ "button",
148
+ {
149
+ type: "button",
150
+ className: "rounded-xl bg-slate-900 px-3 py-1.5 text-white hover:opacity-95 active:scale-[0.98] dark:bg-white dark:text-slate-900",
151
+ onClick: () => setOpen(false),
152
+ children: "Aplicar"
153
+ }
154
+ )
155
+ ] }),
156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid grid-cols-2 gap-3 border-t border-slate-100 p-3 text-sm dark:border-white/10", children: [
157
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mb-1 text-xs text-slate-500 dark:text-slate-300", children: "Desde" }),
159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
160
+ "button",
161
+ {
162
+ type: "button",
163
+ className: "rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 font-medium tracking-wide hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
164
+ onClick: () => setShowFromPop((v) => !v),
165
+ ref: fromBtnRef,
166
+ children: from ? fmtHHmm(from.hh, from.mm) : "--:--"
167
+ }
168
+ ),
169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
170
+ "button",
171
+ {
172
+ type: "button",
173
+ className: "ml-2 rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
174
+ onClick: () => {
175
+ const t = /* @__PURE__ */ new Date();
176
+ const rounded = Math.round(t.getMinutes() / step) * step % 60;
177
+ commit({ hh: t.getHours(), mm: rounded }, to);
178
+ },
179
+ children: "Ahora"
180
+ }
181
+ )
182
+ ] }),
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mb-1 text-xs text-slate-500 dark:text-slate-300", children: "Hasta" }),
185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
186
+ "button",
187
+ {
188
+ type: "button",
189
+ className: "rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 font-medium tracking-wide hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
190
+ onClick: () => setShowToPop((v) => !v),
191
+ ref: toBtnRef,
192
+ children: to ? fmtHHmm(to.hh, to.mm) : "--:--"
193
+ }
194
+ ),
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
196
+ "button",
197
+ {
198
+ type: "button",
199
+ className: "ml-2 rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
200
+ onClick: () => {
201
+ const t = /* @__PURE__ */ new Date();
202
+ const rounded = Math.round(t.getMinutes() / step) * step % 60;
203
+ const candidate = { hh: t.getHours(), mm: rounded };
204
+ commit(from, candidate);
205
+ },
206
+ children: "Ahora"
207
+ }
208
+ )
209
+ ] })
210
+ ] })
211
+ ] });
212
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: anchorRef, className, children: [
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
214
+ import_Input.default,
215
+ {
216
+ readOnly: true,
217
+ value: display,
218
+ placeholder,
219
+ onClick: openPopover,
220
+ clearable,
221
+ onClear: () => {
222
+ setFrom(null);
223
+ setTo(null);
224
+ onValueChange == null ? void 0 : onValueChange({ from: null, to: null });
225
+ },
226
+ disabled,
227
+ rightSlot: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
228
+ "button",
229
+ {
230
+ type: "button",
231
+ className: "pointer-events-auto inline-flex h-7 w-7 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 active:scale-95 dark:border-white/10 dark:bg-white/5",
232
+ onClick: (e) => {
233
+ e.preventDefault();
234
+ openPopover();
235
+ },
236
+ title: "Abrir selector de horas",
237
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", className: "h-4.5 w-4.5", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
238
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 7v5l3 3" }),
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "9" })
240
+ ] })
241
+ }
242
+ )
243
+ }
244
+ ),
245
+ open && (portal ? portalRoot && (0, import_react_dom.createPortal)(popover, portalRoot) : popover),
246
+ open && showFromPop && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
+ import_TimePopover.default,
248
+ {
249
+ anchorEl: fromBtnRef.current,
250
+ hh: (_a = from == null ? void 0 : from.hh) != null ? _a : 0,
251
+ mm: (_b = from == null ? void 0 : from.mm) != null ? _b : 0,
252
+ onChange: (H, M) => commit({ hh: H, mm: M }, to),
253
+ onClose: () => setShowFromPop(false),
254
+ step
255
+ }
256
+ ),
257
+ open && showToPop && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
258
+ import_TimePopover.default,
259
+ {
260
+ anchorEl: toBtnRef.current,
261
+ hh: (_d = to == null ? void 0 : to.hh) != null ? _d : (_c = from == null ? void 0 : from.hh) != null ? _c : 0,
262
+ mm: (_f = to == null ? void 0 : to.mm) != null ? _f : (_e = from == null ? void 0 : from.mm) != null ? _e : 0,
263
+ onChange: (H, M) => commit(from, { hh: H, mm: M }),
264
+ onClose: () => setShowToPop(false),
265
+ step
266
+ }
267
+ )
268
+ ] });
269
+ }
@@ -0,0 +1,239 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useMemo, useRef, useState } from "react";
4
+ import { createPortal } from "react-dom";
5
+ import Input from "./Input";
6
+ import TimePopover from "./TimePopover";
7
+ const pad2 = (n) => n < 10 ? `0${n}` : String(n);
8
+ function parseHHmm(v) {
9
+ if (!v) return null;
10
+ const [hh, mm] = String(v).split(":").map((x) => parseInt(x, 10));
11
+ if (Number.isNaN(hh) || Number.isNaN(mm)) return null;
12
+ return { hh: Math.max(0, Math.min(23, hh)), mm: Math.max(0, Math.min(59, mm)) };
13
+ }
14
+ function fmtHHmm(hh, mm) {
15
+ return `${pad2(hh)}:${pad2(mm)}`;
16
+ }
17
+ function TimeRangeField({ value, onValueChange, portal = true, portalId, clearable = true, step = 5, placeholder = "Selecciona rango", className, disabled }) {
18
+ var _a, _b, _c, _d, _e, _f;
19
+ const anchorRef = useRef(null);
20
+ const [open, setOpen] = useState(false);
21
+ const [portalRoot, setPortalRoot] = useState(null);
22
+ const [anchorRect, setAnchorRect] = useState(null);
23
+ const [from, setFrom] = useState(() => {
24
+ var _a2;
25
+ return (_a2 = parseHHmm(value == null ? void 0 : value.from)) != null ? _a2 : null;
26
+ });
27
+ const [to, setTo] = useState(() => {
28
+ var _a2;
29
+ return (_a2 = parseHHmm(value == null ? void 0 : value.to)) != null ? _a2 : null;
30
+ });
31
+ const fromBtnRef = useRef(null);
32
+ const toBtnRef = useRef(null);
33
+ const [showFromPop, setShowFromPop] = useState(false);
34
+ const [showToPop, setShowToPop] = useState(false);
35
+ useEffect(() => {
36
+ var _a2;
37
+ setFrom((_a2 = parseHHmm(value == null ? void 0 : value.from)) != null ? _a2 : null);
38
+ }, [value == null ? void 0 : value.from]);
39
+ useEffect(() => {
40
+ var _a2;
41
+ setTo((_a2 = parseHHmm(value == null ? void 0 : value.to)) != null ? _a2 : null);
42
+ }, [value == null ? void 0 : value.to]);
43
+ useEffect(() => {
44
+ if (!portal) return;
45
+ const el = portalId ? document.getElementById(portalId) : null;
46
+ setPortalRoot(el != null ? el : document.body);
47
+ }, [portal, portalId]);
48
+ const display = useMemo(() => {
49
+ var _a2;
50
+ const a = from ? fmtHHmm(from.hh, from.mm) : null;
51
+ const b = to ? fmtHHmm(to.hh, to.mm) : null;
52
+ if (!a && !b) return "";
53
+ if (a && b) return `${a} \u2013 ${b}`;
54
+ return (_a2 = a != null ? a : b) != null ? _a2 : "";
55
+ }, [from, to]);
56
+ const openPopover = () => {
57
+ if (disabled) return;
58
+ if (!anchorRef.current) return;
59
+ setAnchorRect(anchorRef.current.getBoundingClientRect());
60
+ setOpen(true);
61
+ };
62
+ useEffect(() => {
63
+ if (!open) return;
64
+ const onDown = (e) => {
65
+ var _a2;
66
+ const t = e.target;
67
+ if (t.closest("[data-trf-pop]")) return;
68
+ if (t.closest("[data-dtf-pop]")) return;
69
+ if ((_a2 = anchorRef.current) == null ? void 0 : _a2.contains(t)) return;
70
+ setOpen(false);
71
+ };
72
+ const update = () => {
73
+ if (!anchorRef.current) return;
74
+ setAnchorRect(anchorRef.current.getBoundingClientRect());
75
+ };
76
+ const onEsc = (e) => {
77
+ if (e.key === "Escape") setOpen(false);
78
+ };
79
+ window.addEventListener("pointerdown", onDown, true);
80
+ window.addEventListener("scroll", update, true);
81
+ window.addEventListener("resize", update);
82
+ window.addEventListener("keydown", onEsc);
83
+ return () => {
84
+ window.removeEventListener("pointerdown", onDown, true);
85
+ window.removeEventListener("scroll", update, true);
86
+ window.removeEventListener("resize", update);
87
+ window.removeEventListener("keydown", onEsc);
88
+ };
89
+ }, [open]);
90
+ const stylePop = (() => {
91
+ if (!anchorRect) return { visibility: "hidden" };
92
+ const W = 360, GAP = 8, MARGIN = 8, H = 180;
93
+ let left = anchorRect.right - W;
94
+ left = Math.max(MARGIN, Math.min(left, window.innerWidth - (W + MARGIN)));
95
+ let top = anchorRect.bottom + GAP;
96
+ if (top + H > window.innerHeight) top = Math.max(MARGIN, anchorRect.top - GAP - H);
97
+ return { position: "fixed", top, left, zIndex: 1e5 };
98
+ })();
99
+ const commit = (f, t) => {
100
+ let f2 = f, t2 = t;
101
+ if (f2 && t2) {
102
+ const a = f2.hh * 60 + f2.mm;
103
+ const b = t2.hh * 60 + t2.mm;
104
+ if (b < a) t2 = { ...f2 };
105
+ }
106
+ setFrom(f2);
107
+ setTo(t2);
108
+ onValueChange == null ? void 0 : onValueChange({ from: f2 ? fmtHHmm(f2.hh, f2.mm) : null, to: t2 ? fmtHHmm(t2.hh, t2.mm) : null });
109
+ };
110
+ const popover = /* @__PURE__ */ jsxs("div", { "data-trf-pop": true, style: stylePop, className: "w-1/3 overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-xl dark:border-white/10 dark:bg-[#0e0d0e]", children: [
111
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2 text-sm", children: [
112
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: "Selecciona horario" }),
113
+ /* @__PURE__ */ jsx(
114
+ "button",
115
+ {
116
+ type: "button",
117
+ className: "rounded-xl bg-slate-900 px-3 py-1.5 text-white hover:opacity-95 active:scale-[0.98] dark:bg-white dark:text-slate-900",
118
+ onClick: () => setOpen(false),
119
+ children: "Aplicar"
120
+ }
121
+ )
122
+ ] }),
123
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 border-t border-slate-100 p-3 text-sm dark:border-white/10", children: [
124
+ /* @__PURE__ */ jsxs("div", { children: [
125
+ /* @__PURE__ */ jsx("div", { className: "mb-1 text-xs text-slate-500 dark:text-slate-300", children: "Desde" }),
126
+ /* @__PURE__ */ jsx(
127
+ "button",
128
+ {
129
+ type: "button",
130
+ className: "rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 font-medium tracking-wide hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
131
+ onClick: () => setShowFromPop((v) => !v),
132
+ ref: fromBtnRef,
133
+ children: from ? fmtHHmm(from.hh, from.mm) : "--:--"
134
+ }
135
+ ),
136
+ /* @__PURE__ */ jsx(
137
+ "button",
138
+ {
139
+ type: "button",
140
+ className: "ml-2 rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
141
+ onClick: () => {
142
+ const t = /* @__PURE__ */ new Date();
143
+ const rounded = Math.round(t.getMinutes() / step) * step % 60;
144
+ commit({ hh: t.getHours(), mm: rounded }, to);
145
+ },
146
+ children: "Ahora"
147
+ }
148
+ )
149
+ ] }),
150
+ /* @__PURE__ */ jsxs("div", { children: [
151
+ /* @__PURE__ */ jsx("div", { className: "mb-1 text-xs text-slate-500 dark:text-slate-300", children: "Hasta" }),
152
+ /* @__PURE__ */ jsx(
153
+ "button",
154
+ {
155
+ type: "button",
156
+ className: "rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 font-medium tracking-wide hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
157
+ onClick: () => setShowToPop((v) => !v),
158
+ ref: toBtnRef,
159
+ children: to ? fmtHHmm(to.hh, to.mm) : "--:--"
160
+ }
161
+ ),
162
+ /* @__PURE__ */ jsx(
163
+ "button",
164
+ {
165
+ type: "button",
166
+ className: "ml-2 rounded-xl ring-1 ring-slate-200 px-2.5 py-1.5 hover:bg-slate-50 active:scale-[0.98] dark:ring-white/10 dark:hover:bg-white/10",
167
+ onClick: () => {
168
+ const t = /* @__PURE__ */ new Date();
169
+ const rounded = Math.round(t.getMinutes() / step) * step % 60;
170
+ const candidate = { hh: t.getHours(), mm: rounded };
171
+ commit(from, candidate);
172
+ },
173
+ children: "Ahora"
174
+ }
175
+ )
176
+ ] })
177
+ ] })
178
+ ] });
179
+ return /* @__PURE__ */ jsxs("div", { ref: anchorRef, className, children: [
180
+ /* @__PURE__ */ jsx(
181
+ Input,
182
+ {
183
+ readOnly: true,
184
+ value: display,
185
+ placeholder,
186
+ onClick: openPopover,
187
+ clearable,
188
+ onClear: () => {
189
+ setFrom(null);
190
+ setTo(null);
191
+ onValueChange == null ? void 0 : onValueChange({ from: null, to: null });
192
+ },
193
+ disabled,
194
+ rightSlot: /* @__PURE__ */ jsx(
195
+ "button",
196
+ {
197
+ type: "button",
198
+ className: "pointer-events-auto inline-flex h-7 w-7 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-600 hover:bg-slate-50 active:scale-95 dark:border-white/10 dark:bg-white/5",
199
+ onClick: (e) => {
200
+ e.preventDefault();
201
+ openPopover();
202
+ },
203
+ title: "Abrir selector de horas",
204
+ children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-4.5 w-4.5", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
205
+ /* @__PURE__ */ jsx("path", { d: "M12 7v5l3 3" }),
206
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" })
207
+ ] })
208
+ }
209
+ )
210
+ }
211
+ ),
212
+ open && (portal ? portalRoot && createPortal(popover, portalRoot) : popover),
213
+ open && showFromPop && /* @__PURE__ */ jsx(
214
+ TimePopover,
215
+ {
216
+ anchorEl: fromBtnRef.current,
217
+ hh: (_a = from == null ? void 0 : from.hh) != null ? _a : 0,
218
+ mm: (_b = from == null ? void 0 : from.mm) != null ? _b : 0,
219
+ onChange: (H, M) => commit({ hh: H, mm: M }, to),
220
+ onClose: () => setShowFromPop(false),
221
+ step
222
+ }
223
+ ),
224
+ open && showToPop && /* @__PURE__ */ jsx(
225
+ TimePopover,
226
+ {
227
+ anchorEl: toBtnRef.current,
228
+ hh: (_d = to == null ? void 0 : to.hh) != null ? _d : (_c = from == null ? void 0 : from.hh) != null ? _c : 0,
229
+ mm: (_f = to == null ? void 0 : to.mm) != null ? _f : (_e = from == null ? void 0 : from.mm) != null ? _e : 0,
230
+ onChange: (H, M) => commit(from, { hh: H, mm: M }),
231
+ onClose: () => setShowToPop(false),
232
+ step
233
+ }
234
+ )
235
+ ] });
236
+ }
237
+ export {
238
+ TimeRangeField as default
239
+ };
package/dist/index.d.mts CHANGED
@@ -23,9 +23,12 @@ export { default as AvatarSquare } from './AvatarSquare.mjs';
23
23
  export { default as AppTopbar } from './AppTopbar.mjs';
24
24
  export { default as OrderButton } from './OrderButton.mjs';
25
25
  export { default as SearchInput } from './SearchInput.mjs';
26
+ export { default as ReviewHistory, ReviewHistoryDialog } from './ReviewHistory.mjs';
27
+ export { default as Sidebar } from './Sidebar.mjs';
26
28
  export { default as CalendarPanel, CalendarPanelProps } from './CalendarPanel.mjs';
27
29
  export { MonthPopover, default as TimePopover, WeekPopover } from './TimePopover.mjs';
28
30
  export { default as TimePanel } from './TimePanel.mjs';
31
+ export { TimeRange, default as TimeRangeField, TimeRangeFieldProps } from './TimeRangeField.mjs';
29
32
  export { StepDef, default as Steps, StepsNav } from './Steps.mjs';
30
33
  export { Aficionados, AuditarDocumento, Borrar, CajaDeMano, Cajas, Calendario, ChevronLeftRightIcon, CirculoAdvertencia, CirculoExito, CirculoPeligro, CirculoPorDefecto, ClientsIcon, CloseIcon, ContraseniaDeEmailIcon, Cotizaciones, DashboardIcon, Directorio, Edificio, Editar, Empresa, EscaneoFacial, EyeIcon, FlechaAbajo, FlechaArriba, Imagenes, LlamadaTelefonica, LogoutIcon, MarketingDigital, MediosDeComunicacionSocial, MenuIcon, MenuPuntosVerticalIcon, Nota, Ojo, OrdersIcon, PencilIcon, PermsIcon, ProductsIcon, PromoIcon, Retroalimentacion, RolesIcon, Sobre, Tablero, Tarea, Tickets, TrabajoEnEquipo, TrashIcon, UserIcon, UsersIcon, UsuarioProhibidoIcon, Usuarios } from './iconos/index.mjs';
31
34
  import 'react/jsx-runtime';
package/dist/index.d.ts CHANGED
@@ -23,9 +23,12 @@ export { default as AvatarSquare } from './AvatarSquare.js';
23
23
  export { default as AppTopbar } from './AppTopbar.js';
24
24
  export { default as OrderButton } from './OrderButton.js';
25
25
  export { default as SearchInput } from './SearchInput.js';
26
+ export { default as ReviewHistory, ReviewHistoryDialog } from './ReviewHistory.js';
27
+ export { default as Sidebar } from './Sidebar.js';
26
28
  export { default as CalendarPanel, CalendarPanelProps } from './CalendarPanel.js';
27
29
  export { MonthPopover, default as TimePopover, WeekPopover } from './TimePopover.js';
28
30
  export { default as TimePanel } from './TimePanel.js';
31
+ export { TimeRange, default as TimeRangeField, TimeRangeFieldProps } from './TimeRangeField.js';
29
32
  export { StepDef, default as Steps, StepsNav } from './Steps.js';
30
33
  export { Aficionados, AuditarDocumento, Borrar, CajaDeMano, Cajas, Calendario, ChevronLeftRightIcon, CirculoAdvertencia, CirculoExito, CirculoPeligro, CirculoPorDefecto, ClientsIcon, CloseIcon, ContraseniaDeEmailIcon, Cotizaciones, DashboardIcon, Directorio, Edificio, Editar, Empresa, EscaneoFacial, EyeIcon, FlechaAbajo, FlechaArriba, Imagenes, LlamadaTelefonica, LogoutIcon, MarketingDigital, MediosDeComunicacionSocial, MenuIcon, MenuPuntosVerticalIcon, Nota, Ojo, OrdersIcon, PencilIcon, PermsIcon, ProductsIcon, PromoIcon, Retroalimentacion, RolesIcon, Sobre, Tablero, Tarea, Tickets, TrabajoEnEquipo, TrashIcon, UserIcon, UsersIcon, UsuarioProhibidoIcon, Usuarios } from './iconos/index.js';
31
34
  import 'react/jsx-runtime';
package/dist/index.js CHANGED
@@ -51,8 +51,11 @@ __export(index_exports, {
51
51
  MonthPopover: () => import_TimePopover2.MonthPopover,
52
52
  OrderButton: () => import_OrderButton.default,
53
53
  Pagination: () => import_Pagination.default,
54
+ ReviewHistory: () => import_ReviewHistory.default,
55
+ ReviewHistoryDialog: () => import_ReviewHistory2.ReviewHistoryDialog,
54
56
  SearchInput: () => import_SearchInput.default,
55
57
  Select: () => import_Select.default,
58
+ Sidebar: () => import_Sidebar.default,
56
59
  SortTh: () => import_Table.SortTh,
57
60
  StatCard: () => import_StatCard.default,
58
61
  Steps: () => import_Steps.default,
@@ -62,6 +65,7 @@ __export(index_exports, {
62
65
  TimeAgo: () => import_TimeAgo.default,
63
66
  TimePanel: () => import_TimePanel.default,
64
67
  TimePopover: () => import_TimePopover.default,
68
+ TimeRangeField: () => import_TimeRangeField.default,
65
69
  WeekPopover: () => import_TimePopover2.WeekPopover
66
70
  });
67
71
  module.exports = __toCommonJS(index_exports);
@@ -92,10 +96,14 @@ var import_AvatarSquare = __toESM(require("./AvatarSquare"));
92
96
  var import_AppTopbar = __toESM(require("./AppTopbar"));
93
97
  var import_OrderButton = __toESM(require("./OrderButton"));
94
98
  var import_SearchInput = __toESM(require("./SearchInput"));
99
+ var import_ReviewHistory = __toESM(require("./ReviewHistory"));
100
+ var import_ReviewHistory2 = require("./ReviewHistory");
101
+ var import_Sidebar = __toESM(require("./Sidebar"));
95
102
  var import_CalendarPanel = __toESM(require("./CalendarPanel"));
96
103
  var import_TimePopover = __toESM(require("./TimePopover"));
97
104
  var import_TimePopover2 = require("./TimePopover");
98
105
  var import_TimePanel = __toESM(require("./TimePanel"));
106
+ var import_TimeRangeField = __toESM(require("./TimeRangeField"));
99
107
  var import_Steps = __toESM(require("./Steps"));
100
108
  var import_Steps2 = require("./Steps");
101
109
  __reExport(index_exports, require("./iconos"), module.exports);
@@ -123,8 +131,11 @@ __reExport(index_exports, require("./iconos"), module.exports);
123
131
  MonthPopover,
124
132
  OrderButton,
125
133
  Pagination,
134
+ ReviewHistory,
135
+ ReviewHistoryDialog,
126
136
  SearchInput,
127
137
  Select,
138
+ Sidebar,
128
139
  SortTh,
129
140
  StatCard,
130
141
  Steps,
@@ -134,6 +145,7 @@ __reExport(index_exports, require("./iconos"), module.exports);
134
145
  TimeAgo,
135
146
  TimePanel,
136
147
  TimePopover,
148
+ TimeRangeField,
137
149
  WeekPopover,
138
150
  ...require("./Dialog"),
139
151
  ...require("./Dropdown"),
package/dist/index.mjs CHANGED
@@ -25,11 +25,15 @@ import { default as default22 } from "./AvatarSquare";
25
25
  import { default as default23 } from "./AppTopbar";
26
26
  import { default as default24 } from "./OrderButton";
27
27
  import { default as default25 } from "./SearchInput";
28
- import { default as default26 } from "./CalendarPanel";
29
- import { default as default27 } from "./TimePopover";
28
+ import { default as default26 } from "./ReviewHistory";
29
+ import { ReviewHistoryDialog } from "./ReviewHistory";
30
+ import { default as default27 } from "./Sidebar";
31
+ import { default as default28 } from "./CalendarPanel";
32
+ import { default as default29 } from "./TimePopover";
30
33
  import { WeekPopover, MonthPopover } from "./TimePopover";
31
- import { default as default28 } from "./TimePanel";
32
- import { default as default29 } from "./Steps";
34
+ import { default as default30 } from "./TimePanel";
35
+ import { default as default31 } from "./TimeRangeField";
36
+ import { default as default32 } from "./Steps";
33
37
  import { StepsNav } from "./Steps";
34
38
  export * from "./iconos";
35
39
  export {
@@ -40,7 +44,7 @@ export {
40
44
  default17 as BadgeCluster,
41
45
  default18 as Breadcrumb,
42
46
  default2 as Button,
43
- default26 as CalendarPanel,
47
+ default28 as CalendarPanel,
44
48
  default14 as ChartCard,
45
49
  default5 as CheckboxPillsGroup,
46
50
  default8 as ColumnSelector,
@@ -55,16 +59,20 @@ export {
55
59
  MonthPopover,
56
60
  default24 as OrderButton,
57
61
  default12 as Pagination,
62
+ default26 as ReviewHistory,
63
+ ReviewHistoryDialog,
58
64
  default25 as SearchInput,
59
65
  default6 as Select,
66
+ default27 as Sidebar,
60
67
  SortTh,
61
68
  default15 as StatCard,
62
- default29 as Steps,
69
+ default32 as Steps,
63
70
  StepsNav,
64
71
  Td,
65
72
  Th,
66
73
  default21 as TimeAgo,
67
- default28 as TimePanel,
68
- default27 as TimePopover,
74
+ default30 as TimePanel,
75
+ default29 as TimePopover,
76
+ default31 as TimeRangeField,
69
77
  WeekPopover
70
78
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framepexls-ui-lib",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "Componentes UI de Framepexls para React/Next.",
@@ -36,8 +36,8 @@
36
36
  "devDependencies": {
37
37
  "typescript": "^5.6.3",
38
38
  "tsup": "^8.1.0",
39
- "@types/react": "^18",
40
- "@types/react-dom": "^18",
39
+ "@types/react": "^19",
40
+ "@types/react-dom": "^19",
41
41
  "tailwindcss": "^4.1.13",
42
42
  "@tailwindcss/postcss": "^4.1.13",
43
43
  "motion": "^12.23.16",
@@ -58,4 +58,4 @@
58
58
  "url": "https://github.com/cponce-framepexls/ui-lib/issues"
59
59
  },
60
60
  "homepage": "https://github.com/cponce-framepexls/ui-lib#readme"
61
- }
61
+ }