@farmzone/fz-react-ui 1.0.0 → 1.0.1
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 +129 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +129 -57
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -1
package/dist/index.d.cts
CHANGED
|
@@ -441,6 +441,7 @@ type DatePickerBaseProps = {
|
|
|
441
441
|
disabled?: boolean;
|
|
442
442
|
maxDate?: YmdDateString;
|
|
443
443
|
calendarYearRange?: CalendarYearRange;
|
|
444
|
+
calendarSelectContainerClass?: string;
|
|
444
445
|
showTodayButton?: boolean;
|
|
445
446
|
};
|
|
446
447
|
type DatePickerSingleMode = DatePickerBaseProps & {
|
|
@@ -842,6 +843,9 @@ interface CascadingSelectFieldConfig {
|
|
|
842
843
|
separator?: string;
|
|
843
844
|
}
|
|
844
845
|
interface SelectWithInputFieldConfig {
|
|
846
|
+
/** 입력 필드 숫자만 허용 여부. 기본: true. */
|
|
847
|
+
numbersOnly?: boolean;
|
|
848
|
+
/** @deprecated numbersOnly를 사용하세요. */
|
|
845
849
|
inputMode?: "number" | "text";
|
|
846
850
|
}
|
|
847
851
|
interface InputWithButtonFieldConfig {
|
|
@@ -859,6 +863,7 @@ interface FormFieldConfig<TFieldValues extends FieldValues = FieldValues> {
|
|
|
859
863
|
options?: SelectOption$1[];
|
|
860
864
|
className?: string;
|
|
861
865
|
allowDecimal?: boolean;
|
|
866
|
+
numbersOnly?: boolean;
|
|
862
867
|
canReset?: boolean;
|
|
863
868
|
datePosition?: "top" | "bottom";
|
|
864
869
|
disableFutureDates?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -441,6 +441,7 @@ type DatePickerBaseProps = {
|
|
|
441
441
|
disabled?: boolean;
|
|
442
442
|
maxDate?: YmdDateString;
|
|
443
443
|
calendarYearRange?: CalendarYearRange;
|
|
444
|
+
calendarSelectContainerClass?: string;
|
|
444
445
|
showTodayButton?: boolean;
|
|
445
446
|
};
|
|
446
447
|
type DatePickerSingleMode = DatePickerBaseProps & {
|
|
@@ -842,6 +843,9 @@ interface CascadingSelectFieldConfig {
|
|
|
842
843
|
separator?: string;
|
|
843
844
|
}
|
|
844
845
|
interface SelectWithInputFieldConfig {
|
|
846
|
+
/** 입력 필드 숫자만 허용 여부. 기본: true. */
|
|
847
|
+
numbersOnly?: boolean;
|
|
848
|
+
/** @deprecated numbersOnly를 사용하세요. */
|
|
845
849
|
inputMode?: "number" | "text";
|
|
846
850
|
}
|
|
847
851
|
interface InputWithButtonFieldConfig {
|
|
@@ -859,6 +863,7 @@ interface FormFieldConfig<TFieldValues extends FieldValues = FieldValues> {
|
|
|
859
863
|
options?: SelectOption$1[];
|
|
860
864
|
className?: string;
|
|
861
865
|
allowDecimal?: boolean;
|
|
866
|
+
numbersOnly?: boolean;
|
|
862
867
|
canReset?: boolean;
|
|
863
868
|
datePosition?: "top" | "bottom";
|
|
864
869
|
disableFutureDates?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -939,7 +939,7 @@ function Select2(props) {
|
|
|
939
939
|
onChange("");
|
|
940
940
|
onReset?.();
|
|
941
941
|
};
|
|
942
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-0.5", containerClass ?? "w-
|
|
942
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-0.5", containerClass ?? "w-20"), children: [
|
|
943
943
|
label && /* @__PURE__ */ jsx(
|
|
944
944
|
"label",
|
|
945
945
|
{
|
|
@@ -1997,7 +1997,8 @@ function RenderCalendar(props) {
|
|
|
1997
1997
|
onYearChange,
|
|
1998
1998
|
onMonthChange,
|
|
1999
1999
|
editDateSelect = true,
|
|
2000
|
-
datePosition = "bottom"
|
|
2000
|
+
datePosition = "bottom",
|
|
2001
|
+
calendarSelectContainerClass
|
|
2001
2002
|
} = props;
|
|
2002
2003
|
const year = currentDate.getFullYear();
|
|
2003
2004
|
const month = currentDate.getMonth();
|
|
@@ -2081,7 +2082,8 @@ function RenderCalendar(props) {
|
|
|
2081
2082
|
value: year.toString(),
|
|
2082
2083
|
options: yearOptions,
|
|
2083
2084
|
onChange: handleYearChange,
|
|
2084
|
-
className: "cursor-pointer"
|
|
2085
|
+
className: "cursor-pointer",
|
|
2086
|
+
containerClass: calendarSelectContainerClass
|
|
2085
2087
|
}
|
|
2086
2088
|
) }),
|
|
2087
2089
|
/* @__PURE__ */ jsx("div", { onClick: handleStopPropagation, onMouseDown: handleStopPropagation, children: /* @__PURE__ */ jsx(
|
|
@@ -2090,7 +2092,8 @@ function RenderCalendar(props) {
|
|
|
2090
2092
|
value: (month + 1).toString(),
|
|
2091
2093
|
options: monthOptions,
|
|
2092
2094
|
onChange: handleMonthChange,
|
|
2093
|
-
className: "
|
|
2095
|
+
className: "cursor-pointer",
|
|
2096
|
+
containerClass: calendarSelectContainerClass
|
|
2094
2097
|
}
|
|
2095
2098
|
) })
|
|
2096
2099
|
]
|
|
@@ -2258,6 +2261,7 @@ function DatePickerRange(props) {
|
|
|
2258
2261
|
disabled = false,
|
|
2259
2262
|
maxDate,
|
|
2260
2263
|
calendarYearRange,
|
|
2264
|
+
calendarSelectContainerClass,
|
|
2261
2265
|
showTodayButton = true
|
|
2262
2266
|
} = props;
|
|
2263
2267
|
const [inputs, setInputs] = useState({ start: startValue, end: endValue });
|
|
@@ -2394,6 +2398,7 @@ function DatePickerRange(props) {
|
|
|
2394
2398
|
datePosition: autoDatePosition,
|
|
2395
2399
|
maxDate,
|
|
2396
2400
|
calendarYearRange,
|
|
2401
|
+
calendarSelectContainerClass,
|
|
2397
2402
|
showTodayButton
|
|
2398
2403
|
}
|
|
2399
2404
|
)
|
|
@@ -2473,6 +2478,7 @@ function DatePickerSingle(props) {
|
|
|
2473
2478
|
disabled = false,
|
|
2474
2479
|
maxDate,
|
|
2475
2480
|
calendarYearRange,
|
|
2481
|
+
calendarSelectContainerClass,
|
|
2476
2482
|
onBlur,
|
|
2477
2483
|
showTodayButton = true
|
|
2478
2484
|
} = props;
|
|
@@ -2565,6 +2571,7 @@ function DatePickerSingle(props) {
|
|
|
2565
2571
|
datePosition: autoDatePosition,
|
|
2566
2572
|
maxDate,
|
|
2567
2573
|
calendarYearRange,
|
|
2574
|
+
calendarSelectContainerClass,
|
|
2568
2575
|
showTodayButton
|
|
2569
2576
|
}
|
|
2570
2577
|
)
|
|
@@ -2623,6 +2630,7 @@ function DatePicker(props) {
|
|
|
2623
2630
|
disabled,
|
|
2624
2631
|
maxDate,
|
|
2625
2632
|
calendarYearRange,
|
|
2633
|
+
calendarSelectContainerClass,
|
|
2626
2634
|
showTodayButton
|
|
2627
2635
|
} = props;
|
|
2628
2636
|
if (isRange) {
|
|
@@ -2640,6 +2648,7 @@ function DatePicker(props) {
|
|
|
2640
2648
|
disabled,
|
|
2641
2649
|
maxDate,
|
|
2642
2650
|
calendarYearRange,
|
|
2651
|
+
calendarSelectContainerClass,
|
|
2643
2652
|
showTodayButton
|
|
2644
2653
|
}
|
|
2645
2654
|
);
|
|
@@ -2659,6 +2668,7 @@ function DatePicker(props) {
|
|
|
2659
2668
|
disabled,
|
|
2660
2669
|
maxDate,
|
|
2661
2670
|
calendarYearRange,
|
|
2671
|
+
calendarSelectContainerClass,
|
|
2662
2672
|
showTodayButton,
|
|
2663
2673
|
onBlur
|
|
2664
2674
|
}
|
|
@@ -3524,7 +3534,7 @@ function TableFooter(props) {
|
|
|
3524
3534
|
const { paginationInfo, renderLeft, renderRight } = props;
|
|
3525
3535
|
return /* @__PURE__ */ jsx("div", { className: "w-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-4 min-h-16", children: [
|
|
3526
3536
|
/* @__PURE__ */ jsx("div", { className: "flex justify-start flex-1 min-w-0", children: renderLeft }),
|
|
3527
|
-
paginationInfo && /* @__PURE__ */ jsx("div", { className: "
|
|
3537
|
+
paginationInfo && /* @__PURE__ */ jsx("div", { className: "px-5", children: /* @__PURE__ */ jsx(Pagination, { ...paginationInfo }) }),
|
|
3528
3538
|
/* @__PURE__ */ jsx("div", { className: "flex justify-end flex-1 min-w-0", children: renderRight })
|
|
3529
3539
|
] }) });
|
|
3530
3540
|
}
|
|
@@ -3680,7 +3690,7 @@ function useTableFixed(columns, isHeader = false) {
|
|
|
3680
3690
|
window.addEventListener("resize", onResize);
|
|
3681
3691
|
const firstKey = columns[0]?.key;
|
|
3682
3692
|
const cell = firstKey ? document.getElementById(`${firstKey}${isHeader ? "-header" : "-body"}`) : null;
|
|
3683
|
-
const tableEl = cell?.closest("table") || document.querySelector("table.table-
|
|
3693
|
+
const tableEl = cell?.closest("table") || document.querySelector("table.table-fixed");
|
|
3684
3694
|
if (tableEl && "ResizeObserver" in window) {
|
|
3685
3695
|
resizeObserverRef.current = new ResizeObserver(handleResize);
|
|
3686
3696
|
resizeObserverRef.current.observe(tableEl);
|
|
@@ -3767,19 +3777,14 @@ function TableHeader(props) {
|
|
|
3767
3777
|
const columns = useMemo(() => {
|
|
3768
3778
|
return customColumns.map((column) => {
|
|
3769
3779
|
const { key } = column;
|
|
3770
|
-
const
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
if (key === "__checkbox__") {
|
|
3778
|
-
return "center";
|
|
3779
|
-
}
|
|
3780
|
-
return column.align ?? "left";
|
|
3780
|
+
const isCheckbox = key === "__checkbox__";
|
|
3781
|
+
return {
|
|
3782
|
+
...column,
|
|
3783
|
+
width: isCheckbox ? "40px" : column.width,
|
|
3784
|
+
minWidth: isCheckbox ? "40px" : column.minWidth ?? column.width,
|
|
3785
|
+
maxWidth: isCheckbox ? "40px" : column.maxWidth,
|
|
3786
|
+
align: isCheckbox ? "center" : column.align ?? "left"
|
|
3781
3787
|
};
|
|
3782
|
-
return { ...column, width: getWidth(), align: getAlign() };
|
|
3783
3788
|
});
|
|
3784
3789
|
}, [customColumns]);
|
|
3785
3790
|
const { getColumnFixedStyle } = useTableFixed(columns, true);
|
|
@@ -4252,11 +4257,11 @@ function SkeletonTd(props) {
|
|
|
4252
4257
|
return /* @__PURE__ */ jsx(
|
|
4253
4258
|
"td",
|
|
4254
4259
|
{
|
|
4255
|
-
className: "px-2 py-[6.8px] whitespace-nowrap text-sm border-r border-b border-gray-200/70 last:border-r-0
|
|
4260
|
+
className: `${col.key === "__checkbox__" ? "p-0" : "px-2 py-[6.8px]"} whitespace-nowrap text-sm border-r border-b border-gray-200/70 last:border-r-0`,
|
|
4256
4261
|
style: {
|
|
4257
4262
|
width: col.width,
|
|
4258
4263
|
minWidth: col.minWidth || col.width,
|
|
4259
|
-
maxWidth: col.maxWidth || col.width
|
|
4264
|
+
maxWidth: col.key === "__checkbox__" ? col.maxWidth || col.width : void 0
|
|
4260
4265
|
},
|
|
4261
4266
|
children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-4", children: showSquare ? /* @__PURE__ */ jsx(Skeleton, { className: "size-4 rounded-xs" }) : /* @__PURE__ */ jsx(Skeleton, { className: "h-1.5 rounded-sm", style: { width: "calc(100% - 20px)" } }) })
|
|
4262
4267
|
}
|
|
@@ -4337,7 +4342,7 @@ function getAlignStyle(align) {
|
|
|
4337
4342
|
return align === "left" ? "flex-start" : align === "center" ? "center" : "flex-end";
|
|
4338
4343
|
}
|
|
4339
4344
|
function applyColDefaults(col) {
|
|
4340
|
-
const width = col.key === "__checkbox__" ? "40px" : col.width ?? col.minWidth
|
|
4345
|
+
const width = col.key === "__checkbox__" ? "40px" : col.width ?? col.minWidth;
|
|
4341
4346
|
const align = col.key === "__checkbox__" ? "center" : col.align ?? "left";
|
|
4342
4347
|
return { ...col, width, align };
|
|
4343
4348
|
}
|
|
@@ -4786,17 +4791,18 @@ function Table(props) {
|
|
|
4786
4791
|
const { width, minWidth, maxWidth, align } = col;
|
|
4787
4792
|
const fixedStyle = isPinned ? getColumnFixedStyleRef.current(col) : void 0;
|
|
4788
4793
|
const cellContent = col.render ? col.render(record[col.key], record, rowIdx) : String(record[col.key] ?? "");
|
|
4794
|
+
const isCheckbox = col.key === "__checkbox__";
|
|
4789
4795
|
return /* @__PURE__ */ jsx(
|
|
4790
4796
|
"td",
|
|
4791
4797
|
{
|
|
4792
4798
|
id: `${col.key}-body`,
|
|
4793
4799
|
"data-row-cell": "true",
|
|
4794
4800
|
"data-col-key": col.key,
|
|
4795
|
-
className: "px-2 py-[6.8px] whitespace-nowrap text-sm text-gray-900 border-r border-b border-gray-200 last:border-r-0 bg-inherit group-hover:bg-gray-100 transition-all
|
|
4801
|
+
className: `${isCheckbox ? "p-0" : "px-2 py-[6.8px]"} whitespace-nowrap text-sm text-gray-900 border-r border-b border-gray-200 last:border-r-0 bg-inherit group-hover:bg-gray-100 transition-all`,
|
|
4796
4802
|
style: {
|
|
4797
4803
|
width,
|
|
4798
4804
|
minWidth: minWidth || width,
|
|
4799
|
-
maxWidth: maxWidth || width,
|
|
4805
|
+
maxWidth: isCheckbox ? maxWidth || width : void 0,
|
|
4800
4806
|
...fixedStyle
|
|
4801
4807
|
},
|
|
4802
4808
|
onClick: (event) => {
|
|
@@ -4892,7 +4898,7 @@ function Table(props) {
|
|
|
4892
4898
|
ref: scrollRef,
|
|
4893
4899
|
className: "relative w-full overflow-y-auto overflow-x-auto custom-view-scrollbar bg-white",
|
|
4894
4900
|
style: { height: `${tableHeight}px` },
|
|
4895
|
-
children: /* @__PURE__ */ jsxs("table", { className: "w-full table-
|
|
4901
|
+
children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed", children: [
|
|
4896
4902
|
/* @__PURE__ */ jsx(
|
|
4897
4903
|
TableHeader,
|
|
4898
4904
|
{
|
|
@@ -5992,6 +5998,7 @@ var FORM_CONTROL_CLASS = "h-8 w-full rounded border border-gray-300 bg-white px-
|
|
|
5992
5998
|
function formControlClass(hasError, extra) {
|
|
5993
5999
|
return cn2(FORM_CONTROL_CLASS, FORM_CONTROL_FOCUS_CLASS, hasError && FORM_FIELD_ERROR_BORDER_CLASS, extra);
|
|
5994
6000
|
}
|
|
6001
|
+
var FIELD_READONLY_TEXT_CLASS = "text-sm text-gray-800 leading-tight";
|
|
5995
6002
|
function fieldControlWrapClass(className) {
|
|
5996
6003
|
return className ? cn2("min-w-0 shrink-0", className) : "min-w-0 w-full";
|
|
5997
6004
|
}
|
|
@@ -6338,6 +6345,7 @@ function AddressField(props) {
|
|
|
6338
6345
|
const {
|
|
6339
6346
|
placeholder = "\uC8FC\uC18C\uB97C \uAC80\uC0C9\uD558\uC138\uC694",
|
|
6340
6347
|
disabled = false,
|
|
6348
|
+
readOnly = false,
|
|
6341
6349
|
className = "",
|
|
6342
6350
|
addressDetailKey,
|
|
6343
6351
|
addressClassNames
|
|
@@ -6352,6 +6360,9 @@ function AddressField(props) {
|
|
|
6352
6360
|
searchButtonRef.current?.click();
|
|
6353
6361
|
}
|
|
6354
6362
|
}, [isFocused]);
|
|
6363
|
+
if (readOnly) {
|
|
6364
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: String(value ?? "") || "\u2014" }) });
|
|
6365
|
+
}
|
|
6355
6366
|
const handleComplete = (data) => {
|
|
6356
6367
|
isAddressSelectedRef.current = true;
|
|
6357
6368
|
const nextAddress = data.roadAddress || data.address;
|
|
@@ -6470,12 +6481,12 @@ function CascadingSelectField(props) {
|
|
|
6470
6481
|
}
|
|
6471
6482
|
function CascadingSelectFieldInner(props) {
|
|
6472
6483
|
const {
|
|
6473
|
-
field: { onChange, value },
|
|
6484
|
+
field: { onChange, onBlur, value },
|
|
6474
6485
|
config,
|
|
6475
6486
|
hasError = false,
|
|
6476
6487
|
cascadingSelect
|
|
6477
6488
|
} = props;
|
|
6478
|
-
const { disabled = false, className = "", cascadingSelectClassNames } = config;
|
|
6489
|
+
const { disabled = false, readOnly = false, className = "", cascadingSelectClassNames } = config;
|
|
6479
6490
|
const {
|
|
6480
6491
|
primaryOptions,
|
|
6481
6492
|
getSecondaryOptions,
|
|
@@ -6489,10 +6500,17 @@ function CascadingSelectFieldInner(props) {
|
|
|
6489
6500
|
[formValue, getSecondaryOptions, separator]
|
|
6490
6501
|
);
|
|
6491
6502
|
useLayoutEffect(() => {
|
|
6503
|
+
if (readOnly) return;
|
|
6492
6504
|
if (normalizedFormValue !== formValue) {
|
|
6493
6505
|
onChange(normalizedFormValue);
|
|
6494
6506
|
}
|
|
6495
|
-
}, [formValue, normalizedFormValue, onChange]);
|
|
6507
|
+
}, [formValue, normalizedFormValue, onChange, readOnly]);
|
|
6508
|
+
if (readOnly) {
|
|
6509
|
+
const primaryLabel = primaryOptions.find((o) => String(o.value) === primary)?.label ?? primary;
|
|
6510
|
+
const secondaryLabel = secondary ? secondaryOptions.find((o) => String(o.value) === secondary)?.label ?? secondary : "";
|
|
6511
|
+
const displayText = secondaryLabel ? `${primaryLabel} ${secondaryLabel}` : primaryLabel || "\u2014";
|
|
6512
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: displayText }) });
|
|
6513
|
+
}
|
|
6496
6514
|
const updateValue = (nextPrimary, nextSecondary) => {
|
|
6497
6515
|
onChange(createCascadingSelectValue(nextPrimary, nextSecondary, separator));
|
|
6498
6516
|
};
|
|
@@ -6518,6 +6536,7 @@ function CascadingSelectFieldInner(props) {
|
|
|
6518
6536
|
canReset: true,
|
|
6519
6537
|
onChange: (nextPrimary) => {
|
|
6520
6538
|
updateValue(nextPrimary, "");
|
|
6539
|
+
if (!nextPrimary) onBlur();
|
|
6521
6540
|
}
|
|
6522
6541
|
}
|
|
6523
6542
|
),
|
|
@@ -6534,6 +6553,7 @@ function CascadingSelectFieldInner(props) {
|
|
|
6534
6553
|
canReset: true,
|
|
6535
6554
|
onChange: (nextSecondary) => {
|
|
6536
6555
|
updateValue(primary, nextSecondary);
|
|
6556
|
+
onBlur();
|
|
6537
6557
|
}
|
|
6538
6558
|
}
|
|
6539
6559
|
)
|
|
@@ -6544,7 +6564,11 @@ function CheckboxField(props) {
|
|
|
6544
6564
|
field: { onChange, value },
|
|
6545
6565
|
config
|
|
6546
6566
|
} = props;
|
|
6547
|
-
const { disabled = false, checkboxLabel, className = "" } = config;
|
|
6567
|
+
const { disabled = false, readOnly = false, checkboxLabel, className = "" } = config;
|
|
6568
|
+
if (readOnly) {
|
|
6569
|
+
const text = value ? checkboxLabel ?? "\uC120\uD0DD\uB428" : "\u2014";
|
|
6570
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: text }) });
|
|
6571
|
+
}
|
|
6548
6572
|
return /* @__PURE__ */ jsx(
|
|
6549
6573
|
Checkbox,
|
|
6550
6574
|
{
|
|
@@ -6565,11 +6589,15 @@ function DateField(props) {
|
|
|
6565
6589
|
const {
|
|
6566
6590
|
placeholder = "YYYY-MM-DD",
|
|
6567
6591
|
disabled = false,
|
|
6592
|
+
readOnly = false,
|
|
6568
6593
|
className = "w-40",
|
|
6569
6594
|
datePosition = "bottom",
|
|
6570
6595
|
disableFutureDates = false
|
|
6571
6596
|
} = config;
|
|
6572
6597
|
const maxDate = disableFutureDates ? formatDate(/* @__PURE__ */ new Date()) : void 0;
|
|
6598
|
+
if (readOnly) {
|
|
6599
|
+
return /* @__PURE__ */ jsx("div", { className: cn2("flex items-center", fieldControlWrapClass(className)), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: String(value ?? "") || "\u2014" }) });
|
|
6600
|
+
}
|
|
6573
6601
|
return /* @__PURE__ */ jsx("div", { className: cn2("flex items-center", fieldControlWrapClass(className)), children: /* @__PURE__ */ jsx(
|
|
6574
6602
|
DatePicker,
|
|
6575
6603
|
{
|
|
@@ -6597,11 +6625,17 @@ function InputField(props) {
|
|
|
6597
6625
|
readOnly = false,
|
|
6598
6626
|
maxLength,
|
|
6599
6627
|
className = "",
|
|
6600
|
-
type = "input"
|
|
6628
|
+
type = "input",
|
|
6629
|
+
numbersOnly = false
|
|
6601
6630
|
} = config;
|
|
6602
6631
|
const inputType = type === "email" ? "email" : type === "password" ? "password" : "text";
|
|
6632
|
+
if (readOnly) {
|
|
6633
|
+
const text = type === "password" ? value ? "**********" : "" : String(value ?? "") || "";
|
|
6634
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: text }) });
|
|
6635
|
+
}
|
|
6603
6636
|
const handleChange = (e) => {
|
|
6604
|
-
|
|
6637
|
+
const value2 = numbersOnly ? e.target.value.replace(/\D/g, "") : e.target.value;
|
|
6638
|
+
onChange(value2);
|
|
6605
6639
|
};
|
|
6606
6640
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(
|
|
6607
6641
|
Input2,
|
|
@@ -6632,7 +6666,7 @@ function InputWithButtonField(props) {
|
|
|
6632
6666
|
placeholder = "\uC870\uD68C \uBC84\uD2BC\uC73C\uB85C \uC120\uD0DD",
|
|
6633
6667
|
disabled = false,
|
|
6634
6668
|
className = "",
|
|
6635
|
-
readOnly =
|
|
6669
|
+
readOnly = false,
|
|
6636
6670
|
inputWithButton,
|
|
6637
6671
|
onClickInputWithButton
|
|
6638
6672
|
} = config;
|
|
@@ -6641,13 +6675,16 @@ function InputWithButtonField(props) {
|
|
|
6641
6675
|
if (disabled) return;
|
|
6642
6676
|
onClickInputWithButton?.();
|
|
6643
6677
|
};
|
|
6678
|
+
if (readOnly) {
|
|
6679
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: String(value ?? "") || "\u2014" }) });
|
|
6680
|
+
}
|
|
6644
6681
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 items-center gap-2", children: [
|
|
6645
6682
|
/* @__PURE__ */ jsx(
|
|
6646
6683
|
Input2,
|
|
6647
6684
|
{
|
|
6648
6685
|
placeholder,
|
|
6649
6686
|
value: String(value ?? ""),
|
|
6650
|
-
readOnly,
|
|
6687
|
+
readOnly: true,
|
|
6651
6688
|
disabled,
|
|
6652
6689
|
bare: true,
|
|
6653
6690
|
className: formControlClass(hasError),
|
|
@@ -6687,6 +6724,9 @@ function NumberField(props) {
|
|
|
6687
6724
|
}
|
|
6688
6725
|
};
|
|
6689
6726
|
const displayValue = value != null && value !== "" ? isMoney ? formatNumberWithCommas(value) : String(value) : "";
|
|
6727
|
+
if (readOnly) {
|
|
6728
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: displayValue || "\u2014" }) });
|
|
6729
|
+
}
|
|
6690
6730
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(
|
|
6691
6731
|
Input2,
|
|
6692
6732
|
{
|
|
@@ -6716,6 +6756,9 @@ function PhoneField(props) {
|
|
|
6716
6756
|
const handleChange = (e) => {
|
|
6717
6757
|
onChange(formatPhoneNumber(e.target.value));
|
|
6718
6758
|
};
|
|
6759
|
+
if (readOnly) {
|
|
6760
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: String(value ?? "") || "\u2014" }) });
|
|
6761
|
+
}
|
|
6719
6762
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(
|
|
6720
6763
|
Input2,
|
|
6721
6764
|
{
|
|
@@ -6740,7 +6783,11 @@ function RadioField(props) {
|
|
|
6740
6783
|
field: { onChange, value, name },
|
|
6741
6784
|
config
|
|
6742
6785
|
} = props;
|
|
6743
|
-
const { disabled = false, options = [], className = "" } = config;
|
|
6786
|
+
const { disabled = false, readOnly = false, options = [], className = "" } = config;
|
|
6787
|
+
if (readOnly) {
|
|
6788
|
+
const label = options.find((o) => String(o.value) === String(value ?? ""))?.label ?? String(value ?? "");
|
|
6789
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: label || "\u2014" }) });
|
|
6790
|
+
}
|
|
6744
6791
|
return /* @__PURE__ */ jsx(
|
|
6745
6792
|
RadioGroup,
|
|
6746
6793
|
{
|
|
@@ -6772,11 +6819,16 @@ function SelectField(props) {
|
|
|
6772
6819
|
const {
|
|
6773
6820
|
placeholder = "\uC120\uD0DD\uD558\uC138\uC694",
|
|
6774
6821
|
disabled = false,
|
|
6822
|
+
readOnly = false,
|
|
6775
6823
|
options = [],
|
|
6776
6824
|
className = "",
|
|
6777
6825
|
canReset = false
|
|
6778
6826
|
} = config;
|
|
6779
6827
|
const selectOptions = toSelectOptions2(options);
|
|
6828
|
+
if (readOnly) {
|
|
6829
|
+
const label = selectOptions.find((o) => o.value === String(value ?? ""))?.label ?? String(value ?? "");
|
|
6830
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: label || "\u2014" }) });
|
|
6831
|
+
}
|
|
6780
6832
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(
|
|
6781
6833
|
Select2,
|
|
6782
6834
|
{
|
|
@@ -6823,16 +6875,6 @@ function combineSelectWithInputValue(prefix, input) {
|
|
|
6823
6875
|
return `${prefix}${input}`;
|
|
6824
6876
|
}
|
|
6825
6877
|
var DEFAULT_SELECT_TRIGGER = "h-8 rounded border bg-white px-2 text-sm shadow-none min-w-[5rem]";
|
|
6826
|
-
function resolveSelectWithInputState(formValue, defaultPrefix, options) {
|
|
6827
|
-
const parsed = parseSelectWithInputValue(formValue, defaultPrefix);
|
|
6828
|
-
const validPrefixes = new Set(options.map((opt) => String(opt.value)));
|
|
6829
|
-
const prefix = validPrefixes.has(parsed.prefix) ? parsed.prefix : defaultPrefix;
|
|
6830
|
-
return {
|
|
6831
|
-
prefix,
|
|
6832
|
-
inputPart: parsed.input,
|
|
6833
|
-
normalizedFormValue: combineSelectWithInputValue(prefix, parsed.input)
|
|
6834
|
-
};
|
|
6835
|
-
}
|
|
6836
6878
|
function SelectWithInputField(props) {
|
|
6837
6879
|
const {
|
|
6838
6880
|
field: { onChange, onBlur, value },
|
|
@@ -6841,37 +6883,58 @@ function SelectWithInputField(props) {
|
|
|
6841
6883
|
} = props;
|
|
6842
6884
|
const {
|
|
6843
6885
|
disabled = false,
|
|
6886
|
+
readOnly = false,
|
|
6844
6887
|
options = [],
|
|
6845
6888
|
maxLength,
|
|
6846
6889
|
className = "",
|
|
6847
6890
|
selectWithInput,
|
|
6848
6891
|
selectWithInputClassNames
|
|
6849
6892
|
} = config;
|
|
6850
|
-
const
|
|
6893
|
+
const validationCtx = useSubmitFormValidation();
|
|
6894
|
+
const numbersOnly = selectWithInput?.numbersOnly ?? selectWithInput?.inputMode !== "text";
|
|
6851
6895
|
const defaultPrefix = String(options[0]?.value ?? "");
|
|
6852
6896
|
const numberInputRef = useRef(null);
|
|
6853
6897
|
const formValue = String(value ?? "");
|
|
6854
|
-
const { prefix, inputPart, normalizedFormValue } = useMemo(
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6898
|
+
const { prefix, inputPart, normalizedFormValue } = useMemo(() => {
|
|
6899
|
+
const parsed = parseSelectWithInputValue(formValue, defaultPrefix);
|
|
6900
|
+
const validPrefixes = new Set(options.map((opt) => String(opt.value)));
|
|
6901
|
+
const resolvedPrefix = validPrefixes.has(parsed.prefix) ? parsed.prefix : defaultPrefix;
|
|
6902
|
+
return {
|
|
6903
|
+
prefix: resolvedPrefix,
|
|
6904
|
+
inputPart: parsed.input,
|
|
6905
|
+
normalizedFormValue: combineSelectWithInputValue(resolvedPrefix, parsed.input)
|
|
6906
|
+
};
|
|
6907
|
+
}, [defaultPrefix, formValue, options]);
|
|
6908
|
+
const [selectedPrefix, setSelectedPrefix] = useState(prefix);
|
|
6909
|
+
const [prevFormValue, setPrevFormValue] = useState(formValue);
|
|
6910
|
+
if (prevFormValue !== formValue) {
|
|
6911
|
+
setPrevFormValue(formValue);
|
|
6912
|
+
setSelectedPrefix(formValue ? prefix : defaultPrefix);
|
|
6913
|
+
}
|
|
6858
6914
|
useLayoutEffect(() => {
|
|
6859
|
-
if (
|
|
6915
|
+
if (readOnly) return;
|
|
6916
|
+
if (formValue && normalizedFormValue !== formValue) {
|
|
6860
6917
|
onChange(normalizedFormValue);
|
|
6861
6918
|
}
|
|
6862
|
-
}, [formValue, normalizedFormValue, onChange]);
|
|
6919
|
+
}, [formValue, normalizedFormValue, onChange, readOnly]);
|
|
6920
|
+
if (readOnly) {
|
|
6921
|
+
const prefixLabel = options.find((o) => String(o.value) === prefix)?.label ?? prefix;
|
|
6922
|
+
const displayText = inputPart ? `${prefixLabel} ${inputPart}` : prefix ? prefixLabel : "\u2014";
|
|
6923
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: displayText || "\u2014" }) });
|
|
6924
|
+
}
|
|
6863
6925
|
const updateCombined = (nextPrefix, nextInput) => {
|
|
6864
6926
|
onChange(combineSelectWithInputValue(nextPrefix, nextInput));
|
|
6865
6927
|
};
|
|
6866
6928
|
const normalizeInput = (raw) => {
|
|
6867
|
-
if (
|
|
6868
|
-
return raw.replace(/\D+/g, "");
|
|
6869
|
-
}
|
|
6929
|
+
if (numbersOnly) return raw.replace(/\D+/g, "");
|
|
6870
6930
|
return raw;
|
|
6871
6931
|
};
|
|
6872
6932
|
const handleInputChange = (raw) => {
|
|
6873
6933
|
const normalized = normalizeInput(raw.normalize("NFKC"));
|
|
6874
|
-
|
|
6934
|
+
if (normalized) {
|
|
6935
|
+
validationCtx?.markFieldHadValue(String(config.name));
|
|
6936
|
+
}
|
|
6937
|
+
updateCombined(selectedPrefix, normalized);
|
|
6875
6938
|
};
|
|
6876
6939
|
const selectClass = resolveSelectClassNameProp(selectWithInputClassNames?.selectClassName, {
|
|
6877
6940
|
containerClassName: "shrink-0",
|
|
@@ -6881,7 +6944,7 @@ function SelectWithInputField(props) {
|
|
|
6881
6944
|
/* @__PURE__ */ jsx(
|
|
6882
6945
|
Select2,
|
|
6883
6946
|
{
|
|
6884
|
-
value:
|
|
6947
|
+
value: selectedPrefix,
|
|
6885
6948
|
placeholder: "\uC120\uD0DD",
|
|
6886
6949
|
disabled,
|
|
6887
6950
|
hasError,
|
|
@@ -6889,6 +6952,7 @@ function SelectWithInputField(props) {
|
|
|
6889
6952
|
containerClass: selectClass.containerClassName,
|
|
6890
6953
|
triggerClassName: selectClass.triggerClassName,
|
|
6891
6954
|
onChange: (nextPrefix) => {
|
|
6955
|
+
setSelectedPrefix(nextPrefix);
|
|
6892
6956
|
updateCombined(nextPrefix, inputPart);
|
|
6893
6957
|
}
|
|
6894
6958
|
}
|
|
@@ -6907,7 +6971,7 @@ function SelectWithInputField(props) {
|
|
|
6907
6971
|
},
|
|
6908
6972
|
onBlur: (e) => {
|
|
6909
6973
|
const normalized = normalizeInput(e.target.value.normalize("NFKC"));
|
|
6910
|
-
|
|
6974
|
+
updateCombined(selectedPrefix, normalized);
|
|
6911
6975
|
onBlur();
|
|
6912
6976
|
}
|
|
6913
6977
|
}
|
|
@@ -6919,7 +6983,10 @@ function SwitchField(props) {
|
|
|
6919
6983
|
field: { onChange, value },
|
|
6920
6984
|
config
|
|
6921
6985
|
} = props;
|
|
6922
|
-
const { disabled = false, className = "" } = config;
|
|
6986
|
+
const { disabled = false, readOnly = false, className = "" } = config;
|
|
6987
|
+
if (readOnly) {
|
|
6988
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: FIELD_READONLY_TEXT_CLASS, children: value ? "\uCF1C\uC9D0" : "\uAEBC\uC9D0" }) });
|
|
6989
|
+
}
|
|
6923
6990
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(BaseSwitch, { checked: Boolean(value), onCheckedChange: onChange, disabled }) });
|
|
6924
6991
|
}
|
|
6925
6992
|
function TextareaField(props) {
|
|
@@ -6932,6 +6999,9 @@ function TextareaField(props) {
|
|
|
6932
6999
|
const handleChange = (e) => {
|
|
6933
7000
|
onChange(e.target.value);
|
|
6934
7001
|
};
|
|
7002
|
+
if (readOnly) {
|
|
7003
|
+
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx("span", { className: cn2(FIELD_READONLY_TEXT_CLASS, "whitespace-pre-wrap"), children: String(value ?? "") || "\u2014" }) });
|
|
7004
|
+
}
|
|
6935
7005
|
return /* @__PURE__ */ jsx("div", { className: fieldControlWrapClass(className), children: /* @__PURE__ */ jsx(
|
|
6936
7006
|
Textarea,
|
|
6937
7007
|
{
|
|
@@ -7177,6 +7247,7 @@ function rowPropsToFieldConfig(props) {
|
|
|
7177
7247
|
options,
|
|
7178
7248
|
className,
|
|
7179
7249
|
allowDecimal,
|
|
7250
|
+
numbersOnly,
|
|
7180
7251
|
canReset,
|
|
7181
7252
|
datePosition,
|
|
7182
7253
|
disableFutureDates,
|
|
@@ -7206,6 +7277,7 @@ function rowPropsToFieldConfig(props) {
|
|
|
7206
7277
|
options,
|
|
7207
7278
|
className,
|
|
7208
7279
|
allowDecimal,
|
|
7280
|
+
numbersOnly,
|
|
7209
7281
|
canReset,
|
|
7210
7282
|
datePosition,
|
|
7211
7283
|
disableFutureDates,
|