@rufous/ui 0.2.64 → 0.2.66

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/main.cjs CHANGED
@@ -1553,6 +1553,7 @@ var BaseDialog = ({
1553
1553
  dialogBodyStyle = {},
1554
1554
  size,
1555
1555
  sx,
1556
+ form,
1556
1557
  TransitionComponent,
1557
1558
  TransitionProps = {}
1558
1559
  }) => {
@@ -1566,15 +1567,27 @@ var BaseDialog = ({
1566
1567
  {
1567
1568
  className: "btn-cancel",
1568
1569
  onClick: onCancel || onClose,
1569
- disabled: isLoading || isButtonLoading
1570
+ disabled: isLoading || isButtonLoading,
1571
+ type: "button"
1570
1572
  },
1571
1573
  cancelText
1572
- ), onConfirm && /* @__PURE__ */ React65.createElement(
1574
+ ), form ? /* @__PURE__ */ React65.createElement(
1573
1575
  "button",
1574
1576
  {
1575
1577
  className: "btn-confirm",
1576
1578
  disabled: disableConfirmBtn || isButtonLoading,
1577
1579
  style: { position: "relative" },
1580
+ type: "submit"
1581
+ },
1582
+ /* @__PURE__ */ React65.createElement("span", { style: { visibility: isButtonLoading ? "hidden" : "visible" } }, submitText),
1583
+ isButtonLoading && /* @__PURE__ */ React65.createElement("span", { className: "spinner", style: { position: "absolute" } })
1584
+ ) : onConfirm && /* @__PURE__ */ React65.createElement(
1585
+ "button",
1586
+ {
1587
+ className: "btn-confirm",
1588
+ disabled: disableConfirmBtn || isButtonLoading,
1589
+ style: { position: "relative" },
1590
+ type: "button",
1578
1591
  onClick: async () => {
1579
1592
  setIsSubmitting(true);
1580
1593
  await onConfirm?.();
@@ -1584,37 +1597,37 @@ var BaseDialog = ({
1584
1597
  /* @__PURE__ */ React65.createElement("span", { style: { visibility: isButtonLoading ? "hidden" : "visible" } }, confirmText),
1585
1598
  isButtonLoading && /* @__PURE__ */ React65.createElement("span", { className: "spinner", style: { position: "absolute" } })
1586
1599
  ));
1587
- const dialogContent = /* @__PURE__ */ React65.createElement(
1600
+ const containerClass = ["dialog-container", size ? `size-${size}` : "", sxClass, className].filter(Boolean).join(" ");
1601
+ const containerStyle = { minWidth, minHeight };
1602
+ const dialogInner = /* @__PURE__ */ React65.createElement(React65.Fragment, null, /* @__PURE__ */ React65.createElement("div", { className: "dialog-title" }, /* @__PURE__ */ React65.createElement("h2", null, formatTitle ? title?.charAt(0).toUpperCase() + title?.slice(1) : title), showCloseButton && /* @__PURE__ */ React65.createElement("button", { className: "btn-close", type: "button", onClick: onClose }, /* @__PURE__ */ React65.createElement(
1603
+ import_lucide_react.X,
1604
+ {
1605
+ size: 18,
1606
+ color: themeConfig?.icon || "#666666"
1607
+ }
1608
+ ))), /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }), /* @__PURE__ */ React65.createElement(
1588
1609
  "div",
1589
1610
  {
1590
- className: ["dialog-container", size ? `size-${size}` : "", sxClass, className].filter(Boolean).join(" "),
1611
+ className: "dialog-body",
1591
1612
  style: {
1592
- minWidth,
1593
- minHeight
1613
+ ...fullScreen ? { height: "100%" } : { maxHeight: "758px", minHeight },
1614
+ ...dialogBodyStyle
1594
1615
  }
1595
1616
  },
1596
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-title" }, /* @__PURE__ */ React65.createElement("h2", null, formatTitle ? title?.charAt(0).toUpperCase() + title?.slice(1) : title), showCloseButton && /* @__PURE__ */ React65.createElement("button", { className: "btn-close", onClick: onClose }, /* @__PURE__ */ React65.createElement(
1597
- import_lucide_react.X,
1598
- {
1599
- size: 18,
1600
- color: themeConfig?.icon || "#666666"
1617
+ children
1618
+ ), /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }), customButtons || renderButtons());
1619
+ const dialogContent = form ? /* @__PURE__ */ React65.createElement(
1620
+ "form",
1621
+ {
1622
+ className: containerClass,
1623
+ style: containerStyle,
1624
+ onSubmit: (e) => {
1625
+ e.preventDefault();
1626
+ form.handleSubmit?.(e);
1601
1627
  }
1602
- ))),
1603
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }),
1604
- /* @__PURE__ */ React65.createElement(
1605
- "div",
1606
- {
1607
- className: "dialog-body",
1608
- style: {
1609
- ...fullScreen ? { height: "100%" } : { maxHeight: "758px", minHeight },
1610
- ...dialogBodyStyle
1611
- }
1612
- },
1613
- children
1614
- ),
1615
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }),
1616
- customButtons || renderButtons()
1617
- );
1628
+ },
1629
+ dialogInner
1630
+ ) : /* @__PURE__ */ React65.createElement("div", { className: containerClass, style: containerStyle }, dialogInner);
1618
1631
  if (TransitionComponent) {
1619
1632
  return /* @__PURE__ */ React65.createElement(
1620
1633
  TransitionComponent,
@@ -2135,6 +2148,7 @@ var AddressLookup_default = AddressLookup;
2135
2148
 
2136
2149
  // lib/TextFields/DateField.tsx
2137
2150
  var import_react19 = __toESM(require("react"), 1);
2151
+ var import_react_dom = require("react-dom");
2138
2152
  var WEEKDAYS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
2139
2153
  var MONTHS = [
2140
2154
  "January",
@@ -2576,7 +2590,10 @@ var DateField = ({
2576
2590
  (0, import_react19.useEffect)(() => {
2577
2591
  if (!open) return;
2578
2592
  const handler = (e) => {
2579
- if (containerRef.current && !containerRef.current.contains(e.target)) setOpen(false);
2593
+ const target = e.target;
2594
+ if (containerRef.current?.contains(target)) return;
2595
+ if (pickerRef.current?.contains(target)) return;
2596
+ setOpen(false);
2580
2597
  };
2581
2598
  document.addEventListener("mousedown", handler);
2582
2599
  return () => document.removeEventListener("mousedown", handler);
@@ -2777,80 +2794,97 @@ var DateField = ({
2777
2794
  )),
2778
2795
  label && /* @__PURE__ */ import_react19.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ import_react19.default.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
2779
2796
  variant === "outlined" && /* @__PURE__ */ import_react19.default.createElement("fieldset", { className: "rf-text-field__notch" }, label && /* @__PURE__ */ import_react19.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react19.default.createElement("span", null, label, required ? " *" : "")))
2780
- ), open && !disabled && /* @__PURE__ */ import_react19.default.createElement(
2781
- "div",
2782
- {
2783
- ref: pickerRef,
2784
- className: [
2785
- "rf-date-picker",
2786
- isSideVariant ? "rf-date-picker--side" : "",
2787
- dropUp ? "rf-date-picker--drop-up" : ""
2788
- ].filter(Boolean).join(" "),
2789
- onMouseDown: (e) => e.preventDefault()
2790
- },
2791
- /* @__PURE__ */ import_react19.default.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ import_react19.default.createElement(
2792
- CalendarBody,
2793
- {
2794
- viewMonth,
2795
- viewYear,
2796
- selectedDate,
2797
- todayDate,
2798
- dayCells,
2799
- onDayClick: handleDayClick,
2800
- onPrev: prevMonth,
2801
- onNext: nextMonth,
2802
- onMonthSelect: setViewMonth,
2803
- onYearSelect: setViewYear
2804
- }
2805
- ), type === "datetime" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement(
2806
- SpinnerPanel,
2807
- {
2808
- hour,
2809
- minute,
2810
- ampm,
2811
- onHourChange: handleHourChange,
2812
- onMinuteChange: handleMinuteChange,
2813
- onHourInput: handleHourInput,
2814
- onMinuteInput: handleMinuteInput,
2815
- onAmpmToggle: handleAmpmToggle
2816
- }
2817
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2818
- type === "datetime-side" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ import_react19.default.createElement(
2819
- SpinnerPanel,
2820
- {
2821
- hour,
2822
- minute,
2823
- ampm,
2824
- onHourChange: handleHourChange,
2825
- onMinuteChange: handleMinuteChange,
2826
- onHourInput: handleHourInput,
2827
- onMinuteInput: handleMinuteInput,
2828
- onAmpmToggle: handleAmpmToggle
2829
- }
2830
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2831
- type === "datetime-scroll" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ import_react19.default.createElement(
2832
- ScrollColumn,
2833
- {
2834
- items: HOURS,
2835
- selected: hour - 1,
2836
- onSelect: handleScrollHour
2837
- }
2838
- ), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ import_react19.default.createElement(
2839
- ScrollColumn,
2840
- {
2841
- items: MINUTES,
2842
- selected: minute,
2843
- onSelect: handleScrollMinute
2844
- }
2845
- ), /* @__PURE__ */ import_react19.default.createElement(
2846
- ScrollColumn,
2797
+ ), open && !disabled && (0, import_react_dom.createPortal)(
2798
+ /* @__PURE__ */ import_react19.default.createElement(
2799
+ "div",
2847
2800
  {
2848
- items: AMPMS,
2849
- selected: ampm === "AM" ? 0 : 1,
2850
- onSelect: handleScrollAmpm,
2851
- infinite: false
2852
- }
2853
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2801
+ ref: pickerRef,
2802
+ className: [
2803
+ "rf-date-picker",
2804
+ "rf-date-picker--portaled",
2805
+ isSideVariant ? "rf-date-picker--side" : "",
2806
+ dropUp ? "rf-date-picker--drop-up" : ""
2807
+ ].filter(Boolean).join(" "),
2808
+ style: (() => {
2809
+ const rect = containerRef.current?.getBoundingClientRect();
2810
+ if (!rect) return {};
2811
+ const top = rect.bottom + 6;
2812
+ const spaceBelow = window.innerHeight - rect.bottom - 6;
2813
+ const useDropUp = spaceBelow < 350 && rect.top > spaceBelow;
2814
+ return {
2815
+ position: "fixed",
2816
+ left: rect.left,
2817
+ ...useDropUp ? { bottom: window.innerHeight - rect.top + 6 } : { top },
2818
+ zIndex: 99999
2819
+ };
2820
+ })(),
2821
+ onMouseDown: (e) => e.preventDefault()
2822
+ },
2823
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ import_react19.default.createElement(
2824
+ CalendarBody,
2825
+ {
2826
+ viewMonth,
2827
+ viewYear,
2828
+ selectedDate,
2829
+ todayDate,
2830
+ dayCells,
2831
+ onDayClick: handleDayClick,
2832
+ onPrev: prevMonth,
2833
+ onNext: nextMonth,
2834
+ onMonthSelect: setViewMonth,
2835
+ onYearSelect: setViewYear
2836
+ }
2837
+ ), type === "datetime" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement(
2838
+ SpinnerPanel,
2839
+ {
2840
+ hour,
2841
+ minute,
2842
+ ampm,
2843
+ onHourChange: handleHourChange,
2844
+ onMinuteChange: handleMinuteChange,
2845
+ onHourInput: handleHourInput,
2846
+ onMinuteInput: handleMinuteInput,
2847
+ onAmpmToggle: handleAmpmToggle
2848
+ }
2849
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2850
+ type === "datetime-side" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ import_react19.default.createElement(
2851
+ SpinnerPanel,
2852
+ {
2853
+ hour,
2854
+ minute,
2855
+ ampm,
2856
+ onHourChange: handleHourChange,
2857
+ onMinuteChange: handleMinuteChange,
2858
+ onHourInput: handleHourInput,
2859
+ onMinuteInput: handleMinuteInput,
2860
+ onAmpmToggle: handleAmpmToggle
2861
+ }
2862
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2863
+ type === "datetime-scroll" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ import_react19.default.createElement(
2864
+ ScrollColumn,
2865
+ {
2866
+ items: HOURS,
2867
+ selected: hour - 1,
2868
+ onSelect: handleScrollHour
2869
+ }
2870
+ ), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ import_react19.default.createElement(
2871
+ ScrollColumn,
2872
+ {
2873
+ items: MINUTES,
2874
+ selected: minute,
2875
+ onSelect: handleScrollMinute
2876
+ }
2877
+ ), /* @__PURE__ */ import_react19.default.createElement(
2878
+ ScrollColumn,
2879
+ {
2880
+ items: AMPMS,
2881
+ selected: ampm === "AM" ? 0 : 1,
2882
+ onSelect: handleScrollAmpm,
2883
+ infinite: false
2884
+ }
2885
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2886
+ ),
2887
+ document.body
2854
2888
  )), helperText && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
2855
2889
  };
2856
2890
  DateField.displayName = "DateField";
@@ -5887,7 +5921,7 @@ Skeleton.displayName = "Skeleton";
5887
5921
 
5888
5922
  // lib/Tooltip/Tooltip.tsx
5889
5923
  var import_react35 = __toESM(require("react"), 1);
5890
- var import_react_dom = __toESM(require("react-dom"), 1);
5924
+ var import_react_dom2 = __toESM(require("react-dom"), 1);
5891
5925
  var GAP = 8;
5892
5926
  function computePosition(anchor, tooltip, placement) {
5893
5927
  const { top: aTop, left: aLeft, width: aW, height: aH } = anchor;
@@ -6106,7 +6140,7 @@ var Tooltip = ({
6106
6140
  ...childProps
6107
6141
  },
6108
6142
  import_react35.default.cloneElement(children)
6109
- ), import_react_dom.default.createPortal(tooltipElement, document.body));
6143
+ ), import_react_dom2.default.createPortal(tooltipElement, document.body));
6110
6144
  };
6111
6145
  Tooltip.displayName = "Tooltip";
6112
6146
 
@@ -6993,7 +7027,7 @@ Stepper.displayName = "Stepper";
6993
7027
 
6994
7028
  // lib/Menu/Menu.tsx
6995
7029
  var import_react40 = __toESM(require("react"), 1);
6996
- var import_react_dom2 = __toESM(require("react-dom"), 1);
7030
+ var import_react_dom3 = __toESM(require("react-dom"), 1);
6997
7031
  var MenuDivider = () => /* @__PURE__ */ import_react40.default.createElement("hr", { className: "rf-menu-divider", "aria-hidden": "true" });
6998
7032
  MenuDivider.displayName = "MenuDivider";
6999
7033
  var MenuItem = ({
@@ -7146,13 +7180,13 @@ var Menu = ({
7146
7180
  },
7147
7181
  children
7148
7182
  ));
7149
- return import_react_dom2.default.createPortal(portal, document.body);
7183
+ return import_react_dom3.default.createPortal(portal, document.body);
7150
7184
  };
7151
7185
  Menu.displayName = "Menu";
7152
7186
 
7153
7187
  // lib/Drawer/Drawer.tsx
7154
7188
  var import_react41 = __toESM(require("react"), 1);
7155
- var import_react_dom3 = __toESM(require("react-dom"), 1);
7189
+ var import_react_dom4 = __toESM(require("react-dom"), 1);
7156
7190
  var Drawer = ({
7157
7191
  open,
7158
7192
  onClose,
@@ -7252,7 +7286,7 @@ var Drawer = ({
7252
7286
  },
7253
7287
  children
7254
7288
  ));
7255
- return import_react_dom3.default.createPortal(
7289
+ return import_react_dom4.default.createPortal(
7256
7290
  /* @__PURE__ */ import_react41.default.createElement("div", { className: rootClasses, style }, drawerContent),
7257
7291
  document.body
7258
7292
  );
@@ -7261,7 +7295,7 @@ Drawer.displayName = "Drawer";
7261
7295
 
7262
7296
  // lib/Snackbar/Snackbar.tsx
7263
7297
  var import_react42 = __toESM(require("react"), 1);
7264
- var import_react_dom4 = __toESM(require("react-dom"), 1);
7298
+ var import_react_dom5 = __toESM(require("react-dom"), 1);
7265
7299
  var SEVERITY_ICONS = {
7266
7300
  success: "\u2713",
7267
7301
  error: "\u2715",
@@ -7366,7 +7400,7 @@ var Snackbar = ({
7366
7400
  "\u2715"
7367
7401
  )
7368
7402
  ));
7369
- return import_react_dom4.default.createPortal(snackbarEl, document.body);
7403
+ return import_react_dom5.default.createPortal(snackbarEl, document.body);
7370
7404
  };
7371
7405
  Snackbar.displayName = "Snackbar";
7372
7406
 
@@ -7420,7 +7454,7 @@ Link.displayName = "Link";
7420
7454
 
7421
7455
  // lib/Popper/Popper.tsx
7422
7456
  var import_react44 = __toESM(require("react"), 1);
7423
- var import_react_dom5 = __toESM(require("react-dom"), 1);
7457
+ var import_react_dom6 = __toESM(require("react-dom"), 1);
7424
7458
  function computePopperPosition(anchorRect, popperRect, placement, offset2 = [0, 8]) {
7425
7459
  const [skid, dist] = offset2;
7426
7460
  let top = 0;
@@ -7563,13 +7597,13 @@ var Popper = ({
7563
7597
  if (disablePortal) {
7564
7598
  return /* @__PURE__ */ import_react44.default.createElement(import_react44.default.Fragment, null, popper);
7565
7599
  }
7566
- return import_react_dom5.default.createPortal(popper, document.body);
7600
+ return import_react_dom6.default.createPortal(popper, document.body);
7567
7601
  };
7568
7602
  Popper.displayName = "Popper";
7569
7603
 
7570
7604
  // lib/Popover/Popover.tsx
7571
7605
  var import_react45 = __toESM(require("react"), 1);
7572
- var import_react_dom6 = __toESM(require("react-dom"), 1);
7606
+ var import_react_dom7 = __toESM(require("react-dom"), 1);
7573
7607
  function getPoint(rect, v, h) {
7574
7608
  const x = h === "left" ? rect.left : h === "center" ? rect.left + rect.width / 2 : rect.right;
7575
7609
  const y = v === "top" ? rect.top : v === "center" ? rect.top + rect.height / 2 : rect.bottom;
@@ -7672,7 +7706,7 @@ var Popover = ({
7672
7706
  if (disablePortal) {
7673
7707
  return /* @__PURE__ */ import_react45.default.createElement("div", { className: `${rootClasses} rf-popover-inline`, style }, content);
7674
7708
  }
7675
- return import_react_dom6.default.createPortal(
7709
+ return import_react_dom7.default.createPortal(
7676
7710
  /* @__PURE__ */ import_react45.default.createElement("div", { className: rootClasses, style }, content),
7677
7711
  document.body
7678
7712
  );
@@ -8323,7 +8357,7 @@ PhoneField.displayName = "PhoneField";
8323
8357
 
8324
8358
  // lib/RufousTextEditor/RufousTextEditor.tsx
8325
8359
  var import_react58 = __toESM(require("react"), 1);
8326
- var import_react_dom12 = require("react-dom");
8360
+ var import_react_dom13 = require("react-dom");
8327
8361
  var import_react59 = require("@tiptap/react");
8328
8362
  var import_starter_kit = __toESM(require("@tiptap/starter-kit"), 1);
8329
8363
  var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"), 1);
@@ -8445,7 +8479,7 @@ function createMentionSuggestion(users) {
8445
8479
 
8446
8480
  // lib/RufousTextEditor/Toolbar.tsx
8447
8481
  var import_react55 = __toESM(require("react"), 1);
8448
- var import_react_dom9 = require("react-dom");
8482
+ var import_react_dom10 = require("react-dom");
8449
8483
 
8450
8484
  // lib/RufousTextEditor/TextToSpeech.tsx
8451
8485
  var import_react51 = __toESM(require("react"), 1);
@@ -8756,7 +8790,7 @@ var SpeechToText_default = SpeechToText;
8756
8790
 
8757
8791
  // lib/RufousTextEditor/AICommands.tsx
8758
8792
  var import_react53 = __toESM(require("react"), 1);
8759
- var import_react_dom7 = require("react-dom");
8793
+ var import_react_dom8 = require("react-dom");
8760
8794
  var AI_COMMANDS = [
8761
8795
  { id: "improve", label: "Improve writing", prompt: "Improve the following text to make it clearer, more engaging, and well-structured. Return only the improved text, no explanations." },
8762
8796
  { id: "shorter", label: "Make shorter", prompt: "Make the following text shorter and more concise while keeping the key points. Return only the shortened text, no explanations." },
@@ -8913,7 +8947,7 @@ var AICommands = ({ editor, onAICommand }) => {
8913
8947
  onClick: () => handleCommandSelect(cmd)
8914
8948
  },
8915
8949
  cmd.label
8916
- ))), /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && (0, import_react_dom7.createPortal)(
8950
+ ))), /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && (0, import_react_dom8.createPortal)(
8917
8951
  /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-modal-overlay", onMouseDown: handleCancel }, /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-modal", onMouseDown: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-modal-header" }, /* @__PURE__ */ import_react53.default.createElement("span", { className: "ai-modal-title" }, "AI Assistant"), /* @__PURE__ */ import_react53.default.createElement("button", { className: "ai-modal-close", onClick: handleCancel }, "\xD7")), /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-modal-prompt-section" }, /* @__PURE__ */ import_react53.default.createElement("label", { className: "ai-modal-label" }, "Prompt"), /* @__PURE__ */ import_react53.default.createElement("div", { className: "ai-modal-prompt-row" }, /* @__PURE__ */ import_react53.default.createElement(
8918
8952
  "textarea",
8919
8953
  {
@@ -8964,7 +8998,7 @@ var AICommands_default = AICommands;
8964
8998
 
8965
8999
  // lib/RufousTextEditor/TranslateModal.tsx
8966
9000
  var import_react54 = __toESM(require("react"), 1);
8967
- var import_react_dom8 = require("react-dom");
9001
+ var import_react_dom9 = require("react-dom");
8968
9002
  var LANGUAGES = [
8969
9003
  { code: "af", name: "Afrikaans" },
8970
9004
  { code: "sq", name: "Albanian" },
@@ -9155,7 +9189,7 @@ var TranslateModal = ({ editor, onClose, onTranslate, initialSource, initialTarg
9155
9189
  setTranslating(false);
9156
9190
  }
9157
9191
  };
9158
- return (0, import_react_dom8.createPortal)(
9192
+ return (0, import_react_dom9.createPortal)(
9159
9193
  /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-overlay", onClick: onClose }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-content translate-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-header" }, /* @__PURE__ */ import_react54.default.createElement("h3", null, "Translate options"), /* @__PURE__ */ import_react54.default.createElement("button", { className: "modal-close", onClick: onClose }, "\xD7")), /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-body" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "translate-columns" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "translate-col" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "translate-filter" }, /* @__PURE__ */ import_react54.default.createElement(
9160
9194
  "input",
9161
9195
  {
@@ -10065,7 +10099,7 @@ var Dropdown = ({ trigger, children, className = "", keepOpen = false }) => {
10065
10099
  },
10066
10100
  trigger.label,
10067
10101
  /* @__PURE__ */ import_react55.default.createElement("span", { className: "dropdown-arrow" }, "\u25BE")
10068
- ), open && (0, import_react_dom9.createPortal)(
10102
+ ), open && (0, import_react_dom10.createPortal)(
10069
10103
  /* @__PURE__ */ import_react55.default.createElement("div", { className: "rf-rte-wrapper rf-rte-dropdown-portal" }, /* @__PURE__ */ import_react55.default.createElement("div", { ref: menuRef, className: "dropdown-menu dropdown-menu-fixed", onClick: keepOpen ? void 0 : () => setOpen(false) }, typeof children === "function" ? children(() => setOpen(false)) : children)),
10070
10104
  document.body
10071
10105
  ));
@@ -10967,7 +11001,7 @@ var Toolbar_default = Toolbar;
10967
11001
 
10968
11002
  // lib/RufousTextEditor/ImageToolbar.tsx
10969
11003
  var import_react56 = __toESM(require("react"), 1);
10970
- var import_react_dom10 = require("react-dom");
11004
+ var import_react_dom11 = require("react-dom");
10971
11005
  var ALIGNMENTS = [
10972
11006
  { value: "left", label: "Left", icon: "\u2630" },
10973
11007
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11139,7 +11173,7 @@ var ImageToolbar = ({ editor }) => {
11139
11173
  }, [editor]);
11140
11174
  const node = editor?.state.selection.node;
11141
11175
  const isImage = node && node.type.name === "image";
11142
- if (!editor || !isImage || !pos) return showModal ? (0, import_react_dom10.createPortal)(
11176
+ if (!editor || !isImage || !pos) return showModal ? (0, import_react_dom11.createPortal)(
11143
11177
  /* @__PURE__ */ import_react56.default.createElement(ImagePropertiesModal, { editor, node, onClose: () => setShowModal(false) }),
11144
11178
  document.body
11145
11179
  ) : null;
@@ -11216,7 +11250,7 @@ var ImageToolbar = ({ editor }) => {
11216
11250
  );
11217
11251
  setShowVAlign(false);
11218
11252
  };
11219
- return (0, import_react_dom10.createPortal)(
11253
+ return (0, import_react_dom11.createPortal)(
11220
11254
  /* @__PURE__ */ import_react56.default.createElement(import_react56.default.Fragment, null, /* @__PURE__ */ import_react56.default.createElement(
11221
11255
  "div",
11222
11256
  {
@@ -11247,7 +11281,7 @@ var ImageToolbar_default = ImageToolbar;
11247
11281
 
11248
11282
  // lib/RufousTextEditor/VideoToolbar.tsx
11249
11283
  var import_react57 = __toESM(require("react"), 1);
11250
- var import_react_dom11 = require("react-dom");
11284
+ var import_react_dom12 = require("react-dom");
11251
11285
  var ALIGNMENTS2 = [
11252
11286
  { value: "left", label: "Left", icon: "\u2630" },
11253
11287
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11393,7 +11427,7 @@ var VideoToolbar = ({ editor }) => {
11393
11427
  const node = editor?.state.selection.node;
11394
11428
  const isVideo = node && VIDEO_TYPES.includes(node.type.name);
11395
11429
  const nodeType = node?.type.name;
11396
- if (!editor || !isVideo || !pos) return showModal ? (0, import_react_dom11.createPortal)(
11430
+ if (!editor || !isVideo || !pos) return showModal ? (0, import_react_dom12.createPortal)(
11397
11431
  /* @__PURE__ */ import_react57.default.createElement(VideoPropertiesModal, { editor, node, nodeType, onClose: () => setShowModal(false) }),
11398
11432
  document.body
11399
11433
  ) : null;
@@ -11440,7 +11474,7 @@ var VideoToolbar = ({ editor }) => {
11440
11474
  })
11441
11475
  );
11442
11476
  };
11443
- return (0, import_react_dom11.createPortal)(
11477
+ return (0, import_react_dom12.createPortal)(
11444
11478
  /* @__PURE__ */ import_react57.default.createElement(import_react57.default.Fragment, null, /* @__PURE__ */ import_react57.default.createElement(
11445
11479
  "div",
11446
11480
  {
@@ -12059,7 +12093,7 @@ var RufousTextEditor = ({
12059
12093
  },
12060
12094
  "\u201C Quote"
12061
12095
  )
12062
- ), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ import_react58.default.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ import_react58.default.createElement(import_react58.default.Fragment, null, /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && (0, import_react_dom12.createPortal)(
12096
+ ), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ import_react58.default.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ import_react58.default.createElement(import_react58.default.Fragment, null, /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && (0, import_react_dom13.createPortal)(
12063
12097
  /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ import_react58.default.createElement(
12064
12098
  "input",
12065
12099
  {
package/dist/main.css CHANGED
@@ -72,7 +72,7 @@
72
72
  display: flex;
73
73
  justify-content: center;
74
74
  align-items: center;
75
- z-index: 99999;
75
+ z-index: 2000;
76
76
  backdrop-filter: blur(2px);
77
77
  }
78
78
  .dialog-container {
@@ -1125,6 +1125,12 @@ pre {
1125
1125
  position: relative;
1126
1126
  width: 100%;
1127
1127
  }
1128
+ .rf-date-picker.rf-date-picker--portaled {
1129
+ position: fixed;
1130
+ top: auto;
1131
+ left: auto;
1132
+ z-index: 99999;
1133
+ }
1128
1134
  .rf-date-picker {
1129
1135
  position: absolute;
1130
1136
  top: calc(100% + 6px);
@@ -5788,6 +5794,7 @@ pre {
5788
5794
  text-transform: uppercase;
5789
5795
  letter-spacing: 0.5px;
5790
5796
  white-space: nowrap;
5797
+ height: 38px;
5791
5798
  }
5792
5799
  .add-btn,
5793
5800
  .btn-add {
package/dist/main.d.cts CHANGED
@@ -457,6 +457,10 @@ interface IconButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
457
457
  }
458
458
  declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
459
459
 
460
+ interface BaseDialogForm {
461
+ handleSubmit?: (e: React.FormEvent) => void;
462
+ [key: string]: any;
463
+ }
460
464
  interface BaseDialogProps {
461
465
  open?: boolean;
462
466
  onConfirm?: () => Promise<void> | void;
@@ -484,6 +488,8 @@ interface BaseDialogProps {
484
488
  size?: "sm" | "md" | "lg" | "xl" | "fullScreen";
485
489
  /** Scoped style overrides. Supports nested CSS selectors with & */
486
490
  sx?: SxProp;
491
+ /** Form object — when provided, wraps dialog in a <form> and shows a submit button */
492
+ form?: BaseDialogForm;
487
493
  /** A transition component (e.g. Fade, Slide, Grow, Zoom) to animate the dialog container */
488
494
  TransitionComponent?: React.ComponentType<{
489
495
  in: boolean;
package/dist/main.d.ts CHANGED
@@ -457,6 +457,10 @@ interface IconButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
457
457
  }
458
458
  declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
459
459
 
460
+ interface BaseDialogForm {
461
+ handleSubmit?: (e: React.FormEvent) => void;
462
+ [key: string]: any;
463
+ }
460
464
  interface BaseDialogProps {
461
465
  open?: boolean;
462
466
  onConfirm?: () => Promise<void> | void;
@@ -484,6 +488,8 @@ interface BaseDialogProps {
484
488
  size?: "sm" | "md" | "lg" | "xl" | "fullScreen";
485
489
  /** Scoped style overrides. Supports nested CSS selectors with & */
486
490
  sx?: SxProp;
491
+ /** Form object — when provided, wraps dialog in a <form> and shows a submit button */
492
+ form?: BaseDialogForm;
487
493
  /** A transition component (e.g. Fade, Slide, Grow, Zoom) to animate the dialog container */
488
494
  TransitionComponent?: React.ComponentType<{
489
495
  in: boolean;
package/dist/main.js CHANGED
@@ -1381,6 +1381,7 @@ var BaseDialog = ({
1381
1381
  dialogBodyStyle = {},
1382
1382
  size,
1383
1383
  sx,
1384
+ form,
1384
1385
  TransitionComponent,
1385
1386
  TransitionProps = {}
1386
1387
  }) => {
@@ -1394,15 +1395,27 @@ var BaseDialog = ({
1394
1395
  {
1395
1396
  className: "btn-cancel",
1396
1397
  onClick: onCancel || onClose,
1397
- disabled: isLoading || isButtonLoading
1398
+ disabled: isLoading || isButtonLoading,
1399
+ type: "button"
1398
1400
  },
1399
1401
  cancelText
1400
- ), onConfirm && /* @__PURE__ */ React65.createElement(
1402
+ ), form ? /* @__PURE__ */ React65.createElement(
1403
+ "button",
1404
+ {
1405
+ className: "btn-confirm",
1406
+ disabled: disableConfirmBtn || isButtonLoading,
1407
+ style: { position: "relative" },
1408
+ type: "submit"
1409
+ },
1410
+ /* @__PURE__ */ React65.createElement("span", { style: { visibility: isButtonLoading ? "hidden" : "visible" } }, submitText),
1411
+ isButtonLoading && /* @__PURE__ */ React65.createElement("span", { className: "spinner", style: { position: "absolute" } })
1412
+ ) : onConfirm && /* @__PURE__ */ React65.createElement(
1401
1413
  "button",
1402
1414
  {
1403
1415
  className: "btn-confirm",
1404
1416
  disabled: disableConfirmBtn || isButtonLoading,
1405
1417
  style: { position: "relative" },
1418
+ type: "button",
1406
1419
  onClick: async () => {
1407
1420
  setIsSubmitting(true);
1408
1421
  await onConfirm?.();
@@ -1412,37 +1425,37 @@ var BaseDialog = ({
1412
1425
  /* @__PURE__ */ React65.createElement("span", { style: { visibility: isButtonLoading ? "hidden" : "visible" } }, confirmText),
1413
1426
  isButtonLoading && /* @__PURE__ */ React65.createElement("span", { className: "spinner", style: { position: "absolute" } })
1414
1427
  ));
1415
- const dialogContent = /* @__PURE__ */ React65.createElement(
1428
+ const containerClass = ["dialog-container", size ? `size-${size}` : "", sxClass, className].filter(Boolean).join(" ");
1429
+ const containerStyle = { minWidth, minHeight };
1430
+ const dialogInner = /* @__PURE__ */ React65.createElement(React65.Fragment, null, /* @__PURE__ */ React65.createElement("div", { className: "dialog-title" }, /* @__PURE__ */ React65.createElement("h2", null, formatTitle ? title?.charAt(0).toUpperCase() + title?.slice(1) : title), showCloseButton && /* @__PURE__ */ React65.createElement("button", { className: "btn-close", type: "button", onClick: onClose }, /* @__PURE__ */ React65.createElement(
1431
+ X,
1432
+ {
1433
+ size: 18,
1434
+ color: themeConfig?.icon || "#666666"
1435
+ }
1436
+ ))), /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }), /* @__PURE__ */ React65.createElement(
1416
1437
  "div",
1417
1438
  {
1418
- className: ["dialog-container", size ? `size-${size}` : "", sxClass, className].filter(Boolean).join(" "),
1439
+ className: "dialog-body",
1419
1440
  style: {
1420
- minWidth,
1421
- minHeight
1441
+ ...fullScreen ? { height: "100%" } : { maxHeight: "758px", minHeight },
1442
+ ...dialogBodyStyle
1422
1443
  }
1423
1444
  },
1424
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-title" }, /* @__PURE__ */ React65.createElement("h2", null, formatTitle ? title?.charAt(0).toUpperCase() + title?.slice(1) : title), showCloseButton && /* @__PURE__ */ React65.createElement("button", { className: "btn-close", onClick: onClose }, /* @__PURE__ */ React65.createElement(
1425
- X,
1426
- {
1427
- size: 18,
1428
- color: themeConfig?.icon || "#666666"
1445
+ children
1446
+ ), /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }), customButtons || renderButtons());
1447
+ const dialogContent = form ? /* @__PURE__ */ React65.createElement(
1448
+ "form",
1449
+ {
1450
+ className: containerClass,
1451
+ style: containerStyle,
1452
+ onSubmit: (e) => {
1453
+ e.preventDefault();
1454
+ form.handleSubmit?.(e);
1429
1455
  }
1430
- ))),
1431
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }),
1432
- /* @__PURE__ */ React65.createElement(
1433
- "div",
1434
- {
1435
- className: "dialog-body",
1436
- style: {
1437
- ...fullScreen ? { height: "100%" } : { maxHeight: "758px", minHeight },
1438
- ...dialogBodyStyle
1439
- }
1440
- },
1441
- children
1442
- ),
1443
- /* @__PURE__ */ React65.createElement("div", { className: "dialog-divider" }),
1444
- customButtons || renderButtons()
1445
- );
1456
+ },
1457
+ dialogInner
1458
+ ) : /* @__PURE__ */ React65.createElement("div", { className: containerClass, style: containerStyle }, dialogInner);
1446
1459
  if (TransitionComponent) {
1447
1460
  return /* @__PURE__ */ React65.createElement(
1448
1461
  TransitionComponent,
@@ -1974,6 +1987,7 @@ import React70, {
1974
1987
  useEffect as useEffect4,
1975
1988
  useCallback
1976
1989
  } from "react";
1990
+ import { createPortal } from "react-dom";
1977
1991
  var WEEKDAYS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
1978
1992
  var MONTHS = [
1979
1993
  "January",
@@ -2415,7 +2429,10 @@ var DateField = ({
2415
2429
  useEffect4(() => {
2416
2430
  if (!open) return;
2417
2431
  const handler = (e) => {
2418
- if (containerRef.current && !containerRef.current.contains(e.target)) setOpen(false);
2432
+ const target = e.target;
2433
+ if (containerRef.current?.contains(target)) return;
2434
+ if (pickerRef.current?.contains(target)) return;
2435
+ setOpen(false);
2419
2436
  };
2420
2437
  document.addEventListener("mousedown", handler);
2421
2438
  return () => document.removeEventListener("mousedown", handler);
@@ -2616,80 +2633,97 @@ var DateField = ({
2616
2633
  )),
2617
2634
  label && /* @__PURE__ */ React70.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ React70.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
2618
2635
  variant === "outlined" && /* @__PURE__ */ React70.createElement("fieldset", { className: "rf-text-field__notch" }, label && /* @__PURE__ */ React70.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ React70.createElement("span", null, label, required ? " *" : "")))
2619
- ), open && !disabled && /* @__PURE__ */ React70.createElement(
2620
- "div",
2621
- {
2622
- ref: pickerRef,
2623
- className: [
2624
- "rf-date-picker",
2625
- isSideVariant ? "rf-date-picker--side" : "",
2626
- dropUp ? "rf-date-picker--drop-up" : ""
2627
- ].filter(Boolean).join(" "),
2628
- onMouseDown: (e) => e.preventDefault()
2629
- },
2630
- /* @__PURE__ */ React70.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ React70.createElement(
2631
- CalendarBody,
2632
- {
2633
- viewMonth,
2634
- viewYear,
2635
- selectedDate,
2636
- todayDate,
2637
- dayCells,
2638
- onDayClick: handleDayClick,
2639
- onPrev: prevMonth,
2640
- onNext: nextMonth,
2641
- onMonthSelect: setViewMonth,
2642
- onYearSelect: setViewYear
2643
- }
2644
- ), type === "datetime" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ React70.createElement(
2645
- SpinnerPanel,
2646
- {
2647
- hour,
2648
- minute,
2649
- ampm,
2650
- onHourChange: handleHourChange,
2651
- onMinuteChange: handleMinuteChange,
2652
- onHourInput: handleHourInput,
2653
- onMinuteInput: handleMinuteInput,
2654
- onAmpmToggle: handleAmpmToggle
2655
- }
2656
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2657
- type === "datetime-side" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ React70.createElement(
2658
- SpinnerPanel,
2659
- {
2660
- hour,
2661
- minute,
2662
- ampm,
2663
- onHourChange: handleHourChange,
2664
- onMinuteChange: handleMinuteChange,
2665
- onHourInput: handleHourInput,
2666
- onMinuteInput: handleMinuteInput,
2667
- onAmpmToggle: handleAmpmToggle
2668
- }
2669
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2670
- type === "datetime-scroll" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ React70.createElement(
2671
- ScrollColumn,
2672
- {
2673
- items: HOURS,
2674
- selected: hour - 1,
2675
- onSelect: handleScrollHour
2676
- }
2677
- ), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ React70.createElement(
2678
- ScrollColumn,
2679
- {
2680
- items: MINUTES,
2681
- selected: minute,
2682
- onSelect: handleScrollMinute
2683
- }
2684
- ), /* @__PURE__ */ React70.createElement(
2685
- ScrollColumn,
2636
+ ), open && !disabled && createPortal(
2637
+ /* @__PURE__ */ React70.createElement(
2638
+ "div",
2686
2639
  {
2687
- items: AMPMS,
2688
- selected: ampm === "AM" ? 0 : 1,
2689
- onSelect: handleScrollAmpm,
2690
- infinite: false
2691
- }
2692
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2640
+ ref: pickerRef,
2641
+ className: [
2642
+ "rf-date-picker",
2643
+ "rf-date-picker--portaled",
2644
+ isSideVariant ? "rf-date-picker--side" : "",
2645
+ dropUp ? "rf-date-picker--drop-up" : ""
2646
+ ].filter(Boolean).join(" "),
2647
+ style: (() => {
2648
+ const rect = containerRef.current?.getBoundingClientRect();
2649
+ if (!rect) return {};
2650
+ const top = rect.bottom + 6;
2651
+ const spaceBelow = window.innerHeight - rect.bottom - 6;
2652
+ const useDropUp = spaceBelow < 350 && rect.top > spaceBelow;
2653
+ return {
2654
+ position: "fixed",
2655
+ left: rect.left,
2656
+ ...useDropUp ? { bottom: window.innerHeight - rect.top + 6 } : { top },
2657
+ zIndex: 99999
2658
+ };
2659
+ })(),
2660
+ onMouseDown: (e) => e.preventDefault()
2661
+ },
2662
+ /* @__PURE__ */ React70.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ React70.createElement(
2663
+ CalendarBody,
2664
+ {
2665
+ viewMonth,
2666
+ viewYear,
2667
+ selectedDate,
2668
+ todayDate,
2669
+ dayCells,
2670
+ onDayClick: handleDayClick,
2671
+ onPrev: prevMonth,
2672
+ onNext: nextMonth,
2673
+ onMonthSelect: setViewMonth,
2674
+ onYearSelect: setViewYear
2675
+ }
2676
+ ), type === "datetime" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ React70.createElement(
2677
+ SpinnerPanel,
2678
+ {
2679
+ hour,
2680
+ minute,
2681
+ ampm,
2682
+ onHourChange: handleHourChange,
2683
+ onMinuteChange: handleMinuteChange,
2684
+ onHourInput: handleHourInput,
2685
+ onMinuteInput: handleMinuteInput,
2686
+ onAmpmToggle: handleAmpmToggle
2687
+ }
2688
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2689
+ type === "datetime-side" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ React70.createElement(
2690
+ SpinnerPanel,
2691
+ {
2692
+ hour,
2693
+ minute,
2694
+ ampm,
2695
+ onHourChange: handleHourChange,
2696
+ onMinuteChange: handleMinuteChange,
2697
+ onHourInput: handleHourInput,
2698
+ onMinuteInput: handleMinuteInput,
2699
+ onAmpmToggle: handleAmpmToggle
2700
+ }
2701
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2702
+ type === "datetime-scroll" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ React70.createElement(
2703
+ ScrollColumn,
2704
+ {
2705
+ items: HOURS,
2706
+ selected: hour - 1,
2707
+ onSelect: handleScrollHour
2708
+ }
2709
+ ), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ React70.createElement(
2710
+ ScrollColumn,
2711
+ {
2712
+ items: MINUTES,
2713
+ selected: minute,
2714
+ onSelect: handleScrollMinute
2715
+ }
2716
+ ), /* @__PURE__ */ React70.createElement(
2717
+ ScrollColumn,
2718
+ {
2719
+ items: AMPMS,
2720
+ selected: ampm === "AM" ? 0 : 1,
2721
+ onSelect: handleScrollAmpm,
2722
+ infinite: false
2723
+ }
2724
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2725
+ ),
2726
+ document.body
2693
2727
  )), helperText && /* @__PURE__ */ React70.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
2694
2728
  };
2695
2729
  DateField.displayName = "DateField";
@@ -8257,7 +8291,7 @@ PhoneField.displayName = "PhoneField";
8257
8291
 
8258
8292
  // lib/RufousTextEditor/RufousTextEditor.tsx
8259
8293
  import React115, { useMemo as useMemo4, useCallback as useCallback13, useState as useState33, useRef as useRef29, useEffect as useEffect26 } from "react";
8260
- import { createPortal as createPortal6 } from "react-dom";
8294
+ import { createPortal as createPortal7 } from "react-dom";
8261
8295
  import { useEditor, EditorContent, EditorContext, FloatingMenu, BubbleMenu } from "@tiptap/react";
8262
8296
  import StarterKit from "@tiptap/starter-kit";
8263
8297
  import Placeholder from "@tiptap/extension-placeholder";
@@ -8379,7 +8413,7 @@ function createMentionSuggestion(users) {
8379
8413
 
8380
8414
  // lib/RufousTextEditor/Toolbar.tsx
8381
8415
  import React112, { useState as useState30, useRef as useRef26, useEffect as useEffect23, useCallback as useCallback12 } from "react";
8382
- import { createPortal as createPortal3 } from "react-dom";
8416
+ import { createPortal as createPortal4 } from "react-dom";
8383
8417
 
8384
8418
  // lib/RufousTextEditor/TextToSpeech.tsx
8385
8419
  import React107, { useState as useState26, useEffect as useEffect20, useRef as useRef23, useCallback as useCallback9 } from "react";
@@ -8690,7 +8724,7 @@ var SpeechToText_default = SpeechToText;
8690
8724
 
8691
8725
  // lib/RufousTextEditor/AICommands.tsx
8692
8726
  import React109, { useState as useState28, useRef as useRef25, useEffect as useEffect22, useCallback as useCallback11 } from "react";
8693
- import { createPortal } from "react-dom";
8727
+ import { createPortal as createPortal2 } from "react-dom";
8694
8728
  var AI_COMMANDS = [
8695
8729
  { id: "improve", label: "Improve writing", prompt: "Improve the following text to make it clearer, more engaging, and well-structured. Return only the improved text, no explanations." },
8696
8730
  { id: "shorter", label: "Make shorter", prompt: "Make the following text shorter and more concise while keeping the key points. Return only the shortened text, no explanations." },
@@ -8847,7 +8881,7 @@ var AICommands = ({ editor, onAICommand }) => {
8847
8881
  onClick: () => handleCommandSelect(cmd)
8848
8882
  },
8849
8883
  cmd.label
8850
- ))), /* @__PURE__ */ React109.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && createPortal(
8884
+ ))), /* @__PURE__ */ React109.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && createPortal2(
8851
8885
  /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-overlay", onMouseDown: handleCancel }, /* @__PURE__ */ React109.createElement("div", { className: "ai-modal", onMouseDown: (e) => e.stopPropagation() }, /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-header" }, /* @__PURE__ */ React109.createElement("span", { className: "ai-modal-title" }, "AI Assistant"), /* @__PURE__ */ React109.createElement("button", { className: "ai-modal-close", onClick: handleCancel }, "\xD7")), /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-prompt-section" }, /* @__PURE__ */ React109.createElement("label", { className: "ai-modal-label" }, "Prompt"), /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-prompt-row" }, /* @__PURE__ */ React109.createElement(
8852
8886
  "textarea",
8853
8887
  {
@@ -8898,7 +8932,7 @@ var AICommands_default = AICommands;
8898
8932
 
8899
8933
  // lib/RufousTextEditor/TranslateModal.tsx
8900
8934
  import React110, { useState as useState29, useMemo as useMemo3 } from "react";
8901
- import { createPortal as createPortal2 } from "react-dom";
8935
+ import { createPortal as createPortal3 } from "react-dom";
8902
8936
  var LANGUAGES = [
8903
8937
  { code: "af", name: "Afrikaans" },
8904
8938
  { code: "sq", name: "Albanian" },
@@ -9089,7 +9123,7 @@ var TranslateModal = ({ editor, onClose, onTranslate, initialSource, initialTarg
9089
9123
  setTranslating(false);
9090
9124
  }
9091
9125
  };
9092
- return createPortal2(
9126
+ return createPortal3(
9093
9127
  /* @__PURE__ */ React110.createElement("div", { className: "modal-overlay", onClick: onClose }, /* @__PURE__ */ React110.createElement("div", { className: "modal-content translate-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React110.createElement("div", { className: "modal-header" }, /* @__PURE__ */ React110.createElement("h3", null, "Translate options"), /* @__PURE__ */ React110.createElement("button", { className: "modal-close", onClick: onClose }, "\xD7")), /* @__PURE__ */ React110.createElement("div", { className: "modal-body" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-columns" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-col" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-filter" }, /* @__PURE__ */ React110.createElement(
9094
9128
  "input",
9095
9129
  {
@@ -9999,7 +10033,7 @@ var Dropdown = ({ trigger, children, className = "", keepOpen = false }) => {
9999
10033
  },
10000
10034
  trigger.label,
10001
10035
  /* @__PURE__ */ React112.createElement("span", { className: "dropdown-arrow" }, "\u25BE")
10002
- ), open && createPortal3(
10036
+ ), open && createPortal4(
10003
10037
  /* @__PURE__ */ React112.createElement("div", { className: "rf-rte-wrapper rf-rte-dropdown-portal" }, /* @__PURE__ */ React112.createElement("div", { ref: menuRef, className: "dropdown-menu dropdown-menu-fixed", onClick: keepOpen ? void 0 : () => setOpen(false) }, typeof children === "function" ? children(() => setOpen(false)) : children)),
10004
10038
  document.body
10005
10039
  ));
@@ -10901,7 +10935,7 @@ var Toolbar_default = Toolbar;
10901
10935
 
10902
10936
  // lib/RufousTextEditor/ImageToolbar.tsx
10903
10937
  import React113, { useState as useState31, useEffect as useEffect24, useRef as useRef27 } from "react";
10904
- import { createPortal as createPortal4 } from "react-dom";
10938
+ import { createPortal as createPortal5 } from "react-dom";
10905
10939
  var ALIGNMENTS = [
10906
10940
  { value: "left", label: "Left", icon: "\u2630" },
10907
10941
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11073,7 +11107,7 @@ var ImageToolbar = ({ editor }) => {
11073
11107
  }, [editor]);
11074
11108
  const node = editor?.state.selection.node;
11075
11109
  const isImage = node && node.type.name === "image";
11076
- if (!editor || !isImage || !pos) return showModal ? createPortal4(
11110
+ if (!editor || !isImage || !pos) return showModal ? createPortal5(
11077
11111
  /* @__PURE__ */ React113.createElement(ImagePropertiesModal, { editor, node, onClose: () => setShowModal(false) }),
11078
11112
  document.body
11079
11113
  ) : null;
@@ -11150,7 +11184,7 @@ var ImageToolbar = ({ editor }) => {
11150
11184
  );
11151
11185
  setShowVAlign(false);
11152
11186
  };
11153
- return createPortal4(
11187
+ return createPortal5(
11154
11188
  /* @__PURE__ */ React113.createElement(React113.Fragment, null, /* @__PURE__ */ React113.createElement(
11155
11189
  "div",
11156
11190
  {
@@ -11181,7 +11215,7 @@ var ImageToolbar_default = ImageToolbar;
11181
11215
 
11182
11216
  // lib/RufousTextEditor/VideoToolbar.tsx
11183
11217
  import React114, { useState as useState32, useEffect as useEffect25, useRef as useRef28 } from "react";
11184
- import { createPortal as createPortal5 } from "react-dom";
11218
+ import { createPortal as createPortal6 } from "react-dom";
11185
11219
  var ALIGNMENTS2 = [
11186
11220
  { value: "left", label: "Left", icon: "\u2630" },
11187
11221
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11327,7 +11361,7 @@ var VideoToolbar = ({ editor }) => {
11327
11361
  const node = editor?.state.selection.node;
11328
11362
  const isVideo = node && VIDEO_TYPES.includes(node.type.name);
11329
11363
  const nodeType = node?.type.name;
11330
- if (!editor || !isVideo || !pos) return showModal ? createPortal5(
11364
+ if (!editor || !isVideo || !pos) return showModal ? createPortal6(
11331
11365
  /* @__PURE__ */ React114.createElement(VideoPropertiesModal, { editor, node, nodeType, onClose: () => setShowModal(false) }),
11332
11366
  document.body
11333
11367
  ) : null;
@@ -11374,7 +11408,7 @@ var VideoToolbar = ({ editor }) => {
11374
11408
  })
11375
11409
  );
11376
11410
  };
11377
- return createPortal5(
11411
+ return createPortal6(
11378
11412
  /* @__PURE__ */ React114.createElement(React114.Fragment, null, /* @__PURE__ */ React114.createElement(
11379
11413
  "div",
11380
11414
  {
@@ -11993,7 +12027,7 @@ var RufousTextEditor = ({
11993
12027
  },
11994
12028
  "\u201C Quote"
11995
12029
  )
11996
- ), /* @__PURE__ */ React115.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React115.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ React115.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ React115.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ React115.createElement(React115.Fragment, null, /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && createPortal6(
12030
+ ), /* @__PURE__ */ React115.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React115.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ React115.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ React115.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ React115.createElement(React115.Fragment, null, /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && createPortal7(
11997
12031
  /* @__PURE__ */ React115.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React115.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ React115.createElement(
11998
12032
  "input",
11999
12033
  {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rufous/ui",
3
3
  "private": false,
4
- "version": "0.2.64",
4
+ "version": "0.2.66",
5
5
  "type": "module",
6
6
  "description": "Experimental: A lightweight React UI component library (Beta)",
7
7
  "style": "./dist/main.css",