@seekho/ui 0.1.32 → 0.1.34

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/index.mjs CHANGED
@@ -1,8 +1,11 @@
1
- import React8, { createContext, useState, useId, useRef, useEffect, Children, isValidElement, useCallback, cloneElement, useContext } from 'react';
2
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import React10, { createContext, useState, useId, useRef, useEffect, useCallback, Children, isValidElement, cloneElement, useContext } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import ReactDOM, { createPortal } from 'react-dom';
3
4
  import { useHotkeys } from 'react-hotkeys-hook';
4
5
 
5
6
  var __defProp = Object.defineProperty;
7
+ var __defProps = Object.defineProperties;
8
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
9
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
11
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -18,6 +21,7 @@ var __spreadValues = (a, b) => {
18
21
  }
19
22
  return a;
20
23
  };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
25
  var __objRest = (source, exclude) => {
22
26
  var target = {};
23
27
  for (var prop in source)
@@ -150,6 +154,62 @@ var AccordionDetails = ({
150
154
  }
151
155
  );
152
156
  };
157
+ var typeMap = {
158
+ success: "bg-green-100 text-green-500",
159
+ error: "bg-red-100 text-red-500",
160
+ warning: "bg-orange-100 text-orange-500",
161
+ default: "bg-gray-100 text-gray-500"
162
+ };
163
+ var Chip = ({
164
+ label,
165
+ type = "default",
166
+ style,
167
+ deleteIcon,
168
+ disabled = false,
169
+ className = "",
170
+ onClick,
171
+ onDelete
172
+ }) => {
173
+ var _a;
174
+ const typeClass = (_a = typeMap[type]) != null ? _a : typeMap.default;
175
+ const cursorClass = disabled ? "opacity-50 cursor-not-allowed" : onClick ? "cursor-pointer" : "cursor-default";
176
+ return /* @__PURE__ */ jsxs(
177
+ "div",
178
+ {
179
+ role: onClick ? "button" : void 0,
180
+ tabIndex: onClick && !disabled ? 0 : void 0,
181
+ style,
182
+ onClick: !disabled && onClick ? onClick : void 0,
183
+ className: `inline-flex items-center gap-1 rounded-full w-fit px-3 py-[6px] text-[12px] capitalize ${typeClass} ${cursorClass} ${className}`,
184
+ children: [
185
+ /* @__PURE__ */ jsx("span", { className: "leading-none", children: label }),
186
+ onDelete && /* @__PURE__ */ jsx(
187
+ "span",
188
+ {
189
+ role: "button",
190
+ tabIndex: disabled ? -1 : 0,
191
+ onClick: (e) => {
192
+ e.stopPropagation();
193
+ if (!disabled) onDelete(e);
194
+ },
195
+ className: "flex items-center cursor-pointer ml-0.5 opacity-60 hover:opacity-100",
196
+ children: deleteIcon != null ? deleteIcon : /* @__PURE__ */ jsx(
197
+ "svg",
198
+ {
199
+ xmlns: "http://www.w3.org/2000/svg",
200
+ width: "16",
201
+ height: "16",
202
+ viewBox: "0 0 24 24",
203
+ fill: "currentColor",
204
+ children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })
205
+ }
206
+ )
207
+ }
208
+ )
209
+ ]
210
+ }
211
+ );
212
+ };
153
213
  function AutoComplete({
154
214
  label,
155
215
  value,
@@ -390,7 +450,7 @@ function AutoComplete({
390
450
  isSelected({ option }) ? "font-semibold" : ""
391
451
  ].join(" ")
392
452
  };
393
- return renderOption ? /* @__PURE__ */ jsx(React8.Fragment, { children: renderOption(optionProps, option) }, idx) : /* @__PURE__ */ jsx(
453
+ return renderOption ? /* @__PURE__ */ jsx(React10.Fragment, { children: renderOption(optionProps, option) }, idx) : /* @__PURE__ */ jsx(
394
454
  "li",
395
455
  {
396
456
  onMouseDown: () => handleSelect({ option }),
@@ -633,7 +693,7 @@ var CustomAnchor = ({
633
693
  }
634
694
  );
635
695
  };
636
- var CustomInput = React8.forwardRef(
696
+ var CustomInput = React10.forwardRef(
637
697
  (_a, ref) => {
638
698
  var _b = _a, { label: _label, error, className, type } = _b, props = __objRest(_b, ["label", "error", "className", "type"]);
639
699
  return /* @__PURE__ */ jsx(
@@ -813,6 +873,123 @@ var FilterDrawer = ({
813
873
  }
814
874
  );
815
875
  };
876
+ var GAP = 4;
877
+ var PAD = 6;
878
+ function reposition(menu, anchorEl, align) {
879
+ const rect = anchorEl.getBoundingClientRect();
880
+ const mw = menu.offsetWidth;
881
+ const mh = menu.offsetHeight;
882
+ const vw = window.innerWidth;
883
+ const vh = window.innerHeight;
884
+ let top = rect.bottom + GAP + mh > vh - PAD ? Math.max(PAD, rect.top - mh - GAP) : rect.bottom + GAP;
885
+ let left = align === "right" ? rect.right - mw : rect.left;
886
+ left = Math.max(PAD, Math.min(left, vw - mw - PAD));
887
+ menu.style.top = `${top}px`;
888
+ menu.style.left = `${left}px`;
889
+ menu.style.minWidth = `${rect.width}px`;
890
+ menu.style.opacity = "1";
891
+ }
892
+ var Menu = ({
893
+ anchorEl,
894
+ open,
895
+ onClose,
896
+ children,
897
+ align = "left",
898
+ className = ""
899
+ }) => {
900
+ const menuRef = useRef(null);
901
+ const onCloseRef = useRef(onClose);
902
+ useEffect(() => {
903
+ onCloseRef.current = onClose;
904
+ });
905
+ useEffect(() => {
906
+ if (!open || !anchorEl) return;
907
+ const id = requestAnimationFrame(() => {
908
+ if (menuRef.current) reposition(menuRef.current, anchorEl, align);
909
+ });
910
+ return () => cancelAnimationFrame(id);
911
+ }, [open, anchorEl, align]);
912
+ useEffect(() => {
913
+ if (!open || !anchorEl) return;
914
+ const update = () => {
915
+ if (menuRef.current) reposition(menuRef.current, anchorEl, align);
916
+ };
917
+ window.addEventListener("scroll", update, true);
918
+ window.addEventListener("resize", update);
919
+ return () => {
920
+ window.removeEventListener("scroll", update, true);
921
+ window.removeEventListener("resize", update);
922
+ };
923
+ }, [open, anchorEl, align]);
924
+ useEffect(() => {
925
+ if (!open) return;
926
+ const handleKey = (e) => {
927
+ if (e.key === "Escape") onCloseRef.current();
928
+ };
929
+ document.addEventListener("keydown", handleKey);
930
+ return () => document.removeEventListener("keydown", handleKey);
931
+ }, [open]);
932
+ useEffect(() => {
933
+ if (!open) return;
934
+ const handleMouseDown = (e) => {
935
+ var _a;
936
+ if ((anchorEl == null ? void 0 : anchorEl.contains(e.target)) || ((_a = menuRef.current) == null ? void 0 : _a.contains(e.target)))
937
+ return;
938
+ onCloseRef.current();
939
+ };
940
+ document.addEventListener("mousedown", handleMouseDown);
941
+ return () => document.removeEventListener("mousedown", handleMouseDown);
942
+ }, [open, anchorEl]);
943
+ if (!open) return null;
944
+ return ReactDOM.createPortal(
945
+ /* @__PURE__ */ jsx(
946
+ "div",
947
+ {
948
+ ref: menuRef,
949
+ role: "menu",
950
+ style: {
951
+ position: "fixed",
952
+ top: -9999,
953
+ left: -9999,
954
+ opacity: 0,
955
+ zIndex: 9999,
956
+ transition: "opacity 100ms ease"
957
+ },
958
+ className: `bg-white rounded shadow-lg border border-gray-100 py-1 max-w-[calc(100vw-12px)] ${className}`,
959
+ children
960
+ }
961
+ ),
962
+ document.body
963
+ );
964
+ };
965
+ var MenuItem = ({
966
+ onClick,
967
+ children,
968
+ disabled = false,
969
+ selected = false,
970
+ icon,
971
+ className = ""
972
+ }) => {
973
+ return /* @__PURE__ */ jsxs(
974
+ "div",
975
+ {
976
+ role: "menuitem",
977
+ "aria-disabled": disabled,
978
+ onClick: disabled ? void 0 : onClick,
979
+ className: [
980
+ "px-3 py-2 flex gap-x-3 items-center text-[14px] tracking-wide min-w-0 w-full",
981
+ disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer hover:bg-gray-50",
982
+ selected ? "bg-gray-100 font-medium" : "",
983
+ className
984
+ ].filter(Boolean).join(" "),
985
+ children: [
986
+ icon && /* @__PURE__ */ jsx("span", { className: "flex items-center shrink-0", children: icon }),
987
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children })
988
+ ]
989
+ }
990
+ );
991
+ };
992
+ var MenuDivider = () => /* @__PURE__ */ jsx("hr", { className: "my-1 border-gray-100" });
816
993
 
817
994
  // src/utils/modalStack.ts
818
995
  var stack = [];
@@ -1688,6 +1865,228 @@ var StagingAlert = ({
1688
1865
  ] })
1689
1866
  ] });
1690
1867
  };
