@farmzone/fz-react-ui 1.1.4 → 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.cjs +64 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +65 -9
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
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"> {
|
|
@@ -966,12 +971,15 @@ type SelectableOption = {
|
|
|
966
971
|
interface BaseOption<P> {
|
|
967
972
|
label?: string;
|
|
968
973
|
key: keyof P;
|
|
974
|
+
className?: string;
|
|
969
975
|
}
|
|
970
976
|
type InputOption<P> = BaseOption<P> & {
|
|
971
977
|
type: "input";
|
|
972
978
|
placeholder?: string;
|
|
973
979
|
/** 입력창 왼쪽에 돋보기 아이콘을 보여줄지 여부. 기본값 true. */
|
|
974
980
|
leftIcon?: boolean;
|
|
981
|
+
/** 입력값이 있을 때 x(clear) 버튼을 보여줄지 여부. 기본값 true. */
|
|
982
|
+
canReset?: boolean;
|
|
975
983
|
};
|
|
976
984
|
type SelectOption<P> = BaseOption<P> & {
|
|
977
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"> {
|
|
@@ -966,12 +971,15 @@ type SelectableOption = {
|
|
|
966
971
|
interface BaseOption<P> {
|
|
967
972
|
label?: string;
|
|
968
973
|
key: keyof P;
|
|
974
|
+
className?: string;
|
|
969
975
|
}
|
|
970
976
|
type InputOption<P> = BaseOption<P> & {
|
|
971
977
|
type: "input";
|
|
972
978
|
placeholder?: string;
|
|
973
979
|
/** 입력창 왼쪽에 돋보기 아이콘을 보여줄지 여부. 기본값 true. */
|
|
974
980
|
leftIcon?: boolean;
|
|
981
|
+
/** 입력값이 있을 때 x(clear) 버튼을 보여줄지 여부. 기본값 true. */
|
|
982
|
+
canReset?: boolean;
|
|
975
983
|
};
|
|
976
984
|
type SelectOption<P> = BaseOption<P> & {
|
|
977
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,
|
|
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
|
|
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:
|
|
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 };
|
|
@@ -7890,7 +7938,10 @@ function PageFilter(props) {
|
|
|
7890
7938
|
onKeyDown: (e) => {
|
|
7891
7939
|
if (e.key === "Enter") handleSubmit();
|
|
7892
7940
|
},
|
|
7893
|
-
leftIcon: option.leftIcon !== false ? /* @__PURE__ */ jsx(Search, { size: 16 }) : void 0
|
|
7941
|
+
leftIcon: option.leftIcon !== false ? /* @__PURE__ */ jsx(Search, { size: 16 }) : void 0,
|
|
7942
|
+
clearable: option.canReset ?? true,
|
|
7943
|
+
onClear: handleInputClear(optionKey),
|
|
7944
|
+
className: option.className
|
|
7894
7945
|
}
|
|
7895
7946
|
) }, String(optionKey));
|
|
7896
7947
|
case "select":
|
|
@@ -7902,7 +7953,8 @@ function PageFilter(props) {
|
|
|
7902
7953
|
options: option.options,
|
|
7903
7954
|
placeholder: option.placeholder || "\uC120\uD0DD",
|
|
7904
7955
|
canReset: option.canReset ?? true,
|
|
7905
|
-
containerClassName: option.containerClassName ?? "w-30"
|
|
7956
|
+
containerClassName: option.containerClassName ?? "w-30",
|
|
7957
|
+
className: option.className
|
|
7906
7958
|
}
|
|
7907
7959
|
) }, String(optionKey));
|
|
7908
7960
|
case "radio":
|
|
@@ -7913,7 +7965,8 @@ function PageFilter(props) {
|
|
|
7913
7965
|
value: currentValue,
|
|
7914
7966
|
onChange: handleRadioChange(optionKey, option.autoSubmit),
|
|
7915
7967
|
options: option.options,
|
|
7916
|
-
direction: "horizontal"
|
|
7968
|
+
direction: "horizontal",
|
|
7969
|
+
containerClassName: option.className
|
|
7917
7970
|
}
|
|
7918
7971
|
) }, String(optionKey));
|
|
7919
7972
|
case "date":
|
|
@@ -7923,7 +7976,8 @@ function PageFilter(props) {
|
|
|
7923
7976
|
value: currentValue,
|
|
7924
7977
|
onChange: handleDateChange(optionKey),
|
|
7925
7978
|
placeholder: option.placeholder,
|
|
7926
|
-
onKeyDownEnter: handleSubmit
|
|
7979
|
+
onKeyDownEnter: handleSubmit,
|
|
7980
|
+
className: option.className
|
|
7927
7981
|
}
|
|
7928
7982
|
) }, String(optionKey));
|
|
7929
7983
|
case "date-range":
|
|
@@ -7933,7 +7987,8 @@ function PageFilter(props) {
|
|
|
7933
7987
|
startValue: currentValue,
|
|
7934
7988
|
endValue: String(values[option.endKey] ?? ""),
|
|
7935
7989
|
onRangeChange: handleRangeChangeCurried(optionKey, option.endKey),
|
|
7936
|
-
onKeyDownEnter: handleSubmit
|
|
7990
|
+
onKeyDownEnter: handleSubmit,
|
|
7991
|
+
className: option.className
|
|
7937
7992
|
}
|
|
7938
7993
|
) }, String(optionKey));
|
|
7939
7994
|
case "checkbox":
|
|
@@ -7944,7 +7999,8 @@ function PageFilter(props) {
|
|
|
7944
7999
|
name: String(optionKey),
|
|
7945
8000
|
value: currentValue,
|
|
7946
8001
|
label: option.label,
|
|
7947
|
-
onChange: handleCheckboxChange(optionKey, option.autoSubmit)
|
|
8002
|
+
onChange: handleCheckboxChange(optionKey, option.autoSubmit),
|
|
8003
|
+
className: option.className
|
|
7948
8004
|
}
|
|
7949
8005
|
) }, String(optionKey));
|
|
7950
8006
|
default: {
|