@farmzone/fz-react-ui 1.0.18 → 1.0.20

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.cjs CHANGED
@@ -751,7 +751,7 @@ function Slider(props) {
751
751
  RadixSlider__namespace.Track,
752
752
  {
753
753
  className: cn(
754
- "relative h-[3px] grow rounded-full bg-blackA7",
754
+ "relative h-[3px] grow rounded-full bg-gray-200",
755
755
  orientation === "vertical" && "w-[3px] h-full",
756
756
  trackClassName
757
757
  ),
@@ -759,7 +759,7 @@ function Slider(props) {
759
759
  RadixSlider__namespace.Range,
760
760
  {
761
761
  className: cn(
762
- "absolute h-full rounded-full bg-white",
762
+ "absolute h-full rounded-full bg-[#009fe3]",
763
763
  orientation === "vertical" && "w-full",
764
764
  rangeClassName
765
765
  )
@@ -767,17 +767,18 @@ function Slider(props) {
767
767
  )
768
768
  }
769
769
  ),
770
- /* @__PURE__ */ jsxRuntime.jsx(
770
+ (value ?? defaultValue).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
771
771
  RadixSlider__namespace.Thumb,
772
772
  {
773
773
  className: cn(
774
- "block size-5 rounded-[10px] bg-white shadow-[0_2px_10px] shadow-blackA4 hover:bg-violet3 focus:shadow-[0_0_0_5px] focus:shadow-blackA5 focus:outline-none",
774
+ "block size-4 rounded-full bg-white border-2 border-[#009fe3] shadow-md hover:border-[#0090cf] focus:outline-none focus:ring-2 focus:ring-[#009fe3]/40 focus:ring-offset-1",
775
775
  disabled && "cursor-not-allowed opacity-50",
776
776
  thumbClassName
777
777
  ),
778
- "aria-label": ariaLabel
779
- }
780
- )
778
+ "aria-label": index === 0 ? ariaLabel : `${ariaLabel} max`
779
+ },
780
+ index
781
+ ))
781
782
  ]
782
783
  }
783
784
  );
@@ -2462,6 +2463,8 @@ function DatePickerRange(props) {
2462
2463
  endValue = "",
2463
2464
  onRangeChange,
2464
2465
  className = "",
2466
+ width,
2467
+ height,
2465
2468
  editDateSelect = true,
2466
2469
  onKeyDownEnter,
2467
2470
  datePosition = "bottom",
@@ -2572,7 +2575,7 @@ function DatePickerRange(props) {
2572
2575
  }
2573
2576
  };
2574
2577
  const inputClassName = cn(
2575
- "w-full px-2 py-1.25 border border-gray-300 shadow-xs outline-none text-sm rounded-sm pr-7 transition-colors",
2578
+ "w-full h-full px-2 py-1.25 border border-gray-300 shadow-xs outline-none text-sm rounded-sm pr-7 transition-colors",
2576
2579
  disabled ? DATE_PICKER_FIELD_DISABLED_CLASS : "bg-white text-gray-900 focus:border-blue-600"
2577
2580
  );
2578
2581
  const iconWrapperClassName = cn(
@@ -2615,72 +2618,84 @@ function DatePickerRange(props) {
2615
2618
  )
2616
2619
  }
2617
2620
  );
