@wordrhyme/auto-crud 1.5.6 → 1.6.0
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/README.md +37 -0
- package/dist/index.cjs +449 -288
- package/dist/index.d.cts +24 -8
- package/dist/index.d.ts +40 -24
- package/dist/index.js +449 -288
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -420,13 +420,15 @@ function hasValidCanonicalDateTimePrefix(value) {
|
|
|
420
420
|
const match = canonicalDateTimePrefixPattern.exec(value);
|
|
421
421
|
return !match || isValidCalendarDate(match[1], match[2], match[3]);
|
|
422
422
|
}
|
|
423
|
+
function getDateLocaleOptions() {
|
|
424
|
+
return hostDateFormatters[hostDateFormatters.length - 1]?.options;
|
|
425
|
+
}
|
|
423
426
|
/**
|
|
424
|
-
* Register the host's
|
|
425
|
-
*
|
|
426
|
-
* this registration, so overlapping registrations may be disposed out of order.
|
|
427
|
+
* Register the host's date formatter and optional calendar locale policy.
|
|
428
|
+
* Cleanup removes only this registration, including out-of-order cleanup.
|
|
427
429
|
* Passing undefined clears every registration.
|
|
428
430
|
*/
|
|
429
|
-
function setDateFormatter(formatter) {
|
|
431
|
+
function setDateFormatter(formatter, options) {
|
|
430
432
|
if (formatter === void 0) {
|
|
431
433
|
const hadFormatter = hostDateFormatters.length > 0;
|
|
432
434
|
hostDateFormatters = [];
|
|
@@ -435,15 +437,16 @@ function setDateFormatter(formatter) {
|
|
|
435
437
|
}
|
|
436
438
|
const registration = {
|
|
437
439
|
formatter,
|
|
440
|
+
...options ? { options } : {},
|
|
438
441
|
token: Symbol("date-formatter")
|
|
439
442
|
};
|
|
440
443
|
hostDateFormatters.push(registration);
|
|
441
444
|
notifyDateFormatterChange();
|
|
442
445
|
return () => {
|
|
443
|
-
const
|
|
446
|
+
const currentRegistration = hostDateFormatters[hostDateFormatters.length - 1];
|
|
444
447
|
const previousLength = hostDateFormatters.length;
|
|
445
448
|
hostDateFormatters = hostDateFormatters.filter(({ token }) => token !== registration.token);
|
|
446
|
-
if (hostDateFormatters.length !== previousLength &&
|
|
449
|
+
if (hostDateFormatters.length !== previousLength && hostDateFormatters[hostDateFormatters.length - 1] !== currentRegistration) notifyDateFormatterChange();
|
|
447
450
|
};
|
|
448
451
|
}
|
|
449
452
|
function formatDate(date, opts = {}, preset) {
|
|
@@ -525,104 +528,6 @@ function DataTable({ table, actionBar, children, className,...props }) {
|
|
|
525
528
|
});
|
|
526
529
|
}
|
|
527
530
|
|
|
528
|
-
//#endregion
|
|
529
|
-
//#region src/lib/id.ts
|
|
530
|
-
const prefixes = {};
|
|
531
|
-
function generateId(prefixOrOptions, inputOptions = {}) {
|
|
532
|
-
const finalOptions = typeof prefixOrOptions === "object" ? prefixOrOptions : inputOptions;
|
|
533
|
-
const prefix = typeof prefixOrOptions === "object" ? void 0 : prefixOrOptions;
|
|
534
|
-
const { length = 12, separator = "_" } = finalOptions;
|
|
535
|
-
const id = (0, nanoid.customAlphabet)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", length)();
|
|
536
|
-
return prefix && prefix in prefixes ? `${prefixes[prefix]}${separator}${id}` : id;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
//#endregion
|
|
540
|
-
//#region src/lib/readable-filters.ts
|
|
541
|
-
const OP_SUFFIX = "__op";
|
|
542
|
-
const INDEX_SEPARATOR = "__";
|
|
543
|
-
const RANGE_VARIANTS = new Set(["range", "dateRange"]);
|
|
544
|
-
function getColumnId(column) {
|
|
545
|
-
if ("id" in column && column.id) return String(column.id);
|
|
546
|
-
if ("accessorKey" in column && column.accessorKey) return String(column.accessorKey);
|
|
547
|
-
return null;
|
|
548
|
-
}
|
|
549
|
-
function getColumnVariant(column) {
|
|
550
|
-
if ("columnDef" in column) return column.columnDef.meta?.variant;
|
|
551
|
-
return column.meta?.variant;
|
|
552
|
-
}
|
|
553
|
-
function splitKey(key) {
|
|
554
|
-
const match = key.match(/^(.*?)(?:__(\d+))?$/);
|
|
555
|
-
if (!match) return { base: key };
|
|
556
|
-
const index$1 = match[2] ? Number(match[2]) : void 0;
|
|
557
|
-
return {
|
|
558
|
-
base: match[1] ?? key,
|
|
559
|
-
index: index$1
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
function isFilterKey(key, columnIds) {
|
|
563
|
-
const { base } = splitKey(key.endsWith(OP_SUFFIX) ? key.slice(0, -4) : key);
|
|
564
|
-
return columnIds.has(base);
|
|
565
|
-
}
|
|
566
|
-
function parseValueByVariant(value, variant) {
|
|
567
|
-
if (variant === "multiSelect") return value ? value.split(",").filter(Boolean) : [];
|
|
568
|
-
if (RANGE_VARIANTS.has(variant)) {
|
|
569
|
-
const parts = value.split(",");
|
|
570
|
-
return [parts[0] ?? "", parts[1] ?? ""];
|
|
571
|
-
}
|
|
572
|
-
if (variant === "select") return value.split(",").filter(Boolean)[0] ?? "";
|
|
573
|
-
return value;
|
|
574
|
-
}
|
|
575
|
-
function serializeValue(value, variant) {
|
|
576
|
-
if (Array.isArray(value)) {
|
|
577
|
-
if (RANGE_VARIANTS.has(variant)) return [value[0] ?? "", value[1] ?? ""].join(",");
|
|
578
|
-
return value.join(",");
|
|
579
|
-
}
|
|
580
|
-
return value;
|
|
581
|
-
}
|
|
582
|
-
function parseReadableFilters(params, columns) {
|
|
583
|
-
const columnsById = /* @__PURE__ */ new Map();
|
|
584
|
-
for (const column of columns) {
|
|
585
|
-
const id = getColumnId(column);
|
|
586
|
-
if (id) columnsById.set(id, column);
|
|
587
|
-
}
|
|
588
|
-
const filters = [];
|
|
589
|
-
for (const [key, rawValue] of params.entries()) {
|
|
590
|
-
if (key.endsWith(OP_SUFFIX)) continue;
|
|
591
|
-
const { base } = splitKey(key);
|
|
592
|
-
const column = columnsById.get(base);
|
|
593
|
-
if (!column) continue;
|
|
594
|
-
const variant = getColumnVariant(column) ?? "text";
|
|
595
|
-
const opKey = `${key}${OP_SUFFIX}`;
|
|
596
|
-
const operator = params.get(opKey) ?? getDefaultFilterOperator(variant);
|
|
597
|
-
const parsedValue = operator === "isEmpty" || operator === "isNotEmpty" ? "" : parseValueByVariant(rawValue, variant);
|
|
598
|
-
filters.push({
|
|
599
|
-
id: base,
|
|
600
|
-
value: parsedValue,
|
|
601
|
-
variant,
|
|
602
|
-
operator,
|
|
603
|
-
filterId: key || generateId({ length: 8 })
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
return filters;
|
|
607
|
-
}
|
|
608
|
-
function applyReadableFilters(params, columns, filters) {
|
|
609
|
-
const columnIds = new Set(columns.map((column) => getColumnId(column)).filter(Boolean));
|
|
610
|
-
for (const key of Array.from(params.keys())) if (isFilterKey(key, columnIds)) params.delete(key);
|
|
611
|
-
const counters = /* @__PURE__ */ new Map();
|
|
612
|
-
for (const filter of filters) {
|
|
613
|
-
const columnId = String(filter.id);
|
|
614
|
-
const count = (counters.get(columnId) ?? 0) + 1;
|
|
615
|
-
counters.set(columnId, count);
|
|
616
|
-
const key = count === 1 ? columnId : `${columnId}${INDEX_SEPARATOR}${count}`;
|
|
617
|
-
const variant = filter.variant ?? "text";
|
|
618
|
-
const value = serializeValue(filter.value, variant);
|
|
619
|
-
params.set(key, filter.operator === "isEmpty" || filter.operator === "isNotEmpty" ? "" : value);
|
|
620
|
-
const defaultOperator = getDefaultFilterOperator(variant);
|
|
621
|
-
if (filter.operator !== defaultOperator) params.set(`${key}${OP_SUFFIX}`, filter.operator);
|
|
622
|
-
}
|
|
623
|
-
return params;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
531
|
//#endregion
|
|
627
532
|
//#region src/hooks/use-url-state.ts
|
|
628
533
|
const parseAsInteger = {
|
|
@@ -873,15 +778,120 @@ function useQueryStates(parsers, options = {}) {
|
|
|
873
778
|
}, [setValues])];
|
|
874
779
|
}
|
|
875
780
|
|
|
781
|
+
//#endregion
|
|
782
|
+
//#region src/lib/id.ts
|
|
783
|
+
const prefixes = {};
|
|
784
|
+
function generateId(prefixOrOptions, inputOptions = {}) {
|
|
785
|
+
const finalOptions = typeof prefixOrOptions === "object" ? prefixOrOptions : inputOptions;
|
|
786
|
+
const prefix = typeof prefixOrOptions === "object" ? void 0 : prefixOrOptions;
|
|
787
|
+
const { length = 12, separator = "_" } = finalOptions;
|
|
788
|
+
const id = (0, nanoid.customAlphabet)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", length)();
|
|
789
|
+
return prefix && prefix in prefixes ? `${prefixes[prefix]}${separator}${id}` : id;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
//#endregion
|
|
793
|
+
//#region src/lib/readable-filters.ts
|
|
794
|
+
const OP_SUFFIX = "__op";
|
|
795
|
+
const INDEX_SEPARATOR = "__";
|
|
796
|
+
const RANGE_VARIANTS = new Set(["range", "dateRange"]);
|
|
797
|
+
function getColumnId(column) {
|
|
798
|
+
if ("id" in column && column.id) return String(column.id);
|
|
799
|
+
if ("accessorKey" in column && column.accessorKey) return String(column.accessorKey);
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
function getColumnVariant(column) {
|
|
803
|
+
if ("columnDef" in column) return column.columnDef.meta?.variant;
|
|
804
|
+
return column.meta?.variant;
|
|
805
|
+
}
|
|
806
|
+
function splitKey(key) {
|
|
807
|
+
const match = key.match(/^(.*?)(?:__(\d+))?$/);
|
|
808
|
+
if (!match) return { base: key };
|
|
809
|
+
const index$1 = match[2] ? Number(match[2]) : void 0;
|
|
810
|
+
return {
|
|
811
|
+
base: match[1] ?? key,
|
|
812
|
+
index: index$1
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
function isFilterKey(key, columnIds) {
|
|
816
|
+
const { base } = splitKey(key.endsWith(OP_SUFFIX) ? key.slice(0, -4) : key);
|
|
817
|
+
return columnIds.has(base);
|
|
818
|
+
}
|
|
819
|
+
function parseValueByVariant(value, variant) {
|
|
820
|
+
if (variant === "multiSelect") return value ? value.split(",").filter(Boolean) : [];
|
|
821
|
+
if (RANGE_VARIANTS.has(variant)) {
|
|
822
|
+
const parts = value.split(",");
|
|
823
|
+
return [parts[0] ?? "", parts[1] ?? ""];
|
|
824
|
+
}
|
|
825
|
+
if (variant === "select") return value.split(",").filter(Boolean)[0] ?? "";
|
|
826
|
+
return value;
|
|
827
|
+
}
|
|
828
|
+
function serializeValue(value, variant) {
|
|
829
|
+
if (Array.isArray(value)) {
|
|
830
|
+
if (RANGE_VARIANTS.has(variant)) return [value[0] ?? "", value[1] ?? ""].join(",");
|
|
831
|
+
return value.join(",");
|
|
832
|
+
}
|
|
833
|
+
return value;
|
|
834
|
+
}
|
|
835
|
+
function parseReadableFilters(params, columns) {
|
|
836
|
+
const columnsById = /* @__PURE__ */ new Map();
|
|
837
|
+
for (const column of columns) {
|
|
838
|
+
const id = getColumnId(column);
|
|
839
|
+
if (id) columnsById.set(id, column);
|
|
840
|
+
}
|
|
841
|
+
const filters = [];
|
|
842
|
+
for (const [key, rawValue] of params.entries()) {
|
|
843
|
+
if (key.endsWith(OP_SUFFIX)) continue;
|
|
844
|
+
const { base } = splitKey(key);
|
|
845
|
+
const column = columnsById.get(base);
|
|
846
|
+
if (!column) continue;
|
|
847
|
+
const variant = getColumnVariant(column) ?? "text";
|
|
848
|
+
const opKey = `${key}${OP_SUFFIX}`;
|
|
849
|
+
const operator = params.get(opKey) ?? getDefaultFilterOperator(variant);
|
|
850
|
+
const parsedValue = operator === "isEmpty" || operator === "isNotEmpty" ? "" : parseValueByVariant(rawValue, variant);
|
|
851
|
+
filters.push({
|
|
852
|
+
id: base,
|
|
853
|
+
value: parsedValue,
|
|
854
|
+
variant,
|
|
855
|
+
operator,
|
|
856
|
+
filterId: key || generateId({ length: 8 })
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
return filters;
|
|
860
|
+
}
|
|
861
|
+
function applyReadableFilters(params, columns, filters) {
|
|
862
|
+
const columnIds = new Set(columns.map((column) => getColumnId(column)).filter(Boolean));
|
|
863
|
+
for (const key of Array.from(params.keys())) if (isFilterKey(key, columnIds)) params.delete(key);
|
|
864
|
+
const counters = /* @__PURE__ */ new Map();
|
|
865
|
+
for (const filter of filters) {
|
|
866
|
+
const columnId = String(filter.id);
|
|
867
|
+
const count = (counters.get(columnId) ?? 0) + 1;
|
|
868
|
+
counters.set(columnId, count);
|
|
869
|
+
const key = count === 1 ? columnId : `${columnId}${INDEX_SEPARATOR}${count}`;
|
|
870
|
+
const variant = filter.variant ?? "text";
|
|
871
|
+
const value = serializeValue(filter.value, variant);
|
|
872
|
+
params.set(key, filter.operator === "isEmpty" || filter.operator === "isNotEmpty" ? "" : value);
|
|
873
|
+
const defaultOperator = getDefaultFilterOperator(variant);
|
|
874
|
+
if (filter.operator !== defaultOperator) params.set(`${key}${OP_SUFFIX}`, filter.operator);
|
|
875
|
+
}
|
|
876
|
+
return params;
|
|
877
|
+
}
|
|
878
|
+
|
|
876
879
|
//#endregion
|
|
877
880
|
//#region src/hooks/use-readable-filters.ts
|
|
878
881
|
const URL_CHANGE_EVENT = "urlchange";
|
|
879
882
|
function toSearchString(params) {
|
|
880
|
-
const queryString = params.toString().replace(/%2C/
|
|
883
|
+
const queryString = params.toString().replace(/%2C/gu, ",");
|
|
881
884
|
return queryString ? `?${queryString}` : "";
|
|
882
885
|
}
|
|
886
|
+
function filterSignature(filters) {
|
|
887
|
+
return JSON.stringify(filters.map(({ id, operator, value, variant }) => JSON.stringify([
|
|
888
|
+
id,
|
|
889
|
+
operator,
|
|
890
|
+
variant === "multiSelect" && Array.isArray(value) ? [...value].sort() : value
|
|
891
|
+
])).sort());
|
|
892
|
+
}
|
|
883
893
|
function useReadableFilters(columns, options = {}) {
|
|
884
|
-
const { history = "replace", scroll = false } = options;
|
|
894
|
+
const { history = "replace", scroll = false, resetPageKey = "page" } = options;
|
|
885
895
|
const columnSnapshot = react.useMemo(() => columns, [columns]);
|
|
886
896
|
const lastWrittenUrlRef = react.useRef(null);
|
|
887
897
|
const filtersRef = react.useRef(null);
|
|
@@ -909,7 +919,10 @@ function useReadableFilters(columns, options = {}) {
|
|
|
909
919
|
}, [columnSnapshot]);
|
|
910
920
|
const writeToUrl = react.useCallback((next) => {
|
|
911
921
|
const params = getUrlParams();
|
|
922
|
+
const previousFilters = parseReadableFilters(params, columnSnapshot);
|
|
912
923
|
applyReadableFilters(params, columnSnapshot, next);
|
|
924
|
+
const nextFilters = parseReadableFilters(params, columnSnapshot);
|
|
925
|
+
if (resetPageKey !== false && resetPageKey.length > 0 && filterSignature(previousFilters) !== filterSignature(nextFilters)) params.delete(resetPageKey);
|
|
913
926
|
lastWrittenUrlRef.current = toSearchString(params);
|
|
914
927
|
setSearchParams(params, {
|
|
915
928
|
history,
|
|
@@ -918,6 +931,7 @@ function useReadableFilters(columns, options = {}) {
|
|
|
918
931
|
}, [
|
|
919
932
|
columnSnapshot,
|
|
920
933
|
history,
|
|
934
|
+
resetPageKey,
|
|
921
935
|
scroll
|
|
922
936
|
]);
|
|
923
937
|
return [filters, react.useCallback((updater) => {
|
|
@@ -1032,6 +1046,71 @@ function useDebouncedCallback(callback, delay) {
|
|
|
1032
1046
|
}, [handleCallback, delay]);
|
|
1033
1047
|
}
|
|
1034
1048
|
|
|
1049
|
+
//#endregion
|
|
1050
|
+
//#region src/lib/calendar-date.ts
|
|
1051
|
+
/** Calendar days are wall dates, never instants in the host's time zone. */
|
|
1052
|
+
function serializeCalendarDate(date) {
|
|
1053
|
+
return `${String(date.getFullYear()).padStart(4, "0")}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
1054
|
+
}
|
|
1055
|
+
function parseCalendarDate(value) {
|
|
1056
|
+
if (value === void 0 || value === "") return void 0;
|
|
1057
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
1058
|
+
const date$1 = /* @__PURE__ */ new Date(`${value}T00:00:00`);
|
|
1059
|
+
return !Number.isNaN(date$1.getTime()) && serializeCalendarDate(date$1) === value ? date$1 : void 0;
|
|
1060
|
+
}
|
|
1061
|
+
const date = new Date(Number(value));
|
|
1062
|
+
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
1063
|
+
}
|
|
1064
|
+
function calendarPresentation() {
|
|
1065
|
+
const localeOptions = getDateLocaleOptions();
|
|
1066
|
+
const locale = localeOptions?.locale ?? "en-US";
|
|
1067
|
+
const chinese = locale.toLowerCase().startsWith("zh");
|
|
1068
|
+
const localeInfo = new Intl.Locale(locale);
|
|
1069
|
+
const firstDay = localeInfo.getWeekInfo?.().firstDay ?? localeInfo.weekInfo?.firstDay ?? (chinese ? 1 : 7);
|
|
1070
|
+
const format = (date, options) => new Intl.DateTimeFormat(locale, {
|
|
1071
|
+
...options,
|
|
1072
|
+
timeZone: "UTC"
|
|
1073
|
+
}).format(/* @__PURE__ */ new Date(`${serializeCalendarDate(date)}T00:00:00Z`));
|
|
1074
|
+
return {
|
|
1075
|
+
locale,
|
|
1076
|
+
weekStartsOn: firstDay % 7,
|
|
1077
|
+
formatDate: (date) => {
|
|
1078
|
+
if (!localeOptions) return formatDate(date);
|
|
1079
|
+
return date ? format(date, {
|
|
1080
|
+
year: "numeric",
|
|
1081
|
+
month: "long",
|
|
1082
|
+
day: "numeric"
|
|
1083
|
+
}) : "";
|
|
1084
|
+
},
|
|
1085
|
+
clearLabel: (title) => chinese ? `清除${title ?? ""}筛选` : `Clear ${title ?? ""} filter`,
|
|
1086
|
+
formatters: {
|
|
1087
|
+
formatCaption: (date) => format(date, {
|
|
1088
|
+
year: "numeric",
|
|
1089
|
+
month: "long"
|
|
1090
|
+
}),
|
|
1091
|
+
formatMonthDropdown: (date) => format(date, { month: "long" }),
|
|
1092
|
+
formatWeekdayName: (date) => format(date, { weekday: "short" })
|
|
1093
|
+
},
|
|
1094
|
+
labels: {
|
|
1095
|
+
labelNext: () => chinese ? "下个月" : "Go to the Next Month",
|
|
1096
|
+
labelPrevious: () => chinese ? "上个月" : "Go to the Previous Month",
|
|
1097
|
+
labelMonthDropdown: () => chinese ? "选择月份" : "Choose the Month",
|
|
1098
|
+
labelYearDropdown: () => chinese ? "选择年份" : "Choose the Year",
|
|
1099
|
+
labelGrid: (date) => format(date, {
|
|
1100
|
+
year: "numeric",
|
|
1101
|
+
month: "long"
|
|
1102
|
+
}),
|
|
1103
|
+
labelWeekday: (date) => format(date, { weekday: "long" }),
|
|
1104
|
+
labelDayButton: (date) => format(date, {
|
|
1105
|
+
year: "numeric",
|
|
1106
|
+
month: "long",
|
|
1107
|
+
day: "numeric",
|
|
1108
|
+
weekday: "long"
|
|
1109
|
+
})
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1035
1114
|
//#endregion
|
|
1036
1115
|
//#region src/components/data-table/data-table-filter-list.tsx
|
|
1037
1116
|
const DEBOUNCE_MS$2 = 300;
|
|
@@ -1053,7 +1132,10 @@ function DataTableFilterList({ table, debounceMs = DEBOUNCE_MS$2, throttleMs = T
|
|
|
1053
1132
|
return true;
|
|
1054
1133
|
});
|
|
1055
1134
|
}, [table, columnDefs]);
|
|
1056
|
-
const [filters, setFilters] = useReadableFilters(columns, {
|
|
1135
|
+
const [filters, setFilters] = useReadableFilters(columns, {
|
|
1136
|
+
debounceMs,
|
|
1137
|
+
resetPageKey: table.options.meta?.queryKeys?.page ?? "page"
|
|
1138
|
+
});
|
|
1057
1139
|
const debouncedSetFilters = useDebouncedCallback(setFilters, debounceMs);
|
|
1058
1140
|
const [joinOperator, setJoinOperator] = useQueryState(table.options.meta?.queryKeys?.joinOperator ?? "", parseAsStringEnum(["and", "or"]).withDefault("and"));
|
|
1059
1141
|
const onFilterAdd = react.useCallback(() => {
|
|
@@ -1200,6 +1282,7 @@ function DataTableFilterList({ table, debounceMs = DEBOUNCE_MS$2, throttleMs = T
|
|
|
1200
1282
|
});
|
|
1201
1283
|
}
|
|
1202
1284
|
function DataTableFilterItem$1({ filter, index: index$1, filterItemId, joinOperator, setJoinOperator, columns, onFilterUpdate, onFilterRemove }) {
|
|
1285
|
+
useDateFormatterVersion();
|
|
1203
1286
|
const [showFieldSelector, setShowFieldSelector] = react.useState(false);
|
|
1204
1287
|
const [showOperatorSelector, setShowOperatorSelector] = react.useState(false);
|
|
1205
1288
|
const [showValueSelector, setShowValueSelector] = react.useState(false);
|
|
@@ -1488,10 +1571,10 @@ function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUp
|
|
|
1488
1571
|
case "dateRange": {
|
|
1489
1572
|
const inputListboxId = `${inputId}-listbox`;
|
|
1490
1573
|
const dateValue = Array.isArray(filter.value) ? filter.value.filter(Boolean) : [filter.value, filter.value].filter(Boolean);
|
|
1491
|
-
const startDate = dateValue[0] ?
|
|
1492
|
-
const endDate = dateValue[1] ?
|
|
1574
|
+
const startDate = dateValue[0] ? parseCalendarDate(dateValue[0]) : void 0;
|
|
1575
|
+
const endDate = dateValue[1] ? parseCalendarDate(dateValue[1]) : void 0;
|
|
1493
1576
|
const isSameDate = startDate && endDate && startDate.toDateString() === endDate.toDateString();
|
|
1494
|
-
const displayValue = filter.operator === "isBetween" && dateValue.length === 2 && !isSameDate ? `${formatDate(startDate
|
|
1577
|
+
const displayValue = filter.operator === "isBetween" && dateValue.length === 2 && !isSameDate ? `${calendarPresentation().formatDate(startDate)} - ${calendarPresentation().formatDate(endDate)}` : startDate ? calendarPresentation().formatDate(startDate) : "Pick a date";
|
|
1495
1578
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Popover, {
|
|
1496
1579
|
open: showValueSelector,
|
|
1497
1580
|
onOpenChange: setShowValueSelector,
|
|
@@ -1514,28 +1597,36 @@ function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUp
|
|
|
1514
1597
|
align: "start",
|
|
1515
1598
|
className: "w-auto p-0",
|
|
1516
1599
|
children: filter.operator === "isBetween" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
1600
|
+
lang: calendarPresentation().locale,
|
|
1601
|
+
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
1602
|
+
formatters: calendarPresentation().formatters,
|
|
1603
|
+
labels: calendarPresentation().labels,
|
|
1517
1604
|
"aria-label": `Select ${columnMeta?.label} date range`,
|
|
1518
1605
|
autoFocus: true,
|
|
1519
1606
|
captionLayout: "dropdown",
|
|
1520
1607
|
mode: "range",
|
|
1521
1608
|
selected: dateValue.length === 2 ? {
|
|
1522
|
-
from:
|
|
1523
|
-
to:
|
|
1609
|
+
from: parseCalendarDate(dateValue[0]),
|
|
1610
|
+
to: parseCalendarDate(dateValue[1])
|
|
1524
1611
|
} : {
|
|
1525
1612
|
from: /* @__PURE__ */ new Date(),
|
|
1526
1613
|
to: /* @__PURE__ */ new Date()
|
|
1527
1614
|
},
|
|
1528
1615
|
onSelect: (date) => {
|
|
1529
|
-
onFilterUpdate(filter.filterId, { value: date ? [(date.from
|
|
1616
|
+
onFilterUpdate(filter.filterId, { value: date ? [date.from ? serializeCalendarDate(date.from) : "", date.to ? serializeCalendarDate(date.to) : ""] : [] });
|
|
1530
1617
|
}
|
|
1531
1618
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
1619
|
+
lang: calendarPresentation().locale,
|
|
1620
|
+
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
1621
|
+
formatters: calendarPresentation().formatters,
|
|
1622
|
+
labels: calendarPresentation().labels,
|
|
1532
1623
|
"aria-label": `Select ${columnMeta?.label} date`,
|
|
1533
1624
|
autoFocus: true,
|
|
1534
1625
|
captionLayout: "dropdown",
|
|
1535
1626
|
mode: "single",
|
|
1536
|
-
selected: dateValue[0] ?
|
|
1627
|
+
selected: dateValue[0] ? parseCalendarDate(dateValue[0]) : void 0,
|
|
1537
1628
|
onSelect: (date) => {
|
|
1538
|
-
onFilterUpdate(filter.filterId, { value: (date
|
|
1629
|
+
onFilterUpdate(filter.filterId, { value: date ? serializeCalendarDate(date) : "" });
|
|
1539
1630
|
setShowValueSelector(false);
|
|
1540
1631
|
}
|
|
1541
1632
|
})
|
|
@@ -1591,7 +1682,10 @@ function DataTableFilterMenu({ table, debounceMs = DEBOUNCE_MS$1, throttleMs = T
|
|
|
1591
1682
|
setSelectedColumn(null);
|
|
1592
1683
|
}
|
|
1593
1684
|
}, [inputValue, selectedColumn]);
|
|
1594
|
-
const [filters, setFilters] = useReadableFilters(columns, {
|
|
1685
|
+
const [filters, setFilters] = useReadableFilters(columns, {
|
|
1686
|
+
debounceMs,
|
|
1687
|
+
resetPageKey: table.options.meta?.queryKeys?.page ?? "page"
|
|
1688
|
+
});
|
|
1595
1689
|
const debouncedSetFilters = useDebouncedCallback(setFilters, debounceMs);
|
|
1596
1690
|
const onFilterAdd = react.useCallback((column, value) => {
|
|
1597
1691
|
if (!value.trim() && column.columnDef.meta?.variant !== "boolean") return;
|
|
@@ -1744,6 +1838,7 @@ function DataTableFilterMenu({ table, debounceMs = DEBOUNCE_MS$1, throttleMs = T
|
|
|
1744
1838
|
}
|
|
1745
1839
|
function DataTableFilterItem({ filter, filterItemId, columns, onFilterUpdate, onFilterRemove }) {
|
|
1746
1840
|
{
|
|
1841
|
+
useDateFormatterVersion();
|
|
1747
1842
|
const [showFieldSelector, setShowFieldSelector] = react.useState(false);
|
|
1748
1843
|
const [showOperatorSelector, setShowOperatorSelector] = react.useState(false);
|
|
1749
1844
|
const [showValueSelector, setShowValueSelector] = react.useState(false);
|
|
@@ -1854,6 +1949,7 @@ function DataTableFilterItem({ filter, filterItemId, columns, onFilterUpdate, on
|
|
|
1854
1949
|
}
|
|
1855
1950
|
}
|
|
1856
1951
|
function FilterValueSelector({ column, value, onSelect }) {
|
|
1952
|
+
useDateFormatterVersion();
|
|
1857
1953
|
switch (column.columnDef.meta?.variant ?? "text") {
|
|
1858
1954
|
case "boolean": return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.CommandGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.CommandItem, {
|
|
1859
1955
|
value: "true",
|
|
@@ -1882,11 +1978,15 @@ function FilterValueSelector({ column, value, onSelect }) {
|
|
|
1882
1978
|
}, option.value)) });
|
|
1883
1979
|
case "date":
|
|
1884
1980
|
case "dateRange": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
1981
|
+
lang: calendarPresentation().locale,
|
|
1982
|
+
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
1983
|
+
formatters: calendarPresentation().formatters,
|
|
1984
|
+
labels: calendarPresentation().labels,
|
|
1885
1985
|
autoFocus: true,
|
|
1886
1986
|
captionLayout: "dropdown",
|
|
1887
1987
|
mode: "single",
|
|
1888
|
-
selected:
|
|
1889
|
-
onSelect: (date) => onSelect(date
|
|
1988
|
+
selected: parseCalendarDate(value),
|
|
1989
|
+
onSelect: (date) => onSelect(date ? serializeCalendarDate(date) : "")
|
|
1890
1990
|
});
|
|
1891
1991
|
default: {
|
|
1892
1992
|
const isEmpty = !value.trim();
|
|
@@ -2040,10 +2140,10 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2040
2140
|
case "dateRange": {
|
|
2041
2141
|
const inputListboxId = `${inputId}-listbox`;
|
|
2042
2142
|
const dateValue = Array.isArray(filter.value) ? filter.value.filter(Boolean) : [filter.value, filter.value].filter(Boolean);
|
|
2043
|
-
const startDate = dateValue[0] ?
|
|
2044
|
-
const endDate = dateValue[1] ?
|
|
2143
|
+
const startDate = dateValue[0] ? parseCalendarDate(dateValue[0]) : void 0;
|
|
2144
|
+
const endDate = dateValue[1] ? parseCalendarDate(dateValue[1]) : void 0;
|
|
2045
2145
|
const isSameDate = startDate && endDate && startDate.toDateString() === endDate.toDateString();
|
|
2046
|
-
const displayValue = filter.operator === "isBetween" && dateValue.length === 2 && !isSameDate ? `${formatDate(startDate
|
|
2146
|
+
const displayValue = filter.operator === "isBetween" && dateValue.length === 2 && !isSameDate ? `${calendarPresentation().formatDate(startDate)} - ${calendarPresentation().formatDate(endDate)}` : startDate ? calendarPresentation().formatDate(startDate) : "Pick date...";
|
|
2047
2147
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Popover, {
|
|
2048
2148
|
open: showValueSelector,
|
|
2049
2149
|
onOpenChange: setShowValueSelector,
|
|
@@ -2065,26 +2165,34 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2065
2165
|
align: "start",
|
|
2066
2166
|
className: "w-auto p-0",
|
|
2067
2167
|
children: filter.operator === "isBetween" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2168
|
+
lang: calendarPresentation().locale,
|
|
2169
|
+
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
2170
|
+
formatters: calendarPresentation().formatters,
|
|
2171
|
+
labels: calendarPresentation().labels,
|
|
2068
2172
|
autoFocus: true,
|
|
2069
2173
|
captionLayout: "dropdown",
|
|
2070
2174
|
mode: "range",
|
|
2071
2175
|
selected: dateValue.length === 2 ? {
|
|
2072
|
-
from:
|
|
2073
|
-
to:
|
|
2176
|
+
from: parseCalendarDate(dateValue[0]),
|
|
2177
|
+
to: parseCalendarDate(dateValue[1])
|
|
2074
2178
|
} : {
|
|
2075
2179
|
from: /* @__PURE__ */ new Date(),
|
|
2076
2180
|
to: /* @__PURE__ */ new Date()
|
|
2077
2181
|
},
|
|
2078
2182
|
onSelect: (date) => {
|
|
2079
|
-
onFilterUpdate(filter.filterId, { value: date ? [(date.from
|
|
2183
|
+
onFilterUpdate(filter.filterId, { value: date ? [date.from ? serializeCalendarDate(date.from) : "", date.to ? serializeCalendarDate(date.to) : ""] : [] });
|
|
2080
2184
|
}
|
|
2081
2185
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2186
|
+
lang: calendarPresentation().locale,
|
|
2187
|
+
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
2188
|
+
formatters: calendarPresentation().formatters,
|
|
2189
|
+
labels: calendarPresentation().labels,
|
|
2082
2190
|
autoFocus: true,
|
|
2083
2191
|
captionLayout: "dropdown",
|
|
2084
2192
|
mode: "single",
|
|
2085
|
-
selected: dateValue[0] ?
|
|
2193
|
+
selected: dateValue[0] ? parseCalendarDate(dateValue[0]) : void 0,
|
|
2086
2194
|
onSelect: (date) => {
|
|
2087
|
-
onFilterUpdate(filter.filterId, { value: (date
|
|
2195
|
+
onFilterUpdate(filter.filterId, { value: date ? serializeCalendarDate(date) : "" });
|
|
2088
2196
|
}
|
|
2089
2197
|
})
|
|
2090
2198
|
})]
|
|
@@ -2397,6 +2505,7 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
|
|
|
2397
2505
|
const queryStateOptions = table.options.meta?.queryStateOptions;
|
|
2398
2506
|
const [queryFilters, setQueryFilters] = useReadableFilters(columns, {
|
|
2399
2507
|
...queryStateOptions,
|
|
2508
|
+
resetPageKey: table.options.meta?.queryKeys?.page ?? "page",
|
|
2400
2509
|
shallow
|
|
2401
2510
|
});
|
|
2402
2511
|
const filters = externalFilters ?? queryFilters;
|
|
@@ -2832,11 +2941,17 @@ function SimpleSliderFilter({ title, range, unit, value, onChange }) {
|
|
|
2832
2941
|
})] });
|
|
2833
2942
|
}
|
|
2834
2943
|
function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
2944
|
+
const [open, setOpen] = react.useState(false);
|
|
2945
|
+
const commit = (next) => {
|
|
2946
|
+
setOpen(false);
|
|
2947
|
+
onChange(next);
|
|
2948
|
+
};
|
|
2949
|
+
const formatterVersion = useDateFormatterVersion();
|
|
2950
|
+
const presentation = react.useMemo(() => calendarPresentation(), [formatterVersion]);
|
|
2951
|
+
const { formatDate: formatDate$1 } = presentation;
|
|
2835
2952
|
const timestamps = Array.isArray(value) ? value : value ? [value] : [];
|
|
2836
|
-
const
|
|
2837
|
-
const
|
|
2838
|
-
const fromDate = fromTimestamp ? new Date(fromTimestamp) : void 0;
|
|
2839
|
-
const toDate = toTimestamp ? new Date(toTimestamp) : void 0;
|
|
2953
|
+
const fromDate = parseCalendarDate(timestamps[0]);
|
|
2954
|
+
const toDate = parseCalendarDate(timestamps[1]);
|
|
2840
2955
|
const [localRange, setLocalRange] = react.useState({
|
|
2841
2956
|
from: void 0,
|
|
2842
2957
|
to: void 0
|
|
@@ -2855,100 +2970,114 @@ function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
|
2855
2970
|
const hasValue = multiple ? fromDate || toDate : fromDate;
|
|
2856
2971
|
const onReset = (e) => {
|
|
2857
2972
|
e.stopPropagation();
|
|
2858
|
-
|
|
2973
|
+
commit(void 0);
|
|
2859
2974
|
};
|
|
2860
|
-
const label = multiple ? fromDate && toDate ? `${formatDate(fromDate)} - ${formatDate(toDate)}` : fromDate ? formatDate(fromDate) : void 0 : fromDate ? formatDate(fromDate) : void 0;
|
|
2861
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Popover, {
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2975
|
+
const label = multiple ? fromDate && toDate ? `${formatDate$1(fromDate)} - ${formatDate$1(toDate)}` : fromDate ? formatDate$1(fromDate) : void 0 : fromDate ? formatDate$1(fromDate) : void 0;
|
|
2976
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Popover, {
|
|
2977
|
+
open,
|
|
2978
|
+
onOpenChange: setOpen,
|
|
2979
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.PopoverTrigger, {
|
|
2980
|
+
asChild: true,
|
|
2981
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Button, {
|
|
2982
|
+
variant: "outline",
|
|
2983
|
+
size: "sm",
|
|
2984
|
+
className: "border-dashed font-normal",
|
|
2985
|
+
children: [
|
|
2986
|
+
hasValue ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2987
|
+
role: "button",
|
|
2988
|
+
tabIndex: 0,
|
|
2989
|
+
className: "rounded-sm opacity-70 hover:opacity-100",
|
|
2990
|
+
onClick: onReset,
|
|
2991
|
+
onKeyDown: (e) => {
|
|
2992
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2993
|
+
e.preventDefault();
|
|
2994
|
+
onReset(e);
|
|
2995
|
+
}
|
|
2996
|
+
},
|
|
2997
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.XCircle, {})
|
|
2998
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.CalendarIcon, {}),
|
|
2999
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: title }),
|
|
3000
|
+
label && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Separator, {
|
|
3001
|
+
orientation: "vertical",
|
|
3002
|
+
className: "mx-0.5 h-4"
|
|
3003
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })] })
|
|
3004
|
+
]
|
|
3005
|
+
})
|
|
3006
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.PopoverContent, {
|
|
3007
|
+
className: "w-auto p-0",
|
|
3008
|
+
align: "start",
|
|
3009
|
+
children: multiple ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
3010
|
+
lang: presentation.locale,
|
|
3011
|
+
weekStartsOn: presentation.weekStartsOn,
|
|
3012
|
+
formatters: presentation.formatters,
|
|
3013
|
+
labels: presentation.labels,
|
|
3014
|
+
defaultMonth: fromDate,
|
|
3015
|
+
autoFocus: true,
|
|
3016
|
+
captionLayout: "dropdown",
|
|
3017
|
+
mode: "range",
|
|
3018
|
+
selected: localRange,
|
|
3019
|
+
onSelect: (range) => {
|
|
3020
|
+
if (!range?.from && !range?.to) {
|
|
3021
|
+
commit(void 0);
|
|
3022
|
+
setLocalRange({
|
|
3023
|
+
from: void 0,
|
|
3024
|
+
to: void 0
|
|
3025
|
+
});
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3028
|
+
const hadFrom = Boolean(localRange.from);
|
|
3029
|
+
const hadTo = Boolean(localRange.to);
|
|
3030
|
+
const from = range.from?.getTime();
|
|
3031
|
+
const to = range.to?.getTime();
|
|
3032
|
+
if (from != null && to != null && from === to) {
|
|
3033
|
+
if (!hadFrom || hadTo) {
|
|
3034
|
+
setLocalRange({
|
|
3035
|
+
from: range.from,
|
|
3036
|
+
to: void 0
|
|
3037
|
+
});
|
|
3038
|
+
return;
|
|
2877
3039
|
}
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
children: multiple ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2892
|
-
autoFocus: true,
|
|
2893
|
-
captionLayout: "dropdown",
|
|
2894
|
-
mode: "range",
|
|
2895
|
-
selected: localRange,
|
|
2896
|
-
onSelect: (range) => {
|
|
2897
|
-
if (!range?.from && !range?.to) {
|
|
2898
|
-
onChange(void 0);
|
|
2899
|
-
setLocalRange({
|
|
2900
|
-
from: void 0,
|
|
2901
|
-
to: void 0
|
|
2902
|
-
});
|
|
2903
|
-
return;
|
|
2904
|
-
}
|
|
2905
|
-
const hadFrom = Boolean(localRange.from);
|
|
2906
|
-
const hadTo = Boolean(localRange.to);
|
|
2907
|
-
const from = range.from?.getTime();
|
|
2908
|
-
const to = range.to?.getTime();
|
|
2909
|
-
if (from != null && to != null && from === to) {
|
|
2910
|
-
if (!hadFrom || hadTo) {
|
|
3040
|
+
if (hadFrom && !hadTo && localRange.from) {
|
|
3041
|
+
const prevFrom = localRange.from;
|
|
3042
|
+
const newDate = range.from;
|
|
3043
|
+
const [finalFrom, finalTo] = prevFrom <= newDate ? [prevFrom, newDate] : [newDate, prevFrom];
|
|
3044
|
+
setLocalRange({
|
|
3045
|
+
from: finalFrom,
|
|
3046
|
+
to: finalTo
|
|
3047
|
+
});
|
|
3048
|
+
commit([serializeCalendarDate(finalFrom), serializeCalendarDate(finalTo)]);
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
if (from != null && to != null && from !== to) {
|
|
2911
3053
|
setLocalRange({
|
|
2912
3054
|
from: range.from,
|
|
2913
|
-
to:
|
|
3055
|
+
to: range.to
|
|
2914
3056
|
});
|
|
3057
|
+
commit([serializeCalendarDate(range.from), serializeCalendarDate(range.to)]);
|
|
2915
3058
|
return;
|
|
2916
3059
|
}
|
|
2917
|
-
if (
|
|
2918
|
-
const prevFrom = localRange.from;
|
|
2919
|
-
const newDate = range.from;
|
|
2920
|
-
const [finalFrom, finalTo] = prevFrom <= newDate ? [prevFrom, newDate] : [newDate, prevFrom];
|
|
3060
|
+
if (range.from && !range.to) {
|
|
2921
3061
|
setLocalRange({
|
|
2922
|
-
from:
|
|
2923
|
-
to:
|
|
3062
|
+
from: range.from,
|
|
3063
|
+
to: void 0
|
|
2924
3064
|
});
|
|
2925
|
-
onChange([finalFrom.getTime().toString(), finalTo.getTime().toString()]);
|
|
2926
3065
|
return;
|
|
2927
3066
|
}
|
|
2928
3067
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
return;
|
|
2943
|
-
}
|
|
2944
|
-
}
|
|
2945
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2946
|
-
captionLayout: "dropdown",
|
|
2947
|
-
mode: "single",
|
|
2948
|
-
selected: fromDate,
|
|
2949
|
-
onSelect: (date) => onChange(date ? date.getTime().toString() : void 0)
|
|
2950
|
-
})
|
|
2951
|
-
})] });
|
|
3068
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
3069
|
+
lang: presentation.locale,
|
|
3070
|
+
weekStartsOn: presentation.weekStartsOn,
|
|
3071
|
+
formatters: presentation.formatters,
|
|
3072
|
+
labels: presentation.labels,
|
|
3073
|
+
defaultMonth: fromDate,
|
|
3074
|
+
captionLayout: "dropdown",
|
|
3075
|
+
mode: "single",
|
|
3076
|
+
selected: fromDate,
|
|
3077
|
+
onSelect: (date) => commit(date ? serializeCalendarDate(date) : void 0)
|
|
3078
|
+
})
|
|
3079
|
+
})]
|
|
3080
|
+
});
|
|
2952
3081
|
}
|
|
2953
3082
|
|
|
2954
3083
|
//#endregion
|
|
@@ -3956,7 +4085,8 @@ function useDataTable(props) {
|
|
|
3956
4085
|
if (enableAdvancedFilter) return [];
|
|
3957
4086
|
return Object.entries(filterValues).reduce((filters, [key, value]) => {
|
|
3958
4087
|
if (value !== null) {
|
|
3959
|
-
const
|
|
4088
|
+
const variant = filterableColumns.find((column) => column.id === key)?.meta?.variant;
|
|
4089
|
+
const processedValue = Array.isArray(value) ? value : typeof value === "string" && (variant === "date" || variant === "dateRange") ? value.split(",").filter(Boolean) : typeof value === "string" && /[^a-zA-Z0-9]/.test(value) ? value.split(/[^a-zA-Z0-9]+/).filter(Boolean) : [value];
|
|
3960
4090
|
filters.push({
|
|
3961
4091
|
id: key,
|
|
3962
4092
|
value: processedValue
|
|
@@ -3964,7 +4094,11 @@ function useDataTable(props) {
|
|
|
3964
4094
|
}
|
|
3965
4095
|
return filters;
|
|
3966
4096
|
}, []);
|
|
3967
|
-
}, [
|
|
4097
|
+
}, [
|
|
4098
|
+
filterValues,
|
|
4099
|
+
enableAdvancedFilter,
|
|
4100
|
+
filterableColumns
|
|
4101
|
+
]);
|
|
3968
4102
|
const [columnFilters, setColumnFilters] = react.useState(initialColumnFilters);
|
|
3969
4103
|
const onColumnFiltersChange = react.useCallback((updaterOrValue) => {
|
|
3970
4104
|
if (enableAdvancedFilter) return;
|
|
@@ -6118,13 +6252,6 @@ function mergeFieldOptions(current, incoming) {
|
|
|
6118
6252
|
if ((!current || current.length === 0) && (!incoming || incoming.length === 0)) return;
|
|
6119
6253
|
return mergeFilterOptions(current, incoming ?? []);
|
|
6120
6254
|
}
|
|
6121
|
-
function mergeOptionsByField(left, right) {
|
|
6122
|
-
const keys = new Set([...Object.keys(left ?? {}), ...Object.keys(right ?? {})]);
|
|
6123
|
-
return Object.fromEntries(Array.from(keys).flatMap((key) => {
|
|
6124
|
-
const options = mergeFieldOptions(left?.[key], right?.[key]);
|
|
6125
|
-
return options ? [[key, options]] : [];
|
|
6126
|
-
}));
|
|
6127
|
-
}
|
|
6128
6255
|
function shouldResolveOptions(field, config, hiddenColumns) {
|
|
6129
6256
|
if (!config) return false;
|
|
6130
6257
|
if (hiddenColumns.has(field)) return false;
|
|
@@ -6661,7 +6788,7 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
|
|
|
6661
6788
|
/**
|
|
6662
6789
|
* 渲染字段值
|
|
6663
6790
|
*/
|
|
6664
|
-
function renderFieldValue(value, type, booleanLocale, options, display = "auto") {
|
|
6791
|
+
function renderFieldValue(value, type, booleanLocale, options, display = "auto", maxItems = 5) {
|
|
6665
6792
|
if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6666
6793
|
className: "text-muted-foreground",
|
|
6667
6794
|
children: "-"
|
|
@@ -6676,12 +6803,12 @@ function renderFieldValue(value, type, booleanLocale, options, display = "auto")
|
|
|
6676
6803
|
if (display === "badge" && (!options || options.length === 0)) {
|
|
6677
6804
|
if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6678
6805
|
className: "flex gap-1 flex-wrap",
|
|
6679
|
-
children: [value.slice(0,
|
|
6806
|
+
children: [value.slice(0, maxItems).map((item, index$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
6680
6807
|
variant: "secondary",
|
|
6681
6808
|
children: String(item)
|
|
6682
|
-
}, index$1)), value.length >
|
|
6809
|
+
}, index$1)), value.length > maxItems && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Badge, {
|
|
6683
6810
|
variant: "outline",
|
|
6684
|
-
children: ["+", value.length -
|
|
6811
|
+
children: ["+", value.length - maxItems]
|
|
6685
6812
|
})]
|
|
6686
6813
|
});
|
|
6687
6814
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
@@ -6693,12 +6820,12 @@ function renderFieldValue(value, type, booleanLocale, options, display = "auto")
|
|
|
6693
6820
|
if ((display === "badge" || display === "auto") && options && options.length > 0) {
|
|
6694
6821
|
if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6695
6822
|
className: "flex gap-1 flex-wrap",
|
|
6696
|
-
children: [value.slice(0,
|
|
6823
|
+
children: [value.slice(0, maxItems).map((v, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
6697
6824
|
variant: "secondary",
|
|
6698
6825
|
children: getOptionLabel(v, options)
|
|
6699
|
-
}, i)), value.length >
|
|
6826
|
+
}, i)), value.length > maxItems && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Badge, {
|
|
6700
6827
|
variant: "outline",
|
|
6701
|
-
children: ["+", value.length -
|
|
6828
|
+
children: ["+", value.length - maxItems]
|
|
6702
6829
|
})]
|
|
6703
6830
|
});
|
|
6704
6831
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
@@ -6717,48 +6844,81 @@ function renderFieldValue(value, type, booleanLocale, options, display = "auto")
|
|
|
6717
6844
|
});
|
|
6718
6845
|
case "array": return Array.isArray(value) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6719
6846
|
className: "flex gap-1 flex-wrap",
|
|
6720
|
-
children: [value.slice(0,
|
|
6847
|
+
children: [value.slice(0, maxItems).map((v, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
6721
6848
|
variant: "secondary",
|
|
6722
6849
|
children: String(v)
|
|
6723
|
-
}, i)), value.length >
|
|
6850
|
+
}, i)), value.length > maxItems && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Badge, {
|
|
6724
6851
|
variant: "outline",
|
|
6725
|
-
children: ["+", value.length -
|
|
6852
|
+
children: ["+", value.length - maxItems]
|
|
6726
6853
|
})]
|
|
6727
6854
|
}) : null;
|
|
6728
6855
|
default: return String(value);
|
|
6729
6856
|
}
|
|
6730
6857
|
}
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
*/
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
const
|
|
6737
|
-
|
|
6858
|
+
function ViewModal(props) {
|
|
6859
|
+
if (!props.open || !props.data) return null;
|
|
6860
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModalContent, { ...props });
|
|
6861
|
+
}
|
|
6862
|
+
function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: fieldConfig, dynamicOptions, denyFields, locale, tableOverrides, view }) {
|
|
6863
|
+
const excluded = react.useMemo(() => {
|
|
6864
|
+
const denied = new Set(denyFields ?? []);
|
|
6865
|
+
return Object.keys(schema.shape).filter((key) => {
|
|
6866
|
+
const config = fieldConfig?.[key];
|
|
6867
|
+
return denied.has(key) || config?.hidden || view?.overrides?.[key]?.hidden || isDefaultHiddenAuditField(key) && !isFieldTableExplicitlyVisible(config) && view?.overrides?.[key]?.hidden !== false;
|
|
6868
|
+
});
|
|
6869
|
+
}, [
|
|
6870
|
+
schema,
|
|
6871
|
+
fieldConfig,
|
|
6872
|
+
denyFields,
|
|
6873
|
+
view?.overrides
|
|
6874
|
+
]);
|
|
6875
|
+
const rows = react.useMemo(() => data ? [data] : [], [data]);
|
|
6876
|
+
const resolvedOptions = useDynamicResolveOptions(fieldConfig, rows, excluded);
|
|
6738
6877
|
const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", {
|
|
6739
6878
|
className: "grid gap-4 py-4",
|
|
6740
|
-
children:
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6879
|
+
children: (0, __tanstack_react_table.useReactTable)({
|
|
6880
|
+
data: rows,
|
|
6881
|
+
columns: react.useMemo(() => {
|
|
6882
|
+
const overrides = {};
|
|
6883
|
+
for (const [key, fieldSchema] of Object.entries(schema.shape).filter(([fieldKey]) => !excluded.includes(fieldKey))) {
|
|
6884
|
+
const config = fieldConfig?.[key] ?? {};
|
|
6885
|
+
const tableConfig = getTableConfig(config);
|
|
6886
|
+
const listOverride = tableOverrides?.[key];
|
|
6887
|
+
const options = getTableOptions(config) ?? resolvedOptions.optionsByField[key] ?? (tableConfig?.dataSource !== void 0 ? void 0 : dynamicOptions?.[key]);
|
|
6888
|
+
overrides[key] = {
|
|
6889
|
+
label: tableConfig?.label ?? config.label ?? listOverride?.label ?? humanize(key),
|
|
6890
|
+
index: tableConfig?.index ?? listOverride?.index,
|
|
6891
|
+
cell: ({ getValue }) => renderFieldValue(getValue(), parseZodField(fieldSchema).type, locale.boolean, options, tableConfig?.display ?? "auto", Infinity),
|
|
6892
|
+
...view?.presentation === "table" ? listOverride : void 0,
|
|
6893
|
+
hidden: false,
|
|
6894
|
+
...view?.overrides?.[key]
|
|
6895
|
+
};
|
|
6896
|
+
}
|
|
6897
|
+
return createTableSchema(schema, {
|
|
6898
|
+
overrides,
|
|
6899
|
+
exclude: excluded
|
|
6900
|
+
});
|
|
6901
|
+
}, [
|
|
6902
|
+
schema,
|
|
6903
|
+
excluded,
|
|
6904
|
+
fieldConfig,
|
|
6905
|
+
tableOverrides,
|
|
6906
|
+
view,
|
|
6907
|
+
resolvedOptions.optionsByField,
|
|
6908
|
+
dynamicOptions,
|
|
6909
|
+
locale.boolean
|
|
6910
|
+
]),
|
|
6911
|
+
getCoreRowModel: (0, __tanstack_react_table.getCoreRowModel)()
|
|
6912
|
+
}).getRowModel().rows[0]?.getAllCells().map((cell) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6913
|
+
className: "grid grid-cols-3 items-start gap-4",
|
|
6914
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
|
|
6915
|
+
className: "text-sm font-medium text-muted-foreground",
|
|
6916
|
+
children: cell.column.columnDef.meta?.label ?? humanize(cell.column.id)
|
|
6917
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
6918
|
+
className: "col-span-2 min-w-0 whitespace-pre-wrap break-words text-sm",
|
|
6919
|
+
children: (0, __tanstack_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext())
|
|
6920
|
+
})]
|
|
6921
|
+
}, cell.id))
|
|
6762
6922
|
});
|
|
6763
6923
|
if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Sheet, {
|
|
6764
6924
|
open,
|
|
@@ -6879,7 +7039,7 @@ function resolveActions(actionsOrFn, defaults, rowActionsLocale, context) {
|
|
|
6879
7039
|
*
|
|
6880
7040
|
* 高级 CRUD 表格组件,封装了完整的增删改查流程
|
|
6881
7041
|
*/
|
|
6882
|
-
function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate }) {
|
|
7042
|
+
function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, view: viewConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate }) {
|
|
6883
7043
|
const locale = resolveLocale(localeProp);
|
|
6884
7044
|
const resolvedSchema = resource.schema ?? schema;
|
|
6885
7045
|
const resolvedFields = react.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
|
|
@@ -6905,18 +7065,6 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
6905
7065
|
tableConfig?.overrides
|
|
6906
7066
|
]);
|
|
6907
7067
|
const dynamicResolveOptions = useDynamicResolveOptions(resolvedFields, resource.tableData.data, hiddenColumns);
|
|
6908
|
-
const sharedResolveOptions = useDynamicResolveOptions(react.useMemo(() => Object.fromEntries(Object.entries(resolvedFields).flatMap(([field, config]) => {
|
|
6909
|
-
const table = getTableConfig(config);
|
|
6910
|
-
if (table?.options === void 0 && table?.dataSource === void 0) return [];
|
|
6911
|
-
const { table: _table,...sharedConfig } = config;
|
|
6912
|
-
return [[field, sharedConfig]];
|
|
6913
|
-
})), [resolvedFields]), resource.tableData.data, hiddenColumns);
|
|
6914
|
-
const viewDynamicOptionsByField = react.useMemo(() => mergeOptionsByField(mergeOptionsByField(dynamicFilterOptions.labelOptionsByField, sharedResolveOptions.optionsByField), Object.fromEntries(Object.entries(dynamicResolveOptions.optionsByField).filter(([field]) => !getTableConfig(resolvedFields[field] ?? {})?.dataSource))), [
|
|
6915
|
-
dynamicFilterOptions.labelOptionsByField,
|
|
6916
|
-
dynamicResolveOptions.optionsByField,
|
|
6917
|
-
sharedResolveOptions.optionsByField,
|
|
6918
|
-
resolvedFields
|
|
6919
|
-
]);
|
|
6920
7068
|
const resourceIdKey = resource.idKey ?? "id";
|
|
6921
7069
|
const actionRegistryVersion = useCrudActionsVersion();
|
|
6922
7070
|
const unifiedActions = react.useMemo(() => {
|
|
@@ -7248,9 +7396,11 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7248
7396
|
data: resource.modal.selected,
|
|
7249
7397
|
schema: resolvedSchema,
|
|
7250
7398
|
fields: resolvedFields,
|
|
7251
|
-
dynamicOptions:
|
|
7399
|
+
dynamicOptions: dynamicFilterOptions.labelOptionsByField,
|
|
7252
7400
|
denyFields,
|
|
7253
|
-
locale
|
|
7401
|
+
locale,
|
|
7402
|
+
tableOverrides,
|
|
7403
|
+
view: viewConfig
|
|
7254
7404
|
}),
|
|
7255
7405
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.AlertDialog, {
|
|
7256
7406
|
open: resource.modal.deleteOpen,
|
|
@@ -7447,10 +7597,7 @@ function getIsDateRange(value) {
|
|
|
7447
7597
|
return value && typeof value === "object" && !Array.isArray(value);
|
|
7448
7598
|
}
|
|
7449
7599
|
function parseAsDate(timestamp) {
|
|
7450
|
-
|
|
7451
|
-
const numericTimestamp = typeof timestamp === "string" ? Number(timestamp) : timestamp;
|
|
7452
|
-
const date = new Date(numericTimestamp);
|
|
7453
|
-
return !Number.isNaN(date.getTime()) ? date : void 0;
|
|
7600
|
+
return parseCalendarDate(timestamp);
|
|
7454
7601
|
}
|
|
7455
7602
|
function parseColumnFilterValue(value) {
|
|
7456
7603
|
if (value === null || value === void 0) return [];
|
|
@@ -7461,6 +7608,9 @@ function parseColumnFilterValue(value) {
|
|
|
7461
7608
|
return [];
|
|
7462
7609
|
}
|
|
7463
7610
|
function DataTableDateFilter({ column, title, multiple }) {
|
|
7611
|
+
const formatterVersion = useDateFormatterVersion();
|
|
7612
|
+
const presentation = react.useMemo(() => calendarPresentation(), [formatterVersion]);
|
|
7613
|
+
const { formatDate: formatDate$1 } = presentation;
|
|
7464
7614
|
const columnFilterValue = column.getFilterValue();
|
|
7465
7615
|
const selectedDates = react.useMemo(() => {
|
|
7466
7616
|
if (!columnFilterValue) return multiple ? {
|
|
@@ -7534,12 +7684,12 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7534
7684
|
from: nextFrom,
|
|
7535
7685
|
to: nextTo
|
|
7536
7686
|
});
|
|
7537
|
-
if (nextTo) column.setFilterValue([nextFrom
|
|
7687
|
+
if (nextTo) column.setFilterValue([serializeCalendarDate(nextFrom), serializeCalendarDate(nextTo)]);
|
|
7538
7688
|
return;
|
|
7539
7689
|
}
|
|
7540
7690
|
setLocalRange(date);
|
|
7541
|
-
if (from && to) column.setFilterValue([from, to]);
|
|
7542
|
-
} else if (!multiple && "getTime" in date) column.setFilterValue(date
|
|
7691
|
+
if (from && to) column.setFilterValue([serializeCalendarDate(new Date(from)), serializeCalendarDate(new Date(to))]);
|
|
7692
|
+
} else if (!multiple && "getTime" in date) column.setFilterValue(serializeCalendarDate(date));
|
|
7543
7693
|
}, [
|
|
7544
7694
|
column,
|
|
7545
7695
|
multiple,
|
|
@@ -7559,9 +7709,9 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7559
7709
|
}, [multiple, selectedDates]);
|
|
7560
7710
|
const formatDateRange = react.useCallback((range) => {
|
|
7561
7711
|
if (!range.from && !range.to) return "";
|
|
7562
|
-
if (range.from && range.to) return `${formatDate(range.from)} - ${formatDate(range.to)}`;
|
|
7563
|
-
return formatDate(range.from ?? range.to);
|
|
7564
|
-
}, []);
|
|
7712
|
+
if (range.from && range.to) return `${formatDate$1(range.from)} - ${formatDate$1(range.to)}`;
|
|
7713
|
+
return formatDate$1(range.from ?? range.to);
|
|
7714
|
+
}, [formatDate$1]);
|
|
7565
7715
|
const label = react.useMemo(() => {
|
|
7566
7716
|
if (multiple) {
|
|
7567
7717
|
if (!getIsDateRange(selectedDates)) return null;
|
|
@@ -7577,7 +7727,7 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7577
7727
|
}
|
|
7578
7728
|
if (getIsDateRange(selectedDates)) return null;
|
|
7579
7729
|
const hasSelectedDate = selectedDates.length > 0;
|
|
7580
|
-
const dateText = hasSelectedDate ? formatDate(selectedDates[0]) : "Select date";
|
|
7730
|
+
const dateText = hasSelectedDate ? formatDate$1(selectedDates[0]) : "Select date";
|
|
7581
7731
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7582
7732
|
className: "flex items-center gap-2",
|
|
7583
7733
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: title }), hasSelectedDate && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Separator, {
|
|
@@ -7589,7 +7739,8 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7589
7739
|
selectedDates,
|
|
7590
7740
|
multiple,
|
|
7591
7741
|
formatDateRange,
|
|
7592
|
-
title
|
|
7742
|
+
title,
|
|
7743
|
+
formatDate$1
|
|
7593
7744
|
]);
|
|
7594
7745
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Popover, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.PopoverTrigger, {
|
|
7595
7746
|
asChild: true,
|
|
@@ -7599,7 +7750,7 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7599
7750
|
className: "border-dashed font-normal",
|
|
7600
7751
|
children: [hasValue ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7601
7752
|
role: "button",
|
|
7602
|
-
"aria-label":
|
|
7753
|
+
"aria-label": presentation.clearLabel(title),
|
|
7603
7754
|
tabIndex: 0,
|
|
7604
7755
|
onClick: onReset,
|
|
7605
7756
|
className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
@@ -7610,14 +7761,24 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7610
7761
|
className: "w-auto p-0",
|
|
7611
7762
|
align: "start",
|
|
7612
7763
|
children: multiple ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
7764
|
+
lang: presentation.locale,
|
|
7765
|
+
weekStartsOn: presentation.weekStartsOn,
|
|
7766
|
+
formatters: presentation.formatters,
|
|
7767
|
+
labels: presentation.labels,
|
|
7613
7768
|
autoFocus: true,
|
|
7614
7769
|
captionLayout: "dropdown",
|
|
7615
7770
|
mode: "range",
|
|
7771
|
+
defaultMonth: localRange.from,
|
|
7616
7772
|
selected: localRange,
|
|
7617
7773
|
onSelect
|
|
7618
7774
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
7775
|
+
lang: presentation.locale,
|
|
7776
|
+
weekStartsOn: presentation.weekStartsOn,
|
|
7777
|
+
formatters: presentation.formatters,
|
|
7778
|
+
labels: presentation.labels,
|
|
7619
7779
|
captionLayout: "dropdown",
|
|
7620
7780
|
mode: "single",
|
|
7781
|
+
defaultMonth: !getIsDateRange(selectedDates) ? selectedDates[0] : void 0,
|
|
7621
7782
|
selected: !getIsDateRange(selectedDates) ? selectedDates[0] : void 0,
|
|
7622
7783
|
onSelect
|
|
7623
7784
|
})
|