@farmzone/fz-react-ui 1.1.5 → 1.1.6

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.d.cts CHANGED
@@ -91,6 +91,8 @@ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
91
91
  leftIcon?: ReactNode;
92
92
  rightIcon?: ReactNode;
93
93
  showPasswordToggle?: boolean;
94
+ clearable?: boolean;
95
+ onClear?: () => void;
94
96
  }
95
97
  declare function Input(props: InputProps): react.JSX.Element;
96
98
 
@@ -194,6 +196,9 @@ interface SelectOptionType {
194
196
  label: string | ReactNode;
195
197
  value: string;
196
198
  disabled?: boolean;
199
+ icon?: ReactNode;
200
+ avatarUrl?: string;
201
+ avatarAlt?: string;
197
202
  }
198
203
 
199
204
  interface SelectProps<T extends SelectOptionType = SelectOptionType> extends Omit<React.ComponentProps<typeof Select$1>, "onValueChange" | "value" | "defaultValue"> {
@@ -973,6 +978,8 @@ type InputOption<P> = BaseOption<P> & {
973
978
  placeholder?: string;
974
979
  /** 입력창 왼쪽에 돋보기 아이콘을 보여줄지 여부. 기본값 true. */
975
980
  leftIcon?: boolean;
981
+ /** 입력값이 있을 때 x(clear) 버튼을 보여줄지 여부. 기본값 true. */
982
+ canReset?: boolean;
976
983
  };
977
984
  type SelectOption<P> = BaseOption<P> & {
978
985
  type: "select";
package/dist/index.d.ts CHANGED
@@ -91,6 +91,8 @@ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
91
91
  leftIcon?: ReactNode;
92
92
  rightIcon?: ReactNode;
93
93
  showPasswordToggle?: boolean;
94
+ clearable?: boolean;
95
+ onClear?: () => void;
94
96
  }
95
97
  declare function Input(props: InputProps): react.JSX.Element;
96
98
 
@@ -194,6 +196,9 @@ interface SelectOptionType {
194
196
  label: string | ReactNode;
195
197
  value: string;
196
198
  disabled?: boolean;
199
+ icon?: ReactNode;
200
+ avatarUrl?: string;
201
+ avatarAlt?: string;
197
202
  }
198
203
 
199
204
  interface SelectProps<T extends SelectOptionType = SelectOptionType> extends Omit<React.ComponentProps<typeof Select$1>, "onValueChange" | "value" | "defaultValue"> {
@@ -973,6 +978,8 @@ type InputOption<P> = BaseOption<P> & {
973
978
  placeholder?: string;
974
979
  /** 입력창 왼쪽에 돋보기 아이콘을 보여줄지 여부. 기본값 true. */
975
980
  leftIcon?: boolean;
981
+ /** 입력값이 있을 때 x(clear) 버튼을 보여줄지 여부. 기본값 true. */
982
+ canReset?: boolean;
976
983
  };
977
984
  type SelectOption<P> = BaseOption<P> & {
978
985
  type: "select";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import * as React6 from 'react';
6
6
  import React6__default, { forwardRef, useState, useRef, useEffect, useImperativeHandle, useCallback, memo, createContext, useContext, useMemo, useId, useLayoutEffect, useDeferredValue, Fragment as Fragment$1 } from 'react';
7
7
  import { Slot } from '@radix-ui/react-slot';
8
8
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
9
- import { ChevronLeft, ChevronRight, FileText, ZoomIn, ZoomOut, RotateCcw, RotateCw, Download, X, Heading1, Heading2, Heading3, Heading4, Bold, Italic, Strikethrough, Code, AlignLeft, AlignCenter, AlignRight, List, ListOrdered, Quote, FileCode, Table as Table$1, Plus, Minus, Trash2, EyeOff, Eye, Check, CircleX, ChevronDown, Calendar, CircleIcon, ChevronUp, Search, TriangleAlert, Info, Pencil, BadgePlus, FileSearch2, Upload, FileUp, PanelRightClose, PanelLeftClose, ChevronFirst, ChevronLast } from 'lucide-react';
9
+ import { ChevronLeft, ChevronRight, FileText, ZoomIn, ZoomOut, RotateCcw, RotateCw, Download, X, Heading1, Heading2, Heading3, Heading4, Bold, Italic, Strikethrough, Code, AlignLeft, AlignCenter, AlignRight, List, ListOrdered, Quote, FileCode, Table as Table$1, Plus, Minus, Trash2, CircleX, EyeOff, Eye, Check, ChevronDown, Calendar, CircleIcon, ChevronUp, Search, TriangleAlert, Info, Pencil, BadgePlus, FileSearch2, Upload, FileUp, PanelRightClose, PanelLeftClose, ChevronFirst, ChevronLast } from 'lucide-react';
10
10
  import * as SwitchPrimitive from '@radix-ui/react-switch';
11
11
  import * as RadixSlider from '@radix-ui/react-slider';
12
12
  import * as SelectPrimitive from '@radix-ui/react-select';
@@ -445,6 +445,8 @@ function Input2(props) {
445
445
  leftIcon,
446
446
  rightIcon,
447
447
  showPasswordToggle = true,
448
+ clearable = false,
449
+ onClear,
448
450
  onChange,
449
451
  ...rest
450
452
  } = props;
@@ -474,7 +476,16 @@ function Input2(props) {
474
476
  const shouldShowPasswordToggle = type === "password" && showPasswordToggle;
475
477
  const actualType = type === "password" && showPassword ? "text" : type;
476
478
  const handlePasswordToggle = () => setShowPassword((prev) => !prev);
477
- const finalRightIcon = rightIcon || (shouldShowPasswordToggle ? /* @__PURE__ */ jsx(
479
+ const handleClear = () => onClear?.();
480
+ const shouldShowClearButton = clearable && !disabled && typeof rest.value === "string" && rest.value.length > 0;
481
+ const finalRightIcon = rightIcon || (shouldShowClearButton ? /* @__PURE__ */ jsx(
482
+ "div",
483
+ {
484
+ onClick: handleClear,
485
+ className: "text-muted-foreground hover:text-foreground cursor-pointer transition-colors",
486
+ children: /* @__PURE__ */ jsx(CircleX, { className: "h-4 w-4" })
487
+ }
488
+ ) : null) || (shouldShowPasswordToggle ? /* @__PURE__ */ jsx(
478
489
  "div",
479
490
  {
480
491
  onClick: handlePasswordToggle,
@@ -940,6 +951,29 @@ function SelectScrollDownButton({
940
951
  }
941
952
  );
942
953
  }
954
+ function SelectOptionVisual(props) {
955
+ const { icon, avatarUrl, avatarAlt, fallbackLabel } = props;
956
+ const [hasAvatarError, setHasAvatarError] = useState(false);
957
+ const handleAvatarError = () => setHasAvatarError(true);
958
+ if (avatarUrl && !hasAvatarError) {
959
+ return /* @__PURE__ */ jsx(
960
+ "img",
961
+ {
962
+ src: avatarUrl,
963
+ alt: avatarAlt ?? "",
964
+ className: "size-5 shrink-0 rounded-full object-cover",
965
+ onError: handleAvatarError
966
+ }
967
+ );
968
+ }
969
+ if (avatarUrl && hasAvatarError) {
970
+ return /* @__PURE__ */ jsx("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-gray-200 text-[10px] font-medium text-gray-500", children: fallbackLabel?.charAt(0).toUpperCase() ?? "?" });
971
+ }
972
+ if (icon) {
973
+ return /* @__PURE__ */ jsx("span", { className: "flex size-4 shrink-0 items-center justify-center text-gray-500", children: icon });
974
+ }
975
+ return null;
976
+ }
943
977
 
944
978
  // src/components/Select/config/default.ts
945
979
  var SELECT_BORDER_COLORS = {
@@ -1031,7 +1065,18 @@ function Select2(props) {
1031
1065
  itemClassName,
1032
1066
  option.disabled && cn("opacity-50 cursor-not-allowed text-gray-300 bg-white", disabledItemClassName)
1033
1067
  ),
1034
- children: option.label
1068
+ children: /* @__PURE__ */ jsxs("span", { className: "flex w-full min-w-0 items-center gap-2", children: [
1069
+ /* @__PURE__ */ jsx(
1070
+ SelectOptionVisual,
1071
+ {
1072
+ icon: option.icon,
1073
+ avatarUrl: option.avatarUrl,
1074
+ avatarAlt: option.avatarAlt,
1075
+ fallbackLabel: typeof option.label === "string" ? option.label : void 0
1076
+ }
1077
+ ),
1078
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: option.label })
1079
+ ] })
1035
1080
  },
1036
1081
  String(option.value)
1037
1082
  )) })
@@ -7847,6 +7892,9 @@ function PageFilter(props) {
7847
7892
  const handleInputChange = (key) => (e) => {
7848
7893
  onChange({ [key]: e.target.value });
7849
7894
  };
7895
+ const handleInputClear = (key) => () => {
7896
+ onChange({ [key]: "" });
7897
+ };
7850
7898
  const handleSelectChange = (key, autoSubmit) => (value) => {
7851
7899
  onChange({ [key]: value });
7852
7900
  if (autoSubmit) pendingAutoSubmitRef.current = { key, value };
@@ -7891,6 +7939,8 @@ function PageFilter(props) {
7891
7939
  if (e.key === "Enter") handleSubmit();
7892
7940
  },
7893
7941
  leftIcon: option.leftIcon !== false ? /* @__PURE__ */ jsx(Search, { size: 16 }) : void 0,
7942
+ clearable: option.canReset ?? true,
7943
+ onClear: handleInputClear(optionKey),
7894
7944
  className: option.className
7895
7945
  }
7896
7946
  ) }, String(optionKey));