@underverse-ui/underverse 0.2.28 → 0.2.30

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.js CHANGED
@@ -1120,9 +1120,21 @@ var TagInput = forwardRef4(
1120
1120
  e.preventDefault();
1121
1121
  if (e.ctrlKey || e.metaKey) {
1122
1122
  triggerSearch();
1123
- } else {
1124
- addTag(inputValue);
1123
+ return;
1124
+ }
1125
+ if (e.shiftKey) {
1126
+ const tagsToAdd = inputValue.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0 && !value.includes(t));
1127
+ if (tagsToAdd.length > 0) {
1128
+ const availableSlots = maxTags !== void 0 ? maxTags - value.length : Infinity;
1129
+ if (availableSlots > 0) {
1130
+ const tagsToInsert = tagsToAdd.slice(0, availableSlots);
1131
+ onChange([...value, ...tagsToInsert]);
1132
+ setInputValue("");
1133
+ }
1134
+ }
1135
+ return;
1125
1136
  }
1137
+ addTag(inputValue);
1126
1138
  } else if (e.key === "Backspace" && inputValue === "" && value.length > 0) {
1127
1139
  removeTag(value.length - 1);
1128
1140
  }
@@ -2370,6 +2382,8 @@ var Modal = ({
2370
2382
  const [isMounted, setIsMounted] = React10.useState(false);
2371
2383
  const [isVisible, setIsVisible] = React10.useState(false);
2372
2384
  const [isAnimating, setIsAnimating] = React10.useState(true);
2385
+ const mouseDownTarget = React10.useRef(null);
2386
+ const modalContentRef = React10.useRef(null);
2373
2387
  React10.useEffect(() => {
2374
2388
  setIsMounted(true);
2375
2389
  return () => setIsMounted(false);
@@ -2409,74 +2423,90 @@ var Modal = ({
2409
2423
  document.body.style.overflow = "unset";
2410
2424
  };
2411
2425
  }, [isOpen]);
2412
- const handleOverlayClick = (event) => {
2413
- if (closeOnOverlayClick) {
2426
+ const handleOverlayMouseDown = (event) => {
2427
+ mouseDownTarget.current = event.target;
2428
+ };
2429
+ const handleOverlayMouseUp = (event) => {
2430
+ const modalContent2 = modalContentRef.current;
2431
+ const mouseDownOutside = modalContent2 && !modalContent2.contains(mouseDownTarget.current);
2432
+ const mouseUpOutside = modalContent2 && !modalContent2.contains(event.target);
2433
+ if (closeOnOverlayClick && mouseDownOutside && mouseUpOutside) {
2414
2434
  onClose();
2415
2435
  }
2436
+ mouseDownTarget.current = null;
2416
2437
  };
2417
2438
  if (!isMounted || !isOpen && !isVisible) {
2418
2439
  return null;
2419
2440
  }
2420
2441
  const maxWidthClass = width ? "max-w-none" : fullWidth ? "max-w-full" : sizeStyles3[size];
2421
- const modalContent = /* @__PURE__ */ jsxs12("div", { className: cn("fixed inset-0 z-9999 flex items-center justify-center", overlayClassName), onClick: handleOverlayClick, children: [
2422
- /* @__PURE__ */ jsx14(
2423
- "div",
2424
- {
2425
- className: "absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out",
2426
- style: {
2427
- opacity: isOpen && !isAnimating ? 1 : 0
2428
- }
2429
- }
2430
- ),
2431
- /* @__PURE__ */ jsxs12(
2432
- "div",
2433
- {
2434
- className: cn(
2435
- "relative w-full rounded-lg bg-card text-card-foreground shadow-xl",
2436
- "transition-all duration-200 ease-out",
2437
- maxWidthClass,
2438
- fullWidth && "mx-0",
2439
- className
2442
+ const modalContent = /* @__PURE__ */ jsxs12(
2443
+ "div",
2444
+ {
2445
+ className: cn("fixed inset-0 z-9999 flex items-center justify-center", overlayClassName),
2446
+ onMouseDown: handleOverlayMouseDown,
2447
+ onMouseUp: handleOverlayMouseUp,
2448
+ children: [
2449
+ /* @__PURE__ */ jsx14(
2450
+ "div",
2451
+ {
2452
+ className: "absolute inset-0 bg-background/80 backdrop-blur-sm transition-opacity duration-200 ease-out",
2453
+ style: {
2454
+ opacity: isOpen && !isAnimating ? 1 : 0
2455
+ }
2456
+ }
2440
2457
  ),
2441
- style: {
2442
- opacity: isOpen && !isAnimating ? 1 : 0,
2443
- transform: isOpen && !isAnimating ? "scale(1)" : "scale(0.9)",
2444
- // Thêm dòng này để tạo hiệu ứng nảy
2445
- transition: "all 300ms cubic-bezier(0.34, 1.76, 0.64, 1)",
2446
- width,
2447
- height
2448
- },
2449
- onClick: (e) => e.stopPropagation(),
2450
- children: [
2451
- (title || description || showCloseButton) && /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between p-6 pb-0", children: [
2452
- /* @__PURE__ */ jsxs12("div", { className: "space-y-1.5", children: [
2453
- title && /* @__PURE__ */ jsx14("h2", { className: "text-lg font-semibold leading-none tracking-tight", children: title }),
2454
- description && /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: description })
2455
- ] }),
2456
- showCloseButton && /* @__PURE__ */ jsx14(
2457
- "button",
2458
- {
2459
- onClick: onClose,
2460
- className: cn(
2461
- "rounded-sm opacity-70 ring-offset-background transition-opacity",
2462
- "hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
2463
- "disabled:pointer-events-none "
2464
- ),
2465
- children: /* @__PURE__ */ jsx14(X4, { className: "h-4 w-4 cursor-pointer" })
2466
- }
2467
- )
2468
- ] }),
2469
- /* @__PURE__ */ jsx14("div", { className: cn("p-6", noPadding && "p-0", contentClassName), children })
2470
- ]
2471
- }
2472
- )
2473
- ] });
2458
+ /* @__PURE__ */ jsxs12(
2459
+ "div",
2460
+ {
2461
+ ref: modalContentRef,
2462
+ className: cn(
2463
+ "relative w-full rounded-lg bg-card text-card-foreground shadow-xl",
2464
+ "transition-all duration-200 ease-out",
2465
+ maxWidthClass,
2466
+ fullWidth && "mx-0",
2467
+ className
2468
+ ),
2469
+ style: {
2470
+ opacity: isOpen && !isAnimating ? 1 : 0,
2471
+ transform: isOpen && !isAnimating ? "scale(1)" : "scale(0.9)",
2472
+ // Thêm dòng này để tạo hiệu ứng nảy
2473
+ transition: "all 300ms cubic-bezier(0.34, 1.76, 0.64, 1)",
2474
+ width,
2475
+ height
2476
+ },
2477
+ onClick: (e) => e.stopPropagation(),
2478
+ children: [
2479
+ (title || description || showCloseButton) && /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between p-6 pb-0", children: [
2480
+ /* @__PURE__ */ jsxs12("div", { className: "space-y-1.5", children: [
2481
+ title && /* @__PURE__ */ jsx14("h2", { className: "text-lg font-semibold leading-none tracking-tight", children: title }),
2482
+ description && /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: description })
2483
+ ] }),
2484
+ showCloseButton && /* @__PURE__ */ jsx14(
2485
+ "button",
2486
+ {
2487
+ onClick: onClose,
2488
+ className: cn(
2489
+ "rounded-sm opacity-70 ring-offset-background transition-opacity",
2490
+ "hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
2491
+ "disabled:pointer-events-none "
2492
+ ),
2493
+ children: /* @__PURE__ */ jsx14(X4, { className: "h-4 w-4 cursor-pointer" })
2494
+ }
2495
+ )
2496
+ ] }),
2497
+ /* @__PURE__ */ jsx14("div", { className: cn("p-6", noPadding && "p-0", contentClassName), children })
2498
+ ]
2499
+ }
2500
+ )
2501
+ ]
2502
+ }
2503
+ );
2474
2504
  return typeof window !== "undefined" ? createPortal(modalContent, document.body) : null;
