@sia.soul/sia-react-ui 0.1.14 → 0.1.17

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/core.cjs CHANGED
@@ -989,6 +989,7 @@ function Tag({
989
989
  variant = "soft",
990
990
  icon,
991
991
  closable = false,
992
+ closeOnHover = false,
992
993
  disabled = false,
993
994
  onClose,
994
995
  className = "",
@@ -998,7 +999,7 @@ function Tag({
998
999
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
999
1000
  "span",
1000
1001
  {
1001
- className: `sia-tag sia-tag--${status} sia-tag--${variant}${compact ? " sia-tag--compact" : ""}${disabled ? " sia-tag--disabled" : ""} ${className}`.trim(),
1002
+ className: `sia-tag${closable && closeOnHover ? " sia-tag--close-on-hover" : ""} sia-tag--${status} sia-tag--${variant}${compact ? " sia-tag--compact" : ""}${disabled ? " sia-tag--disabled" : ""} ${className}`.trim(),
1002
1003
  "aria-disabled": disabled || void 0,
1003
1004
  ...props,
1004
1005
  children: [
@@ -2294,7 +2295,7 @@ function useFloatingPlaceholder({ mode, placeholder, filled, active = false }) {
2294
2295
  }
2295
2296
 
2296
2297
  // src/components/Select.tsx
2297
- var import_react18 = require("react");
2298
+ var import_react20 = require("react");
2298
2299
 
2299
2300
  // src/components/Modal.tsx
2300
2301
  var import_react14 = require("react");
@@ -2457,7 +2458,7 @@ function openModal(config) {
2457
2458
  let currentOpen = true;
2458
2459
  let destroyed = false;
2459
2460
  let cleanupTimer;
2460
- function cleanup() {
2461
+ function cleanup2() {
2461
2462
  if (destroyed) return;
2462
2463
  destroyed = true;
2463
2464
  if (cleanupTimer !== void 0) window.clearTimeout(cleanupTimer);
@@ -2469,7 +2470,7 @@ function openModal(config) {
2469
2470
  if (destroyed || !currentOpen) return;
2470
2471
  currentOpen = false;
2471
2472
  render();
2472
- cleanupTimer = window.setTimeout(cleanup, MODAL_MOTION_DURATION);
2473
+ cleanupTimer = window.setTimeout(cleanup2, MODAL_MOTION_DURATION);
2473
2474
  }
2474
2475
  function render() {
2475
2476
  root.render(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ModalRoot, { ...currentConfig, open: currentOpen, onOpenChange: (nextOpen) => {
@@ -2839,13 +2840,388 @@ function OverflowTags({ items, maxCount: maxCount2, className = "", tagClassName
2839
2840
  ] });
2840
2841
  }
2841
2842
 
2843
+ // src/components/FloatingScrollbarProvider.tsx
2844
+ var import_react19 = require("react");
2845
+
2846
+ // src/components/useScrollbarProximity.ts
2847
+ var import_react18 = require("react");
2848
+ var users = 0;
2849
+ var cleanup;
2850
+ function useScrollbarProximity() {
2851
+ (0, import_react18.useEffect)(() => {
2852
+ if (users++ === 0) {
2853
+ let frame = 0;
2854
+ let x = -Infinity;
2855
+ let y = -Infinity;
2856
+ const nearby = /* @__PURE__ */ new Set();
2857
+ const clear = () => {
2858
+ nearby.forEach((track) => track.removeAttribute("data-scrollbar-near"));
2859
+ nearby.clear();
2860
+ };
2861
+ const update = () => {
2862
+ frame = 0;
2863
+ const next = /* @__PURE__ */ new Set();
2864
+ document.querySelectorAll(".sia-scrollbar-track").forEach((track) => {
2865
+ const rect = track.getBoundingClientRect();
2866
+ const proximity = Number.parseFloat(getComputedStyle(track).getPropertyValue("--sia-scrollbar-proximity")) || 16;
2867
+ if (rect.width && rect.height && x >= rect.left - proximity && x <= rect.right + proximity && y >= rect.top - proximity && y <= rect.bottom + proximity) {
2868
+ next.add(track);
2869
+ if (!nearby.has(track)) track.setAttribute("data-scrollbar-near", "true");
2870
+ }
2871
+ });
2872
+ nearby.forEach((track) => {
2873
+ if (!next.has(track)) track.removeAttribute("data-scrollbar-near");
2874
+ });
2875
+ nearby.clear();
2876
+ next.forEach((track) => nearby.add(track));
2877
+ };
2878
+ const move = (event) => {
2879
+ if (event.pointerType === "touch") return;
2880
+ x = event.clientX;
2881
+ y = event.clientY;
2882
+ if (!frame) frame = requestAnimationFrame(update);
2883
+ };
2884
+ const leave = () => {
2885
+ x = y = -Infinity;
2886
+ clear();
2887
+ };
2888
+ document.addEventListener("pointermove", move, { passive: true });
2889
+ document.documentElement.addEventListener("pointerleave", leave);
2890
+ window.addEventListener("blur", leave);
2891
+ cleanup = () => {
2892
+ if (frame) cancelAnimationFrame(frame);
2893
+ document.removeEventListener("pointermove", move);
2894
+ document.documentElement.removeEventListener("pointerleave", leave);
2895
+ window.removeEventListener("blur", leave);
2896
+ clear();
2897
+ };
2898
+ }
2899
+ return () => {
2900
+ if (--users === 0) {
2901
+ cleanup?.();
2902
+ cleanup = void 0;
2903
+ }
2904
+ };
2905
+ }, []);
2906
+ }
2907
+
2908
+ // src/components/FloatingScrollbarProvider.tsx
2909
+ var scrollableOverflow = /* @__PURE__ */ new Set(["auto", "scroll", "overlay"]);
2910
+ var clippingOverflow = /* @__PURE__ */ new Set(["auto", "scroll", "overlay", "hidden", "clip"]);
2911
+ function isRootScroller(target) {
2912
+ return target === document.scrollingElement || target === document.documentElement;
2913
+ }
2914
+ function canScroll(target, axis) {
2915
+ if (target.matches(".sia-table__viewport, [data-sia-native-scrollbar]")) return false;
2916
+ if (isRootScroller(target)) {
2917
+ return axis === "horizontal" ? target.scrollWidth > target.clientWidth + 1 : target.scrollHeight > target.clientHeight + 1;
2918
+ }
2919
+ const style = getComputedStyle(target);
2920
+ const overflow = axis === "horizontal" ? style.overflowX : style.overflowY;
2921
+ const hasOverflow = axis === "horizontal" ? target.scrollWidth > target.clientWidth + 1 : target.scrollHeight > target.clientHeight + 1;
2922
+ return hasOverflow && scrollableOverflow.has(overflow);
2923
+ }
2924
+ function visibleRect(target) {
2925
+ if (isRootScroller(target)) {
2926
+ return { top: 0, right: window.innerWidth, bottom: window.innerHeight, left: 0, width: window.innerWidth, height: window.innerHeight };
2927
+ }
2928
+ const ownRect = target.getBoundingClientRect();
2929
+ let top = Math.max(0, ownRect.top);
2930
+ let right = Math.min(window.innerWidth, ownRect.right);
2931
+ let bottom = Math.min(window.innerHeight, ownRect.bottom);
2932
+ let left = Math.max(0, ownRect.left);
2933
+ let parent = target.parentElement;
2934
+ while (parent && parent !== document.body && parent !== document.documentElement) {
2935
+ const style = getComputedStyle(parent);
2936
+ const clipX = clippingOverflow.has(style.overflowX);
2937
+ const clipY = clippingOverflow.has(style.overflowY);
2938
+ if (clipX || clipY) {
2939
+ const rect = parent.getBoundingClientRect();
2940
+ if (clipX) {
2941
+ left = Math.max(left, rect.left);
2942
+ right = Math.min(right, rect.right);
2943
+ }
2944
+ if (clipY) {
2945
+ top = Math.max(top, rect.top);
2946
+ bottom = Math.min(bottom, rect.bottom);
2947
+ }
2948
+ }
2949
+ parent = parent.parentElement;
2950
+ }
2951
+ return {
2952
+ top,
2953
+ right,
2954
+ bottom,
2955
+ left,
2956
+ width: Math.max(0, right - left),
2957
+ height: Math.max(0, bottom - top)
2958
+ };
2959
+ }
2960
+ function createTrack(axis) {
2961
+ const track = document.createElement("div");
2962
+ const thumb = document.createElement("div");
2963
+ track.className = `sia-scrollbar-track sia-floating-scrollbar sia-floating-scrollbar--${axis}`;
2964
+ thumb.className = "sia-floating-scrollbar__thumb";
2965
+ track.dataset.axis = axis;
2966
+ track.setAttribute("aria-hidden", "true");
2967
+ track.append(thumb);
2968
+ return { track, thumb };
2969
+ }
2970
+ function FloatingScrollbarProvider({ disabled = false, targetRef }) {
2971
+ useScrollbarProximity();
2972
+ (0, import_react19.useEffect)(() => {
2973
+ if (disabled) return;
2974
+ const layer = document.createElement("div");
2975
+ layer.className = "sia-floating-scrollbar-layer";
2976
+ layer.setAttribute("aria-hidden", "true");
2977
+ document.body.append(layer);
2978
+ const entries = /* @__PURE__ */ new Map();
2979
+ let scanFrame = 0;
2980
+ let updateFrame = 0;
2981
+ const setEntryVisible = (entry, visible) => {
2982
+ entry.horizontalTrack.classList.toggle("sia-floating-scrollbar--visible", visible);
2983
+ entry.verticalTrack.classList.toggle("sia-floating-scrollbar--visible", visible);
2984
+ };
2985
+ const showEntry = (entry) => {
2986
+ if (entry.hideTimer !== null) window.clearTimeout(entry.hideTimer);
2987
+ entry.hideTimer = null;
2988
+ setEntryVisible(entry, true);
2989
+ };
2990
+ const scheduleHide = (entry, delay = 500) => {
2991
+ if (entry.hideTimer !== null) window.clearTimeout(entry.hideTimer);
2992
+ entry.hideTimer = window.setTimeout(() => {
2993
+ entry.hideTimer = null;
2994
+ if (!entry.hoveringTarget && !entry.hoveringTrack && !entry.dragging) setEntryVisible(entry, false);
2995
+ }, delay);
2996
+ };
2997
+ const updateEntry = (entry) => {
2998
+ const { target, horizontalTrack, horizontalThumb, verticalTrack, verticalThumb } = entry;
2999
+ const hasHorizontal = canScroll(target, "horizontal");
3000
+ const hasVertical = canScroll(target, "vertical");
3001
+ const rect = visibleRect(target);
3002
+ const thickness = 10;
3003
+ horizontalTrack.hidden = !hasHorizontal || rect.width <= thickness || rect.height <= 0;
3004
+ verticalTrack.hidden = !hasVertical || rect.height <= thickness || rect.width <= 0;
3005
+ if (!horizontalTrack.hidden) {
3006
+ const trackWidth = Math.max(0, rect.width - (hasVertical ? thickness : 0));
3007
+ const thumbWidth = Math.max(24, Math.min(trackWidth, trackWidth * target.clientWidth / target.scrollWidth));
3008
+ const travel = Math.max(0, trackWidth - thumbWidth);
3009
+ const maxScroll = Math.max(1, target.scrollWidth - target.clientWidth);
3010
+ horizontalTrack.style.left = `${rect.left}px`;
3011
+ horizontalTrack.style.top = `${rect.bottom - thickness}px`;
3012
+ horizontalTrack.style.width = `${trackWidth}px`;
3013
+ horizontalTrack.style.height = `${thickness}px`;
3014
+ horizontalThumb.style.width = `${thumbWidth}px`;
3015
+ horizontalThumb.style.transform = `translate3d(${travel * target.scrollLeft / maxScroll}px, 0, 0)`;
3016
+ }
3017
+ if (!verticalTrack.hidden) {
3018
+ const trackHeight = Math.max(0, rect.height - (hasHorizontal ? thickness : 0));
3019
+ const thumbHeight = Math.max(24, Math.min(trackHeight, trackHeight * target.clientHeight / target.scrollHeight));
3020
+ const travel = Math.max(0, trackHeight - thumbHeight);
3021
+ const maxScroll = Math.max(1, target.scrollHeight - target.clientHeight);
3022
+ verticalTrack.style.left = `${rect.right - thickness}px`;
3023
+ verticalTrack.style.top = `${rect.top}px`;
3024
+ verticalTrack.style.width = `${thickness}px`;
3025
+ verticalTrack.style.height = `${trackHeight}px`;
3026
+ verticalThumb.style.height = `${thumbHeight}px`;
3027
+ verticalThumb.style.transform = `translate3d(0, ${travel * target.scrollTop / maxScroll}px, 0)`;
3028
+ }
3029
+ };
3030
+ const scheduleUpdateAll = () => {
3031
+ if (updateFrame) return;
3032
+ updateFrame = window.requestAnimationFrame(() => {
3033
+ updateFrame = 0;
3034
+ entries.forEach(updateEntry);
3035
+ });
3036
+ };
3037
+ const bindTrackDrag = (entry, axis, track, thumb) => {
3038
+ const target = entry.target;
3039
+ const onTrackPointerEnter = () => {
3040
+ entry.hoveringTrack = true;
3041
+ showEntry(entry);
3042
+ };
3043
+ const onTrackPointerLeave = () => {
3044
+ entry.hoveringTrack = false;
3045
+ scheduleHide(entry);
3046
+ };
3047
+ const onTrackPointerDown = (event) => {
3048
+ if (event.target === thumb || event.button !== 0) return;
3049
+ event.preventDefault();
3050
+ event.stopPropagation();
3051
+ const trackRect = track.getBoundingClientRect();
3052
+ const thumbRect = thumb.getBoundingClientRect();
3053
+ const trackLength = axis === "vertical" ? trackRect.height : trackRect.width;
3054
+ const thumbLength = axis === "vertical" ? thumbRect.height : thumbRect.width;
3055
+ const pointer = axis === "vertical" ? event.clientY - trackRect.top : event.clientX - trackRect.left;
3056
+ const ratio = Math.max(0, Math.min(1, (pointer - thumbLength / 2) / Math.max(1, trackLength - thumbLength)));
3057
+ if (axis === "vertical") target.scrollTop = ratio * (target.scrollHeight - target.clientHeight);
3058
+ else target.scrollLeft = ratio * (target.scrollWidth - target.clientWidth);
3059
+ };
3060
+ const onThumbPointerDown = (event) => {
3061
+ if (event.button !== 0) return;
3062
+ event.preventDefault();
3063
+ event.stopPropagation();
3064
+ entry.dragging = true;
3065
+ showEntry(entry);
3066
+ thumb.setPointerCapture(event.pointerId);
3067
+ const startPointer = axis === "vertical" ? event.clientY : event.clientX;
3068
+ const startScroll = axis === "vertical" ? target.scrollTop : target.scrollLeft;
3069
+ const trackRect = track.getBoundingClientRect();
3070
+ const thumbRect = thumb.getBoundingClientRect();
3071
+ const trackLength = axis === "vertical" ? trackRect.height : trackRect.width;
3072
+ const thumbLength = axis === "vertical" ? thumbRect.height : thumbRect.width;
3073
+ const maxScroll = axis === "vertical" ? target.scrollHeight - target.clientHeight : target.scrollWidth - target.clientWidth;
3074
+ const travel = Math.max(1, trackLength - thumbLength);
3075
+ const onPointerMove = (moveEvent) => {
3076
+ if (moveEvent.pointerId !== event.pointerId) return;
3077
+ const pointer = axis === "vertical" ? moveEvent.clientY : moveEvent.clientX;
3078
+ const nextScroll = startScroll + (pointer - startPointer) * maxScroll / travel;
3079
+ if (axis === "vertical") target.scrollTop = nextScroll;
3080
+ else target.scrollLeft = nextScroll;
3081
+ };
3082
+ const onPointerUp = (upEvent) => {
3083
+ if (upEvent.pointerId !== event.pointerId) return;
3084
+ entry.dragging = false;
3085
+ thumb.releasePointerCapture(event.pointerId);
3086
+ window.removeEventListener("pointermove", onPointerMove);
3087
+ window.removeEventListener("pointerup", onPointerUp);
3088
+ window.removeEventListener("pointercancel", onPointerUp);
3089
+ scheduleHide(entry);
3090
+ };
3091
+ window.addEventListener("pointermove", onPointerMove);
3092
+ window.addEventListener("pointerup", onPointerUp);
3093
+ window.addEventListener("pointercancel", onPointerUp);
3094
+ };
3095
+ track.addEventListener("pointerenter", onTrackPointerEnter);
3096
+ track.addEventListener("pointerleave", onTrackPointerLeave);
3097
+ track.addEventListener("pointerdown", onTrackPointerDown);
3098
+ thumb.addEventListener("pointerdown", onThumbPointerDown);
3099
+ return () => {
3100
+ track.removeEventListener("pointerenter", onTrackPointerEnter);
3101
+ track.removeEventListener("pointerleave", onTrackPointerLeave);
3102
+ track.removeEventListener("pointerdown", onTrackPointerDown);
3103
+ thumb.removeEventListener("pointerdown", onThumbPointerDown);
3104
+ };
3105
+ };
3106
+ const resizeObserver = new ResizeObserver((observedEntries) => {
3107
+ observedEntries.forEach(({ target }) => {
3108
+ const entry = entries.get(target);
3109
+ if (entry) updateEntry(entry);
3110
+ });
3111
+ });
3112
+ const addTarget = (target) => {
3113
+ if (entries.has(target)) return;
3114
+ const horizontal = createTrack("horizontal");
3115
+ const vertical = createTrack("vertical");
3116
+ layer.append(horizontal.track, vertical.track);
3117
+ const onPointerEnter = () => {
3118
+ const entry2 = entries.get(target);
3119
+ if (!entry2) return;
3120
+ entry2.hoveringTarget = true;
3121
+ showEntry(entry2);
3122
+ };
3123
+ const onPointerLeave = () => {
3124
+ const entry2 = entries.get(target);
3125
+ if (!entry2) return;
3126
+ entry2.hoveringTarget = false;
3127
+ scheduleHide(entry2);
3128
+ };
3129
+ const onScroll = () => {
3130
+ const entry2 = entries.get(target);
3131
+ if (!entry2) return;
3132
+ updateEntry(entry2);
3133
+ showEntry(entry2);
3134
+ scheduleHide(entry2, 700);
3135
+ };
3136
+ target.addEventListener("pointerenter", onPointerEnter);
3137
+ target.addEventListener("pointerleave", onPointerLeave);
3138
+ target.addEventListener("scroll", onScroll, { passive: true });
3139
+ const entry = {
3140
+ target,
3141
+ horizontalTrack: horizontal.track,
3142
+ horizontalThumb: horizontal.thumb,
3143
+ verticalTrack: vertical.track,
3144
+ verticalThumb: vertical.thumb,
3145
+ hideTimer: null,
3146
+ hoveringTarget: target.matches(":hover"),
3147
+ hoveringTrack: false,
3148
+ dragging: false,
3149
+ cleanup: () => void 0
3150
+ };
3151
+ const cleanupHorizontal = bindTrackDrag(entry, "horizontal", horizontal.track, horizontal.thumb);
3152
+ const cleanupVertical = bindTrackDrag(entry, "vertical", vertical.track, vertical.thumb);
3153
+ entry.cleanup = () => {
3154
+ if (entry.hideTimer !== null) window.clearTimeout(entry.hideTimer);
3155
+ cleanupHorizontal();
3156
+ cleanupVertical();
3157
+ target.removeEventListener("pointerenter", onPointerEnter);
3158
+ target.removeEventListener("pointerleave", onPointerLeave);
3159
+ target.removeEventListener("scroll", onScroll);
3160
+ resizeObserver.unobserve(target);
3161
+ target.removeAttribute("data-sia-floating-scrollbar");
3162
+ horizontal.track.remove();
3163
+ vertical.track.remove();
3164
+ };
3165
+ entries.set(target, entry);
3166
+ target.setAttribute("data-sia-floating-scrollbar", "");
3167
+ resizeObserver.observe(target);
3168
+ updateEntry(entry);
3169
+ if (entry.hoveringTarget) showEntry(entry);
3170
+ };
3171
+ const removeTarget = (target) => {
3172
+ const entry = entries.get(target);
3173
+ if (!entry) return;
3174
+ entry.cleanup();
3175
+ entries.delete(target);
3176
+ };
3177
+ const scanTargets = () => {
3178
+ scanFrame = 0;
3179
+ const candidates = (targetRef ? [targetRef.current] : [document.scrollingElement, ...document.querySelectorAll("*")]).filter((target) => target instanceof HTMLElement);
3180
+ const nextTargets = /* @__PURE__ */ new Set();
3181
+ candidates.forEach((target) => {
3182
+ if (canScroll(target, "horizontal") || canScroll(target, "vertical")) {
3183
+ nextTargets.add(target);
3184
+ if (entries.has(target) || !target.hasAttribute("data-sia-floating-scrollbar")) addTarget(target);
3185
+ }
3186
+ });
3187
+ entries.forEach((_entry, target) => {
3188
+ if (!target.isConnected || !nextTargets.has(target)) removeTarget(target);
3189
+ else updateEntry(_entry);
3190
+ });
3191
+ };
3192
+ const scheduleScan = () => {
3193
+ if (scanFrame) return;
3194
+ scanFrame = window.requestAnimationFrame(scanTargets);
3195
+ };
3196
+ const mutationObserver = new MutationObserver((mutations) => {
3197
+ if (mutations.some((mutation) => !layer.contains(mutation.target))) scheduleScan();
3198
+ });
3199
+ mutationObserver.observe(document.documentElement, { subtree: true, childList: true, attributes: true });
3200
+ window.addEventListener("resize", scheduleScan);
3201
+ window.addEventListener("scroll", scheduleUpdateAll, true);
3202
+ scheduleScan();
3203
+ return () => {
3204
+ mutationObserver.disconnect();
3205
+ resizeObserver.disconnect();
3206
+ window.removeEventListener("resize", scheduleScan);
3207
+ window.removeEventListener("scroll", scheduleUpdateAll, true);
3208
+ if (scanFrame) window.cancelAnimationFrame(scanFrame);
3209
+ if (updateFrame) window.cancelAnimationFrame(updateFrame);
3210
+ entries.forEach((entry) => entry.cleanup());
3211
+ entries.clear();
3212
+ layer.remove();
3213
+ };
3214
+ }, [disabled, targetRef]);
3215
+ return null;
3216
+ }
3217
+
2842
3218
  // src/components/Select.tsx
2843
3219
  var import_jsx_runtime19 = require("react/jsx-runtime");
2844
3220
  function defaultFilterOption(query, option) {
2845
3221
  const keyword = query.toLowerCase();
2846
3222
  return [option.label, option.value].some((value) => String(value).toLowerCase().includes(keyword));
2847
3223
  }
2848
- var Select = (0, import_react18.forwardRef)(function Select2({
3224
+ var Select = (0, import_react20.forwardRef)(function Select2({
2849
3225
  options,
2850
3226
  mode = "single",
2851
3227
  popupMode = "dropdown",
@@ -2882,20 +3258,20 @@ var Select = (0, import_react18.forwardRef)(function Select2({
2882
3258
  ...props
2883
3259
  }, forwardedRef) {
2884
3260
  const size = useControlSize(sizeProp);
2885
- const fallbackId = (0, import_react18.useId)();
3261
+ const fallbackId = (0, import_react20.useId)();
2886
3262
  const selectId = id ?? fallbackId;
2887
3263
  const listboxId = `${selectId}-listbox`;
2888
- const rootRef = (0, import_react18.useRef)(null);
2889
- const popupRef = (0, import_react18.useRef)(null);
2890
- const searchRef = (0, import_react18.useRef)(null);
2891
- const listRef = (0, import_react18.useRef)(null);
2892
- const [open, setOpen] = (0, import_react18.useState)(false);
2893
- const [modalValues, setModalValues] = (0, import_react18.useState)([]);
2894
- const [selectedOnly, setSelectedOnly] = (0, import_react18.useState)(false);
2895
- const [query, setQuery] = (0, import_react18.useState)("");
2896
- const [activeIndex, setActiveIndex] = (0, import_react18.useState)(-1);
2897
- const [scrollTop, setScrollTop] = (0, import_react18.useState)(0);
2898
- const deferredQuery = (0, import_react18.useDeferredValue)(query.trim());
3264
+ const rootRef = (0, import_react20.useRef)(null);
3265
+ const popupRef = (0, import_react20.useRef)(null);
3266
+ const searchRef = (0, import_react20.useRef)(null);
3267
+ const listRef = (0, import_react20.useRef)(null);
3268
+ const [open, setOpen] = (0, import_react20.useState)(false);
3269
+ const [modalValues, setModalValues] = (0, import_react20.useState)([]);
3270
+ const [selectedOnly, setSelectedOnly] = (0, import_react20.useState)(false);
3271
+ const [query, setQuery] = (0, import_react20.useState)("");
3272
+ const [activeIndex, setActiveIndex] = (0, import_react20.useState)(-1);
3273
+ const [scrollTop, setScrollTop] = (0, import_react20.useState)(0);
3274
+ const deferredQuery = (0, import_react20.useDeferredValue)(query.trim());
2899
3275
  const initialValue = defaultValue === void 0 ? mode === "multiple" ? [] : null : defaultValue;
2900
3276
  const [currentValue, setCurrentValue] = useControllableState({
2901
3277
  value,
@@ -2910,19 +3286,19 @@ var Select = (0, import_react18.forwardRef)(function Select2({
2910
3286
  }
2911
3287
  }
2912
3288
  });
2913
- const selectedValues = (0, import_react18.useMemo)(() => {
3289
+ const selectedValues = (0, import_react20.useMemo)(() => {
2914
3290
  if (mode === "multiple") return Array.isArray(currentValue) ? currentValue : currentValue === null ? [] : [currentValue];
2915
3291
  return Array.isArray(currentValue) ? currentValue.slice(0, 1) : currentValue === null ? [] : [currentValue];
2916
3292
  }, [currentValue, mode]);
2917
- const selectedValueSet = (0, import_react18.useMemo)(() => new Set(selectedValues), [selectedValues]);
2918
- const availableOptions = (0, import_react18.useMemo)(() => {
3293
+ const selectedValueSet = (0, import_react20.useMemo)(() => new Set(selectedValues), [selectedValues]);
3294
+ const availableOptions = (0, import_react20.useMemo)(() => {
2919
3295
  if (!allowInput) return options;
2920
3296
  const optionValueSet = new Set(options.map((option) => option.value));
2921
3297
  const selectedCustomOptions = selectedValues.filter((selectedValue) => !optionValueSet.has(selectedValue)).map((selectedValue) => ({ label: String(selectedValue), value: selectedValue }));
2922
3298
  return selectedCustomOptions.length ? [...selectedCustomOptions, ...options] : options;
2923
3299
  }, [allowInput, options, selectedValues]);
2924
- const selectedOptions = (0, import_react18.useMemo)(() => selectedValues.map((selectedValue) => availableOptions.find((option) => option.value === selectedValue)).filter((option) => option !== void 0), [availableOptions, selectedValues]);
2925
- const filteredOptions = (0, import_react18.useMemo)(() => deferredQuery ? availableOptions.filter((option) => filterOption(deferredQuery, option)) : availableOptions, [availableOptions, deferredQuery, filterOption]);
3300
+ const selectedOptions = (0, import_react20.useMemo)(() => selectedValues.map((selectedValue) => availableOptions.find((option) => option.value === selectedValue)).filter((option) => option !== void 0), [availableOptions, selectedValues]);
3301
+ const filteredOptions = (0, import_react20.useMemo)(() => deferredQuery ? availableOptions.filter((option) => filterOption(deferredQuery, option)) : availableOptions, [availableOptions, deferredQuery, filterOption]);
2926
3302
  const inputValue = query.trim();
2927
3303
  const exactInputOption = inputValue ? availableOptions.find((option) => String(option.value).toLowerCase() === inputValue.toLowerCase() || typeof option.label === "string" && option.label.toLowerCase() === inputValue.toLowerCase()) : void 0;
2928
3304
  const canSubmitInput = allowInput && Boolean(inputValue) && !exactInputOption;
@@ -2936,7 +3312,7 @@ var Select = (0, import_react18.forwardRef)(function Select2({
2936
3312
  const renderedOptions = virtualEnabled ? filteredOptions.slice(virtualStart, virtualEnd) : filteredOptions;
2937
3313
  const enabledFilteredOptions = filteredOptions.filter((option) => !option.disabled);
2938
3314
  const allFilteredSelected = enabledFilteredOptions.length > 0 && enabledFilteredOptions.every((option) => selectedValueSet.has(option.value));
2939
- (0, import_react18.useEffect)(() => {
3315
+ (0, import_react20.useEffect)(() => {
2940
3316
  if (!open || popupMode === "modal") return void 0;
2941
3317
  function closeFromOutside(event) {
2942
3318
  const target = event.target;
@@ -2945,10 +3321,10 @@ var Select = (0, import_react18.forwardRef)(function Select2({
2945
3321
  document.addEventListener("mousedown", closeFromOutside);
2946
3322
  return () => document.removeEventListener("mousedown", closeFromOutside);
2947
3323
  }, [open, popupMode]);
2948
- (0, import_react18.useEffect)(() => {
3324
+ (0, import_react20.useEffect)(() => {
2949
3325
  if (open && (showSearch || allowInput)) searchRef.current?.focus();
2950
3326
  }, [allowInput, open, showSearch]);
2951
- (0, import_react18.useEffect)(() => {
3327
+ (0, import_react20.useEffect)(() => {
2952
3328
  if (disabled || loading) closeDropdown();
2953
3329
  }, [disabled, loading]);
2954
3330
  function firstEnabledIndex() {
@@ -3135,6 +3511,7 @@ var Select = (0, import_react18.forwardRef)(function Select2({
3135
3511
  ),
3136
3512
  allowClear && hasValue && !disabled && !loading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { className: "sia-select__clear", type: "button", "aria-label": "\u6E05\u7A7A\u9009\u62E9", onClick: clearValue, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
3137
3513
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: open && popupMode === "dropdown", className: `sia-select__dropdown${filteredOptions.length === 0 && !canSubmitInput ? " sia-select__dropdown--empty" : ""}`, children: [
3514
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FloatingScrollbarProvider, { targetRef: listRef }),
3138
3515
  showSearch || allowInput ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "sia-select__search", children: [
3139
3516
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { name: "search", size: 15 }),
3140
3517
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { ref: searchRef, value: query, maxLength: inputMaxLength, onChange: handleSearchChange, onKeyDown: (event) => handleInteractionKeyDown(event, true), placeholder: searchPlaceholder, "aria-label": searchPlaceholder })
@@ -3265,7 +3642,7 @@ var Select = (0, import_react18.forwardRef)(function Select2({
3265
3642
  });
3266
3643
 
3267
3644
  // src/components/Upload.tsx
3268
- var import_react19 = require("react");
3645
+ var import_react21 = require("react");
3269
3646
  var import_jsx_runtime20 = require("react/jsx-runtime");
3270
3647
  var LIST_IGNORE = /* @__PURE__ */ Symbol("SIA_UPLOAD_LIST_IGNORE");
3271
3648
  function UploadRoot({
@@ -3288,9 +3665,9 @@ function UploadRoot({
3288
3665
  onDrop,
3289
3666
  ...props
3290
3667
  }) {
3291
- const inputRef = (0, import_react19.useRef)(null);
3292
- const filesRef = (0, import_react19.useRef)(fileList ?? defaultFileList);
3293
- const id = (0, import_react19.useId)();
3668
+ const inputRef = (0, import_react21.useRef)(null);
3669
+ const filesRef = (0, import_react21.useRef)(fileList ?? defaultFileList);
3670
+ const id = (0, import_react21.useId)();
3294
3671
  const [files, setFiles] = useControllableState({ value: fileList, defaultValue: defaultFileList });
3295
3672
  filesRef.current = files;
3296
3673
  function emit(file, nextList) {
@@ -3513,12 +3890,12 @@ function Breadcrumb({ items, separator = "/", itemRender, className = "", ...pro
3513
3890
  }
3514
3891
 
3515
3892
  // src/components/Typography.tsx
3516
- var import_react21 = require("react");
3893
+ var import_react23 = require("react");
3517
3894
 
3518
3895
  // src/components/TextArea.tsx
3519
- var import_react20 = require("react");
3896
+ var import_react22 = require("react");
3520
3897
  var import_jsx_runtime23 = require("react/jsx-runtime");
3521
- var TextArea = (0, import_react20.forwardRef)(function TextArea2({
3898
+ var TextArea = (0, import_react22.forwardRef)(function TextArea2({
3522
3899
  label,
3523
3900
  hint,
3524
3901
  status = "default",
@@ -3536,9 +3913,9 @@ var TextArea = (0, import_react20.forwardRef)(function TextArea2({
3536
3913
  ...props
3537
3914
  }, ref) {
3538
3915
  const size = useControlSize(sizeProp);
3539
- const fallbackId = (0, import_react20.useId)();
3916
+ const fallbackId = (0, import_react22.useId)();
3540
3917
  const textAreaId = id ?? fallbackId;
3541
- const [uncontrolledValue, setUncontrolledValue] = (0, import_react20.useState)(() => defaultValue === void 0 ? "" : String(defaultValue));
3918
+ const [uncontrolledValue, setUncontrolledValue] = (0, import_react22.useState)(() => defaultValue === void 0 ? "" : String(defaultValue));
3542
3919
  const currentText = value !== void 0 ? String(value) : uncontrolledValue;
3543
3920
  const floating = useFloatingPlaceholder({ mode: placeholderMode, placeholder, filled: currentText.length > 0 });
3544
3921
  const hintId = `${textAreaId}-hint`;
@@ -3599,26 +3976,26 @@ function TypographyContent({
3599
3976
  className = "",
3600
3977
  ...props
3601
3978
  }) {
3602
- const contentRef = (0, import_react21.useRef)(null);
3603
- const editRef = (0, import_react21.useRef)(null);
3604
- const timer = (0, import_react21.useRef)();
3605
- const [localText, setLocalText] = (0, import_react21.useState)();
3606
- const [draft, setDraft] = (0, import_react21.useState)("");
3607
- const [editing, setEditing] = (0, import_react21.useState)(false);
3608
- const [copied, setCopied] = (0, import_react21.useState)(false);
3609
- const [copyError, setCopyError] = (0, import_react21.useState)(false);
3610
- const [expanded, setExpanded] = (0, import_react21.useState)(false);
3611
- const [overflow, setOverflow] = (0, import_react21.useState)(false);
3979
+ const contentRef = (0, import_react23.useRef)(null);
3980
+ const editRef = (0, import_react23.useRef)(null);
3981
+ const timer = (0, import_react23.useRef)();
3982
+ const [localText, setLocalText] = (0, import_react23.useState)();
3983
+ const [draft, setDraft] = (0, import_react23.useState)("");
3984
+ const [editing, setEditing] = (0, import_react23.useState)(false);
3985
+ const [copied, setCopied] = (0, import_react23.useState)(false);
3986
+ const [copyError, setCopyError] = (0, import_react23.useState)(false);
3987
+ const [expanded, setExpanded] = (0, import_react23.useState)(false);
3988
+ const [overflow, setOverflow] = (0, import_react23.useState)(false);
3612
3989
  const editConfig = typeof editable === "object" ? editable : void 0;
3613
3990
  const content = editConfig?.text ?? localText ?? children;
3614
3991
  const requestedRows = typeof ellipsis === "object" ? ellipsis.rows ?? 1 : 1;
3615
3992
  const rows = Number.isFinite(requestedRows) ? Math.max(1, Math.floor(requestedRows)) : 1;
3616
3993
  const expandable = typeof ellipsis === "object" && ellipsis.expandable;
3617
- (0, import_react21.useEffect)(() => {
3994
+ (0, import_react23.useEffect)(() => {
3618
3995
  setLocalText(void 0);
3619
3996
  }, [children]);
3620
- (0, import_react21.useEffect)(() => () => clearTimeout(timer.current), []);
3621
- (0, import_react21.useLayoutEffect)(() => {
3997
+ (0, import_react23.useEffect)(() => () => clearTimeout(timer.current), []);
3998
+ (0, import_react23.useLayoutEffect)(() => {
3622
3999
  const element = contentRef.current;
3623
4000
  if (!element || !ellipsis || editing || expanded) return;
3624
4001
  const measure = () => setOverflow(element.scrollHeight > element.clientHeight + 1 || element.scrollWidth > element.clientWidth + 1);
@@ -3727,10 +4104,10 @@ function TypographyRoot({ className = "", ...props }) {
3727
4104
  var Typography = Object.assign(TypographyRoot, { Title, Text, Paragraph, Link });
3728
4105
 
3729
4106
  // src/components/FloatButton.tsx
3730
- var import_react22 = require("react");
4107
+ var import_react24 = require("react");
3731
4108
  var import_jsx_runtime25 = require("react/jsx-runtime");
3732
- var GroupShape = (0, import_react22.createContext)(void 0);
3733
- var FloatButtonRoot = (0, import_react22.forwardRef)(function FloatButton({
4109
+ var GroupShape = (0, import_react24.createContext)(void 0);
4110
+ var FloatButtonRoot = (0, import_react24.forwardRef)(function FloatButton({
3734
4111
  icon,
3735
4112
  description,
3736
4113
  tooltip,
@@ -3743,7 +4120,7 @@ var FloatButtonRoot = (0, import_react22.forwardRef)(function FloatButton({
3743
4120
  children,
3744
4121
  ...props
3745
4122
  }, ref) {
3746
- const groupShape = (0, import_react22.useContext)(GroupShape);
4123
+ const groupShape = (0, import_react24.useContext)(GroupShape);
3747
4124
  const label = props["aria-label"] ?? (typeof tooltip === "string" ? tooltip : typeof description === "string" ? description : "\u60AC\u6D6E\u64CD\u4F5C");
3748
4125
  const button = /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3749
4126
  "button",
@@ -3781,10 +4158,10 @@ function FloatButtonGroup({
3781
4158
  ...props
3782
4159
  }) {
3783
4160
  const [visible, setVisible] = useControllableState({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });
3784
- const rootRef = (0, import_react22.useRef)(null);
3785
- const triggerRef = (0, import_react22.useRef)(null);
3786
- const id = (0, import_react22.useId)();
3787
- (0, import_react22.useEffect)(() => {
4161
+ const rootRef = (0, import_react24.useRef)(null);
4162
+ const triggerRef = (0, import_react24.useRef)(null);
4163
+ const id = (0, import_react24.useId)();
4164
+ (0, import_react24.useEffect)(() => {
3788
4165
  if (!trigger || !visible) return;
3789
4166
  const close = (event) => {
3790
4167
  if (!rootRef.current?.contains(event.target)) setVisible(false);
@@ -3838,8 +4215,8 @@ function FloatButtonGroup({
3838
4215
  ) });
3839
4216
  }
3840
4217
  function FloatButtonBackTop({ target, visibilityHeight = 400, behavior = "smooth", onClick, icon, tooltip = "\u8FD4\u56DE\u9876\u90E8", ...props }) {
3841
- const [visible, setVisible] = (0, import_react22.useState)(false);
3842
- (0, import_react22.useEffect)(() => {
4218
+ const [visible, setVisible] = (0, import_react24.useState)(false);
4219
+ (0, import_react24.useEffect)(() => {
3843
4220
  const element = target ? target() : window;
3844
4221
  if (!element) return;
3845
4222
  const update = () => setVisible((element === window ? window.scrollY : element.scrollTop) >= visibilityHeight);