1868
+ var sizeStyles = {
1869
+ small: { padding: "4px 10px", fontSize: "13px" },
1870
+ medium: { padding: "7px 14px", fontSize: "16px" },
1871
+ large: { padding: "10px 16px", fontSize: "16px" }
1872
+ };
1873
+ var Select = ({
1874
+ value,
1875
+ onChange,
1876
+ children,
1877
+ disabled = false,
1878
+ placeholder = "Select...",
1879
+ size = "medium",
1880
+ error = false,
1881
+ className = ""
1882
+ }) => {
1883
+ const [isOpen, setIsOpen] = useState(false);
1884
+ const [dropdownStyle, setDropdownStyle] = useState({});
1885
+ const [focusedIndex, setFocusedIndex] = useState(-1);
1886
+ const triggerRef = useRef(null);
1887
+ const dropdownRef = useRef(null);
1888
+ const options = React10.Children.toArray(children).filter(Boolean).map((child) => {
1889
+ var _a, _b, _c, _d, _e;
1890
+ const c = child;
1891
+ return {
1892
+ value: (_b = (_a = c.props) == null ? void 0 : _a.value) != null ? _b : "",
1893
+ label: (_c = c.props) == null ? void 0 : _c.children,
1894
+ disabled: (_e = (_d = c.props) == null ? void 0 : _d.disabled) != null ? _e : false
1895
+ };
1896
+ });
1897
+ const selectedOption = options.find(
1898
+ (opt) => String(opt.value) === String(value)
1899
+ );
1900
+ const computePosition = useCallback(() => {
1901
+ if (!triggerRef.current) return;
1902
+ const rect = triggerRef.current.getBoundingClientRect();
1903
+ const dropdownHeight = Math.min(options.length * 40, 240);
1904
+ const spaceBelow = window.innerHeight - rect.bottom;
1905
+ const openAbove = spaceBelow < dropdownHeight + 8 && rect.top > dropdownHeight;
1906
+ setDropdownStyle(__spreadProps(__spreadValues({
1907
+ position: "fixed"
1908
+ }, openAbove ? { bottom: window.innerHeight - rect.top + 2 } : { top: rect.bottom + 2 }), {
1909
+ left: rect.left,
1910
+ width: rect.width,
1911
+ zIndex: 9999
1912
+ }));
1913
+ }, [options.length]);
1914
+ useEffect(() => {
1915
+ const handleClickOutside = (e) => {
1916
+ if (triggerRef.current && !triggerRef.current.contains(e.target) && (!dropdownRef.current || !dropdownRef.current.contains(e.target))) {
1917
+ setIsOpen(false);
1918
+ setFocusedIndex(-1);
1919
+ }
1920
+ };
1921
+ document.addEventListener("mousedown", handleClickOutside);
1922
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1923
+ }, []);
1924
+ useEffect(() => {
1925
+ if (!isOpen) return;
1926
+ const handleKeyDown = (e) => {
1927
+ if (e.key === "Escape") {
1928
+ setIsOpen(false);
1929
+ setFocusedIndex(-1);
1930
+ } else if (e.key === "ArrowDown") {
1931
+ e.preventDefault();
1932
+ setFocusedIndex((prev) => {
1933
+ var _a;
1934
+ let next = prev + 1;
1935
+ while (next < options.length && ((_a = options[next]) == null ? void 0 : _a.disabled)) next++;
1936
+ return next < options.length ? next : prev;
1937
+ });
1938
+ } else if (e.key === "ArrowUp") {
1939
+ e.preventDefault();
1940
+ setFocusedIndex((prev) => {
1941
+ var _a;
1942
+ let next = prev - 1;
1943
+ while (next >= 0 && ((_a = options[next]) == null ? void 0 : _a.disabled)) next--;
1944
+ return next >= 0 ? next : prev;
1945
+ });
1946
+ } else if (e.key === "Enter" && focusedIndex >= 0) {
1947
+ const opt = options[focusedIndex];
1948
+ if (opt && !opt.disabled) {
1949
+ onChange({ target: { value: opt.value } });
1950
+ setIsOpen(false);
1951
+ setFocusedIndex(-1);
1952
+ }
1953
+ }
1954
+ };
1955
+ document.addEventListener("keydown", handleKeyDown);
1956
+ return () => document.removeEventListener("keydown", handleKeyDown);
1957
+ }, [isOpen, focusedIndex, options, onChange]);
1958
+ useEffect(() => {
1959
+ if (focusedIndex >= 0 && dropdownRef.current) {
1960
+ const item = dropdownRef.current.children[focusedIndex];
1961
+ item == null ? void 0 : item.scrollIntoView({ block: "nearest" });
1962
+ }
1963
+ }, [focusedIndex]);
1964
+ useEffect(() => {
1965
+ if (!isOpen) return;
1966
+ window.addEventListener("scroll", computePosition, true);
1967
+ window.addEventListener("resize", computePosition);
1968
+ return () => {
1969
+ window.removeEventListener("scroll", computePosition, true);
1970
+ window.removeEventListener("resize", computePosition);
1971
+ };
1972
+ }, [isOpen, computePosition]);
1973
+ const handleOpen = () => {
1974
+ if (disabled) return;
1975
+ if (!isOpen) {
1976
+ computePosition();
1977
+ setFocusedIndex(
1978
+ options.findIndex((opt) => String(opt.value) === String(value))
1979
+ );
1980
+ }
1981
+ setIsOpen((prev) => !prev);
1982
+ };
1983
+ const handleSelect = (opt) => {
1984
+ if (opt.disabled) return;
1985
+ onChange({ target: { value: opt.value } });
1986
+ setIsOpen(false);
1987
+ setFocusedIndex(-1);
1988
+ };
1989
+ const borderColor = error ? "#ef4444" : isOpen ? "#534f8f" : "rgba(0,0,0,0.23)";
1990
+ const { padding, fontSize } = sizeStyles[size];
1991
+ return /* @__PURE__ */ jsxs("div", { className: `relative ${className}`, ref: triggerRef, children: [
1992
+ /* @__PURE__ */ jsxs(
1993
+ "button",
1994
+ {
1995
+ type: "button",
1996
+ disabled,
1997
+ onClick: handleOpen,
1998
+ className: "w-full flex items-center justify-between rounded-md bg-white text-left outline-none disabled:opacity-50 disabled:cursor-not-allowed",
1999
+ style: { padding, border: `1px solid ${borderColor}`, transition: "border-color 0.15s ease" },
2000
+ children: [
2001
+ /* @__PURE__ */ jsx("span", { className: "truncate flex-1", style: { fontSize }, children: selectedOption ? selectedOption.label : /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: placeholder }) }),
2002
+ /* @__PURE__ */ jsx(
2003
+ "svg",
2004
+ {
2005
+ xmlns: "http://www.w3.org/2000/svg",
2006
+ width: "18",
2007
+ height: "18",
2008
+ viewBox: "0 0 24 24",
2009
+ fill: "currentColor",
2010
+ className: `shrink-0 ml-2 text-gray-400 transition-transform duration-150 ${isOpen ? "rotate-180" : ""}`,
2011
+ children: /* @__PURE__ */ jsx("path", { d: "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" })
2012
+ }
2013
+ )
2014
+ ]
2015
+ }
2016
+ ),
2017
+ isOpen && ReactDOM.createPortal(
2018
+ /* @__PURE__ */ jsx(
2019
+ "ul",
2020
+ {
2021
+ ref: dropdownRef,
2022
+ style: dropdownStyle,
2023
+ className: "bg-white shadow-lg rounded-md border border-gray-200 max-h-60 overflow-y-auto",
2024
+ children: options.map((opt, i) => /* @__PURE__ */ jsx(
2025
+ "li",
2026
+ {
2027
+ onClick: () => handleSelect(opt),
2028
+ className: `px-4 py-2 text-[14px] ${opt.disabled ? "text-gray-400 cursor-not-allowed" : String(opt.value) === String(value) ? "bg-purple-100 text-[#534f8f] font-medium cursor-pointer" : focusedIndex === i ? "bg-gray-100 text-gray-800 cursor-pointer" : "text-gray-800 hover:bg-gray-50 cursor-pointer"}`,
2029
+ children: opt.label
2030
+ },
2031
+ i
2032
+ ))
2033
+ }
2034
+ ),
2035
+ document.body
2036
+ )
2037
+ ] });
2038
+ };
2039
+
2040
+ // src/components/Select/SelectOption.tsx
2041
+ var SelectOption = (_props) => null;
2042
+ var Switch = ({
2043
+ checked,
2044
+ onChange,
2045
+ disabled = false,
2046
+ className = ""
2047
+ }) => {
2048
+ return /* @__PURE__ */ jsxs(
2049
+ "button",
2050
+ {
2051
+ type: "button",
2052
+ role: "switch",
2053
+ "aria-checked": checked,
2054
+ disabled,
2055
+ onClick: disabled ? void 0 : onChange,
2056
+ className: `relative inline-flex shrink-0 border-0 bg-transparent p-0 focus:outline-none ${disabled ? "opacity-40 cursor-not-allowed" : "cursor-pointer"} ${className}`,
2057
+ style: { width: 58, height: 38 },
2058
+ children: [
2059
+ /* @__PURE__ */ jsx(
2060
+ "span",
2061
+ {
2062
+ className: "absolute rounded-full transition-colors duration-200",
2063
+ style: {
2064
+ width: 34,
2065
+ height: 14,
2066
+ top: 12,
2067
+ left: 12,
2068
+ backgroundColor: checked ? "rgba(83,79,143,0.5)" : "rgba(0,0,0,0.38)"
2069
+ }
2070
+ }
2071
+ ),
2072
+ /* @__PURE__ */ jsx(
2073
+ "span",
2074
+ {
2075
+ className: "absolute rounded-full transition-all duration-200",
2076
+ style: {
2077
+ width: 20,
2078
+ height: 20,
2079
+ top: 9,
2080
+ left: checked ? 29 : 9,
2081
+ backgroundColor: checked ? "#534f8f" : "#fafafa",
2082
+ boxShadow: "0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12)"
2083
+ }
2084
+ }
2085
+ )
2086
+ ]
2087
+ }
2088
+ );
2089
+ };
1691
2090
  var SCROLL_STEP = 120;