2618
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative w-64 h-8", className), "aria-disabled": disabled, children: [
2619
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-1", children: [
2620
- /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: startAnchorRef, className: "relative flex-1", children: [
2621
- /* @__PURE__ */ jsxRuntime.jsx(
2622
- "input",
2623
- {
2624
- type: "text",
2625
- value: startInputValue,
2626
- onChange: (e) => handleRangeInputChange(e, true),
2627
- placeholder: "\uC2DC\uC791 \uB0A0\uC9DC",
2628
- disabled,
2629
- className: inputClassName,
2630
- maxLength: 10,
2631
- onKeyDown: (e) => {
2632
- if (e.key === "Enter") {
2633
- e.preventDefault();
2634
- handleFieldEnter(startInputValue);
2621
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2622
+ "div",
2623
+ {
2624
+ ref: containerRef,
2625
+ className: cn("relative w-64 h-8", className),
2626
+ style: {
2627
+ width: typeof width === "number" ? `${width}px` : width,
2628
+ height: typeof height === "number" ? `${height}px` : height
2629
+ },
2630
+ "aria-disabled": disabled,
2631
+ children: [
2632
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-1 h-full", children: [
2633
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: startAnchorRef, className: "relative flex-1 h-full", children: [
2634
+ /* @__PURE__ */ jsxRuntime.jsx(
2635
+ "input",
2636
+ {
2637
+ type: "text",
2638
+ value: startInputValue,
2639
+ onChange: (e) => handleRangeInputChange(e, true),
2640
+ placeholder: "\uC2DC\uC791 \uB0A0\uC9DC",
2641
+ disabled,
2642
+ className: inputClassName,
2643
+ maxLength: 10,
2644
+ onKeyDown: (e) => {
2645
+ if (e.key === "Enter") {
2646
+ e.preventDefault();
2647
+ handleFieldEnter(startInputValue);
2648
+ }
2649
+ }
2635
2650
  }
2636
- }
2637
- }
2638
- ),
2639
- /* @__PURE__ */ jsxRuntime.jsx(
2640
- "div",
2641
- {
2642
- onClick: () => {
2643
- if (!disabled) handleCalendarIconClick("start");
2644
- },
2645
- className: iconWrapperClassName,
2646
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: iconClassName })
2647
- }
2648
- )
2649
- ] }),
2650
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-sm w-2 text-center", disabled && "text-neutral-400 opacity-50"), children: "~" }),
2651
- /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: endAnchorRef, className: "relative flex-1", children: [
2652
- /* @__PURE__ */ jsxRuntime.jsx(
2653
- "input",
2654
- {
2655
- type: "text",
2656
- value: endInputValue,
2657
- onChange: (e) => handleRangeInputChange(e, false),
2658
- placeholder: "\uC885\uB8CC \uB0A0\uC9DC",
2659
- disabled,
2660
- className: inputClassName,
2661
- maxLength: 10,
2662
- onKeyDown: (e) => {
2663
- if (e.key === "Enter") {
2664
- e.preventDefault();
2665
- handleFieldEnter(endInputValue);
2651
+ ),
2652
+ /* @__PURE__ */ jsxRuntime.jsx(
2653
+ "div",
2654
+ {
2655
+ onClick: () => {
2656
+ if (!disabled) handleCalendarIconClick("start");
2657
+ },
2658
+ className: iconWrapperClassName,
2659
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: iconClassName })
2666
2660
  }
2667
- }
2668
- }
2669
- ),
2670
- /* @__PURE__ */ jsxRuntime.jsx(
2671
- "div",
2672
- {
2673
- onClick: () => {
2674
- if (!disabled) handleCalendarIconClick("end");
2675
- },
2676
- className: iconWrapperClassName,
2677
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: iconClassName })
2678
- }
2679
- )
2680
- ] })
2681
- ] }),
2682
- calendarNode
2683
- ] });
2661
+ )
2662
+ ] }),
2663
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-sm w-2 text-center", disabled && "text-neutral-400 opacity-50"), children: "~" }),
2664
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: endAnchorRef, className: "relative flex-1 h-full", children: [
2665
+ /* @__PURE__ */ jsxRuntime.jsx(
2666
+ "input",
2667
+ {
2668
+ type: "text",
2669
+ value: endInputValue,
2670
+ onChange: (e) => handleRangeInputChange(e, false),
2671
+ placeholder: "\uC885\uB8CC \uB0A0\uC9DC",
2672
+ disabled,
2673
+ className: inputClassName,
2674
+ maxLength: 10,
2675
+ onKeyDown: (e) => {
2676
+ if (e.key === "Enter") {
2677
+ e.preventDefault();
2678
+ handleFieldEnter(endInputValue);
2679
+ }
2680
+ }
2681
+ }
2682
+ ),
2683
+ /* @__PURE__ */ jsxRuntime.jsx(
2684
+ "div",
2685
+ {
2686
+ onClick: () => {
2687
+ if (!disabled) handleCalendarIconClick("end");
2688
+ },
2689
+ className: iconWrapperClassName,
2690
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: iconClassName })
2691
+ }
2692
+ )
2693
+ ] })
2694
+ ] }),
2695
+ calendarNode
2696
+ ]
2697
+ }
2698
+ );
2684
2699
  }
