framepexls-ui-lib 2.2.7 → 2.2.11

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.
Files changed (50) hide show
  1. package/dist/AccessibilityFab.js +2 -0
  2. package/dist/AccessibilityFab.mjs +2 -0
  3. package/dist/AvatarSquare.d.mts +4 -1
  4. package/dist/AvatarSquare.d.ts +4 -1
  5. package/dist/AvatarSquare.js +7 -1
  6. package/dist/AvatarSquare.mjs +7 -1
  7. package/dist/Checkbox.js +2 -2
  8. package/dist/Checkbox.mjs +2 -2
  9. package/dist/ComboSelect.js +4 -3
  10. package/dist/ComboSelect.mjs +4 -3
  11. package/dist/DateTimeField.js +3 -2
  12. package/dist/DateTimeField.mjs +3 -2
  13. package/dist/Dropdown.js +3 -0
  14. package/dist/Dropdown.mjs +3 -0
  15. package/dist/HeliipLoader.js +77 -5
  16. package/dist/HeliipLoader.mjs +77 -5
  17. package/dist/MarkdownEditor.d.mts +71 -3
  18. package/dist/MarkdownEditor.d.ts +71 -3
  19. package/dist/MarkdownEditor.js +2370 -65
  20. package/dist/MarkdownEditor.mjs +2388 -66
  21. package/dist/MediaSelector.d.mts +4 -1
  22. package/dist/MediaSelector.d.ts +4 -1
  23. package/dist/MediaSelector.js +134 -23
  24. package/dist/MediaSelector.mjs +135 -24
  25. package/dist/Select.js +2 -0
  26. package/dist/Select.mjs +2 -0
  27. package/dist/Sidebar.d.mts +2 -1
  28. package/dist/Sidebar.d.ts +2 -1
  29. package/dist/Sidebar.js +82 -19
  30. package/dist/Sidebar.mjs +82 -19
  31. package/dist/SupportChatWidget.js +88 -42
  32. package/dist/SupportChatWidget.mjs +89 -42
  33. package/dist/TimePanel.js +2 -1
  34. package/dist/TimePanel.mjs +2 -1
  35. package/dist/TimePopover.js +4 -3
  36. package/dist/TimePopover.mjs +4 -3
  37. package/dist/TimeRangeField.js +3 -2
  38. package/dist/TimeRangeField.mjs +3 -2
  39. package/dist/UploadCard.js +7 -7
  40. package/dist/UploadCard.mjs +7 -7
  41. package/dist/index.d.mts +1 -1
  42. package/dist/index.d.ts +1 -1
  43. package/dist/index.js +4 -0
  44. package/dist/index.mjs +3 -1
  45. package/dist/theme/FontSizeController.js +1 -1
  46. package/dist/theme/FontSizeController.mjs +1 -1
  47. package/dist/theme/ThemeController.js +2 -1
  48. package/dist/theme/ThemeController.mjs +2 -1
  49. package/dist/theme.css +47 -0
  50. package/package.json +8 -8
@@ -10,6 +10,7 @@ import TimeAgo from "./TimeAgo.mjs";
10
10
  import Tooltip from "./Tooltip.mjs";