2475
2505
  };
2476
2506
  var Modal_default = Modal;
2477
2507
 
2478
2508
  // ../../components/ui/Toast.tsx
2479
- import { createContext, useContext, useState as useState9, useCallback as useCallback2, useEffect as useEffect2, useRef as useRef3 } from "react";
2509
+ import { createContext, useContext, useState as useState9, useCallback as useCallback2, useEffect as useEffect2, useRef as useRef4 } from "react";
2480
2510
  import { X as X5, CheckCircle as CheckCircle2, AlertCircle as AlertCircle2, Info, AlertTriangle as AlertTriangle2 } from "lucide-react";
2481
2511
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2482
2512
  var ToastContext = createContext(void 0);
@@ -2489,7 +2519,7 @@ var useToast = () => {
2489
2519
  };
2490
2520
  var ToastProvider = ({ children, position = "top-right", maxToasts = 5 }) => {
2491
2521
  const [toasts, setToasts] = useState9([]);
2492
- const idRef = useRef3(0);
2522
+ const idRef = useRef4(0);
2493
2523
  const removeToast = useCallback2((id) => {
2494
2524
  setToasts((prev) => prev.filter((toast) => toast.id !== id));
2495
2525
  }, []);
@@ -7750,7 +7780,7 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
7750
7780
  }