1692
2091
  function Tabs({
1693
2092
  value,
@@ -1862,26 +2261,43 @@ function Tab({
1862
2261
  }
1863
2262
  );
1864
2263
  }
1865
- var placementClass = {
1866
- top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
1867
- "top-start": "bottom-full left-0 mb-2",
1868
- "top-end": "bottom-full right-0 mb-2",
1869
- bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
1870
- "bottom-start": "top-full left-0 mt-2",
1871
- "bottom-end": "top-full right-0 mt-2",
1872
- left: "right-full top-1/2 -translate-y-1/2 mr-2",
1873
- "left-start": "right-full top-0 mr-2",
1874
- "left-end": "right-full bottom-0 mr-2",
1875
- right: "left-full top-1/2 -translate-y-1/2 ml-2",
1876
- "right-start": "left-full top-0 ml-2",
1877
- "right-end": "left-full bottom-0 ml-2"
1878
- };
2264
+ var GAP2 = 8;
2265
+ var VIEWPORT_PADDING = 6;
1879
2266
  var arrowClass = {
1880
2267
  top: "top-full left-1/2 -translate-x-1/2 border-t-gray-600/80 border-x-transparent border-b-transparent",
1881
2268
  bottom: "bottom-full left-1/2 -translate-x-1/2 border-b-gray-600/80 border-x-transparent border-t-transparent",
1882
2269
  left: "left-full top-1/2 -translate-y-1/2 border-l-gray-600/80 border-y-transparent border-r-transparent",
1883
2270
  right: "right-full top-1/2 -translate-y-1/2 border-r-gray-600/80 border-y-transparent border-l-transparent"
1884
2271
  };
2272
+ function getPosition(trigger, tooltip, placement) {
2273
+ const tw = tooltip.offsetWidth;
2274
+ const th = tooltip.offsetHeight;
2275
+ const { top, left, right, bottom, width, height } = trigger;
2276
+ const positions = {
2277
+ top: { top: top - th - GAP2, left: left + width / 2 - tw / 2 },
2278
+ "top-start": { top: top - th - GAP2, left },
2279
+ "top-end": { top: top - th - GAP2, left: right - tw },
2280
+ bottom: { top: bottom + GAP2, left: left + width / 2 - tw / 2 },
2281
+ "bottom-start": { top: bottom + GAP2, left },
2282
+ "bottom-end": { top: bottom + GAP2, left: right - tw },
2283
+ left: { top: top + height / 2 - th / 2, left: left - tw - GAP2 },
2284
+ "left-start": { top, left: left - tw - GAP2 },
2285
+ "left-end": { top: bottom - th, left: left - tw - GAP2 },
2286
+ right: { top: top + height / 2 - th / 2, left: right + GAP2 },
2287
+ "right-start": { top, left: right + GAP2 },
2288
+ "right-end": { top: bottom - th, left: right + GAP2 }
2289
+ };
2290
+ const pos = positions[placement];
2291
+ pos.left = Math.max(
2292
+ VIEWPORT_PADDING,
2293
+ Math.min(pos.left, window.innerWidth - tw - VIEWPORT_PADDING)
2294
+ );
2295
+ pos.top = Math.max(
2296
+ VIEWPORT_PADDING,
2297
+ Math.min(pos.top, window.innerHeight - th - VIEWPORT_PADDING)
2298
+ );
2299
+ return pos;
2300
+ }
1885
2301
  function Tooltip({
1886
2302
  title,
1887
2303
  children,
@@ -1894,10 +2310,34 @@ function Tooltip({
1894
2310
  disabled = false
1895
2311
  }) {
1896
2312
  const [visible, setVisible] = useState(false);
2313
+ const triggerRef = useRef(null);
2314
+ const tooltipRef = useRef(null);
2315
+ const enterTimer = useRef(null);
2316
+ const leaveTimer = useRef(null);
1897
2317
  const isControlled = controlledOpen !== void 0;
1898
2318
  const show = isControlled ? controlledOpen : visible;
1899
- const enterTimer = React8.useRef(null);
1900
- const leaveTimer = React8.useRef(null);
2319
+ const positionAndShow = useCallback(() => {
2320
+ const tooltip = tooltipRef.current;
2321
+ const trigger2 = triggerRef.current;
2322
+ if (!tooltip || !trigger2) return;
2323
+ const pos = getPosition(
2324
+ trigger2.getBoundingClientRect(),
2325
+ tooltip,
2326
+ placement
2327
+ );
2328
+ tooltip.style.top = `${pos.top}px`;
2329
+ tooltip.style.left = `${pos.left}px`;
2330
+ tooltip.style.opacity = "1";
2331
+ }, [placement]);
2332
+ useEffect(() => {
2333
+ if (!show) {
2334
+ const tooltip = tooltipRef.current;
2335
+ if (tooltip) tooltip.style.opacity = "0";
2336
+ return;
2337
+ }
2338
+ const id = requestAnimationFrame(positionAndShow);
2339
+ return () => cancelAnimationFrame(id);
2340
+ }, [show, positionAndShow]);
1901
2341
  const handleEnter = () => {
1902
2342
  if (disabled || isControlled) return;
1903
2343
  if (leaveTimer.current) clearTimeout(leaveTimer.current);
@@ -1908,44 +2348,76 @@ function Tooltip({
1908
2348
  if (enterTimer.current) clearTimeout(enterTimer.current);
1909
2349
  leaveTimer.current = setTimeout(() => setVisible(false), leaveDelay);
1910
2350
  };
2351
+ useEffect(() => {
2352
+ return () => {
2353
+ if (enterTimer.current) clearTimeout(enterTimer.current);
2354
+ if (leaveTimer.current) clearTimeout(leaveTimer.current);
2355
+ };
2356
+ }, []);
2357
+ if (!React10.isValidElement(children)) return children;
1911
2358
  const side = placement.split("-")[0];
1912
- return /* @__PURE__ */ jsxs(
1913
- "div",
2359
+ const trigger = React10.cloneElement(
2360
+ children,
1914
2361
  {
1915
- className: "relative inline-flex",
1916
- onMouseEnter: handleEnter,
1917
- onMouseLeave: handleLeave,
1918
- onFocus: handleEnter,
1919
- onBlur: handleLeave,
1920
- children: [
1921
- children,
1922
- show && title && !disabled && /* @__PURE__ */ jsxs(
1923
- "div",
1924
- {
1925
- role: "tooltip",
1926
- className: [
1927
- "absolute z-[9999] max-w-[300px] px-2 py-1.5 whitespace-nowrap",
1928
- "bg-gray-600/80 text-white text-xs rounded shadow-md pointer-events-none",
1929
- "animate-in fade-in-0 zoom-in-95 duration-100",
1930
- placementClass[placement],
1931
- className || ""
1932
- ].join(" "),
1933
- children: [
1934
- arrow && /* @__PURE__ */ jsx(
1935
- "span",
1936
- {
1937
- className: ["absolute w-0 h-0 border-4", arrowClass[side]].join(
1938
- " "
1939
- )
1940
- }
1941
- ),
1942
- title
1943
- ]
1944
- }
1945
- )
1946
- ]
2362
+ ref: triggerRef,
2363
+ onMouseEnter: (e) => {
2364
+ var _a, _b;
2365
+ handleEnter();
2366
+ (_b = (_a = children.props).onMouseEnter) == null ? void 0 : _b.call(_a, e);
2367
+ },
2368
+ onMouseLeave: (e) => {
2369
+ var _a, _b;
2370
+ handleLeave();
2371
+ (_b = (_a = children.props).onMouseLeave) == null ? void 0 : _b.call(_a, e);
2372
+ },
2373
+ onFocus: (e) => {
2374
+ var _a, _b;
2375
+ handleEnter();
2376
+ (_b = (_a = children.props).onFocus) == null ? void 0 : _b.call(_a, e);
2377
+ },
2378
+ onBlur: (e) => {
2379
+ var _a, _b;
2380
+ handleLeave();
2381
+ (_b = (_a = children.props).onBlur) == null ? void 0 : _b.call(_a, e);
2382
+ }
1947
2383
  }
1948
2384
  );
2385
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2386
+ trigger,
2387
+ createPortal(
2388
+ title ? /* @__PURE__ */ jsxs(
2389
+ "div",
2390
+ {
2391
+ ref: tooltipRef,
2392
+ role: "tooltip",
2393
+ style: {
2394
+ position: "fixed",
2395
+ top: -9999,
2396
+ left: -9999,
2397
+ opacity: 0,
2398
+ transition: "opacity 100ms ease"
2399
+ },
2400
+ className: [
2401
+ "z-[99] max-w-[300px] px-2 py-1.5",
2402
+ "bg-gray-600/80 text-white text-xs rounded shadow-md pointer-events-none",
2403
+ className || ""
2404
+ ].join(" "),
2405
+ children: [
2406
+ arrow && /* @__PURE__ */ jsx(
2407
+ "span",
2408
+ {
2409
+ className: ["absolute w-0 h-0 border-4", arrowClass[side]].join(
2410
+ " "
2411
+ )
2412
+ }
2413
+ ),
2414
+ title
2415
+ ]
2416
+ }
2417
+ ) : null,
2418
+ document.body
2419
+ )
2420
+ ] });
1949
2421
  }
1950
2422
  function useLocalStorage(key, initialValue) {
1951
2423
  const [storedValue, setStoredValue] = useState(() => {
@@ -1981,4 +2453,4 @@ function useLocalStorage(key, initialValue) {
1981
2453
  return [storedValue, setValue, remove];
1982
2454
  }
1983
2455
 
1984
- export { Accordion, AccordionDetails, AccordionSummary, AutoComplete, Breadcrumb, ButtonLoader, CopyId, CustomAnchor, CustomInput, Drawer, FilterDrawer, InputTitleWithRequired, Modal, MonthYearPicker, Pagination, ReadMore, SearchBar, StagingAlert, Tab, Tabs, Tooltip, cn, handleAllyProps, handleCopyTextToClipboard, useLocalStorage };
2456
+ export { Accordion, AccordionDetails, AccordionSummary, AutoComplete, Breadcrumb, ButtonLoader, Chip, CopyId, CustomAnchor, CustomInput, Drawer, FilterDrawer, InputTitleWithRequired, Menu, MenuDivider, MenuItem, Modal, MonthYearPicker, Pagination, ReadMore, SearchBar, Select, SelectOption, StagingAlert, Switch, Tab, Tabs, Tooltip, cn, handleAllyProps, handleCopyTextToClipboard, useLocalStorage };