2685
2700
  function DatePickerSingle(props) {
2686
2701
  const {
@@ -2688,6 +2703,8 @@ function DatePickerSingle(props) {
2688
2703
  onChange,
2689
2704
  placeholder = "\uB0A0\uC9DC \uC120\uD0DD",
2690
2705
  className = "",
2706
+ width,
2707
+ height,
2691
2708
  editDateSelect = true,
2692
2709
  onKeyDownEnter,
2693
2710
  datePosition = "bottom",
@@ -2798,56 +2815,70 @@ function DatePickerSingle(props) {
2798
2815
  )
2799
2816
  }
2800
2817
  );
2801
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: cn("relative w-30 h-8", className), "aria-disabled": disabled, children: [
2802
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2803
- /* @__PURE__ */ jsxRuntime.jsx(
2804
- "input",
2805
- {
2806
- type: "text",
2807
- value: inputValue,
2808
- onChange: handleInputChange,
2809
- onBlur: () => onBlur && handleInputBlur(),
2810
- placeholder,
2811
- disabled,
2812
- className: cn(
2813
- "w-full px-2 py-1.25 border text-sm rounded-sm outline-none shadow-xs transition-colors",
2814
- validation ? "border-red-600 focus:border-blue-600 focus-visible:border-blue-600 focus-visible:ring-1 focus-visible:ring-blue-600/30 focus-visible:outline-none" : "border-gray-300 focus:border-blue-600 focus-visible:border-blue-600 focus-visible:ring-1 focus-visible:ring-blue-600/30 focus-visible:outline-none",
2815
- disabled ? DATE_PICKER_FIELD_DISABLED_CLASS : "bg-white text-gray-900"
2816
- ),
2817
- maxLength: 10,
2818
- onKeyDown: (e) => {
2819
- if (e.key === "Enter") {
2820
- e.preventDefault();
2821
- handleFieldEnter(inputValue);
2818
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2819
+ "div",
2820
+ {
2821
+ ref: containerRef,
2822
+ className: cn("relative w-30 h-8", className),
2823
+ style: {
2824
+ width: typeof width === "number" ? `${width}px` : width,
2825
+ height: typeof height === "number" ? `${height}px` : height
2826
+ },
2827
+ "aria-disabled": disabled,
2828
+ children: [
2829
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full", children: [
2830
+ /* @__PURE__ */ jsxRuntime.jsx(
2831
+ "input",
2832
+ {
2833
+ type: "text",
2834
+ value: inputValue,
2835
+ onChange: handleInputChange,
2836
+ onBlur: () => onBlur && handleInputBlur(),
2837
+ placeholder,
2838
+ disabled,
2839
+ className: cn(
2840
+ "w-full h-full px-2 py-1.25 border text-sm rounded-sm outline-none shadow-xs transition-colors",
2841
+ validation ? "border-red-600 focus:border-blue-600 focus-visible:border-blue-600 focus-visible:ring-1 focus-visible:ring-blue-600/30 focus-visible:outline-none" : "border-gray-300 focus:border-blue-600 focus-visible:border-blue-600 focus-visible:ring-1 focus-visible:ring-blue-600/30 focus-visible:outline-none",
2842
+ disabled ? DATE_PICKER_FIELD_DISABLED_CLASS : "bg-white text-gray-900"
2843
+ ),
2844
+ maxLength: 10,
2845
+ onKeyDown: (e) => {
2846
+ if (e.key === "Enter") {
2847
+ e.preventDefault();
2848
+ handleFieldEnter(inputValue);
2849
+ }
2850
+ },
2851
+ "data-date-input": "true"
2822
2852
  }
2823
- },
2824
- "data-date-input": "true"
2825
- }
2826
- ),
2827
- /* @__PURE__ */ jsxRuntime.jsx(
2828
- "div",
2829
- {
2830
- role: "button",
2831
- tabIndex: -1,
2832
- "aria-hidden": disabled,
2833
- onClick: () => {
2834
- if (!disabled) toggleCalendar(inputValue);
2835
- },
2836
- className: cn(
2837
- "absolute right-1 top-1/2 -translate-y-1/2 rounded-full p-1",
2838
- disabled ? DATE_PICKER_ICON_DISABLED_CLASS : DATE_PICKER_ICON_ENABLED_CLASS
2839
2853
  ),
2840
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: cn(disabled ? "text-neutral-400 opacity-50" : "text-gray-600") })
2841
- }
2842
- )
2843
- ] }),
2844
- calendarNode
2845
- ] });
2854
+ /* @__PURE__ */ jsxRuntime.jsx(
2855
+ "div",
2856
+ {
2857
+ role: "button",
2858
+ tabIndex: -1,
2859
+ "aria-hidden": disabled,
2860
+ onClick: () => {
2861
+ if (!disabled) toggleCalendar(inputValue);
2862
+ },
2863
+ className: cn(
2864
+ "absolute right-1 top-1/2 -translate-y-1/2 rounded-full p-1",
2865
+ disabled ? DATE_PICKER_ICON_DISABLED_CLASS : DATE_PICKER_ICON_ENABLED_CLASS
2866
+ ),
2867
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 15, className: cn(disabled ? "text-neutral-400 opacity-50" : "text-gray-600") })
2868
+ }
2869
+ )
2870
+ ] }),
2871
+ calendarNode
2872
+ ]
2873
+ }
2874
+ );
2846
2875
  }