7751
7781
 
7752
7782
  // ../../components/ui/ImageUpload.tsx
7753
- import { useState as useState26, useRef as useRef11, useCallback as useCallback9 } from "react";
7783
+ import { useState as useState26, useRef as useRef12, useCallback as useCallback9 } from "react";
7754
7784
  import { Upload, X as X10, Image as ImageIcon, Loader2 as Loader25, Check as Check7 } from "lucide-react";
7755
7785
  import { useTranslations as useTranslations6 } from "next-intl";
7756
7786
  import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
@@ -7772,7 +7802,7 @@ function ImageUpload({
7772
7802
  const [isDragging, setIsDragging] = useState26(false);
7773
7803
  const [uploading, setUploading] = useState26(false);
7774
7804
  const [uploadedImages, setUploadedImages] = useState26([]);
7775
- const fileInputRef = useRef11(null);
7805
+ const fileInputRef = useRef12(null);
7776
7806
  const { addToast } = useToast();
7777
7807
  const t = useTranslations6("OCR.imageUpload");
7778
7808
  const previewSizes = {
@@ -10911,7 +10941,7 @@ function AccessDenied({
10911
10941
 
10912
10942
  // ../../components/ui/ThemeToggleHeadless.tsx
10913
10943
  import { Moon, Sun, Monitor } from "lucide-react";
10914
- import { useEffect as useEffect20, useRef as useRef13, useState as useState33 } from "react";
10944
+ import { useEffect as useEffect20, useRef as useRef14, useState as useState33 } from "react";
10915
10945
  import { createPortal as createPortal10 } from "react-dom";
10916
10946
  import { Fragment as Fragment18, jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
10917
10947
  function ThemeToggleHeadless({
@@ -10922,7 +10952,7 @@ function ThemeToggleHeadless({
10922
10952
  }) {
10923
10953
  const [isOpen, setIsOpen] = useState33(false);
10924
10954
  const [mounted, setMounted] = useState33(false);
10925
- const triggerRef = useRef13(null);
10955
+ const triggerRef = useRef14(null);
10926
10956
  const [dropdownPosition, setDropdownPosition] = useState33(null);
10927
10957
  useEffect20(() => setMounted(true), []);
10928
10958
  const themes = [
@@ -11013,7 +11043,7 @@ function ThemeToggleHeadless({
11013
11043
  }
11014
11044
 
11015
11045
  // ../../components/ui/LanguageSwitcherHeadless.tsx
11016
- import { useRef as useRef14, useState as useState34 } from "react";
11046
+ import { useRef as useRef15, useState as useState34 } from "react";
11017
11047
  import { createPortal as createPortal11 } from "react-dom";
11018
11048
  import { Globe } from "lucide-react";
11019
11049
  import { Fragment as Fragment19, jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
@@ -11026,7 +11056,7 @@ function LanguageSwitcherHeadless({
11026
11056
  }) {
11027
11057
  const [isOpen, setIsOpen] = useState34(false);
11028
11058
  const [dropdownPosition, setDropdownPosition] = useState34(null);
11029
- const triggerButtonRef = useRef14(null);
11059
+ const triggerButtonRef = useRef15(null);
11030
11060
  const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
11031
11061
  const calculatePosition = () => {
11032
11062
  const rect = triggerButtonRef.current?.getBoundingClientRect();