@wordrhyme/auto-crud 1.7.0 → 1.8.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 +58 -0
- package/dist/index.cjs +397 -47
- package/dist/index.d.cts +453 -414
- package/dist/index.d.ts +426 -387
- package/dist/index.js +400 -51
- package/dist/styles.css +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -43,12 +43,12 @@ let __wordrhyme_ui = require("@wordrhyme/ui");
|
|
|
43
43
|
__wordrhyme_ui = __toESM(__wordrhyme_ui);
|
|
44
44
|
let zod = require("zod");
|
|
45
45
|
zod = __toESM(zod);
|
|
46
|
+
let __wordrhyme_formily_shadcn = require("@wordrhyme/formily-shadcn");
|
|
47
|
+
__wordrhyme_formily_shadcn = __toESM(__wordrhyme_formily_shadcn);
|
|
46
48
|
let __formily_core = require("@formily/core");
|
|
47
49
|
__formily_core = __toESM(__formily_core);
|
|
48
50
|
let __formily_reactive = require("@formily/reactive");
|
|
49
51
|
__formily_reactive = __toESM(__formily_reactive);
|
|
50
|
-
let __wordrhyme_formily_shadcn = require("@wordrhyme/formily-shadcn");
|
|
51
|
-
__wordrhyme_formily_shadcn = __toESM(__wordrhyme_formily_shadcn);
|
|
52
52
|
let sonner = require("sonner");
|
|
53
53
|
sonner = __toESM(sonner);
|
|
54
54
|
let __tanstack_react_query = require("@tanstack/react-query");
|
|
@@ -67,12 +67,66 @@ function DataTablePagination({ table, pageSizeOptions = [
|
|
|
67
67
|
30,
|
|
68
68
|
40,
|
|
69
69
|
50
|
|
70
|
-
], className,...props }) {
|
|
70
|
+
], alwaysShowFirstLast = false, responsive = false, showPageJump = false, pageJumpLabel = "Go to page", className,...props }) {
|
|
71
|
+
const pageJump = (0, react.useRef)(null);
|
|
72
|
+
const container = (0, react.useRef)(null);
|
|
73
|
+
const summary = (0, react.useRef)(null);
|
|
74
|
+
const controls = (0, react.useRef)(null);
|
|
75
|
+
const navigation = (0, react.useRef)(null);
|
|
76
|
+
const [hasSpace, setHasSpace] = (0, react.useState)(false);
|
|
77
|
+
const hideExtras = responsive && !hasSpace;
|
|
78
|
+
const hiddenClass = hideExtras ? "absolute invisible pointer-events-none left-0 top-0" : void 0;
|
|
79
|
+
const pageIndex = table.getState().pagination.pageIndex;
|
|
80
|
+
const pageCount = table.getPageCount();
|
|
81
|
+
const canJump = Number.isFinite(pageCount) && pageCount > 0;
|
|
71
82
|
const total = table.options.rowCount ?? (table.options.manualPagination ? void 0 : table.getRowCount());
|
|
83
|
+
(0, react.useEffect)(() => {
|
|
84
|
+
if (!responsive || !container.current || !summary.current || !controls.current || !navigation.current) return;
|
|
85
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
86
|
+
const root = container.current;
|
|
87
|
+
const info = summary.current;
|
|
88
|
+
const group = controls.current;
|
|
89
|
+
const nav = navigation.current;
|
|
90
|
+
const jump = pageJump.current;
|
|
91
|
+
const gap = (node) => parseFloat(getComputedStyle(node).columnGap) || 0;
|
|
92
|
+
const width = (node) => {
|
|
93
|
+
const children = Array.from(node.children);
|
|
94
|
+
return children.reduce((sum, child) => {
|
|
95
|
+
const style = getComputedStyle(child);
|
|
96
|
+
return sum + (child === nav || child === jump ? width(child) : child.getBoundingClientRect().width) + (parseFloat(style.marginLeft) || 0) + (parseFloat(style.marginRight) || 0);
|
|
97
|
+
}, 0) + Math.max(0, children.length - 1) * gap(node);
|
|
98
|
+
};
|
|
99
|
+
const measure = () => {
|
|
100
|
+
const style = getComputedStyle(root);
|
|
101
|
+
const available = root.clientWidth - (parseFloat(style.paddingLeft) || 0) - (parseFloat(style.paddingRight) || 0);
|
|
102
|
+
const required = style.flexDirection.startsWith("column") ? Math.max(width(info), width(group)) : width(info) + width(group) + gap(root);
|
|
103
|
+
setHasSpace(available + .5 >= required);
|
|
104
|
+
};
|
|
105
|
+
const observer = new ResizeObserver(measure);
|
|
106
|
+
for (const node of [
|
|
107
|
+
root,
|
|
108
|
+
info,
|
|
109
|
+
group,
|
|
110
|
+
nav,
|
|
111
|
+
...info.children,
|
|
112
|
+
...group.children,
|
|
113
|
+
...nav.children,
|
|
114
|
+
...jump?.children ?? []
|
|
115
|
+
]) observer.observe(node);
|
|
116
|
+
measure();
|
|
117
|
+
return () => observer.disconnect();
|
|
118
|
+
}, [
|
|
119
|
+
responsive,
|
|
120
|
+
showPageJump,
|
|
121
|
+
alwaysShowFirstLast,
|
|
122
|
+
total !== void 0
|
|
123
|
+
]);
|
|
72
124
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
73
|
-
|
|
125
|
+
ref: container,
|
|
126
|
+
className: cn("flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8", responsive && "relative", className),
|
|
74
127
|
...props,
|
|
75
128
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
129
|
+
ref: summary,
|
|
76
130
|
className: "flex flex-1 items-center gap-6 whitespace-nowrap text-muted-foreground text-sm",
|
|
77
131
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
78
132
|
table.getFilteredSelectedRowModel().rows.length,
|
|
@@ -82,7 +136,8 @@ function DataTablePagination({ table, pageSizeOptions = [
|
|
|
82
136
|
" row(s) selected."
|
|
83
137
|
] }), total !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Total: ", total] })]
|
|
84
138
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
85
|
-
|
|
139
|
+
ref: controls,
|
|
140
|
+
className: cn("flex items-center gap-4 sm:gap-6 lg:gap-8", responsive ? "flex-row flex-wrap justify-center whitespace-nowrap [&>*]:shrink-0" : "flex-col-reverse sm:flex-row"),
|
|
86
141
|
children: [
|
|
87
142
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
88
143
|
className: "flex items-center space-x-2",
|
|
@@ -110,19 +165,55 @@ function DataTablePagination({ table, pageSizeOptions = [
|
|
|
110
165
|
className: "flex items-center justify-center font-medium text-sm",
|
|
111
166
|
children: [
|
|
112
167
|
"Page ",
|
|
113
|
-
|
|
168
|
+
pageIndex + 1,
|
|
114
169
|
" of ",
|
|
115
|
-
|
|
170
|
+
pageCount
|
|
116
171
|
]
|
|
117
172
|
}),
|
|
173
|
+
showPageJump && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
174
|
+
ref: pageJump,
|
|
175
|
+
className: hideExtras ? "pointer-events-none absolute inset-x-0 top-0 invisible overflow-hidden" : void 0,
|
|
176
|
+
"aria-hidden": hideExtras || void 0,
|
|
177
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
178
|
+
className: "flex w-max items-center gap-2",
|
|
179
|
+
onSubmit: (event) => {
|
|
180
|
+
event.preventDefault();
|
|
181
|
+
const page = Number(new FormData(event.currentTarget).get("page"));
|
|
182
|
+
if (canJump && Number.isInteger(page) && page >= 1 && page <= pageCount) table.setPageIndex(page - 1);
|
|
183
|
+
},
|
|
184
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
185
|
+
className: "flex items-center gap-2 whitespace-nowrap text-sm",
|
|
186
|
+
children: [pageJumpLabel, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Input, {
|
|
187
|
+
name: "page",
|
|
188
|
+
type: "number",
|
|
189
|
+
min: 1,
|
|
190
|
+
max: canJump ? pageCount : void 0,
|
|
191
|
+
step: 1,
|
|
192
|
+
required: true,
|
|
193
|
+
defaultValue: pageIndex + 1,
|
|
194
|
+
disabled: !canJump,
|
|
195
|
+
className: "h-8 w-20"
|
|
196
|
+
}, `${pageIndex}-${pageCount}`)]
|
|
197
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
|
|
198
|
+
type: "submit",
|
|
199
|
+
variant: "outline",
|
|
200
|
+
size: "icon",
|
|
201
|
+
className: "size-8",
|
|
202
|
+
disabled: !canJump,
|
|
203
|
+
"aria-label": pageJumpLabel,
|
|
204
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, {})
|
|
205
|
+
})]
|
|
206
|
+
})
|
|
207
|
+
}),
|
|
118
208
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
209
|
+
ref: navigation,
|
|
119
210
|
className: "flex items-center space-x-2",
|
|
120
211
|
children: [
|
|
121
212
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
|
|
122
213
|
"aria-label": "Go to first page",
|
|
123
214
|
variant: "outline",
|
|
124
215
|
size: "icon",
|
|
125
|
-
className: "
|
|
216
|
+
className: cn("size-8", alwaysShowFirstLast ? "flex" : "hidden lg:flex", hiddenClass),
|
|
126
217
|
onClick: () => table.setPageIndex(0),
|
|
127
218
|
disabled: !table.getCanPreviousPage(),
|
|
128
219
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronsLeft, {})
|
|
@@ -149,9 +240,9 @@ function DataTablePagination({ table, pageSizeOptions = [
|
|
|
149
240
|
"aria-label": "Go to last page",
|
|
150
241
|
variant: "outline",
|
|
151
242
|
size: "icon",
|
|
152
|
-
className: "
|
|
243
|
+
className: cn("size-8", alwaysShowFirstLast ? "flex" : "hidden lg:flex", hiddenClass),
|
|
153
244
|
onClick: () => table.setPageIndex(table.getPageCount() - 1),
|
|
154
|
-
disabled: !table.getCanNextPage(),
|
|
245
|
+
disabled: !table.getCanNextPage() || alwaysShowFirstLast && !canJump,
|
|
155
246
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronsRight, {})
|
|
156
247
|
})
|
|
157
248
|
]
|
|
@@ -497,7 +588,7 @@ function formatDate(date, opts = {}, preset) {
|
|
|
497
588
|
|
|
498
589
|
//#endregion
|
|
499
590
|
//#region src/components/data-table/data-table.tsx
|
|
500
|
-
function DataTable({ table, actionBar, children, className, classNames,...props }) {
|
|
591
|
+
function DataTable({ table, actionBar, pagination, children, className, classNames,...props }) {
|
|
501
592
|
useDateFormatterVersion();
|
|
502
593
|
const columns = [
|
|
503
594
|
...table.getLeftVisibleLeafColumns(),
|
|
@@ -562,7 +653,10 @@ function DataTable({ table, actionBar, children, className, classNames,...props
|
|
|
562
653
|
}),
|
|
563
654
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
564
655
|
className: "flex flex-col gap-2.5",
|
|
565
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTablePagination, {
|
|
656
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTablePagination, {
|
|
657
|
+
table,
|
|
658
|
+
...pagination
|
|
659
|
+
}), actionBar && table.getFilteredSelectedRowModel().rows.length > 0 && actionBar]
|
|
566
660
|
})
|
|
567
661
|
]
|
|
568
662
|
});
|
|
@@ -1101,6 +1195,59 @@ function parseCalendarDate(value) {
|
|
|
1101
1195
|
const date = new Date(Number(value));
|
|
1102
1196
|
return Number.isNaN(date.getTime()) ? void 0 : date;
|
|
1103
1197
|
}
|
|
1198
|
+
/** Resolve bounds and the calendar's today marker in the Host's configured time zone. */
|
|
1199
|
+
function calendarMaxDate(value) {
|
|
1200
|
+
if (value !== "today") return parseCalendarDate(value);
|
|
1201
|
+
return parseCalendarDate(calendarDay(/* @__PURE__ */ new Date(), calendarDayFormatter()));
|
|
1202
|
+
}
|
|
1203
|
+
function calendarDayFormatter() {
|
|
1204
|
+
return new Intl.DateTimeFormat("en-CA", {
|
|
1205
|
+
timeZone: getDateLocaleOptions()?.timeZone,
|
|
1206
|
+
year: "numeric",
|
|
1207
|
+
month: "2-digit",
|
|
1208
|
+
day: "2-digit"
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
function calendarDay(date, formatter) {
|
|
1212
|
+
const parts = Object.fromEntries(formatter.formatToParts(date).map((part) => [part.type, part.value]));
|
|
1213
|
+
return `${parts.year}-${parts.month}-${parts.day}`;
|
|
1214
|
+
}
|
|
1215
|
+
/** Keep both the today marker and relative bounds current while a filter stays mounted. */
|
|
1216
|
+
function useCalendarToday() {
|
|
1217
|
+
useDateFormatterVersion();
|
|
1218
|
+
const timeZone = getDateLocaleOptions()?.timeZone;
|
|
1219
|
+
const [today, setToday] = (0, react.useState)(() => calendarMaxDate("today"));
|
|
1220
|
+
(0, react.useEffect)(() => {
|
|
1221
|
+
const formatter = calendarDayFormatter();
|
|
1222
|
+
let timer;
|
|
1223
|
+
const refresh = () => {
|
|
1224
|
+
clearTimeout(timer);
|
|
1225
|
+
const now = Date.now();
|
|
1226
|
+
const day = calendarDay(new Date(now), formatter);
|
|
1227
|
+
setToday((previous) => serializeCalendarDate(previous) === day ? previous : parseCalendarDate(day));
|
|
1228
|
+
let before = now;
|
|
1229
|
+
let after = now + 2880 * 60 * 1e3;
|
|
1230
|
+
while (after - before > 1) {
|
|
1231
|
+
const middle = Math.floor((before + after) / 2);
|
|
1232
|
+
if (calendarDay(new Date(middle), formatter) === day) before = middle;
|
|
1233
|
+
else after = middle;
|
|
1234
|
+
}
|
|
1235
|
+
timer = setTimeout(refresh, Math.max(1, after - Date.now()));
|
|
1236
|
+
};
|
|
1237
|
+
const onVisibilityChange = () => {
|
|
1238
|
+
if (!document.hidden) refresh();
|
|
1239
|
+
};
|
|
1240
|
+
refresh();
|
|
1241
|
+
window.addEventListener("focus", refresh);
|
|
1242
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
1243
|
+
return () => {
|
|
1244
|
+
clearTimeout(timer);
|
|
1245
|
+
window.removeEventListener("focus", refresh);
|
|
1246
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
1247
|
+
};
|
|
1248
|
+
}, [timeZone]);
|
|
1249
|
+
return today;
|
|
1250
|
+
}
|
|
1104
1251
|
function calendarPresentation() {
|
|
1105
1252
|
const localeOptions = getDateLocaleOptions();
|
|
1106
1253
|
const locale = localeOptions?.locale ?? "en-US";
|
|
@@ -1322,7 +1469,7 @@ function DataTableFilterList({ table, debounceMs = DEBOUNCE_MS$2, throttleMs = T
|
|
|
1322
1469
|
});
|
|
1323
1470
|
}
|
|
1324
1471
|
function DataTableFilterItem$1({ filter, index: index$1, filterItemId, joinOperator, setJoinOperator, columns, onFilterUpdate, onFilterRemove }) {
|
|
1325
|
-
|
|
1472
|
+
const today = useCalendarToday();
|
|
1326
1473
|
const [showFieldSelector, setShowFieldSelector] = react.useState(false);
|
|
1327
1474
|
const [showOperatorSelector, setShowOperatorSelector] = react.useState(false);
|
|
1328
1475
|
const [showValueSelector, setShowValueSelector] = react.useState(false);
|
|
@@ -1451,6 +1598,7 @@ function DataTableFilterItem$1({ filter, index: index$1, filterItemId, joinOpera
|
|
|
1451
1598
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1452
1599
|
className: "min-w-36 max-w-60 flex-1",
|
|
1453
1600
|
children: onFilterInputRender$1({
|
|
1601
|
+
today,
|
|
1454
1602
|
filter,
|
|
1455
1603
|
inputId,
|
|
1456
1604
|
column,
|
|
@@ -1481,7 +1629,9 @@ function DataTableFilterItem$1({ filter, index: index$1, filterItemId, joinOpera
|
|
|
1481
1629
|
})
|
|
1482
1630
|
});
|
|
1483
1631
|
}
|
|
1484
|
-
function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUpdate, showValueSelector, setShowValueSelector }) {
|
|
1632
|
+
function onFilterInputRender$1({ today, filter, inputId, column, columnMeta, onFilterUpdate, showValueSelector, setShowValueSelector }) {
|
|
1633
|
+
const maxDate = column.columnDef.meta?.maxDate;
|
|
1634
|
+
const upperBound = maxDate === "today" ? today : calendarMaxDate(maxDate);
|
|
1485
1635
|
if (filter.operator === "isEmpty" || filter.operator === "isNotEmpty") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1486
1636
|
id: inputId,
|
|
1487
1637
|
role: "status",
|
|
@@ -1637,6 +1787,8 @@ function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUp
|
|
|
1637
1787
|
align: "start",
|
|
1638
1788
|
className: "w-auto p-0",
|
|
1639
1789
|
children: filter.operator === "isBetween" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
1790
|
+
today,
|
|
1791
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
1640
1792
|
lang: calendarPresentation().locale,
|
|
1641
1793
|
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
1642
1794
|
formatters: calendarPresentation().formatters,
|
|
@@ -1645,6 +1797,7 @@ function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUp
|
|
|
1645
1797
|
autoFocus: true,
|
|
1646
1798
|
captionLayout: "dropdown",
|
|
1647
1799
|
mode: "range",
|
|
1800
|
+
excludeDisabled: !!column.columnDef.meta?.maxDate,
|
|
1648
1801
|
selected: dateValue.length === 2 ? {
|
|
1649
1802
|
from: parseCalendarDate(dateValue[0]),
|
|
1650
1803
|
to: parseCalendarDate(dateValue[1])
|
|
@@ -1656,6 +1809,8 @@ function onFilterInputRender$1({ filter, inputId, column, columnMeta, onFilterUp
|
|
|
1656
1809
|
onFilterUpdate(filter.filterId, { value: date ? [date.from ? serializeCalendarDate(date.from) : "", date.to ? serializeCalendarDate(date.to) : ""] : [] });
|
|
1657
1810
|
}
|
|
1658
1811
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
1812
|
+
today,
|
|
1813
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
1659
1814
|
lang: calendarPresentation().locale,
|
|
1660
1815
|
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
1661
1816
|
formatters: calendarPresentation().formatters,
|
|
@@ -1878,7 +2033,7 @@ function DataTableFilterMenu({ table, debounceMs = DEBOUNCE_MS$1, throttleMs = T
|
|
|
1878
2033
|
}
|
|
1879
2034
|
function DataTableFilterItem({ filter, filterItemId, columns, onFilterUpdate, onFilterRemove }) {
|
|
1880
2035
|
{
|
|
1881
|
-
|
|
2036
|
+
const today = useCalendarToday();
|
|
1882
2037
|
const [showFieldSelector, setShowFieldSelector] = react.useState(false);
|
|
1883
2038
|
const [showOperatorSelector, setShowOperatorSelector] = react.useState(false);
|
|
1884
2039
|
const [showValueSelector, setShowValueSelector] = react.useState(false);
|
|
@@ -1969,6 +2124,7 @@ function DataTableFilterItem({ filter, filterItemId, columns, onFilterUpdate, on
|
|
|
1969
2124
|
})]
|
|
1970
2125
|
}),
|
|
1971
2126
|
onFilterInputRender({
|
|
2127
|
+
today,
|
|
1972
2128
|
filter,
|
|
1973
2129
|
column,
|
|
1974
2130
|
inputId,
|
|
@@ -1989,7 +2145,9 @@ function DataTableFilterItem({ filter, filterItemId, columns, onFilterUpdate, on
|
|
|
1989
2145
|
}
|
|
1990
2146
|
}
|
|
1991
2147
|
function FilterValueSelector({ column, value, onSelect }) {
|
|
1992
|
-
|
|
2148
|
+
const today = useCalendarToday();
|
|
2149
|
+
const maxDate = column.columnDef.meta?.maxDate;
|
|
2150
|
+
const upperBound = maxDate === "today" ? today : calendarMaxDate(maxDate);
|
|
1993
2151
|
switch (column.columnDef.meta?.variant ?? "text") {
|
|
1994
2152
|
case "boolean": return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.CommandGroup, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.CommandItem, {
|
|
1995
2153
|
value: "true",
|
|
@@ -2018,6 +2176,8 @@ function FilterValueSelector({ column, value, onSelect }) {
|
|
|
2018
2176
|
}, option.value)) });
|
|
2019
2177
|
case "date":
|
|
2020
2178
|
case "dateRange": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2179
|
+
today,
|
|
2180
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
2021
2181
|
lang: calendarPresentation().locale,
|
|
2022
2182
|
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
2023
2183
|
formatters: calendarPresentation().formatters,
|
|
@@ -2046,7 +2206,9 @@ function FilterValueSelector({ column, value, onSelect }) {
|
|
|
2046
2206
|
}
|
|
2047
2207
|
}
|
|
2048
2208
|
}
|
|
2049
|
-
function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValueSelector, setShowValueSelector }) {
|
|
2209
|
+
function onFilterInputRender({ today, filter, column, inputId, onFilterUpdate, showValueSelector, setShowValueSelector }) {
|
|
2210
|
+
const maxDate = column.columnDef.meta?.maxDate;
|
|
2211
|
+
const upperBound = maxDate === "today" ? today : calendarMaxDate(maxDate);
|
|
2050
2212
|
if (filter.operator === "isEmpty" || filter.operator === "isNotEmpty") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2051
2213
|
id: inputId,
|
|
2052
2214
|
role: "status",
|
|
@@ -2205,6 +2367,8 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2205
2367
|
align: "start",
|
|
2206
2368
|
className: "w-auto p-0",
|
|
2207
2369
|
children: filter.operator === "isBetween" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2370
|
+
today,
|
|
2371
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
2208
2372
|
lang: calendarPresentation().locale,
|
|
2209
2373
|
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
2210
2374
|
formatters: calendarPresentation().formatters,
|
|
@@ -2212,6 +2376,7 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2212
2376
|
autoFocus: true,
|
|
2213
2377
|
captionLayout: "dropdown",
|
|
2214
2378
|
mode: "range",
|
|
2379
|
+
excludeDisabled: !!column.columnDef.meta?.maxDate,
|
|
2215
2380
|
selected: dateValue.length === 2 ? {
|
|
2216
2381
|
from: parseCalendarDate(dateValue[0]),
|
|
2217
2382
|
to: parseCalendarDate(dateValue[1])
|
|
@@ -2223,6 +2388,8 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2223
2388
|
onFilterUpdate(filter.filterId, { value: date ? [date.from ? serializeCalendarDate(date.from) : "", date.to ? serializeCalendarDate(date.to) : ""] : [] });
|
|
2224
2389
|
}
|
|
2225
2390
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
2391
|
+
today,
|
|
2392
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
2226
2393
|
lang: calendarPresentation().locale,
|
|
2227
2394
|
weekStartsOn: calendarPresentation().weekStartsOn,
|
|
2228
2395
|
formatters: calendarPresentation().formatters,
|
|
@@ -2758,6 +2925,7 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
|
|
|
2758
2925
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SimpleDateFilter, {
|
|
2759
2926
|
title: meta.label ?? column.id,
|
|
2760
2927
|
multiple: meta.variant === "dateRange",
|
|
2928
|
+
maxDate: meta.maxDate,
|
|
2761
2929
|
value,
|
|
2762
2930
|
onChange: (v) => updateFilter(column.id, v)
|
|
2763
2931
|
})
|
|
@@ -2980,7 +3148,9 @@ function SimpleSliderFilter({ title, range, unit, value, onChange }) {
|
|
|
2980
3148
|
]
|
|
2981
3149
|
})] });
|
|
2982
3150
|
}
|
|
2983
|
-
function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
3151
|
+
function SimpleDateFilter({ title, maxDate, multiple, value, onChange }) {
|
|
3152
|
+
const today = useCalendarToday();
|
|
3153
|
+
const upperBound = maxDate === "today" ? today : calendarMaxDate(maxDate);
|
|
2984
3154
|
const [open, setOpen] = react.useState(false);
|
|
2985
3155
|
const commit = (next) => {
|
|
2986
3156
|
setOpen(false);
|
|
@@ -3047,6 +3217,8 @@ function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
|
3047
3217
|
className: "w-auto p-0",
|
|
3048
3218
|
align: "start",
|
|
3049
3219
|
children: multiple ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
3220
|
+
today,
|
|
3221
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
3050
3222
|
lang: presentation.locale,
|
|
3051
3223
|
weekStartsOn: presentation.weekStartsOn,
|
|
3052
3224
|
formatters: presentation.formatters,
|
|
@@ -3055,6 +3227,7 @@ function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
|
3055
3227
|
autoFocus: true,
|
|
3056
3228
|
captionLayout: "dropdown",
|
|
3057
3229
|
mode: "range",
|
|
3230
|
+
excludeDisabled: !!upperBound,
|
|
3058
3231
|
selected: localRange,
|
|
3059
3232
|
onSelect: (range) => {
|
|
3060
3233
|
if (!range?.from && !range?.to) {
|
|
@@ -3106,6 +3279,8 @@ function SimpleDateFilter({ title, multiple, value, onChange }) {
|
|
|
3106
3279
|
}
|
|
3107
3280
|
}
|
|
3108
3281
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
3282
|
+
today,
|
|
3283
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
3109
3284
|
lang: presentation.locale,
|
|
3110
3285
|
weekStartsOn: presentation.weekStartsOn,
|
|
3111
3286
|
formatters: presentation.formatters,
|
|
@@ -3684,7 +3859,7 @@ function generateCSVTemplate(headers) {
|
|
|
3684
3859
|
function dataToCSV(data, opts = {}) {
|
|
3685
3860
|
if (data.length === 0) return "";
|
|
3686
3861
|
const allHeaders = Object.keys(data[0]);
|
|
3687
|
-
const headers = (opts.headers ?? allHeaders).filter((h) => !opts.excludeColumns?.includes(h));
|
|
3862
|
+
const headers = (opts.headers ?? allHeaders).filter((h) => h !== "__crudExtensionProjection" && !opts.excludeColumns?.includes(h));
|
|
3688
3863
|
return [headers.map((h) => escapeCSVField(h)).join(","), ...data.map((row) => headers.map((h) => escapeCSVField(String(row[h] ?? ""))).join(","))].join("\n");
|
|
3689
3864
|
}
|
|
3690
3865
|
function escapeCSVField(field) {
|
|
@@ -3773,7 +3948,7 @@ function downloadCSVTemplate(headers, filename = "template") {
|
|
|
3773
3948
|
}).join(",") + "\n", filename);
|
|
3774
3949
|
}
|
|
3775
3950
|
function downloadCSV(csvContent, filename) {
|
|
3776
|
-
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
3951
|
+
const blob = new Blob(["", csvContent], { type: "text/csv;charset=utf-8;" });
|
|
3777
3952
|
const url = URL.createObjectURL(blob);
|
|
3778
3953
|
const link = document.createElement("a");
|
|
3779
3954
|
link.setAttribute("href", url);
|
|
@@ -4248,7 +4423,7 @@ const filterModeConfig = {
|
|
|
4248
4423
|
tooltip: "Linear-style command filters"
|
|
4249
4424
|
}
|
|
4250
4425
|
};
|
|
4251
|
-
function AutoTable({ schema, data, pageCount = 1, total, overrides, classNames, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
|
|
4426
|
+
function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
|
|
4252
4427
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
4253
4428
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
4254
4429
|
const showToggle = modes.length > 1;
|
|
@@ -4411,6 +4586,7 @@ function AutoTable({ schema, data, pageCount = 1, total, overrides, classNames,
|
|
|
4411
4586
|
})]
|
|
4412
4587
|
}),
|
|
4413
4588
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
|
|
4589
|
+
pagination,
|
|
4414
4590
|
table,
|
|
4415
4591
|
classNames
|
|
4416
4592
|
}),
|
|
@@ -4484,6 +4660,45 @@ function FormModal({ open, onOpenChange, title, description, children, variant =
|
|
|
4484
4660
|
});
|
|
4485
4661
|
}
|
|
4486
4662
|
|
|
4663
|
+
//#endregion
|
|
4664
|
+
//#region src/components/auto-crud/date-only-picker.tsx
|
|
4665
|
+
const primitives = {
|
|
4666
|
+
Button: __wordrhyme_ui.Button,
|
|
4667
|
+
Calendar: __wordrhyme_ui.Calendar,
|
|
4668
|
+
Popover: __wordrhyme_ui.Popover,
|
|
4669
|
+
PopoverContent: __wordrhyme_ui.PopoverContent,
|
|
4670
|
+
PopoverTrigger: __wordrhyme_ui.PopoverTrigger
|
|
4671
|
+
};
|
|
4672
|
+
function DatePicker({ dateInput,...props }) {
|
|
4673
|
+
if (props.valueFormat !== void 0 && dateInput === "utc-projection") {
|
|
4674
|
+
const value = props.value;
|
|
4675
|
+
props = {
|
|
4676
|
+
...props,
|
|
4677
|
+
value: value instanceof Date ? Number.isNaN(value.getTime()) ? "" : parseCalendarDate(value.toISOString().slice(0, 10)) : typeof value === "string" && /^\d{4}-\d{2}-\d{2}T/.test(value) && !Number.isNaN(Date.parse(value)) ? parseCalendarDate(value.slice(0, 10)) : value
|
|
4678
|
+
};
|
|
4679
|
+
}
|
|
4680
|
+
useDateFormatterVersion();
|
|
4681
|
+
const presentation = calendarPresentation();
|
|
4682
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_formily_shadcn.DatePicker, {
|
|
4683
|
+
primitives,
|
|
4684
|
+
...props.valueFormat !== void 0 ? {
|
|
4685
|
+
captionLayout: "dropdown-months",
|
|
4686
|
+
formatters: presentation.formatters,
|
|
4687
|
+
labels: presentation.labels,
|
|
4688
|
+
weekStartsOn: presentation.weekStartsOn,
|
|
4689
|
+
placeholder: props.valueFormat
|
|
4690
|
+
} : {},
|
|
4691
|
+
...props
|
|
4692
|
+
});
|
|
4693
|
+
}
|
|
4694
|
+
/** @deprecated Use DatePicker with valueFormat="YYYY-MM-DD". */
|
|
4695
|
+
function DateOnlyPicker(props) {
|
|
4696
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DatePicker, {
|
|
4697
|
+
...props,
|
|
4698
|
+
valueFormat: "YYYY-MM-DD"
|
|
4699
|
+
});
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4487
4702
|
//#endregion
|
|
4488
4703
|
//#region src/lib/schema-bridge/zod-to-formily.ts
|
|
4489
4704
|
const DEFAULT_FORM_MANAGED_FIELDS = [
|
|
@@ -4586,6 +4801,27 @@ function createEditFormSchema(schema, options) {
|
|
|
4586
4801
|
});
|
|
4587
4802
|
}
|
|
4588
4803
|
|
|
4804
|
+
//#endregion
|
|
4805
|
+
//#region src/lib/crud-reference-projection.ts
|
|
4806
|
+
function isRecord$1(value) {
|
|
4807
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4808
|
+
}
|
|
4809
|
+
/** Read a label only while its ID still matches the field's current value. */
|
|
4810
|
+
function readCrudReferenceOption(row, field, value) {
|
|
4811
|
+
if (!isRecord$1(row)) return void 0;
|
|
4812
|
+
const { __crudExtensionProjection: projections } = row;
|
|
4813
|
+
if (!isRecord$1(projections)) return void 0;
|
|
4814
|
+
const projection = projections[field];
|
|
4815
|
+
if (!isRecord$1(projection)) return void 0;
|
|
4816
|
+
if (typeof value !== "string" && typeof value !== "number") return void 0;
|
|
4817
|
+
if (typeof projection.refId !== "string" && typeof projection.refId !== "number") return;
|
|
4818
|
+
if (String(value).length === 0 || String(projection.refId) !== String(value) || typeof projection.display !== "string" || projection.display.length === 0) return;
|
|
4819
|
+
return {
|
|
4820
|
+
value: String(value),
|
|
4821
|
+
label: projection.display
|
|
4822
|
+
};
|
|
4823
|
+
}
|
|
4824
|
+
|
|
4589
4825
|
//#endregion
|
|
4590
4826
|
//#region src/lib/registries.ts
|
|
4591
4827
|
function createRegistry(label) {
|
|
@@ -4625,6 +4861,7 @@ function createRegistry(label) {
|
|
|
4625
4861
|
}
|
|
4626
4862
|
};
|
|
4627
4863
|
}
|
|
4864
|
+
const tablePagination = createRegistry("table pagination");
|
|
4628
4865
|
const formComponents = createRegistry("form component");
|
|
4629
4866
|
const components = formComponents;
|
|
4630
4867
|
function normalizeDataSourceRegistration(registration) {
|
|
@@ -4763,6 +5000,14 @@ function AutoCrudMultiCombobox({ options = [], className,...props }) {
|
|
|
4763
5000
|
});
|
|
4764
5001
|
}
|
|
4765
5002
|
const defaultFieldComponents = {
|
|
5003
|
+
DatePicker: {
|
|
5004
|
+
component: DatePicker,
|
|
5005
|
+
decorator: "FormItem"
|
|
5006
|
+
},
|
|
5007
|
+
DateOnlyPicker: {
|
|
5008
|
+
component: DateOnlyPicker,
|
|
5009
|
+
decorator: "FormItem"
|
|
5010
|
+
},
|
|
4766
5011
|
Combobox: {
|
|
4767
5012
|
component: FormilyCombobox,
|
|
4768
5013
|
decorator: "FormItem"
|
|
@@ -4838,6 +5083,13 @@ function mergeDataSourceOptions(current, incoming) {
|
|
|
4838
5083
|
for (const option of incoming) optionsByValue.set(option.value, option);
|
|
4839
5084
|
return Array.from(optionsByValue.values());
|
|
4840
5085
|
}
|
|
5086
|
+
function setAutoCrudDataSourceOptions(field, options) {
|
|
5087
|
+
const projectedOption = readCrudReferenceOption(field.form.initialValues, field.path.toString(), field.value);
|
|
5088
|
+
field.setDataSource(projectedOption ? mergeDataSourceOptions([{
|
|
5089
|
+
...projectedOption,
|
|
5090
|
+
disabled: true
|
|
5091
|
+
}], options) : options);
|
|
5092
|
+
}
|
|
4841
5093
|
function isNearPopupScrollBottom$1(target) {
|
|
4842
5094
|
return target.scrollHeight - target.scrollTop - target.clientHeight <= POPUP_SCROLL_LOAD_THRESHOLD$1;
|
|
4843
5095
|
}
|
|
@@ -4853,6 +5105,7 @@ function loadAutoCrudDataSource({ entry, field, registryVersion, search, sourceK
|
|
|
4853
5105
|
values,
|
|
4854
5106
|
search: searchValue
|
|
4855
5107
|
});
|
|
5108
|
+
setAutoCrudDataSourceOptions(field, state.options);
|
|
4856
5109
|
if (!append && state.loadKey === loadKey && state.registryVersion === registryVersion) return;
|
|
4857
5110
|
if (entry.reset && state.dependencyKey !== void 0 && state.dependencyKey !== dependencyKey) field.setValue(void 0);
|
|
4858
5111
|
state.dependencyKey = dependencyKey;
|
|
@@ -4895,7 +5148,7 @@ function loadAutoCrudDataSource({ entry, field, registryVersion, search, sourceK
|
|
|
4895
5148
|
state.page = page ?? 0;
|
|
4896
5149
|
state.hasMore = entry.loadMore ? normalizeHasMore(result) : false;
|
|
4897
5150
|
state.appendLoading = false;
|
|
4898
|
-
field
|
|
5151
|
+
setAutoCrudDataSourceOptions(field, nextOptions);
|
|
4899
5152
|
field.setLoading(false);
|
|
4900
5153
|
field.setComponentProps({
|
|
4901
5154
|
loading: false,
|
|
@@ -4907,7 +5160,7 @@ function loadAutoCrudDataSource({ entry, field, registryVersion, search, sourceK
|
|
|
4907
5160
|
if (!append) {
|
|
4908
5161
|
state.options = [];
|
|
4909
5162
|
state.hasMore = false;
|
|
4910
|
-
field
|
|
5163
|
+
setAutoCrudDataSourceOptions(field, []);
|
|
4911
5164
|
}
|
|
4912
5165
|
state.appendLoading = false;
|
|
4913
5166
|
field.setLoading(false);
|
|
@@ -4931,7 +5184,7 @@ function applySearchComponentProps({ entry, field, registryState, sourceKey, sta
|
|
|
4931
5184
|
const currentEntry = dataSources.get(sourceKey);
|
|
4932
5185
|
if (!currentEntry) {
|
|
4933
5186
|
state.controller?.abort();
|
|
4934
|
-
field
|
|
5187
|
+
setAutoCrudDataSourceOptions(field, []);
|
|
4935
5188
|
field.setLoading(false);
|
|
4936
5189
|
field.setComponentProps({ loading: false });
|
|
4937
5190
|
return;
|
|
@@ -4961,7 +5214,7 @@ function applyLoadMoreComponentProps({ entry, field, registryState, sourceKey, s
|
|
|
4961
5214
|
state.controller?.abort();
|
|
4962
5215
|
state.hasMore = false;
|
|
4963
5216
|
state.appendLoading = false;
|
|
4964
|
-
field
|
|
5217
|
+
setAutoCrudDataSourceOptions(field, []);
|
|
4965
5218
|
field.setLoading(false);
|
|
4966
5219
|
field.setComponentProps({
|
|
4967
5220
|
hasMore: false,
|
|
@@ -4994,14 +5247,14 @@ function createAutoCrudDataSourceReaction(config, registryState) {
|
|
|
4994
5247
|
state.initialized = true;
|
|
4995
5248
|
}
|
|
4996
5249
|
if (!source) {
|
|
4997
|
-
field
|
|
5250
|
+
setAutoCrudDataSourceOptions(field, []);
|
|
4998
5251
|
field.setLoading(false);
|
|
4999
5252
|
return;
|
|
5000
5253
|
}
|
|
5001
5254
|
const entry = dataSources.get(source.key);
|
|
5002
5255
|
if (!entry) {
|
|
5003
5256
|
state.controller?.abort();
|
|
5004
|
-
field
|
|
5257
|
+
setAutoCrudDataSourceOptions(field, []);
|
|
5005
5258
|
field.setLoading(false);
|
|
5006
5259
|
return;
|
|
5007
5260
|
}
|
|
@@ -5099,6 +5352,7 @@ const AutoForm = (0, react.forwardRef)(AutoFormInner);
|
|
|
5099
5352
|
//#endregion
|
|
5100
5353
|
//#region src/i18n/locale.ts
|
|
5101
5354
|
const zhCN = {
|
|
5355
|
+
pagination: { pageJump: "跳转到页" },
|
|
5102
5356
|
toolbar: {
|
|
5103
5357
|
refresh: "刷新",
|
|
5104
5358
|
create: "新建",
|
|
@@ -5166,6 +5420,7 @@ const zhCN = {
|
|
|
5166
5420
|
}
|
|
5167
5421
|
};
|
|
5168
5422
|
const enUS = {
|
|
5423
|
+
pagination: { pageJump: "Go to page" },
|
|
5169
5424
|
toolbar: {
|
|
5170
5425
|
refresh: "Refresh",
|
|
5171
5426
|
create: "New",
|
|
@@ -5233,6 +5488,7 @@ const enUS = {
|
|
|
5233
5488
|
}
|
|
5234
5489
|
};
|
|
5235
5490
|
const jaJP = {
|
|
5491
|
+
pagination: { pageJump: "ページへ移動" },
|
|
5236
5492
|
toolbar: {
|
|
5237
5493
|
refresh: "更新",
|
|
5238
5494
|
create: "新規作成",
|
|
@@ -5300,6 +5556,7 @@ const jaJP = {
|
|
|
5300
5556
|
}
|
|
5301
5557
|
};
|
|
5302
5558
|
const koKR = {
|
|
5559
|
+
pagination: { pageJump: "페이지로 이동" },
|
|
5303
5560
|
toolbar: {
|
|
5304
5561
|
refresh: "새로고침",
|
|
5305
5562
|
create: "새로 만들기",
|
|
@@ -5367,6 +5624,7 @@ const koKR = {
|
|
|
5367
5624
|
}
|
|
5368
5625
|
};
|
|
5369
5626
|
const frFR = {
|
|
5627
|
+
pagination: { pageJump: "Aller à la page" },
|
|
5370
5628
|
toolbar: {
|
|
5371
5629
|
refresh: "Actualiser",
|
|
5372
5630
|
create: "Nouveau",
|
|
@@ -5434,6 +5692,7 @@ const frFR = {
|
|
|
5434
5692
|
}
|
|
5435
5693
|
};
|
|
5436
5694
|
const deDE = {
|
|
5695
|
+
pagination: { pageJump: "Zur Seite springen" },
|
|
5437
5696
|
toolbar: {
|
|
5438
5697
|
refresh: "Aktualisieren",
|
|
5439
5698
|
create: "Neu",
|
|
@@ -5501,6 +5760,7 @@ const deDE = {
|
|
|
5501
5760
|
}
|
|
5502
5761
|
};
|
|
5503
5762
|
const esES = {
|
|
5763
|
+
pagination: { pageJump: "Ir a la página" },
|
|
5504
5764
|
toolbar: {
|
|
5505
5765
|
refresh: "Actualizar",
|
|
5506
5766
|
create: "Nuevo",
|
|
@@ -5737,7 +5997,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title, local
|
|
|
5737
5997
|
open,
|
|
5738
5998
|
onOpenChange: handleOpenChange,
|
|
5739
5999
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.DialogContent, {
|
|
5740
|
-
className: "
|
|
6000
|
+
className: "max-h-[85vh] overflow-y-auto",
|
|
6001
|
+
style: {
|
|
6002
|
+
width: "calc(100vw - 4rem)",
|
|
6003
|
+
maxWidth: "52rem"
|
|
6004
|
+
},
|
|
5741
6005
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.DialogTitle, { children: title ?? locale.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.DialogDescription, { children: [
|
|
5742
6006
|
step === "upload" && locale.uploadDescription,
|
|
5743
6007
|
step === "preview" && locale.previewDescription(parsedData?.rows.length ?? 0),
|
|
@@ -6686,12 +6950,26 @@ function useDynamicResolveOptions(fields, rows, hiddenColumns) {
|
|
|
6686
6950
|
rows,
|
|
6687
6951
|
sourceEntries
|
|
6688
6952
|
]);
|
|
6689
|
-
|
|
6953
|
+
const displayOptionsByField = { ...optionsByField };
|
|
6954
|
+
for (const field of Object.keys(fields ?? {}).filter((key) => !hiddenColumns.includes(key))) {
|
|
6955
|
+
const projectedOptions = rows.flatMap((row) => {
|
|
6956
|
+
const option = readCrudReferenceOption(row, field, row[field]);
|
|
6957
|
+
return option ? [option] : [];
|
|
6958
|
+
});
|
|
6959
|
+
if (projectedOptions.length > 0) displayOptionsByField[field] = mergeFilterOptions(projectedOptions, optionsByField[field] ?? []);
|
|
6960
|
+
}
|
|
6961
|
+
return { optionsByField: displayOptionsByField };
|
|
6690
6962
|
}
|
|
6691
6963
|
function getOptionLabel(value, options) {
|
|
6692
6964
|
const stringValue = String(value);
|
|
6693
6965
|
return options?.find((option) => option.value === stringValue)?.label ?? stringValue;
|
|
6694
6966
|
}
|
|
6967
|
+
function formatExportRow(row, fields, values = row) {
|
|
6968
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, fields[key]?.format?.(value, {
|
|
6969
|
+
row,
|
|
6970
|
+
target: "export"
|
|
6971
|
+
}) ?? value]));
|
|
6972
|
+
}
|
|
6695
6973
|
/**
|
|
6696
6974
|
* 从统一配置生成表格 overrides
|
|
6697
6975
|
* 当 filter 配置存在时,合并到 meta 中(不影响列隐藏)
|
|
@@ -6788,10 +7066,16 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
|
|
|
6788
7066
|
const options = tableConfig?.dataSource ? mergeFieldOptions(dynamicResolveOptions, presentationOptions) : presentationOptions ?? mergedSharedDynamicOptions;
|
|
6789
7067
|
result[key] = {
|
|
6790
7068
|
...result[key],
|
|
6791
|
-
cell: ({ row }) =>
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
7069
|
+
cell: ({ row, getValue }) => {
|
|
7070
|
+
const value = getValue();
|
|
7071
|
+
return config.format?.(value, {
|
|
7072
|
+
row: row.original,
|
|
7073
|
+
target: "display"
|
|
7074
|
+
}) ?? renderFieldValue(value, "string", {
|
|
7075
|
+
true: "true",
|
|
7076
|
+
false: "false"
|
|
7077
|
+
}, options, display ?? "auto");
|
|
7078
|
+
}
|
|
6795
7079
|
};
|
|
6796
7080
|
}
|
|
6797
7081
|
}
|
|
@@ -7008,7 +7292,13 @@ function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: f
|
|
|
7008
7292
|
overrides[key] = {
|
|
7009
7293
|
label: tableConfig?.label ?? config.label ?? listOverride?.label ?? humanize(key),
|
|
7010
7294
|
index: tableConfig?.index ?? listOverride?.index,
|
|
7011
|
-
cell: ({ getValue }) =>
|
|
7295
|
+
cell: ({ getValue, row }) => {
|
|
7296
|
+
const value = getValue();
|
|
7297
|
+
return config.format?.(value, {
|
|
7298
|
+
row: row.original,
|
|
7299
|
+
target: "display"
|
|
7300
|
+
}) ?? renderFieldValue(value, parseZodField(fieldSchema).type, locale.boolean, options, tableConfig?.display ?? "auto", Infinity);
|
|
7301
|
+
},
|
|
7012
7302
|
...view?.presentation === "table" ? listOverride : void 0,
|
|
7013
7303
|
hidden: false,
|
|
7014
7304
|
...view?.overrides?.[key]
|
|
@@ -7040,18 +7330,18 @@ function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: f
|
|
|
7040
7330
|
})]
|
|
7041
7331
|
}, cell.id))
|
|
7042
7332
|
});
|
|
7043
|
-
if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7333
|
+
if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.Sheet, {
|
|
7044
7334
|
open,
|
|
7045
7335
|
onOpenChange,
|
|
7046
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
7336
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.SheetTitle, { children: locale.viewModal.title }) }), content] })
|
|
7047
7337
|
});
|
|
7048
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7338
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.Dialog, {
|
|
7049
7339
|
open,
|
|
7050
7340
|
onOpenChange,
|
|
7051
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
7341
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.DialogContent, {
|
|
7052
7342
|
"aria-describedby": void 0,
|
|
7053
7343
|
className: "max-w-2xl max-h-[80vh] overflow-y-auto",
|
|
7054
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7344
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.DialogTitle, { children: locale.viewModal.title }) }), content]
|
|
7055
7345
|
})
|
|
7056
7346
|
});
|
|
7057
7347
|
}
|
|
@@ -7115,6 +7405,9 @@ function resolveActions(actions, defaults, rowActionsLocale, context) {
|
|
|
7115
7405
|
*/
|
|
7116
7406
|
function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, view: viewConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate }) {
|
|
7117
7407
|
const locale = resolveLocale(localeProp);
|
|
7408
|
+
const getPagination = react.useCallback(() => id ? tablePagination.get(id) : void 0, [id]);
|
|
7409
|
+
const registeredPagination = react.useSyncExternalStore(tablePagination.subscribe, getPagination, getPagination);
|
|
7410
|
+
const pagination = tableConfig?.pagination ?? registeredPagination;
|
|
7118
7411
|
const resolvedSchema = resource.schema ?? schema;
|
|
7119
7412
|
const resolvedFields = react.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
|
|
7120
7413
|
const can = {
|
|
@@ -7187,13 +7480,13 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7187
7480
|
if (mode === "selected") {
|
|
7188
7481
|
const selectedRows$1 = getSelectedRowsRef.current?.();
|
|
7189
7482
|
if (!selectedRows$1 || selectedRows$1.length === 0) return;
|
|
7190
|
-
exportAllToCSV(selectedRows$1, {
|
|
7483
|
+
exportAllToCSV(selectedRows$1.map((row) => formatExportRow(row, resolvedFields)), {
|
|
7191
7484
|
filename,
|
|
7192
7485
|
excludeColumns
|
|
7193
7486
|
});
|
|
7194
7487
|
} else {
|
|
7195
7488
|
if (!resource.handlers.export) return;
|
|
7196
|
-
exportAllToCSV(await resource.handlers.export(), {
|
|
7489
|
+
exportAllToCSV((await resource.handlers.export()).map((row) => formatExportRow(row, resolvedFields)), {
|
|
7197
7490
|
filename,
|
|
7198
7491
|
excludeColumns
|
|
7199
7492
|
});
|
|
@@ -7201,7 +7494,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7201
7494
|
}, [
|
|
7202
7495
|
resource.handlers.export,
|
|
7203
7496
|
title,
|
|
7204
|
-
denyFields
|
|
7497
|
+
denyFields,
|
|
7498
|
+
resolvedFields
|
|
7205
7499
|
]);
|
|
7206
7500
|
const handleExportClick = react.useCallback(async () => {
|
|
7207
7501
|
const mode = selectedCount > 0 ? "selected" : "filtered";
|
|
@@ -7212,6 +7506,26 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7212
7506
|
setExporting(false);
|
|
7213
7507
|
}
|
|
7214
7508
|
}, [selectedCount, handleExport]);
|
|
7509
|
+
const exportBatchActions = react.useMemo(() => {
|
|
7510
|
+
if (!Object.values(resolvedFields).some((field) => field.format)) return registryBatchActions;
|
|
7511
|
+
return registryBatchActions.map((action$1) => {
|
|
7512
|
+
if (action$1.type !== "export" || action$1.onClick !== void 0 || Boolean(action$1.component)) return action$1;
|
|
7513
|
+
return {
|
|
7514
|
+
...action$1,
|
|
7515
|
+
onClick: (_rows, { table }) => {
|
|
7516
|
+
const headers = table.getAllLeafColumns().map((column) => column.id).filter((key) => key !== "select" && key !== "actions" && !denyFields?.includes(key));
|
|
7517
|
+
exportAllToCSV(table.getFilteredSelectedRowModel().rows.map((row) => formatExportRow(row.original, resolvedFields, Object.fromEntries(headers.map((key) => [key, row.getValue(key)])))), {
|
|
7518
|
+
filename: "table",
|
|
7519
|
+
headers
|
|
7520
|
+
});
|
|
7521
|
+
}
|
|
7522
|
+
};
|
|
7523
|
+
});
|
|
7524
|
+
}, [
|
|
7525
|
+
registryBatchActions,
|
|
7526
|
+
resolvedFields,
|
|
7527
|
+
denyFields
|
|
7528
|
+
]);
|
|
7215
7529
|
const toolbarRefresh = react.useMemo(() => {
|
|
7216
7530
|
const refresh = ownerRefreshAction?.onClick ?? resource.handlers.refresh;
|
|
7217
7531
|
if (!refresh) return void 0;
|
|
@@ -7265,7 +7579,30 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7265
7579
|
toolbarOpenCreate
|
|
7266
7580
|
]);
|
|
7267
7581
|
const resolvedToolbarActions = resolveToolbarActionsWithResolver(id, registryToolbarActions, toolbarContext);
|
|
7268
|
-
const tableOverrides = react.useMemo(() =>
|
|
7582
|
+
const { tableOverrides, detailTableOverrides } = react.useMemo(() => {
|
|
7583
|
+
const presentationOverrides = mergeTableOverrides(buildTableOverrides(resolvedFields, tableConfig?.overrides, dynamicFilterOptions, dynamicResolveOptions), buildCapabilityTableOverrides(resolvedSchema, resource.capabilities));
|
|
7584
|
+
const formattedOverrides = { ...presentationOverrides };
|
|
7585
|
+
for (const [key, config] of Object.entries(resolvedFields)) {
|
|
7586
|
+
const override = formattedOverrides[key];
|
|
7587
|
+
if (config.format && override?.cell === void 0 && resolvedSchema.shape[key]) {
|
|
7588
|
+
const { type } = parseZodField(resolvedSchema.shape[key]);
|
|
7589
|
+
formattedOverrides[key] = {
|
|
7590
|
+
...override,
|
|
7591
|
+
cell: (context) => {
|
|
7592
|
+
const value = context.getValue();
|
|
7593
|
+
return config.format?.(value, {
|
|
7594
|
+
row: context.row.original,
|
|
7595
|
+
target: "display"
|
|
7596
|
+
}) ?? renderCell(value, type, context.column.columnDef.meta?.options);
|
|
7597
|
+
}
|
|
7598
|
+
};
|
|
7599
|
+
}
|
|
7600
|
+
}
|
|
7601
|
+
return {
|
|
7602
|
+
tableOverrides: formattedOverrides,
|
|
7603
|
+
detailTableOverrides: presentationOverrides
|
|
7604
|
+
};
|
|
7605
|
+
}, [
|
|
7269
7606
|
resolvedFields,
|
|
7270
7607
|
tableConfig?.overrides,
|
|
7271
7608
|
dynamicFilterOptions,
|
|
@@ -7431,6 +7768,10 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7431
7768
|
data: resource.tableData.data,
|
|
7432
7769
|
schema: resolvedSchema,
|
|
7433
7770
|
pageCount: resource.tableData.pageCount,
|
|
7771
|
+
pagination: pagination ? {
|
|
7772
|
+
pageJumpLabel: locale.pagination?.pageJump,
|
|
7773
|
+
...pagination
|
|
7774
|
+
} : void 0,
|
|
7434
7775
|
...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
|
|
7435
7776
|
overrides: tableOverrides,
|
|
7436
7777
|
classNames: tableConfig?.classNames,
|
|
@@ -7441,7 +7782,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7441
7782
|
onDeleteSelected: can.delete ? resource.handlers.deleteMany : void 0,
|
|
7442
7783
|
onUpdateSelected: can.update ? resource.handlers.updateMany : void 0,
|
|
7443
7784
|
batchUpdateFields: can.update ? batchFields : void 0,
|
|
7444
|
-
actionBarActions:
|
|
7785
|
+
actionBarActions: exportBatchActions,
|
|
7445
7786
|
deleteConfirmation: locale.bulkDeleteModal,
|
|
7446
7787
|
enableExport: canExport,
|
|
7447
7788
|
showDefaultExport: false,
|
|
@@ -7478,13 +7819,13 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7478
7819
|
dynamicOptions: dynamicFilterOptions.labelOptionsByField,
|
|
7479
7820
|
denyFields,
|
|
7480
7821
|
locale,
|
|
7481
|
-
tableOverrides,
|
|
7822
|
+
tableOverrides: detailTableOverrides,
|
|
7482
7823
|
view: viewConfig
|
|
7483
7824
|
}),
|
|
7484
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7825
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialog, {
|
|
7485
7826
|
open: resource.modal.deleteOpen,
|
|
7486
7827
|
onOpenChange: (open) => !open && resource.handlers.closeModals(),
|
|
7487
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
7828
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.AlertDialogContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.AlertDialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialogTitle, { children: locale.deleteModal.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialogDescription, { children: locale.deleteModal.description })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.AlertDialogFooter, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialogCancel, { children: locale.deleteModal.cancel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialogAction, {
|
|
7488
7829
|
onClick: resource.handlers.confirmDelete,
|
|
7489
7830
|
disabled: resource.mutations.isDeleting,
|
|
7490
7831
|
children: resource.mutations.isDeleting ? locale.deleteModal.confirming : locale.deleteModal.confirm
|
|
@@ -7687,6 +8028,9 @@ function parseColumnFilterValue(value) {
|
|
|
7687
8028
|
return [];
|
|
7688
8029
|
}
|
|
7689
8030
|
function DataTableDateFilter({ column, title, multiple }) {
|
|
8031
|
+
const today = useCalendarToday();
|
|
8032
|
+
const maxDate = column.columnDef.meta?.maxDate;
|
|
8033
|
+
const upperBound = maxDate === "today" ? today : calendarMaxDate(maxDate);
|
|
7690
8034
|
const formatterVersion = useDateFormatterVersion();
|
|
7691
8035
|
const presentation = react.useMemo(() => calendarPresentation(), [formatterVersion]);
|
|
7692
8036
|
const { formatDate: formatDate$1 } = presentation;
|
|
@@ -7840,6 +8184,8 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7840
8184
|
className: "w-auto p-0",
|
|
7841
8185
|
align: "start",
|
|
7842
8186
|
children: multiple ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
8187
|
+
today,
|
|
8188
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
7843
8189
|
lang: presentation.locale,
|
|
7844
8190
|
weekStartsOn: presentation.weekStartsOn,
|
|
7845
8191
|
formatters: presentation.formatters,
|
|
@@ -7847,10 +8193,13 @@ function DataTableDateFilter({ column, title, multiple }) {
|
|
|
7847
8193
|
autoFocus: true,
|
|
7848
8194
|
captionLayout: "dropdown",
|
|
7849
8195
|
mode: "range",
|
|
8196
|
+
excludeDisabled: !!upperBound,
|
|
7850
8197
|
defaultMonth: localRange.from,
|
|
7851
8198
|
selected: localRange,
|
|
7852
8199
|
onSelect
|
|
7853
8200
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Calendar, {
|
|
8201
|
+
today,
|
|
8202
|
+
disabled: upperBound ? { after: upperBound } : void 0,
|
|
7854
8203
|
lang: presentation.locale,
|
|
7855
8204
|
weekStartsOn: presentation.weekStartsOn,
|
|
7856
8205
|
formatters: presentation.formatters,
|
|
@@ -8968,6 +9317,7 @@ exports.resolveLocale = resolveLocale;
|
|
|
8968
9317
|
exports.setDateFormatter = setDateFormatter;
|
|
8969
9318
|
exports.setSearchParams = setSearchParams;
|
|
8970
9319
|
exports.setToolbarResolver = setToolbarResolver;
|
|
9320
|
+
exports.tablePagination = tablePagination;
|
|
8971
9321
|
exports.useAutoCrudResource = useAutoCrudResource;
|
|
8972
9322
|
exports.useDataTable = useDataTable;
|
|
8973
9323
|
exports.useQueryState = useQueryState;
|