2847
2876
  function DatePicker(props) {
2848
2877
  const {
2849
2878
  isRange,
2850
2879
  className,
2880
+ width,
2881
+ height,
2851
2882
  editDateSelect,
2852
2883
  onKeyDownEnter,
2853
2884
  datePosition,
@@ -2866,6 +2897,8 @@ function DatePicker(props) {
2866
2897
  endValue,
2867
2898
  onRangeChange,
2868
2899
  className,
2900
+ width,
2901
+ height,
2869
2902
  editDateSelect,
2870
2903
  onKeyDownEnter,
2871
2904
  datePosition,
@@ -2885,6 +2918,8 @@ function DatePicker(props) {
2885
2918
  onChange,
2886
2919
  placeholder,
2887
2920
  className,
2921
+ width,
2922
+ height,
2888
2923
  editDateSelect,
2889
2924
  onKeyDownEnter,
2890
2925
  datePosition,
@@ -6148,7 +6183,7 @@ function FilePreviewViewerSession(props) {
6148
6183
  React6.useEffect(() => {
6149
6184
  if (!showNavigation) return;
6150
6185
  const [prevIndex, nextIndex] = getAdjacentIndexes(currentIndex, fileArray.length);
6151
- const urlsToPreload = [prevIndex, nextIndex].filter((idx) => idx !== currentIndex).map((idx) => fileArray[idx]);
6186
+ const urlsToPreload = [prevIndex, nextIndex].filter((idx) => idx !== currentIndex).map((idx) => fileArray[idx]).filter((url) => url !== void 0);
6152
6187
  preloadPreviewImages(urlsToPreload);
6153
6188
  }, [showNavigation, currentIndex, fileArray]);
6154
6189
  React6.useEffect(() => {
@@ -7784,7 +7819,7 @@ var SubmitForm = Object.assign(SubmitFormRoot, {
7784
7819
  function LabeledFilterOption(props) {
7785
7820
  const { label, children, gap } = props;
7786
7821
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginLeft: gap }, className: "flex flex-row items-center gap-4", children: [
7787
- label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-60 shrink-0", children: label }),
7822
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-gray-60 shrink-0 select-none", children: label }),
7788
7823
  children
7789
7824
  ] });
7790
7825
  }
@@ -7820,8 +7855,9 @@ function PageFilter(props) {
7820
7855
  onChange({ [key]: value });
7821
7856
  if (autoSubmit) pendingAutoSubmitRef.current = { key, value };
7822
7857
  };
7823
- const handleRadioChange = (key) => (value) => {
7858
+ const handleRadioChange = (key, autoSubmit) => (value) => {
7824
7859
  onChange({ [key]: value });
7860
+ if (autoSubmit) pendingAutoSubmitRef.current = { key, value };
7825
7861
  };
7826
7862
  const handleDateChange = (key) => (date) => {
7827
7863
  onChange({ [key]: date });
@@ -7829,8 +7865,10 @@ function PageFilter(props) {
7829
7865
  const handleRangeChangeCurried = (startKey, endKey) => (start, end) => {
7830
7866
  onChange({ [startKey]: start, [endKey]: end });
7831
7867
  };
7832
- const handleCheckboxChange = (key) => (checked) => {
7833
- onChange({ [key]: checked ? "true" : "false" });
7868
+ const handleCheckboxChange = (key, autoSubmit) => (checked) => {
7869
+ const value = checked ? "true" : "false";
7870
+ onChange({ [key]: value });
7871
+ if (autoSubmit) pendingAutoSubmitRef.current = { key, value };
7834
7872
  };
7835
7873
  const handleSubmit = () => {
7836
7874
  pendingAutoSubmitRef.current = null;
@@ -7876,7 +7914,7 @@ function PageFilter(props) {
7876
7914
  {
7877
7915
  name: String(optionKey),
7878
7916
  value: currentValue,
7879
- onChange: handleRadioChange(optionKey),
7917
+ onChange: handleRadioChange(optionKey, option.autoSubmit),
7880
7918
  options: option.options,
7881
7919
  direction: "horizontal"
7882
7920
  }
@@ -7908,7 +7946,7 @@ function PageFilter(props) {
7908
7946
  checked: currentValue === "true",
7909
7947
  name: String(optionKey),
7910
7948
  value: currentValue,
7911
- onChange: handleCheckboxChange(optionKey)
7949
+ onChange: handleCheckboxChange(optionKey, option.autoSubmit)
7912
7950
  }
7913
7951
  ) }, String(optionKey));
7914
7952
  default: {
@@ -8619,7 +8657,9 @@ function BaseUploader(props) {
8619
8657
  maxSize,
8620
8658
  disabled = false,
8621
8659
  placeholder,
8622
- className
8660
+ className,
8661
+ width,
8662
+ height
8623
8663
  } = props;
8624
8664
  const inputRef = React6.useRef(null);
8625
8665
  const inputId = React6.useId();
@@ -8662,7 +8702,7 @@ function BaseUploader(props) {
8662
8702
  };
8663
8703
  const showZone = multiple || files.length === 0;
8664
8704
  const acceptLabel = accept ? accept.split(",").map((s) => s.trim().toUpperCase()).join(", ") : "\uBAA8\uB4E0 \uD615\uC2DD";
8665
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [
8705
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-3", className), style: { width: typeof width === "number" ? `${width}px` : width }, children: [
8666
8706
  /* @__PURE__ */ jsxRuntime.jsx(
8667
8707
  "input",
8668
8708
  {
@@ -8696,6 +8736,7 @@ function BaseUploader(props) {
8696
8736
  setIsDragging(false);
8697
8737
  },
8698
8738
  onDrop: handleDrop,
8739
+ style: { minHeight: typeof height === "number" ? `${height}px` : height ?? "7rem" },
8699
8740
  className: cn(
8700
8741
  "flex flex-col items-center justify-center gap-2 min-h-28 w-full rounded-lg bg-gray-50/50 border-[1.5px] border-dashed",
8701
8742
  disabled ? "cursor-not-allowed border-gray-200 bg-gray-100 opacity-60" : "cursor-pointer hover:bg-gray-50",
@@ -8741,7 +8782,7 @@ function BaseUploader(props) {
8741
8782
  var EXCEL_ACCEPT = ".xlsx,.xls,.csv";
8742
8783
  var MAX_EXCEL_BYTES = 10 * 1024 * 1024;
8743
8784
  function ExcelUploader(props) {
8744
- const { files, onChange, disabled, className } = props;
8785
+ const { files, onChange, disabled, className, width, height } = props;
8745
8786
  return /* @__PURE__ */ jsxRuntime.jsx(
8746
8787
  BaseUploader,
8747
8788
  {
@@ -8752,7 +8793,9 @@ function ExcelUploader(props) {
8752
8793
  maxSize: MAX_EXCEL_BYTES,
8753
8794
  disabled,
8754
8795
  placeholder: "\uC5D1\uC140 \uD30C\uC77C\uC744 \uD074\uB9AD\uD558\uAC70\uB098 \uB4DC\uB798\uADF8\uD558\uC138\uC694",
8755
- className
8796
+ className,
8797
+ width,
8798
+ height
8756
8799
  }
8757
8800
  );
8758
8801
  }
@@ -8849,7 +8892,7 @@ var compressImage = (file) => {
8849
8892
  }).catch(() => file);
8850
8893
  };
8851
8894
  function FileUploader(props) {
8852
- const { files, onChange, multiple = true, disabled = false, className } = props;
8895
+ const { files, onChange, multiple = true, disabled = false, className, width, height } = props;
8853
8896
  const inputRef = React6.useRef(null);
8854
8897
  const containerRef = React6.useRef(null);
8855
8898
  const [isDragging, setIsDragging] = React6.useState(false);
@@ -8956,121 +8999,129 @@ function FileUploader(props) {
8956
8999
  setError("");
8957
9000
  };
8958
9001
  const isProcessing = processingCount > 0;
8959
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [
8960
- /* @__PURE__ */ jsxRuntime.jsx(
8961
- "input",
8962
- {
8963
- ref: inputRef,
8964
- type: "file",
8965
- multiple,
8966
- accept: "image/jpeg,image/png,image/webp,image/heic,image/heif,application/pdf,.heic,.heif",
8967
- disabled,
8968
- className: "hidden",
8969
- onChange: (e) => {
8970
- handleFiles(e.target.files);
8971
- if (inputRef.current) inputRef.current.value = "";
8972
- }
8973
- }
8974
- ),
8975
- /* @__PURE__ */ jsxRuntime.jsxs(
8976
- "div",
8977
- {
8978
- ref: containerRef,
8979
- onClick: isProcessing || disabled ? void 0 : () => inputRef.current?.click(),
8980
- onDragOver: handleDragOver,
8981
- onDragEnter: handleDragOver,
8982
- onDragLeave: handleDragLeave,
8983
- onDrop: handleDrop,
8984
- className: cn(
8985
- "relative w-full rounded-lg bg-gray-50/50 border-[1.5px] border-dashed",
8986
- disabled ? "cursor-not-allowed border-gray-200 bg-gray-100 opacity-60" : isProcessing ? "cursor-default border-gray-300" : "cursor-pointer hover:bg-gray-50",
8987
- isDragging ? "border-blue-500 bg-blue-50" : "border-gray-300",
8988
- error && !isDragging ? "border-red-300 bg-red-50" : "",
8989
- files.length > 0 ? "p-3" : "flex flex-col items-center justify-center gap-1 min-h-32"
9002
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9003
+ "div",
9004
+ {
9005
+ className: cn("space-y-3", className),
9006
+ style: { width: typeof width === "number" ? `${width}px` : width },
9007
+ children: [
9008
+ /* @__PURE__ */ jsxRuntime.jsx(
9009
+ "input",
9010
+ {
9011
+ ref: inputRef,
9012
+ type: "file",
9013
+ multiple,
9014
+ accept: "image/jpeg,image/png,image/webp,image/heic,image/heif,application/pdf,.heic,.heif",
9015
+ disabled,
9016
+ className: "hidden",
9017
+ onChange: (e) => {
9018
+ handleFiles(e.target.files);
9019
+ if (inputRef.current) inputRef.current.value = "";
9020
+ }
9021
+ }
8990
9022
  ),
8991
- children: [
8992
- isProcessing && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 rounded-lg bg-white/80", children: [
8993
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-blue-400 border-t-transparent" }),
8994
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600", children: "\uCC98\uB9AC \uC911..." })
8995
- ] }),
8996
- files.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8997
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3", children: files.map((file, idx) => {
8998
- const url = previewUrls[idx];
8999
- const isImage = file.type.startsWith("image/");
9000
- return /* @__PURE__ */ jsxRuntime.jsxs(
9001
- "div",
9002
- {
9003
- className: "group relative overflow-hidden rounded-lg border border-gray-200 bg-white shadow-sm transition-shadow hover:shadow-md",
9004
- children: [
9005
- /* @__PURE__ */ jsxRuntime.jsx(
9006
- "button",
9007
- {
9008
- type: "button",
9009
- onClick: (e) => {
9010
- e.stopPropagation();
9011
- viewer.open(idx);
9012
- },
9013
- className: "block w-full aspect-square cursor-pointer",
9014
- "aria-label": `${file.name} \uBBF8\uB9AC\uBCF4\uAE30`,
9015
- children: isImage && url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt: file.name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full flex-col items-center justify-center bg-gray-50 text-gray-400", children: [
9016
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "w-8 h-8" }),
9017
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 max-w-full truncate px-1 text-center text-[10px]", children: file.name })
9018
- ] })
9019
- }
9020
- ),
9021
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-1 border-t border-gray-100 px-1.5 py-1", children: [
9022
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-[10px] text-gray-600", title: file.name, children: file.name }),
9023
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-gray-400", children: formatFileSize(file.size) })
9024
- ] }),
9025
- !disabled && /* @__PURE__ */ jsxRuntime.jsx(
9026
- "button",
9027
- {
9028
- type: "button",
9029
- onClick: (e) => {
9030
- e.stopPropagation();
9031
- removeFile(idx);
9032
- },
9033
- className: "absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition-opacity group-hover:opacity-100 cursor-pointer",
9034
- "aria-label": "\uD30C\uC77C \uC81C\uAC70",
9035
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3 h-3" })
9036
- }
9037
- )
9038
- ]
9039
- },
9040
- `${file.name}-${idx}`
9041
- );
9042
- }) }),
9043
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between text-xs text-gray-500", children: [
9044
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9045
- files.length,
9046
- "\uAC1C \uD30C\uC77C \uC120\uD0DD\uB428",
9047
- !disabled && " \xB7 \uD074\uB9AD\uD558\uC5EC \uCD94\uAC00"
9023
+ /* @__PURE__ */ jsxRuntime.jsxs(
9024
+ "div",
9025
+ {
9026
+ ref: containerRef,
9027
+ onClick: isProcessing || disabled ? void 0 : () => inputRef.current?.click(),
9028
+ onDragOver: handleDragOver,
9029
+ onDragEnter: handleDragOver,
9030
+ onDragLeave: handleDragLeave,
9031
+ onDrop: handleDrop,
9032
+ className: cn(
9033
+ "relative w-full rounded-lg bg-gray-50/50 border-[1.5px] border-dashed",
9034
+ disabled ? "cursor-not-allowed border-gray-200 bg-gray-100 opacity-60" : isProcessing ? "cursor-default border-gray-300" : "cursor-pointer hover:bg-gray-50",
9035
+ isDragging ? "border-blue-500 bg-blue-50" : "border-gray-300",
9036
+ error && !isDragging ? "border-red-300 bg-red-50" : "",
9037
+ files.length > 0 ? "p-3" : "flex flex-col items-center justify-center gap-1"
9038
+ ),
9039
+ style: files.length === 0 ? { minHeight: typeof height === "number" ? `${height}px` : height ?? "8rem" } : void 0,
9040
+ children: [
9041
+ isProcessing && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 rounded-lg bg-white/80", children: [
9042
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-blue-400 border-t-transparent" }),
9043
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600", children: "\uCC98\uB9AC \uC911..." })
9048
9044
  ] }),
9049
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9050
- "\uCD1D ",
9051
- formatFileSize(files.reduce((sum, f) => sum + f.size, 0))
9045
+ files.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9046
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3", children: files.map((file, idx) => {
9047
+ const url = previewUrls[idx];
9048
+ const isImage = file.type.startsWith("image/");
9049
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9050
+ "div",
9051
+ {
9052
+ className: "group relative overflow-hidden rounded-lg border border-gray-200 bg-white shadow-sm transition-shadow hover:shadow-md",
9053
+ children: [
9054
+ /* @__PURE__ */ jsxRuntime.jsx(
9055
+ "button",
9056
+ {
9057
+ type: "button",
9058
+ onClick: (e) => {
9059
+ e.stopPropagation();
9060
+ viewer.open(idx);
9061
+ },
9062
+ className: "block w-full aspect-square cursor-pointer",
9063
+ "aria-label": `${file.name} \uBBF8\uB9AC\uBCF4\uAE30`,
9064
+ children: isImage && url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: url, alt: file.name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full w-full flex-col items-center justify-center bg-gray-50 text-gray-400", children: [
9065
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "w-8 h-8" }),
9066
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 max-w-full truncate px-1 text-center text-[10px]", children: file.name })
9067
+ ] })
9068
+ }
9069
+ ),
9070
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-1 border-t border-gray-100 px-1.5 py-1", children: [
9071
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-[10px] text-gray-600", title: file.name, children: file.name }),
9072
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-[10px] text-gray-400", children: formatFileSize(file.size) })
9073
+ ] }),
9074
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx(
9075
+ "button",
9076
+ {
9077
+ type: "button",
9078
+ onClick: (e) => {
9079
+ e.stopPropagation();
9080
+ removeFile(idx);
9081
+ },
9082
+ className: "absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition-opacity group-hover:opacity-100 cursor-pointer",
9083
+ "aria-label": "\uD30C\uC77C \uC81C\uAC70",
9084
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3 h-3" })
9085
+ }
9086
+ )
9087
+ ]
9088
+ },
9089
+ `${file.name}-${idx}`
9090
+ );
9091
+ }) }),
9092
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex items-center justify-between text-xs text-gray-500", children: [
9093
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9094
+ files.length,
9095
+ "\uAC1C \uD30C\uC77C \uC120\uD0DD\uB428",
9096
+ !disabled && " \xB7 \uD074\uB9AD\uD558\uC5EC \uCD94\uAC00"
9097
+ ] }),
9098
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9099
+ "\uCD1D ",
9100
+ formatFileSize(files.reduce((sum, f) => sum + f.size, 0))
9101
+ ] })
9102
+ ] })
9103
+ ] }) : isDragging ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-1 text-blue-500", children: [
9104
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-semibold flex gap-1", children: [
9105
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileUp, { size: 15, className: "mt-[1px]" }),
9106
+ "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uC544\uC8FC\uC138\uC694"
9107
+ ] }),
9108
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium", children: "\uB4DC\uB86D\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uC5C5\uB85C\uB4DC\uB429\uB2C8\uB2E4." })
9109
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9110
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600 flex gap-1", children: [
9111
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileUp, { size: 15, className: "text-gray-400 mt-[1px]" }),
9112
+ " \uD074\uB9AD\uD558\uC5EC \uD30C\uC77C\uC744 \uC120\uD0DD\uD558\uAC70\uB098 \uB4DC\uB798\uADF8\uD558\uC138\uC694"
9113
+ ] }),
9114
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: "\uC774\uBBF8\uC9C0(JPG \xB7 PNG \xB7 WEBP \xB7 HEIC, \uCD5C\uB300 50MB) \xB7 PDF(\uCD5C\uB300 10MB)" }),
9115
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: multiple ? `\uCD5C\uB300 ${MAX_FILES}\uAC1C \xB7 \uC804\uCCB4 20MB \uC774\uD558` : "\uB2E8\uC77C \uD30C\uC77C" })
9052
9116
  ] })
