@rufous/ui 0.2.95 → 0.2.97
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/main.cjs +91 -42
- package/dist/main.css +28 -0
- package/dist/main.d.cts +4 -0
- package/dist/main.d.ts +4 -0
- package/dist/main.js +91 -42
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -2989,6 +2989,14 @@ var today = () => {
|
|
|
2989
2989
|
return new Date(t.getFullYear(), t.getMonth(), t.getDate());
|
|
2990
2990
|
};
|
|
2991
2991
|
var isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
2992
|
+
var normaliseBoundary = (d) => {
|
|
2993
|
+
if (!d) return null;
|
|
2994
|
+
const base = d instanceof Date ? d : isoToDate(typeof d === "string" ? d.split("T")[0] : d);
|
|
2995
|
+
if (!base) return null;
|
|
2996
|
+
return new Date(base.getFullYear(), base.getMonth(), base.getDate());
|
|
2997
|
+
};
|
|
2998
|
+
var isBeforeDay = (a, b) => a.getFullYear() < b.getFullYear() || a.getFullYear() === b.getFullYear() && a.getMonth() < b.getMonth() || a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() < b.getDate();
|
|
2999
|
+
var isAfterDay = (a, b) => a.getFullYear() > b.getFullYear() || a.getFullYear() === b.getFullYear() && a.getMonth() > b.getMonth() || a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() > b.getDate();
|
|
2992
3000
|
var isDatetimeType = (t) => t !== "date";
|
|
2993
3001
|
var buildISO = (date, type, hour, minute, ampm) => {
|
|
2994
3002
|
const y = date.getFullYear();
|
|
@@ -3149,15 +3157,13 @@ var CalendarBody = ({
|
|
|
3149
3157
|
onPrev,
|
|
3150
3158
|
onNext,
|
|
3151
3159
|
onMonthSelect,
|
|
3152
|
-
onYearSelect
|
|
3160
|
+
onYearSelect,
|
|
3161
|
+
minDate,
|
|
3162
|
+
maxDate
|
|
3153
3163
|
}) => {
|
|
3154
3164
|
const [pickerView, setPickerView] = (0, import_react21.useState)("calendar");
|
|
3155
|
-
const handleMonthClick = () =>
|
|
3156
|
-
|
|
3157
|
-
};
|
|
3158
|
-
const handleYearClick = () => {
|
|
3159
|
-
setPickerView(pickerView === "year" ? "calendar" : "year");
|
|
3160
|
-
};
|
|
3165
|
+
const handleMonthClick = () => setPickerView(pickerView === "month" ? "calendar" : "month");
|
|
3166
|
+
const handleYearClick = () => setPickerView(pickerView === "year" ? "calendar" : "year");
|
|
3161
3167
|
const handleMonthPick = (month) => {
|
|
3162
3168
|
onMonthSelect(month);
|
|
3163
3169
|
setPickerView("calendar");
|
|
@@ -3169,6 +3175,22 @@ var CalendarBody = ({
|
|
|
3169
3175
|
const currentYear = todayDate.getFullYear();
|
|
3170
3176
|
const yearStart = viewYear - 6;
|
|
3171
3177
|
const years = Array.from({ length: 16 }, (_, i) => yearStart + i);
|
|
3178
|
+
const prevMonthLastDay = new Date(viewYear, viewMonth, 0);
|
|
3179
|
+
const isPrevDisabled = minDate ? isBeforeDay(prevMonthLastDay, minDate) : false;
|
|
3180
|
+
const nextMonthFirstDay = new Date(viewYear, viewMonth + 1, 1);
|
|
3181
|
+
const isNextDisabled = maxDate ? isAfterDay(nextMonthFirstDay, maxDate) : false;
|
|
3182
|
+
const isMonthDisabled = (idx) => {
|
|
3183
|
+
const lastDayOfMonth = new Date(viewYear, idx + 1, 0);
|
|
3184
|
+
const firstDayOfMonth = new Date(viewYear, idx, 1);
|
|
3185
|
+
if (minDate && isBeforeDay(lastDayOfMonth, minDate)) return true;
|
|
3186
|
+
if (maxDate && isAfterDay(firstDayOfMonth, maxDate)) return true;
|
|
3187
|
+
return false;
|
|
3188
|
+
};
|
|
3189
|
+
const isYearDisabled = (y) => {
|
|
3190
|
+
if (minDate && y < minDate.getFullYear()) return true;
|
|
3191
|
+
if (maxDate && y > maxDate.getFullYear()) return true;
|
|
3192
|
+
return false;
|
|
3193
|
+
};
|
|
3172
3194
|
return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__header" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__header-labels" }, /* @__PURE__ */ import_react21.default.createElement(
|
|
3173
3195
|
"span",
|
|
3174
3196
|
{
|
|
@@ -3183,48 +3205,61 @@ var CalendarBody = ({
|
|
|
3183
3205
|
onClick: handleYearClick
|
|
3184
3206
|
},
|
|
3185
3207
|
viewYear
|
|
3186
|
-
)), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) =>
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
"
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3208
|
+
)), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, disabled: isPrevDisabled, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, disabled: isNextDisabled, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) => {
|
|
3209
|
+
const monthDisabled = isMonthDisabled(idx);
|
|
3210
|
+
return /* @__PURE__ */ import_react21.default.createElement(
|
|
3211
|
+
"button",
|
|
3212
|
+
{
|
|
3213
|
+
key: m,
|
|
3214
|
+
type: "button",
|
|
3215
|
+
disabled: monthDisabled,
|
|
3216
|
+
className: [
|
|
3217
|
+
"rf-date-picker__month-cell",
|
|
3218
|
+
idx === viewMonth ? "rf-date-picker__month-cell--selected" : "",
|
|
3219
|
+
idx === todayDate.getMonth() && viewYear === currentYear ? "rf-date-picker__month-cell--current" : "",
|
|
3220
|
+
monthDisabled ? "rf-date-picker__month-cell--disabled" : ""
|
|
3221
|
+
].filter(Boolean).join(" "),
|
|
3222
|
+
onClick: () => !monthDisabled && handleMonthPick(idx)
|
|
3223
|
+
},
|
|
3224
|
+
m
|
|
3225
|
+
);
|
|
3226
|
+
})), pickerView === "year" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__year-grid" }, years.map((y) => {
|
|
3227
|
+
const yearDisabled = isYearDisabled(y);
|
|
3228
|
+
return /* @__PURE__ */ import_react21.default.createElement(
|
|
3229
|
+
"button",
|
|
3230
|
+
{
|
|
3231
|
+
key: y,
|
|
3232
|
+
type: "button",
|
|
3233
|
+
disabled: yearDisabled,
|
|
3234
|
+
className: [
|
|
3235
|
+
"rf-date-picker__year-cell",
|
|
3236
|
+
y === viewYear ? "rf-date-picker__year-cell--selected" : "",
|
|
3237
|
+
y === currentYear ? "rf-date-picker__year-cell--current" : "",
|
|
3238
|
+
yearDisabled ? "rf-date-picker__year-cell--disabled" : ""
|
|
3239
|
+
].filter(Boolean).join(" "),
|
|
3240
|
+
onClick: () => !yearDisabled && handleYearPick(y)
|
|
3241
|
+
},
|
|
3242
|
+
y
|
|
3243
|
+
);
|
|
3244
|
+
})), pickerView === "calendar" && /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__weekdays" }, WEEKDAYS.map((w) => /* @__PURE__ */ import_react21.default.createElement("div", { key: w, className: "rf-date-picker__weekday" }, w))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__grid" }, dayCells.map((day, idx) => {
|
|
3213
3245
|
if (day === null) return /* @__PURE__ */ import_react21.default.createElement("div", { key: `e-${idx}`, className: "rf-date-picker__day rf-date-picker__day--empty" });
|
|
3214
3246
|
const cellDate = new Date(viewYear, viewMonth, day);
|
|
3215
3247
|
const isSelected = selectedDate ? isSameDay(cellDate, selectedDate) : false;
|
|
3216
3248
|
const isToday = isSameDay(cellDate, todayDate);
|
|
3249
|
+
const dayDisabled = (minDate ? isBeforeDay(cellDate, minDate) : false) || (maxDate ? isAfterDay(cellDate, maxDate) : false);
|
|
3217
3250
|
return /* @__PURE__ */ import_react21.default.createElement(
|
|
3218
3251
|
"button",
|
|
3219
3252
|
{
|
|
3220
3253
|
key: day,
|
|
3221
3254
|
type: "button",
|
|
3255
|
+
disabled: dayDisabled,
|
|
3222
3256
|
className: [
|
|
3223
3257
|
"rf-date-picker__day",
|
|
3224
3258
|
isSelected ? "rf-date-picker__day--selected" : "",
|
|
3225
|
-
isToday && !isSelected ? "rf-date-picker__day--today" : ""
|
|
3259
|
+
isToday && !isSelected ? "rf-date-picker__day--today" : "",
|
|
3260
|
+
dayDisabled ? "rf-date-picker__day--disabled" : ""
|
|
3226
3261
|
].filter(Boolean).join(" "),
|
|
3227
|
-
onClick: () => onDayClick(day)
|
|
3262
|
+
onClick: () => !dayDisabled && onDayClick(day)
|
|
3228
3263
|
},
|
|
3229
3264
|
day
|
|
3230
3265
|
);
|
|
@@ -3236,6 +3271,8 @@ var DateField = ({
|
|
|
3236
3271
|
onChange,
|
|
3237
3272
|
type = "date",
|
|
3238
3273
|
dateFormat = "MM/DD/YYYY",
|
|
3274
|
+
minDate: minDateProp,
|
|
3275
|
+
maxDate: maxDateProp,
|
|
3239
3276
|
variant = "outlined",
|
|
3240
3277
|
size = "medium",
|
|
3241
3278
|
color = "primary",
|
|
@@ -3249,6 +3286,8 @@ var DateField = ({
|
|
|
3249
3286
|
style,
|
|
3250
3287
|
sx
|
|
3251
3288
|
}) => {
|
|
3289
|
+
const minDate = normaliseBoundary(minDateProp);
|
|
3290
|
+
const maxDate = normaliseBoundary(maxDateProp);
|
|
3252
3291
|
const sxClass = useSx(sx);
|
|
3253
3292
|
const [open, setOpen] = (0, import_react21.useState)(false);
|
|
3254
3293
|
const [selectedDate, setSelectedDate] = (0, import_react21.useState)(() => value ? isoToDate(value) : null);
|
|
@@ -3348,8 +3387,10 @@ var DateField = ({
|
|
|
3348
3387
|
setInputStr(str);
|
|
3349
3388
|
onChange?.(buildISO(d, type, h, m, ap));
|
|
3350
3389
|
}, [type, onChange, dateFormat]);
|
|
3390
|
+
const isOutOfRange = (d) => (minDate ? isBeforeDay(d, minDate) : false) || (maxDate ? isAfterDay(d, maxDate) : false);
|
|
3351
3391
|
const handleDayClick = (day) => {
|
|
3352
3392
|
const d = new Date(viewYear, viewMonth, day);
|
|
3393
|
+
if (isOutOfRange(d)) return;
|
|
3353
3394
|
setSelectedDate(d);
|
|
3354
3395
|
let str = formatDisplay(d, dateFormat);
|
|
3355
3396
|
if (isDatetimeType(type)) str += " " + formatTimeDisplay(hour, minute, ampm);
|
|
@@ -3359,6 +3400,7 @@ var DateField = ({
|
|
|
3359
3400
|
};
|
|
3360
3401
|
const handleToday = () => {
|
|
3361
3402
|
const t = today();
|
|
3403
|
+
if (isOutOfRange(t)) return;
|
|
3362
3404
|
setViewYear(t.getFullYear());
|
|
3363
3405
|
setViewMonth(t.getMonth());
|
|
3364
3406
|
commitDate(t, hour, minute, ampm);
|
|
@@ -3373,7 +3415,7 @@ var DateField = ({
|
|
|
3373
3415
|
const datePart = words.slice(0, dateWordCount).join(" ");
|
|
3374
3416
|
const timeParts = words.slice(dateWordCount);
|
|
3375
3417
|
const parsed = parseDisplay(datePart, dateFormat);
|
|
3376
|
-
if (parsed) {
|
|
3418
|
+
if (parsed && !isOutOfRange(parsed)) {
|
|
3377
3419
|
setSelectedDate(parsed);
|
|
3378
3420
|
setViewYear(parsed.getFullYear());
|
|
3379
3421
|
setViewMonth(parsed.getMonth());
|
|
@@ -3567,7 +3609,9 @@ var DateField = ({
|
|
|
3567
3609
|
onPrev: prevMonth,
|
|
3568
3610
|
onNext: nextMonth,
|
|
3569
3611
|
onMonthSelect: setViewMonth,
|
|
3570
|
-
onYearSelect: setViewYear
|
|
3612
|
+
onYearSelect: setViewYear,
|
|
3613
|
+
minDate,
|
|
3614
|
+
maxDate
|
|
3571
3615
|
}
|
|
3572
3616
|
), type === "datetime" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ import_react21.default.createElement(
|
|
3573
3617
|
SpinnerPanel,
|
|
@@ -3581,7 +3625,7 @@ var DateField = ({
|
|
|
3581
3625
|
onMinuteInput: handleMinuteInput,
|
|
3582
3626
|
onAmpmToggle: handleAmpmToggle
|
|
3583
3627
|
}
|
|
3584
|
-
)), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
|
|
3628
|
+
)), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday, disabled: isOutOfRange(todayDate) }, "Today"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
|
|
3585
3629
|
type === "datetime-side" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ import_react21.default.createElement(
|
|
3586
3630
|
SpinnerPanel,
|
|
3587
3631
|
{
|
|
@@ -4622,9 +4666,14 @@ function DataGrid({
|
|
|
4622
4666
|
const headers = exportableCols.map((c) => c.headerName).join(",");
|
|
4623
4667
|
const rows = sortedData.map(
|
|
4624
4668
|
(item) => exportableCols.map((c) => {
|
|
4625
|
-
const
|
|
4626
|
-
const
|
|
4627
|
-
|
|
4669
|
+
const field = String(c.field);
|
|
4670
|
+
const raw = item[field];
|
|
4671
|
+
let val = c.valueGetter ? c.valueGetter({ value: raw, row: item, field }) : raw;
|
|
4672
|
+
if (c.valueFormatter) {
|
|
4673
|
+
val = c.valueFormatter({ value: val, row: item, field });
|
|
4674
|
+
}
|
|
4675
|
+
const str = val === null || val === void 0 ? "" : String(val).replace(/"/g, '""');
|
|
4676
|
+
return `"${str}"`;
|
|
4628
4677
|
}).join(",")
|
|
4629
4678
|
);
|
|
4630
4679
|
const csv = [headers, ...rows].join("\n");
|
package/dist/main.css
CHANGED
|
@@ -1758,6 +1758,34 @@ pre {
|
|
|
1758
1758
|
color: #a41b06;
|
|
1759
1759
|
font-weight: 600;
|
|
1760
1760
|
}
|
|
1761
|
+
.rf-date-picker__day--disabled,
|
|
1762
|
+
.rf-date-picker__day:disabled {
|
|
1763
|
+
opacity: 0.3;
|
|
1764
|
+
cursor: not-allowed;
|
|
1765
|
+
pointer-events: none;
|
|
1766
|
+
}
|
|
1767
|
+
.rf-date-picker__month-cell--disabled,
|
|
1768
|
+
.rf-date-picker__month-cell:disabled {
|
|
1769
|
+
opacity: 0.3;
|
|
1770
|
+
cursor: not-allowed;
|
|
1771
|
+
pointer-events: none;
|
|
1772
|
+
}
|
|
1773
|
+
.rf-date-picker__year-cell--disabled,
|
|
1774
|
+
.rf-date-picker__year-cell:disabled {
|
|
1775
|
+
opacity: 0.3;
|
|
1776
|
+
cursor: not-allowed;
|
|
1777
|
+
pointer-events: none;
|
|
1778
|
+
}
|
|
1779
|
+
.rf-date-picker__nav-btn:disabled {
|
|
1780
|
+
opacity: 0.3;
|
|
1781
|
+
cursor: not-allowed;
|
|
1782
|
+
pointer-events: none;
|
|
1783
|
+
}
|
|
1784
|
+
.rf-date-picker__footer-btn:disabled {
|
|
1785
|
+
opacity: 0.3;
|
|
1786
|
+
cursor: not-allowed;
|
|
1787
|
+
pointer-events: none;
|
|
1788
|
+
}
|
|
1761
1789
|
|
|
1762
1790
|
/* lib/styles/date-range-field.css */
|
|
1763
1791
|
.rf-date-range-field {
|
package/dist/main.d.cts
CHANGED
|
@@ -627,6 +627,10 @@ interface DateFieldProps {
|
|
|
627
627
|
type?: "date" | "datetime" | "datetime-side" | "datetime-scroll";
|
|
628
628
|
/** Display format for the date in the input field. Default: "MM/DD/YYYY" */
|
|
629
629
|
dateFormat?: DateFormatString;
|
|
630
|
+
/** Earliest selectable date — ISO string "YYYY-MM-DD" or a Date object */
|
|
631
|
+
minDate?: string | Date;
|
|
632
|
+
/** Latest selectable date — ISO string "YYYY-MM-DD" or a Date object */
|
|
633
|
+
maxDate?: string | Date;
|
|
630
634
|
variant?: "outlined" | "filled" | "standard" | "compact";
|
|
631
635
|
size?: "small" | "medium";
|
|
632
636
|
color?: "primary" | "secondary" | "error" | "success" | "info" | "warning";
|
package/dist/main.d.ts
CHANGED
|
@@ -627,6 +627,10 @@ interface DateFieldProps {
|
|
|
627
627
|
type?: "date" | "datetime" | "datetime-side" | "datetime-scroll";
|
|
628
628
|
/** Display format for the date in the input field. Default: "MM/DD/YYYY" */
|
|
629
629
|
dateFormat?: DateFormatString;
|
|
630
|
+
/** Earliest selectable date — ISO string "YYYY-MM-DD" or a Date object */
|
|
631
|
+
minDate?: string | Date;
|
|
632
|
+
/** Latest selectable date — ISO string "YYYY-MM-DD" or a Date object */
|
|
633
|
+
maxDate?: string | Date;
|
|
630
634
|
variant?: "outlined" | "filled" | "standard" | "compact";
|
|
631
635
|
size?: "small" | "medium";
|
|
632
636
|
color?: "primary" | "secondary" | "error" | "success" | "info" | "warning";
|
package/dist/main.js
CHANGED
|
@@ -2838,6 +2838,14 @@ var today = () => {
|
|
|
2838
2838
|
return new Date(t.getFullYear(), t.getMonth(), t.getDate());
|
|
2839
2839
|
};
|
|
2840
2840
|
var isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
2841
|
+
var normaliseBoundary = (d) => {
|
|
2842
|
+
if (!d) return null;
|
|
2843
|
+
const base = d instanceof Date ? d : isoToDate(typeof d === "string" ? d.split("T")[0] : d);
|
|
2844
|
+
if (!base) return null;
|
|
2845
|
+
return new Date(base.getFullYear(), base.getMonth(), base.getDate());
|
|
2846
|
+
};
|
|
2847
|
+
var isBeforeDay = (a, b) => a.getFullYear() < b.getFullYear() || a.getFullYear() === b.getFullYear() && a.getMonth() < b.getMonth() || a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() < b.getDate();
|
|
2848
|
+
var isAfterDay = (a, b) => a.getFullYear() > b.getFullYear() || a.getFullYear() === b.getFullYear() && a.getMonth() > b.getMonth() || a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() > b.getDate();
|
|
2841
2849
|
var isDatetimeType = (t) => t !== "date";
|
|
2842
2850
|
var buildISO = (date, type, hour, minute, ampm) => {
|
|
2843
2851
|
const y = date.getFullYear();
|
|
@@ -2998,15 +3006,13 @@ var CalendarBody = ({
|
|
|
2998
3006
|
onPrev,
|
|
2999
3007
|
onNext,
|
|
3000
3008
|
onMonthSelect,
|
|
3001
|
-
onYearSelect
|
|
3009
|
+
onYearSelect,
|
|
3010
|
+
minDate,
|
|
3011
|
+
maxDate
|
|
3002
3012
|
}) => {
|
|
3003
3013
|
const [pickerView, setPickerView] = useState7("calendar");
|
|
3004
|
-
const handleMonthClick = () =>
|
|
3005
|
-
|
|
3006
|
-
};
|
|
3007
|
-
const handleYearClick = () => {
|
|
3008
|
-
setPickerView(pickerView === "year" ? "calendar" : "year");
|
|
3009
|
-
};
|
|
3014
|
+
const handleMonthClick = () => setPickerView(pickerView === "month" ? "calendar" : "month");
|
|
3015
|
+
const handleYearClick = () => setPickerView(pickerView === "year" ? "calendar" : "year");
|
|
3010
3016
|
const handleMonthPick = (month) => {
|
|
3011
3017
|
onMonthSelect(month);
|
|
3012
3018
|
setPickerView("calendar");
|
|
@@ -3018,6 +3024,22 @@ var CalendarBody = ({
|
|
|
3018
3024
|
const currentYear = todayDate.getFullYear();
|
|
3019
3025
|
const yearStart = viewYear - 6;
|
|
3020
3026
|
const years = Array.from({ length: 16 }, (_, i) => yearStart + i);
|
|
3027
|
+
const prevMonthLastDay = new Date(viewYear, viewMonth, 0);
|
|
3028
|
+
const isPrevDisabled = minDate ? isBeforeDay(prevMonthLastDay, minDate) : false;
|
|
3029
|
+
const nextMonthFirstDay = new Date(viewYear, viewMonth + 1, 1);
|
|
3030
|
+
const isNextDisabled = maxDate ? isAfterDay(nextMonthFirstDay, maxDate) : false;
|
|
3031
|
+
const isMonthDisabled = (idx) => {
|
|
3032
|
+
const lastDayOfMonth = new Date(viewYear, idx + 1, 0);
|
|
3033
|
+
const firstDayOfMonth = new Date(viewYear, idx, 1);
|
|
3034
|
+
if (minDate && isBeforeDay(lastDayOfMonth, minDate)) return true;
|
|
3035
|
+
if (maxDate && isAfterDay(firstDayOfMonth, maxDate)) return true;
|
|
3036
|
+
return false;
|
|
3037
|
+
};
|
|
3038
|
+
const isYearDisabled = (y) => {
|
|
3039
|
+
if (minDate && y < minDate.getFullYear()) return true;
|
|
3040
|
+
if (maxDate && y > maxDate.getFullYear()) return true;
|
|
3041
|
+
return false;
|
|
3042
|
+
};
|
|
3021
3043
|
return /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__header" }, /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__header-labels" }, /* @__PURE__ */ React72.createElement(
|
|
3022
3044
|
"span",
|
|
3023
3045
|
{
|
|
@@ -3032,48 +3054,61 @@ var CalendarBody = ({
|
|
|
3032
3054
|
onClick: handleYearClick
|
|
3033
3055
|
},
|
|
3034
3056
|
viewYear
|
|
3035
|
-
)), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) =>
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
"
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3057
|
+
)), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, disabled: isPrevDisabled, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, disabled: isNextDisabled, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) => {
|
|
3058
|
+
const monthDisabled = isMonthDisabled(idx);
|
|
3059
|
+
return /* @__PURE__ */ React72.createElement(
|
|
3060
|
+
"button",
|
|
3061
|
+
{
|
|
3062
|
+
key: m,
|
|
3063
|
+
type: "button",
|
|
3064
|
+
disabled: monthDisabled,
|
|
3065
|
+
className: [
|
|
3066
|
+
"rf-date-picker__month-cell",
|
|
3067
|
+
idx === viewMonth ? "rf-date-picker__month-cell--selected" : "",
|
|
3068
|
+
idx === todayDate.getMonth() && viewYear === currentYear ? "rf-date-picker__month-cell--current" : "",
|
|
3069
|
+
monthDisabled ? "rf-date-picker__month-cell--disabled" : ""
|
|
3070
|
+
].filter(Boolean).join(" "),
|
|
3071
|
+
onClick: () => !monthDisabled && handleMonthPick(idx)
|
|
3072
|
+
},
|
|
3073
|
+
m
|
|
3074
|
+
);
|
|
3075
|
+
})), pickerView === "year" && /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__year-grid" }, years.map((y) => {
|
|
3076
|
+
const yearDisabled = isYearDisabled(y);
|
|
3077
|
+
return /* @__PURE__ */ React72.createElement(
|
|
3078
|
+
"button",
|
|
3079
|
+
{
|
|
3080
|
+
key: y,
|
|
3081
|
+
type: "button",
|
|
3082
|
+
disabled: yearDisabled,
|
|
3083
|
+
className: [
|
|
3084
|
+
"rf-date-picker__year-cell",
|
|
3085
|
+
y === viewYear ? "rf-date-picker__year-cell--selected" : "",
|
|
3086
|
+
y === currentYear ? "rf-date-picker__year-cell--current" : "",
|
|
3087
|
+
yearDisabled ? "rf-date-picker__year-cell--disabled" : ""
|
|
3088
|
+
].filter(Boolean).join(" "),
|
|
3089
|
+
onClick: () => !yearDisabled && handleYearPick(y)
|
|
3090
|
+
},
|
|
3091
|
+
y
|
|
3092
|
+
);
|
|
3093
|
+
})), pickerView === "calendar" && /* @__PURE__ */ React72.createElement(React72.Fragment, null, /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__weekdays" }, WEEKDAYS.map((w) => /* @__PURE__ */ React72.createElement("div", { key: w, className: "rf-date-picker__weekday" }, w))), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__grid" }, dayCells.map((day, idx) => {
|
|
3062
3094
|
if (day === null) return /* @__PURE__ */ React72.createElement("div", { key: `e-${idx}`, className: "rf-date-picker__day rf-date-picker__day--empty" });
|
|
3063
3095
|
const cellDate = new Date(viewYear, viewMonth, day);
|
|
3064
3096
|
const isSelected = selectedDate ? isSameDay(cellDate, selectedDate) : false;
|
|
3065
3097
|
const isToday = isSameDay(cellDate, todayDate);
|
|
3098
|
+
const dayDisabled = (minDate ? isBeforeDay(cellDate, minDate) : false) || (maxDate ? isAfterDay(cellDate, maxDate) : false);
|
|
3066
3099
|
return /* @__PURE__ */ React72.createElement(
|
|
3067
3100
|
"button",
|
|
3068
3101
|
{
|
|
3069
3102
|
key: day,
|
|
3070
3103
|
type: "button",
|
|
3104
|
+
disabled: dayDisabled,
|
|
3071
3105
|
className: [
|
|
3072
3106
|
"rf-date-picker__day",
|
|
3073
3107
|
isSelected ? "rf-date-picker__day--selected" : "",
|
|
3074
|
-
isToday && !isSelected ? "rf-date-picker__day--today" : ""
|
|
3108
|
+
isToday && !isSelected ? "rf-date-picker__day--today" : "",
|
|
3109
|
+
dayDisabled ? "rf-date-picker__day--disabled" : ""
|
|
3075
3110
|
].filter(Boolean).join(" "),
|
|
3076
|
-
onClick: () => onDayClick(day)
|
|
3111
|
+
onClick: () => !dayDisabled && onDayClick(day)
|
|
3077
3112
|
},
|
|
3078
3113
|
day
|
|
3079
3114
|
);
|
|
@@ -3085,6 +3120,8 @@ var DateField = ({
|
|
|
3085
3120
|
onChange,
|
|
3086
3121
|
type = "date",
|
|
3087
3122
|
dateFormat = "MM/DD/YYYY",
|
|
3123
|
+
minDate: minDateProp,
|
|
3124
|
+
maxDate: maxDateProp,
|
|
3088
3125
|
variant = "outlined",
|
|
3089
3126
|
size = "medium",
|
|
3090
3127
|
color = "primary",
|
|
@@ -3098,6 +3135,8 @@ var DateField = ({
|
|
|
3098
3135
|
style,
|
|
3099
3136
|
sx
|
|
3100
3137
|
}) => {
|
|
3138
|
+
const minDate = normaliseBoundary(minDateProp);
|
|
3139
|
+
const maxDate = normaliseBoundary(maxDateProp);
|
|
3101
3140
|
const sxClass = useSx(sx);
|
|
3102
3141
|
const [open, setOpen] = useState7(false);
|
|
3103
3142
|
const [selectedDate, setSelectedDate] = useState7(() => value ? isoToDate(value) : null);
|
|
@@ -3197,8 +3236,10 @@ var DateField = ({
|
|
|
3197
3236
|
setInputStr(str);
|
|
3198
3237
|
onChange?.(buildISO(d, type, h, m, ap));
|
|
3199
3238
|
}, [type, onChange, dateFormat]);
|
|
3239
|
+
const isOutOfRange = (d) => (minDate ? isBeforeDay(d, minDate) : false) || (maxDate ? isAfterDay(d, maxDate) : false);
|
|
3200
3240
|
const handleDayClick = (day) => {
|
|
3201
3241
|
const d = new Date(viewYear, viewMonth, day);
|
|
3242
|
+
if (isOutOfRange(d)) return;
|
|
3202
3243
|
setSelectedDate(d);
|
|
3203
3244
|
let str = formatDisplay(d, dateFormat);
|
|
3204
3245
|
if (isDatetimeType(type)) str += " " + formatTimeDisplay(hour, minute, ampm);
|
|
@@ -3208,6 +3249,7 @@ var DateField = ({
|
|
|
3208
3249
|
};
|
|
3209
3250
|
const handleToday = () => {
|
|
3210
3251
|
const t = today();
|
|
3252
|
+
if (isOutOfRange(t)) return;
|
|
3211
3253
|
setViewYear(t.getFullYear());
|
|
3212
3254
|
setViewMonth(t.getMonth());
|
|
3213
3255
|
commitDate(t, hour, minute, ampm);
|
|
@@ -3222,7 +3264,7 @@ var DateField = ({
|
|
|
3222
3264
|
const datePart = words.slice(0, dateWordCount).join(" ");
|
|
3223
3265
|
const timeParts = words.slice(dateWordCount);
|
|
3224
3266
|
const parsed = parseDisplay(datePart, dateFormat);
|
|
3225
|
-
if (parsed) {
|
|
3267
|
+
if (parsed && !isOutOfRange(parsed)) {
|
|
3226
3268
|
setSelectedDate(parsed);
|
|
3227
3269
|
setViewYear(parsed.getFullYear());
|
|
3228
3270
|
setViewMonth(parsed.getMonth());
|
|
@@ -3416,7 +3458,9 @@ var DateField = ({
|
|
|
3416
3458
|
onPrev: prevMonth,
|
|
3417
3459
|
onNext: nextMonth,
|
|
3418
3460
|
onMonthSelect: setViewMonth,
|
|
3419
|
-
onYearSelect: setViewYear
|
|
3461
|
+
onYearSelect: setViewYear,
|
|
3462
|
+
minDate,
|
|
3463
|
+
maxDate
|
|
3420
3464
|
}
|
|
3421
3465
|
), type === "datetime" && /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ React72.createElement(
|
|
3422
3466
|
SpinnerPanel,
|
|
@@ -3430,7 +3474,7 @@ var DateField = ({
|
|
|
3430
3474
|
onMinuteInput: handleMinuteInput,
|
|
3431
3475
|
onAmpmToggle: handleAmpmToggle
|
|
3432
3476
|
}
|
|
3433
|
-
)), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
|
|
3477
|
+
)), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday, disabled: isOutOfRange(todayDate) }, "Today"), /* @__PURE__ */ React72.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
|
|
3434
3478
|
type === "datetime-side" && /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React72.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ React72.createElement(
|
|
3435
3479
|
SpinnerPanel,
|
|
3436
3480
|
{
|
|
@@ -4492,9 +4536,14 @@ function DataGrid({
|
|
|
4492
4536
|
const headers = exportableCols.map((c) => c.headerName).join(",");
|
|
4493
4537
|
const rows = sortedData.map(
|
|
4494
4538
|
(item) => exportableCols.map((c) => {
|
|
4495
|
-
const
|
|
4496
|
-
const
|
|
4497
|
-
|
|
4539
|
+
const field = String(c.field);
|
|
4540
|
+
const raw = item[field];
|
|
4541
|
+
let val = c.valueGetter ? c.valueGetter({ value: raw, row: item, field }) : raw;
|
|
4542
|
+
if (c.valueFormatter) {
|
|
4543
|
+
val = c.valueFormatter({ value: val, row: item, field });
|
|
4544
|
+
}
|
|
4545
|
+
const str = val === null || val === void 0 ? "" : String(val).replace(/"/g, '""');
|
|
4546
|
+
return `"${str}"`;
|
|
4498
4547
|
}).join(",")
|
|
4499
4548
|
);
|
|
4500
4549
|
const csv = [headers, ...rows].join("\n");
|