@underverse-ui/underverse 1.0.59 → 1.0.60

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
@@ -3503,11 +3503,11 @@ var ToastProvider = ({ children, position = "top-right", maxToasts = 5 }) => {
3503
3503
  ] });
3504
3504
  };
3505
3505
  var ToastComponent = ({ toast, onRemove }) => {
3506
- const [isVisible, setIsVisible] = useState7(false);
3506
+ const [isVisible, setIsVisible] = useState7(true);
3507
3507
  const [progress, setProgress] = useState7(100);
3508
3508
  const [paused, setPaused] = useState7(false);
3509
3509
  const total = toast.duration && toast.duration > 0 ? toast.duration : 5e3;
3510
- const endTsRef = useRef4(Date.now() + total);
3510
+ const endTsRef = useRef4(0);
3511
3511
  const remainingRef = useRef4(total);
3512
3512
  const pausedRef = useRef4(false);
3513
3513
  const handleRemove = useCallback3(() => {
@@ -3515,7 +3515,6 @@ var ToastComponent = ({ toast, onRemove }) => {
3515
3515
  setTimeout(() => onRemove(toast.id), 150);
3516
3516
  }, [onRemove, toast.id]);
3517
3517
  useEffect2(() => {
3518
- setIsVisible(true);
3519
3518
  if (toast.duration === 0) return;
3520
3519
  remainingRef.current = total;
3521
3520
  endTsRef.current = Date.now() + total;
@@ -3641,6 +3640,18 @@ var Toast_default = ToastProvider;
3641
3640
  // src/components/Tooltip.tsx
3642
3641
  import * as React14 from "react";
3643
3642
  import { createPortal as createPortal2 } from "react-dom";
3643
+
3644
+ // src/hooks/useHydrated.ts
3645
+ import { useSyncExternalStore } from "react";
3646
+ var subscribe = () => () => {
3647
+ };
3648
+ var getSnapshot = () => true;
3649
+ var getServerSnapshot = () => false;
3650
+ function useHydrated() {
3651
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
3652
+ }
3653
+
3654
+ // src/components/Tooltip.tsx
3644
3655
  import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
3645
3656
  var variantStyles3 = {
3646
3657
  default: "bg-popover text-popover-foreground border-border/50",
@@ -3649,17 +3660,6 @@ var variantStyles3 = {
3649
3660
  error: "bg-destructive text-destructive-foreground border-destructive/20",
3650
3661
  success: "bg-success text-success-foreground border-success/20"
3651
3662
  };
3652
- function assignRef(ref, value) {
3653
- if (!ref) return;
3654
- if (typeof ref === "function") {
3655
- ref(value);
3656
- return;
3657
- }
3658
- try {
3659
- ref.current = value;
3660
- } catch {
3661
- }
3662
- }
3663
3663
  var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
3664
3664
  function getTransformOrigin(side) {
3665
3665
  switch (side) {
@@ -3715,19 +3715,24 @@ var Tooltip = ({
3715
3715
  variant = "default"
3716
3716
  }) => {
3717
3717
  const [isOpen, setIsOpen] = React14.useState(false);
3718
- const [isMounted, setIsMounted] = React14.useState(false);
3718
+ const isMounted = useHydrated();
3719
3719
  const triggerRef = React14.useRef(null);
3720
3720
  const positionerRef = React14.useRef(null);
3721
3721
  const panelRef = React14.useRef(null);
3722
3722
  const timeoutRef = React14.useRef(void 0);
3723
3723
  const lastAppliedRef = React14.useRef(null);
3724
- React14.useEffect(() => {
3725
- setIsMounted(true);
3726
- }, []);
3724
+ const triggerSelector = React14.useId();
3727
3725
  const delayOpen = typeof delay === "object" ? delay.open || 700 : delay;
3728
3726
  const delayClose = typeof delay === "object" ? delay.close || 300 : delay;
3729
3727
  const offset = 8;
3730
3728
  const padding = 8;
3729
+ React14.useLayoutEffect(() => {
3730
+ if (typeof document === "undefined") return;
3731
+ const triggerEl = document.querySelector(`[data-underverse-tooltip-trigger="${triggerSelector}"]`);
3732
+ if (triggerEl) {
3733
+ triggerRef.current = triggerEl;
3734
+ }
3735
+ }, [children, triggerSelector]);
3731
3736
  const updatePosition = React14.useCallback(() => {
3732
3737
  const triggerEl = triggerRef.current;
3733
3738
  const positionerEl = positionerRef.current;
@@ -3827,28 +3832,36 @@ var Tooltip = ({
3827
3832
  return children;
3828
3833
  }
3829
3834
  return /* @__PURE__ */ jsxs13(Fragment3, { children: [
3830
- React14.cloneElement(children, {
3831
- ref: (node) => {
3832
- triggerRef.current = node;
3833
- assignRef(children.props?.ref, node);
3834
- },
3835
- onMouseEnter: (e) => {
3836
- handleMouseEnter();
3837
- if (typeof children.props?.onMouseEnter === "function") children.props.onMouseEnter(e);
3838
- },
3839
- onMouseLeave: (e) => {
3840
- handleMouseLeave();
3841
- if (typeof children.props?.onMouseLeave === "function") children.props.onMouseLeave(e);
3842
- },
3843
- onFocus: (e) => {
3844
- handleFocus();
3845
- if (typeof children.props?.onFocus === "function") children.props.onFocus(e);
3846
- },
3847
- onBlur: (e) => {
3848
- handleBlur();
3849
- if (typeof children.props?.onBlur === "function") children.props.onBlur(e);
3850
- }
3851
- }),
3835
+ (() => {
3836
+ const TriggerComponent = children.type;
3837
+ const triggerProps = children.props;
3838
+ return /* @__PURE__ */ jsx17(
3839
+ TriggerComponent,
3840
+ {
3841
+ ...triggerProps,
3842
+ "data-underverse-tooltip-trigger": triggerSelector,
3843
+ onMouseEnter: (e) => {
3844
+ triggerRef.current = e.currentTarget;
3845
+ handleMouseEnter();
3846
+ if (typeof triggerProps.onMouseEnter === "function") triggerProps.onMouseEnter(e);
3847
+ },
3848
+ onMouseLeave: (e) => {
3849
+ triggerRef.current = e.currentTarget;
3850
+ handleMouseLeave();
3851
+ if (typeof triggerProps.onMouseLeave === "function") triggerProps.onMouseLeave(e);
3852
+ },
3853
+ onFocus: (e) => {
3854
+ triggerRef.current = e.currentTarget;
3855
+ handleFocus();
3856
+ if (typeof triggerProps.onFocus === "function") triggerProps.onFocus(e);
3857
+ },
3858
+ onBlur: (e) => {
3859
+ handleBlur();
3860
+ if (typeof triggerProps.onBlur === "function") triggerProps.onBlur(e);
3861
+ }
3862
+ }
3863
+ );
3864
+ })(),
3852
3865
  isMounted && isOpen && createPortal2(
3853
3866
  /* @__PURE__ */ jsx17(
3854
3867
  "div",
@@ -4086,17 +4099,6 @@ function getAnimationStyles() {
4086
4099
 
4087
4100
  // src/components/Popover.tsx
4088
4101
  import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4089
- function assignRef2(ref, value) {
4090
- if (!ref) return;
4091
- if (typeof ref === "function") {
4092
- ref(value);
4093
- return;
4094
- }
4095
- try {
4096
- ref.current = value;
4097
- } catch {
4098
- }
4099
- }
4100
4102
  function getTransformOrigin2(side, align) {
4101
4103
  if (side === "top") return `${align === "end" ? "right" : "left"} bottom`;
4102
4104
  if (side === "bottom") return `${align === "end" ? "right" : "left"} top`;
@@ -4208,7 +4210,15 @@ var Popover = ({
4208
4210
  );
4209
4211
  const offset = 4;
4210
4212
  const padding = 8;
4213
+ const triggerSelector = React15.useId();
4211
4214
  const initialPlacement = React15.useMemo(() => normalizePlacement(placement), [placement]);
4215
+ React15.useLayoutEffect(() => {
4216
+ if (typeof document === "undefined") return;
4217
+ const triggerEl = document.querySelector(`[data-underverse-popover-trigger="${triggerSelector}"]`);
4218
+ if (triggerEl) {
4219
+ triggerRef.current = triggerEl;
4220
+ }
4221
+ }, [triggerSelector, trigger]);
4212
4222
  const updatePosition = React15.useCallback(() => {
4213
4223
  const triggerEl = triggerRef.current;
4214
4224
  const positionerEl = positionerRef.current;
@@ -4386,27 +4396,36 @@ var Popover = ({
4386
4396
  ) : null;
4387
4397
  return /* @__PURE__ */ jsxs14(Fragment4, { children: [
4388
4398
  (() => {
4389
- const triggerEl = trigger;
4390
- return React15.cloneElement(triggerEl, {
4391
- ref: (node) => {
4392
- triggerRef.current = node;
4393
- assignRef2(triggerEl.props?.ref, node);
4394
- },
4395
- onClick: (e) => {
4396
- e.preventDefault();
4397
- e.stopPropagation();
4398
- handleTriggerClick();
4399
- if (triggerEl.props && typeof triggerEl.props.onClick === "function") {
4400
- triggerEl.props.onClick(e);
4401
- }
4402
- },
4403
- "aria-expanded": isOpen,
4404
- "aria-haspopup": triggerEl.props?.["aria-haspopup"] ?? "dialog",
4405
- className: cn(
4406
- triggerEl.props?.className,
4407
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
4408
- )
4409
- });
4399
+ const TriggerComponent = trigger.type;
4400
+ const triggerProps = trigger.props;
4401
+ return /* @__PURE__ */ jsx18(
4402
+ TriggerComponent,
4403
+ {
4404
+ ...triggerProps,
4405
+ "data-underverse-popover-trigger": triggerSelector,
4406
+ onClick: (e) => {
4407
+ triggerRef.current = e.currentTarget;
4408
+ e.preventDefault();
4409
+ e.stopPropagation();
4410
+ handleTriggerClick();
4411
+ if (typeof triggerProps.onClick === "function") {
4412
+ triggerProps.onClick(e);
4413
+ }
4414
+ },
4415
+ onFocus: (e) => {
4416
+ triggerRef.current = e.currentTarget;
4417
+ if (typeof triggerProps.onFocus === "function") {
4418
+ triggerProps.onFocus(e);
4419
+ }
4420
+ },
4421
+ "aria-expanded": isOpen,
4422
+ "aria-haspopup": triggerProps["aria-haspopup"] ?? "dialog",
4423
+ className: cn(
4424
+ triggerProps.className,
4425
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
4426
+ )
4427
+ }
4428
+ );
4410
4429
  })(),
4411
4430
  popoverContent
4412
4431
  ] });
@@ -5165,6 +5184,20 @@ var VerticalTabs = ({ sidebarWidth = "w-48", className, ...props }) => {
5165
5184
  // src/components/DropdownMenu.tsx
5166
5185
  import React20, { useState as useState15 } from "react";
5167
5186
  import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
5187
+ function useResettingIndex(resetToken) {
5188
+ const [state, setState] = React20.useState({ resetToken, index: -1 });
5189
+ const activeIndex = Object.is(state.resetToken, resetToken) ? state.index : -1;
5190
+ const setActiveIndex = React20.useCallback((nextIndex) => {
5191
+ setState((prev) => {
5192
+ const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : -1;
5193
+ return {
5194
+ resetToken,
5195
+ index: typeof nextIndex === "function" ? nextIndex(prevIndex) : nextIndex
5196
+ };
5197
+ });
5198
+ }, [resetToken]);
5199
+ return [activeIndex, setActiveIndex];
5200
+ }
5168
5201
  var DropdownMenu = ({
5169
5202
  trigger,
5170
5203
  children,
@@ -5178,16 +5211,13 @@ var DropdownMenu = ({
5178
5211
  items
5179
5212
  }) => {
5180
5213
  const [internalOpen, setInternalOpen] = useState15(false);
5214
+ const open = isOpen !== void 0 ? isOpen : internalOpen;
5215
+ const setOpen = onOpenChange || setInternalOpen;
5181
5216
  const triggerRef = React20.useRef(null);
5182
5217
  const menuRef = React20.useRef(null);
5183
5218
  const itemsRef = React20.useRef([]);
5184
- const [activeIndex, setActiveIndex] = useState15(-1);
5219
+ const [activeIndex, setActiveIndex] = useResettingIndex(open);
5185
5220
  useShadCNAnimations();
5186
- const open = isOpen !== void 0 ? isOpen : internalOpen;
5187
- const setOpen = onOpenChange || setInternalOpen;
5188
- React20.useEffect(() => {
5189
- if (open) setActiveIndex(-1);
5190
- }, [open]);
5191
5221
  React20.useEffect(() => {
5192
5222
  if (!open) return;
5193
5223
  const handleKeyNav = (e) => {
@@ -5224,7 +5254,7 @@ var DropdownMenu = ({
5224
5254
  return () => {
5225
5255
  document.removeEventListener("keydown", handleKeyNav);
5226
5256
  };
5227
- }, [open, activeIndex]);
5257
+ }, [open, activeIndex, setActiveIndex]);
5228
5258
  const handleItemClick = (itemOnClick) => {
5229
5259
  itemOnClick();
5230
5260
  if (closeOnSelect) {
@@ -5262,36 +5292,48 @@ var DropdownMenu = ({
5262
5292
  index
5263
5293
  );
5264
5294
  }) : children });
5265
- const enhancedTrigger = React20.cloneElement(trigger, {
5266
- ref: triggerRef,
5267
- "aria-haspopup": "menu",
5268
- "aria-expanded": open,
5269
- onKeyDown: (e) => {
5270
- if (disabled) return;
5271
- if (e.key === "ArrowDown") {
5272
- e.preventDefault();
5273
- setOpen(true);
5274
- requestAnimationFrame(() => itemsRef.current.find((el) => el && !el.disabled)?.focus());
5275
- } else if (e.key === "ArrowUp") {
5276
- e.preventDefault();
5277
- setOpen(true);
5278
- requestAnimationFrame(() => {
5279
- const enabled = itemsRef.current.filter((el) => el && !el.disabled);
5280
- enabled[enabled.length - 1]?.focus();
5281
- });
5282
- } else if (e.key === "Escape") {
5283
- e.preventDefault();
5284
- setOpen(false);
5285
- }
5286
- if (typeof trigger.props?.onKeyDown === "function") {
5287
- trigger.props.onKeyDown(e);
5288
- }
5289
- },
5290
- className: cn(
5291
- trigger.props?.className,
5292
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5293
- )
5294
- });
5295
+ const TriggerComponent = trigger.type;
5296
+ const triggerProps = trigger.props;
5297
+ const enhancedTrigger = /* @__PURE__ */ jsx24(
5298
+ TriggerComponent,
5299
+ {
5300
+ ...triggerProps,
5301
+ "aria-haspopup": "menu",
5302
+ "aria-expanded": open,
5303
+ onKeyDown: (e) => {
5304
+ triggerRef.current = e.currentTarget;
5305
+ if (disabled) return;
5306
+ if (e.key === "ArrowDown") {
5307
+ e.preventDefault();
5308
+ setOpen(true);
5309
+ requestAnimationFrame(() => itemsRef.current.find((el) => el && !el.disabled)?.focus());
5310
+ } else if (e.key === "ArrowUp") {
5311
+ e.preventDefault();
5312
+ setOpen(true);
5313
+ requestAnimationFrame(() => {
5314
+ const enabled = itemsRef.current.filter((el) => el && !el.disabled);
5315
+ enabled[enabled.length - 1]?.focus();
5316
+ });
5317
+ } else if (e.key === "Escape") {
5318
+ e.preventDefault();
5319
+ setOpen(false);
5320
+ }
5321
+ if (typeof triggerProps.onKeyDown === "function") {
5322
+ triggerProps.onKeyDown(e);
5323
+ }
5324
+ },
5325
+ onFocus: (e) => {
5326
+ triggerRef.current = e.currentTarget;
5327
+ if (typeof triggerProps.onFocus === "function") {
5328
+ triggerProps.onFocus(e);
5329
+ }
5330
+ },
5331
+ className: cn(
5332
+ triggerProps.className,
5333
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5334
+ )
5335
+ }
5336
+ );
5295
5337
  return /* @__PURE__ */ jsx24(
5296
5338
  Popover,
5297
5339
  {
@@ -5376,7 +5418,7 @@ import { ChevronLeft, ChevronRight as ChevronRight2, ChevronsLeft, ChevronsRight
5376
5418
 
5377
5419
  // src/components/Combobox.tsx
5378
5420
  import * as React22 from "react";
5379
- import { useId as useId3 } from "react";
5421
+ import { useId as useId5 } from "react";
5380
5422
  import { ChevronDown, Search as Search3, SearchX, Check as Check3, X as X8 } from "lucide-react";
5381
5423
 
5382
5424
  // src/components/OverlayScrollbarProvider.tsx
@@ -5659,7 +5701,7 @@ var Combobox = ({
5659
5701
  const inputRef = React22.useRef(null);
5660
5702
  const optionsViewportRef = React22.useRef(null);
5661
5703
  useOverlayScrollbarTarget(optionsViewportRef, { enabled: useOverlayScrollbar });
5662
- const autoId = useId3();
5704
+ const autoId = useId5();
5663
5705
  const resolvedId = id ? String(id) : `combobox-${autoId}`;
5664
5706
  const labelId = label ? `${resolvedId}-label` : void 0;
5665
5707
  const enableSearch = options.length > 10;
@@ -6687,7 +6729,7 @@ function formatDateSmart(date, locale = "en") {
6687
6729
  // src/components/DatePicker.tsx
6688
6730
  import { Calendar, ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight3, Sparkles as Sparkles2, X as XIcon } from "lucide-react";
6689
6731
  import * as React26 from "react";
6690
- import { useId as useId4 } from "react";
6732
+ import { useId as useId6 } from "react";
6691
6733
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
6692
6734
  var DatePicker = ({
6693
6735
  id,
@@ -7086,7 +7128,7 @@ var DatePicker = ({
7086
7128
  )
7087
7129
  ] })
7088
7130
  ] });
7089
- const autoId = useId4();
7131
+ const autoId = useId6();
7090
7132
  const resolvedId = id ? String(id) : `datepicker-${autoId}`;
7091
7133
  const labelId = label ? `${resolvedId}-label` : void 0;
7092
7134
  const labelSize = sizeStyles8[size].label;
@@ -7773,10 +7815,8 @@ function WheelColumn({
7773
7815
  };
7774
7816
  const currentVirtual = React27.useMemo(() => {
7775
7817
  if (!loop || items.length <= 0) return valueIndex;
7776
- const fallback = baseOffset + valueIndex;
7777
- const from = lastVirtualIndexRef.current ?? fallback;
7778
- return getNearestVirtualIndex(valueIndex, from);
7779
- }, [baseOffset, getNearestVirtualIndex, items.length, loop, valueIndex]);
7818
+ return baseOffset + valueIndex;
7819
+ }, [baseOffset, items.length, loop, valueIndex]);
7780
7820
  const commitFromScrollTop = React27.useCallback(
7781
7821
  (behavior) => {
7782
7822
  const el = scrollRef.current;
@@ -9213,10 +9253,8 @@ function WheelColumn2({
9213
9253
  };
9214
9254
  const currentVirtual = React29.useMemo(() => {
9215
9255
  if (!loop || items.length <= 0) return valueIndex;
9216
- const fallback = baseOffset + valueIndex;
9217
- const from = lastVirtualIndexRef.current ?? fallback;
9218
- return getNearestVirtualIndex(valueIndex, from);
9219
- }, [baseOffset, getNearestVirtualIndex, items.length, loop, valueIndex]);
9256
+ return baseOffset + valueIndex;
9257
+ }, [baseOffset, items.length, loop, valueIndex]);
9220
9258
  const commitFromScrollTop = React29.useCallback(
9221
9259
  (behavior) => {
9222
9260
  const el = scrollRef.current;
@@ -13276,7 +13314,7 @@ function CalendarTimeline({
13276
13314
 
13277
13315
  // src/components/MultiCombobox.tsx
13278
13316
  import * as React37 from "react";
13279
- import { useId as useId5 } from "react";
13317
+ import { useId as useId7 } from "react";
13280
13318
  import { ChevronDown as ChevronDown4, Search as Search4, Check as Check6, SearchX as SearchX2, Loader2 as Loader24, X as X12, Sparkles as Sparkles3 } from "lucide-react";
13281
13319
  import { Fragment as Fragment13, jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
13282
13320
  var MultiCombobox = ({
@@ -13405,7 +13443,7 @@ var MultiCombobox = ({
13405
13443
  outline: "border-2 border-input bg-transparent hover:border-primary",
13406
13444
  ghost: "border border-transparent bg-muted/50 hover:bg-muted"
13407
13445
  };
13408
- const autoId = useId5();
13446
+ const autoId = useId7();
13409
13447
  const resolvedId = id ? String(id) : `multicombobox-${autoId}`;
13410
13448
  const labelId = label ? `${resolvedId}-label` : void 0;
13411
13449
  const labelSize = size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm";
@@ -14033,6 +14071,36 @@ var SIZE_STYLES = {
14033
14071
  }
14034
14072
  };
14035
14073
  var clamp6 = (n, min, max) => Math.min(max, Math.max(min, n));
14074
+ function SliderTooltip({
14075
+ displayValue,
14076
+ position,
14077
+ visible,
14078
+ sizeClassName,
14079
+ tooltipClassName
14080
+ }) {
14081
+ return /* @__PURE__ */ jsxs36(
14082
+ "div",
14083
+ {
14084
+ className: cn(
14085
+ "absolute pointer-events-none transition-all duration-200 ease-out",
14086
+ "bg-popover text-popover-foreground rounded-lg shadow-lg border border-border/50",
14087
+ "whitespace-nowrap font-medium -translate-x-1/2 z-50",
14088
+ sizeClassName,
14089
+ visible ? "opacity-100 -translate-y-10 scale-100" : "opacity-0 -translate-y-8 scale-95",
14090
+ tooltipClassName
14091
+ ),
14092
+ style: {
14093
+ left: `${position}%`,
14094
+ bottom: "100%"
14095
+ },
14096
+ children: [
14097
+ displayValue,
14098
+ /* @__PURE__ */ jsx44("div", { className: "absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-4 border-transparent border-t-border" }),
14099
+ /* @__PURE__ */ jsx44("div", { className: "absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-[3px] border-transparent border-t-popover -mt-px" })
14100
+ ]
14101
+ }
14102
+ );
14103
+ }
14036
14104
  var Slider = React39.forwardRef(
14037
14105
  ({
14038
14106
  className,
@@ -14122,6 +14190,7 @@ var Slider = React39.forwardRef(
14122
14190
  const rangeStartPct = (normalizedRange[0] - min) / denom * 100;
14123
14191
  const rangeEndPct = (normalizedRange[1] - min) / denom * 100;
14124
14192
  const sizeStyles8 = SIZE_STYLES[size];
14193
+ const tooltipVisible = showTooltip && !disabled && (isHovering || isDragging);
14125
14194
  const displayValue = React39.useMemo(() => {
14126
14195
  if (isRange) {
14127
14196
  const a = formatValue ? formatValue(normalizedRange[0]) : normalizedRange[0].toString();
@@ -14195,32 +14264,6 @@ var Slider = React39.forwardRef(
14195
14264
  };
14196
14265
  if (orientation === "vertical") {
14197
14266
  }
14198
- const Tooltip2 = ({ value: value2, position }) => {
14199
- const shouldShow = showTooltip && !disabled && (isHovering || isDragging);
14200
- const displayVal = formatValue ? formatValue(value2) : value2.toString();
14201
- return /* @__PURE__ */ jsxs36(
14202
- "div",
14203
- {
14204
- className: cn(
14205
- "absolute pointer-events-none transition-all duration-200 ease-out",
14206
- "bg-popover text-popover-foreground rounded-lg shadow-lg border border-border/50",
14207
- "whitespace-nowrap font-medium -translate-x-1/2 z-50",
14208
- sizeStyles8.tooltip,
14209
- shouldShow ? "opacity-100 -translate-y-10 scale-100" : "opacity-0 -translate-y-8 scale-95",
14210
- tooltipClassName
14211
- ),
14212
- style: {
14213
- left: `${position}%`,
14214
- bottom: "100%"
14215
- },
14216
- children: [
14217
- displayVal,
14218
- /* @__PURE__ */ jsx44("div", { className: "absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-4 border-transparent border-t-border" }),
14219
- /* @__PURE__ */ jsx44("div", { className: "absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-[3px] border-transparent border-t-popover -mt-px" })
14220
- ]
14221
- }
14222
- );
14223
- };
14224
14267
  return /* @__PURE__ */ jsxs36("div", { className: cn("w-full space-y-2", containerClassName), children: [
14225
14268
  (label || showValue) && /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between", children: [
14226
14269
  label && /* @__PURE__ */ jsx44("label", { className: cn("text-sm font-medium text-foreground", labelClassName), children: label }),
@@ -14253,10 +14296,37 @@ var Slider = React39.forwardRef(
14253
14296
  style: { width: `${percentage}%` }
14254
14297
  }
14255
14298
  ) }),
14256
- !isRange && /* @__PURE__ */ jsx44(Tooltip2, { value: currentValue, position: percentage }),
14299
+ !isRange && /* @__PURE__ */ jsx44(
14300
+ SliderTooltip,
14301
+ {
14302
+ displayValue: formatValue ? formatValue(currentValue) : currentValue.toString(),
14303
+ position: percentage,
14304
+ visible: tooltipVisible,
14305
+ sizeClassName: sizeStyles8.tooltip,
14306
+ tooltipClassName
14307
+ }
14308
+ ),
14257
14309
  isRange && /* @__PURE__ */ jsxs36(Fragment14, { children: [
14258
- /* @__PURE__ */ jsx44(Tooltip2, { value: normalizedRange[0], position: rangeStartPct }),
14259
- /* @__PURE__ */ jsx44(Tooltip2, { value: normalizedRange[1], position: rangeEndPct })
14310
+ /* @__PURE__ */ jsx44(
14311
+ SliderTooltip,
14312
+ {
14313
+ displayValue: formatValue ? formatValue(normalizedRange[0]) : normalizedRange[0].toString(),
14314
+ position: rangeStartPct,
14315
+ visible: tooltipVisible,
14316
+ sizeClassName: sizeStyles8.tooltip,
14317
+ tooltipClassName
14318
+ }
14319
+ ),
14320
+ /* @__PURE__ */ jsx44(
14321
+ SliderTooltip,
14322
+ {
14323
+ displayValue: formatValue ? formatValue(normalizedRange[1]) : normalizedRange[1].toString(),
14324
+ position: rangeEndPct,
14325
+ visible: tooltipVisible,
14326
+ sizeClassName: sizeStyles8.tooltip,
14327
+ tooltipClassName
14328
+ }
14329
+ )
14260
14330
  ] }),
14261
14331
  (() => {
14262
14332
  const baseInputClassName = cn(
@@ -14829,7 +14899,7 @@ function OverlayControls({
14829
14899
  }
14830
14900
 
14831
14901
  // src/components/CategoryTreeSelect.tsx
14832
- import { useEffect as useEffect23, useId as useId7, useMemo as useMemo17, useRef as useRef17, useState as useState29 } from "react";
14902
+ import { useEffect as useEffect23, useId as useId9, useMemo as useMemo17, useRef as useRef17, useState as useState29 } from "react";
14833
14903
  import { ChevronRight as ChevronRight6, ChevronDown as ChevronDown5, FolderTree, Layers, Search as Search5, SearchX as SearchX3, X as X13 } from "lucide-react";
14834
14904
  import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
14835
14905
  var defaultLabels = {
@@ -14838,6 +14908,16 @@ var defaultLabels = {
14838
14908
  searchPlaceholder: "Search...",
14839
14909
  noResultsText: "No results found"
14840
14910
  };
14911
+ function getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline) {
14912
+ if (!(viewOnly || inline) || !defaultExpanded) return /* @__PURE__ */ new Set();
14913
+ const parentIds = /* @__PURE__ */ new Set();
14914
+ for (const category of categories) {
14915
+ if (typeof category.parent_id === "number") {
14916
+ parentIds.add(category.parent_id);
14917
+ }
14918
+ }
14919
+ return parentIds;
14920
+ }
14841
14921
  function CategoryTreeSelect(props) {
14842
14922
  const {
14843
14923
  id,
@@ -14863,12 +14943,12 @@ function CategoryTreeSelect(props) {
14863
14943
  singleSelect = false
14864
14944
  } = props;
14865
14945
  const [isOpen, setIsOpen] = useState29(false);
14866
- const [expandedNodes, setExpandedNodes] = useState29(/* @__PURE__ */ new Set());
14946
+ const [expandedNodes, setExpandedNodes] = useState29(() => getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline));
14867
14947
  const [query, setQuery] = useState29("");
14868
14948
  const searchInputRef = useRef17(null);
14869
14949
  const dropdownViewportRef = useRef17(null);
14870
14950
  useOverlayScrollbarTarget(dropdownViewportRef, { enabled: useOverlayScrollbar });
14871
- const autoId = useId7();
14951
+ const autoId = useId9();
14872
14952
  const resolvedId = id ? String(id) : `category-tree-select-${autoId}`;
14873
14953
  const labelId = label ? `${resolvedId}-label` : void 0;
14874
14954
  const helperId = helperText && !error ? `${resolvedId}-helper` : void 0;
@@ -14937,21 +15017,12 @@ function CategoryTreeSelect(props) {
14937
15017
  }
14938
15018
  return visible;
14939
15019
  }, [byId, categories, childrenMap, isSearchMode, normalizedQuery]);
14940
- useEffect23(() => {
14941
- if (!isOpen) setQuery("");
14942
- }, [isOpen]);
14943
15020
  useEffect23(() => {
14944
15021
  if (!isOpen) return;
14945
15022
  if (!isSearchEnabled) return;
14946
15023
  const t = setTimeout(() => searchInputRef.current?.focus(), 50);
14947
15024
  return () => clearTimeout(t);
14948
15025
  }, [isOpen, isSearchEnabled]);
14949
- useEffect23(() => {
14950
- if ((viewOnly || inline) && defaultExpanded) {
14951
- const allParentIds = categories.filter((c) => childrenMap.has(c.id)).map((c) => c.id);
14952
- setExpandedNodes(new Set(allParentIds));
14953
- }
14954
- }, [viewOnly, inline, defaultExpanded, categories, childrenMap]);
14955
15026
  const toggleExpand = (id2) => {
14956
15027
  if (isSearchMode) return;
14957
15028
  const newExpanded = new Set(expandedNodes);
@@ -14975,7 +15046,7 @@ function CategoryTreeSelect(props) {
14975
15046
  onChange(categoryId);
14976
15047
  }
14977
15048
  if (!inline) {
14978
- setIsOpen(false);
15049
+ handleOpenChange(false);
14979
15050
  }
14980
15051
  } else {
14981
15052
  const onChange = props.onChange;
@@ -15113,17 +15184,16 @@ function CategoryTreeSelect(props) {
15113
15184
  if (!isSearchMode) return parentCategories;
15114
15185
  return parentCategories.filter((c) => visibleIds?.has(c.id));
15115
15186
  }, [isSearchMode, parentCategories, visibleIds]);
15116
- const effectiveChildrenMap = useMemo17(() => {
15117
- if (!isSearchMode || !visibleIds) return childrenMap;
15118
- const next = /* @__PURE__ */ new Map();
15187
+ let effectiveChildrenMap = childrenMap;
15188
+ if (isSearchMode && visibleIds) {
15189
+ effectiveChildrenMap = /* @__PURE__ */ new Map();
15119
15190
  for (const [parentId, children] of childrenMap.entries()) {
15120
- next.set(
15191
+ effectiveChildrenMap.set(
15121
15192
  parentId,
15122
15193
  children.filter((child) => visibleIds.has(child.id))
15123
15194
  );
15124
15195
  }
15125
- return next;
15126
- }, [childrenMap, isSearchMode, visibleIds]);
15196
+ }
15127
15197
  const renderTreeContent = () => /* @__PURE__ */ jsx46("div", { className: "space-y-0.5 overflow-x-hidden", children: effectiveParentCategories.length === 0 ? /* @__PURE__ */ jsxs38("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
15128
15198
  /* @__PURE__ */ jsx46("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: isSearchMode ? /* @__PURE__ */ jsx46(SearchX3, { className: "w-6 h-6 text-muted-foreground/50" }) : /* @__PURE__ */ jsx46(Layers, { className: "w-6 h-6 text-muted-foreground/50" }) }),
15129
15199
  /* @__PURE__ */ jsx46("span", { className: "text-sm text-muted-foreground", children: isSearchMode ? mergedLabels.noResultsText : mergedLabels.emptyText })
@@ -15232,7 +15302,13 @@ function CategoryTreeSelect(props) {
15232
15302
  event.preventDefault();
15233
15303
  event.stopPropagation();
15234
15304
  clearSelection();
15235
- setIsOpen(false);
15305
+ handleOpenChange(false);
15306
+ };
15307
+ const handleOpenChange = (nextOpen) => {
15308
+ setIsOpen(nextOpen);
15309
+ if (!nextOpen) {
15310
+ setQuery("");
15311
+ }
15236
15312
  };
15237
15313
  let displayText;
15238
15314
  if (singleSelect) {
@@ -15265,7 +15341,7 @@ function CategoryTreeSelect(props) {
15265
15341
  Popover,
15266
15342
  {
15267
15343
  open: isOpen,
15268
- onOpenChange: setIsOpen,
15344
+ onOpenChange: handleOpenChange,
15269
15345
  disabled,
15270
15346
  placement: "bottom-start",
15271
15347
  matchTriggerWidth: true,
@@ -18310,7 +18386,7 @@ var MusicPlayer = ({
18310
18386
  var MusicPlayer_default = MusicPlayer;
18311
18387
 
18312
18388
  // src/components/Grid.tsx
18313
- import React49, { useId as useId8 } from "react";
18389
+ import React49, { useId as useId10 } from "react";
18314
18390
  import { Fragment as Fragment20, jsx as jsx56, jsxs as jsxs48 } from "react/jsx-runtime";
18315
18391
  var BP_MIN = {
18316
18392
  sm: 640,
@@ -18375,7 +18451,7 @@ var GridRoot = React49.forwardRef(
18375
18451
  children,
18376
18452
  ...rest
18377
18453
  }, ref) => {
18378
- const id = useId8().replace(/[:]/g, "");
18454
+ const id = useId10().replace(/[:]/g, "");
18379
18455
  const baseClass = `uv-grid-${id}`;
18380
18456
  const baseCols = toTemplateCols(columns, minColumnWidth);
18381
18457
  const baseRows = toTemplateRows(rows);
@@ -18498,13 +18574,9 @@ var Grid = Object.assign(GridRoot, { Item: GridItem });
18498
18574
  var Grid_default = Grid;
18499
18575
 
18500
18576
  // src/components/ClientOnly.tsx
18501
- import { useEffect as useEffect28, useState as useState38 } from "react";
18502
18577
  import { Fragment as Fragment21, jsx as jsx57 } from "react/jsx-runtime";
18503
18578
  function ClientOnly({ children, fallback = null }) {
18504
- const [hasMounted, setHasMounted] = useState38(false);
18505
- useEffect28(() => {
18506
- setHasMounted(true);
18507
- }, []);
18579
+ const hasMounted = useHydrated();
18508
18580
  if (!hasMounted) {
18509
18581
  return /* @__PURE__ */ jsx57(Fragment21, { children: fallback });
18510
18582
  }
@@ -18607,7 +18679,7 @@ var TABLE_CONTAINER_BASE_CLASS = [
18607
18679
  "bg-card text-card-foreground shadow-sm",
18608
18680
  "backdrop-blur-sm transition-all duration-300"
18609
18681
  ].join(" ");
18610
- function assignRef3(ref, value) {
18682
+ function assignRef(ref, value) {
18611
18683
  if (typeof ref === "function") {
18612
18684
  ref(value);
18613
18685
  return;
@@ -18624,7 +18696,7 @@ var TableContainer = React50.forwardRef(({ className, useOverlayScrollbar = fals
18624
18696
  {
18625
18697
  ref: (node) => {
18626
18698
  containerRef.current = node;
18627
- assignRef3(ref, node);
18699
+ assignRef(ref, node);
18628
18700
  },
18629
18701
  className: cn(TABLE_CONTAINER_BASE_CLASS, className),
18630
18702
  ...props
@@ -19376,39 +19448,40 @@ import React57 from "react";
19376
19448
 
19377
19449
  // src/components/DataTable/hooks/usePageSizeStorage.ts
19378
19450
  import React56 from "react";
19451
+ function readStoredPageSize(storageKey) {
19452
+ if (typeof window === "undefined" || !storageKey) return null;
19453
+ try {
19454
+ const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
19455
+ if (!saved) return null;
19456
+ const parsed = parseInt(saved, 10);
19457
+ return !isNaN(parsed) && parsed > 0 ? parsed : null;
19458
+ } catch {
19459
+ return null;
19460
+ }
19461
+ }
19379
19462
  function usePageSizeStorage({ pageSize, storageKey }) {
19380
- const loadedFromStorage = React56.useRef(false);
19381
- const [curPageSize, setCurPageSize] = React56.useState(() => {
19382
- if (typeof window === "undefined" || !storageKey) return pageSize;
19383
- try {
19384
- const saved = localStorage.getItem(`datatable_${storageKey}_pageSize`);
19385
- if (saved) {
19386
- const parsed = parseInt(saved, 10);
19387
- if (!isNaN(parsed) && parsed > 0) {
19388
- loadedFromStorage.current = true;
19389
- return parsed;
19390
- }
19391
- }
19392
- } catch {
19393
- }
19394
- return pageSize;
19463
+ const storedPageSize = React56.useMemo(() => readStoredPageSize(storageKey), [storageKey]);
19464
+ const [overrideState, setOverrideState] = React56.useState({
19465
+ storageKey,
19466
+ pageSize: null
19395
19467
  });
19396
- const hasMounted = React56.useRef(false);
19397
- React56.useEffect(() => {
19398
- hasMounted.current = true;
19399
- }, []);
19400
- React56.useEffect(() => {
19401
- if (typeof window === "undefined" || !storageKey) return;
19402
- if (!hasMounted.current) return;
19403
- try {
19404
- localStorage.setItem(`datatable_${storageKey}_pageSize`, String(curPageSize));
19405
- } catch {
19406
- }
19407
- }, [curPageSize, storageKey]);
19408
- React56.useEffect(() => {
19409
- if (storageKey && loadedFromStorage.current) return;
19410
- setCurPageSize(pageSize);
19411
- }, [pageSize, storageKey]);
19468
+ const overridePageSize = overrideState.storageKey === storageKey ? overrideState.pageSize : null;
19469
+ const persistedPageSize = storageKey ? overridePageSize ?? storedPageSize : null;
19470
+ const loadedFromStorage = persistedPageSize != null;
19471
+ const curPageSize = storageKey ? persistedPageSize ?? pageSize : overridePageSize ?? pageSize;
19472
+ const setCurPageSize = React56.useCallback(
19473
+ (nextPageSize) => {
19474
+ const baseValue = storageKey ? persistedPageSize ?? pageSize : overridePageSize ?? pageSize;
19475
+ const resolved = typeof nextPageSize === "function" ? nextPageSize(baseValue) : nextPageSize;
19476
+ setOverrideState({ storageKey, pageSize: resolved });
19477
+ if (!storageKey || typeof window === "undefined") return;
19478
+ try {
19479
+ localStorage.setItem(`datatable_${storageKey}_pageSize`, String(resolved));
19480
+ } catch {
19481
+ }
19482
+ },
19483
+ [overridePageSize, pageSize, persistedPageSize, storageKey]
19484
+ );
19412
19485
  return { curPageSize, setCurPageSize, loadedFromStorage };
19413
19486
  }
19414
19487
 
@@ -20071,7 +20144,7 @@ function AccessDenied({
20071
20144
 
20072
20145
  // src/components/ThemeToggleHeadless.tsx
20073
20146
  import { Moon as Moon2, Sun as Sun2, Monitor } from "lucide-react";
20074
- import { useEffect as useEffect30, useRef as useRef22, useState as useState39 } from "react";
20147
+ import { useRef as useRef22, useState as useState38 } from "react";
20075
20148
  import { createPortal as createPortal6 } from "react-dom";
20076
20149
  import { Fragment as Fragment23, jsx as jsx68, jsxs as jsxs59 } from "react/jsx-runtime";
20077
20150
  function ThemeToggleHeadless({
@@ -20080,17 +20153,16 @@ function ThemeToggleHeadless({
20080
20153
  labels,
20081
20154
  className
20082
20155
  }) {
20083
- const [isOpen, setIsOpen] = useState39(false);
20084
- const [mounted, setMounted] = useState39(false);
20156
+ const [isOpen, setIsOpen] = useState38(false);
20157
+ const isHydrated = useHydrated();
20085
20158
  const triggerRef = useRef22(null);
20086
- const [dropdownPosition, setDropdownPosition] = useState39(null);
20087
- useEffect30(() => setMounted(true), []);
20159
+ const [dropdownPosition, setDropdownPosition] = useState38(null);
20088
20160
  const themes = [
20089
20161
  { value: "light", label: labels?.light ?? "Light", icon: Sun2 },
20090
20162
  { value: "dark", label: labels?.dark ?? "Dark", icon: Moon2 },
20091
20163
  { value: "system", label: labels?.system ?? "System", icon: Monitor }
20092
20164
  ];
20093
- const current = mounted ? themes.find((t) => t.value === theme) || themes[2] : themes[2];
20165
+ const current = isHydrated ? themes.find((t) => t.value === theme) || themes[2] : themes[2];
20094
20166
  const CurrentIcon = current.icon;
20095
20167
  const calculatePosition = () => {
20096
20168
  const rect = triggerRef.current?.getBoundingClientRect();
@@ -20173,7 +20245,7 @@ function ThemeToggleHeadless({
20173
20245
  }
20174
20246
 
20175
20247
  // src/components/LanguageSwitcherHeadless.tsx
20176
- import { useRef as useRef23, useState as useState40 } from "react";
20248
+ import { useRef as useRef23, useState as useState39 } from "react";
20177
20249
  import { createPortal as createPortal7 } from "react-dom";
20178
20250
  import { Globe } from "lucide-react";
20179
20251
  import { Fragment as Fragment24, jsx as jsx69, jsxs as jsxs60 } from "react/jsx-runtime";
@@ -20184,8 +20256,8 @@ function LanguageSwitcherHeadless({
20184
20256
  labels,
20185
20257
  className
20186
20258
  }) {
20187
- const [isOpen, setIsOpen] = useState40(false);
20188
- const [dropdownPosition, setDropdownPosition] = useState40(null);
20259
+ const [isOpen, setIsOpen] = useState39(false);
20260
+ const [dropdownPosition, setDropdownPosition] = useState39(null);
20189
20261
  const triggerButtonRef = useRef23(null);
20190
20262
  const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
20191
20263
  const calculatePosition = () => {
@@ -20724,7 +20796,7 @@ function useLocale() {
20724
20796
  }
20725
20797
 
20726
20798
  // src/components/UEditor/UEditor.tsx
20727
- import React71, { useEffect as useEffect37, useImperativeHandle as useImperativeHandle3, useMemo as useMemo22, useRef as useRef30 } from "react";
20799
+ import React71, { useEffect as useEffect34, useImperativeHandle as useImperativeHandle3, useMemo as useMemo22, useRef as useRef30 } from "react";
20728
20800
  import { useEditor, EditorContent } from "@tiptap/react";
20729
20801
 
20730
20802
  // src/components/UEditor/extensions.ts
@@ -20765,7 +20837,7 @@ import { common, createLowlight } from "lowlight";
20765
20837
  import { Extension } from "@tiptap/core";
20766
20838
  import Suggestion from "@tiptap/suggestion";
20767
20839
  import { ReactRenderer } from "@tiptap/react";
20768
- import { forwardRef as forwardRef13, useEffect as useEffect31, useImperativeHandle, useRef as useRef24, useState as useState41 } from "react";
20840
+ import React63, { forwardRef as forwardRef13, useEffect as useEffect29, useImperativeHandle, useRef as useRef24 } from "react";
20769
20841
  import {
20770
20842
  FileCode as FileCode2,
20771
20843
  Heading1,
@@ -20807,13 +20879,24 @@ var DEFAULT_MESSAGES = {
20807
20879
  table: "Table",
20808
20880
  tableDesc: "Insert a table"
20809
20881
  };
20882
+ function useResettingIndex2(resetToken) {
20883
+ const [state, setState] = React63.useState({ resetToken, index: 0 });
20884
+ const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
20885
+ const setSelectedIndex = React63.useCallback((nextIndex) => {
20886
+ setState((prev) => {
20887
+ const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
20888
+ return {
20889
+ resetToken,
20890
+ index: typeof nextIndex === "function" ? nextIndex(prevIndex) : nextIndex
20891
+ };
20892
+ });
20893
+ }, [resetToken]);
20894
+ return [selectedIndex, setSelectedIndex];
20895
+ }
20810
20896
  var CommandList = forwardRef13((props, ref) => {
20811
- const [selectedIndex, setSelectedIndex] = useState41(0);
20897
+ const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
20812
20898
  const listRef = useRef24(null);
20813
- useEffect31(() => {
20814
- setSelectedIndex(0);
20815
- }, [props.items]);
20816
- useEffect31(() => {
20899
+ useEffect29(() => {
20817
20900
  const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
20818
20901
  selectedElement?.scrollIntoView({ block: "nearest" });
20819
20902
  }, [selectedIndex, props.items]);
@@ -21138,7 +21221,7 @@ import { Extension as Extension3 } from "@tiptap/core";
21138
21221
  import Suggestion2 from "@tiptap/suggestion";
21139
21222
  import { ReactRenderer as ReactRenderer2 } from "@tiptap/react";
21140
21223
  import { PluginKey } from "@tiptap/pm/state";
21141
- import { forwardRef as forwardRef14, useEffect as useEffect32, useImperativeHandle as useImperativeHandle2, useState as useState42 } from "react";
21224
+ import React64, { forwardRef as forwardRef14, useImperativeHandle as useImperativeHandle2 } from "react";
21142
21225
  import { Smile } from "lucide-react";
21143
21226
  import tippy2 from "tippy.js";
21144
21227
 
@@ -21909,11 +21992,22 @@ var EMOJI_LIST = [
21909
21992
 
21910
21993
  // src/components/UEditor/emoji-suggestion.tsx
21911
21994
  import { jsx as jsx72, jsxs as jsxs62 } from "react/jsx-runtime";
21995
+ function useResettingIndex3(resetToken) {
21996
+ const [state, setState] = React64.useState({ resetToken, index: 0 });
21997
+ const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
21998
+ const setSelectedIndex = React64.useCallback((nextIndex) => {
21999
+ setState((prev) => {
22000
+ const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
22001
+ return {
22002
+ resetToken,
22003
+ index: typeof nextIndex === "function" ? nextIndex(prevIndex) : nextIndex
22004
+ };
22005
+ });
22006
+ }, [resetToken]);
22007
+ return [selectedIndex, setSelectedIndex];
22008
+ }
21912
22009
  var EmojiList = forwardRef14((props, ref) => {
21913
- const [selectedIndex, setSelectedIndex] = useState42(0);
21914
- useEffect32(() => {
21915
- setSelectedIndex(0);
21916
- }, [props.items]);
22010
+ const [selectedIndex, setSelectedIndex] = useResettingIndex3(props.items);
21917
22011
  useImperativeHandle2(ref, () => ({
21918
22012
  onKeyDown: ({ event }) => {
21919
22013
  if (event.key === "ArrowUp") {
@@ -22119,7 +22213,7 @@ var UEditorPlaceholder = Extension4.create({
22119
22213
  });
22120
22214
 
22121
22215
  // src/components/UEditor/resizable-image.tsx
22122
- import { useEffect as useEffect33, useRef as useRef25, useState as useState43 } from "react";
22216
+ import { useEffect as useEffect30, useRef as useRef25, useState as useState41 } from "react";
22123
22217
  import Image3 from "@tiptap/extension-image";
22124
22218
  import { mergeAttributes } from "@tiptap/core";
22125
22219
  import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
@@ -22141,13 +22235,13 @@ function ResizableImageNodeView(props) {
22141
22235
  const { node, selected, updateAttributes, editor, getPos } = props;
22142
22236
  const wrapperRef = useRef25(null);
22143
22237
  const imgRef = useRef25(null);
22144
- const [isHovered, setIsHovered] = useState43(false);
22145
- const [isResizing, setIsResizing] = useState43(false);
22238
+ const [isHovered, setIsHovered] = useState41(false);
22239
+ const [isResizing, setIsResizing] = useState41(false);
22146
22240
  const widthAttr = toNullableNumber(node.attrs["width"]);
22147
22241
  const heightAttr = toNullableNumber(node.attrs["height"]);
22148
22242
  const textAlign = String(node.attrs["textAlign"] ?? "");
22149
22243
  const dragStateRef = useRef25(null);
22150
- useEffect33(() => {
22244
+ useEffect30(() => {
22151
22245
  const img = imgRef.current;
22152
22246
  if (!img) return;
22153
22247
  img.style.width = widthAttr ? `${widthAttr}px` : "";
@@ -22478,7 +22572,7 @@ function buildUEditorExtensions({
22478
22572
  }
22479
22573
 
22480
22574
  // src/components/UEditor/toolbar.tsx
22481
- import React69, { useRef as useRef28, useState as useState46 } from "react";
22575
+ import React69, { useRef as useRef28, useState as useState44 } from "react";
22482
22576
  import {
22483
22577
  AlignCenter,
22484
22578
  AlignJustify,
@@ -22579,7 +22673,7 @@ var EditorColorPalette = ({
22579
22673
  ] });
22580
22674
 
22581
22675
  // src/components/UEditor/inputs.tsx
22582
- import { useEffect as useEffect34, useRef as useRef26, useState as useState44 } from "react";
22676
+ import { useEffect as useEffect31, useRef as useRef26, useState as useState42 } from "react";
22583
22677
  import { Check as Check10, X as X18 } from "lucide-react";
22584
22678
  import { jsx as jsx75, jsxs as jsxs65 } from "react/jsx-runtime";
22585
22679
  function normalizeUrl(raw) {
@@ -22595,9 +22689,9 @@ var LinkInput = ({
22595
22689
  initialUrl = ""
22596
22690
  }) => {
22597
22691
  const t = useSmartTranslations("UEditor");
22598
- const [url, setUrl] = useState44(initialUrl);
22692
+ const [url, setUrl] = useState42(initialUrl);
22599
22693
  const inputRef = useRef26(null);
22600
- useEffect34(() => {
22694
+ useEffect31(() => {
22601
22695
  inputRef.current?.focus();
22602
22696
  inputRef.current?.select();
22603
22697
  }, []);
@@ -22624,10 +22718,10 @@ var LinkInput = ({
22624
22718
  };
22625
22719
  var ImageInput = ({ onSubmit, onCancel }) => {
22626
22720
  const t = useSmartTranslations("UEditor");
22627
- const [url, setUrl] = useState44("");
22628
- const [alt, setAlt] = useState44("");
22721
+ const [url, setUrl] = useState42("");
22722
+ const [alt, setAlt] = useState42("");
22629
22723
  const inputRef = useRef26(null);
22630
- useEffect34(() => {
22724
+ useEffect31(() => {
22631
22725
  inputRef.current?.focus();
22632
22726
  }, []);
22633
22727
  const handleSubmit = (e) => {
@@ -22680,7 +22774,7 @@ var ImageInput = ({ onSubmit, onCancel }) => {
22680
22774
  };
22681
22775
 
22682
22776
  // src/components/UEditor/emoji-picker.tsx
22683
- import { useState as useState45, useMemo as useMemo20, useRef as useRef27, useEffect as useEffect35 } from "react";
22777
+ import { useState as useState43, useMemo as useMemo20, useRef as useRef27, useEffect as useEffect32 } from "react";
22684
22778
  import { Search as Search6, X as X19, Smile as Smile2, Leaf, Utensils, Dumbbell, Lightbulb, Hash, Flag } from "lucide-react";
22685
22779
  import { jsx as jsx76, jsxs as jsxs66 } from "react/jsx-runtime";
22686
22780
  var CATEGORY_ICONS = {
@@ -22694,8 +22788,8 @@ var CATEGORY_ICONS = {
22694
22788
  };
22695
22789
  var EmojiPicker = ({ onSelect, onClose }) => {
22696
22790
  const t = useSmartTranslations("UEditor");
22697
- const [search, setSearch] = useState45("");
22698
- const [activeCategory, setActiveCategory] = useState45(EMOJI_LIST[0]?.id || "");
22791
+ const [search, setSearch] = useState43("");
22792
+ const [activeCategory, setActiveCategory] = useState43(EMOJI_LIST[0]?.id || "");
22699
22793
  const scrollContainerRef = useRef27(null);
22700
22794
  const categoryRefs = useRef27({});
22701
22795
  const isUserScrolling = useRef27(false);
@@ -22713,7 +22807,7 @@ var EmojiPicker = ({ onSelect, onClose }) => {
22713
22807
  onSelect(emoji);
22714
22808
  setSearch("");
22715
22809
  };
22716
- useEffect35(() => {
22810
+ useEffect32(() => {
22717
22811
  if (search) return;
22718
22812
  const container = scrollContainerRef.current;
22719
22813
  if (!container) return;
@@ -22753,7 +22847,7 @@ var EmojiPicker = ({ onSelect, onClose }) => {
22753
22847
  isUserScrolling.current = true;
22754
22848
  }, 500);
22755
22849
  };
22756
- useEffect35(() => {
22850
+ useEffect32(() => {
22757
22851
  isUserScrolling.current = true;
22758
22852
  }, []);
22759
22853
  return /* @__PURE__ */ jsxs66("div", { className: "w-96 bg-card border border-border/50 rounded-2xl shadow-xl overflow-hidden flex flex-col max-h-128", children: [
@@ -22910,10 +23004,10 @@ var EditorToolbar = ({
22910
23004
  }) => {
22911
23005
  const t = useSmartTranslations("UEditor");
22912
23006
  const { textColors, highlightColors } = useEditorColors();
22913
- const [showImageInput, setShowImageInput] = useState46(false);
23007
+ const [showImageInput, setShowImageInput] = useState44(false);
22914
23008
  const fileInputRef = useRef28(null);
22915
- const [isUploadingImage, setIsUploadingImage] = useState46(false);
22916
- const [imageUploadError, setImageUploadError] = useState46(null);
23009
+ const [isUploadingImage, setIsUploadingImage] = useState44(false);
23010
+ const [imageUploadError, setImageUploadError] = useState44(null);
22917
23011
  const insertImageFiles = async (files) => {
22918
23012
  if (files.length === 0) return;
22919
23013
  setIsUploadingImage(true);
@@ -23361,7 +23455,7 @@ var EditorToolbar = ({
23361
23455
  };
23362
23456
 
23363
23457
  // src/components/UEditor/menus.tsx
23364
- import { useCallback as useCallback17, useEffect as useEffect36, useMemo as useMemo21, useRef as useRef29, useState as useState47 } from "react";
23458
+ import React70, { useCallback as useCallback17, useEffect as useEffect33, useMemo as useMemo21, useRef as useRef29, useState as useState45 } from "react";
23365
23459
  import { createPortal as createPortal8 } from "react-dom";
23366
23460
  import {
23367
23461
  Bold as BoldIcon2,
@@ -23387,9 +23481,23 @@ import {
23387
23481
  Strikethrough as StrikethroughIcon2
23388
23482
  } from "lucide-react";
23389
23483
  import { jsx as jsx78, jsxs as jsxs68 } from "react/jsx-runtime";
23484
+ function useResettingIndex4(resetToken) {
23485
+ const [state, setState] = React70.useState({ resetToken, index: 0 });
23486
+ const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
23487
+ const setSelectedIndex = React70.useCallback((nextIndex) => {
23488
+ setState((prev) => {
23489
+ const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
23490
+ return {
23491
+ resetToken,
23492
+ index: typeof nextIndex === "function" ? nextIndex(prevIndex) : nextIndex
23493
+ };
23494
+ });
23495
+ }, [resetToken]);
23496
+ return [selectedIndex, setSelectedIndex];
23497
+ }
23390
23498
  var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
23391
23499
  const t = useSmartTranslations("UEditor");
23392
- const [selectedIndex, setSelectedIndex] = useState47(0);
23500
+ const [selectedIndex, setSelectedIndex] = useResettingIndex4(filterText);
23393
23501
  const menuRef = useRef29(null);
23394
23502
  const allCommands = useMemo21(
23395
23503
  () => [
@@ -23467,13 +23575,10 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
23467
23575
  const lowerFilter = filterText.toLowerCase();
23468
23576
  return allCommands.filter((cmd) => cmd.label.toLowerCase().includes(lowerFilter) || cmd.description.toLowerCase().includes(lowerFilter));
23469
23577
  }, [allCommands, filterText]);
23470
- useEffect36(() => {
23471
- setSelectedIndex(0);
23472
- }, [filterText]);
23473
- useEffect36(() => {
23578
+ useEffect33(() => {
23474
23579
  const selectedElement = menuRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
23475
23580
  selectedElement?.scrollIntoView({ block: "nearest" });
23476
- }, [selectedIndex]);
23581
+ }, [commands, selectedIndex, setSelectedIndex]);
23477
23582
  const selectCommand = useCallback17(
23478
23583
  (index) => {
23479
23584
  const command = commands[index];
@@ -23484,7 +23589,7 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
23484
23589
  },
23485
23590
  [commands, onClose]
23486
23591
  );
23487
- useEffect36(() => {
23592
+ useEffect33(() => {
23488
23593
  const handleKeyDown = (e) => {
23489
23594
  if (commands.length === 0) return;
23490
23595
  if (e.key === "ArrowDown") {
@@ -23503,7 +23608,7 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
23503
23608
  };
23504
23609
  document.addEventListener("keydown", handleKeyDown);
23505
23610
  return () => document.removeEventListener("keydown", handleKeyDown);
23506
- }, [commands, selectedIndex, selectCommand, onClose]);
23611
+ }, [commands, onClose, selectCommand, selectedIndex, setSelectedIndex]);
23507
23612
  if (commands.length === 0) {
23508
23613
  return /* @__PURE__ */ jsx78("div", { className: "w-72 p-4 text-center text-muted-foreground text-sm", children: t("slashCommand.noResults") });
23509
23614
  }
@@ -23544,7 +23649,7 @@ var SlashCommandMenu = ({ editor, onClose, filterText = "" }) => {
23544
23649
  };
23545
23650
  var FloatingMenuContent = ({ editor }) => {
23546
23651
  const t = useSmartTranslations("UEditor");
23547
- const [showCommands, setShowCommands] = useState47(false);
23652
+ const [showCommands, setShowCommands] = useState45(false);
23548
23653
  if (showCommands) {
23549
23654
  return /* @__PURE__ */ jsx78(SlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
23550
23655
  }
@@ -23567,12 +23672,12 @@ var BubbleMenuContent = ({
23567
23672
  }) => {
23568
23673
  const t = useSmartTranslations("UEditor");
23569
23674
  const { textColors, highlightColors } = useEditorColors();
23570
- const [showLinkInput, setShowLinkInput] = useState47(false);
23571
- const [showEditorColorPalette, setShowEditorColorPalette] = useState47(false);
23572
- useEffect36(() => {
23675
+ const [showLinkInput, setShowLinkInput] = useState45(false);
23676
+ const [showEditorColorPalette, setShowEditorColorPalette] = useState45(false);
23677
+ useEffect33(() => {
23573
23678
  onKeepOpenChange?.(showLinkInput);
23574
23679
  }, [onKeepOpenChange, showLinkInput]);
23575
- useEffect36(() => {
23680
+ useEffect33(() => {
23576
23681
  if (!showLinkInput) return;
23577
23682
  const close = () => setShowLinkInput(false);
23578
23683
  editor.on("selectionUpdate", close);
@@ -23695,15 +23800,15 @@ var BubbleMenuContent = ({
23695
23800
  ] });
23696
23801
  };
23697
23802
  var CustomBubbleMenu = ({ editor }) => {
23698
- const [isVisible, setIsVisible] = useState47(false);
23699
- const [position, setPosition] = useState47({ top: 0, left: 0 });
23803
+ const [isVisible, setIsVisible] = useState45(false);
23804
+ const [position, setPosition] = useState45({ top: 0, left: 0 });
23700
23805
  const menuRef = useRef29(null);
23701
23806
  const keepOpenRef = useRef29(false);
23702
23807
  const setKeepOpen = useCallback17((next) => {
23703
23808
  keepOpenRef.current = next;
23704
23809
  if (next) setIsVisible(true);
23705
23810
  }, []);
23706
- useEffect36(() => {
23811
+ useEffect33(() => {
23707
23812
  const updatePosition = () => {
23708
23813
  const { state, view } = editor;
23709
23814
  const { from, to, empty } = state.selection;
@@ -23756,9 +23861,9 @@ var CustomBubbleMenu = ({ editor }) => {
23756
23861
  );
23757
23862
  };
23758
23863
  var CustomFloatingMenu = ({ editor }) => {
23759
- const [isVisible, setIsVisible] = useState47(false);
23760
- const [position, setPosition] = useState47({ top: 0, left: 0 });
23761
- useEffect36(() => {
23864
+ const [isVisible, setIsVisible] = useState45(false);
23865
+ const [position, setPosition] = useState45({ top: 0, left: 0 });
23866
+ useEffect33(() => {
23762
23867
  const updatePosition = () => {
23763
23868
  const { state, view } = editor;
23764
23869
  const { $from, empty } = state.selection;
@@ -24241,7 +24346,7 @@ var UEditor = React71.forwardRef(({
24241
24346
  }),
24242
24347
  [content, editor, uploadImageForSave]
24243
24348
  );
24244
- useEffect37(() => {
24349
+ useEffect34(() => {
24245
24350
  if (editor && content !== editor.getHTML()) {
24246
24351
  if (editor.isEmpty && content) {
24247
24352
  editor.commands.setContent(content);