framepexls-ui-lib 0.1.8 → 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.
package/dist/Badge.d.mts CHANGED
@@ -2,8 +2,10 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
 
4
4
  type Tone = "emerald" | "indigo" | "amber" | "slate" | "rose" | "sky" | "violet" | "cyan" | "teal" | "pink" | "orange" | "lime";
5
- declare function Badge({ tone, children, onClick, title, className, }: {
5
+ type Size = "sm" | "md" | "lg";
6
+ declare function Badge({ tone, size, children, onClick, title, className, }: {
6
7
  tone?: Tone;
8
+ size?: Size;
7
9
  children: React__default.ReactNode;
8
10
  onClick?: (e: React__default.MouseEvent) => void;
9
11
  title?: string;
package/dist/Badge.d.ts CHANGED
@@ -2,8 +2,10 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React__default from 'react';
3
3
 
4
4
  type Tone = "emerald" | "indigo" | "amber" | "slate" | "rose" | "sky" | "violet" | "cyan" | "teal" | "pink" | "orange" | "lime";
5
- declare function Badge({ tone, children, onClick, title, className, }: {
5
+ type Size = "sm" | "md" | "lg";
6
+ declare function Badge({ tone, size, children, onClick, title, className, }: {
6
7
  tone?: Tone;
8
+ size?: Size;
7
9
  children: React__default.ReactNode;
8
10
  onClick?: (e: React__default.MouseEvent) => void;
9
11
  title?: string;
package/dist/Badge.js CHANGED
@@ -37,27 +37,37 @@ const tones = {
37
37
  orange: "bg-orange-100 text-orange-700 ring-1 ring-orange-200",
38
38
  lime: "bg-lime-100 text-lime-700 ring-1 ring-lime-200"
39
39
  };
40
+ const sizeClasses = {
41
+ sm: { wrap: "px-2 py-0.5 text-[11px]", dot: "h-1.5 w-1.5", gap: "gap-1.5" },
42
+ md: { wrap: "px-2.5 py-1 text-xs", dot: "h-1.5 w-1.5", gap: "gap-2" },
43
+ lg: { wrap: "px-3 py-1.5 text-sm", dot: "h-2 w-2", gap: "gap-2" }
44
+ };
40
45
  function Badge({
41
46
  tone = "slate",
47
+ size = "md",
42
48
  children,
43
49
  onClick,
44
50
  title,
45
51
  className = ""
46
52
  }) {
53
+ var _a;
47
54
  const clickable = typeof onClick === "function";
55
+ const sz = (_a = sizeClasses[size]) != null ? _a : sizeClasses.md;
48
56
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
49
57
  "span",
50
58
  {
51
59
  title,
52
60
  onClick,
53
61
  className: [
54
- "inline-flex items-center gap-2 rounded-full px-2.5 py-1 text-xs font-semibold truncate",
62
+ "inline-flex items-center rounded-full font-semibold truncate",
55
63
  tones[tone],
64
+ sz.wrap,
65
+ sz.gap,
56
66
  clickable ? "cursor-pointer hover:opacity-90 active:scale-[0.98]" : "",
57
67
  className
58
68
  ].join(" "),
59
69
  children: [
60
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-70" }),
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: ["inline-block rounded-full bg-current opacity-70", sz.dot].join(" ") }),
61
71
  children
62
72
  ]
63
73
  }
package/dist/Badge.mjs CHANGED
@@ -14,27 +14,37 @@ const tones = {
14
14
  orange: "bg-orange-100 text-orange-700 ring-1 ring-orange-200",
15
15
  lime: "bg-lime-100 text-lime-700 ring-1 ring-lime-200"
16
16
  };
17
+ const sizeClasses = {
18
+ sm: { wrap: "px-2 py-0.5 text-[11px]", dot: "h-1.5 w-1.5", gap: "gap-1.5" },
19
+ md: { wrap: "px-2.5 py-1 text-xs", dot: "h-1.5 w-1.5", gap: "gap-2" },
20
+ lg: { wrap: "px-3 py-1.5 text-sm", dot: "h-2 w-2", gap: "gap-2" }
21
+ };
17
22
  function Badge({
18
23
  tone = "slate",
24
+ size = "md",
19
25
  children,
20
26
  onClick,
21
27
  title,
22
28
  className = ""
23
29
  }) {
30
+ var _a;
24
31
  const clickable = typeof onClick === "function";
32
+ const sz = (_a = sizeClasses[size]) != null ? _a : sizeClasses.md;
25
33
  return /* @__PURE__ */ jsxs(
26
34
  "span",
27
35
  {
28
36
  title,
29
37
  onClick,
30
38
  className: [
31
- "inline-flex items-center gap-2 rounded-full px-2.5 py-1 text-xs font-semibold truncate",
39
+ "inline-flex items-center rounded-full font-semibold truncate",
32
40
  tones[tone],
41
+ sz.wrap,
42
+ sz.gap,
33
43
  clickable ? "cursor-pointer hover:opacity-90 active:scale-[0.98]" : "",
34
44
  className
35
45
  ].join(" "),
36
46
  children: [
37
- /* @__PURE__ */ jsx("span", { className: "inline-block h-1.5 w-1.5 rounded-full bg-current opacity-70" }),
47
+ /* @__PURE__ */ jsx("span", { className: ["inline-block rounded-full bg-current opacity-70", sz.dot].join(" ") }),
38
48
  children
39
49
  ]
40
50
  }
package/dist/Button.d.mts CHANGED
@@ -11,7 +11,10 @@ type ButtonProps = {
11
11
  className?: string;
12
12
  active?: boolean;
13
13
  inverted?: boolean;
14
+ iconOnly?: boolean;
15
+ icon?: React__default.ReactNode;
16
+ noPaddingX?: boolean;
14
17
  } & React__default.ButtonHTMLAttributes<HTMLButtonElement>;
15
- declare function Button({ children, variant, size, loading, disabled, leftIcon, rightIcon, block, className, type, active, inverted, ...rest }: ButtonProps): react_jsx_runtime.JSX.Element;
18
+ declare function Button({ children, variant, size, loading, disabled, leftIcon, rightIcon, block, className, type, active, inverted, iconOnly, icon, noPaddingX, ...rest }: ButtonProps): react_jsx_runtime.JSX.Element;
16
19
 
17
20
  export { Button as default };
package/dist/Button.d.ts CHANGED
@@ -11,7 +11,10 @@ type ButtonProps = {
11
11
  className?: string;
12
12
  active?: boolean;
13
13
  inverted?: boolean;
14
+ iconOnly?: boolean;
15
+ icon?: React__default.ReactNode;
16
+ noPaddingX?: boolean;
14
17
  } & React__default.ButtonHTMLAttributes<HTMLButtonElement>;
15
- declare function Button({ children, variant, size, loading, disabled, leftIcon, rightIcon, block, className, type, active, inverted, ...rest }: ButtonProps): react_jsx_runtime.JSX.Element;
18
+ declare function Button({ children, variant, size, loading, disabled, leftIcon, rightIcon, block, className, type, active, inverted, iconOnly, icon, noPaddingX, ...rest }: ButtonProps): react_jsx_runtime.JSX.Element;
16
19
 
17
20
  export { Button as default };
package/dist/Button.js CHANGED
@@ -36,10 +36,13 @@ function Button({
36
36
  type = "button",
37
37
  active = false,
38
38
  inverted = false,
39
+ iconOnly = false,
40
+ icon,
41
+ noPaddingX = false,
39
42
  ...rest
40
43
  }) {
41
- const base = "inline-flex items-center justify-center gap-2 rounded-xl font-medium transition focus:outline-none focus-visible:ring-2 disabled:opacity-60 disabled:cursor-not-allowed";
42
- const sizes = size === "sm" ? "h-9 px-3 text-sm" : size === "lg" ? "h-11 px-5 text-base" : "h-10 px-4 text-sm";
44
+ const base = "inline-flex items-center justify-center rounded-xl font-medium transition focus:outline-none focus-visible:ring-2 disabled:opacity-60 disabled:cursor-not-allowed";
45
+ const sizes = size === "sm" ? `h-9 ${noPaddingX ? "" : "px-3"} text-sm` : size === "lg" ? `h-11 ${noPaddingX ? "" : "px-5"} text-base` : `h-10 ${noPaddingX ? "" : "px-4"} text-sm`;
43
46
  const variantClass = (() => {
44
47
  switch (variant) {
45
48
  case "primary":
@@ -55,6 +58,12 @@ function Button({
55
58
  }
56
59
  })();
57
60
  const activeClass = active ? variant === "primary" ? "ring-2 ring-slate-300/60 dark:ring-white/20" : variant === "ghost" ? inverted ? "bg-white/15 text-white shadow-sm" : "bg-slate-100 text-slate-900 shadow-sm" : variant === "outline" ? inverted ? "bg-white/10 text-white" : "bg-slate-50" : variant === "secondary" ? inverted ? "bg-white/15 text-white" : "bg-slate-100" : "" : "";
61
+ const hasChildren = children !== void 0 && children !== null && children !== false;
62
+ const showText = hasChildren && !iconOnly;
63
+ const iconLeft = !loading ? leftIcon != null ? leftIcon : iconOnly ? icon != null ? icon : children : void 0 : void 0;
64
+ const iconRight = !loading ? rightIcon : void 0;
65
+ const visibleParts = [iconLeft, showText ? true : null, iconRight].filter(Boolean).length;
66
+ const gapClass = visibleParts > 1 ? "gap-2" : "gap-0";
58
67
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
59
68
  "button",
60
69
  {
@@ -66,6 +75,7 @@ function Button({
66
75
  sizes,
67
76
  variantClass,
68
77
  activeClass,
78
+ gapClass,
69
79
  block ? "w-full" : "",
70
80
  className
71
81
  ].join(" "),
@@ -75,9 +85,9 @@ function Button({
75
85
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "9", className: "opacity-25" }),
76
86
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12a9 9 0 0 0-9-9", className: "opacity-90" })
77
87
  ] }),
78
- !loading && leftIcon,
79
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children }),
80
- !loading && rightIcon
88
+ iconLeft,
89
+ showText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children }),
90
+ iconRight
81
91
  ]
82
92
  }
83
93
  );
package/dist/Button.mjs CHANGED
@@ -13,10 +13,13 @@ function Button({
13
13
  type = "button",
14
14
  active = false,
15
15
  inverted = false,
16
+ iconOnly = false,
17
+ icon,
18
+ noPaddingX = false,
16
19
  ...rest
17
20
  }) {
18
- const base = "inline-flex items-center justify-center gap-2 rounded-xl font-medium transition focus:outline-none focus-visible:ring-2 disabled:opacity-60 disabled:cursor-not-allowed";
19
- const sizes = size === "sm" ? "h-9 px-3 text-sm" : size === "lg" ? "h-11 px-5 text-base" : "h-10 px-4 text-sm";
21
+ const base = "inline-flex items-center justify-center rounded-xl font-medium transition focus:outline-none focus-visible:ring-2 disabled:opacity-60 disabled:cursor-not-allowed";
22
+ const sizes = size === "sm" ? `h-9 ${noPaddingX ? "" : "px-3"} text-sm` : size === "lg" ? `h-11 ${noPaddingX ? "" : "px-5"} text-base` : `h-10 ${noPaddingX ? "" : "px-4"} text-sm`;
20
23
  const variantClass = (() => {
21
24
  switch (variant) {
22
25
  case "primary":
@@ -32,6 +35,12 @@ function Button({
32
35
  }
33
36
  })();
34
37
  const activeClass = active ? variant === "primary" ? "ring-2 ring-slate-300/60 dark:ring-white/20" : variant === "ghost" ? inverted ? "bg-white/15 text-white shadow-sm" : "bg-slate-100 text-slate-900 shadow-sm" : variant === "outline" ? inverted ? "bg-white/10 text-white" : "bg-slate-50" : variant === "secondary" ? inverted ? "bg-white/15 text-white" : "bg-slate-100" : "" : "";
38
+ const hasChildren = children !== void 0 && children !== null && children !== false;
39
+ const showText = hasChildren && !iconOnly;
40
+ const iconLeft = !loading ? leftIcon != null ? leftIcon : iconOnly ? icon != null ? icon : children : void 0 : void 0;
41
+ const iconRight = !loading ? rightIcon : void 0;
42
+ const visibleParts = [iconLeft, showText ? true : null, iconRight].filter(Boolean).length;
43
+ const gapClass = visibleParts > 1 ? "gap-2" : "gap-0";
35
44
  return /* @__PURE__ */ jsxs(
36
45
  "button",
37
46
  {
@@ -43,6 +52,7 @@ function Button({
43
52
  sizes,
44
53
  variantClass,
45
54
  activeClass,
55
+ gapClass,
46
56
  block ? "w-full" : "",
47
57
  className
48
58
  ].join(" "),
@@ -52,9 +62,9 @@ function Button({
52
62
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", className: "opacity-25" }),
53
63
  /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", className: "opacity-90" })
54
64
  ] }),
55
- !loading && leftIcon,
56
- /* @__PURE__ */ jsx("span", { className: "truncate", children }),
57
- !loading && rightIcon
65
+ iconLeft,
66
+ showText && /* @__PURE__ */ jsx("span", { className: "truncate", children }),
67
+ iconRight
58
68
  ]
59
69
  }
60
70
  );
@@ -0,0 +1,23 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type ReviewItem = {
4
+ id: number;
5
+ status: "pendiente" | "en_revision" | "aprobado" | "rechazado";
6
+ comment?: string | null;
7
+ by_name?: string | null;
8
+ by_email?: string | null;
9
+ user_id?: number | null;
10
+ created_at: string;
11
+ };
12
+ declare function ReviewHistory({ items, loading, onViewAll, }: {
13
+ items: ReviewItem[];
14
+ loading?: boolean;
15
+ onViewAll?: () => void;
16
+ }): react_jsx_runtime.JSX.Element;
17
+ declare function ReviewHistoryDialog({ open, onClose, items, }: {
18
+ open: boolean;
19
+ onClose: () => void;
20
+ items: ReviewItem[];
21
+ }): react_jsx_runtime.JSX.Element;
22
+
23
+ export { ReviewHistoryDialog, type ReviewItem, ReviewHistory as default };
@@ -0,0 +1,23 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type ReviewItem = {
4
+ id: number;
5
+ status: "pendiente" | "en_revision" | "aprobado" | "rechazado";
6
+ comment?: string | null;
7
+ by_name?: string | null;
8
+ by_email?: string | null;
9
+ user_id?: number | null;
10
+ created_at: string;
11
+ };
12
+ declare function ReviewHistory({ items, loading, onViewAll, }: {
13
+ items: ReviewItem[];
14
+ loading?: boolean;
15
+ onViewAll?: () => void;
16
+ }): react_jsx_runtime.JSX.Element;
17
+ declare function ReviewHistoryDialog({ open, onClose, items, }: {
18
+ open: boolean;
19
+ onClose: () => void;
20
+ items: ReviewItem[];
21
+ }): react_jsx_runtime.JSX.Element;
22
+
23
+ export { ReviewHistoryDialog, type ReviewItem, ReviewHistory as default };
@@ -0,0 +1,137 @@
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 ReviewHistory_exports = {};
31
+ __export(ReviewHistory_exports, {
32
+ ReviewHistoryDialog: () => ReviewHistoryDialog,
33
+ default: () => ReviewHistory
34
+ });
35
+ module.exports = __toCommonJS(ReviewHistory_exports);
36
+ var import_jsx_runtime = require("react/jsx-runtime");
37
+ var import_Dialog = __toESM(require("./Dialog"));
38
+ var import_Badge = __toESM(require("./Badge"));
39
+ function ReviewHistory({
40
+ items,
41
+ loading,
42
+ onViewAll
43
+ }) {
44
+ const latest = (items != null ? items : []).slice(0, 3);
45
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid gap-2", children: [
46
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between", children: [
47
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm font-semibold", children: "Historial de estado" }),
48
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-muted", children: loading ? "Cargando\u2026" : `${items.length} total` })
49
+ ] }),
50
+ latest.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-muted", children: "Sin registros" }),
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2", children: latest.map((r) => {
52
+ var _a;
53
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border border-border bg-surface px-3 py-2 text-sm", children: [
54
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-medium", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Badge.default, { tone: statusTone(r.status), children: statusLabel(r.status) }) }),
56
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-muted", children: formatDateTime(r.created_at) })
57
+ ] }),
58
+ r.comment && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 text-sm text-foreground whitespace-pre-line", children: r.comment }),
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 text-xs text-muted", children: r.by_name || r.by_email ? `${(_a = r.by_name) != null ? _a : ""} ${r.by_email ? `\xB7 ${r.by_email}` : ""}` : r.user_id ? "Usuario interno" : "Invitado" })
60
+ ] }, r.id);
61
+ }) }),
62
+ items.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pt-1", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "text-sm text-blue-600 hover:underline dark:text-blue-400", onClick: onViewAll, children: "Ver todos" }) })
63
+ ] });
64
+ }
65
+ function ReviewHistoryDialog({
66
+ open,
67
+ onClose,
68
+ items
69
+ }) {
70
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dialog.default, { open, onClose, size: "md", children: [
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dialog.default.Header, { title: "Historial de estado", onClose, showClose: true, compact: true }),
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dialog.default.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "grid gap-2", children: [
73
+ items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-muted", children: "Sin registros" }),
74
+ items.map((r) => {
75
+ var _a;
76
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border border-border bg-surface px-3 py-2 text-sm", children: [
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "font-medium", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Badge.default, { tone: statusTone(r.status), children: statusLabel(r.status) }) }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-muted", children: formatDateTime(r.created_at) })
80
+ ] }),
81
+ r.comment && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 text-sm text-foreground whitespace-pre-line", children: r.comment }),
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 text-xs text-muted", children: r.by_name || r.by_email ? `${(_a = r.by_name) != null ? _a : ""} ${r.by_email ? `\xB7 ${r.by_email}` : ""}` : r.user_id ? "Usuario interno" : "Invitado" })
83
+ ] }, r.id);
84
+ })
85
+ ] }) }),
86
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dialog.default.Footer, { align: "end", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
87
+ "button",
88
+ {
89
+ className: "inline-flex h-10 items-center gap-2 rounded-xl border border-slate-300/80 bg-white px-4 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 dark:border-white/10 dark:bg-white/5 dark:text-slate-200 dark:hover:bg-white/10",
90
+ onClick: onClose,
91
+ children: "Cerrar"
92
+ }
93
+ ) })
94
+ ] });
95
+ }
96
+ function formatDateTime(value) {
97
+ try {
98
+ return new Date(value).toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
99
+ } catch {
100
+ return value;
101
+ }
102
+ }
103
+ function ucfirst(s) {
104
+ return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
105
+ }
106
+ function statusLabel(s) {
107
+ switch (s) {
108
+ case "pendiente":
109
+ return "Pendiente";
110
+ case "en_revision":
111
+ return "En revisi\xF3n";
112
+ case "aprobado":
113
+ return "Aprobado";
114
+ case "rechazado":
115
+ return "Rechazado";
116
+ default:
117
+ return ucfirst(String(s));
118
+ }
119
+ }
120
+ function statusTone(s) {
121
+ switch (s) {
122
+ case "pendiente":
123
+ return "sky";
124
+ case "en_revision":
125
+ return "amber";
126
+ case "aprobado":
127
+ return "emerald";
128
+ case "rechazado":
129
+ return "rose";
130
+ default:
131
+ return "slate";
132
+ }
133
+ }
134
+ // Annotate the CommonJS export names for ESM import in node:
135
+ 0 && (module.exports = {
136
+ ReviewHistoryDialog
137
+ });
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import Dialog from "./Dialog";
4
+ import Badge from "./Badge";
5
+ function ReviewHistory({
6
+ items,
7
+ loading,
8
+ onViewAll
9
+ }) {
10
+ const latest = (items != null ? items : []).slice(0, 3);
11
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
12
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
13
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: "Historial de estado" }),
14
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: loading ? "Cargando\u2026" : `${items.length} total` })
15
+ ] }),
16
+ latest.length === 0 && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted", children: "Sin registros" }),
17
+ /* @__PURE__ */ jsx("div", { className: "grid gap-2", children: latest.map((r) => {
18
+ var _a;
19
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-surface px-3 py-2 text-sm", children: [
20
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
21
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: /* @__PURE__ */ jsx(Badge, { tone: statusTone(r.status), children: statusLabel(r.status) }) }),
22
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: formatDateTime(r.created_at) })
23
+ ] }),
24
+ r.comment && /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-foreground whitespace-pre-line", children: r.comment }),
25
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-muted", children: r.by_name || r.by_email ? `${(_a = r.by_name) != null ? _a : ""} ${r.by_email ? `\xB7 ${r.by_email}` : ""}` : r.user_id ? "Usuario interno" : "Invitado" })
26
+ ] }, r.id);
27
+ }) }),
28
+ items.length > 3 && /* @__PURE__ */ jsx("div", { className: "pt-1", children: /* @__PURE__ */ jsx("button", { className: "text-sm text-blue-600 hover:underline dark:text-blue-400", onClick: onViewAll, children: "Ver todos" }) })
29
+ ] });
30
+ }
31
+ function ReviewHistoryDialog({
32
+ open,
33
+ onClose,
34
+ items
35
+ }) {
36
+ return /* @__PURE__ */ jsxs(Dialog, { open, onClose, size: "md", children: [
37
+ /* @__PURE__ */ jsx(Dialog.Header, { title: "Historial de estado", onClose, showClose: true, compact: true }),
38
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
39
+ items.length === 0 && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted", children: "Sin registros" }),
40
+ items.map((r) => {
41
+ var _a;
42
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-surface px-3 py-2 text-sm", children: [
43
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
44
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: /* @__PURE__ */ jsx(Badge, { tone: statusTone(r.status), children: statusLabel(r.status) }) }),
45
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: formatDateTime(r.created_at) })
46
+ ] }),
47
+ r.comment && /* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-foreground whitespace-pre-line", children: r.comment }),
48
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-muted", children: r.by_name || r.by_email ? `${(_a = r.by_name) != null ? _a : ""} ${r.by_email ? `\xB7 ${r.by_email}` : ""}` : r.user_id ? "Usuario interno" : "Invitado" })
49
+ ] }, r.id);
50
+ })
51
+ ] }) }),
52
+ /* @__PURE__ */ jsx(Dialog.Footer, { align: "end", children: /* @__PURE__ */ jsx(
53
+ "button",
54
+ {
55
+ className: "inline-flex h-10 items-center gap-2 rounded-xl border border-slate-300/80 bg-white px-4 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 dark:border-white/10 dark:bg-white/5 dark:text-slate-200 dark:hover:bg-white/10",
56
+ onClick: onClose,
57
+ children: "Cerrar"
58
+ }
59
+ ) })
60
+ ] });
61
+ }
62
+ function formatDateTime(value) {
63
+ try {
64
+ return new Date(value).toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
65
+ } catch {
66
+ return value;
67
+ }
68
+ }
69
+ function ucfirst(s) {
70
+ return s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
71
+ }
72
+ function statusLabel(s) {
73
+ switch (s) {
74
+ case "pendiente":
75
+ return "Pendiente";
76
+ case "en_revision":
77
+ return "En revisi\xF3n";
78
+ case "aprobado":
79
+ return "Aprobado";
80
+ case "rechazado":
81
+ return "Rechazado";
82
+ default:
83
+ return ucfirst(String(s));
84
+ }
85
+ }
86
+ function statusTone(s) {
87
+ switch (s) {
88
+ case "pendiente":
89
+ return "sky";
90
+ case "en_revision":
91
+ return "amber";
92
+ case "aprobado":
93
+ return "emerald";
94
+ case "rechazado":
95
+ return "rose";
96
+ default:
97
+ return "slate";
98
+ }
99
+ }
100
+ export {
101
+ ReviewHistoryDialog,
102
+ ReviewHistory as default
103
+ };
@@ -0,0 +1,35 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+
4
+ type SidebarUser = {
5
+ name: string;
6
+ rol_principal: string;
7
+ avatarUrl?: string | null;
8
+ };
9
+ type SidebarItem = {
10
+ key: string;
11
+ label: string;
12
+ group: string;
13
+ icon?: React__default.ComponentType<{
14
+ className?: string;
15
+ }>;
16
+ path?: string;
17
+ children?: SidebarItem[];
18
+ };
19
+ type SidebarProps = {
20
+ items: SidebarItem[];
21
+ activeKey?: string;
22
+ onNavigate: (key: string) => void;
23
+ user?: SidebarUser;
24
+ userMenuSlot?: React__default.ReactNode;
25
+ onBrandClick?: () => void;
26
+ /** LocalStorage key para persistir colapsado */
27
+ collapsedKey?: string;
28
+ /** Rotulación de marca, valores por defecto mantienen estilos existentes */
29
+ brandInitials?: string;
30
+ brandTitle?: string;
31
+ brandSubtitle?: string;
32
+ };
33
+ declare function Sidebar({ items, activeKey, onNavigate, user, userMenuSlot, onBrandClick, collapsedKey, brandInitials, brandTitle, brandSubtitle, }: SidebarProps): react_jsx_runtime.JSX.Element;
34
+
35
+ export { type SidebarItem, type SidebarProps, type SidebarUser, Sidebar as default };
@@ -0,0 +1,35 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+
4
+ type SidebarUser = {
5
+ name: string;
6
+ rol_principal: string;
7
+ avatarUrl?: string | null;
8
+ };
9
+ type SidebarItem = {
10
+ key: string;
11
+ label: string;
12
+ group: string;
13
+ icon?: React__default.ComponentType<{
14
+ className?: string;
15
+ }>;
16
+ path?: string;
17
+ children?: SidebarItem[];
18
+ };
19
+ type SidebarProps = {
20
+ items: SidebarItem[];
21
+ activeKey?: string;
22
+ onNavigate: (key: string) => void;
23
+ user?: SidebarUser;
24
+ userMenuSlot?: React__default.ReactNode;
25
+ onBrandClick?: () => void;
26
+ /** LocalStorage key para persistir colapsado */
27
+ collapsedKey?: string;
28
+ /** Rotulación de marca, valores por defecto mantienen estilos existentes */
29
+ brandInitials?: string;
30
+ brandTitle?: string;
31
+ brandSubtitle?: string;
32
+ };
33
+ declare function Sidebar({ items, activeKey, onNavigate, user, userMenuSlot, onBrandClick, collapsedKey, brandInitials, brandTitle, brandSubtitle, }: SidebarProps): react_jsx_runtime.JSX.Element;
34
+
35
+ export { type SidebarItem, type SidebarProps, type SidebarUser, Sidebar as default };