@vesture/react 0.1.1 → 0.2.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.css +392 -3
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +98 -2
- package/dist/index.js +1320 -167
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1079,7 +1079,7 @@ function Alert({
|
|
|
1079
1079
|
}
|
|
1080
1080
|
|
|
1081
1081
|
// src/components/DataGrid/DataGrid.tsx
|
|
1082
|
-
import { useCallback as useCallback2, useMemo as useMemo2, useRef as useRef3, useState as useState8 } from "react";
|
|
1082
|
+
import { useCallback as useCallback2, useEffect, useMemo as useMemo2, useRef as useRef3, useState as useState8 } from "react";
|
|
1083
1083
|
|
|
1084
1084
|
// src/components/DataGrid/DataGrid.css.ts
|
|
1085
1085
|
var actionsCell = "DataGrid_actionsCell__7xivx7g";
|
|
@@ -1087,12 +1087,18 @@ var body3 = "DataGrid_body__7xivx77";
|
|
|
1087
1087
|
var cell = "DataGrid_cell__7xivx79";
|
|
1088
1088
|
var checkboxCell = "DataGrid_checkboxCell__7xivx7a";
|
|
1089
1089
|
var container = "DataGrid_container__7xivx71";
|
|
1090
|
-
var editInput = "
|
|
1090
|
+
var editInput = "DataGrid_editInput__7xivx7o";
|
|
1091
1091
|
var emptyState = "DataGrid_emptyState__7xivx7b";
|
|
1092
|
+
var filterCell = "DataGrid_filterCell__7xivx7j";
|
|
1093
|
+
var filterInput = "DataGrid_filterInput__7xivx7k";
|
|
1094
|
+
var filterRow = "DataGrid_filterRow__7xivx7i";
|
|
1095
|
+
var gridWrapper = "DataGrid_gridWrapper__7xivx7l";
|
|
1092
1096
|
var headerButton = "DataGrid_headerButton__7xivx74";
|
|
1093
1097
|
var headerCell = "DataGrid_headerCell__7xivx73";
|
|
1094
1098
|
var headerRow = "DataGrid_headerRow__7xivx72";
|
|
1095
1099
|
var iconButton = "DataGrid_iconButton__7xivx7h";
|
|
1100
|
+
var loadingOverlay = "DataGrid_loadingOverlay__7xivx7m";
|
|
1101
|
+
var paginationFooter = "DataGrid_paginationFooter__7xivx7n";
|
|
1096
1102
|
var pinnedCell = "DataGrid_pinnedCell__7xivx7c";
|
|
1097
1103
|
var pinnedHeaderCell = "DataGrid_pinnedHeaderCell__7xivx7d";
|
|
1098
1104
|
var pinnedLeftEdge = "DataGrid_pinnedLeftEdge__7xivx7e";
|
|
@@ -1107,6 +1113,45 @@ import { Fragment as Fragment5, jsx as jsx34, jsxs as jsxs17 } from "react/jsx-r
|
|
|
1107
1113
|
var DEFAULT_COLUMN_WIDTH = 160;
|
|
1108
1114
|
var CHECKBOX_COLUMN_WIDTH = 44;
|
|
1109
1115
|
var ACTIONS_COLUMN_WIDTH = 72;
|
|
1116
|
+
var FILTER_DEBOUNCE_MS = 200;
|
|
1117
|
+
function useDebouncedValue(value, delay) {
|
|
1118
|
+
const [debounced, setDebounced] = useState8(value);
|
|
1119
|
+
useEffect(() => {
|
|
1120
|
+
const timer = setTimeout(() => setDebounced(value), delay);
|
|
1121
|
+
return () => clearTimeout(timer);
|
|
1122
|
+
}, [value, delay]);
|
|
1123
|
+
return debounced;
|
|
1124
|
+
}
|
|
1125
|
+
function FilterTextInput({
|
|
1126
|
+
value,
|
|
1127
|
+
onChange,
|
|
1128
|
+
...rest
|
|
1129
|
+
}) {
|
|
1130
|
+
const [draft, setDraft] = useState8(value);
|
|
1131
|
+
const debounced = useDebouncedValue(draft, FILTER_DEBOUNCE_MS);
|
|
1132
|
+
const onChangeRef = useRef3(onChange);
|
|
1133
|
+
onChangeRef.current = onChange;
|
|
1134
|
+
const mounted = useRef3(false);
|
|
1135
|
+
useEffect(() => {
|
|
1136
|
+
if (!mounted.current) {
|
|
1137
|
+
mounted.current = true;
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
onChangeRef.current(debounced);
|
|
1141
|
+
}, [debounced]);
|
|
1142
|
+
useEffect(() => {
|
|
1143
|
+
setDraft(value);
|
|
1144
|
+
}, [value]);
|
|
1145
|
+
return /* @__PURE__ */ jsx34(
|
|
1146
|
+
"input",
|
|
1147
|
+
{
|
|
1148
|
+
type: "text",
|
|
1149
|
+
value: draft,
|
|
1150
|
+
onChange: (e) => setDraft(e.target.value),
|
|
1151
|
+
...rest
|
|
1152
|
+
}
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1110
1155
|
function compareValues(a, b) {
|
|
1111
1156
|
if (typeof a === "number" && typeof b === "number") {
|
|
1112
1157
|
return a - b;
|
|
@@ -1131,19 +1176,35 @@ function DataGrid({
|
|
|
1131
1176
|
onSelectionChange,
|
|
1132
1177
|
sort: controlledSort,
|
|
1133
1178
|
onSortChange,
|
|
1179
|
+
filters: controlledFilters,
|
|
1180
|
+
onFilterChange,
|
|
1134
1181
|
emptyMessage = "No data",
|
|
1135
|
-
onRowEdit
|
|
1182
|
+
onRowEdit,
|
|
1183
|
+
serverSide = false,
|
|
1184
|
+
loading = false,
|
|
1185
|
+
totalRowCount,
|
|
1186
|
+
page,
|
|
1187
|
+
pageSize,
|
|
1188
|
+
onPageChange
|
|
1136
1189
|
}) {
|
|
1137
|
-
const [uncontrolledSort, setUncontrolledSort] = useState8(
|
|
1190
|
+
const [uncontrolledSort, setUncontrolledSort] = useState8(
|
|
1191
|
+
null
|
|
1192
|
+
);
|
|
1193
|
+
const [uncontrolledFilters, setUncontrolledFilters] = useState8(
|
|
1194
|
+
[]
|
|
1195
|
+
);
|
|
1138
1196
|
const [uncontrolledSelectedIds, setUncontrolledSelectedIds] = useState8(() => /* @__PURE__ */ new Set());
|
|
1139
1197
|
const [columnWidths, setColumnWidths] = useState8(
|
|
1140
|
-
() => Object.fromEntries(
|
|
1198
|
+
() => Object.fromEntries(
|
|
1199
|
+
columns.map((c) => [c.key, c.width ?? DEFAULT_COLUMN_WIDTH])
|
|
1200
|
+
)
|
|
1141
1201
|
);
|
|
1142
1202
|
const [scrollTop, setScrollTop] = useState8(0);
|
|
1143
1203
|
const [editingRowId, setEditingRowId] = useState8(null);
|
|
1144
1204
|
const [editDraft, setEditDraft] = useState8({});
|
|
1145
1205
|
const editingEnabled = Boolean(onRowEdit);
|
|
1146
1206
|
const sort = controlledSort !== void 0 ? controlledSort : uncontrolledSort;
|
|
1207
|
+
const filters = controlledFilters !== void 0 ? controlledFilters : uncontrolledFilters;
|
|
1147
1208
|
const selectedIds = controlledSelectedIds ?? uncontrolledSelectedIds;
|
|
1148
1209
|
const setSort = (next) => {
|
|
1149
1210
|
if (controlledSort === void 0) {
|
|
@@ -1151,6 +1212,17 @@ function DataGrid({
|
|
|
1151
1212
|
}
|
|
1152
1213
|
onSortChange?.(next);
|
|
1153
1214
|
};
|
|
1215
|
+
const setFilters = (next) => {
|
|
1216
|
+
if (controlledFilters === void 0) {
|
|
1217
|
+
setUncontrolledFilters(next);
|
|
1218
|
+
}
|
|
1219
|
+
onFilterChange?.(next);
|
|
1220
|
+
};
|
|
1221
|
+
const handleFilterChange = (key, value) => {
|
|
1222
|
+
const next = value ? [...filters.filter((f) => f.key !== key), { key, value }] : filters.filter((f) => f.key !== key);
|
|
1223
|
+
setFilters(next);
|
|
1224
|
+
};
|
|
1225
|
+
const getFilterValue = (key) => filters.find((f) => f.key === key)?.value ?? "";
|
|
1154
1226
|
const setSelectedIds = (next) => {
|
|
1155
1227
|
if (controlledSelectedIds === void 0) {
|
|
1156
1228
|
setUncontrolledSelectedIds(next);
|
|
@@ -1167,17 +1239,50 @@ function DataGrid({
|
|
|
1167
1239
|
setSort(null);
|
|
1168
1240
|
}
|
|
1169
1241
|
};
|
|
1242
|
+
const filteredData = useMemo2(() => {
|
|
1243
|
+
if (serverSide || filters.length === 0) {
|
|
1244
|
+
return data;
|
|
1245
|
+
}
|
|
1246
|
+
return data.filter(
|
|
1247
|
+
(row2) => filters.every((f) => {
|
|
1248
|
+
if (!f.value) return true;
|
|
1249
|
+
const column = columns.find((c) => c.key === f.key);
|
|
1250
|
+
if (!column) return true;
|
|
1251
|
+
const cellValue = String(getCellValue(column, row2) ?? "").toLowerCase();
|
|
1252
|
+
return cellValue.includes(f.value.toLowerCase());
|
|
1253
|
+
})
|
|
1254
|
+
);
|
|
1255
|
+
}, [data, filters, columns, serverSide]);
|
|
1170
1256
|
const sortedData = useMemo2(() => {
|
|
1171
|
-
if (
|
|
1257
|
+
if (serverSide) {
|
|
1172
1258
|
return data;
|
|
1173
1259
|
}
|
|
1260
|
+
if (!sort || !sort.direction) {
|
|
1261
|
+
return filteredData;
|
|
1262
|
+
}
|
|
1174
1263
|
const column = columns.find((c) => c.key === sort.key);
|
|
1175
1264
|
if (!column) {
|
|
1176
|
-
return
|
|
1265
|
+
return filteredData;
|
|
1177
1266
|
}
|
|
1178
|
-
const sorted = [...
|
|
1267
|
+
const sorted = [...filteredData].sort(
|
|
1268
|
+
(a, b) => compareValues(getCellValue(column, a), getCellValue(column, b))
|
|
1269
|
+
);
|
|
1179
1270
|
return sort.direction === "desc" ? sorted.reverse() : sorted;
|
|
1180
|
-
}, [
|
|
1271
|
+
}, [filteredData, sort, columns, serverSide, data]);
|
|
1272
|
+
const selectFilterOptions = useMemo2(() => {
|
|
1273
|
+
const map = {};
|
|
1274
|
+
for (const column of columns) {
|
|
1275
|
+
if (!column.filterable || column.filterType !== "select") continue;
|
|
1276
|
+
const values = /* @__PURE__ */ new Set();
|
|
1277
|
+
for (const row2 of data) {
|
|
1278
|
+
values.add(String(getCellValue(column, row2) ?? ""));
|
|
1279
|
+
}
|
|
1280
|
+
map[column.key] = Array.from(values).sort();
|
|
1281
|
+
}
|
|
1282
|
+
return map;
|
|
1283
|
+
}, [columns, data]);
|
|
1284
|
+
const hasFilterableColumns = columns.some((c) => c.filterable);
|
|
1285
|
+
const showPagination = page !== void 0 && pageSize !== void 0 && onPageChange !== void 0;
|
|
1181
1286
|
const allSelected = sortedData.length > 0 && sortedData.every((r) => selectedIds.has(getRowId(r)));
|
|
1182
1287
|
const someSelected = !allSelected && sortedData.some((r) => selectedIds.has(getRowId(r)));
|
|
1183
1288
|
const toggleAll = () => {
|
|
@@ -1212,18 +1317,24 @@ function DataGrid({
|
|
|
1212
1317
|
},
|
|
1213
1318
|
[columnWidths]
|
|
1214
1319
|
);
|
|
1215
|
-
const handleResizeMove = useCallback2(
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1320
|
+
const handleResizeMove = useCallback2(
|
|
1321
|
+
(event) => {
|
|
1322
|
+
const state = resizeState.current;
|
|
1323
|
+
if (!state) return;
|
|
1324
|
+
const delta = event.clientX - state.startX;
|
|
1325
|
+
const minWidth = columns.find((c) => c.key === state.key)?.minWidth ?? 60;
|
|
1326
|
+
const nextWidth = Math.max(minWidth, state.startWidth + delta);
|
|
1327
|
+
setColumnWidths((prev) => ({ ...prev, [state.key]: nextWidth }));
|
|
1328
|
+
},
|
|
1329
|
+
[columns]
|
|
1330
|
+
);
|
|
1331
|
+
const handleResizeEnd = useCallback2(
|
|
1332
|
+
(event) => {
|
|
1333
|
+
resizeState.current = null;
|
|
1334
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
1335
|
+
},
|
|
1336
|
+
[]
|
|
1337
|
+
);
|
|
1227
1338
|
const widthOf = useCallback2(
|
|
1228
1339
|
(column) => columnWidths[column.key] ?? column.width ?? DEFAULT_COLUMN_WIDTH,
|
|
1229
1340
|
[columnWidths]
|
|
@@ -1309,162 +1420,1201 @@ function DataGrid({
|
|
|
1309
1420
|
const endIndex = Math.min(sortedData.length, startIndex + visibleCount);
|
|
1310
1421
|
const visibleRows = sortedData.slice(startIndex, endIndex);
|
|
1311
1422
|
const totalWidth = (selectable ? CHECKBOX_COLUMN_WIDTH : 0) + (editingEnabled ? ACTIONS_COLUMN_WIDTH : 0) + columns.reduce((sum, c) => sum + widthOf(c), 0);
|
|
1312
|
-
return /* @__PURE__ */ jsxs17(
|
|
1313
|
-
"div",
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
{
|
|
1324
|
-
type: "checkbox",
|
|
1325
|
-
checked: allSelected,
|
|
1326
|
-
ref: (el) => {
|
|
1327
|
-
if (el) el.indeterminate = someSelected;
|
|
1328
|
-
},
|
|
1329
|
-
onChange: toggleAll,
|
|
1330
|
-
"aria-label": "Select all rows"
|
|
1331
|
-
}
|
|
1332
|
-
) }) : null,
|
|
1333
|
-
layout.ordered.map((column) => {
|
|
1334
|
-
const width = widthOf(column);
|
|
1335
|
-
const isSorted = sort?.key === column.key;
|
|
1336
|
-
const direction2 = isSorted ? sort.direction : null;
|
|
1337
|
-
return /* @__PURE__ */ jsxs17(
|
|
1423
|
+
return /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1424
|
+
/* @__PURE__ */ jsxs17("div", { className: gridWrapper, children: [
|
|
1425
|
+
/* @__PURE__ */ jsxs17(
|
|
1426
|
+
"div",
|
|
1427
|
+
{
|
|
1428
|
+
className: container,
|
|
1429
|
+
style: { height },
|
|
1430
|
+
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
1431
|
+
role: "table",
|
|
1432
|
+
children: [
|
|
1433
|
+
/* @__PURE__ */ jsxs17(
|
|
1338
1434
|
"div",
|
|
1339
1435
|
{
|
|
1340
|
-
className:
|
|
1341
|
-
style: { width,
|
|
1342
|
-
role: "
|
|
1343
|
-
"aria-sort": direction2 === "asc" ? "ascending" : direction2 === "desc" ? "descending" : "none",
|
|
1436
|
+
className: headerRow,
|
|
1437
|
+
style: { width: totalWidth, minWidth: "100%" },
|
|
1438
|
+
role: "row",
|
|
1344
1439
|
children: [
|
|
1345
|
-
|
|
1346
|
-
column.header,
|
|
1347
|
-
/* @__PURE__ */ jsx34("span", { className: sortIcon, "aria-hidden": "true", children: direction2 === "asc" ? "\u25B2" : direction2 === "desc" ? "\u25BC" : "" })
|
|
1348
|
-
] }) : column.header,
|
|
1349
|
-
column.resizable !== false ? /* @__PURE__ */ jsx34(
|
|
1440
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1350
1441
|
"div",
|
|
1351
1442
|
{
|
|
1352
|
-
className:
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
"aria-orientation": "vertical",
|
|
1358
|
-
"aria-label": `Resize ${String(column.header)} column`
|
|
1359
|
-
}
|
|
1360
|
-
) : null
|
|
1361
|
-
]
|
|
1362
|
-
},
|
|
1363
|
-
column.key
|
|
1364
|
-
);
|
|
1365
|
-
}),
|
|
1366
|
-
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1367
|
-
"div",
|
|
1368
|
-
{
|
|
1369
|
-
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1370
|
-
style: { right: 0 },
|
|
1371
|
-
role: "columnheader",
|
|
1372
|
-
children: /* @__PURE__ */ jsx34("span", { className: srOnly2, children: "Actions" })
|
|
1373
|
-
}
|
|
1374
|
-
) : null
|
|
1375
|
-
] }),
|
|
1376
|
-
sortedData.length === 0 ? /* @__PURE__ */ jsx34("div", { className: emptyState, children: emptyMessage }) : /* @__PURE__ */ jsx34("div", { className: body3, style: { height: totalHeight, width: totalWidth, minWidth: "100%" }, children: visibleRows.map((rowData, i) => {
|
|
1377
|
-
const index = startIndex + i;
|
|
1378
|
-
const id = getRowId(rowData);
|
|
1379
|
-
const isSelected = selectedIds.has(id);
|
|
1380
|
-
const isEditing = editingRowId === id;
|
|
1381
|
-
const style = { top: index * rowHeight, height: rowHeight, width: totalWidth };
|
|
1382
|
-
return /* @__PURE__ */ jsxs17(
|
|
1383
|
-
"div",
|
|
1384
|
-
{
|
|
1385
|
-
className: row,
|
|
1386
|
-
style,
|
|
1387
|
-
role: "row",
|
|
1388
|
-
"data-selected": isSelected || void 0,
|
|
1389
|
-
"data-editing": isEditing || void 0,
|
|
1390
|
-
children: [
|
|
1391
|
-
selectable ? /* @__PURE__ */ jsx34("div", { className: [checkboxCell, pinnedCell].join(" "), style: { left: 0 }, role: "cell", children: /* @__PURE__ */ jsx34(
|
|
1392
|
-
"input",
|
|
1393
|
-
{
|
|
1394
|
-
type: "checkbox",
|
|
1395
|
-
checked: isSelected,
|
|
1396
|
-
onChange: () => toggleRow(id),
|
|
1397
|
-
"aria-label": `Select row ${index + 1}`
|
|
1398
|
-
}
|
|
1399
|
-
) }) : null,
|
|
1400
|
-
layout.ordered.map((column) => /* @__PURE__ */ jsx34(
|
|
1401
|
-
"div",
|
|
1402
|
-
{
|
|
1403
|
-
className: [cell, pinnedClass(column)].filter(Boolean).join(" "),
|
|
1404
|
-
style: { width: widthOf(column), ...pinnedStyle(column) },
|
|
1405
|
-
role: "cell",
|
|
1406
|
-
children: isEditing && column.editable ? /* @__PURE__ */ jsx34(
|
|
1407
|
-
"input",
|
|
1408
|
-
{
|
|
1409
|
-
type: "text",
|
|
1410
|
-
className: editInput,
|
|
1411
|
-
value: editDraft[column.key] ?? "",
|
|
1412
|
-
onChange: (e) => setEditDraft((prev) => ({ ...prev, [column.key]: e.target.value })),
|
|
1413
|
-
onKeyDown: (e) => {
|
|
1414
|
-
if (e.key === "Enter") saveEditing();
|
|
1415
|
-
if (e.key === "Escape") cancelEditing();
|
|
1416
|
-
},
|
|
1417
|
-
"aria-label": `Edit ${String(column.header)}`,
|
|
1418
|
-
autoFocus: column.key === columns.find((c) => c.editable)?.key
|
|
1419
|
-
}
|
|
1420
|
-
) : column.render ? column.render(rowData) : String(getCellValue(column, rowData) ?? "")
|
|
1421
|
-
},
|
|
1422
|
-
column.key
|
|
1423
|
-
)),
|
|
1424
|
-
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1425
|
-
"div",
|
|
1426
|
-
{
|
|
1427
|
-
className: [actionsCell, pinnedCell].join(" "),
|
|
1428
|
-
style: { right: 0 },
|
|
1429
|
-
role: "cell",
|
|
1430
|
-
children: isEditing ? /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1431
|
-
/* @__PURE__ */ jsx34(
|
|
1432
|
-
"button",
|
|
1433
|
-
{
|
|
1434
|
-
type: "button",
|
|
1435
|
-
className: iconButton,
|
|
1436
|
-
onClick: saveEditing,
|
|
1437
|
-
"aria-label": `Save row ${index + 1}`,
|
|
1438
|
-
children: "\u2713"
|
|
1439
|
-
}
|
|
1440
|
-
),
|
|
1441
|
-
/* @__PURE__ */ jsx34(
|
|
1442
|
-
"button",
|
|
1443
|
+
className: [checkboxCell, pinnedHeaderCell].join(" "),
|
|
1444
|
+
style: { left: 0 },
|
|
1445
|
+
role: "columnheader",
|
|
1446
|
+
children: /* @__PURE__ */ jsx34(
|
|
1447
|
+
"input",
|
|
1443
1448
|
{
|
|
1444
|
-
type: "
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
+
type: "checkbox",
|
|
1450
|
+
checked: allSelected,
|
|
1451
|
+
ref: (el) => {
|
|
1452
|
+
if (el) el.indeterminate = someSelected;
|
|
1453
|
+
},
|
|
1454
|
+
onChange: toggleAll,
|
|
1455
|
+
"aria-label": "Select all rows"
|
|
1449
1456
|
}
|
|
1450
1457
|
)
|
|
1451
|
-
|
|
1452
|
-
|
|
1458
|
+
}
|
|
1459
|
+
) : null,
|
|
1460
|
+
layout.ordered.map((column) => {
|
|
1461
|
+
const width = widthOf(column);
|
|
1462
|
+
const isSorted = sort?.key === column.key;
|
|
1463
|
+
const direction2 = isSorted ? sort.direction : null;
|
|
1464
|
+
return /* @__PURE__ */ jsxs17(
|
|
1465
|
+
"div",
|
|
1453
1466
|
{
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
"aria-
|
|
1458
|
-
children:
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1467
|
+
className: [headerCell, headerPinnedClass(column)].filter(Boolean).join(" "),
|
|
1468
|
+
style: { width, ...pinnedStyle(column) },
|
|
1469
|
+
role: "columnheader",
|
|
1470
|
+
"aria-sort": direction2 === "asc" ? "ascending" : direction2 === "desc" ? "descending" : "none",
|
|
1471
|
+
children: [
|
|
1472
|
+
column.sortable ? /* @__PURE__ */ jsxs17(
|
|
1473
|
+
"button",
|
|
1474
|
+
{
|
|
1475
|
+
type: "button",
|
|
1476
|
+
className: headerButton,
|
|
1477
|
+
onClick: () => handleSortClick(column),
|
|
1478
|
+
children: [
|
|
1479
|
+
column.header,
|
|
1480
|
+
/* @__PURE__ */ jsx34("span", { className: sortIcon, "aria-hidden": "true", children: direction2 === "asc" ? "\u25B2" : direction2 === "desc" ? "\u25BC" : "" })
|
|
1481
|
+
]
|
|
1482
|
+
}
|
|
1483
|
+
) : column.header,
|
|
1484
|
+
column.resizable !== false ? /* @__PURE__ */ jsx34(
|
|
1485
|
+
"div",
|
|
1486
|
+
{
|
|
1487
|
+
className: resizeHandle,
|
|
1488
|
+
onPointerDown: (e) => handleResizeStart(e, column),
|
|
1489
|
+
onPointerMove: handleResizeMove,
|
|
1490
|
+
onPointerUp: handleResizeEnd,
|
|
1491
|
+
role: "separator",
|
|
1492
|
+
"aria-orientation": "vertical",
|
|
1493
|
+
"aria-label": `Resize ${String(column.header)} column`
|
|
1494
|
+
}
|
|
1495
|
+
) : null
|
|
1496
|
+
]
|
|
1497
|
+
},
|
|
1498
|
+
column.key
|
|
1499
|
+
);
|
|
1500
|
+
}),
|
|
1501
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1502
|
+
"div",
|
|
1503
|
+
{
|
|
1504
|
+
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1505
|
+
style: { right: 0 },
|
|
1506
|
+
role: "columnheader",
|
|
1507
|
+
children: /* @__PURE__ */ jsx34("span", { className: srOnly2, children: "Actions" })
|
|
1508
|
+
}
|
|
1509
|
+
) : null
|
|
1510
|
+
]
|
|
1511
|
+
}
|
|
1512
|
+
),
|
|
1513
|
+
hasFilterableColumns ? /* @__PURE__ */ jsxs17(
|
|
1514
|
+
"div",
|
|
1515
|
+
{
|
|
1516
|
+
className: filterRow,
|
|
1517
|
+
style: { width: totalWidth, minWidth: "100%" },
|
|
1518
|
+
role: "row",
|
|
1519
|
+
children: [
|
|
1520
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1521
|
+
"div",
|
|
1522
|
+
{
|
|
1523
|
+
className: [checkboxCell, pinnedHeaderCell].join(" "),
|
|
1524
|
+
style: { left: 0 },
|
|
1525
|
+
role: "cell"
|
|
1526
|
+
}
|
|
1527
|
+
) : null,
|
|
1528
|
+
layout.ordered.map((column) => {
|
|
1529
|
+
const width = widthOf(column);
|
|
1530
|
+
return /* @__PURE__ */ jsx34(
|
|
1531
|
+
"div",
|
|
1532
|
+
{
|
|
1533
|
+
className: [filterCell, headerPinnedClass(column)].filter(Boolean).join(" "),
|
|
1534
|
+
style: { width, ...pinnedStyle(column) },
|
|
1535
|
+
role: "cell",
|
|
1536
|
+
children: column.filterable ? column.filterType === "select" ? /* @__PURE__ */ jsxs17(
|
|
1537
|
+
"select",
|
|
1538
|
+
{
|
|
1539
|
+
className: filterInput,
|
|
1540
|
+
value: getFilterValue(column.key),
|
|
1541
|
+
onChange: (e) => handleFilterChange(column.key, e.target.value),
|
|
1542
|
+
"aria-label": `Filter ${String(column.header)}`,
|
|
1543
|
+
children: [
|
|
1544
|
+
/* @__PURE__ */ jsx34("option", { value: "", children: "All" }),
|
|
1545
|
+
(selectFilterOptions[column.key] ?? []).map(
|
|
1546
|
+
(value) => /* @__PURE__ */ jsx34("option", { value, children: value }, value)
|
|
1547
|
+
)
|
|
1548
|
+
]
|
|
1549
|
+
}
|
|
1550
|
+
) : /* @__PURE__ */ jsx34(
|
|
1551
|
+
FilterTextInput,
|
|
1552
|
+
{
|
|
1553
|
+
className: filterInput,
|
|
1554
|
+
value: getFilterValue(column.key),
|
|
1555
|
+
onChange: (value) => handleFilterChange(column.key, value),
|
|
1556
|
+
placeholder: `Filter ${String(column.header)}`,
|
|
1557
|
+
"aria-label": `Filter ${String(column.header)}`
|
|
1558
|
+
}
|
|
1559
|
+
) : null
|
|
1560
|
+
},
|
|
1561
|
+
column.key
|
|
1562
|
+
);
|
|
1563
|
+
}),
|
|
1564
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1565
|
+
"div",
|
|
1566
|
+
{
|
|
1567
|
+
className: [actionsCell, pinnedHeaderCell].join(" "),
|
|
1568
|
+
style: { right: 0 },
|
|
1569
|
+
role: "cell"
|
|
1570
|
+
}
|
|
1571
|
+
) : null
|
|
1572
|
+
]
|
|
1573
|
+
}
|
|
1574
|
+
) : null,
|
|
1575
|
+
sortedData.length === 0 ? /* @__PURE__ */ jsx34("div", { className: emptyState, children: emptyMessage }) : /* @__PURE__ */ jsx34(
|
|
1576
|
+
"div",
|
|
1577
|
+
{
|
|
1578
|
+
className: body3,
|
|
1579
|
+
style: {
|
|
1580
|
+
height: totalHeight,
|
|
1581
|
+
width: totalWidth,
|
|
1582
|
+
minWidth: "100%"
|
|
1583
|
+
},
|
|
1584
|
+
children: visibleRows.map((rowData, i) => {
|
|
1585
|
+
const index = startIndex + i;
|
|
1586
|
+
const id = getRowId(rowData);
|
|
1587
|
+
const isSelected = selectedIds.has(id);
|
|
1588
|
+
const isEditing = editingRowId === id;
|
|
1589
|
+
const style = {
|
|
1590
|
+
top: index * rowHeight,
|
|
1591
|
+
height: rowHeight,
|
|
1592
|
+
width: totalWidth
|
|
1593
|
+
};
|
|
1594
|
+
return /* @__PURE__ */ jsxs17(
|
|
1595
|
+
"div",
|
|
1596
|
+
{
|
|
1597
|
+
className: row,
|
|
1598
|
+
style,
|
|
1599
|
+
role: "row",
|
|
1600
|
+
"data-selected": isSelected || void 0,
|
|
1601
|
+
"data-editing": isEditing || void 0,
|
|
1602
|
+
children: [
|
|
1603
|
+
selectable ? /* @__PURE__ */ jsx34(
|
|
1604
|
+
"div",
|
|
1605
|
+
{
|
|
1606
|
+
className: [checkboxCell, pinnedCell].join(" "),
|
|
1607
|
+
style: { left: 0 },
|
|
1608
|
+
role: "cell",
|
|
1609
|
+
children: /* @__PURE__ */ jsx34(
|
|
1610
|
+
"input",
|
|
1611
|
+
{
|
|
1612
|
+
type: "checkbox",
|
|
1613
|
+
checked: isSelected,
|
|
1614
|
+
onChange: () => toggleRow(id),
|
|
1615
|
+
"aria-label": `Select row ${index + 1}`
|
|
1616
|
+
}
|
|
1617
|
+
)
|
|
1618
|
+
}
|
|
1619
|
+
) : null,
|
|
1620
|
+
layout.ordered.map((column) => /* @__PURE__ */ jsx34(
|
|
1621
|
+
"div",
|
|
1622
|
+
{
|
|
1623
|
+
className: [cell, pinnedClass(column)].filter(Boolean).join(" "),
|
|
1624
|
+
style: {
|
|
1625
|
+
width: widthOf(column),
|
|
1626
|
+
...pinnedStyle(column)
|
|
1627
|
+
},
|
|
1628
|
+
role: "cell",
|
|
1629
|
+
children: isEditing && column.editable ? /* @__PURE__ */ jsx34(
|
|
1630
|
+
"input",
|
|
1631
|
+
{
|
|
1632
|
+
type: "text",
|
|
1633
|
+
className: editInput,
|
|
1634
|
+
value: editDraft[column.key] ?? "",
|
|
1635
|
+
onChange: (e) => setEditDraft((prev) => ({
|
|
1636
|
+
...prev,
|
|
1637
|
+
[column.key]: e.target.value
|
|
1638
|
+
})),
|
|
1639
|
+
onKeyDown: (e) => {
|
|
1640
|
+
if (e.key === "Enter") saveEditing();
|
|
1641
|
+
if (e.key === "Escape") cancelEditing();
|
|
1642
|
+
},
|
|
1643
|
+
"aria-label": `Edit ${String(column.header)}`,
|
|
1644
|
+
autoFocus: column.key === columns.find((c) => c.editable)?.key
|
|
1645
|
+
}
|
|
1646
|
+
) : column.render ? column.render(rowData) : String(getCellValue(column, rowData) ?? "")
|
|
1647
|
+
},
|
|
1648
|
+
column.key
|
|
1649
|
+
)),
|
|
1650
|
+
editingEnabled ? /* @__PURE__ */ jsx34(
|
|
1651
|
+
"div",
|
|
1652
|
+
{
|
|
1653
|
+
className: [actionsCell, pinnedCell].join(" "),
|
|
1654
|
+
style: { right: 0 },
|
|
1655
|
+
role: "cell",
|
|
1656
|
+
children: isEditing ? /* @__PURE__ */ jsxs17(Fragment5, { children: [
|
|
1657
|
+
/* @__PURE__ */ jsx34(
|
|
1658
|
+
"button",
|
|
1659
|
+
{
|
|
1660
|
+
type: "button",
|
|
1661
|
+
className: iconButton,
|
|
1662
|
+
onClick: saveEditing,
|
|
1663
|
+
"aria-label": `Save row ${index + 1}`,
|
|
1664
|
+
children: "\u2713"
|
|
1665
|
+
}
|
|
1666
|
+
),
|
|
1667
|
+
/* @__PURE__ */ jsx34(
|
|
1668
|
+
"button",
|
|
1669
|
+
{
|
|
1670
|
+
type: "button",
|
|
1671
|
+
className: iconButton,
|
|
1672
|
+
onClick: cancelEditing,
|
|
1673
|
+
"aria-label": `Cancel editing row ${index + 1}`,
|
|
1674
|
+
children: "\u2715"
|
|
1675
|
+
}
|
|
1676
|
+
)
|
|
1677
|
+
] }) : /* @__PURE__ */ jsx34(
|
|
1678
|
+
"button",
|
|
1679
|
+
{
|
|
1680
|
+
type: "button",
|
|
1681
|
+
className: iconButton,
|
|
1682
|
+
onClick: () => startEditing(rowData),
|
|
1683
|
+
"aria-label": `Edit row ${index + 1}`,
|
|
1684
|
+
children: "\u270E"
|
|
1685
|
+
}
|
|
1686
|
+
)
|
|
1687
|
+
}
|
|
1688
|
+
) : null
|
|
1689
|
+
]
|
|
1690
|
+
},
|
|
1691
|
+
id
|
|
1692
|
+
);
|
|
1693
|
+
})
|
|
1694
|
+
}
|
|
1695
|
+
)
|
|
1696
|
+
]
|
|
1697
|
+
}
|
|
1698
|
+
),
|
|
1699
|
+
loading ? /* @__PURE__ */ jsx34("div", { className: loadingOverlay, children: /* @__PURE__ */ jsx34(Spinner, { size: "md" }) }) : null
|
|
1700
|
+
] }),
|
|
1701
|
+
showPagination ? /* @__PURE__ */ jsx34("div", { className: paginationFooter, children: /* @__PURE__ */ jsx34(
|
|
1702
|
+
Pagination,
|
|
1703
|
+
{
|
|
1704
|
+
page,
|
|
1705
|
+
totalPages: Math.max(
|
|
1706
|
+
1,
|
|
1707
|
+
Math.ceil((totalRowCount ?? data.length) / pageSize)
|
|
1708
|
+
),
|
|
1709
|
+
onPageChange
|
|
1710
|
+
}
|
|
1711
|
+
) }) : null
|
|
1712
|
+
] });
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
// src/components/Calendar/Calendar.tsx
|
|
1716
|
+
import { useEffect as useEffect2, useMemo as useMemo3, useRef as useRef4, useState as useState9 } from "react";
|
|
1717
|
+
|
|
1718
|
+
// src/components/Calendar/Calendar.css.ts
|
|
1719
|
+
var dayButton = "Calendar_dayButton__1uy43my8";
|
|
1720
|
+
var dayCell = "Calendar_dayCell__1uy43my7";
|
|
1721
|
+
var grid = "Calendar_grid__1uy43my4";
|
|
1722
|
+
var header = "Calendar_header__1uy43my1";
|
|
1723
|
+
var monthLabel = "Calendar_monthLabel__1uy43my2";
|
|
1724
|
+
var navButton = "Calendar_navButton__1uy43my3";
|
|
1725
|
+
var root2 = "Calendar_root__1uy43my0";
|
|
1726
|
+
var weekRow = "Calendar_weekRow__1uy43my5";
|
|
1727
|
+
var weekdayCell = "Calendar_weekdayCell__1uy43my6";
|
|
1728
|
+
|
|
1729
|
+
// src/components/Calendar/Calendar.tsx
|
|
1730
|
+
import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1731
|
+
function startOfMonth(date) {
|
|
1732
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
1733
|
+
}
|
|
1734
|
+
function endOfMonth(date) {
|
|
1735
|
+
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
|
|
1736
|
+
}
|
|
1737
|
+
function addDays(date, amount) {
|
|
1738
|
+
const next = new Date(date);
|
|
1739
|
+
next.setDate(next.getDate() + amount);
|
|
1740
|
+
return next;
|
|
1741
|
+
}
|
|
1742
|
+
function addMonths(date, amount) {
|
|
1743
|
+
const next = new Date(date);
|
|
1744
|
+
next.setMonth(next.getMonth() + amount);
|
|
1745
|
+
return next;
|
|
1746
|
+
}
|
|
1747
|
+
function isSameDay(a, b) {
|
|
1748
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
1749
|
+
}
|
|
1750
|
+
function isSameMonth(a, b) {
|
|
1751
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
1752
|
+
}
|
|
1753
|
+
function clampToMidnight(date) {
|
|
1754
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
1755
|
+
}
|
|
1756
|
+
function startOfWeek(date, weekStartsOn) {
|
|
1757
|
+
const diff = (date.getDay() - weekStartsOn + 7) % 7;
|
|
1758
|
+
return addDays(date, -diff);
|
|
1759
|
+
}
|
|
1760
|
+
function endOfWeek(date, weekStartsOn) {
|
|
1761
|
+
return addDays(startOfWeek(date, weekStartsOn), 6);
|
|
1762
|
+
}
|
|
1763
|
+
function dateKey(date) {
|
|
1764
|
+
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
|
|
1765
|
+
}
|
|
1766
|
+
function getCalendarWeeks(month, weekStartsOn) {
|
|
1767
|
+
const gridStart = startOfWeek(startOfMonth(month), weekStartsOn);
|
|
1768
|
+
const gridEnd = endOfWeek(endOfMonth(month), weekStartsOn);
|
|
1769
|
+
const weeks = [];
|
|
1770
|
+
let cursor = gridStart;
|
|
1771
|
+
while (cursor <= gridEnd) {
|
|
1772
|
+
const week = [];
|
|
1773
|
+
for (let i = 0; i < 7; i++) {
|
|
1774
|
+
week.push(cursor);
|
|
1775
|
+
cursor = addDays(cursor, 1);
|
|
1776
|
+
}
|
|
1777
|
+
weeks.push(week);
|
|
1778
|
+
}
|
|
1779
|
+
return weeks;
|
|
1780
|
+
}
|
|
1781
|
+
function isDateDisabledBy(date, minDate, maxDate, isDateDisabled) {
|
|
1782
|
+
const target = clampToMidnight(date);
|
|
1783
|
+
if (minDate && target < clampToMidnight(minDate)) return true;
|
|
1784
|
+
if (maxDate && target > clampToMidnight(maxDate)) return true;
|
|
1785
|
+
if (isDateDisabled?.(target)) return true;
|
|
1786
|
+
return false;
|
|
1787
|
+
}
|
|
1788
|
+
function findEnabledDate(date, direction2, minDate, maxDate, isDateDisabled) {
|
|
1789
|
+
let cursor = date;
|
|
1790
|
+
for (let i = 0; i < 366; i++) {
|
|
1791
|
+
if (!isDateDisabledBy(cursor, minDate, maxDate, isDateDisabled)) {
|
|
1792
|
+
return cursor;
|
|
1793
|
+
}
|
|
1794
|
+
cursor = addDays(cursor, direction2);
|
|
1795
|
+
}
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
function getFocusableDate(month, value, minDate, maxDate, isDateDisabled) {
|
|
1799
|
+
if (value && isSameMonth(value, month) && !isDateDisabledBy(value, minDate, maxDate, isDateDisabled)) {
|
|
1800
|
+
return clampToMidnight(value);
|
|
1801
|
+
}
|
|
1802
|
+
const today = clampToMidnight(/* @__PURE__ */ new Date());
|
|
1803
|
+
if (isSameMonth(today, month) && !isDateDisabledBy(today, minDate, maxDate, isDateDisabled)) {
|
|
1804
|
+
return today;
|
|
1805
|
+
}
|
|
1806
|
+
const firstEnabled = findEnabledDate(
|
|
1807
|
+
startOfMonth(month),
|
|
1808
|
+
1,
|
|
1809
|
+
minDate,
|
|
1810
|
+
maxDate,
|
|
1811
|
+
isDateDisabled
|
|
1812
|
+
);
|
|
1813
|
+
if (firstEnabled && isSameMonth(firstEnabled, month)) {
|
|
1814
|
+
return firstEnabled;
|
|
1815
|
+
}
|
|
1816
|
+
return startOfMonth(month);
|
|
1817
|
+
}
|
|
1818
|
+
function Calendar({
|
|
1819
|
+
value: controlledValue,
|
|
1820
|
+
defaultValue = null,
|
|
1821
|
+
onChange,
|
|
1822
|
+
month: controlledMonth,
|
|
1823
|
+
onMonthChange,
|
|
1824
|
+
minDate,
|
|
1825
|
+
maxDate,
|
|
1826
|
+
isDateDisabled,
|
|
1827
|
+
weekStartsOn = 1,
|
|
1828
|
+
locale = "en-US",
|
|
1829
|
+
rangeEnd
|
|
1830
|
+
}) {
|
|
1831
|
+
const [uncontrolledValue, setUncontrolledValue] = useState9(
|
|
1832
|
+
defaultValue
|
|
1833
|
+
);
|
|
1834
|
+
const value = controlledValue !== void 0 ? controlledValue : uncontrolledValue;
|
|
1835
|
+
const setValue = (next) => {
|
|
1836
|
+
if (controlledValue === void 0) {
|
|
1837
|
+
setUncontrolledValue(next);
|
|
1838
|
+
}
|
|
1839
|
+
onChange?.(next);
|
|
1840
|
+
};
|
|
1841
|
+
const [uncontrolledMonth, setUncontrolledMonth] = useState9(
|
|
1842
|
+
() => startOfMonth(controlledMonth ?? value ?? /* @__PURE__ */ new Date())
|
|
1843
|
+
);
|
|
1844
|
+
const month = controlledMonth !== void 0 ? startOfMonth(controlledMonth) : uncontrolledMonth;
|
|
1845
|
+
const setMonth = (next) => {
|
|
1846
|
+
const normalized = startOfMonth(next);
|
|
1847
|
+
if (controlledMonth === void 0) {
|
|
1848
|
+
setUncontrolledMonth(normalized);
|
|
1849
|
+
}
|
|
1850
|
+
onMonthChange?.(normalized);
|
|
1851
|
+
};
|
|
1852
|
+
const [rovingDate, setRovingDate] = useState9(
|
|
1853
|
+
() => getFocusableDate(month, value, minDate, maxDate, isDateDisabled)
|
|
1854
|
+
);
|
|
1855
|
+
const shouldFocusRef = useRef4(false);
|
|
1856
|
+
const dayRefs = useRef4(/* @__PURE__ */ new Map());
|
|
1857
|
+
useEffect2(() => {
|
|
1858
|
+
setRovingDate((prev) => {
|
|
1859
|
+
if (isSameMonth(prev, month)) return prev;
|
|
1860
|
+
return getFocusableDate(month, value, minDate, maxDate, isDateDisabled);
|
|
1861
|
+
});
|
|
1862
|
+
}, [month]);
|
|
1863
|
+
useEffect2(() => {
|
|
1864
|
+
if (!shouldFocusRef.current) return;
|
|
1865
|
+
shouldFocusRef.current = false;
|
|
1866
|
+
dayRefs.current.get(dateKey(rovingDate))?.focus();
|
|
1867
|
+
}, [rovingDate, month]);
|
|
1868
|
+
const weeks = useMemo3(
|
|
1869
|
+
() => getCalendarWeeks(month, weekStartsOn),
|
|
1870
|
+
[month, weekStartsOn]
|
|
1871
|
+
);
|
|
1872
|
+
const today = useMemo3(() => clampToMidnight(/* @__PURE__ */ new Date()), []);
|
|
1873
|
+
const monthLabelFormatter = useMemo3(
|
|
1874
|
+
() => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }),
|
|
1875
|
+
[locale]
|
|
1876
|
+
);
|
|
1877
|
+
const weekdayFormatter = useMemo3(
|
|
1878
|
+
() => new Intl.DateTimeFormat(locale, { weekday: "short" }),
|
|
1879
|
+
[locale]
|
|
1880
|
+
);
|
|
1881
|
+
const handleDayClick = (date, disabled, inMonth) => {
|
|
1882
|
+
if (disabled) return;
|
|
1883
|
+
if (!inMonth) {
|
|
1884
|
+
setMonth(startOfMonth(date));
|
|
1885
|
+
return;
|
|
1886
|
+
}
|
|
1887
|
+
const normalized = clampToMidnight(date);
|
|
1888
|
+
setValue(normalized);
|
|
1889
|
+
setRovingDate(normalized);
|
|
1890
|
+
};
|
|
1891
|
+
const handleKeyDown = (event, date) => {
|
|
1892
|
+
let targetRaw;
|
|
1893
|
+
let direction2;
|
|
1894
|
+
switch (event.key) {
|
|
1895
|
+
case "ArrowLeft":
|
|
1896
|
+
targetRaw = addDays(date, -1);
|
|
1897
|
+
direction2 = -1;
|
|
1898
|
+
break;
|
|
1899
|
+
case "ArrowRight":
|
|
1900
|
+
targetRaw = addDays(date, 1);
|
|
1901
|
+
direction2 = 1;
|
|
1902
|
+
break;
|
|
1903
|
+
case "ArrowUp":
|
|
1904
|
+
targetRaw = addDays(date, -7);
|
|
1905
|
+
direction2 = -1;
|
|
1906
|
+
break;
|
|
1907
|
+
case "ArrowDown":
|
|
1908
|
+
targetRaw = addDays(date, 7);
|
|
1909
|
+
direction2 = 1;
|
|
1910
|
+
break;
|
|
1911
|
+
case "Home":
|
|
1912
|
+
targetRaw = startOfWeek(date, weekStartsOn);
|
|
1913
|
+
direction2 = -1;
|
|
1914
|
+
break;
|
|
1915
|
+
case "End":
|
|
1916
|
+
targetRaw = endOfWeek(date, weekStartsOn);
|
|
1917
|
+
direction2 = 1;
|
|
1918
|
+
break;
|
|
1919
|
+
case "PageUp":
|
|
1920
|
+
targetRaw = addMonths(date, -1);
|
|
1921
|
+
direction2 = -1;
|
|
1922
|
+
break;
|
|
1923
|
+
case "PageDown":
|
|
1924
|
+
targetRaw = addMonths(date, 1);
|
|
1925
|
+
direction2 = 1;
|
|
1926
|
+
break;
|
|
1927
|
+
default:
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
event.preventDefault();
|
|
1931
|
+
const target = findEnabledDate(
|
|
1932
|
+
targetRaw,
|
|
1933
|
+
direction2,
|
|
1934
|
+
minDate,
|
|
1935
|
+
maxDate,
|
|
1936
|
+
isDateDisabled
|
|
1937
|
+
);
|
|
1938
|
+
if (!target) return;
|
|
1939
|
+
shouldFocusRef.current = true;
|
|
1940
|
+
setRovingDate(target);
|
|
1941
|
+
if (!isSameMonth(target, month)) {
|
|
1942
|
+
setMonth(startOfMonth(target));
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
const monthLabelText = monthLabelFormatter.format(month);
|
|
1946
|
+
const clampedValue = value ? clampToMidnight(value) : null;
|
|
1947
|
+
const clampedRangeEnd = rangeEnd ? clampToMidnight(rangeEnd) : null;
|
|
1948
|
+
return /* @__PURE__ */ jsxs18("div", { className: root2, role: "application", "aria-label": monthLabelText, children: [
|
|
1949
|
+
/* @__PURE__ */ jsxs18("div", { className: header, children: [
|
|
1950
|
+
/* @__PURE__ */ jsx35(
|
|
1951
|
+
"button",
|
|
1952
|
+
{
|
|
1953
|
+
type: "button",
|
|
1954
|
+
className: navButton,
|
|
1955
|
+
onClick: () => setMonth(addMonths(month, -1)),
|
|
1956
|
+
"aria-label": "Previous month",
|
|
1957
|
+
children: "\u2039"
|
|
1958
|
+
}
|
|
1959
|
+
),
|
|
1960
|
+
/* @__PURE__ */ jsx35("span", { className: monthLabel, children: monthLabelText }),
|
|
1961
|
+
/* @__PURE__ */ jsx35(
|
|
1962
|
+
"button",
|
|
1963
|
+
{
|
|
1964
|
+
type: "button",
|
|
1965
|
+
className: navButton,
|
|
1966
|
+
onClick: () => setMonth(addMonths(month, 1)),
|
|
1967
|
+
"aria-label": "Next month",
|
|
1968
|
+
children: "\u203A"
|
|
1969
|
+
}
|
|
1970
|
+
)
|
|
1971
|
+
] }),
|
|
1972
|
+
/* @__PURE__ */ jsxs18("div", { className: grid, role: "grid", "aria-label": monthLabelText, children: [
|
|
1973
|
+
/* @__PURE__ */ jsx35("div", { className: weekRow, role: "row", children: weeks[0].map((date) => /* @__PURE__ */ jsx35(
|
|
1974
|
+
"div",
|
|
1975
|
+
{
|
|
1976
|
+
className: weekdayCell,
|
|
1977
|
+
role: "columnheader",
|
|
1978
|
+
children: weekdayFormatter.format(date)
|
|
1979
|
+
},
|
|
1980
|
+
dateKey(date)
|
|
1981
|
+
)) }),
|
|
1982
|
+
weeks.map((week, weekIndex) => /* @__PURE__ */ jsx35("div", { className: weekRow, role: "row", children: week.map((date) => {
|
|
1983
|
+
const inMonth = isSameMonth(date, month);
|
|
1984
|
+
const disabled = isDateDisabledBy(
|
|
1985
|
+
date,
|
|
1986
|
+
minDate,
|
|
1987
|
+
maxDate,
|
|
1988
|
+
isDateDisabled
|
|
1989
|
+
);
|
|
1990
|
+
const isRangeEndDay = clampedRangeEnd ? isSameDay(date, clampedRangeEnd) : false;
|
|
1991
|
+
const selected = (clampedValue ? isSameDay(date, clampedValue) : false) || isRangeEndDay;
|
|
1992
|
+
const inRange = Boolean(
|
|
1993
|
+
clampedValue && clampedRangeEnd && date > clampedValue && date < clampedRangeEnd
|
|
1994
|
+
);
|
|
1995
|
+
const isToday = isSameDay(date, today);
|
|
1996
|
+
const tabIndex = inMonth && !disabled && isSameDay(date, rovingDate) ? 0 : -1;
|
|
1997
|
+
return /* @__PURE__ */ jsx35("div", { className: dayCell, role: "gridcell", children: /* @__PURE__ */ jsx35(
|
|
1998
|
+
"button",
|
|
1999
|
+
{
|
|
2000
|
+
type: "button",
|
|
2001
|
+
ref: (el) => {
|
|
2002
|
+
if (el) {
|
|
2003
|
+
dayRefs.current.set(dateKey(date), el);
|
|
2004
|
+
} else {
|
|
2005
|
+
dayRefs.current.delete(dateKey(date));
|
|
2006
|
+
}
|
|
1464
2007
|
},
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
2008
|
+
className: dayButton,
|
|
2009
|
+
"data-outside": !inMonth || void 0,
|
|
2010
|
+
"data-today": isToday || void 0,
|
|
2011
|
+
"data-selected": selected || void 0,
|
|
2012
|
+
"data-in-range": inRange || void 0,
|
|
2013
|
+
disabled,
|
|
2014
|
+
tabIndex,
|
|
2015
|
+
"aria-selected": selected || void 0,
|
|
2016
|
+
"aria-current": isToday ? "date" : void 0,
|
|
2017
|
+
"aria-disabled": disabled || void 0,
|
|
2018
|
+
"aria-label": date.toDateString(),
|
|
2019
|
+
onClick: () => handleDayClick(date, disabled, inMonth),
|
|
2020
|
+
onKeyDown: inMonth ? (e) => handleKeyDown(e, date) : void 0,
|
|
2021
|
+
children: date.getDate()
|
|
2022
|
+
}
|
|
2023
|
+
) }, dateKey(date));
|
|
2024
|
+
}) }, weekIndex))
|
|
2025
|
+
] })
|
|
2026
|
+
] });
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
// src/components/DatePicker/DatePicker.tsx
|
|
2030
|
+
import { useEffect as useEffect3, useRef as useRef5, useState as useState10 } from "react";
|
|
2031
|
+
import {
|
|
2032
|
+
FloatingFocusManager as FloatingFocusManager4,
|
|
2033
|
+
FloatingPortal as FloatingPortal5,
|
|
2034
|
+
autoUpdate as autoUpdate4,
|
|
2035
|
+
flip as flip4,
|
|
2036
|
+
offset as offset4,
|
|
2037
|
+
shift as shift4,
|
|
2038
|
+
useDismiss as useDismiss5,
|
|
2039
|
+
useFloating as useFloating5,
|
|
2040
|
+
useInteractions as useInteractions5,
|
|
2041
|
+
useRole as useRole5
|
|
2042
|
+
} from "@floating-ui/react";
|
|
2043
|
+
|
|
2044
|
+
// src/components/DatePicker/DatePicker.css.ts
|
|
2045
|
+
var dateInput = "DatePicker_dateInput__d7uy1a1";
|
|
2046
|
+
var iconButton2 = "DatePicker_iconButton__d7uy1a2";
|
|
2047
|
+
var popover2 = "DatePicker_popover__d7uy1a3";
|
|
2048
|
+
var wrapper6 = "DatePicker_wrapper__d7uy1a0";
|
|
2049
|
+
|
|
2050
|
+
// src/components/DatePicker/DatePicker.tsx
|
|
2051
|
+
import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2052
|
+
function startOfMonth2(date) {
|
|
2053
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
2054
|
+
}
|
|
2055
|
+
function clampToMidnight2(date) {
|
|
2056
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
2057
|
+
}
|
|
2058
|
+
function isDisabled(date, minDate, maxDate, isDateDisabled) {
|
|
2059
|
+
const target = clampToMidnight2(date);
|
|
2060
|
+
if (minDate && target < clampToMidnight2(minDate)) return true;
|
|
2061
|
+
if (maxDate && target > clampToMidnight2(maxDate)) return true;
|
|
2062
|
+
if (isDateDisabled?.(target)) return true;
|
|
2063
|
+
return false;
|
|
2064
|
+
}
|
|
2065
|
+
function getDatePartOrder(locale) {
|
|
2066
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(
|
|
2067
|
+
new Date(2e3, 0, 2)
|
|
2068
|
+
);
|
|
2069
|
+
return parts.filter(
|
|
2070
|
+
(part) => part.type === "month" || part.type === "day" || part.type === "year"
|
|
2071
|
+
).map((part) => part.type);
|
|
2072
|
+
}
|
|
2073
|
+
function getDatePlaceholder(locale) {
|
|
2074
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(
|
|
2075
|
+
new Date(2e3, 0, 2)
|
|
2076
|
+
);
|
|
2077
|
+
return parts.map((part) => {
|
|
2078
|
+
switch (part.type) {
|
|
2079
|
+
case "month":
|
|
2080
|
+
return "MM";
|
|
2081
|
+
case "day":
|
|
2082
|
+
return "DD";
|
|
2083
|
+
case "year":
|
|
2084
|
+
return "YYYY";
|
|
2085
|
+
default:
|
|
2086
|
+
return part.value;
|
|
2087
|
+
}
|
|
2088
|
+
}).join("");
|
|
2089
|
+
}
|
|
2090
|
+
function formatDate(date, locale) {
|
|
2091
|
+
return new Intl.DateTimeFormat(locale).format(date);
|
|
2092
|
+
}
|
|
2093
|
+
function parseDate(text, locale) {
|
|
2094
|
+
const numbers = text.match(/\d+/g);
|
|
2095
|
+
if (!numbers || numbers.length < 3) return null;
|
|
2096
|
+
const order = getDatePartOrder(locale);
|
|
2097
|
+
if (order.length < 3) return null;
|
|
2098
|
+
const values = {};
|
|
2099
|
+
order.forEach((type, i) => {
|
|
2100
|
+
values[type] = Number.parseInt(numbers[i], 10);
|
|
2101
|
+
});
|
|
2102
|
+
const { month, day, year } = values;
|
|
2103
|
+
if (!month || !day || !year) return null;
|
|
2104
|
+
const fullYear = year < 100 ? 2e3 + year : year;
|
|
2105
|
+
const date = new Date(fullYear, month - 1, day);
|
|
2106
|
+
if (date.getFullYear() !== fullYear || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
2107
|
+
return null;
|
|
2108
|
+
}
|
|
2109
|
+
return date;
|
|
2110
|
+
}
|
|
2111
|
+
function DatePicker({
|
|
2112
|
+
value: controlledValue,
|
|
2113
|
+
defaultValue = null,
|
|
2114
|
+
onChange,
|
|
2115
|
+
minDate,
|
|
2116
|
+
maxDate,
|
|
2117
|
+
isDateDisabled,
|
|
2118
|
+
weekStartsOn = 1,
|
|
2119
|
+
locale = "en-US",
|
|
2120
|
+
placeholder,
|
|
2121
|
+
disabled = false,
|
|
2122
|
+
open: controlledOpen,
|
|
2123
|
+
onOpenChange
|
|
2124
|
+
}) {
|
|
2125
|
+
const [uncontrolledValue, setUncontrolledValue] = useState10(
|
|
2126
|
+
defaultValue
|
|
2127
|
+
);
|
|
2128
|
+
const value = controlledValue !== void 0 ? controlledValue : uncontrolledValue;
|
|
2129
|
+
const setValue = (next) => {
|
|
2130
|
+
if (controlledValue === void 0) {
|
|
2131
|
+
setUncontrolledValue(next);
|
|
2132
|
+
}
|
|
2133
|
+
onChange?.(next);
|
|
2134
|
+
};
|
|
2135
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState10(false);
|
|
2136
|
+
const open = controlledOpen ?? uncontrolledOpen;
|
|
2137
|
+
const setOpen = onOpenChange ?? setUncontrolledOpen;
|
|
2138
|
+
const [month, setMonth] = useState10(
|
|
2139
|
+
() => startOfMonth2(value ?? /* @__PURE__ */ new Date())
|
|
2140
|
+
);
|
|
2141
|
+
const [inputText, setInputText] = useState10(
|
|
2142
|
+
() => value ? formatDate(value, locale) : ""
|
|
2143
|
+
);
|
|
2144
|
+
const inputRef = useRef5(null);
|
|
2145
|
+
useEffect3(() => {
|
|
2146
|
+
setInputText(value ? formatDate(value, locale) : "");
|
|
2147
|
+
}, [value, locale]);
|
|
2148
|
+
useEffect3(() => {
|
|
2149
|
+
if (open && value) {
|
|
2150
|
+
setMonth(startOfMonth2(value));
|
|
2151
|
+
}
|
|
2152
|
+
}, [open]);
|
|
2153
|
+
const { refs, floatingStyles, context } = useFloating5({
|
|
2154
|
+
open,
|
|
2155
|
+
onOpenChange: setOpen,
|
|
2156
|
+
placement: "bottom-start",
|
|
2157
|
+
whileElementsMounted: autoUpdate4,
|
|
2158
|
+
middleware: [offset4(8), flip4(), shift4({ padding: 8 })]
|
|
2159
|
+
});
|
|
2160
|
+
const { getReferenceProps, getFloatingProps } = useInteractions5([
|
|
2161
|
+
useDismiss5(context),
|
|
2162
|
+
useRole5(context, { role: "dialog" })
|
|
2163
|
+
]);
|
|
2164
|
+
const revertInputText = () => {
|
|
2165
|
+
setInputText(value ? formatDate(value, locale) : "");
|
|
2166
|
+
};
|
|
2167
|
+
const commitTypedValue = () => {
|
|
2168
|
+
const trimmed = inputText.trim();
|
|
2169
|
+
if (!trimmed) {
|
|
2170
|
+
if (value !== null) {
|
|
2171
|
+
setValue(null);
|
|
2172
|
+
}
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
const parsed = parseDate(trimmed, locale);
|
|
2176
|
+
if (!parsed || isDisabled(parsed, minDate, maxDate, isDateDisabled)) {
|
|
2177
|
+
revertInputText();
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
setValue(parsed);
|
|
2181
|
+
setMonth(startOfMonth2(parsed));
|
|
2182
|
+
setInputText(formatDate(parsed, locale));
|
|
2183
|
+
};
|
|
2184
|
+
const handleInputKeyDown = (event) => {
|
|
2185
|
+
if (event.key === "Enter") {
|
|
2186
|
+
event.preventDefault();
|
|
2187
|
+
commitTypedValue();
|
|
2188
|
+
}
|
|
2189
|
+
};
|
|
2190
|
+
const handleCalendarChange = (date) => {
|
|
2191
|
+
setValue(date);
|
|
2192
|
+
setMonth(startOfMonth2(date));
|
|
2193
|
+
setOpen(false);
|
|
2194
|
+
};
|
|
2195
|
+
const placeholderText = placeholder ?? getDatePlaceholder(locale);
|
|
2196
|
+
return /* @__PURE__ */ jsxs19("div", { className: wrapper6, ref: refs.setReference, children: [
|
|
2197
|
+
/* @__PURE__ */ jsx36(
|
|
2198
|
+
"input",
|
|
2199
|
+
{
|
|
2200
|
+
ref: inputRef,
|
|
2201
|
+
type: "text",
|
|
2202
|
+
className: dateInput,
|
|
2203
|
+
value: inputText,
|
|
2204
|
+
placeholder: placeholderText,
|
|
2205
|
+
disabled,
|
|
2206
|
+
onChange: (e) => setInputText(e.target.value),
|
|
2207
|
+
onBlur: commitTypedValue,
|
|
2208
|
+
onKeyDown: handleInputKeyDown,
|
|
2209
|
+
"aria-label": "Date"
|
|
2210
|
+
}
|
|
2211
|
+
),
|
|
2212
|
+
/* @__PURE__ */ jsx36(
|
|
2213
|
+
"button",
|
|
2214
|
+
{
|
|
2215
|
+
type: "button",
|
|
2216
|
+
className: iconButton2,
|
|
2217
|
+
disabled,
|
|
2218
|
+
"aria-label": open ? "Close calendar" : "Open calendar",
|
|
2219
|
+
...getReferenceProps({
|
|
2220
|
+
onClick: () => {
|
|
2221
|
+
if (disabled) return;
|
|
2222
|
+
setOpen(!open);
|
|
2223
|
+
}
|
|
2224
|
+
}),
|
|
2225
|
+
children: /* @__PURE__ */ jsxs19(
|
|
2226
|
+
"svg",
|
|
2227
|
+
{
|
|
2228
|
+
width: "16",
|
|
2229
|
+
height: "16",
|
|
2230
|
+
viewBox: "0 0 16 16",
|
|
2231
|
+
fill: "none",
|
|
2232
|
+
"aria-hidden": "true",
|
|
2233
|
+
children: [
|
|
2234
|
+
/* @__PURE__ */ jsx36(
|
|
2235
|
+
"rect",
|
|
2236
|
+
{
|
|
2237
|
+
x: "1.5",
|
|
2238
|
+
y: "2.5",
|
|
2239
|
+
width: "13",
|
|
2240
|
+
height: "12",
|
|
2241
|
+
rx: "1.5",
|
|
2242
|
+
stroke: "currentColor",
|
|
2243
|
+
strokeWidth: "1.3"
|
|
2244
|
+
}
|
|
2245
|
+
),
|
|
2246
|
+
/* @__PURE__ */ jsx36("path", { d: "M1.5 6h13", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
2247
|
+
/* @__PURE__ */ jsx36(
|
|
2248
|
+
"path",
|
|
2249
|
+
{
|
|
2250
|
+
d: "M4.5 1v3M11.5 1v3",
|
|
2251
|
+
stroke: "currentColor",
|
|
2252
|
+
strokeWidth: "1.3",
|
|
2253
|
+
strokeLinecap: "round"
|
|
2254
|
+
}
|
|
2255
|
+
)
|
|
2256
|
+
]
|
|
2257
|
+
}
|
|
2258
|
+
)
|
|
2259
|
+
}
|
|
2260
|
+
),
|
|
2261
|
+
open ? /* @__PURE__ */ jsx36(FloatingPortal5, { children: /* @__PURE__ */ jsx36(
|
|
2262
|
+
FloatingFocusManager4,
|
|
2263
|
+
{
|
|
2264
|
+
context,
|
|
2265
|
+
modal: false,
|
|
2266
|
+
returnFocus: inputRef,
|
|
2267
|
+
children: /* @__PURE__ */ jsx36(
|
|
2268
|
+
"div",
|
|
2269
|
+
{
|
|
2270
|
+
ref: refs.setFloating,
|
|
2271
|
+
className: popover2,
|
|
2272
|
+
style: floatingStyles,
|
|
2273
|
+
...getFloatingProps(),
|
|
2274
|
+
children: /* @__PURE__ */ jsx36(
|
|
2275
|
+
Calendar,
|
|
2276
|
+
{
|
|
2277
|
+
value,
|
|
2278
|
+
onChange: handleCalendarChange,
|
|
2279
|
+
month,
|
|
2280
|
+
onMonthChange: setMonth,
|
|
2281
|
+
minDate,
|
|
2282
|
+
maxDate,
|
|
2283
|
+
isDateDisabled,
|
|
2284
|
+
weekStartsOn,
|
|
2285
|
+
locale
|
|
2286
|
+
}
|
|
2287
|
+
)
|
|
2288
|
+
}
|
|
2289
|
+
)
|
|
2290
|
+
}
|
|
2291
|
+
) }) : null
|
|
2292
|
+
] });
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
// src/components/DateRangePicker/DateRangePicker.tsx
|
|
2296
|
+
import { useEffect as useEffect4, useState as useState11 } from "react";
|
|
2297
|
+
import {
|
|
2298
|
+
FloatingFocusManager as FloatingFocusManager5,
|
|
2299
|
+
FloatingPortal as FloatingPortal6,
|
|
2300
|
+
autoUpdate as autoUpdate5,
|
|
2301
|
+
flip as flip5,
|
|
2302
|
+
offset as offset5,
|
|
2303
|
+
shift as shift5,
|
|
2304
|
+
useDismiss as useDismiss6,
|
|
2305
|
+
useFloating as useFloating6,
|
|
2306
|
+
useInteractions as useInteractions6,
|
|
2307
|
+
useRole as useRole6
|
|
2308
|
+
} from "@floating-ui/react";
|
|
2309
|
+
|
|
2310
|
+
// src/components/DateRangePicker/DateRangePicker.css.ts
|
|
2311
|
+
var dateInput2 = "DateRangePicker_dateInput__11t25r41";
|
|
2312
|
+
var iconButton3 = "DateRangePicker_iconButton__11t25r43";
|
|
2313
|
+
var popover3 = "DateRangePicker_popover__11t25r44";
|
|
2314
|
+
var separator2 = "DateRangePicker_separator__11t25r42";
|
|
2315
|
+
var wrapper7 = "DateRangePicker_wrapper__11t25r40";
|
|
2316
|
+
|
|
2317
|
+
// src/components/DateRangePicker/DateRangePicker.tsx
|
|
2318
|
+
import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2319
|
+
function startOfMonth3(date) {
|
|
2320
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
2321
|
+
}
|
|
2322
|
+
function clampToMidnight3(date) {
|
|
2323
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
2324
|
+
}
|
|
2325
|
+
function compareDates(a, b) {
|
|
2326
|
+
const x = clampToMidnight3(a).getTime();
|
|
2327
|
+
const y = clampToMidnight3(b).getTime();
|
|
2328
|
+
if (x < y) return -1;
|
|
2329
|
+
if (x > y) return 1;
|
|
2330
|
+
return 0;
|
|
2331
|
+
}
|
|
2332
|
+
function isDisabled2(date, minDate, maxDate, isDateDisabled) {
|
|
2333
|
+
const target = clampToMidnight3(date);
|
|
2334
|
+
if (minDate && target < clampToMidnight3(minDate)) return true;
|
|
2335
|
+
if (maxDate && target > clampToMidnight3(maxDate)) return true;
|
|
2336
|
+
if (isDateDisabled?.(target)) return true;
|
|
2337
|
+
return false;
|
|
2338
|
+
}
|
|
2339
|
+
function getDatePartOrder2(locale) {
|
|
2340
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(
|
|
2341
|
+
new Date(2e3, 0, 2)
|
|
2342
|
+
);
|
|
2343
|
+
return parts.filter(
|
|
2344
|
+
(part) => part.type === "month" || part.type === "day" || part.type === "year"
|
|
2345
|
+
).map((part) => part.type);
|
|
2346
|
+
}
|
|
2347
|
+
function getDatePlaceholder2(locale) {
|
|
2348
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(
|
|
2349
|
+
new Date(2e3, 0, 2)
|
|
2350
|
+
);
|
|
2351
|
+
return parts.map((part) => {
|
|
2352
|
+
switch (part.type) {
|
|
2353
|
+
case "month":
|
|
2354
|
+
return "MM";
|
|
2355
|
+
case "day":
|
|
2356
|
+
return "DD";
|
|
2357
|
+
case "year":
|
|
2358
|
+
return "YYYY";
|
|
2359
|
+
default:
|
|
2360
|
+
return part.value;
|
|
2361
|
+
}
|
|
2362
|
+
}).join("");
|
|
2363
|
+
}
|
|
2364
|
+
function formatDate2(date, locale) {
|
|
2365
|
+
return new Intl.DateTimeFormat(locale).format(date);
|
|
2366
|
+
}
|
|
2367
|
+
function parseDate2(text, locale) {
|
|
2368
|
+
const numbers = text.match(/\d+/g);
|
|
2369
|
+
if (!numbers || numbers.length < 3) return null;
|
|
2370
|
+
const order = getDatePartOrder2(locale);
|
|
2371
|
+
if (order.length < 3) return null;
|
|
2372
|
+
const values = {};
|
|
2373
|
+
order.forEach((type, i) => {
|
|
2374
|
+
values[type] = Number.parseInt(numbers[i], 10);
|
|
2375
|
+
});
|
|
2376
|
+
const { month, day, year } = values;
|
|
2377
|
+
if (!month || !day || !year) return null;
|
|
2378
|
+
const fullYear = year < 100 ? 2e3 + year : year;
|
|
2379
|
+
const date = new Date(fullYear, month - 1, day);
|
|
2380
|
+
if (date.getFullYear() !== fullYear || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
2381
|
+
return null;
|
|
2382
|
+
}
|
|
2383
|
+
return date;
|
|
2384
|
+
}
|
|
2385
|
+
var EMPTY_RANGE = { start: null, end: null };
|
|
2386
|
+
function DateRangePicker({
|
|
2387
|
+
value: controlledValue,
|
|
2388
|
+
defaultValue = EMPTY_RANGE,
|
|
2389
|
+
onChange,
|
|
2390
|
+
minDate,
|
|
2391
|
+
maxDate,
|
|
2392
|
+
isDateDisabled,
|
|
2393
|
+
weekStartsOn = 1,
|
|
2394
|
+
locale = "en-US",
|
|
2395
|
+
startPlaceholder,
|
|
2396
|
+
endPlaceholder,
|
|
2397
|
+
disabled = false,
|
|
2398
|
+
open: controlledOpen,
|
|
2399
|
+
onOpenChange
|
|
2400
|
+
}) {
|
|
2401
|
+
const [uncontrolledValue, setUncontrolledValue] = useState11(defaultValue);
|
|
2402
|
+
const value = controlledValue !== void 0 ? controlledValue : uncontrolledValue;
|
|
2403
|
+
const setValue = (next) => {
|
|
2404
|
+
if (controlledValue === void 0) {
|
|
2405
|
+
setUncontrolledValue(next);
|
|
2406
|
+
}
|
|
2407
|
+
onChange?.(next);
|
|
2408
|
+
};
|
|
2409
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState11(false);
|
|
2410
|
+
const open = controlledOpen ?? uncontrolledOpen;
|
|
2411
|
+
const setOpen = onOpenChange ?? setUncontrolledOpen;
|
|
2412
|
+
const [month, setMonth] = useState11(
|
|
2413
|
+
() => startOfMonth3(value.start ?? /* @__PURE__ */ new Date())
|
|
2414
|
+
);
|
|
2415
|
+
const [startText, setStartText] = useState11(
|
|
2416
|
+
() => value.start ? formatDate2(value.start, locale) : ""
|
|
2417
|
+
);
|
|
2418
|
+
const [endText, setEndText] = useState11(
|
|
2419
|
+
() => value.end ? formatDate2(value.end, locale) : ""
|
|
2420
|
+
);
|
|
2421
|
+
useEffect4(() => {
|
|
2422
|
+
setStartText(value.start ? formatDate2(value.start, locale) : "");
|
|
2423
|
+
}, [value.start, locale]);
|
|
2424
|
+
useEffect4(() => {
|
|
2425
|
+
setEndText(value.end ? formatDate2(value.end, locale) : "");
|
|
2426
|
+
}, [value.end, locale]);
|
|
2427
|
+
useEffect4(() => {
|
|
2428
|
+
if (open && value.start) {
|
|
2429
|
+
setMonth(startOfMonth3(value.start));
|
|
2430
|
+
}
|
|
2431
|
+
}, [open]);
|
|
2432
|
+
const { refs, floatingStyles, context } = useFloating6({
|
|
2433
|
+
open,
|
|
2434
|
+
onOpenChange: setOpen,
|
|
2435
|
+
placement: "bottom-start",
|
|
2436
|
+
whileElementsMounted: autoUpdate5,
|
|
2437
|
+
middleware: [offset5(8), flip5(), shift5({ padding: 8 })]
|
|
2438
|
+
});
|
|
2439
|
+
const { getReferenceProps, getFloatingProps } = useInteractions6([
|
|
2440
|
+
useDismiss6(context),
|
|
2441
|
+
useRole6(context, { role: "dialog" })
|
|
2442
|
+
]);
|
|
2443
|
+
const revertStartText = () => {
|
|
2444
|
+
setStartText(value.start ? formatDate2(value.start, locale) : "");
|
|
2445
|
+
};
|
|
2446
|
+
const revertEndText = () => {
|
|
2447
|
+
setEndText(value.end ? formatDate2(value.end, locale) : "");
|
|
2448
|
+
};
|
|
2449
|
+
const commitStartText = () => {
|
|
2450
|
+
const trimmed = startText.trim();
|
|
2451
|
+
if (!trimmed) {
|
|
2452
|
+
if (value.start !== null) {
|
|
2453
|
+
setValue({ start: null, end: value.end });
|
|
2454
|
+
}
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
const parsed = parseDate2(trimmed, locale);
|
|
2458
|
+
if (!parsed || isDisabled2(parsed, minDate, maxDate, isDateDisabled) || value.end && compareDates(parsed, value.end) > 0) {
|
|
2459
|
+
revertStartText();
|
|
2460
|
+
return;
|
|
2461
|
+
}
|
|
2462
|
+
setValue({ start: parsed, end: value.end });
|
|
2463
|
+
setMonth(startOfMonth3(parsed));
|
|
2464
|
+
};
|
|
2465
|
+
const commitEndText = () => {
|
|
2466
|
+
const trimmed = endText.trim();
|
|
2467
|
+
if (!trimmed) {
|
|
2468
|
+
if (value.end !== null) {
|
|
2469
|
+
setValue({ start: value.start, end: null });
|
|
2470
|
+
}
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2473
|
+
const parsed = parseDate2(trimmed, locale);
|
|
2474
|
+
if (!parsed || isDisabled2(parsed, minDate, maxDate, isDateDisabled) || value.start && compareDates(parsed, value.start) < 0) {
|
|
2475
|
+
revertEndText();
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
setValue({ start: value.start, end: parsed });
|
|
2479
|
+
setMonth(startOfMonth3(parsed));
|
|
2480
|
+
};
|
|
2481
|
+
const handleStartKeyDown = (event) => {
|
|
2482
|
+
if (event.key === "Enter") {
|
|
2483
|
+
event.preventDefault();
|
|
2484
|
+
commitStartText();
|
|
2485
|
+
}
|
|
2486
|
+
};
|
|
2487
|
+
const handleEndKeyDown = (event) => {
|
|
2488
|
+
if (event.key === "Enter") {
|
|
2489
|
+
event.preventDefault();
|
|
2490
|
+
commitEndText();
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
const handleCalendarChange = (date) => {
|
|
2494
|
+
const { start, end } = value;
|
|
2495
|
+
if (!start || start && end) {
|
|
2496
|
+
setValue({ start: date, end: null });
|
|
2497
|
+
setMonth(startOfMonth3(date));
|
|
2498
|
+
return;
|
|
2499
|
+
}
|
|
2500
|
+
if (compareDates(date, start) < 0) {
|
|
2501
|
+
setValue({ start: date, end: start });
|
|
2502
|
+
} else {
|
|
2503
|
+
setValue({ start, end: date });
|
|
2504
|
+
}
|
|
2505
|
+
setOpen(false);
|
|
2506
|
+
};
|
|
2507
|
+
const startPlaceholderText = startPlaceholder ?? getDatePlaceholder2(locale);
|
|
2508
|
+
const endPlaceholderText = endPlaceholder ?? getDatePlaceholder2(locale);
|
|
2509
|
+
return /* @__PURE__ */ jsxs20(
|
|
2510
|
+
"div",
|
|
2511
|
+
{
|
|
2512
|
+
className: wrapper7,
|
|
2513
|
+
"data-disabled": disabled || void 0,
|
|
2514
|
+
ref: refs.setReference,
|
|
2515
|
+
children: [
|
|
2516
|
+
/* @__PURE__ */ jsx37(
|
|
2517
|
+
"input",
|
|
2518
|
+
{
|
|
2519
|
+
type: "text",
|
|
2520
|
+
className: dateInput2,
|
|
2521
|
+
value: startText,
|
|
2522
|
+
placeholder: startPlaceholderText,
|
|
2523
|
+
disabled,
|
|
2524
|
+
onChange: (e) => setStartText(e.target.value),
|
|
2525
|
+
onBlur: commitStartText,
|
|
2526
|
+
onKeyDown: handleStartKeyDown,
|
|
2527
|
+
"aria-label": "Start date"
|
|
2528
|
+
}
|
|
2529
|
+
),
|
|
2530
|
+
/* @__PURE__ */ jsx37("span", { className: separator2, "aria-hidden": "true", children: "\u2013" }),
|
|
2531
|
+
/* @__PURE__ */ jsx37(
|
|
2532
|
+
"input",
|
|
2533
|
+
{
|
|
2534
|
+
type: "text",
|
|
2535
|
+
className: dateInput2,
|
|
2536
|
+
value: endText,
|
|
2537
|
+
placeholder: endPlaceholderText,
|
|
2538
|
+
disabled,
|
|
2539
|
+
onChange: (e) => setEndText(e.target.value),
|
|
2540
|
+
onBlur: commitEndText,
|
|
2541
|
+
onKeyDown: handleEndKeyDown,
|
|
2542
|
+
"aria-label": "End date"
|
|
2543
|
+
}
|
|
2544
|
+
),
|
|
2545
|
+
/* @__PURE__ */ jsx37(
|
|
2546
|
+
"button",
|
|
2547
|
+
{
|
|
2548
|
+
type: "button",
|
|
2549
|
+
className: iconButton3,
|
|
2550
|
+
disabled,
|
|
2551
|
+
"aria-label": open ? "Close calendar" : "Open calendar",
|
|
2552
|
+
...getReferenceProps({
|
|
2553
|
+
onClick: () => {
|
|
2554
|
+
if (disabled) return;
|
|
2555
|
+
setOpen(!open);
|
|
2556
|
+
}
|
|
2557
|
+
}),
|
|
2558
|
+
children: /* @__PURE__ */ jsxs20(
|
|
2559
|
+
"svg",
|
|
2560
|
+
{
|
|
2561
|
+
width: "16",
|
|
2562
|
+
height: "16",
|
|
2563
|
+
viewBox: "0 0 16 16",
|
|
2564
|
+
fill: "none",
|
|
2565
|
+
"aria-hidden": "true",
|
|
2566
|
+
children: [
|
|
2567
|
+
/* @__PURE__ */ jsx37(
|
|
2568
|
+
"rect",
|
|
2569
|
+
{
|
|
2570
|
+
x: "1.5",
|
|
2571
|
+
y: "2.5",
|
|
2572
|
+
width: "13",
|
|
2573
|
+
height: "12",
|
|
2574
|
+
rx: "1.5",
|
|
2575
|
+
stroke: "currentColor",
|
|
2576
|
+
strokeWidth: "1.3"
|
|
2577
|
+
}
|
|
2578
|
+
),
|
|
2579
|
+
/* @__PURE__ */ jsx37("path", { d: "M1.5 6h13", stroke: "currentColor", strokeWidth: "1.3" }),
|
|
2580
|
+
/* @__PURE__ */ jsx37(
|
|
2581
|
+
"path",
|
|
2582
|
+
{
|
|
2583
|
+
d: "M4.5 1v3M11.5 1v3",
|
|
2584
|
+
stroke: "currentColor",
|
|
2585
|
+
strokeWidth: "1.3",
|
|
2586
|
+
strokeLinecap: "round"
|
|
2587
|
+
}
|
|
2588
|
+
)
|
|
2589
|
+
]
|
|
2590
|
+
}
|
|
2591
|
+
)
|
|
2592
|
+
}
|
|
2593
|
+
),
|
|
2594
|
+
open ? /* @__PURE__ */ jsx37(FloatingPortal6, { children: /* @__PURE__ */ jsx37(FloatingFocusManager5, { context, modal: false, children: /* @__PURE__ */ jsx37(
|
|
2595
|
+
"div",
|
|
2596
|
+
{
|
|
2597
|
+
ref: refs.setFloating,
|
|
2598
|
+
className: popover3,
|
|
2599
|
+
style: floatingStyles,
|
|
2600
|
+
...getFloatingProps(),
|
|
2601
|
+
children: /* @__PURE__ */ jsx37(
|
|
2602
|
+
Calendar,
|
|
2603
|
+
{
|
|
2604
|
+
value: value.start,
|
|
2605
|
+
rangeEnd: value.end,
|
|
2606
|
+
onChange: handleCalendarChange,
|
|
2607
|
+
month,
|
|
2608
|
+
onMonthChange: setMonth,
|
|
2609
|
+
minDate,
|
|
2610
|
+
maxDate,
|
|
2611
|
+
isDateDisabled,
|
|
2612
|
+
weekStartsOn,
|
|
2613
|
+
locale
|
|
2614
|
+
}
|
|
2615
|
+
)
|
|
2616
|
+
}
|
|
2617
|
+
) }) }) : null
|
|
1468
2618
|
]
|
|
1469
2619
|
}
|
|
1470
2620
|
);
|
|
@@ -1483,9 +2633,12 @@ export {
|
|
|
1483
2633
|
Breadcrumbs2 as Breadcrumbs,
|
|
1484
2634
|
BreadcrumbsItem,
|
|
1485
2635
|
Button,
|
|
2636
|
+
Calendar,
|
|
1486
2637
|
Card,
|
|
1487
2638
|
Checkbox,
|
|
1488
2639
|
DataGrid,
|
|
2640
|
+
DatePicker,
|
|
2641
|
+
DateRangePicker,
|
|
1489
2642
|
Divider,
|
|
1490
2643
|
DropdownMenu2 as DropdownMenu,
|
|
1491
2644
|
DropdownMenuItem,
|