@farmzone/fz-react-ui 1.0.1 → 1.0.2
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 +313 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -82
- package/dist/index.d.ts +88 -82
- package/dist/index.js +313 -149
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -943,7 +943,7 @@ var SELECT_BORDER_COLORS = {
|
|
|
943
943
|
};
|
|
944
944
|
function Select2(props) {
|
|
945
945
|
const {
|
|
946
|
-
|
|
946
|
+
containerClassName,
|
|
947
947
|
options,
|
|
948
948
|
placeholder = "\uC120\uD0DD\uD574 \uC8FC\uC138\uC694",
|
|
949
949
|
triggerClassName,
|
|
@@ -973,7 +973,7 @@ function Select2(props) {
|
|
|
973
973
|
onChange("");
|
|
974
974
|
onReset?.();
|
|
975
975
|
};
|
|
976
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-0.5",
|
|
976
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-0.5", containerClassName ?? "w-30"), children: [
|
|
977
977
|
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
978
978
|
"label",
|
|
979
979
|
{
|
|
@@ -1056,6 +1056,7 @@ function Radio(props) {
|
|
|
1056
1056
|
checked,
|
|
1057
1057
|
onChange,
|
|
1058
1058
|
disabled = false,
|
|
1059
|
+
disabledMessage,
|
|
1059
1060
|
checkColor = DEFAULT_CHECK_COLOR,
|
|
1060
1061
|
unCheckColor = DEFAULT_UNCHECK_COLOR,
|
|
1061
1062
|
labelClassName,
|
|
@@ -1104,23 +1105,29 @@ function Radio(props) {
|
|
|
1104
1105
|
}
|
|
1105
1106
|
)
|
|
1106
1107
|
] });
|
|
1108
|
+
const withTooltip = (node) => {
|
|
1109
|
+
if (!disabled || !disabledMessage) return node;
|
|
1110
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip2, { content: disabledMessage, position: "bottom", asChild: true, sideOffset: 4, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex", children: node }) });
|
|
1111
|
+
};
|
|
1107
1112
|
if (onChange !== void 0 && checked !== void 0) {
|
|
1108
|
-
return
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1113
|
+
return withTooltip(
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1115
|
+
RadioGroupPrimitive__namespace.Root,
|
|
1116
|
+
{
|
|
1117
|
+
name,
|
|
1118
|
+
value: checked ? value : "",
|
|
1119
|
+
onValueChange: (newValue) => {
|
|
1120
|
+
if (newValue === value) {
|
|
1121
|
+
onChange(value);
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
disabled,
|
|
1125
|
+
children: control
|
|
1126
|
+
}
|
|
1127
|
+
)
|
|
1121
1128
|
);
|
|
1122
1129
|
}
|
|
1123
|
-
return control;
|
|
1130
|
+
return withTooltip(control);
|
|
1124
1131
|
}
|
|
1125
1132
|
function RadioGroup(props) {
|
|
1126
1133
|
const {
|
|
@@ -1156,6 +1163,7 @@ function RadioGroup(props) {
|
|
|
1156
1163
|
value: option.value,
|
|
1157
1164
|
label: option.label,
|
|
1158
1165
|
disabled: disabled || option.disabled,
|
|
1166
|
+
disabledMessage: option.disabled ? option.disabledMessage : void 0,
|
|
1159
1167
|
checkColor,
|
|
1160
1168
|
unCheckColor,
|
|
1161
1169
|
labelClassName,
|
|
@@ -1960,6 +1968,28 @@ function parseLocalYmd(ymd) {
|
|
|
1960
1968
|
if (dt.getFullYear() !== y || dt.getMonth() !== mo || dt.getDate() !== d) return null;
|
|
1961
1969
|
return dt;
|
|
1962
1970
|
}
|
|
1971
|
+
function canSelectToday(options) {
|
|
1972
|
+
const today = options.now ?? /* @__PURE__ */ new Date();
|
|
1973
|
+
const todayYmd = formatDate(today);
|
|
1974
|
+
if (options.maxDate && isCalendarDayAfterMax(today, options.maxDate)) {
|
|
1975
|
+
return false;
|
|
1976
|
+
}
|
|
1977
|
+
if (!options.range) {
|
|
1978
|
+
return true;
|
|
1979
|
+
}
|
|
1980
|
+
if (options.isSelectingEnd) {
|
|
1981
|
+
const start = options.rangeStart?.trim() ?? "";
|
|
1982
|
+
if (start.length === 10 && todayYmd < start) {
|
|
1983
|
+
return false;
|
|
1984
|
+
}
|
|
1985
|
+
return true;
|
|
1986
|
+
}
|
|
1987
|
+
const end = options.rangeEnd?.trim() ?? "";
|
|
1988
|
+
if (end.length === 10 && todayYmd > end) {
|
|
1989
|
+
return false;
|
|
1990
|
+
}
|
|
1991
|
+
return true;
|
|
1992
|
+
}
|
|
1963
1993
|
function isCalendarDayAfterMax(date, maxYmd) {
|
|
1964
1994
|
const max = parseLocalYmd(maxYmd);
|
|
1965
1995
|
if (!max) return false;
|
|
@@ -2016,6 +2046,105 @@ function validateAndFormatInput(input) {
|
|
|
2016
2046
|
}
|
|
2017
2047
|
return `${year}-${month}-${day}`;
|
|
2018
2048
|
}
|
|
2049
|
+
|
|
2050
|
+
// src/components/DatePicker/calendar/config/default.ts
|
|
2051
|
+
var DEFAULT_CALENDAR_YEAR_HALF_SPAN = 25;
|
|
2052
|
+
var CALENDAR_WEEKDAY_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
|
|
2053
|
+
var CALENDAR_RANGE_HINT = {
|
|
2054
|
+
start: "\uC2DC\uC791 \uB0A0\uC9DC\uB97C \uC120\uD0DD\uD558\uC138\uC694",
|
|
2055
|
+
end: "\uC885\uB8CC \uB0A0\uC9DC\uB97C \uC120\uD0DD\uD558\uC138\uC694"
|
|
2056
|
+
};
|
|
2057
|
+
var CALENDAR_PORTAL_Z_INDEX = Z_INDEX.CALENDAR_PORTAL;
|
|
2058
|
+
var CALENDAR_SELECT_CLASSNAMES = {
|
|
2059
|
+
containerClass: "w-20 shrink-0",
|
|
2060
|
+
triggerClassName: "h-8 px-2 py-1 text-sm cursor-pointer",
|
|
2061
|
+
contentClassName: "min-w-[5rem]"
|
|
2062
|
+
};
|
|
2063
|
+
var CALENDAR_PANEL_BASE_CLASS = "bg-white border border-gray-300 rounded-lg shadow-lg p-3 min-w-[280px]";
|
|
2064
|
+
var CALENDAR_PANEL_ANCHORED_CLASS = `${CALENDAR_PANEL_BASE_CLASS} absolute z-50`;
|
|
2065
|
+
var YEAR_SELECT_CONTENT_EXTRA_CLASS = "year-select-content custom-view-scrollbar max-h-50 overflow-y-auto";
|
|
2066
|
+
var YEAR_SELECT_OPEN_CONTENT_SELECTOR = ".year-select-content[data-state='open']";
|
|
2067
|
+
var SELECT_ITEM_CHECKED_SELECTOR = "[data-slot='select-item'][data-state='checked']";
|
|
2068
|
+
|
|
2069
|
+
// src/components/DatePicker/calendar/config/calendar.ts
|
|
2070
|
+
function parseYmdDateString(value) {
|
|
2071
|
+
if (value.length !== 10) return null;
|
|
2072
|
+
return parseLocalYmd(value);
|
|
2073
|
+
}
|
|
2074
|
+
function resolveCalendarYearBounds(anchorYear, calendarYearRange) {
|
|
2075
|
+
const fallbackMin = anchorYear - DEFAULT_CALENDAR_YEAR_HALF_SPAN;
|
|
2076
|
+
const fallbackMax = anchorYear + DEFAULT_CALENDAR_YEAR_HALF_SPAN;
|
|
2077
|
+
const rawMin = calendarYearRange?.minYear?.trim();
|
|
2078
|
+
const rawMax = calendarYearRange?.maxYear?.trim();
|
|
2079
|
+
if (rawMin === void 0 || rawMin === "" || rawMax === void 0 || rawMax === "") {
|
|
2080
|
+
return { minYear: fallbackMin, maxYear: fallbackMax };
|
|
2081
|
+
}
|
|
2082
|
+
const minParsed = Number.parseInt(rawMin, 10);
|
|
2083
|
+
const maxParsed = Number.parseInt(rawMax, 10);
|
|
2084
|
+
if (Number.isNaN(minParsed) || Number.isNaN(maxParsed) || minParsed > maxParsed) {
|
|
2085
|
+
return { minYear: fallbackMin, maxYear: fallbackMax };
|
|
2086
|
+
}
|
|
2087
|
+
return { minYear: minParsed, maxYear: maxParsed };
|
|
2088
|
+
}
|
|
2089
|
+
function buildCalendarYearSelectOptions(maxDate, anchorYear = (/* @__PURE__ */ new Date()).getFullYear(), calendarYearRange) {
|
|
2090
|
+
const { minYear, maxYear } = resolveCalendarYearBounds(anchorYear, calendarYearRange);
|
|
2091
|
+
const maxSelectableYear = maxDate ? parseLocalYmd(maxDate)?.getFullYear() ?? null : null;
|
|
2092
|
+
const options = [];
|
|
2093
|
+
for (let y = maxYear; y >= minYear; y--) {
|
|
2094
|
+
options.push({
|
|
2095
|
+
value: String(y),
|
|
2096
|
+
label: `${y}\uB144`,
|
|
2097
|
+
disabled: maxSelectableYear !== null && y > maxSelectableYear
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
return options;
|
|
2101
|
+
}
|
|
2102
|
+
function buildCalendarMonthSelectOptions(viewYear, maxDate) {
|
|
2103
|
+
const maxDateParsed = maxDate ? parseLocalYmd(maxDate) : null;
|
|
2104
|
+
const maxYear = maxDateParsed?.getFullYear() ?? null;
|
|
2105
|
+
const maxMonth = maxDateParsed !== null && maxDateParsed !== void 0 ? maxDateParsed.getMonth() + 1 : null;
|
|
2106
|
+
const isMaxYear = maxYear !== null && viewYear === maxYear;
|
|
2107
|
+
const options = [];
|
|
2108
|
+
for (let m = 1; m <= 12; m++) {
|
|
2109
|
+
options.push({
|
|
2110
|
+
value: String(m),
|
|
2111
|
+
label: `${m}\uC6D4`,
|
|
2112
|
+
disabled: isMaxYear && maxMonth !== null && m > maxMonth
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
return options;
|
|
2116
|
+
}
|
|
2117
|
+
function getCalendarMonthGrid(year, monthIndex) {
|
|
2118
|
+
const firstDay = new Date(year, monthIndex, 1);
|
|
2119
|
+
const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();
|
|
2120
|
+
const leadingEmpty = firstDay.getDay();
|
|
2121
|
+
const totalCells = leadingEmpty + daysInMonth;
|
|
2122
|
+
const trailingEmpty = totalCells % 7 === 0 ? 0 : 7 - totalCells % 7;
|
|
2123
|
+
return { leadingEmpty, daysInMonth, trailingEmpty };
|
|
2124
|
+
}
|
|
2125
|
+
function disableNextCalendarMonth(year, monthIndex, maxDate) {
|
|
2126
|
+
if (maxDate === void 0) return false;
|
|
2127
|
+
return isCalendarDayAfterMax(new Date(year, monthIndex + 1, 1), maxDate);
|
|
2128
|
+
}
|
|
2129
|
+
function scrollOpenYearSelectCheckedIntoView() {
|
|
2130
|
+
requestAnimationFrame(() => {
|
|
2131
|
+
const root2 = document.querySelector(YEAR_SELECT_OPEN_CONTENT_SELECTOR);
|
|
2132
|
+
if (!(root2 instanceof HTMLElement)) return;
|
|
2133
|
+
const checkedItem = root2.querySelector(SELECT_ITEM_CHECKED_SELECTOR);
|
|
2134
|
+
if (!(checkedItem instanceof HTMLElement)) return;
|
|
2135
|
+
checkedItem.scrollIntoView({ block: "start" });
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
function dayCellButtonClass(opts) {
|
|
2139
|
+
const { isToday, isSelected, isInRange, isRangeStart, isRangeEnd, interactiveDisabled } = opts;
|
|
2140
|
+
const parts = ["w-8 h-8 text-sm flex items-center justify-center rounded-2xl transition-colors"];
|
|
2141
|
+
if (isToday) parts.push("bg-gray-100");
|
|
2142
|
+
if (isSelected && !isToday) parts.push("bg-neutral-200 text-gray-700");
|
|
2143
|
+
if (isInRange && !isToday) parts.push("bg-gray-100/90");
|
|
2144
|
+
if ((isRangeStart || isRangeEnd) && !isToday) parts.push("bg-neutral-300 text-gray-700 opacity-100");
|
|
2145
|
+
parts.push(interactiveDisabled ? "opacity-20 cursor-not-allowed" : "hover:bg-blue-100 cursor-pointer");
|
|
2146
|
+
return parts.filter(Boolean).join(" ").trim();
|
|
2147
|
+
}
|
|
2019
2148
|
function RenderCalendar(props) {
|
|
2020
2149
|
const {
|
|
2021
2150
|
currentDate,
|
|
@@ -2030,133 +2159,163 @@ function RenderCalendar(props) {
|
|
|
2030
2159
|
goToNextMonth,
|
|
2031
2160
|
onYearChange,
|
|
2032
2161
|
onMonthChange,
|
|
2162
|
+
onSelectOpenChange,
|
|
2033
2163
|
editDateSelect = true,
|
|
2034
2164
|
datePosition = "bottom",
|
|
2035
|
-
|
|
2165
|
+
maxDate,
|
|
2166
|
+
calendarYearRange,
|
|
2167
|
+
calendarSelectContainerClass,
|
|
2168
|
+
floating = false,
|
|
2169
|
+
showTodayButton = true
|
|
2036
2170
|
} = props;
|
|
2037
2171
|
const year = currentDate.getFullYear();
|
|
2038
|
-
const
|
|
2039
|
-
const
|
|
2040
|
-
const
|
|
2041
|
-
const
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
const
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
}
|
|
2049
|
-
const lastDay = new Date(year, month + 1, 0);
|
|
2050
|
-
const startDate = new Date(firstDay);
|
|
2051
|
-
startDate.setDate(startDate.getDate() - firstDay.getDay());
|
|
2052
|
-
const endDate = new Date(lastDay);
|
|
2053
|
-
endDate.setDate(endDate.getDate() + (6 - endDate.getDay()));
|
|
2054
|
-
const totalDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
|
|
2172
|
+
const monthIndex = currentDate.getMonth();
|
|
2173
|
+
const anchorYear = (/* @__PURE__ */ new Date()).getFullYear();
|
|
2174
|
+
const disableNextMonth = disableNextCalendarMonth(year, monthIndex, maxDate);
|
|
2175
|
+
const { leadingEmpty, daysInMonth, trailingEmpty } = getCalendarMonthGrid(year, monthIndex);
|
|
2176
|
+
const yearOptions = buildCalendarYearSelectOptions(maxDate, anchorYear, calendarYearRange);
|
|
2177
|
+
const monthOptions = buildCalendarMonthSelectOptions(year, maxDate);
|
|
2178
|
+
const todayFormatted = formatDate(/* @__PURE__ */ new Date());
|
|
2179
|
+
const selectedSingleYmd = range ? null : inputValue;
|
|
2180
|
+
const rangeStartYmd = rangeStart.trim();
|
|
2181
|
+
const rangeEndYmd = rangeEnd.trim();
|
|
2055
2182
|
const days = [];
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
for (let i = 0; i < totalDays; i++) {
|
|
2062
|
-
const date = new Date(startDate);
|
|
2063
|
-
date.setDate(startDate.getDate() + i);
|
|
2183
|
+
for (let i = 0; i < leadingEmpty; i++) {
|
|
2184
|
+
days.push(/* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-8", "aria-hidden": true }, `lead-${i}`));
|
|
2185
|
+
}
|
|
2186
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
2187
|
+
const date = new Date(year, monthIndex, d);
|
|
2064
2188
|
const dateFormatted = formatDate(date);
|
|
2065
|
-
const isToday = dateFormatted ===
|
|
2066
|
-
const isSelected = dateFormatted ===
|
|
2189
|
+
const isToday = dateFormatted === todayFormatted;
|
|
2190
|
+
const isSelected = dateFormatted === selectedSingleYmd;
|
|
2067
2191
|
const isInRange = isDateInRange(date, range, rangeStart, rangeEnd);
|
|
2068
|
-
const
|
|
2069
|
-
const
|
|
2070
|
-
const
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
const
|
|
2192
|
+
const isRangeStartFlag = Boolean(range && dateFormatted === rangeStart);
|
|
2193
|
+
const isRangeEndFlag = Boolean(range && dateFormatted === rangeEnd);
|
|
2194
|
+
const isBeforeRangeStart = range && isSelectingEnd && rangeStartYmd.length === 10 && dateFormatted < rangeStartYmd;
|
|
2195
|
+
const isAfterRangeEnd = range && !isSelectingEnd && rangeEndYmd.length === 10 && dateFormatted > rangeEndYmd;
|
|
2196
|
+
const isGreyedForRange = Boolean(isBeforeRangeStart || isAfterRangeEnd);
|
|
2197
|
+
const isPastMax = maxDate ? isCalendarDayAfterMax(date, maxDate) : false;
|
|
2074
2198
|
days.push(
|
|
2075
2199
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2076
2200
|
"button",
|
|
2077
2201
|
{
|
|
2202
|
+
type: "button",
|
|
2078
2203
|
onClick: () => handleDateSelect(date),
|
|
2079
|
-
disabled:
|
|
2080
|
-
className:
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
children: date.getDate()
|
|
2204
|
+
disabled: isGreyedForRange || isPastMax,
|
|
2205
|
+
className: dayCellButtonClass({
|
|
2206
|
+
isToday,
|
|
2207
|
+
isSelected: Boolean(isSelected),
|
|
2208
|
+
isInRange,
|
|
2209
|
+
isRangeStart: isRangeStartFlag,
|
|
2210
|
+
isRangeEnd: isRangeEndFlag,
|
|
2211
|
+
interactiveDisabled: isGreyedForRange || isPastMax
|
|
2212
|
+
}),
|
|
2213
|
+
children: d
|
|
2090
2214
|
},
|
|
2091
|
-
|
|
2215
|
+
d
|
|
2092
2216
|
)
|
|
2093
2217
|
);
|
|
2094
2218
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2219
|
+
for (let i = 0; i < trailingEmpty; i++) {
|
|
2220
|
+
days.push(/* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-8", "aria-hidden": true }, `trail-${i}`));
|
|
2221
|
+
}
|
|
2222
|
+
const calendarPositionClass = !floating && range && calendarPosition === "end" ? "right-0" : !floating ? "left-0" : "";
|
|
2223
|
+
const datePositionClass = floating ? "" : datePosition === "top" ? "bottom-full mb-1" : "top-full mt-1";
|
|
2224
|
+
const panelClass = floating ? CALENDAR_PANEL_BASE_CLASS : cn(CALENDAR_PANEL_ANCHORED_CLASS, datePositionClass, calendarPositionClass);
|
|
2225
|
+
const handleYearSelectOpenChange = (open) => {
|
|
2226
|
+
onSelectOpenChange?.(open);
|
|
2227
|
+
if (open) scrollOpenYearSelectCheckedIntoView();
|
|
2228
|
+
};
|
|
2229
|
+
const sel = CALENDAR_SELECT_CLASSNAMES;
|
|
2230
|
+
const containerClass = cn(sel.containerClass, calendarSelectContainerClass);
|
|
2231
|
+
const stopBubble = (e) => e.stopPropagation();
|
|
2232
|
+
const isTodaySelectable = canSelectToday({
|
|
2233
|
+
maxDate,
|
|
2234
|
+
range,
|
|
2235
|
+
isSelectingEnd,
|
|
2236
|
+
rangeStart,
|
|
2237
|
+
rangeEnd
|
|
2238
|
+
});
|
|
2239
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: panelClass, onClick: stopBubble, onMouseDown: stopBubble, children: [
|
|
2240
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
2241
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2242
|
+
"button",
|
|
2243
|
+
{
|
|
2244
|
+
type: "button",
|
|
2245
|
+
onClick: goToPreviousMonth,
|
|
2246
|
+
className: "cursor-pointer rounded p-1 hover:bg-gray-100",
|
|
2247
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-4" })
|
|
2248
|
+
}
|
|
2249
|
+
),
|
|
2250
|
+
editDateSelect ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2251
|
+
"div",
|
|
2252
|
+
{
|
|
2253
|
+
role: "presentation",
|
|
2254
|
+
className: "flex items-center gap-2",
|
|
2255
|
+
onClick: stopBubble,
|
|
2256
|
+
onMouseDown: stopBubble,
|
|
2257
|
+
children: [
|
|
2258
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2259
|
+
Select2,
|
|
2260
|
+
{
|
|
2261
|
+
value: year.toString(),
|
|
2262
|
+
options: yearOptions,
|
|
2263
|
+
onChange: (value) => onYearChange(Number.parseInt(value, 10)),
|
|
2264
|
+
containerClassName: containerClass,
|
|
2265
|
+
triggerClassName: sel.triggerClassName,
|
|
2266
|
+
contentClassName: cn(YEAR_SELECT_CONTENT_EXTRA_CLASS, sel.contentClassName),
|
|
2267
|
+
disableScrollButtonEvents: true,
|
|
2268
|
+
onOpenChange: handleYearSelectOpenChange
|
|
2269
|
+
}
|
|
2270
|
+
),
|
|
2271
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2272
|
+
Select2,
|
|
2273
|
+
{
|
|
2274
|
+
value: (monthIndex + 1).toString(),
|
|
2275
|
+
options: monthOptions,
|
|
2276
|
+
onChange: (value) => onMonthChange(Number.parseInt(value, 10) - 1),
|
|
2277
|
+
containerClassName: containerClass,
|
|
2278
|
+
triggerClassName: sel.triggerClassName,
|
|
2279
|
+
contentClassName: sel.contentClassName,
|
|
2280
|
+
onOpenChange: (open) => onSelectOpenChange?.(open)
|
|
2281
|
+
}
|
|
2282
|
+
)
|
|
2283
|
+
]
|
|
2284
|
+
}
|
|
2285
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-lg font-semibold", children: [
|
|
2286
|
+
year,
|
|
2287
|
+
"\uB144 ",
|
|
2288
|
+
monthIndex + 1,
|
|
2289
|
+
"\uC6D4"
|
|
2290
|
+
] }),
|
|
2291
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2292
|
+
"button",
|
|
2293
|
+
{
|
|
2294
|
+
type: "button",
|
|
2295
|
+
onClick: goToNextMonth,
|
|
2296
|
+
disabled: disableNextMonth,
|
|
2297
|
+
className: cn(
|
|
2298
|
+
"rounded p-1",
|
|
2299
|
+
disableNextMonth ? "cursor-not-allowed opacity-30" : "cursor-pointer hover:bg-gray-100"
|
|
2300
|
+
),
|
|
2301
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-4" })
|
|
2302
|
+
}
|
|
2303
|
+
)
|
|
2304
|
+
] }),
|
|
2305
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 grid grid-cols-7 gap-1", children: CALENDAR_WEEKDAY_LABELS.map((day) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 text-center text-sm font-medium text-gray-500", children: day }, day)) }),
|
|
2306
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-2", children: days }),
|
|
2307
|
+
range && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 text-sm text-gray-600", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center", children: isSelectingEnd ? CALENDAR_RANGE_HINT.end : CALENDAR_RANGE_HINT.start }) }),
|
|
2308
|
+
showTodayButton && isTodaySelectable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-3 -mb-3 mt-3 flex items-center justify-center border-t border-gray-200 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2309
|
+
"button",
|
|
2310
|
+
{
|
|
2311
|
+
type: "button",
|
|
2312
|
+
onClick: () => handleDateSelect(/* @__PURE__ */ new Date()),
|
|
2313
|
+
className: "cursor-pointer text-sm text-gray-800 hover:text-main",
|
|
2314
|
+
children: "Today"
|
|
2315
|
+
}
|
|
2316
|
+
) })
|
|
2317
|
+
] });
|
|
2157
2318
|
}
|
|
2158
|
-
|
|
2159
|
-
// src/components/DatePicker/calendar/hooks/useCalendarState.ts
|
|
2160
2319
|
function useCalendarState(props) {
|
|
2161
2320
|
const { datePosition = "bottom", disabled = false, calendarRef } = props;
|
|
2162
2321
|
const [isCalendarOpen, setIsCalendarOpen] = React6.useState(false);
|
|
@@ -2253,11 +2412,15 @@ function useFloatingCalendarPosition(anchorRef, isOpen2, placement, align = "sta
|
|
|
2253
2412
|
setStyle({ ...base, top: rect.bottom + CALENDAR_GAP });
|
|
2254
2413
|
}
|
|
2255
2414
|
};
|
|
2415
|
+
const handleScroll = (e) => {
|
|
2416
|
+
if (e.target?.closest?.('[data-slot="select-content"]')) return;
|
|
2417
|
+
update();
|
|
2418
|
+
};
|
|
2256
2419
|
update();
|
|
2257
|
-
window.addEventListener("scroll",
|
|
2420
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
2258
2421
|
window.addEventListener("resize", update);
|
|
2259
2422
|
return () => {
|
|
2260
|
-
window.removeEventListener("scroll",
|
|
2423
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
2261
2424
|
window.removeEventListener("resize", update);
|
|
2262
2425
|
};
|
|
2263
2426
|
}, [isOpen2, placement, align, anchorRef]);
|
|
@@ -6565,7 +6728,7 @@ function CascadingSelectFieldInner(props) {
|
|
|
6565
6728
|
disabled,
|
|
6566
6729
|
hasError,
|
|
6567
6730
|
options: toSelectOptions(primaryOptions),
|
|
6568
|
-
|
|
6731
|
+
containerClassName: firstSelectClass.containerClassName,
|
|
6569
6732
|
triggerClassName: firstSelectClass.triggerClassName,
|
|
6570
6733
|
canReset: true,
|
|
6571
6734
|
onChange: (nextPrimary) => {
|
|
@@ -6582,7 +6745,7 @@ function CascadingSelectFieldInner(props) {
|
|
|
6582
6745
|
disabled: disabled || !primary || secondaryOptions.length === 0,
|
|
6583
6746
|
hasError,
|
|
6584
6747
|
options: toSelectOptions(secondaryOptions),
|
|
6585
|
-
|
|
6748
|
+
containerClassName: secondSelectClass.containerClassName,
|
|
6586
6749
|
triggerClassName: secondSelectClass.triggerClassName,
|
|
6587
6750
|
canReset: true,
|
|
6588
6751
|
onChange: (nextSecondary) => {
|
|
@@ -6626,7 +6789,8 @@ function DateField(props) {
|
|
|
6626
6789
|
readOnly = false,
|
|
6627
6790
|
className = "w-40",
|
|
6628
6791
|
datePosition = "bottom",
|
|
6629
|
-
disableFutureDates = false
|
|
6792
|
+
disableFutureDates = false,
|
|
6793
|
+
calendarSelectContainerClass = "w-20"
|
|
6630
6794
|
} = config;
|
|
6631
6795
|
const maxDate = disableFutureDates ? formatDate(/* @__PURE__ */ new Date()) : void 0;
|
|
6632
6796
|
if (readOnly) {
|
|
@@ -6643,7 +6807,8 @@ function DateField(props) {
|
|
|
6643
6807
|
className: "w-full",
|
|
6644
6808
|
validation: hasError,
|
|
6645
6809
|
datePosition,
|
|
6646
|
-
maxDate
|
|
6810
|
+
maxDate,
|
|
6811
|
+
calendarSelectContainerClass
|
|
6647
6812
|
}
|
|
6648
6813
|
) });
|
|
6649
6814
|
}
|
|
@@ -6833,7 +6998,9 @@ function RadioField(props) {
|
|
|
6833
6998
|
containerClassName: cn2("justify-start", fieldControlWrapClass(className)),
|
|
6834
6999
|
options: options.map((option) => ({
|
|
6835
7000
|
label: option.label,
|
|
6836
|
-
value: String(option.value)
|
|
7001
|
+
value: String(option.value),
|
|
7002
|
+
disabled: option.disabled,
|
|
7003
|
+
disabledMessage: option.disabledMessage
|
|
6837
7004
|
}))
|
|
6838
7005
|
}
|
|
6839
7006
|
);
|
|
@@ -6871,7 +7038,7 @@ function SelectField(props) {
|
|
|
6871
7038
|
disabled,
|
|
6872
7039
|
hasError,
|
|
6873
7040
|
options: selectOptions,
|
|
6874
|
-
|
|
7041
|
+
containerClassName: "flex w-full min-w-0 max-w-full items-center",
|
|
6875
7042
|
className: "w-full min-w-0",
|
|
6876
7043
|
triggerClassName: cn2(
|
|
6877
7044
|
"h-8 w-full min-w-0 max-w-full rounded border bg-white px-2 py-1 text-sm shadow-none",
|
|
@@ -6983,11 +7150,12 @@ function SelectWithInputField(props) {
|
|
|
6983
7150
|
disabled,
|
|
6984
7151
|
hasError,
|
|
6985
7152
|
options: toSelectOptions(options),
|
|
6986
|
-
|
|
7153
|
+
containerClassName: selectClass.containerClassName,
|
|
6987
7154
|
triggerClassName: selectClass.triggerClassName,
|
|
6988
7155
|
onChange: (nextPrefix) => {
|
|
6989
7156
|
setSelectedPrefix(nextPrefix);
|
|
6990
7157
|
updateCombined(nextPrefix, inputPart);
|
|
7158
|
+
onBlur();
|
|
6991
7159
|
}
|
|
6992
7160
|
}
|
|
6993
7161
|
),
|
|
@@ -7122,7 +7290,7 @@ function useBlurValidation(name, options) {
|
|
|
7122
7290
|
(value, fieldOnChange) => {
|
|
7123
7291
|
markHadValueIfFilled(value);
|
|
7124
7292
|
fieldOnChange(value);
|
|
7125
|
-
if (options.revalidateOnChange || shouldValidateEmptyOnChange(value)) {
|
|
7293
|
+
if (options.revalidateOnChange || options.validateEmptyOnChange && shouldValidateEmptyOnChange(value)) {
|
|
7126
7294
|
void trigger(name);
|
|
7127
7295
|
}
|
|
7128
7296
|
void triggerRelatedFields();
|
|
@@ -7130,6 +7298,7 @@ function useBlurValidation(name, options) {
|
|
|
7130
7298
|
[
|
|
7131
7299
|
markHadValueIfFilled,
|
|
7132
7300
|
options.revalidateOnChange,
|
|
7301
|
+
options.validateEmptyOnChange,
|
|
7133
7302
|
shouldValidateEmptyOnChange,
|
|
7134
7303
|
trigger,
|
|
7135
7304
|
name,
|
|
@@ -7150,9 +7319,7 @@ var REVALIDATE_ON_CHANGE_TYPES = /* @__PURE__ */ new Set([
|
|
|
7150
7319
|
"radio",
|
|
7151
7320
|
"switch",
|
|
7152
7321
|
"select",
|
|
7153
|
-
"date",
|
|
7154
7322
|
"cascading-select",
|
|
7155
|
-
"select-with-input",
|
|
7156
7323
|
"input-with-button",
|
|
7157
7324
|
"address"
|
|
7158
7325
|
]);
|
|
@@ -7173,14 +7340,15 @@ function FormFieldRow(props) {
|
|
|
7173
7340
|
const { control } = reactHookForm.useFormContext();
|
|
7174
7341
|
const { isSubmitted } = reactHookForm.useFormState({ control });
|
|
7175
7342
|
const { name, label, type = "input", required = false, renderCustomField, contentAlign = "left" } = config;
|
|
7343
|
+
const revalidateOnChange = REVALIDATE_ON_CHANGE_TYPES.has(type);
|
|
7176
7344
|
const { handleBlur, handleChange } = useBlurValidation(name, {
|
|
7177
7345
|
required,
|
|
7178
|
-
revalidateOnChange
|
|
7346
|
+
revalidateOnChange,
|
|
7347
|
+
validateEmptyOnChange: revalidateOnChange,
|
|
7179
7348
|
revalidateFields: config.revalidateFields
|
|
7180
7349
|
});
|
|
7181
7350
|
const showError = Boolean(fieldState.error?.message) && (isSubmitted || fieldState.isTouched);
|
|
7182
7351
|
const isTextarea = type === "textarea";
|
|
7183
|
-
const revalidateOnChange = REVALIDATE_ON_CHANGE_TYPES.has(type);
|
|
7184
7352
|
const wrappedField = wrapFieldHandlers(field, {
|
|
7185
7353
|
onBlur: () => handleBlur(() => field.onBlur()),
|
|
7186
7354
|
onChange: (value) => {
|
|
@@ -7285,6 +7453,7 @@ function rowPropsToFieldConfig(props) {
|
|
|
7285
7453
|
canReset,
|
|
7286
7454
|
datePosition,
|
|
7287
7455
|
disableFutureDates,
|
|
7456
|
+
calendarSelectContainerClass,
|
|
7288
7457
|
revalidateFields,
|
|
7289
7458
|
renderCustomField,
|
|
7290
7459
|
colspan,
|
|
@@ -7315,6 +7484,7 @@ function rowPropsToFieldConfig(props) {
|
|
|
7315
7484
|
canReset,
|
|
7316
7485
|
datePosition,
|
|
7317
7486
|
disableFutureDates,
|
|
7487
|
+
calendarSelectContainerClass,
|
|
7318
7488
|
revalidateFields,
|
|
7319
7489
|
renderCustomField,
|
|
7320
7490
|
colspan,
|
|
@@ -7474,14 +7644,7 @@ function PageFilter(props) {
|
|
|
7474
7644
|
const rowGap2 = index !== 0 ? option.label ? gap : 5 : 0;
|
|
7475
7645
|
switch (option.type) {
|
|
7476
7646
|
case "input":
|
|
7477
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7478
|
-
Input2,
|
|
7479
|
-
{
|
|
7480
|
-
placeholder: option.placeholder,
|
|
7481
|
-
value: currentValue,
|
|
7482
|
-
onChange: handleInputChange(optionKey)
|
|
7483
|
-
}
|
|
7484
|
-
) }, String(optionKey));
|
|
7647
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsxRuntime.jsx(Input2, { placeholder: option.placeholder, value: currentValue, onChange: handleInputChange(optionKey) }) }, String(optionKey));
|
|
7485
7648
|
case "select":
|
|
7486
7649
|
return /* @__PURE__ */ jsxRuntime.jsx(LabeledFilterOption, { label: option.label, gap: rowGap2, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7487
7650
|
Select2,
|
|
@@ -7489,7 +7652,8 @@ function PageFilter(props) {
|
|
|
7489
7652
|
value: currentValue,
|
|
7490
7653
|
onChange: handleSelectChange(optionKey),
|
|
7491
7654
|
options: option.options,
|
|
7492
|
-
placeholder: "\uC120\uD0DD
|
|
7655
|
+
placeholder: "\uC120\uD0DD",
|
|
7656
|
+
containerClassName: option.containerClassName ?? "w-30"
|
|
7493
7657
|
}
|
|
7494
7658
|
) }, String(optionKey));
|
|
7495
7659
|
case "radio":
|