@wordrhyme/auto-crud 1.8.1 → 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 +57 -2
- package/dist/index.cjs +140 -88
- package/dist/index.d.cts +34 -24
- package/dist/index.d.ts +18 -8
- package/dist/index.js +121 -50
- package/dist/position--p6kJnYA.js +56 -0
- package/dist/position-BlO0bPw6.cjs +109 -0
- package/dist/position-DoBV7yB6.d.cts +29 -0
- package/dist/position-mYekVBBH.d.ts +29 -0
- package/dist/position.cjs +6 -0
- package/dist/position.d.cts +2 -0
- package/dist/position.d.ts +2 -0
- package/dist/position.js +3 -0
- package/package.json +12 -7
package/README.md
CHANGED
|
@@ -803,7 +803,7 @@ type ToolbarBuiltinActionItem = ActionMeta & {
|
|
|
803
803
|
type ToolbarCustomActionItem = ActionMeta & {
|
|
804
804
|
type: 'custom';
|
|
805
805
|
component: React.ReactNode | ((context: AutoCrudToolbarContext) => React.ReactNode);
|
|
806
|
-
position?:
|
|
806
|
+
position?: ActionPosition; // start/end 仅无内置项时生效;也支持 { anchor, side }
|
|
807
807
|
};
|
|
808
808
|
|
|
809
809
|
interface AutoCrudToolbarContext {
|
|
@@ -911,6 +911,28 @@ crudActions.register({
|
|
|
911
911
|
`order` 不再重排同一插件数组内的显示顺序。内置属性覆盖仍沿用原有的 action `order`、`ownerId`、注册序优先级,最后一个配置生效。
|
|
912
912
|
使用 `order` 排列同一插件操作的旧调用方,应把数组调整为所需顺序。最终权限过滤只移除不可用的内置操作,不改变其余操作顺序或授予权限。
|
|
913
913
|
|
|
914
|
+
### 统一位置契约
|
|
915
|
+
|
|
916
|
+
AutoCrud action 和 WordRhyme PluginSlot 共用 `ActionPosition`:`"start"`、`"end"`,或 `{ anchor, side: "before" | "after" }`。类型、schema、位置匹配和锚点排序从不依赖 React 的 `@wordrhyme/auto-crud/position` 导出。
|
|
917
|
+
|
|
918
|
+
`positionActions(ownerActions, fills)` 合并拥有方按钮和扩展数组:`start` fills 放在数组前,`end` 或未指定位置的 fills 放在数组后,相对位置按基础按钮锚点插入。AutoCrud 和 PluginSlot 共用此解析器。原有 action 数组及 start/end 排列规则保持不变。指定锚点时,在原有合并、覆盖和隐藏之后定位,`order` 按升序排列同一锚点的 fills。AutoCrud 使用合并后基础 action 的 `id` 作为锚点;原生按钮未设置 `id` 时使用 `type`。合并后的动作列表不存在锚点时,不显示依赖它的扩展;最终权限过滤继续沿用已有行为。
|
|
919
|
+
|
|
920
|
+
```tsx
|
|
921
|
+
crudActions.register({
|
|
922
|
+
targetId: 'com.wordrhyme.shop.products',
|
|
923
|
+
zone: 'toolbar',
|
|
924
|
+
ownerId: 'com.wordrhyme.sync',
|
|
925
|
+
actions: [
|
|
926
|
+
{
|
|
927
|
+
type: 'custom',
|
|
928
|
+
component: SyncButton,
|
|
929
|
+
position: { anchor: 'create', side: 'before' },
|
|
930
|
+
order: 30,
|
|
931
|
+
},
|
|
932
|
+
],
|
|
933
|
+
});
|
|
934
|
+
```
|
|
935
|
+
|
|
914
936
|
---
|
|
915
937
|
|
|
916
938
|
## 🎬 行操作配置
|
|
@@ -1005,7 +1027,7 @@ type RowCustomActionItem<T> = ActionMeta & {
|
|
|
1005
1027
|
component?:
|
|
1006
1028
|
| React.ReactNode
|
|
1007
1029
|
| ((context: AutoCrudRowActionContext<T>) => React.ReactNode);
|
|
1008
|
-
position?:
|
|
1030
|
+
position?: ActionPosition; // start/end 仅无内置项时生效;也支持 { anchor, side }
|
|
1009
1031
|
separator?: boolean;
|
|
1010
1032
|
variant?: 'default' | 'destructive';
|
|
1011
1033
|
};
|
|
@@ -1629,6 +1651,14 @@ MIT © [wordrhyme](https://github.com/denvey/wordrhyme-components)
|
|
|
1629
1651
|
- [Notion](https://notion.so) - 高级筛选器设计
|
|
1630
1652
|
- [Linear](https://linear.app) - 命令面板设计
|
|
1631
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
|
+
|
|
1632
1662
|
### Detail presentation
|
|
1633
1663
|
|
|
1634
1664
|
Details automatically share field labels, `enum`/`dataSource` mappings and
|
|
@@ -1689,6 +1719,31 @@ is pinned to the already-published alpha.19 for reproducible ESM tests and type
|
|
|
1689
1719
|
checks until alpha.20 is published; it is not the supported CommonJS runtime.
|
|
1690
1720
|
The CommonJS export/identity regression belongs to the UI provider repository.
|
|
1691
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
|
+
|
|
1692
1747
|
### 按 ID 隐藏或替换自定义操作
|
|
1693
1748
|
|
|
1694
1749
|
拥有方为 custom 操作声明稳定 `id` 后,扩展可以在相同 CRUD target 和操作区域
|
package/dist/index.cjs
CHANGED
|
@@ -1,58 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
1
|
+
const require_position = require('./position-BlO0bPw6.cjs');
|
|
24
2
|
let react = require("react");
|
|
25
|
-
react = __toESM(react);
|
|
3
|
+
react = require_position.__toESM(react);
|
|
26
4
|
let lucide_react = require("lucide-react");
|
|
27
|
-
lucide_react = __toESM(lucide_react);
|
|
5
|
+
lucide_react = require_position.__toESM(lucide_react);
|
|
28
6
|
let __tanstack_react_table = require("@tanstack/react-table");
|
|
29
|
-
__tanstack_react_table = __toESM(__tanstack_react_table);
|
|
7
|
+
__tanstack_react_table = require_position.__toESM(__tanstack_react_table);
|
|
30
8
|
let __wordrhyme_shadcn = require("@wordrhyme/shadcn");
|
|
31
|
-
__wordrhyme_shadcn = __toESM(__wordrhyme_shadcn);
|
|
9
|
+
__wordrhyme_shadcn = require_position.__toESM(__wordrhyme_shadcn);
|
|
32
10
|
let clsx = require("clsx");
|
|
33
|
-
clsx = __toESM(clsx);
|
|
11
|
+
clsx = require_position.__toESM(clsx);
|
|
34
12
|
let tailwind_merge = require("tailwind-merge");
|
|
35
|
-
tailwind_merge = __toESM(tailwind_merge);
|
|
13
|
+
tailwind_merge = require_position.__toESM(tailwind_merge);
|
|
36
14
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
-
react_jsx_runtime = __toESM(react_jsx_runtime);
|
|
15
|
+
react_jsx_runtime = require_position.__toESM(react_jsx_runtime);
|
|
38
16
|
let nanoid = require("nanoid");
|
|
39
|
-
nanoid = __toESM(nanoid);
|
|
17
|
+
nanoid = require_position.__toESM(nanoid);
|
|
40
18
|
let __wordrhyme_shadcn_ui = require("@wordrhyme/shadcn-ui");
|
|
41
|
-
__wordrhyme_shadcn_ui = __toESM(__wordrhyme_shadcn_ui);
|
|
19
|
+
__wordrhyme_shadcn_ui = require_position.__toESM(__wordrhyme_shadcn_ui);
|
|
42
20
|
let __wordrhyme_ui = require("@wordrhyme/ui");
|
|
43
|
-
__wordrhyme_ui = __toESM(__wordrhyme_ui);
|
|
21
|
+
__wordrhyme_ui = require_position.__toESM(__wordrhyme_ui);
|
|
44
22
|
let zod = require("zod");
|
|
45
|
-
zod = __toESM(zod);
|
|
23
|
+
zod = require_position.__toESM(zod);
|
|
46
24
|
let __wordrhyme_formily_shadcn = require("@wordrhyme/formily-shadcn");
|
|
47
|
-
__wordrhyme_formily_shadcn = __toESM(__wordrhyme_formily_shadcn);
|
|
25
|
+
__wordrhyme_formily_shadcn = require_position.__toESM(__wordrhyme_formily_shadcn);
|
|
48
26
|
let __formily_core = require("@formily/core");
|
|
49
|
-
__formily_core = __toESM(__formily_core);
|
|
27
|
+
__formily_core = require_position.__toESM(__formily_core);
|
|
50
28
|
let __formily_reactive = require("@formily/reactive");
|
|
51
|
-
__formily_reactive = __toESM(__formily_reactive);
|
|
29
|
+
__formily_reactive = require_position.__toESM(__formily_reactive);
|
|
52
30
|
let sonner = require("sonner");
|
|
53
|
-
sonner = __toESM(sonner);
|
|
31
|
+
sonner = require_position.__toESM(sonner);
|
|
54
32
|
let __tanstack_react_query = require("@tanstack/react-query");
|
|
55
|
-
__tanstack_react_query = __toESM(__tanstack_react_query);
|
|
33
|
+
__tanstack_react_query = require_position.__toESM(__tanstack_react_query);
|
|
56
34
|
|
|
57
35
|
//#region src/lib/utils.ts
|
|
58
36
|
function cn(...inputs) {
|
|
@@ -1034,6 +1012,11 @@ function useReadableFilters(columns, options = {}) {
|
|
|
1034
1012
|
filtersRef.current = initial;
|
|
1035
1013
|
return initial;
|
|
1036
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]);
|
|
1037
1020
|
react.useEffect(() => {
|
|
1038
1021
|
const handleUrlChange = () => {
|
|
1039
1022
|
if (lastWrittenUrlRef.current !== null && window.location.search === lastWrittenUrlRef.current) {
|
|
@@ -4112,7 +4095,7 @@ function AutoTableActionBar({ table, onDeleteSelected, onUpdateSelected, batchUp
|
|
|
4112
4095
|
{ type: "export" },
|
|
4113
4096
|
{ type: "delete" }
|
|
4114
4097
|
]) : actions;
|
|
4115
|
-
|
|
4098
|
+
let resolvedActions = configuredActions?.filter((action$1) => !action$1.hidden);
|
|
4116
4099
|
if (configuredActions === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
4117
4100
|
renderBuiltinAction({ type: "batchUpdate" }),
|
|
4118
4101
|
extraActions,
|
|
@@ -4120,7 +4103,20 @@ function AutoTableActionBar({ table, onDeleteSelected, onUpdateSelected, batchUp
|
|
|
4120
4103
|
renderBuiltinAction({ type: "delete" })
|
|
4121
4104
|
] });
|
|
4122
4105
|
if (!resolvedActions || resolvedActions.length === 0) return null;
|
|
4123
|
-
|
|
4106
|
+
let hasBuiltin = resolvedActions.some((action$1) => action$1.type !== "custom");
|
|
4107
|
+
if (resolvedActions.some((action$1) => "position" in action$1 && typeof action$1.position === "object")) if (!hasBuiltin) {
|
|
4108
|
+
resolvedActions = require_position.positionActions([
|
|
4109
|
+
{ type: "batchUpdate" },
|
|
4110
|
+
...extraActions ? [{
|
|
4111
|
+
type: "custom",
|
|
4112
|
+
component: extraActions
|
|
4113
|
+
}] : [],
|
|
4114
|
+
...showDefaultExport ? [{ type: "export" }] : [],
|
|
4115
|
+
{ type: "delete" }
|
|
4116
|
+
], resolvedActions);
|
|
4117
|
+
hasBuiltin = true;
|
|
4118
|
+
} else resolvedActions = require_position.positionActions(resolvedActions);
|
|
4119
|
+
if (!hasBuiltin) {
|
|
4124
4120
|
const startNodes = resolvedActions.filter(isBatchCustomAction).filter((action$1) => action$1.position === "start").map((action$1, index$1) => renderCustomAction(action$1, index$1));
|
|
4125
4121
|
const endNodes = resolvedActions.filter(isBatchCustomAction).filter((action$1) => action$1.position !== "start").map((action$1, index$1) => renderCustomAction(action$1, index$1));
|
|
4126
4122
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
@@ -4423,7 +4419,7 @@ const filterModeConfig = {
|
|
|
4423
4419
|
tooltip: "Linear-style command filters"
|
|
4424
4420
|
}
|
|
4425
4421
|
};
|
|
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 }) {
|
|
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 }) {
|
|
4427
4423
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
4428
4424
|
const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
|
|
4429
4425
|
const showToggle = modes.length > 1;
|
|
@@ -4438,9 +4434,24 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4438
4434
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
4439
4435
|
const enableAdvancedFilter = true;
|
|
4440
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
|
+
}
|
|
4441
4445
|
const dataColumns = createTableSchema(schema, {
|
|
4442
|
-
overrides,
|
|
4446
|
+
overrides: columnOverrides,
|
|
4443
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;
|
|
4444
4455
|
});
|
|
4445
4456
|
const result = enableRowSelection ? [createSelectColumn(), ...dataColumns] : dataColumns;
|
|
4446
4457
|
if (actions) result.push(createActionsColumn(actions));
|
|
@@ -4450,7 +4461,8 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4450
4461
|
overrides,
|
|
4451
4462
|
enableRowSelection,
|
|
4452
4463
|
exclude,
|
|
4453
|
-
actions
|
|
4464
|
+
actions,
|
|
4465
|
+
filterOnly
|
|
4454
4466
|
]);
|
|
4455
4467
|
const stableInitialState = (0, react.useMemo)(() => ({
|
|
4456
4468
|
sorting: initialSorting,
|
|
@@ -4474,6 +4486,16 @@ function AutoTable({ schema, data, pageCount = 1, pagination, total, overrides,
|
|
|
4474
4486
|
shallow: false,
|
|
4475
4487
|
clearOnDefault: true
|
|
4476
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]);
|
|
4477
4499
|
const rowSelection = table.getState().rowSelection;
|
|
4478
4500
|
const columnFilters = table.getState().columnFilters;
|
|
4479
4501
|
const selectedRows = (0, react.useMemo)(() => table.getFilteredSelectedRowModel().rows.map((row) => row.original), [
|
|
@@ -4914,6 +4936,30 @@ function normalizeHasMore(result) {
|
|
|
4914
4936
|
|
|
4915
4937
|
//#endregion
|
|
4916
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
|
+
}
|
|
4917
4963
|
function normalizeFieldOptions$1(options) {
|
|
4918
4964
|
if (!options || options.length === 0) return void 0;
|
|
4919
4965
|
return options.map((option) => ({
|
|
@@ -6273,15 +6319,18 @@ function unregisterOwnerActions(ownerId, options = {}, shouldNotify = true) {
|
|
|
6273
6319
|
if (changed && shouldNotify) notify();
|
|
6274
6320
|
}
|
|
6275
6321
|
function sortEntries(left, right) {
|
|
6276
|
-
const orderDiff = left
|
|
6322
|
+
const orderDiff = require_position.compareOrder(left, right);
|
|
6277
6323
|
if (orderDiff !== 0) return orderDiff;
|
|
6278
6324
|
const ownerDiff = left.ownerId.localeCompare(right.ownerId);
|
|
6279
6325
|
if (ownerDiff !== 0) return ownerDiff;
|
|
6280
6326
|
return left.seq - right.seq;
|
|
6281
6327
|
}
|
|
6282
6328
|
function withoutRegistryMeta(action$1) {
|
|
6283
|
-
const { id, order,...rest } = action$1;
|
|
6284
|
-
return
|
|
6329
|
+
const { id, order, position,...rest } = action$1;
|
|
6330
|
+
return {
|
|
6331
|
+
...rest,
|
|
6332
|
+
...typeof position === "string" ? { position } : {}
|
|
6333
|
+
};
|
|
6285
6334
|
}
|
|
6286
6335
|
function isCustomAction$1(action$1) {
|
|
6287
6336
|
return action$1.type === "custom";
|
|
@@ -6296,12 +6345,10 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6296
6345
|
if (isCustomAction$1(action$1) && action$1.id && !isMaskedCustom(action$1)) customOverrides.set(action$1.id, entry);
|
|
6297
6346
|
}
|
|
6298
6347
|
const ownerCustomIds = new Set(ownerActions.flatMap((action$1) => isCustomAction$1(action$1) && action$1.id ? [action$1.id] : []));
|
|
6299
|
-
const baseActions = ownerActions.filter((action$1) => !action$1.hidden && !isMaskedCustom(action$1)).map((action$1) =>
|
|
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 }));
|
|
6300
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));
|
|
6301
|
-
if (registered.length === 0) return baseActions;
|
|
6302
6350
|
const nextActions = [...baseActions];
|
|
6303
|
-
const
|
|
6304
|
-
const endCustomActions = [];
|
|
6351
|
+
const extraActions = [];
|
|
6305
6352
|
const groups = /* @__PURE__ */ new Map();
|
|
6306
6353
|
for (const entry of registered) {
|
|
6307
6354
|
if (isMaskedCustom(entry.action)) continue;
|
|
@@ -6315,7 +6362,7 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6315
6362
|
if (existingIndex >= 0) nextActions.splice(existingIndex, 1);
|
|
6316
6363
|
continue;
|
|
6317
6364
|
}
|
|
6318
|
-
const builtin =
|
|
6365
|
+
const builtin = action$1;
|
|
6319
6366
|
if (existingIndex >= 0) nextActions[existingIndex] = {
|
|
6320
6367
|
...nextActions[existingIndex],
|
|
6321
6368
|
...builtin
|
|
@@ -6326,7 +6373,13 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6326
6373
|
const items = group.sort((left, right) => left.seq - right.seq).flatMap((entry) => {
|
|
6327
6374
|
const { action: action$1 } = entry;
|
|
6328
6375
|
if (action$1.hidden || isReplacedCustom(entry)) return [];
|
|
6329
|
-
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
|
+
}
|
|
6330
6383
|
const builtin = nextActions.find((item) => item.type === action$1.type);
|
|
6331
6384
|
return builtin ? [builtin] : [];
|
|
6332
6385
|
});
|
|
@@ -6345,13 +6398,18 @@ function resolveActions$1(targetId, zone, ownerActions) {
|
|
|
6345
6398
|
cursor += 1;
|
|
6346
6399
|
}
|
|
6347
6400
|
}
|
|
6348
|
-
} else
|
|
6401
|
+
} else extraActions.push(...items);
|
|
6349
6402
|
}
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
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
|
+
}
|
|
6412
|
+
return require_position.positionActions(nextActions, extraActions).map(withoutRegistryMeta);
|
|
6355
6413
|
}
|
|
6356
6414
|
const crudActions = {
|
|
6357
6415
|
register(registration) {
|
|
@@ -6453,8 +6511,8 @@ function resolveOwnerActions(config, defaults) {
|
|
|
6453
6511
|
const items = resolved !== void 0 && resolved.length > 0 ? [...resolved] : [];
|
|
6454
6512
|
if (items.length === 0) return [...defaults];
|
|
6455
6513
|
if (items.some((item) => !isCustomAction(item))) return items;
|
|
6456
|
-
const startItems = items.filter((item) => isCustomAction(item) && item.position
|
|
6457
|
-
const endItems = items.filter((item) => isCustomAction(item) && item.position
|
|
6514
|
+
const startItems = items.filter((item) => isCustomAction(item) && require_position.matchesPosition(item.position, "start"));
|
|
6515
|
+
const endItems = items.filter((item) => isCustomAction(item) && !require_position.matchesPosition(item.position, "start"));
|
|
6458
6516
|
return [
|
|
6459
6517
|
...startItems,
|
|
6460
6518
|
...defaults,
|
|
@@ -6500,30 +6558,6 @@ function resolveToolbarActionsWithResolver(targetId, ownerActions, context) {
|
|
|
6500
6558
|
const resolver = autoCrudToolbarResolver;
|
|
6501
6559
|
return targetId !== void 0 && targetId.length > 0 && resolver !== null ? resolver(targetId, ownerActions, context) : ownerActions;
|
|
6502
6560
|
}
|
|
6503
|
-
function mergeFieldPart(base, override) {
|
|
6504
|
-
if (override === void 0) return base;
|
|
6505
|
-
if (override === false || base === false || typeof base !== "object" || typeof override !== "object" || base === null || override === null || Array.isArray(base) || Array.isArray(override)) return override;
|
|
6506
|
-
return {
|
|
6507
|
-
...base,
|
|
6508
|
-
...override
|
|
6509
|
-
};
|
|
6510
|
-
}
|
|
6511
|
-
function mergeFieldConfig(base, override) {
|
|
6512
|
-
return {
|
|
6513
|
-
...base,
|
|
6514
|
-
...override,
|
|
6515
|
-
enum: override?.enum ?? base?.enum,
|
|
6516
|
-
dataSource: override?.dataSource ?? base?.dataSource,
|
|
6517
|
-
table: mergeFieldPart(base?.table, override?.table),
|
|
6518
|
-
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
6519
|
-
form: mergeFieldPart(base?.form, override?.form)
|
|
6520
|
-
};
|
|
6521
|
-
}
|
|
6522
|
-
function mergeFields(base, override) {
|
|
6523
|
-
if (!base && !override) return void 0;
|
|
6524
|
-
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
6525
|
-
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
6526
|
-
}
|
|
6527
6561
|
function applyResourceTablePresentation(fields, resourceFields) {
|
|
6528
6562
|
if (!fields || !resourceFields) return fields;
|
|
6529
6563
|
return Object.fromEntries(Object.entries(fields).map(([key, config]) => {
|
|
@@ -7425,6 +7459,12 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7425
7459
|
const [exporting, setExporting] = react.useState(false);
|
|
7426
7460
|
const getSelectedRowsRef = react.useRef(null);
|
|
7427
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
|
+
]);
|
|
7428
7468
|
const hiddenColumns = react.useMemo(() => buildHiddenColumns(resolvedFields, tableConfig?.hidden, denyFields, tableConfig?.overrides), [
|
|
7429
7469
|
resolvedFields,
|
|
7430
7470
|
tableConfig?.hidden,
|
|
@@ -7775,7 +7815,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
7775
7815
|
...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
|
|
7776
7816
|
overrides: tableOverrides,
|
|
7777
7817
|
classNames: tableConfig?.classNames,
|
|
7778
|
-
exclude: hiddenColumns,
|
|
7818
|
+
exclude: hiddenColumns.filter((key) => !filterOnly.includes(key)),
|
|
7819
|
+
filterOnly,
|
|
7779
7820
|
filterMode: tableConfig?.filterModes,
|
|
7780
7821
|
search: searchConfig,
|
|
7781
7822
|
actions: tableRowActions,
|
|
@@ -8608,7 +8649,7 @@ function modalReducer(state, action$1) {
|
|
|
8608
8649
|
/**
|
|
8609
8650
|
* Hook 主函数
|
|
8610
8651
|
*/
|
|
8611
|
-
function useAutoCrudResource({ router, schema, query: queryTransform, options = {} }) {
|
|
8652
|
+
function useAutoCrudResource({ router, schema, query: queryTransform, fields, options = {} }) {
|
|
8612
8653
|
const { idKey = "id", defaultVariant = "dialog", hooks, toast: toastAdapter, exportFetcher, defaultSort: defaultSortOption } = options;
|
|
8613
8654
|
const toast = (0, react.useMemo)(() => toastAdapter === false ? noopToastAdapter : toastAdapter ?? defaultToastAdapter, [toastAdapter]);
|
|
8614
8655
|
const hooksRef = (0, react.useRef)(hooks);
|
|
@@ -8620,7 +8661,14 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
|
|
|
8620
8661
|
const defaultSorting = (0, react.useMemo)(() => defaultSortOption === false ? [] : defaultSortOption ?? getDefaultSortingForSchema(resolvedSchema), [defaultSortOption, resolvedSchema]);
|
|
8621
8662
|
const metadataFields = (0, react.useMemo)(() => readMetadataFields(metadata?.fields), [metadata?.fields]);
|
|
8622
8663
|
const capabilities = metadata?.capabilities;
|
|
8623
|
-
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
|
+
]);
|
|
8624
8672
|
const [urlParams] = useQueryStates({
|
|
8625
8673
|
page: parseAsInteger.withDefault(1),
|
|
8626
8674
|
perPage: parseAsInteger.withDefault(10),
|
|
@@ -9275,8 +9323,10 @@ Object.defineProperty(exports, 'Select', {
|
|
|
9275
9323
|
return __wordrhyme_shadcn_ui.Select;
|
|
9276
9324
|
}
|
|
9277
9325
|
});
|
|
9326
|
+
exports.actionPositionSchema = require_position.actionPositionSchema;
|
|
9278
9327
|
exports.cn = cn;
|
|
9279
9328
|
exports.coerceRowValues = coerceRowValues;
|
|
9329
|
+
exports.compareOrder = require_position.compareOrder;
|
|
9280
9330
|
exports.components = components;
|
|
9281
9331
|
exports.createActionsColumn = createActionsColumn;
|
|
9282
9332
|
exports.createEditFormSchema = createEditFormSchema;
|
|
@@ -9302,6 +9352,7 @@ exports.getUrlParams = getUrlParams;
|
|
|
9302
9352
|
exports.humanize = humanize;
|
|
9303
9353
|
exports.jaJP = jaJP;
|
|
9304
9354
|
exports.koKR = koKR;
|
|
9355
|
+
exports.matchesPosition = require_position.matchesPosition;
|
|
9305
9356
|
exports.noopToastAdapter = noopToastAdapter;
|
|
9306
9357
|
exports.normalizeDataSourceConfig = normalizeDataSourceConfig;
|
|
9307
9358
|
exports.normalizeOptions = normalizeOptions;
|
|
@@ -9313,6 +9364,7 @@ exports.parseCSV = parseCSV;
|
|
|
9313
9364
|
exports.parseImportFile = parseImportFile;
|
|
9314
9365
|
exports.parseJSON = parseJSON;
|
|
9315
9366
|
exports.parseZodField = parseZodField;
|
|
9367
|
+
exports.positionActions = require_position.positionActions;
|
|
9316
9368
|
exports.resolveLocale = resolveLocale;
|
|
9317
9369
|
exports.setDateFormatter = setDateFormatter;
|
|
9318
9370
|
exports.setSearchParams = setSearchParams;
|