9053
- ] })
9054
- ] }) : isDragging ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-1 text-blue-500", children: [
9055
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-semibold flex gap-1", children: [
9056
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileUp, { size: 15, className: "mt-[1px]" }),
9057
- "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uC544\uC8FC\uC138\uC694"
9058
- ] }),
9059
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium", children: "\uB4DC\uB86D\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uC5C5\uB85C\uB4DC\uB429\uB2C8\uB2E4." })
9060
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9061
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600 flex gap-1", children: [
9062
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileUp, { size: 15, className: "text-gray-400 mt-[1px]" }),
9063
- " \uD074\uB9AD\uD558\uC5EC \uD30C\uC77C\uC744 \uC120\uD0DD\uD558\uAC70\uB098 \uB4DC\uB798\uADF8\uD558\uC138\uC694"
9064
- ] }),
9065
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: "\uC774\uBBF8\uC9C0(JPG \xB7 PNG \xB7 WEBP \xB7 HEIC, \uCD5C\uB300 50MB) \xB7 PDF(\uCD5C\uB300 10MB)" }),
9066
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: multiple ? `\uCD5C\uB300 ${MAX_FILES}\uAC1C \xB7 \uC804\uCCB4 20MB \uC774\uD558` : "\uB2E8\uC77C \uD30C\uC77C" })
9067
- ] })
9068
- ]
9069
- }
9070
- ),
9071
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-line text-xs text-red-500 bg-red-50 border border-red-200 rounded px-3 py-2", children: error }),
9072
- /* @__PURE__ */ jsxRuntime.jsx(FilePreviewViewer, { ...viewer.viewerProps, fileTypes, fileNames: files.map((f) => f.name) })
9073
- ] });
9117
+ ]
9118
+ }
9119
+ ),
9120
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-line text-xs text-red-500 bg-red-50 border border-red-200 rounded px-3 py-2", children: error }),
9121
+ /* @__PURE__ */ jsxRuntime.jsx(FilePreviewViewer, { ...viewer.viewerProps, fileTypes, fileNames: files.map((f) => f.name) })
9122
+ ]
9123
+ }
9124
+ );
9074
9125
  }
9075
9126
  var VARIANT_STYLES2 = {
9076
9127
  light: {