@wordrhyme/auto-crud 1.8.2 → 1.9.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 +33 -0
- package/dist/index.cjs +91 -32
- package/dist/index.d.cts +25 -16
- package/dist/index.d.ts +9 -0
- package/dist/index.js +91 -32
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1651,6 +1651,14 @@ MIT © [wordrhyme](https://github.com/denvey/wordrhyme-components)
|
|
|
1651
1651
|
- [Notion](https://notion.so) - 高级筛选器设计
|
|
1652
1652
|
- [Linear](https://linear.app) - 命令面板设计
|
|
1653
1653
|
|
|
1654
|
+
### Status badge colors
|
|
1655
|
+
|
|
1656
|
+
For `table.display: "badge"`, a scalar field's `table.options` entries may set `badgeTone` to `neutral`, `success`, `warning`, or `info`. This renders a tinted, outlined rounded label with a decorative dot. Labels remain readable without color; omitted tones retain the default badge. `display: "text"` is unaffected. Domain-specific state-to-tone mappings belong in the consuming plugin metadata.
|
|
1657
|
+
|
|
1658
|
+
Registered custom actions may set `before: "delete"` (or another builtin action type) to appear immediately before that action. If the builtin is absent, the existing `position` fallback applies. This only controls ordering and does not add or grant the target action.
|
|
1659
|
+
|
|
1660
|
+
Custom row components receive `MenuItem` in their action context. Use this supplied primitive instead of importing a menu item from another UI bundle: the menu root and item must share the same Radix runtime context. Prevent the select event's default dismissal when the component owns an open dialog, so the menu does not unmount the workflow.
|
|
1661
|
+
|
|
1654
1662
|
### Detail presentation
|
|
1655
1663
|
|
|
1656
1664
|
Details automatically share field labels, `enum`/`dataSource` mappings and
|
|
@@ -1711,6 +1719,31 @@ is pinned to the already-published alpha.19 for reproducible ESM tests and type
|
|
|
1711
1719
|
checks until alpha.20 is published; it is not the supported CommonJS runtime.
|
|
1712
1720
|
The CommonJS export/identity regression belongs to the UI provider repository.
|
|
1713
1721
|
|
|
1722
|
+
### Filter-only fields
|
|
1723
|
+
|
|
1724
|
+
Use `table: false` with an explicit `filter` to keep a field in the standard
|
|
1725
|
+
filter bar without rendering a data column. Shared `hidden`, permission `deny`,
|
|
1726
|
+
and explicit table exclusions still hide the filter. Pass the same filter
|
|
1727
|
+
configuration to the resource so URL values use the same variants/operators:
|
|
1728
|
+
|
|
1729
|
+
```tsx
|
|
1730
|
+
const fields = {
|
|
1731
|
+
customerId: {
|
|
1732
|
+
label: 'Customer',
|
|
1733
|
+
table: false as const,
|
|
1734
|
+
form: false as const,
|
|
1735
|
+
filter: { variant: 'select' as const, dataSource: 'customers', index: 20 },
|
|
1736
|
+
},
|
|
1737
|
+
};
|
|
1738
|
+
const resource = useAutoCrudResource({ router, schema, fields });
|
|
1739
|
+
return <AutoCrudTable schema={schema} resource={resource} fields={fields} />;
|
|
1740
|
+
```
|
|
1741
|
+
|
|
1742
|
+
The field must exist in the schema or resource metadata, and the server must
|
|
1743
|
+
resolve its filter. A data source loads options; it does not translate query
|
|
1744
|
+
conditions. Standard filters share URL state, Reset, and pagination. Dynamically
|
|
1745
|
+
registered schema fields hydrate existing URL values without resetting the page.
|
|
1746
|
+
|
|
1714
1747
|
### 按 ID 隐藏或替换自定义操作
|
|
1715
1748
|
|
|
1716
1749
|
拥有方为 custom 操作声明稳定 `id` 后,扩展可以在相同 CRUD target 和操作区域
|
package/dist/index.cjs
CHANGED
|
@@ -1012,6 +1012,11 @@ function useReadableFilters(columns, options = {}) {
|
|
|
1012
1012
|
filtersRef.current = initial;
|
|
1013
1013
|
return initial;
|
|
1014
1014
|
});
|
|
1015
|
+
react.useEffect(() => {
|
|
1016
|
+
const next = parseReadableFilters(getUrlParams(), columnSnapshot);
|
|
1017
|
+
filtersRef.current = next;
|
|
1018
|
+
setFilters((previous) => JSON.stringify(previous) === JSON.stringify(next) ? previous : next);
|
|
1019
|
+
}, [columnSnapshot]);
|
|
1015
1020
|
react.useEffect(() => {
|
|
1016
1021
|
const handleUrlChange = () => {
|
|
1017
1022
|
if (lastWrittenUrlRef.current !== null && window.location.search === lastWrittenUrlRef.current) {
|
|
@@ -4414,7 +4419,7 @@ const filterModeConfig = {
|
|
|
4414
4419
|
tooltip: "Linear-style command filters"
|
|
4415
4420
|
}
|
|
4416
4421
|
};
|
|
4417
|
-
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 }) {
|
|
4422
|
+
function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
|
|
4418
4423
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
4419
4424
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
4420
4425
|
const showToggle = modes.length > 1;
|
|
@@ -4429,9 +4434,24 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4429
4434
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
4430
4435
|
const enableAdvancedFilter = true;
|
|
4431
4436
|
const columns = (0, react.useMemo)(() => {
|
|
4437
|
+
const columnOverrides = Object.assign({}, overrides);
|
|
4438
|
+
for (const key of filterOnly ?? []) {
|
|
4439
|
+
const field = key;
|
|
4440
|
+
Object.assign(columnOverrides, { [field]: {
|
|
4441
|
+
...columnOverrides[field],
|
|
4442
|
+
hidden: false
|
|
4443
|
+
} });
|
|
4444
|
+
}
|
|
4432
4445
|
const dataColumns = createTableSchema(schema, {
|
|
4433
|
-
overrides,
|
|
4446
|
+
overrides: columnOverrides,
|
|
4434
4447
|
exclude
|
|
4448
|
+
}).map((column) => {
|
|
4449
|
+
const key = column.id ?? ("accessorKey" in column ? String(column.accessorKey) : "");
|
|
4450
|
+
return filterOnly?.includes(key) ? {
|
|
4451
|
+
...column,
|
|
4452
|
+
enableHiding: false,
|
|
4453
|
+
enableSorting: false
|
|
4454
|
+
} : column;
|
|
4435
4455
|
});
|
|
4436
4456
|
const result = enableRowSelection ? [createSelectColumn(), ...dataColumns] : dataColumns;
|
|
4437
4457
|
if (actions) result.push(createActionsColumn(actions));
|
|
@@ -4441,7 +4461,8 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4441
4461
|
overrides,
|
|
4442
4462
|
enableRowSelection,
|
|
4443
4463
|
exclude,
|
|
4444
|
-
actions
|
|
4464
|
+
actions,
|
|
4465
|
+
filterOnly
|
|
4445
4466
|
]);
|
|
4446
4467
|
const stableInitialState = (0, react.useMemo)(() => ({
|
|
4447
4468
|
sorting: initialSorting,
|
|
@@ -4465,6 +4486,16 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4465
4486
|
shallow: false,
|
|
4466
4487
|
clearOnDefault: true
|
|
4467
4488
|
});
|
|
4489
|
+
(0, react.useEffect)(() => {
|
|
4490
|
+
if (!filterOnly?.length) return;
|
|
4491
|
+
table.setColumnVisibility((previous) => {
|
|
4492
|
+
if (filterOnly.every((key) => previous[key] === false)) return previous;
|
|
4493
|
+
return {
|
|
4494
|
+
...previous,
|
|
4495
|
+
...Object.fromEntries(filterOnly.map((key) => [key, false]))
|
|
4496
|
+
};
|
|
4497
|
+
});
|
|
4498
|
+
}, [table, filterOnly]);
|
|
4468
4499
|
const rowSelection = table.getState().rowSelection;
|
|
4469
4500
|
const columnFilters = table.getState().columnFilters;
|
|
4470
4501
|
const selectedRows = (0, react.useMemo)(() => table.getFilteredSelectedRowModel().rows.map((row) => row.original), [
|
|
@@ -4905,6 +4936,30 @@ function normalizeHasMore(result) {
|
|
|
4905
4936
|
|
|
4906
4937
|
//#endregion
|
|
4907
4938
|
//#region src/lib/field-config.ts
|
|
4939
|
+
function mergeFieldPart(base, override) {
|
|
4940
|
+
if (override === void 0) return base;
|
|
4941
|
+
if (override === false || base === false || typeof base !== "object" || typeof override !== "object" || base === null || override === null || Array.isArray(base) || Array.isArray(override)) return override;
|
|
4942
|
+
return {
|
|
4943
|
+
...base,
|
|
4944
|
+
...override
|
|
4945
|
+
};
|
|
4946
|
+
}
|
|
4947
|
+
function mergeFieldConfig(base, override) {
|
|
4948
|
+
return {
|
|
4949
|
+
...base,
|
|
4950
|
+
...override,
|
|
4951
|
+
enum: override?.enum ?? base?.enum,
|
|
4952
|
+
dataSource: override?.dataSource ?? base?.dataSource,
|
|
4953
|
+
table: mergeFieldPart(base?.table, override?.table),
|
|
4954
|
+
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
4955
|
+
form: mergeFieldPart(base?.form, override?.form)
|
|
4956
|
+
};
|
|
4957
|
+
}
|
|
4958
|
+
function mergeFields(base, override) {
|
|
4959
|
+
if (!base && !override) return void 0;
|
|
4960
|
+
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
4961
|
+
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
4962
|
+
}
|
|
4908
4963
|
function normalizeFieldOptions$1(options) {
|
|
4909
4964
|
if (!options || options.length === 0) return void 0;
|
|
4910
4965
|
return options.map((option) => ({
|
|
@@ -6292,7 +6347,6 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6292
6347
|
const ownerCustomIds = new Set(ownerActions.flatMap((action$1) => isCustomAction$1(action$1) && action$1.id ? [action$1.id] : []));
|
|
6293
6348
|
const baseActions = ownerActions.filter((action$1) => !action$1.hidden && !isMaskedCustom(action$1)).map((action$1) => ({ ...isCustomAction$1(action$1) && action$1.id ? customOverrides.get(action$1.id)?.action ?? action$1 : action$1 }));
|
|
6294
6349
|
const isReplacedCustom = ({ action: action$1, seq: seq$1 }) => isCustomAction$1(action$1) && Boolean(action$1.id && (ownerCustomIds.has(action$1.id) || customOverrides.get(action$1.id)?.seq !== seq$1));
|
|
6295
|
-
if (registered.length === 0) return require_position.positionActions(baseActions).map(withoutRegistryMeta);
|
|
6296
6350
|
const nextActions = [...baseActions];
|
|
6297
6351
|
const extraActions = [];
|
|
6298
6352
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -6319,7 +6373,13 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6319
6373
|
const items = group.sort((left, right) => left.seq - right.seq).flatMap((entry) => {
|
|
6320
6374
|
const { action: action$1 } = entry;
|
|
6321
6375
|
if (action$1.hidden || isReplacedCustom(entry)) return [];
|
|
6322
|
-
if (isCustomAction$1(action$1))
|
|
6376
|
+
if (isCustomAction$1(action$1)) {
|
|
6377
|
+
if (action$1.before) {
|
|
6378
|
+
extraActions.push({ ...action$1 });
|
|
6379
|
+
return [];
|
|
6380
|
+
}
|
|
6381
|
+
return [{ ...action$1 }];
|
|
6382
|
+
}
|
|
6323
6383
|
const builtin = nextActions.find((item) => item.type === action$1.type);
|
|
6324
6384
|
return builtin ? [builtin] : [];
|
|
6325
6385
|
});
|
|
@@ -6340,6 +6400,15 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6340
6400
|
}
|
|
6341
6401
|
} else extraActions.push(...items);
|
|
6342
6402
|
}
|
|
6403
|
+
for (const action$1 of [...nextActions, ...extraActions]) {
|
|
6404
|
+
if (!isCustomAction$1(action$1) || !action$1.before) continue;
|
|
6405
|
+
const anchor = nextActions.find((item) => !isCustomAction$1(item) && item.type === action$1.before);
|
|
6406
|
+
if (anchor) action$1.position = {
|
|
6407
|
+
anchor: anchor.id ?? anchor.type,
|
|
6408
|
+
side: "before"
|
|
6409
|
+
};
|
|
6410
|
+
else if (typeof action$1.position === "object") action$1.position = "end";
|
|
6411
|
+
}
|
|
6343
6412
|
return require_position.positionActions(nextActions, extraActions).map(withoutRegistryMeta);
|
|
6344
6413
|
}
|
|
6345
6414
|
const crudActions = {
|
|
@@ -6489,30 +6558,6 @@ function resolveToolbarActionsWithResolver(targetId, ownerActions, context) {
|
|
|
6489
6558
|
const resolver = autoCrudToolbarResolver;
|
|
6490
6559
|
return targetId !== void 0 && targetId.length > 0 && resolver !== null ? resolver(targetId, ownerActions, context) : ownerActions;
|
|
6491
6560
|
}
|
|
6492
|
-
function mergeFieldPart(base, override) {
|
|
6493
|
-
if (override === void 0) return base;
|
|
6494
|
-
if (override === false || base === false || typeof base !== "object" || typeof override !== "object" || base === null || override === null || Array.isArray(base) || Array.isArray(override)) return override;
|
|
6495
|
-
return {
|
|
6496
|
-
...base,
|
|
6497
|
-
...override
|
|
6498
|
-
};
|
|
6499
|
-
}
|
|
6500
|
-
function mergeFieldConfig(base, override) {
|
|
6501
|
-
return {
|
|
6502
|
-
...base,
|
|
6503
|
-
...override,
|
|
6504
|
-
enum: override?.enum ?? base?.enum,
|
|
6505
|
-
dataSource: override?.dataSource ?? base?.dataSource,
|
|
6506
|
-
table: mergeFieldPart(base?.table, override?.table),
|
|
6507
|
-
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
6508
|
-
form: mergeFieldPart(base?.form, override?.form)
|
|
6509
|
-
};
|
|
6510
|
-
}
|
|
6511
|
-
function mergeFields(base, override) {
|
|
6512
|
-
if (!base && !override) return void 0;
|
|
6513
|
-
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
6514
|
-
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
6515
|
-
}
|
|
6516
6561
|
function applyResourceTablePresentation(fields, resourceFields) {
|
|
6517
6562
|
if (!fields || !resourceFields) return fields;
|
|
6518
6563
|
return Object.fromEntries(Object.entries(fields).map(([key, config]) => {
|
|
@@ -7414,6 +7459,12 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7414
7459
|
const [exporting, setExporting] = react.useState(false);
|
|
7415
7460
|
const getSelectedRowsRef = react.useRef(null);
|
|
7416
7461
|
const dynamicFilterOptions = useDynamicFilterOptions(resolvedFields);
|
|
7462
|
+
const filterOnly = react.useMemo(() => Object.entries(resolvedFields).filter(([key, config]) => config.table === false && config.filter && config.hidden !== true && !denyFields?.includes(key) && !tableConfig?.hidden?.includes(key) && tableConfig?.overrides?.[key]?.hidden !== true).map(([key]) => key), [
|
|
7463
|
+
resolvedFields,
|
|
7464
|
+
denyFields,
|
|
7465
|
+
tableConfig?.hidden,
|
|
7466
|
+
tableConfig?.overrides
|
|
7467
|
+
]);
|
|
7417
7468
|
const hiddenColumns = react.useMemo(() => buildHiddenColumns(resolvedFields, tableConfig?.hidden, denyFields, tableConfig?.overrides), [
|
|
7418
7469
|
resolvedFields,
|
|
7419
7470
|
tableConfig?.hidden,
|
|
@@ -7764,7 +7815,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7764
7815
|
...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
|
|
7765
7816
|
overrides: tableOverrides,
|
|
7766
7817
|
classNames: tableConfig?.classNames,
|
|
7767
|
-
exclude: hiddenColumns,
|
|
7818
|
+
exclude: hiddenColumns.filter((key) => !filterOnly.includes(key)),
|
|
7819
|
+
filterOnly,
|
|
7768
7820
|
filterMode: tableConfig?.filterModes,
|
|
7769
7821
|
search: searchConfig,
|
|
7770
7822
|
actions: tableRowActions,
|
|
@@ -8597,7 +8649,7 @@ function modalReducer(state, action$1) {
|
|
|
8597
8649
|
/**
|
|
8598
8650
|
* Hook 主函数
|
|
8599
8651
|
*/
|
|
8600
|
-
function useAutoCrudResource({ router, schema, query: queryTransform, options = {} }) {
|
|
8652
|
+
function useAutoCrudResource({ router, schema, query: queryTransform, fields, options = {} }) {
|
|
8601
8653
|
const { idKey = "id", defaultVariant = "dialog", hooks, toast: toastAdapter, exportFetcher, defaultSort: defaultSortOption } = options;
|
|
8602
8654
|
const toast = (0, react.useMemo)(() => toastAdapter === false ? noopToastAdapter : toastAdapter ?? defaultToastAdapter, [toastAdapter]);
|
|
8603
8655
|
const hooksRef = (0, react.useRef)(hooks);
|
|
@@ -8609,7 +8661,14 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
|
|
|
8609
8661
|
const defaultSorting = (0, react.useMemo)(() => defaultSortOption === false ? [] : defaultSortOption ?? getDefaultSortingForSchema(resolvedSchema), [defaultSortOption, resolvedSchema]);
|
|
8610
8662
|
const metadataFields = (0, react.useMemo)(() => readMetadataFields(metadata?.fields), [metadata?.fields]);
|
|
8611
8663
|
const capabilities = metadata?.capabilities;
|
|
8612
|
-
const columns = (0, react.useMemo)(() => createTableSchema(resolvedSchema),
|
|
8664
|
+
const columns = (0, react.useMemo)(() => createTableSchema(resolvedSchema, { overrides: Object.fromEntries(Object.entries(mergeFields(metadataFields, fields) ?? {}).flatMap(([key, field]) => {
|
|
8665
|
+
const filter = field.filter;
|
|
8666
|
+
return filter && typeof filter === "object" && filter.variant ? [[key, { meta: { variant: filter.variant } }]] : [];
|
|
8667
|
+
})) }), [
|
|
8668
|
+
resolvedSchema,
|
|
8669
|
+
fields,
|
|
8670
|
+
metadataFields
|
|
8671
|
+
]);
|
|
8613
8672
|
const [urlParams] = useQueryStates({
|
|
8614
8673
|
page: parseAsInteger.withDefault(1),
|
|
8615
8674
|
perPage: parseAsInteger.withDefault(10),
|
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_runtime4 from "react/jsx-runtime";
|
|
3
3
|
import * as React$1 from "react";
|
|
4
4
|
import * as _tanstack_react_table0 from "@tanstack/react-table";
|
|
5
5
|
import { Column, ColumnDef, ColumnMeta, ColumnSort, Row, RowData, Table, TableOptions, TableState } from "@tanstack/react-table";
|
|
@@ -573,6 +573,8 @@ interface UseAutoCrudResourceParams<TSchema extends z.ZodObject<z.ZodRawShape>,
|
|
|
573
573
|
router: CrudRouter;
|
|
574
574
|
/** Zod schema */
|
|
575
575
|
schema: TSchema;
|
|
576
|
+
/** Field filter configuration shared with AutoCrudTable. */
|
|
577
|
+
fields?: Fields;
|
|
576
578
|
/**
|
|
577
579
|
* 查询参数变换函数
|
|
578
580
|
*
|
|
@@ -599,6 +601,7 @@ declare function useAutoCrudResource<TSchema extends z.ZodObject<z.ZodRawShape>,
|
|
|
599
601
|
router,
|
|
600
602
|
schema,
|
|
601
603
|
query: queryTransform,
|
|
604
|
+
fields,
|
|
602
605
|
options
|
|
603
606
|
}: UseAutoCrudResourceParams<TSchema, TListItem>): UseAutoCrudResourceReturn<TSchema, TListItem>;
|
|
604
607
|
//#endregion
|
|
@@ -735,7 +738,7 @@ declare function AutoTableActionBar<TData>({
|
|
|
735
738
|
extraActions,
|
|
736
739
|
actions,
|
|
737
740
|
deleteConfirmation
|
|
738
|
-
}: AutoTableActionBarProps<TData>):
|
|
741
|
+
}: AutoTableActionBarProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
739
742
|
//#endregion
|
|
740
743
|
//#region src/lib/schema-bridge/types.d.ts
|
|
741
744
|
/**
|
|
@@ -856,6 +859,7 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
|
|
|
856
859
|
classNames?: DataTableClassNames;
|
|
857
860
|
enableRowSelection?: boolean;
|
|
858
861
|
exclude?: (keyof z.infer<T>)[];
|
|
862
|
+
filterOnly?: string[];
|
|
859
863
|
actions?: ActionsColumnConfig<z.infer<T>>;
|
|
860
864
|
/** 自定义固定列配置 */
|
|
861
865
|
pinnedColumns?: {
|
|
@@ -908,6 +912,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
908
912
|
classNames,
|
|
909
913
|
enableRowSelection,
|
|
910
914
|
exclude,
|
|
915
|
+
filterOnly,
|
|
911
916
|
actions,
|
|
912
917
|
pinnedColumns,
|
|
913
918
|
filterMode,
|
|
@@ -924,7 +929,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
924
929
|
onSelectedCountChange,
|
|
925
930
|
onSelectedRowsChange,
|
|
926
931
|
getSelectedRows
|
|
927
|
-
}: AutoTableProps<T>):
|
|
932
|
+
}: AutoTableProps<T>): react_jsx_runtime4.JSX.Element;
|
|
928
933
|
//#endregion
|
|
929
934
|
//#region src/lib/row-action-dialog.d.ts
|
|
930
935
|
interface RowActionDialogProps {
|
|
@@ -1272,6 +1277,8 @@ type RowCustomActionItem<T> = ActionMeta & {
|
|
|
1272
1277
|
onClick?: (row: T) => void;
|
|
1273
1278
|
component?: ActionComponent<AutoCrudRowActionContext<T>>;
|
|
1274
1279
|
position?: ActionPosition;
|
|
1280
|
+
/** Place a registered custom action before the named builtin, when present. */
|
|
1281
|
+
before?: RowBuiltinActionType;
|
|
1275
1282
|
separator?: boolean;
|
|
1276
1283
|
variant?: 'default' | 'destructive';
|
|
1277
1284
|
};
|
|
@@ -1476,7 +1483,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1476
1483
|
toolbarActions,
|
|
1477
1484
|
locale: localeProp,
|
|
1478
1485
|
onCreate
|
|
1479
|
-
}: AutoCrudTableProps<TSchema>):
|
|
1486
|
+
}: AutoCrudTableProps<TSchema>): react_jsx_runtime4.JSX.Element;
|
|
1480
1487
|
//#endregion
|
|
1481
1488
|
//#region src/components/auto-crud/auto-form.d.ts
|
|
1482
1489
|
interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
|
|
@@ -1515,7 +1522,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1515
1522
|
labelAlign,
|
|
1516
1523
|
labelWidth,
|
|
1517
1524
|
showSubmitButton
|
|
1518
|
-
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>):
|
|
1525
|
+
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime4.JSX.Element;
|
|
1519
1526
|
declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
|
|
1520
1527
|
ref?: React.Ref<AutoFormRef>;
|
|
1521
1528
|
}) => ReturnType<typeof AutoFormInner>;
|
|
@@ -1534,7 +1541,7 @@ declare function AutoTableSimpleFilters<TData>({
|
|
|
1534
1541
|
filters: externalFilters,
|
|
1535
1542
|
onFiltersChange,
|
|
1536
1543
|
leading
|
|
1537
|
-
}: AutoTableSimpleFiltersProps<TData>):
|
|
1544
|
+
}: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime4.JSX.Element | null;
|
|
1538
1545
|
//#endregion
|
|
1539
1546
|
//#region src/components/auto-crud/form-modal.d.ts
|
|
1540
1547
|
type ModalVariant = 'dialog' | 'sheet';
|
|
@@ -1578,7 +1585,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1578
1585
|
labelAlign,
|
|
1579
1586
|
labelWidth,
|
|
1580
1587
|
className
|
|
1581
|
-
}: CrudFormModalProps<T>):
|
|
1588
|
+
}: CrudFormModalProps<T>): react_jsx_runtime4.JSX.Element;
|
|
1582
1589
|
//#endregion
|
|
1583
1590
|
//#region src/components/auto-crud/import-dialog.d.ts
|
|
1584
1591
|
interface ImportDialogProps {
|
|
@@ -1600,7 +1607,7 @@ declare function ImportDialog({
|
|
|
1600
1607
|
columns,
|
|
1601
1608
|
title,
|
|
1602
1609
|
locale
|
|
1603
|
-
}: ImportDialogProps):
|
|
1610
|
+
}: ImportDialogProps): react_jsx_runtime4.JSX.Element;
|
|
1604
1611
|
//#endregion
|
|
1605
1612
|
//#region src/components/auto-crud/export-dialog.d.ts
|
|
1606
1613
|
type ExportMode = 'selected' | 'filtered';
|
|
@@ -1620,7 +1627,7 @@ declare function ExportDialog({
|
|
|
1620
1627
|
selectedCount,
|
|
1621
1628
|
onExport,
|
|
1622
1629
|
canExportFiltered
|
|
1623
|
-
}: ExportDialogProps):
|
|
1630
|
+
}: ExportDialogProps): react_jsx_runtime4.JSX.Element;
|
|
1624
1631
|
//#endregion
|
|
1625
1632
|
//#region src/components/data-table/data-table.d.ts
|
|
1626
1633
|
interface DataTableProps<TData> extends React$1.ComponentProps<'div'> {
|
|
@@ -1637,7 +1644,7 @@ declare function DataTable<TData>({
|
|
|
1637
1644
|
className,
|
|
1638
1645
|
classNames,
|
|
1639
1646
|
...props
|
|
1640
|
-
}: DataTableProps<TData>):
|
|
1647
|
+
}: DataTableProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
1641
1648
|
//#endregion
|
|
1642
1649
|
//#region src/components/data-table/data-table-advanced-toolbar.d.ts
|
|
1643
1650
|
interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<'div'> {
|
|
@@ -1648,7 +1655,7 @@ declare function DataTableAdvancedToolbar<TData>({
|
|
|
1648
1655
|
children,
|
|
1649
1656
|
className,
|
|
1650
1657
|
...props
|
|
1651
|
-
}: DataTableAdvancedToolbarProps<TData>):
|
|
1658
|
+
}: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
1652
1659
|
//#endregion
|
|
1653
1660
|
//#region src/components/data-table/data-table-column-header.d.ts
|
|
1654
1661
|
interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
|
|
@@ -1660,7 +1667,7 @@ declare function DataTableColumnHeader<TData, TValue>({
|
|
|
1660
1667
|
label,
|
|
1661
1668
|
className,
|
|
1662
1669
|
...props
|
|
1663
|
-
}: DataTableColumnHeaderProps<TData, TValue>):
|
|
1670
|
+
}: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime4.JSX.Element;
|
|
1664
1671
|
//#endregion
|
|
1665
1672
|
//#region src/components/data-table/data-table-faceted-filter.d.ts
|
|
1666
1673
|
interface DataTableFacetedFilterProps<TData, TValue> {
|
|
@@ -1674,7 +1681,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
|
|
|
1674
1681
|
title,
|
|
1675
1682
|
options,
|
|
1676
1683
|
multiple
|
|
1677
|
-
}: DataTableFacetedFilterProps<TData, TValue>):
|
|
1684
|
+
}: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime4.JSX.Element;
|
|
1678
1685
|
//#endregion
|
|
1679
1686
|
//#region src/components/data-table/data-table-pagination.d.ts
|
|
1680
1687
|
interface DataTablePaginationProps<TData> extends React.ComponentProps<'div'>, TablePaginationOptions {
|
|
@@ -1690,7 +1697,7 @@ declare function DataTablePagination<TData>({
|
|
|
1690
1697
|
pageJumpLabel,
|
|
1691
1698
|
className,
|
|
1692
1699
|
...props
|
|
1693
|
-
}: DataTablePaginationProps<TData>):
|
|
1700
|
+
}: DataTablePaginationProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
1694
1701
|
//#endregion
|
|
1695
1702
|
//#region src/components/data-table/data-table-toolbar.d.ts
|
|
1696
1703
|
interface DataTableToolbarProps<TData> extends React$1.ComponentProps<'div'> {
|
|
@@ -1701,7 +1708,7 @@ declare function DataTableToolbar<TData>({
|
|
|
1701
1708
|
children,
|
|
1702
1709
|
className,
|
|
1703
1710
|
...props
|
|
1704
|
-
}: DataTableToolbarProps<TData>):
|
|
1711
|
+
}: DataTableToolbarProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
1705
1712
|
//#endregion
|
|
1706
1713
|
//#region src/components/data-table/data-table-view-options.d.ts
|
|
1707
1714
|
interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
|
|
@@ -1712,7 +1719,7 @@ declare function DataTableViewOptions<TData>({
|
|
|
1712
1719
|
table,
|
|
1713
1720
|
disabled,
|
|
1714
1721
|
...props
|
|
1715
|
-
}: DataTableViewOptionsProps<TData>):
|
|
1722
|
+
}: DataTableViewOptionsProps<TData>): react_jsx_runtime4.JSX.Element;
|
|
1716
1723
|
//#endregion
|
|
1717
1724
|
//#region src/lib/crud-actions.d.ts
|
|
1718
1725
|
type CrudActionZone = 'toolbar' | 'row' | 'batch';
|
|
@@ -1722,6 +1729,8 @@ type CrudActionBase = {
|
|
|
1722
1729
|
order?: number;
|
|
1723
1730
|
hidden?: boolean;
|
|
1724
1731
|
position?: ActionPosition;
|
|
1732
|
+
/** Insert a custom action before a builtin action type, if present. */
|
|
1733
|
+
before?: string;
|
|
1725
1734
|
};
|
|
1726
1735
|
type CrudActionEntry<TAction extends CrudActionBase = CrudActionBase> = {
|
|
1727
1736
|
targetId: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -573,6 +573,8 @@ interface UseAutoCrudResourceParams<TSchema extends z.ZodObject<z.ZodRawShape>,
|
|
|
573
573
|
router: CrudRouter;
|
|
574
574
|
/** Zod schema */
|
|
575
575
|
schema: TSchema;
|
|
576
|
+
/** Field filter configuration shared with AutoCrudTable. */
|
|
577
|
+
fields?: Fields;
|
|
576
578
|
/**
|
|
577
579
|
* 查询参数变换函数
|
|
578
580
|
*
|
|
@@ -599,6 +601,7 @@ declare function useAutoCrudResource<TSchema extends z.ZodObject<z.ZodRawShape>,
|
|
|
599
601
|
router,
|
|
600
602
|
schema,
|
|
601
603
|
query: queryTransform,
|
|
604
|
+
fields,
|
|
602
605
|
options
|
|
603
606
|
}: UseAutoCrudResourceParams<TSchema, TListItem>): UseAutoCrudResourceReturn<TSchema, TListItem>;
|
|
604
607
|
//#endregion
|
|
@@ -856,6 +859,7 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
|
|
|
856
859
|
classNames?: DataTableClassNames;
|
|
857
860
|
enableRowSelection?: boolean;
|
|
858
861
|
exclude?: (keyof z.infer<T>)[];
|
|
862
|
+
filterOnly?: string[];
|
|
859
863
|
actions?: ActionsColumnConfig<z.infer<T>>;
|
|
860
864
|
/** 自定义固定列配置 */
|
|
861
865
|
pinnedColumns?: {
|
|
@@ -908,6 +912,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
908
912
|
classNames,
|
|
909
913
|
enableRowSelection,
|
|
910
914
|
exclude,
|
|
915
|
+
filterOnly,
|
|
911
916
|
actions,
|
|
912
917
|
pinnedColumns,
|
|
913
918
|
filterMode,
|
|
@@ -1272,6 +1277,8 @@ type RowCustomActionItem<T> = ActionMeta & {
|
|
|
1272
1277
|
onClick?: (row: T) => void;
|
|
1273
1278
|
component?: ActionComponent<AutoCrudRowActionContext<T>>;
|
|
1274
1279
|
position?: ActionPosition;
|
|
1280
|
+
/** Place a registered custom action before the named builtin, when present. */
|
|
1281
|
+
before?: RowBuiltinActionType;
|
|
1275
1282
|
separator?: boolean;
|
|
1276
1283
|
variant?: 'default' | 'destructive';
|
|
1277
1284
|
};
|
|
@@ -1722,6 +1729,8 @@ type CrudActionBase = {
|
|
|
1722
1729
|
order?: number;
|
|
1723
1730
|
hidden?: boolean;
|
|
1724
1731
|
position?: ActionPosition;
|
|
1732
|
+
/** Insert a custom action before a builtin action type, if present. */
|
|
1733
|
+
before?: string;
|
|
1725
1734
|
};
|
|
1726
1735
|
type CrudActionEntry<TAction extends CrudActionBase = CrudActionBase> = {
|
|
1727
1736
|
targetId: string;
|
package/dist/index.js
CHANGED
|
@@ -997,6 +997,11 @@ function useReadableFilters(columns, options = {}) {
|
|
|
997
997
|
filtersRef.current = initial;
|
|
998
998
|
return initial;
|
|
999
999
|
});
|
|
1000
|
+
React.useEffect(() => {
|
|
1001
|
+
const next = parseReadableFilters(getUrlParams(), columnSnapshot);
|
|
1002
|
+
filtersRef.current = next;
|
|
1003
|
+
setFilters((previous) => JSON.stringify(previous) === JSON.stringify(next) ? previous : next);
|
|
1004
|
+
}, [columnSnapshot]);
|
|
1000
1005
|
React.useEffect(() => {
|
|
1001
1006
|
const handleUrlChange = () => {
|
|
1002
1007
|
if (lastWrittenUrlRef.current !== null && window.location.search === lastWrittenUrlRef.current) {
|
|
@@ -4399,7 +4404,7 @@ const filterModeConfig = {
|
|
|
4399
4404
|
tooltip: "Linear-style command filters"
|
|
4400
4405
|
}
|
|
4401
4406
|
};
|
|
4402
|
-
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 }) {
|
|
4407
|
+
function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
|
|
4403
4408
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
4404
4409
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
4405
4410
|
const showToggle = modes.length > 1;
|
|
@@ -4414,9 +4419,24 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4414
4419
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
4415
4420
|
const enableAdvancedFilter = true;
|
|
4416
4421
|
const columns = useMemo(() => {
|
|
4422
|
+
const columnOverrides = Object.assign({}, overrides);
|
|
4423
|
+
for (const key of filterOnly ?? []) {
|
|
4424
|
+
const field = key;
|
|
4425
|
+
Object.assign(columnOverrides, { [field]: {
|
|
4426
|
+
...columnOverrides[field],
|
|
4427
|
+
hidden: false
|
|
4428
|
+
} });
|
|
4429
|
+
}
|
|
4417
4430
|
const dataColumns = createTableSchema(schema, {
|
|
4418
|
-
overrides,
|
|
4431
|
+
overrides: columnOverrides,
|
|
4419
4432
|
exclude
|
|
4433
|
+
}).map((column) => {
|
|
4434
|
+
const key = column.id ?? ("accessorKey" in column ? String(column.accessorKey) : "");
|
|
4435
|
+
return filterOnly?.includes(key) ? {
|
|
4436
|
+
...column,
|
|
4437
|
+
enableHiding: false,
|
|
4438
|
+
enableSorting: false
|
|
4439
|
+
} : column;
|
|
4420
4440
|
});
|
|
4421
4441
|
const result = enableRowSelection ? [createSelectColumn(), ...dataColumns] : dataColumns;
|
|
4422
4442
|
if (actions) result.push(createActionsColumn(actions));
|
|
@@ -4426,7 +4446,8 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4426
4446
|
overrides,
|
|
4427
4447
|
enableRowSelection,
|
|
4428
4448
|
exclude,
|
|
4429
|
-
actions
|
|
4449
|
+
actions,
|
|
4450
|
+
filterOnly
|
|
4430
4451
|
]);
|
|
4431
4452
|
const stableInitialState = useMemo(() => ({
|
|
4432
4453
|
sorting: initialSorting,
|
|
@@ -4450,6 +4471,16 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4450
4471
|
shallow: false,
|
|
4451
4472
|
clearOnDefault: true
|
|
4452
4473
|
});
|
|
4474
|
+
useEffect(() => {
|
|
4475
|
+
if (!filterOnly?.length) return;
|
|
4476
|
+
table.setColumnVisibility((previous) => {
|
|
4477
|
+
if (filterOnly.every((key) => previous[key] === false)) return previous;
|
|
4478
|
+
return {
|
|
4479
|
+
...previous,
|
|
4480
|
+
...Object.fromEntries(filterOnly.map((key) => [key, false]))
|
|
4481
|
+
};
|
|
4482
|
+
});
|
|
4483
|
+
}, [table, filterOnly]);
|
|
4453
4484
|
const rowSelection = table.getState().rowSelection;
|
|
4454
4485
|
const columnFilters = table.getState().columnFilters;
|
|
4455
4486
|
const selectedRows = useMemo(() => table.getFilteredSelectedRowModel().rows.map((row) => row.original), [
|
|
@@ -4890,6 +4921,30 @@ function normalizeHasMore(result) {
|
|
|
4890
4921
|
|
|
4891
4922
|
//#endregion
|
|
4892
4923
|
//#region src/lib/field-config.ts
|
|
4924
|
+
function mergeFieldPart(base, override) {
|
|
4925
|
+
if (override === void 0) return base;
|
|
4926
|
+
if (override === false || base === false || typeof base !== "object" || typeof override !== "object" || base === null || override === null || Array.isArray(base) || Array.isArray(override)) return override;
|
|
4927
|
+
return {
|
|
4928
|
+
...base,
|
|
4929
|
+
...override
|
|
4930
|
+
};
|
|
4931
|
+
}
|
|
4932
|
+
function mergeFieldConfig(base, override) {
|
|
4933
|
+
return {
|
|
4934
|
+
...base,
|
|
4935
|
+
...override,
|
|
4936
|
+
enum: override?.enum ?? base?.enum,
|
|
4937
|
+
dataSource: override?.dataSource ?? base?.dataSource,
|
|
4938
|
+
table: mergeFieldPart(base?.table, override?.table),
|
|
4939
|
+
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
4940
|
+
form: mergeFieldPart(base?.form, override?.form)
|
|
4941
|
+
};
|
|
4942
|
+
}
|
|
4943
|
+
function mergeFields(base, override) {
|
|
4944
|
+
if (!base && !override) return void 0;
|
|
4945
|
+
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
4946
|
+
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
4947
|
+
}
|
|
4893
4948
|
function normalizeFieldOptions$1(options) {
|
|
4894
4949
|
if (!options || options.length === 0) return void 0;
|
|
4895
4950
|
return options.map((option) => ({
|
|
@@ -6277,7 +6332,6 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6277
6332
|
const ownerCustomIds = new Set(ownerActions.flatMap((action$1) => isCustomAction$1(action$1) && action$1.id ? [action$1.id] : []));
|
|
6278
6333
|
const baseActions = ownerActions.filter((action$1) => !action$1.hidden && !isMaskedCustom(action$1)).map((action$1) => ({ ...isCustomAction$1(action$1) && action$1.id ? customOverrides.get(action$1.id)?.action ?? action$1 : action$1 }));
|
|
6279
6334
|
const isReplacedCustom = ({ action: action$1, seq: seq$1 }) => isCustomAction$1(action$1) && Boolean(action$1.id && (ownerCustomIds.has(action$1.id) || customOverrides.get(action$1.id)?.seq !== seq$1));
|
|
6280
|
-
if (registered.length === 0) return positionActions(baseActions).map(withoutRegistryMeta);
|
|
6281
6335
|
const nextActions = [...baseActions];
|
|
6282
6336
|
const extraActions = [];
|
|
6283
6337
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -6304,7 +6358,13 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6304
6358
|
const items = group.sort((left, right) => left.seq - right.seq).flatMap((entry) => {
|
|
6305
6359
|
const { action: action$1 } = entry;
|
|
6306
6360
|
if (action$1.hidden || isReplacedCustom(entry)) return [];
|
|
6307
|
-
if (isCustomAction$1(action$1))
|
|
6361
|
+
if (isCustomAction$1(action$1)) {
|
|
6362
|
+
if (action$1.before) {
|
|
6363
|
+
extraActions.push({ ...action$1 });
|
|
6364
|
+
return [];
|
|
6365
|
+
}
|
|
6366
|
+
return [{ ...action$1 }];
|
|
6367
|
+
}
|
|
6308
6368
|
const builtin = nextActions.find((item) => item.type === action$1.type);
|
|
6309
6369
|
return builtin ? [builtin] : [];
|
|
6310
6370
|
});
|
|
@@ -6325,6 +6385,15 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6325
6385
|
}
|
|
6326
6386
|
} else extraActions.push(...items);
|
|
6327
6387
|
}
|
|
6388
|
+
for (const action$1 of [...nextActions, ...extraActions]) {
|
|
6389
|
+
if (!isCustomAction$1(action$1) || !action$1.before) continue;
|
|
6390
|
+
const anchor = nextActions.find((item) => !isCustomAction$1(item) && item.type === action$1.before);
|
|
6391
|
+
if (anchor) action$1.position = {
|
|
6392
|
+
anchor: anchor.id ?? anchor.type,
|
|
6393
|
+
side: "before"
|
|
6394
|
+
};
|
|
6395
|
+
else if (typeof action$1.position === "object") action$1.position = "end";
|
|
6396
|
+
}
|
|
6328
6397
|
return positionActions(nextActions, extraActions).map(withoutRegistryMeta);
|
|
6329
6398
|
}
|
|
6330
6399
|
const crudActions = {
|
|
@@ -6474,30 +6543,6 @@ function resolveToolbarActionsWithResolver(targetId, ownerActions, context) {
|
|
|
6474
6543
|
const resolver = autoCrudToolbarResolver;
|
|
6475
6544
|
return targetId !== void 0 && targetId.length > 0 && resolver !== null ? resolver(targetId, ownerActions, context) : ownerActions;
|
|
6476
6545
|
}
|
|
6477
|
-
function mergeFieldPart(base, override) {
|
|
6478
|
-
if (override === void 0) return base;
|
|
6479
|
-
if (override === false || base === false || typeof base !== "object" || typeof override !== "object" || base === null || override === null || Array.isArray(base) || Array.isArray(override)) return override;
|
|
6480
|
-
return {
|
|
6481
|
-
...base,
|
|
6482
|
-
...override
|
|
6483
|
-
};
|
|
6484
|
-
}
|
|
6485
|
-
function mergeFieldConfig(base, override) {
|
|
6486
|
-
return {
|
|
6487
|
-
...base,
|
|
6488
|
-
...override,
|
|
6489
|
-
enum: override?.enum ?? base?.enum,
|
|
6490
|
-
dataSource: override?.dataSource ?? base?.dataSource,
|
|
6491
|
-
table: mergeFieldPart(base?.table, override?.table),
|
|
6492
|
-
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
6493
|
-
form: mergeFieldPart(base?.form, override?.form)
|
|
6494
|
-
};
|
|
6495
|
-
}
|
|
6496
|
-
function mergeFields(base, override) {
|
|
6497
|
-
if (!base && !override) return void 0;
|
|
6498
|
-
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
6499
|
-
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
6500
|
-
}
|
|
6501
6546
|
function applyResourceTablePresentation(fields, resourceFields) {
|
|
6502
6547
|
if (!fields || !resourceFields) return fields;
|
|
6503
6548
|
return Object.fromEntries(Object.entries(fields).map(([key, config]) => {
|
|
@@ -7399,6 +7444,12 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7399
7444
|
const [exporting, setExporting] = React.useState(false);
|
|
7400
7445
|
const getSelectedRowsRef = React.useRef(null);
|
|
7401
7446
|
const dynamicFilterOptions = useDynamicFilterOptions(resolvedFields);
|
|
7447
|
+
const filterOnly = React.useMemo(() => Object.entries(resolvedFields).filter(([key, config]) => config.table === false && config.filter && config.hidden !== true && !denyFields?.includes(key) && !tableConfig?.hidden?.includes(key) && tableConfig?.overrides?.[key]?.hidden !== true).map(([key]) => key), [
|
|
7448
|
+
resolvedFields,
|
|
7449
|
+
denyFields,
|
|
7450
|
+
tableConfig?.hidden,
|
|
7451
|
+
tableConfig?.overrides
|
|
7452
|
+
]);
|
|
7402
7453
|
const hiddenColumns = React.useMemo(() => buildHiddenColumns(resolvedFields, tableConfig?.hidden, denyFields, tableConfig?.overrides), [
|
|
7403
7454
|
resolvedFields,
|
|
7404
7455
|
tableConfig?.hidden,
|
|
@@ -7749,7 +7800,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7749
7800
|
...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
|
|
7750
7801
|
overrides: tableOverrides,
|
|
7751
7802
|
classNames: tableConfig?.classNames,
|
|
7752
|
-
exclude: hiddenColumns,
|
|
7803
|
+
exclude: hiddenColumns.filter((key) => !filterOnly.includes(key)),
|
|
7804
|
+
filterOnly,
|
|
7753
7805
|
filterMode: tableConfig?.filterModes,
|
|
7754
7806
|
search: searchConfig,
|
|
7755
7807
|
actions: tableRowActions,
|
|
@@ -8582,7 +8634,7 @@ function modalReducer(state, action$1) {
|
|
|
8582
8634
|
/**
|
|
8583
8635
|
* Hook 主函数
|
|
8584
8636
|
*/
|
|
8585
|
-
function useAutoCrudResource({ router, schema, query: queryTransform, options = {} }) {
|
|
8637
|
+
function useAutoCrudResource({ router, schema, query: queryTransform, fields, options = {} }) {
|
|
8586
8638
|
const { idKey = "id", defaultVariant = "dialog", hooks, toast: toastAdapter, exportFetcher, defaultSort: defaultSortOption } = options;
|
|
8587
8639
|
const toast$1 = useMemo(() => toastAdapter === false ? noopToastAdapter : toastAdapter ?? defaultToastAdapter, [toastAdapter]);
|
|
8588
8640
|
const hooksRef = useRef(hooks);
|
|
@@ -8594,7 +8646,14 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
|
|
|
8594
8646
|
const defaultSorting = useMemo(() => defaultSortOption === false ? [] : defaultSortOption ?? getDefaultSortingForSchema(resolvedSchema), [defaultSortOption, resolvedSchema]);
|
|
8595
8647
|
const metadataFields = useMemo(() => readMetadataFields(metadata?.fields), [metadata?.fields]);
|
|
8596
8648
|
const capabilities = metadata?.capabilities;
|
|
8597
|
-
const columns = useMemo(() => createTableSchema(resolvedSchema),
|
|
8649
|
+
const columns = useMemo(() => createTableSchema(resolvedSchema, { overrides: Object.fromEntries(Object.entries(mergeFields(metadataFields, fields) ?? {}).flatMap(([key, field]) => {
|
|
8650
|
+
const filter = field.filter;
|
|
8651
|
+
return filter && typeof filter === "object" && filter.variant ? [[key, { meta: { variant: filter.variant } }]] : [];
|
|
8652
|
+
})) }), [
|
|
8653
|
+
resolvedSchema,
|
|
8654
|
+
fields,
|
|
8655
|
+
metadataFields
|
|
8656
|
+
]);
|
|
8598
8657
|
const [urlParams] = useQueryStates({
|
|
8599
8658
|
page: parseAsInteger.withDefault(1),
|
|
8600
8659
|
perPage: parseAsInteger.withDefault(10),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordrhyme/auto-crud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.9.0",
|
|
5
5
|
"description": "Schema-first CRUD components with auto-generated tables and forms",
|
|
6
6
|
"author": "wordrhyme",
|
|
7
7
|
"license": "MIT",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"tailwind-merge": "^3.5.0",
|
|
72
72
|
"vaul": "^1.1.2",
|
|
73
73
|
"@wordrhyme/shadcn": "2.0.1",
|
|
74
|
-
"@wordrhyme/
|
|
75
|
-
"@wordrhyme/shadcn
|
|
74
|
+
"@wordrhyme/shadcn-ui": "2.1.1",
|
|
75
|
+
"@wordrhyme/formily-shadcn": "2.1.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@storybook/react": "^8.6.18",
|
|
@@ -93,11 +93,11 @@
|
|
|
93
93
|
"tsdown": "^0.15.12",
|
|
94
94
|
"typescript": "^5.9.3",
|
|
95
95
|
"vitest": "^3.2.4",
|
|
96
|
-
"@internal/tsconfig": "0.1.0",
|
|
97
96
|
"@internal/prettier-config": "0.0.1",
|
|
98
|
-
"@internal/eslint-config": "0.3.0",
|
|
99
97
|
"@internal/tsdown-config": "0.1.0",
|
|
100
|
-
"@internal/
|
|
98
|
+
"@internal/tsconfig": "0.1.0",
|
|
99
|
+
"@internal/vitest-config": "0.1.0",
|
|
100
|
+
"@internal/eslint-config": "0.3.0"
|
|
101
101
|
},
|
|
102
102
|
"prettier": "@internal/prettier-config",
|
|
103
103
|
"scripts": {
|