11
11
  import {
12
12
  ChatCenteredDotsIcon,
13
+ ChatCircleTextIcon,
13
14
  ClockIcon,
14
15
  CloseIcon,
15
16
  DownloadSimpleIcon,
@@ -194,14 +195,34 @@ function SupportChatWidget({
194
195
  const open = openProp != null ? openProp : openState;
195
196
  const setOpen = (next) => {
196
197
  if (openProp === void 0) setOpenState(next);
198
+ if (next) setUnseenReplyCount(0);
197
199
  onOpenChange == null ? void 0 : onOpenChange(next);
198
200
  };
199
201
  const [messagesState, setMessagesState] = React.useState(() => defaultMessages != null ? defaultMessages : []);
200
202
  const messages = messagesProp != null ? messagesProp : messagesState;
201
203
  const messagesRef = React.useRef(messages);
204
+ const knownMessageIdsRef = React.useRef(new Set(messages.map((message) => message.id)));
205
+ const panelRef = React.useRef(null);
206
+ const triggerRef = React.useRef(null);
207
+ const [unseenReplyCount, setUnseenReplyCount] = React.useState(0);
202
208
  React.useEffect(() => {
203
209
  messagesRef.current = messages;
204
210
  }, [messages]);
211
+ React.useEffect(() => {
212
+ const knownIds = knownMessageIdsRef.current;
213
+ const newReplies = messages.filter((message) => {
214
+ const isNew = !knownIds.has(message.id);
215
+ return isNew && (message.role === "bot" || message.role === "agent");
216
+ });
217
+ messages.forEach((message) => knownIds.add(message.id));
218
+ if (open) {
219
+ setUnseenReplyCount(0);
220
+ return;
221
+ }
222
+ if (newReplies.length) {
223
+ setUnseenReplyCount((current) => Math.min(99, current + newReplies.length));
224
+ }
225
+ }, [messages, open]);
205
226
  const setMessages = (next) => {
206
227
  if (typeof next === "function") {
207
228
  const fn = next;
@@ -278,6 +299,18 @@ function SupportChatWidget({
278
299
  if (!open) return;
279
300
  (_a2 = endRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "end" });
280
301
  }, [open, messages.length, sending]);
302
+ React.useEffect(() => {
303
+ if (!open || position === "inline") return;
304
+ const onPointerDown = (event) => {
305
+ var _a2, _b2;
306
+ const target = event.target;
307
+ if (!target) return;
308
+ if (((_a2 = panelRef.current) == null ? void 0 : _a2.contains(target)) || ((_b2 = triggerRef.current) == null ? void 0 : _b2.contains(target))) return;
309
+ setOpen(false);
310
+ };
311
+ document.addEventListener("pointerdown", onPointerDown);
312
+ return () => document.removeEventListener("pointerdown", onPointerDown);
313
+ }, [open, position]);
281
314
  const appendBotResult = (result) => {
282
315
  if (!result) return;
283
316
  if (typeof result === "string") {
@@ -383,19 +416,22 @@ function SupportChatWidget({
383
416
  await ((_d2 = config.onSave) == null ? void 0 : _d2.call(config, payload));
384
417
  downloadFile(fileName, content, mimeType);
385
418
  };
386
- const trigger = /* @__PURE__ */ jsx(Tooltip, { content: labelTrigger, placement: position === "bottom-left" ? "right" : "left", offset: 10, children: /* @__PURE__ */ jsx("div", { className: cx(positionClass, className), style: position === "inline" ? void 0 : { zIndex }, children: /* @__PURE__ */ jsxs(
419
+ const trigger = /* @__PURE__ */ jsx(Tooltip, { content: labelTrigger, placement: position === "bottom-left" ? "right" : "left", offset: 10, children: /* @__PURE__ */ jsx("div", { ref: triggerRef, className: cx(positionClass, className), style: position === "inline" ? void 0 : { zIndex }, children: /* @__PURE__ */ jsxs(
387
420
  "button",
388
421
  {
389
422
  type: "button",
390
423
  "aria-label": labelTrigger,
391
424
  onClick: () => setOpen(true),
392
425
  className: cx(
393
- "relative grid h-14 w-14 place-items-center rounded-2xl border border-[color-mix(in_oklab,var(--ring)_28%,var(--border))]",
394
- "bg-[var(--primary)] text-[var(--primary-foreground)] shadow-xl transition hover:brightness-95 active:scale-[0.98]"
426
+ "group relative grid size-14 place-items-center overflow-hidden rounded-2xl border border-[var(--border)]",
427
+ "bg-[color-mix(in_oklab,var(--card)_94%,transparent)] text-[var(--primary)] shadow-[0_20px_48px_rgba(6,19,22,0.13)] backdrop-blur-xl",
428
+ "transition duration-200 hover:-translate-y-0.5 hover:border-[color-mix(in_oklab,var(--primary)_38%,var(--border))] hover:bg-[var(--surface)] hover:text-[var(--foreground)] hover:shadow-[0_24px_58px_rgba(6,19,22,0.18)] active:scale-[0.98]",
429
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color-mix(in_oklab,var(--primary)_42%,transparent)] dark:shadow-[0_20px_48px_rgba(0,0,0,0.28)] dark:hover:shadow-[0_24px_58px_rgba(0,0,0,0.36)]"
395
430
  ),
396
431
  children: [
397
- mode === "live" ? /* @__PURE__ */ jsx(HeadsetIcon, { "aria-hidden": true, className: "h-6 w-6" }) : /* @__PURE__ */ jsx(ChatCenteredDotsIcon, { "aria-hidden": true, className: "h-6 w-6" }),
398
- unreadCount > 0 ? /* @__PURE__ */ jsx("span", { className: "absolute -right-1.5 -top-1.5 grid h-5 min-w-5 place-items-center rounded-full bg-[var(--danger)] px-1 text-[0.65rem] font-semibold text-white shadow ring-2 ring-[var(--card)]", children: unreadCount > 99 ? "99+" : unreadCount }) : null
432
+ /* @__PURE__ */ jsx("span", { className: "absolute inset-0 bg-[radial-gradient(circle_at_30%_20%,color-mix(in_oklab,var(--primary)_18%,transparent),transparent_38%)] opacity-80 transition group-hover:opacity-100" }),
433
+ /* @__PURE__ */ jsx("span", { className: "relative grid size-9 place-items-center rounded-xl bg-[color-mix(in_oklab,var(--primary)_12%,transparent)] ring-1 ring-[color-mix(in_oklab,var(--primary)_18%,transparent)]", children: /* @__PURE__ */ jsx(ChatCircleTextIcon, { "aria-hidden": true, className: "h-5 w-5" }) }),
434
+ Math.max(unreadCount, unseenReplyCount) > 0 ? /* @__PURE__ */ jsx("span", { className: "absolute -right-1.5 -top-1.5 grid h-5 min-w-5 animate-[fx-chat-badge_280ms_ease-out] place-items-center rounded-full bg-[var(--danger)] px-1 text-[0.65rem] font-semibold text-white shadow ring-2 ring-[var(--card)]", children: Math.max(unreadCount, unseenReplyCount) > 99 ? "99+" : Math.max(unreadCount, unseenReplyCount) }) : null
399
435
  ]
400
436
  }
401
437
  ) }) });
@@ -487,43 +523,53 @@ function SupportChatWidget({
487
523
  const prev = messages[index - 1];
488
524
  const showAvatar = !mine && !system && (prev == null ? void 0 : prev.role) !== message.role;
489
525
  const bubbleClass = system ? "mx-auto max-w-[92%] border-[color-mix(in_oklab,var(--warning)_28%,var(--border))] bg-[color-mix(in_oklab,var(--warning)_10%,transparent)] text-center text-[var(--foreground)]" : mine ? "border-[color-mix(in_oklab,var(--ring)_35%,var(--border))] bg-[color-mix(in_oklab,var(--primary)_14%,transparent)] text-[var(--foreground)]" : "border-[var(--border)] bg-[color-mix(in_oklab,var(--card)_94%,transparent)] text-[var(--foreground)]";
490
- return /* @__PURE__ */ jsxs("div", { className: cx("flex items-end gap-2", mine ? "justify-end" : system ? "justify-center" : "justify-start"), children: [
491
- !mine && !system ? /* @__PURE__ */ jsx("div", { className: cx("shrink-0", showAvatar ? "" : "opacity-0"), children: /* @__PURE__ */ jsx(
492
- AvatarSquare,
493
- {
494
- size: 28,
495
- src: (_b2 = actor == null ? void 0 : actor.avatarUrl) != null ? _b2 : void 0,
496
- alt: (_c2 = actor == null ? void 0 : actor.name) != null ? _c2 : brandName,
497
- initials: actor == null ? void 0 : actor.initials,
498
- color: actor == null ? void 0 : actor.color,
499
- radiusClass: "rounded-lg",
500
- className: "ring-0"
501
- }
502
- ) }) : null,
503
- /* @__PURE__ */ jsxs("div", { className: cx("max-w-[82%]", mine ? "items-end" : "items-start"), children: [
504
- !mine && !system && showAvatar ? /* @__PURE__ */ jsx("div", { className: "mb-1 px-2 text-[0.6875rem] font-semibold text-[var(--muted)]", children: (_d2 = actor == null ? void 0 : actor.name) != null ? _d2 : brandName }) : null,
505
- /* @__PURE__ */ jsxs("div", { className: cx("rounded-2xl border px-3.5 py-2.5 text-sm leading-6 shadow-sm", bubbleClass, message.state === "error" ? "border-[color-mix(in_oklab,var(--danger)_35%,var(--border))]" : ""), children: [
506
- message.state === "typing" ? /* @__PURE__ */ jsx(Dots, {}) : /* @__PURE__ */ jsx("span", { className: "whitespace-pre-wrap", children: message.content }),
507
- ((_e2 = message.suggestedReplies) == null ? void 0 : _e2.length) ? /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: message.suggestedReplies.slice(0, 4).map((reply) => /* @__PURE__ */ jsx(
508
- "button",
526
+ return /* @__PURE__ */ jsxs(
527
+ "div",
528
+ {
529
+ className: cx(
530
+ "flex animate-[fx-chat-message_260ms_cubic-bezier(.2,.8,.2,1)_both] items-end gap-2",
531
+ mine ? "justify-end [--fx-chat-x:10px]" : system ? "justify-center [--fx-chat-x:0px]" : "justify-start [--fx-chat-x:-10px]"
532
+ ),
533
+ children: [
534
+ !mine && !system ? /* @__PURE__ */ jsx("div", { className: cx("shrink-0", showAvatar ? "" : "opacity-0"), children: /* @__PURE__ */ jsx(
535
+ AvatarSquare,
509
536
  {
510
- type: "button",
511
- onClick: () => {
512
- onQuickReply == null ? void 0 : onQuickReply(reply);
513
- void send(reply);
514
- },
515
- className: "rounded-full border border-[var(--border)] bg-[var(--card)] px-3 py-1.5 text-xs font-semibold text-[var(--foreground)] shadow-sm transition hover:bg-[color-mix(in_oklab,var(--surface)_72%,transparent)]",
516
- children: reply
517
- },
518
- `${message.id}:${reply}`
519
- )) }) : null,
520
- ((_f2 = message.serviceSuggestions) == null ? void 0 : _f2.length) ? /* @__PURE__ */ jsx("div", { className: "mt-3 space-y-2", children: message.serviceSuggestions.slice(0, 3).map(renderService) }) : null
521
- ] }),
522
- message.createdAt ? /* @__PURE__ */ jsx("div", { className: cx("mt-1 px-2 text-[0.6875rem] text-[var(--muted)]", mine ? "text-right" : "text-left"), children: /* @__PURE__ */ jsx(TimeAgo, { iso: message.createdAt }) }) : null
523
- ] })
524
- ] }, message.id);
537
+ size: 28,
538
+ src: (_b2 = actor == null ? void 0 : actor.avatarUrl) != null ? _b2 : void 0,
539
+ alt: (_c2 = actor == null ? void 0 : actor.name) != null ? _c2 : brandName,
540
+ initials: actor == null ? void 0 : actor.initials,
541
+ color: actor == null ? void 0 : actor.color,
542
+ radiusClass: "rounded-lg",
543
+ className: "ring-0"
544
+ }
545
+ ) }) : null,
546
+ /* @__PURE__ */ jsxs("div", { className: cx("max-w-[82%]", mine ? "items-end" : "items-start"), children: [
547
+ !mine && !system && showAvatar ? /* @__PURE__ */ jsx("div", { className: "mb-1 px-2 text-[0.6875rem] font-semibold text-[var(--muted)]", children: (_d2 = actor == null ? void 0 : actor.name) != null ? _d2 : brandName }) : null,
548
+ /* @__PURE__ */ jsxs("div", { className: cx("rounded-2xl border px-3.5 py-2.5 text-sm leading-6 shadow-sm transition-[background,border-color,box-shadow,transform] duration-200", bubbleClass, message.state === "error" ? "border-[color-mix(in_oklab,var(--danger)_35%,var(--border))]" : ""), children: [
549
+ message.state === "typing" ? /* @__PURE__ */ jsx(Dots, {}) : /* @__PURE__ */ jsx("span", { className: "whitespace-pre-wrap", children: message.content }),
550
+ ((_e2 = message.suggestedReplies) == null ? void 0 : _e2.length) ? /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: message.suggestedReplies.slice(0, 4).map((reply) => /* @__PURE__ */ jsx(
551
+ "button",
552
+ {
553
+ type: "button",
554
+ onClick: () => {
555
+ onQuickReply == null ? void 0 : onQuickReply(reply);
556
+ void send(reply);
557
+ },
558
+ className: "rounded-full border border-[var(--border)] bg-[var(--card)] px-3 py-1.5 text-xs font-semibold text-[var(--foreground)] shadow-sm transition hover:bg-[color-mix(in_oklab,var(--surface)_72%,transparent)]",
559
+ children: reply
560
+ },
561
+ `${message.id}:${reply}`
562
+ )) }) : null,
563
+ ((_f2 = message.serviceSuggestions) == null ? void 0 : _f2.length) ? /* @__PURE__ */ jsx("div", { className: "mt-3 space-y-2", children: message.serviceSuggestions.slice(0, 3).map(renderService) }) : null
564
+ ] }),
565
+ message.createdAt ? /* @__PURE__ */ jsx("div", { className: cx("mt-1 px-2 text-[0.6875rem] text-[var(--muted)]", mine ? "text-right" : "text-left"), children: /* @__PURE__ */ jsx(TimeAgo, { iso: message.createdAt }) }) : null
566
+ ] })
567
+ ]
568
+ },
569
+ message.id
570
+ );
525
571
  }),
526
- sending ? /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
572
+ sending ? /* @__PURE__ */ jsxs("div", { className: "flex animate-[fx-chat-message_260ms_cubic-bezier(.2,.8,.2,1)_both] items-end gap-2 [--fx-chat-x:-10px]", children: [
527
573
  /* @__PURE__ */ jsx(
528
574
  AvatarSquare,
529
575
  {
@@ -543,16 +589,17 @@ function SupportChatWidget({
543
589
  const panel = open ? /* @__PURE__ */ jsxs(
544
590
  "div",
545
591
  {
592
+ ref: panelRef,
546
593
  className: cx(
547
594
  panelPositionClass,
548
- "flex h-[min(680px,calc(100vh-7rem))] w-[min(400px,calc(100vw-2rem))] flex-col overflow-hidden rounded-2xl border border-[var(--border)] bg-[var(--card)] text-[var(--foreground)] shadow-2xl",
595
+ "flex h-[min(680px,calc(100vh-7rem))] w-[min(400px,calc(100vw-2rem))] animate-[fx-chat-panel_180ms_cubic-bezier(.2,.8,.2,1)_both] flex-col overflow-hidden rounded-2xl border border-[var(--border)] bg-[color-mix(in_oklab,var(--card)_96%,transparent)] text-[var(--foreground)] shadow-[0_28px_80px_rgba(6,19,22,0.18)] backdrop-blur-xl dark:shadow-[0_28px_80px_rgba(0,0,0,0.38)]",
549
596
  panelClassName
550
597
  ),
551
598
  style: position === "inline" ? void 0 : { zIndex },
552
599
  role: "dialog",
553
600
  "aria-label": labelTitle,
554
601
  children: [
555
- /* @__PURE__ */ jsx("div", { className: "border-b border-[var(--border)] bg-[color-mix(in_oklab,var(--card)_96%,transparent)] px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
602
+ /* @__PURE__ */ jsx("div", { className: "border-b border-[var(--border)] bg-[linear-gradient(135deg,color-mix(in_oklab,var(--card)_98%,transparent),color-mix(in_oklab,var(--primary)_8%,var(--surface)))] px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
556
603
  /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
557
604
  /* @__PURE__ */ jsx(
558
605
  AvatarSquare,
package/dist/TimePanel.js CHANGED
@@ -36,6 +36,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
36
36
  var import_react = require("react");
37
37
  var import_Button = __toESM(require("./Button"));
38
38
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
39
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
39
40
  function TimePopover({
40
41
  anchorRef,
41
42
  hh,
@@ -54,7 +55,7 @@ function TimePopover({
54
55
  left = Math.max(M, Math.min(left, window.innerWidth - (W + M)));
55
56
  let top = r.bottom + GAP;
56
57
  if (top + H > window.innerHeight) top = Math.max(M, r.top - GAP - H);
57
- return { position: "fixed", top, left, width: W, zIndex: 100001 };
58
+ return { position: "fixed", top, left, width: W, zIndex: PORTAL_OVERLAY_Z_INDEX };
58
59
  }, [anchorRef]);
59
60
  (0, import_react.useEffect)(() => {
60
61
  const stopInside = (e) => {
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useMemo, useRef } from "react";
4
4
  import Button from "./Button.mjs";
5
5
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
6
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
6
7
  function TimePopover({
7
8
  anchorRef,
8
9
  hh,
@@ -21,7 +22,7 @@ function TimePopover({
21
22
  left = Math.max(M, Math.min(left, window.innerWidth - (W + M)));
22
23
  let top = r.bottom + GAP;
23
24
  if (top + H > window.innerHeight) top = Math.max(M, r.top - GAP - H);
24
- return { position: "fixed", top, left, width: W, zIndex: 100001 };
25
+ return { position: "fixed", top, left, width: W, zIndex: PORTAL_OVERLAY_Z_INDEX };
25
26
  }, [anchorRef]);
26
27
  useEffect(() => {
27
28
  const stopInside = (e) => {
@@ -42,6 +42,7 @@ var import_animations = require("./animations");
42
42
  var import_Button = __toESM(require("./Button"));
43
43
  var import_Input = __toESM(require("./Input"));
44
44
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
45
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
45
46
  function TimePopover({
46
47
  anchorEl,
47
48
  hh,
@@ -142,7 +143,7 @@ function TimePopover({
142
143
  "data-dtf-pop": true,
143
144
  onPointerDownCapture: (e) => e.stopPropagation(),
144
145
  onKeyDown,
145
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
146
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
146
147
  className: "w-64 rounded-2xl border border-slate-200 bg-white p-3 shadow-xl dark:border-white/10 dark:bg-[var(--fx-surface)]",
147
148
  children: [
148
149
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mb-2 text-sm font-medium text-slate-700 dark:text-slate-200", children: "Selecciona hora" }),
@@ -361,7 +362,7 @@ function WeekPopover({ anchorEl, cursor, value, onCursorChange, onPick, onClose
361
362
  import_framer_motion.motion.div,
362
363
  {
363
364
  ref: popRef,
364
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
365
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
365
366
  variants: import_animations.popOver,
366
367
  initial: "initial",
367
368
  animate: "animate",
@@ -480,7 +481,7 @@ function MonthPopover({ anchorEl, cursor, value, onCursorChange, onPick, onClose
480
481
  import_framer_motion.motion.div,
481
482
  {
482
483
  ref: popRef,
483
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
484
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
484
485
  variants: import_animations.popOver,
485
486
  initial: "initial",
486
487
  animate: "animate",
@@ -7,6 +7,7 @@ import { popOver, menuTransition } from "./animations.mjs";
7
7
  import Button from "./Button.mjs";
8
8
  import Input from "./Input.mjs";
9
9
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
10
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
10
11
  function TimePopover({
11
12
  anchorEl,
12
13
  hh,
@@ -107,7 +108,7 @@ function TimePopover({
107
108
  "data-dtf-pop": true,
108
109
  onPointerDownCapture: (e) => e.stopPropagation(),
109
110
  onKeyDown,
110
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
111
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
111
112
  className: "w-64 rounded-2xl border border-slate-200 bg-white p-3 shadow-xl dark:border-white/10 dark:bg-[var(--fx-surface)]",
112
113
  children: [
113
114
  /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm font-medium text-slate-700 dark:text-slate-200", children: "Selecciona hora" }),
@@ -326,7 +327,7 @@ function WeekPopover({ anchorEl, cursor, value, onCursorChange, onPick, onClose
326
327
  motion.div,
327
328
  {
328
329
  ref: popRef,
329
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
330
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
330
331
  variants: popOver,
331
332
  initial: "initial",
332
333
  animate: "animate",
@@ -445,7 +446,7 @@ function MonthPopover({ anchorEl, cursor, value, onCursorChange, onPick, onClose
445
446
  motion.div,
446
447
  {
447
448
  ref: popRef,
448
- style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 1e5, willChange: "transform, opacity" },
449
+ style: { position: "fixed", top: pos.top, left: pos.left, zIndex: PORTAL_OVERLAY_Z_INDEX, willChange: "transform, opacity" },
449
450
  variants: popOver,
450
451
  initial: "initial",
451
452
  animate: "animate",
@@ -41,6 +41,7 @@ var import_TimePopover = __toESM(require("./TimePopover"));
41
41
  var import_ActionIconButton = __toESM(require("./ActionIconButton"));
42
42
  var import_iconos = require("./iconos");
43
43
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
44
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
44
45
  function parseHHmm(v) {
45
46
  if (!v) return null;
46
47
  const [hh, mm] = String(v).split(":").map((x) => parseInt(x, 10));
@@ -142,10 +143,10 @@ function TimeRangeField({ value, onValueChange, portal = true, portalId, clearab
142
143
  const placeAbove = spaceAbove >= spaceBelow;
143
144
  if (placeAbove) {
144
145
  const top2 = Math.max(MARGIN, anchorRect.top - GAP);
145
- return { position: "fixed", width: W, top: top2, left, zIndex: 1e5, transform: "translateY(-100%)" };
146
+ return { position: "fixed", width: W, top: top2, left, zIndex: PORTAL_OVERLAY_Z_INDEX, transform: "translateY(-100%)" };
146
147
  }
147
148
  const top = Math.max(MARGIN, anchorRect.bottom + GAP);
148
- return { position: "fixed", width: W, top, left, zIndex: 1e5 };
149
+ return { position: "fixed", width: W, top, left, zIndex: PORTAL_OVERLAY_Z_INDEX };
149
150
  })();
150
151
  const commit = (f, t) => {
151
152
  let f2 = f, t2 = t;
@@ -8,6 +8,7 @@ import TimePopover from "./TimePopover.mjs";
8
8
  import ActionIconButton from "./ActionIconButton.mjs";
9
9
  import { ClockIcon } from "./iconos/index.mjs";
10
10
  const pad2 = (n) => n < 10 ? `0${n}` : String(n);
11
+ const PORTAL_OVERLAY_Z_INDEX = 2147483647;
11
12
  function parseHHmm(v) {
12
13
  if (!v) return null;
13
14
  const [hh, mm] = String(v).split(":").map((x) => parseInt(x, 10));
@@ -109,10 +110,10 @@ function TimeRangeField({ value, onValueChange, portal = true, portalId, clearab
109
110
  const placeAbove = spaceAbove >= spaceBelow;
110
111
  if (placeAbove) {
111
112
  const top2 = Math.max(MARGIN, anchorRect.top - GAP);
112
- return { position: "fixed", width: W, top: top2, left, zIndex: 1e5, transform: "translateY(-100%)" };
113
+ return { position: "fixed", width: W, top: top2, left, zIndex: PORTAL_OVERLAY_Z_INDEX, transform: "translateY(-100%)" };
113
114
  }
114
115
  const top = Math.max(MARGIN, anchorRect.bottom + GAP);
115
- return { position: "fixed", width: W, top, left, zIndex: 1e5 };
116
+ return { position: "fixed", width: W, top, left, zIndex: PORTAL_OVERLAY_Z_INDEX };
116
117
  })();
117
118
  const commit = (f, t) => {
118
119
  let f2 = f, t2 = t;
@@ -47,8 +47,8 @@ function UploadCard({
47
47
  multiple = true,
48
48
  disabled,
49
49
  buttonLabel = "Seleccionar",
50
- dropLabel = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm font-medium text-slate-700 dark:text-slate-200", children: "Arrastra y suelta archivos aqu\xED o haz clic" }),
51
- note = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-slate-500 dark:text-slate-400", children: "M\xE1ximo recomendado 16MB por archivo" }),
50
+ dropLabel = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm font-semibold text-[var(--foreground)]", children: "Arrastra y suelta archivos aqu\xED o haz clic" }),
51
+ note = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-xs text-[var(--muted)]", children: "M\xE1ximo recomendado 16MB por archivo" }),
52
52
  uploads,
53
53
  className,
54
54
  onFilesSelected
@@ -95,9 +95,9 @@ function UploadCard({
95
95
  var _a;
96
96
  return (_a = inputRef.current) == null ? void 0 : _a.click();
97
97
  },
98
- className: "flex cursor-pointer flex-col items-center justify-center gap-2 rounded-2xl border border-dashed border-slate-300 bg-gradient-to-b from-white/90 to-white/60 p-8 text-center transition hover:border-slate-400 hover:bg-white/80 ring-1 ring-black/5 dark:border-white/10 dark:bg-[var(--fx-surface)] dark:from-white/10 dark:to-white/5 dark:hover:bg-white/10",
98
+ className: "group flex min-h-[190px] cursor-pointer flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-[color-mix(in_oklab,var(--border)_82%,transparent)] bg-[color-mix(in_oklab,var(--surface)_86%,var(--card))] p-8 text-center transition hover:border-[color-mix(in_oklab,var(--primary)_54%,var(--border))] hover:bg-[color-mix(in_oklab,var(--primary)_5%,var(--surface))] focus:outline-none focus-visible:ring-1 focus-visible:ring-[var(--primary)]",
99
99
  children: [
100
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.ArrowUpFromBracketIcon, { "aria-hidden": true, className: "h-8 w-8 text-slate-400 dark:text-slate-400" }),
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex h-12 w-12 items-center justify-center rounded-lg border border-[var(--border)] bg-[var(--card)] text-[color-mix(in_oklab,var(--muted)_82%,transparent)] transition group-hover:text-[var(--primary)]", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.ArrowUpFromBracketIcon, { "aria-hidden": true, className: "h-6 w-6" }) }),
101
101
  dropLabel,
102
102
  note
103
103
  ]
@@ -114,7 +114,7 @@ function UploadCard({
114
114
  animate: { opacity: 1, y: 0 },
115
115
  exit: { opacity: 0, y: -6 },
116
116
  transition: import_animations.springSm,
117
- className: "flex items-center gap-3 rounded-xl border border-slate-200 bg-white/70 p-2 dark:border-white/10 dark:bg-[var(--fx-surface)]",
117
+ className: "flex items-center gap-3 rounded-lg border border-[var(--border)] bg-[var(--card)] p-2",
118
118
  children: [
119
119
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
120
120
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
@@ -124,10 +124,10 @@ function UploadCard({
124
124
  "%"
125
125
  ] })
126
126
  ] }),
127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 h-2 w-full overflow-hidden rounded-full bg-slate-100 dark:bg-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-1 h-2 w-full overflow-hidden rounded-full bg-[color-mix(in_oklab,var(--surface)_84%,transparent)]", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
128
128
  import_framer_motion.motion.div,
129
129
  {
130
- className: "h-full w-full origin-left bg-gradient-to-r from-emerald-500/70 to-emerald-500/20 will-change-transform",
130
+ className: "h-full w-full origin-left bg-[var(--primary)] will-change-transform",
131
131
  initial: { scaleX: 0 },
132
132
  animate: { scaleX: pct / 100 },
133
133
  transition: import_animations.springSm
@@ -14,8 +14,8 @@ function UploadCard({
14
14
  multiple = true,
15
15
  disabled,
16
16
  buttonLabel = "Seleccionar",
17
- dropLabel = /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-slate-700 dark:text-slate-200", children: "Arrastra y suelta archivos aqu\xED o haz clic" }),
18
- note = /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 dark:text-slate-400", children: "M\xE1ximo recomendado 16MB por archivo" }),
17
+ dropLabel = /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-[var(--foreground)]", children: "Arrastra y suelta archivos aqu\xED o haz clic" }),
18
+ note = /* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--muted)]", children: "M\xE1ximo recomendado 16MB por archivo" }),
19
19
  uploads,
20
20
  className,
21
21
  onFilesSelected
@@ -62,9 +62,9 @@ function UploadCard({
62
62
  var _a;
63
63
  return (_a = inputRef.current) == null ? void 0 : _a.click();
64
64
  },
65
- className: "flex cursor-pointer flex-col items-center justify-center gap-2 rounded-2xl border border-dashed border-slate-300 bg-gradient-to-b from-white/90 to-white/60 p-8 text-center transition hover:border-slate-400 hover:bg-white/80 ring-1 ring-black/5 dark:border-white/10 dark:bg-[var(--fx-surface)] dark:from-white/10 dark:to-white/5 dark:hover:bg-white/10",
65
+ className: "group flex min-h-[190px] cursor-pointer flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-[color-mix(in_oklab,var(--border)_82%,transparent)] bg-[color-mix(in_oklab,var(--surface)_86%,var(--card))] p-8 text-center transition hover:border-[color-mix(in_oklab,var(--primary)_54%,var(--border))] hover:bg-[color-mix(in_oklab,var(--primary)_5%,var(--surface))] focus:outline-none focus-visible:ring-1 focus-visible:ring-[var(--primary)]",
66
66
  children: [
67
- /* @__PURE__ */ jsx(ArrowUpFromBracketIcon, { "aria-hidden": true, className: "h-8 w-8 text-slate-400 dark:text-slate-400" }),
67
+ /* @__PURE__ */ jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-lg border border-[var(--border)] bg-[var(--card)] text-[color-mix(in_oklab,var(--muted)_82%,transparent)] transition group-hover:text-[var(--primary)]", children: /* @__PURE__ */ jsx(ArrowUpFromBracketIcon, { "aria-hidden": true, className: "h-6 w-6" }) }),
68
68
  dropLabel,
69
69
  note
70
70
  ]
@@ -81,7 +81,7 @@ function UploadCard({
81
81
  animate: { opacity: 1, y: 0 },
82
82
  exit: { opacity: 0, y: -6 },
83
83
  transition: springSm,
84
- className: "flex items-center gap-3 rounded-xl border border-slate-200 bg-white/70 p-2 dark:border-white/10 dark:bg-[var(--fx-surface)]",
84
+ className: "flex items-center gap-3 rounded-lg border border-[var(--border)] bg-[var(--card)] p-2",
85
85
  children: [
86
86
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
87
87
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
@@ -91,10 +91,10 @@ function UploadCard({
91
91
  "%"
92
92
  ] })
93
93
  ] }),
94
- /* @__PURE__ */ jsx("div", { className: "mt-1 h-2 w-full overflow-hidden rounded-full bg-slate-100 dark:bg-white/10", children: /* @__PURE__ */ jsx(
94
+ /* @__PURE__ */ jsx("div", { className: "mt-1 h-2 w-full overflow-hidden rounded-full bg-[color-mix(in_oklab,var(--surface)_84%,transparent)]", children: /* @__PURE__ */ jsx(
95
95
  motion.div,
96
96
  {
97
- className: "h-full w-full origin-left bg-gradient-to-r from-emerald-500/70 to-emerald-500/20 will-change-transform",
97
+ className: "h-full w-full origin-left bg-[var(--primary)] will-change-transform",
98
98
  initial: { scaleX: 0 },
99
99
  animate: { scaleX: pct / 100 },
100
100
  transition: springSm
package/dist/index.d.mts CHANGED
@@ -92,7 +92,7 @@ export { default as ColorPicker, ColorPickerProps } from './ColorPicker.mjs';
92
92
  export { Accent, Theme, ThemeProvider, useTheme } from './theme/ThemeProvider.mjs';
93
93
  export { ThemeScript } from './theme/ThemeScript.mjs';
94
94
  export { default as ThemeToggle } from './theme/ThemeToggle.mjs';
95
- export { default as MarkdownEditor, MarkdownEditorProps } from './MarkdownEditor.mjs';
95
+ export { default as MarkdownEditor, MarkdownEditorProps, MarkdownPreview, renderMarkdown } from './MarkdownEditor.mjs';
96
96
  export { default as QuoteEditor, QuoteEditorClientOption, QuoteEditorLabels, QuoteEditorProps } from './QuoteEditor.mjs';
97
97
  export { Currency, DiscountType, QuoteDraft, QuoteLine, QuoteStatus, QuoteTotals, TaxMethod, calcDiscountAmount, calcLineDiscount, calcLineSubtotal, calcQuoteTotals, calcSubtotal, clampIsrRetRate, clampIvaRetFactor, clampMoney, clampTaxRate, fmtMoney } from './quote.mjs';
98
98
  export { default as DocumentEditor, DocumentEditorLabels, DocumentEditorProps, DocumentPreview } from './DocumentEditor.mjs';
package/dist/index.d.ts CHANGED
@@ -92,7 +92,7 @@ export { default as ColorPicker, ColorPickerProps } from './ColorPicker.js';
92
92
  export { Accent, Theme, ThemeProvider, useTheme } from './theme/ThemeProvider.js';
93
93
  export { ThemeScript } from './theme/ThemeScript.js';
94
94
  export { default as ThemeToggle } from './theme/ThemeToggle.js';
95
- export { default as MarkdownEditor, MarkdownEditorProps } from './MarkdownEditor.js';
95
+ export { default as MarkdownEditor, MarkdownEditorProps, MarkdownPreview, renderMarkdown } from './MarkdownEditor.js';
96
96
  export { default as QuoteEditor, QuoteEditorClientOption, QuoteEditorLabels, QuoteEditorProps } from './QuoteEditor.js';
97
97
  export { Currency, DiscountType, QuoteDraft, QuoteLine, QuoteStatus, QuoteTotals, TaxMethod, calcDiscountAmount, calcLineDiscount, calcLineSubtotal, calcQuoteTotals, calcSubtotal, clampIsrRetRate, clampIvaRetFactor, clampMoney, clampTaxRate, fmtMoney } from './quote.js';
98
98
  export { default as DocumentEditor, DocumentEditorLabels, DocumentEditorProps, DocumentPreview } from './DocumentEditor.js';
package/dist/index.js CHANGED
@@ -98,6 +98,7 @@ __export(index_exports, {
98
98
  LoginTools: () => import_LoginTools.default,
99
99
  Map: () => import_Map.default,
100
100
  MarkdownEditor: () => import_MarkdownEditor.default,
101
+ MarkdownPreview: () => import_MarkdownEditor.MarkdownPreview,
101
102
  MediaCard: () => import_MediaCard.default,
102
103
  MediaLibraryLayout: () => import_MediaLibraryLayout.default,
103
104
  MediaSelector: () => import_MediaSelector.default,
@@ -163,6 +164,7 @@ __export(index_exports, {
163
164
  formatNumericValue: () => import_Numeric.formatNumericValue,
164
165
  formatPercentValue: () => import_Numeric.formatPercentValue,
165
166
  generatePassword: () => import_PasswordField2.generatePassword,
167
+ renderMarkdown: () => import_MarkdownEditor.renderMarkdown,
166
168
  useCarousel: () => import_Carousel.useCarousel,
167
169
  useI18n: () => import_i18n.useI18n,
168
170
  useOmniSearchRegistry: () => import_OmniSearch2.useOmniSearchRegistry,
@@ -360,6 +362,7 @@ var import_LoginGallery = __toESM(require("./LoginGallery"));
360
362
  LoginTools,
361
363
  Map,
362
364
  MarkdownEditor,
365
+ MarkdownPreview,
363
366
  MediaCard,
364
367
  MediaLibraryLayout,
365
368
  MediaSelector,
@@ -425,6 +428,7 @@ var import_LoginGallery = __toESM(require("./LoginGallery"));
425
428
  formatNumericValue,
426
429
  formatPercentValue,
427
430
  generatePassword,
431
+ renderMarkdown,
428
432
  useCarousel,
429
433
  useI18n,
430
434
  useOmniSearchRegistry,
package/dist/index.mjs CHANGED
@@ -112,7 +112,7 @@ import { default as default88 } from "./ColorPicker.mjs";
112
112
  import { default as default89, useTheme } from "./theme/ThemeProvider.mjs";
113
113
  import { default as default90 } from "./theme/ThemeScript.mjs";
114
114
  import { default as default91 } from "./theme/ThemeToggle.mjs";
115
- import { default as default92 } from "./MarkdownEditor.mjs";
115
+ import { default as default92, MarkdownPreview, renderMarkdown } from "./MarkdownEditor.mjs";
116
116
  import { default as default93 } from "./QuoteEditor.mjs";
117
117
  export * from "./quote.mjs";
118
118
  import { default as default94, DocumentPreview } from "./DocumentEditor.mjs";
@@ -196,6 +196,7 @@ export {
196
196
  default100 as LoginTools,
197
197
  default4 as Map,
198
198
  default92 as MarkdownEditor,
199
+ MarkdownPreview,
199
200
  default32 as MediaCard,
200
201
  default33 as MediaLibraryLayout,
201
202
  default35 as MediaSelector,
@@ -261,6 +262,7 @@ export {
261
262
  formatNumericValue,
262
263
  formatPercentValue,
263
264
  generatePassword,
265
+ renderMarkdown,
264
266
  useCarousel,
265
267
  useI18n,
266
268
  useOmniSearchRegistry,
@@ -54,7 +54,7 @@ function FontSizeController({
54
54
  labels
55
55
  }) {
56
56
  var _a, _b, _c, _d, _e;
57
- const POPOVER_Z_INDEX = 10050;
57
+ const POPOVER_Z_INDEX = 2147483647;
58
58
  const [mounted, setMounted] = import_react.default.useState(false);
59
59
  import_react.default.useEffect(() => setMounted(true), []);
60
60
  const { fontScale, setFontScale, increaseFont, decreaseFont, resetFont } = (0, import_ThemeProvider.useTheme)();
@@ -21,7 +21,7 @@ function FontSizeController({
21
21
  labels
22
22
  }) {
23
23
  var _a, _b, _c, _d, _e;
24
- const POPOVER_Z_INDEX = 10050;
24
+ const POPOVER_Z_INDEX = 2147483647;
25
25
  const [mounted, setMounted] = React.useState(false);
26
26
  React.useEffect(() => setMounted(true), []);
27
27
  const { fontScale, setFontScale, increaseFont, decreaseFont, resetFont } = useTheme();
@@ -82,7 +82,7 @@ function ThemeController({
82
82
  labels
83
83
  }) {
84
84
  var _a, _b, _c, _d, _e, _f, _g;
85
- const POPOVER_Z_INDEX = 10050;
85
+ const POPOVER_Z_INDEX = 2147483647;
86
86
  const [mounted, setMounted] = import_react.default.useState(false);
87
87
  import_react.default.useEffect(() => setMounted(true), []);
88
88
  const { theme, setTheme, accent, setAccent } = (0, import_ThemeProvider.useTheme)();
@@ -269,6 +269,7 @@ function ThemeController({
269
269
  style: popStyle,
270
270
  role: "dialog",
271
271
  "aria-label": (_g = labels == null ? void 0 : labels.accentGroup) != null ? _g : "Color",
272
+ "data-fx-keep-open": true,
272
273
  className: [
273
274
  "rounded-2xl border border-[var(--border)] bg-[var(--card)] shadow-2xl ring-1 ring-black/5",
274
275
  "dark:ring-white/10",
@@ -49,7 +49,7 @@ function ThemeController({
49
49
  labels
50
50
  }) {
51
51
  var _a, _b, _c, _d, _e, _f, _g;
52
- const POPOVER_Z_INDEX = 10050;
52
+ const POPOVER_Z_INDEX = 2147483647;
53
53
  const [mounted, setMounted] = React.useState(false);
54
54
  React.useEffect(() => setMounted(true), []);
55
55
  const { theme, setTheme, accent, setAccent } = useTheme();
@@ -236,6 +236,7 @@ function ThemeController({
236
236
  style: popStyle,
237
237
  role: "dialog",
238
238
  "aria-label": (_g = labels == null ? void 0 : labels.accentGroup) != null ? _g : "Color",
239
+ "data-fx-keep-open": true,
239
240
  className: [
240
241
  "rounded-2xl border border-[var(--border)] bg-[var(--card)] shadow-2xl ring-1 ring-black/5",
241
242
  "dark:ring-white/10",