@wordrhyme/auto-crud 1.14.1 → 1.14.3
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 +4 -0
- package/dist/index.cjs +64 -27
- package/dist/index.d.cts +19 -19
- package/dist/index.d.ts +3 -3
- package/dist/index.js +64 -27
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -357,6 +357,8 @@ const resource = useAutoCrudResource({
|
|
|
357
357
|
|
|
358
358
|
未配置的参数名保留默认值。搜索仍使用共享的 `search` 参数,字段筛选仍使用字段名;`queryKeys` 不隔离这些值。筛选或搜索变化时,仅重置该表格对应的页码。直接使用 `AutoTable` 时传入相同的 `queryKeys`;`table.queryKeys` 可覆盖资源提供的整组配置。
|
|
359
359
|
|
|
360
|
+
全局搜索输入立即显示,停止输入 200ms 后提交查询并回到第一页;清空立即提交,中文输入法组词期间不查询。可以通过 `table.search: { debounceMs: 0 }` 恢复即时查询,或指定其他延时;直接使用 `AutoTable` 时配置 `search.debounceMs`。浏览器导航或其他 URL 状态变化会取消尚未提交的搜索,并按 URL 恢复输入框。
|
|
361
|
+
|
|
360
362
|
`enableRowSelection` 默认 `true`,设为 `false` 后关闭行选择并隐藏选择列和批量操作栏。`initialColumnVisibility` 只设置首次显示的列,用户仍可通过列设置切换;它不同于 `table.hidden` 对列的排除。
|
|
361
363
|
|
|
362
364
|
### `useAutoCrudResource()`
|
|
@@ -1788,6 +1790,8 @@ does not control detail layout, even with `view.presentation: 'table'`.
|
|
|
1788
1790
|
`view.overrides[field].index` takes precedence for detail-only ordering. Fields
|
|
1789
1791
|
hidden only in forms remain available in details; use detail ordering to place
|
|
1790
1792
|
read-only business fields next to related information or audit fields at the end.
|
|
1793
|
+
Field spans come from the shared form configuration; details do not expand arrays,
|
|
1794
|
+
objects or long-text fields to a full row automatically.
|
|
1791
1795
|
|
|
1792
1796
|
```tsx
|
|
1793
1797
|
<AutoCrudTable
|
package/dist/index.cjs
CHANGED
|
@@ -1166,11 +1166,15 @@ function useCallbackRef(callback) {
|
|
|
1166
1166
|
function useDebouncedCallback(callback, delay) {
|
|
1167
1167
|
const handleCallback = useCallbackRef(callback);
|
|
1168
1168
|
const debounceTimerRef = react.useRef(0);
|
|
1169
|
-
react.
|
|
1170
|
-
|
|
1169
|
+
const cancel = react.useCallback(() => {
|
|
1170
|
+
window.clearTimeout(debounceTimerRef.current);
|
|
1171
|
+
}, []);
|
|
1172
|
+
react.useEffect(() => cancel, [cancel, delay]);
|
|
1173
|
+
const setValue = react.useCallback((...args) => {
|
|
1171
1174
|
window.clearTimeout(debounceTimerRef.current);
|
|
1172
1175
|
debounceTimerRef.current = window.setTimeout(() => handleCallback(...args), delay);
|
|
1173
1176
|
}, [handleCallback, delay]);
|
|
1177
|
+
return Object.assign(setValue, { cancel });
|
|
1174
1178
|
}
|
|
1175
1179
|
|
|
1176
1180
|
//#endregion
|
|
@@ -4015,6 +4019,57 @@ function SimpleDateFilter({ title, maxDate, multiple, value, onChange }) {
|
|
|
4015
4019
|
});
|
|
4016
4020
|
}
|
|
4017
4021
|
|
|
4022
|
+
//#endregion
|
|
4023
|
+
//#region src/components/auto-crud/auto-table-search.tsx
|
|
4024
|
+
function AutoTableSearch({ placeholder = "搜索", debounceMs = 200, pageKey = "page" }) {
|
|
4025
|
+
const [value, setValue] = (0, react.useState)(() => getUrlParams().get("search") ?? "");
|
|
4026
|
+
const composing = (0, react.useRef)(false);
|
|
4027
|
+
const commit = (0, react.useCallback)((next) => {
|
|
4028
|
+
const params = getUrlParams();
|
|
4029
|
+
if ((params.get("search") ?? "") === next) return;
|
|
4030
|
+
if (next) params.set("search", next);
|
|
4031
|
+
else params.delete("search");
|
|
4032
|
+
params.delete(pageKey);
|
|
4033
|
+
setSearchParams(params);
|
|
4034
|
+
}, [pageKey]);
|
|
4035
|
+
const debouncedCommit = useDebouncedCallback(commit, debounceMs);
|
|
4036
|
+
const { cancel } = debouncedCommit;
|
|
4037
|
+
(0, react.useEffect)(() => {
|
|
4038
|
+
const sync = () => {
|
|
4039
|
+
cancel();
|
|
4040
|
+
setValue(getUrlParams().get("search") ?? "");
|
|
4041
|
+
};
|
|
4042
|
+
window.addEventListener("popstate", sync);
|
|
4043
|
+
window.addEventListener("urlchange", sync);
|
|
4044
|
+
return () => {
|
|
4045
|
+
cancel();
|
|
4046
|
+
window.removeEventListener("popstate", sync);
|
|
4047
|
+
window.removeEventListener("urlchange", sync);
|
|
4048
|
+
};
|
|
4049
|
+
}, [cancel, pageKey]);
|
|
4050
|
+
const change = (next) => {
|
|
4051
|
+
setValue(next);
|
|
4052
|
+
cancel();
|
|
4053
|
+
if (composing.current) return;
|
|
4054
|
+
if (!next || debounceMs <= 0) commit(next);
|
|
4055
|
+
else debouncedCommit(next);
|
|
4056
|
+
};
|
|
4057
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Input, {
|
|
4058
|
+
value,
|
|
4059
|
+
onChange: (event) => change(event.target.value),
|
|
4060
|
+
onCompositionStart: () => {
|
|
4061
|
+
composing.current = true;
|
|
4062
|
+
cancel();
|
|
4063
|
+
},
|
|
4064
|
+
onCompositionEnd: (event) => {
|
|
4065
|
+
composing.current = false;
|
|
4066
|
+
change(event.currentTarget.value);
|
|
4067
|
+
},
|
|
4068
|
+
placeholder,
|
|
4069
|
+
className: "h-8 w-48 shrink-0"
|
|
4070
|
+
});
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4018
4073
|
//#endregion
|
|
4019
4074
|
//#region src/components/data-table/data-table-column-header.tsx
|
|
4020
4075
|
function DataTableColumnHeader({ column, label, className,...props }) {
|
|
@@ -5194,14 +5249,6 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5194
5249
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
5195
5250
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
5196
5251
|
const showToggle = modes.length > 1;
|
|
5197
|
-
const [searchValue, setSearchValue] = useUrlState("search", parseAsString.withDefault(""), {
|
|
5198
|
-
shallow: false,
|
|
5199
|
-
clearOnDefault: true
|
|
5200
|
-
});
|
|
5201
|
-
const [, setSearchPage] = useUrlState(queryKeys?.page ?? "page", parseAsInteger.withDefault(1), {
|
|
5202
|
-
shallow: false,
|
|
5203
|
-
clearOnDefault: true
|
|
5204
|
-
});
|
|
5205
5252
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
5206
5253
|
const enableAdvancedFilter = true;
|
|
5207
5254
|
const { columns, expandColumnId } = (0, react.useMemo)(() => {
|
|
@@ -5363,14 +5410,9 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5363
5410
|
})
|
|
5364
5411
|
})
|
|
5365
5412
|
})] }) : null;
|
|
5366
|
-
const searchInput = search ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
setSearchValue(event.target.value);
|
|
5370
|
-
setSearchPage(1);
|
|
5371
|
-
},
|
|
5372
|
-
placeholder: searchConfig.placeholder ?? "搜索",
|
|
5373
|
-
className: "h-8 w-48 shrink-0"
|
|
5413
|
+
const searchInput = search ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTableSearch, {
|
|
5414
|
+
...searchConfig,
|
|
5415
|
+
pageKey: queryKeys?.page
|
|
5374
5416
|
}) : null;
|
|
5375
5417
|
const filtersContent = (0, react.useMemo)(() => {
|
|
5376
5418
|
switch (currentMode) {
|
|
@@ -6268,15 +6310,10 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, fields, ove
|
|
|
6268
6310
|
className: (0, __wordrhyme_shadcn.cn)(grid["x-component-props"]?.className, "gap-x-10 gap-y-7 py-2")
|
|
6269
6311
|
};
|
|
6270
6312
|
const properties = typeof grid.properties === "object" ? grid.properties : {};
|
|
6271
|
-
for (const property of Object.values(properties)) {
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
colon: false,
|
|
6276
|
-
...decoratorProps,
|
|
6277
|
-
className: (0, __wordrhyme_shadcn.cn)(fullWidth && decoratorProps?.gridSpan == null && "col-span-full", decoratorProps?.className)
|
|
6278
|
-
};
|
|
6279
|
-
}
|
|
6313
|
+
for (const property of Object.values(properties)) property["x-decorator-props"] = {
|
|
6314
|
+
colon: false,
|
|
6315
|
+
...property["x-decorator-props"]
|
|
6316
|
+
};
|
|
6280
6317
|
}
|
|
6281
6318
|
applyDataSourceReactions(nextSchema, mode === "view");
|
|
6282
6319
|
return nextSchema;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as positionActions, i as matchesPosition, n as actionPositionSchema, r as compareOrder, t as ActionPosition } from "./position-DoBV7yB6.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime8 from "react/jsx-runtime";
|
|
3
3
|
import * as React$1 from "react";
|
|
4
4
|
import { ComponentProps, ReactNode } from "react";
|
|
5
5
|
import * as _tanstack_react_table0 from "@tanstack/react-table";
|
|
@@ -676,7 +676,7 @@ declare function DataTable<TData>({
|
|
|
676
676
|
className,
|
|
677
677
|
classNames,
|
|
678
678
|
...props
|
|
679
|
-
}: DataTableProps<TData>):
|
|
679
|
+
}: DataTableProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
680
680
|
//#endregion
|
|
681
681
|
//#region src/components/auto-crud/auto-table-action-bar.d.ts
|
|
682
682
|
/** 批量更新字段配置 */
|
|
@@ -765,7 +765,7 @@ declare function AutoTableActionBar<TData>({
|
|
|
765
765
|
extraActions,
|
|
766
766
|
actions,
|
|
767
767
|
deleteConfirmation
|
|
768
|
-
}: AutoTableActionBarProps<TData>):
|
|
768
|
+
}: AutoTableActionBarProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
769
769
|
//#endregion
|
|
770
770
|
//#region src/lib/schema-bridge/types.d.ts
|
|
771
771
|
/**
|
|
@@ -1042,6 +1042,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> extends Pick<Data
|
|
|
1042
1042
|
/** 全局搜索框 */
|
|
1043
1043
|
search?: boolean | {
|
|
1044
1044
|
placeholder?: string;
|
|
1045
|
+
/** Search delay in milliseconds. Defaults to 200; use 0 for immediate queries. */
|
|
1046
|
+
debounceMs?: number;
|
|
1045
1047
|
};
|
|
1046
1048
|
/** Extra table controls rendered between sorting and column visibility. */
|
|
1047
1049
|
toolbarExtra?: React.ReactNode;
|
|
@@ -1109,7 +1111,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1109
1111
|
onSelectedRowsChange,
|
|
1110
1112
|
getSelectedRows,
|
|
1111
1113
|
exportTableRef
|
|
1112
|
-
}: AutoTableProps<T>):
|
|
1114
|
+
}: AutoTableProps<T>): react_jsx_runtime8.JSX.Element;
|
|
1113
1115
|
//#endregion
|
|
1114
1116
|
//#region src/components/auto-crud/auto-form.d.ts
|
|
1115
1117
|
type AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> = {
|
|
@@ -1152,7 +1154,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1152
1154
|
labelAlign,
|
|
1153
1155
|
labelWidth,
|
|
1154
1156
|
showSubmitButton
|
|
1155
|
-
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>):
|
|
1157
|
+
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime8.JSX.Element;
|
|
1156
1158
|
declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
|
|
1157
1159
|
ref?: React.Ref<AutoFormRef>;
|
|
1158
1160
|
}) => ReturnType<typeof AutoFormInner>;
|
|
@@ -1515,9 +1517,7 @@ interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
|
|
|
1515
1517
|
*/
|
|
1516
1518
|
filterModes?: FilterMode | FilterMode[];
|
|
1517
1519
|
/** 全局搜索框;默认在存在 search: true 字段时显示 */
|
|
1518
|
-
search?:
|
|
1519
|
-
placeholder?: string;
|
|
1520
|
-
};
|
|
1520
|
+
search?: AutoTableProps<TSchema>['search'];
|
|
1521
1521
|
/**
|
|
1522
1522
|
* 批量更新字段配置
|
|
1523
1523
|
* - 只需传字段名数组,options 自动从 schema enum 推导
|
|
@@ -1622,7 +1622,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1622
1622
|
locale: localeProp,
|
|
1623
1623
|
onCreate,
|
|
1624
1624
|
onExport
|
|
1625
|
-
}: AutoCrudTableProps<TSchema>):
|
|
1625
|
+
}: AutoCrudTableProps<TSchema>): react_jsx_runtime8.JSX.Element;
|
|
1626
1626
|
//#endregion
|
|
1627
1627
|
//#region src/components/auto-crud/auto-table-simple-filters.d.ts
|
|
1628
1628
|
interface AutoTableSimpleFiltersProps<TData> {
|
|
@@ -1638,7 +1638,7 @@ declare function AutoTableSimpleFilters<TData>({
|
|
|
1638
1638
|
filters: externalFilters,
|
|
1639
1639
|
onFiltersChange,
|
|
1640
1640
|
leading
|
|
1641
|
-
}: AutoTableSimpleFiltersProps<TData>):
|
|
1641
|
+
}: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime8.JSX.Element | null;
|
|
1642
1642
|
//#endregion
|
|
1643
1643
|
//#region src/components/auto-crud/form-modal.d.ts
|
|
1644
1644
|
type ModalVariant = 'dialog' | 'sheet';
|
|
@@ -1687,7 +1687,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1687
1687
|
labelAlign,
|
|
1688
1688
|
labelWidth,
|
|
1689
1689
|
className
|
|
1690
|
-
}: CrudFormModalProps<T> & CrudFormModalMode<T>):
|
|
1690
|
+
}: CrudFormModalProps<T> & CrudFormModalMode<T>): react_jsx_runtime8.JSX.Element;
|
|
1691
1691
|
//#endregion
|
|
1692
1692
|
//#region src/components/auto-crud/import-dialog.d.ts
|
|
1693
1693
|
interface ImportDialogProps {
|
|
@@ -1709,7 +1709,7 @@ declare function ImportDialog({
|
|
|
1709
1709
|
columns,
|
|
1710
1710
|
title,
|
|
1711
1711
|
locale
|
|
1712
|
-
}: ImportDialogProps):
|
|
1712
|
+
}: ImportDialogProps): react_jsx_runtime8.JSX.Element;
|
|
1713
1713
|
//#endregion
|
|
1714
1714
|
//#region src/components/auto-crud/export-dialog.d.ts
|
|
1715
1715
|
type ExportMode = 'selected' | 'filtered';
|
|
@@ -1729,7 +1729,7 @@ declare function ExportDialog({
|
|
|
1729
1729
|
selectedCount,
|
|
1730
1730
|
onExport,
|
|
1731
1731
|
canExportFiltered
|
|
1732
|
-
}: ExportDialogProps):
|
|
1732
|
+
}: ExportDialogProps): react_jsx_runtime8.JSX.Element;
|
|
1733
1733
|
//#endregion
|
|
1734
1734
|
//#region src/components/data-table/data-table-advanced-toolbar.d.ts
|
|
1735
1735
|
interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<'div'> {
|
|
@@ -1740,7 +1740,7 @@ declare function DataTableAdvancedToolbar<TData>({
|
|
|
1740
1740
|
children,
|
|
1741
1741
|
className,
|
|
1742
1742
|
...props
|
|
1743
|
-
}: DataTableAdvancedToolbarProps<TData>):
|
|
1743
|
+
}: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
1744
1744
|
//#endregion
|
|
1745
1745
|
//#region src/components/data-table/data-table-column-header.d.ts
|
|
1746
1746
|
interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
|
|
@@ -1752,7 +1752,7 @@ declare function DataTableColumnHeader<TData, TValue>({
|
|
|
1752
1752
|
label,
|
|
1753
1753
|
className,
|
|
1754
1754
|
...props
|
|
1755
|
-
}: DataTableColumnHeaderProps<TData, TValue>):
|
|
1755
|
+
}: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime8.JSX.Element;
|
|
1756
1756
|
//#endregion
|
|
1757
1757
|
//#region src/components/data-table/data-table-faceted-filter.d.ts
|
|
1758
1758
|
interface DataTableFacetedFilterProps<TData, TValue> {
|
|
@@ -1766,7 +1766,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
|
|
|
1766
1766
|
title,
|
|
1767
1767
|
options,
|
|
1768
1768
|
multiple
|
|
1769
|
-
}: DataTableFacetedFilterProps<TData, TValue>):
|
|
1769
|
+
}: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime8.JSX.Element;
|
|
1770
1770
|
//#endregion
|
|
1771
1771
|
//#region src/components/data-table/data-table-pagination.d.ts
|
|
1772
1772
|
interface DataTablePaginationProps<TData> extends React.ComponentProps<'div'>, TablePaginationOptions {
|
|
@@ -1782,7 +1782,7 @@ declare function DataTablePagination<TData>({
|
|
|
1782
1782
|
pageJumpLabel,
|
|
1783
1783
|
className,
|
|
1784
1784
|
...props
|
|
1785
|
-
}: DataTablePaginationProps<TData>):
|
|
1785
|
+
}: DataTablePaginationProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
1786
1786
|
//#endregion
|
|
1787
1787
|
//#region src/components/data-table/data-table-toolbar.d.ts
|
|
1788
1788
|
interface DataTableToolbarProps<TData> extends React$1.ComponentProps<'div'> {
|
|
@@ -1793,7 +1793,7 @@ declare function DataTableToolbar<TData>({
|
|
|
1793
1793
|
children,
|
|
1794
1794
|
className,
|
|
1795
1795
|
...props
|
|
1796
|
-
}: DataTableToolbarProps<TData>):
|
|
1796
|
+
}: DataTableToolbarProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
1797
1797
|
//#endregion
|
|
1798
1798
|
//#region src/components/data-table/data-table-view-options.d.ts
|
|
1799
1799
|
interface DataTableViewOptionsProps<TData> extends PopoverContentProps {
|
|
@@ -1806,7 +1806,7 @@ declare function DataTableViewOptions<TData>({
|
|
|
1806
1806
|
disabled,
|
|
1807
1807
|
locale,
|
|
1808
1808
|
...props
|
|
1809
|
-
}: DataTableViewOptionsProps<TData>):
|
|
1809
|
+
}: DataTableViewOptionsProps<TData>): react_jsx_runtime8.JSX.Element;
|
|
1810
1810
|
//#endregion
|
|
1811
1811
|
//#region src/lib/crud-actions.d.ts
|
|
1812
1812
|
type CrudActionZone = 'toolbar' | 'row' | 'batch';
|
package/dist/index.d.ts
CHANGED
|
@@ -1042,6 +1042,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> extends Pick<Data
|
|
|
1042
1042
|
/** 全局搜索框 */
|
|
1043
1043
|
search?: boolean | {
|
|
1044
1044
|
placeholder?: string;
|
|
1045
|
+
/** Search delay in milliseconds. Defaults to 200; use 0 for immediate queries. */
|
|
1046
|
+
debounceMs?: number;
|
|
1045
1047
|
};
|
|
1046
1048
|
/** Extra table controls rendered between sorting and column visibility. */
|
|
1047
1049
|
toolbarExtra?: React.ReactNode;
|
|
@@ -1515,9 +1517,7 @@ interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
|
|
|
1515
1517
|
*/
|
|
1516
1518
|
filterModes?: FilterMode | FilterMode[];
|
|
1517
1519
|
/** 全局搜索框;默认在存在 search: true 字段时显示 */
|
|
1518
|
-
search?:
|
|
1519
|
-
placeholder?: string;
|
|
1520
|
-
};
|
|
1520
|
+
search?: AutoTableProps<TSchema>['search'];
|
|
1521
1521
|
/**
|
|
1522
1522
|
* 批量更新字段配置
|
|
1523
1523
|
* - 只需传字段名数组,options 自动从 schema enum 推导
|
package/dist/index.js
CHANGED
|
@@ -1150,11 +1150,15 @@ function useCallbackRef(callback) {
|
|
|
1150
1150
|
function useDebouncedCallback(callback, delay) {
|
|
1151
1151
|
const handleCallback = useCallbackRef(callback);
|
|
1152
1152
|
const debounceTimerRef = React.useRef(0);
|
|
1153
|
-
React.
|
|
1154
|
-
|
|
1153
|
+
const cancel = React.useCallback(() => {
|
|
1154
|
+
window.clearTimeout(debounceTimerRef.current);
|
|
1155
|
+
}, []);
|
|
1156
|
+
React.useEffect(() => cancel, [cancel, delay]);
|
|
1157
|
+
const setValue = React.useCallback((...args) => {
|
|
1155
1158
|
window.clearTimeout(debounceTimerRef.current);
|
|
1156
1159
|
debounceTimerRef.current = window.setTimeout(() => handleCallback(...args), delay);
|
|
1157
1160
|
}, [handleCallback, delay]);
|
|
1161
|
+
return Object.assign(setValue, { cancel });
|
|
1158
1162
|
}
|
|
1159
1163
|
|
|
1160
1164
|
//#endregion
|
|
@@ -3999,6 +4003,57 @@ function SimpleDateFilter({ title, maxDate, multiple, value, onChange }) {
|
|
|
3999
4003
|
});
|
|
4000
4004
|
}
|
|
4001
4005
|
|
|
4006
|
+
//#endregion
|
|
4007
|
+
//#region src/components/auto-crud/auto-table-search.tsx
|
|
4008
|
+
function AutoTableSearch({ placeholder = "搜索", debounceMs = 200, pageKey = "page" }) {
|
|
4009
|
+
const [value, setValue] = useState(() => getUrlParams().get("search") ?? "");
|
|
4010
|
+
const composing = useRef(false);
|
|
4011
|
+
const commit = useCallback((next) => {
|
|
4012
|
+
const params = getUrlParams();
|
|
4013
|
+
if ((params.get("search") ?? "") === next) return;
|
|
4014
|
+
if (next) params.set("search", next);
|
|
4015
|
+
else params.delete("search");
|
|
4016
|
+
params.delete(pageKey);
|
|
4017
|
+
setSearchParams(params);
|
|
4018
|
+
}, [pageKey]);
|
|
4019
|
+
const debouncedCommit = useDebouncedCallback(commit, debounceMs);
|
|
4020
|
+
const { cancel } = debouncedCommit;
|
|
4021
|
+
useEffect(() => {
|
|
4022
|
+
const sync = () => {
|
|
4023
|
+
cancel();
|
|
4024
|
+
setValue(getUrlParams().get("search") ?? "");
|
|
4025
|
+
};
|
|
4026
|
+
window.addEventListener("popstate", sync);
|
|
4027
|
+
window.addEventListener("urlchange", sync);
|
|
4028
|
+
return () => {
|
|
4029
|
+
cancel();
|
|
4030
|
+
window.removeEventListener("popstate", sync);
|
|
4031
|
+
window.removeEventListener("urlchange", sync);
|
|
4032
|
+
};
|
|
4033
|
+
}, [cancel, pageKey]);
|
|
4034
|
+
const change = (next) => {
|
|
4035
|
+
setValue(next);
|
|
4036
|
+
cancel();
|
|
4037
|
+
if (composing.current) return;
|
|
4038
|
+
if (!next || debounceMs <= 0) commit(next);
|
|
4039
|
+
else debouncedCommit(next);
|
|
4040
|
+
};
|
|
4041
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
4042
|
+
value,
|
|
4043
|
+
onChange: (event) => change(event.target.value),
|
|
4044
|
+
onCompositionStart: () => {
|
|
4045
|
+
composing.current = true;
|
|
4046
|
+
cancel();
|
|
4047
|
+
},
|
|
4048
|
+
onCompositionEnd: (event) => {
|
|
4049
|
+
composing.current = false;
|
|
4050
|
+
change(event.currentTarget.value);
|
|
4051
|
+
},
|
|
4052
|
+
placeholder,
|
|
4053
|
+
className: "h-8 w-48 shrink-0"
|
|
4054
|
+
});
|
|
4055
|
+
}
|
|
4056
|
+
|
|
4002
4057
|
//#endregion
|
|
4003
4058
|
//#region src/components/data-table/data-table-column-header.tsx
|
|
4004
4059
|
function DataTableColumnHeader({ column, label, className,...props }) {
|
|
@@ -5178,14 +5233,6 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5178
5233
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
5179
5234
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
5180
5235
|
const showToggle = modes.length > 1;
|
|
5181
|
-
const [searchValue, setSearchValue] = useUrlState("search", parseAsString.withDefault(""), {
|
|
5182
|
-
shallow: false,
|
|
5183
|
-
clearOnDefault: true
|
|
5184
|
-
});
|
|
5185
|
-
const [, setSearchPage] = useUrlState(queryKeys?.page ?? "page", parseAsInteger.withDefault(1), {
|
|
5186
|
-
shallow: false,
|
|
5187
|
-
clearOnDefault: true
|
|
5188
|
-
});
|
|
5189
5236
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
5190
5237
|
const enableAdvancedFilter = true;
|
|
5191
5238
|
const { columns, expandColumnId } = useMemo(() => {
|
|
@@ -5347,14 +5394,9 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5347
5394
|
})
|
|
5348
5395
|
})
|
|
5349
5396
|
})] }) : null;
|
|
5350
|
-
const searchInput = search ? /* @__PURE__ */ jsx(
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
setSearchValue(event.target.value);
|
|
5354
|
-
setSearchPage(1);
|
|
5355
|
-
},
|
|
5356
|
-
placeholder: searchConfig.placeholder ?? "搜索",
|
|
5357
|
-
className: "h-8 w-48 shrink-0"
|
|
5397
|
+
const searchInput = search ? /* @__PURE__ */ jsx(AutoTableSearch, {
|
|
5398
|
+
...searchConfig,
|
|
5399
|
+
pageKey: queryKeys?.page
|
|
5358
5400
|
}) : null;
|
|
5359
5401
|
const filtersContent = useMemo(() => {
|
|
5360
5402
|
switch (currentMode) {
|
|
@@ -6252,15 +6294,10 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, fields, ove
|
|
|
6252
6294
|
className: cn$1(grid["x-component-props"]?.className, "gap-x-10 gap-y-7 py-2")
|
|
6253
6295
|
};
|
|
6254
6296
|
const properties = typeof grid.properties === "object" ? grid.properties : {};
|
|
6255
|
-
for (const property of Object.values(properties)) {
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
colon: false,
|
|
6260
|
-
...decoratorProps,
|
|
6261
|
-
className: cn$1(fullWidth && decoratorProps?.gridSpan == null && "col-span-full", decoratorProps?.className)
|
|
6262
|
-
};
|
|
6263
|
-
}
|
|
6297
|
+
for (const property of Object.values(properties)) property["x-decorator-props"] = {
|
|
6298
|
+
colon: false,
|
|
6299
|
+
...property["x-decorator-props"]
|
|
6300
|
+
};
|
|
6264
6301
|
}
|
|
6265
6302
|
applyDataSourceReactions(nextSchema, mode === "view");
|
|
6266
6303
|
return nextSchema;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordrhyme/auto-crud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.14.
|
|
4
|
+
"version": "1.14.3",
|
|
5
5
|
"description": "Schema-first CRUD components with auto-generated tables and forms",
|
|
6
6
|
"author": "wordrhyme",
|
|
7
7
|
"license": "MIT",
|
|
@@ -95,10 +95,10 @@
|
|
|
95
95
|
"typescript": "^5.9.3",
|
|
96
96
|
"vitest": "^3.2.4",
|
|
97
97
|
"@internal/eslint-config": "0.3.0",
|
|
98
|
-
"@internal/tsconfig": "0.1.0",
|
|
99
98
|
"@internal/prettier-config": "0.0.1",
|
|
100
|
-
"@internal/
|
|
101
|
-
"@internal/vitest-config": "0.1.0"
|
|
99
|
+
"@internal/tsconfig": "0.1.0",
|
|
100
|
+
"@internal/vitest-config": "0.1.0",
|
|
101
|
+
"@internal/tsdown-config": "0.1.0"
|
|
102
102
|
},
|
|
103
103
|
"prettier": "@internal/prettier-config",
|
|
104
104
|
"scripts": {
|