@wordrhyme/auto-crud 1.14.2 → 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 +2 -0
- package/dist/index.cjs +60 -18
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +60 -18
- package/package.json +3 -3
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()`
|
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) {
|
package/dist/index.d.cts
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.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) {
|
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/prettier-config": "0.0.1",
|
|
98
99
|
"@internal/tsconfig": "0.1.0",
|
|
99
|
-
"@internal/tsdown-config": "0.1.0",
|
|
100
100
|
"@internal/vitest-config": "0.1.0",
|
|
101
|
-
"@internal/
|
|
101
|
+
"@internal/tsdown-config": "0.1.0"
|
|
102
102
|
},
|
|
103
103
|
"prettier": "@internal/prettier-config",
|
|
104
104
|
"scripts": {
|