@wordrhyme/auto-crud 1.5.7 → 1.7.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 +245 -0
- package/dist/index.cjs +527 -305
- package/dist/index.d.cts +1118 -1058
- package/dist/index.d.ts +1103 -1043
- package/dist/index.js +527 -306
- package/dist/styles.css +2 -0
- package/dist/tailwind.css +3 -0
- package/package.json +23 -19
package/README.md
CHANGED
|
@@ -375,6 +375,7 @@ interface Field {
|
|
|
375
375
|
/** 表格特定配置 */
|
|
376
376
|
table?: {
|
|
377
377
|
hidden?: boolean; // 仅表格隐藏
|
|
378
|
+
classNames?: { th?: string; td?: string }; // 该列的表头和正文类名
|
|
378
379
|
meta?: Record<string, unknown>; // 筛选器配置
|
|
379
380
|
[key: string]: unknown;
|
|
380
381
|
};
|
|
@@ -391,6 +392,72 @@ interface Field {
|
|
|
391
392
|
type Fields = Record<string, Field>;
|
|
392
393
|
```
|
|
393
394
|
|
|
395
|
+
### 列宽与单元格样式
|
|
396
|
+
|
|
397
|
+
`fields.xxx.table` 中的 `size`、`minSize` 和 `maxSize` 控制列宽。`fields.xxx.table.classNames` 按元素分组配置该列的 CSS 类名:`th` 应用于该列的表头单元格,`td` 应用于该列每一行的正文单元格。
|
|
398
|
+
|
|
399
|
+
任一可见列设置有限的 `maxSize` 后,表格使用固定列宽布局,其他列采用各自的 `size` 或 TanStack 默认宽度。默认正文保持单行,超出列宽的文本省略;通过 `fields.xxx.table.classNames.td` 可以为该列配置换行展示。
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
fields={{
|
|
403
|
+
primaryContactValue: {
|
|
404
|
+
table: {
|
|
405
|
+
size: 250,
|
|
406
|
+
minSize: 250,
|
|
407
|
+
maxSize: 250,
|
|
408
|
+
classNames: {
|
|
409
|
+
th: 'text-center',
|
|
410
|
+
td: 'whitespace-normal break-words',
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
}}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 全局表格类名
|
|
418
|
+
|
|
419
|
+
组件顶层的 `table.classNames` 为整个表格设置类名,所有值均为 CSS 类名字符串。
|
|
420
|
+
|
|
421
|
+
| 配置 | 作用范围 |
|
|
422
|
+
| ------- | -------------------------------- |
|
|
423
|
+
| `table` | `<table>` 元素 |
|
|
424
|
+
| `thead` | `<thead>` 表头区域 |
|
|
425
|
+
| `tbody` | `<tbody>` 正文区域 |
|
|
426
|
+
| `tr` | 所有表头行、正文行和空状态行 |
|
|
427
|
+
| `th` | 所有表头单元格 |
|
|
428
|
+
| `td` | 所有正文单元格,包括空状态单元格 |
|
|
429
|
+
|
|
430
|
+
单元格类名按默认类名、全局类名、列级类名的顺序合并;存在冲突的 Tailwind 类名由后者覆盖。空状态单元格跨越所有列,只应用全局 `td` 类名。
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
<AutoCrudTable
|
|
434
|
+
schema={schema}
|
|
435
|
+
resource={resource}
|
|
436
|
+
table={{
|
|
437
|
+
classNames: {
|
|
438
|
+
table: 'text-xs',
|
|
439
|
+
thead: 'bg-muted',
|
|
440
|
+
tbody: 'text-foreground',
|
|
441
|
+
tr: 'hover:bg-accent/50',
|
|
442
|
+
th: 'h-12 text-left',
|
|
443
|
+
td: 'py-3 text-left',
|
|
444
|
+
},
|
|
445
|
+
}}
|
|
446
|
+
fields={{
|
|
447
|
+
primaryContactValue: {
|
|
448
|
+
table: {
|
|
449
|
+
classNames: {
|
|
450
|
+
th: 'text-center',
|
|
451
|
+
td: 'text-center whitespace-normal break-words',
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
}}
|
|
456
|
+
/>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
直接使用 `AutoTable` 或 `DataTable` 时,通过组件的 `classNames` prop 传入同一组全局类名。直接定义 TanStack 列时,通过 `columnDef.meta.classNames` 配置该列的 `th`、`td`。
|
|
460
|
+
|
|
394
461
|
### 基础配置
|
|
395
462
|
|
|
396
463
|
```typescript
|
|
@@ -794,6 +861,26 @@ crudActions.register({
|
|
|
794
861
|
|
|
795
862
|
同一个 `ownerId + targetId + zone` 再次注册会替换该 owner 的旧动作;卸载插件或页面时可调用 `crudActions.unregister(ownerId)`。
|
|
796
863
|
|
|
864
|
+
插件的 `actions` 数组与页面配置一样,用数组表达操作的相对顺序。例如,在删除前插入同步操作:
|
|
865
|
+
|
|
866
|
+
```tsx
|
|
867
|
+
crudActions.register({
|
|
868
|
+
targetId: 'com.wordrhyme.shop.products',
|
|
869
|
+
zone: 'row',
|
|
870
|
+
ownerId: 'com.wordrhyme.sync',
|
|
871
|
+
actions: [{ type: 'custom', label: '同步', onClick: sync }, { type: 'delete' }],
|
|
872
|
+
});
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
插件仍是增量合并:未提及的宿主或其他插件操作保留,隐藏内置项必须显式使用 `hidden: true`。
|
|
876
|
+
有可见内置项的数组按声明顺序排列:从第一个列出的内置项所在位置开始,依次插入自定义项,只在顺序冲突时移动已存在的内置项。
|
|
877
|
+
未提及的操作之间保持相对顺序。内置项的已有 handler 等属性保留,只有显式声明的属性会覆盖它们。
|
|
878
|
+
只有自定义项(或列出的内置项全部被隐藏)时,沿用 `position: 'start' | 'end'`,同一位置内仍按数组顺序排列。
|
|
879
|
+
|
|
880
|
+
多插件按各自数组中最小的 `order`(未设置为 100)、`ownerId` 依次合并;后处理的数组在顺序冲突时优先,但不会删除前面的插件操作。
|
|
881
|
+
`order` 不再重排同一插件数组内的显示顺序。内置属性覆盖仍沿用原有的 action `order`、`ownerId`、注册序优先级,最后一个配置生效。
|
|
882
|
+
使用 `order` 排列同一插件操作的旧调用方,应把数组调整为所需顺序。最终权限过滤只移除不可用的内置操作,不改变其余操作顺序或授予权限。
|
|
883
|
+
|
|
797
884
|
---
|
|
798
885
|
|
|
799
886
|
## 🎬 行操作配置
|
|
@@ -894,6 +981,7 @@ type RowCustomActionItem<T> = ActionMeta & {
|
|
|
894
981
|
};
|
|
895
982
|
|
|
896
983
|
interface AutoCrudRowActionContext<T> {
|
|
984
|
+
open: (options: AutoCrudRowOpenOptions<T>) => void;
|
|
897
985
|
crudId: string;
|
|
898
986
|
idKey: string;
|
|
899
987
|
row: T;
|
|
@@ -905,6 +993,56 @@ interface AutoCrudRowActionContext<T> {
|
|
|
905
993
|
}
|
|
906
994
|
```
|
|
907
995
|
|
|
996
|
+
### 统一打开入口
|
|
997
|
+
|
|
998
|
+
行操作上下文提供 `open(options)`,旧的 `openView`、`openEdit`、`copyRow`、
|
|
999
|
+
`openDelete` 保持兼容:
|
|
1000
|
+
|
|
1001
|
+
```tsx
|
|
1002
|
+
open({ type: 'view', row });
|
|
1003
|
+
open({ type: 'edit', row });
|
|
1004
|
+
open({ type: 'copy', row });
|
|
1005
|
+
open({ type: 'delete', row });
|
|
1006
|
+
open({
|
|
1007
|
+
type: 'custom',
|
|
1008
|
+
component: <TransferDialog customer={row} open={false} onOpenChange={() => {}} />,
|
|
1009
|
+
});
|
|
1010
|
+
```
|
|
1011
|
+
|
|
1012
|
+
`AutoCrudRowOpenOptions<T>` 是判别联合:内置操作必须传 `row`,
|
|
1013
|
+
`custom` 必须传 `component`。内置操作复用旧方法的处理器,不可用的操作不执行;
|
|
1014
|
+
仍可通过旧的可选方法(如 `openEdit`)判断是否应显示对应菜单项。
|
|
1015
|
+
|
|
1016
|
+
自定义 `component` 由开发者实现弹窗或抽屉,并接收 `open/onOpenChange` 控制。
|
|
1017
|
+
`AutoCrudTable` 只管理生命周期,不额外包裹内置弹窗,也不会把普通组件自动变成弹窗。
|
|
1018
|
+
|
|
1019
|
+
### 自定义行操作弹窗
|
|
1020
|
+
|
|
1021
|
+
在行操作配置的 `component` 中使用 `open` 打开自定义弹窗:
|
|
1022
|
+
|
|
1023
|
+
```tsx
|
|
1024
|
+
{
|
|
1025
|
+
type: 'custom',
|
|
1026
|
+
component: ({ row, MenuItem, open }) => (
|
|
1027
|
+
<MenuItem onSelect={() => open({
|
|
1028
|
+
type: 'custom',
|
|
1029
|
+
component: <TransferDialog customer={row} open={false} onOpenChange={() => {}} />,
|
|
1030
|
+
})}>
|
|
1031
|
+
交接
|
|
1032
|
+
</MenuItem>
|
|
1033
|
+
),
|
|
1034
|
+
}
|
|
1035
|
+
```
|
|
1036
|
+
|
|
1037
|
+
`TransferDialog` 由开发者实现并接收 `RowActionDialogProps`。`AutoCrudTable` 托管
|
|
1038
|
+
`open`、`onOpenChange` 和可选的 `onDismiss`(调用方传入的同名属性会被覆盖),
|
|
1039
|
+
但不额外包裹弹窗。调用 `onOpenChange(false)` 或 `onDismiss()` 会卸载弹窗并清理状态;
|
|
1040
|
+
每次 `open({ type: 'custom', component })` 都创建新会话并替换当前自定义弹窗。
|
|
1041
|
+
|
|
1042
|
+
弹窗位于表格层,菜单关闭、列配置重建、翻页或筛选移除原行都不会卸载它。
|
|
1043
|
+
它继续使用打开时传入的记录,关闭后再次打开才获取新的记录。
|
|
1044
|
+
表格卸载时弹窗一起释放。弹窗自身负责 Portal、布局和业务提交。
|
|
1045
|
+
|
|
908
1046
|
## 🔄 批量操作
|
|
909
1047
|
|
|
910
1048
|
### 批量更新
|
|
@@ -1044,6 +1182,12 @@ setDateFormatter(undefined);
|
|
|
1044
1182
|
|
|
1045
1183
|
`setDateFormatter` 是进程/运行时级配置,建议在应用启动时注册一个稳定的 formatter。多个注册可以重叠,清理函数只移除对应注册,允许乱序清理。SSR 场景不要在每个请求中重复调用 setter;如需按请求选择语言或时区,应由稳定 formatter 通过宿主提供的并发安全上下文读取当前请求策略。
|
|
1046
1184
|
|
|
1185
|
+
原有 `setDateFormatter(formatter)` 调用保持兼容:筛选器的已选日期标签继续使用宿主 formatter,包括其自定义格式和时区行为。
|
|
1186
|
+
|
|
1187
|
+
日期筛选日历可通过 `setDateFormatter(formatter, { locale, timeZone })` 接收宿主配置(`DateLocaleOptions`)。语言或时区改变时重新注册并清理旧注册,已挂载的筛选器会同步更新月份、星期和日期标签。筛选值使用 `YYYY-MM-DD` 日历日字符串;服务端配置 `resolveDateRange` 时按宿主查询时区解析边界,否则使用服务端本地时区,并继续兼容时间戳输入。显式传入日历配置后,日期标签使用指定 locale,直接格式化日历日,不再调用 formatter 或进行时间点的时区转换。`timeZone` 仅随注册保存宿主策略,不会改变日历的“今天”、默认月份或自动配置服务端查询时区;业务时区边界仍须由服务端 `resolveDateRange` 提供。
|
|
1188
|
+
|
|
1189
|
+
升级时请同时更新 `@wordrhyme/auto-crud` 与 `@wordrhyme/auto-crud-server`:新日历提交 `YYYY-MM-DD`,旧服务端默认解析器无法识别。自定义 `resolveDateRange` 也应接受此格式;已有时间戳 URL 仍可读取。
|
|
1190
|
+
|
|
1047
1191
|
### Schema Bridge - 核心转换函数
|
|
1048
1192
|
|
|
1049
1193
|
```typescript
|
|
@@ -1454,3 +1598,104 @@ MIT © [wordrhyme](https://github.com/pixpilot/shadcn-components)
|
|
|
1454
1598
|
- [Shadcn UI](https://ui.shadcn.com/) - 优雅的 UI 组件
|
|
1455
1599
|
- [Notion](https://notion.so) - 高级筛选器设计
|
|
1456
1600
|
- [Linear](https://linear.app) - 命令面板设计
|
|
1601
|
+
|
|
1602
|
+
### Detail presentation
|
|
1603
|
+
|
|
1604
|
+
Details automatically share field labels, `enum`/`dataSource` mappings and
|
|
1605
|
+
`fields[field].table` presentation settings (`label`, `display`, `options`,
|
|
1606
|
+
`dataSource`) with the list. No presentation switch is required. Default details
|
|
1607
|
+
show full text and all array items, preserving localized boolean labels.
|
|
1608
|
+
Table-only hidden fields remain available in details; shared `hidden` and
|
|
1609
|
+
`permissions.deny` always take precedence. Labels are resolved from the selected
|
|
1610
|
+
record, including when it is absent from the current list page.
|
|
1611
|
+
|
|
1612
|
+
```tsx
|
|
1613
|
+
<AutoCrudTable
|
|
1614
|
+
schema={schema}
|
|
1615
|
+
resource={resource}
|
|
1616
|
+
fields={{ description: { table: { hidden: true } } }}
|
|
1617
|
+
view={{
|
|
1618
|
+
overrides: {
|
|
1619
|
+
description: { label: 'Full description', index: 0 },
|
|
1620
|
+
region: { cell: ({ getValue }) => <strong>{String(getValue())}</strong> },
|
|
1621
|
+
},
|
|
1622
|
+
}}
|
|
1623
|
+
/>
|
|
1624
|
+
```
|
|
1625
|
+
|
|
1626
|
+
`view.overrides` changes details only. Custom list `cell` callbacks are not inherited
|
|
1627
|
+
by default because they can contain list actions or depend on table state. To
|
|
1628
|
+
explicitly reuse them, set `view.presentation: 'table'`; detail overrides still win.
|
|
1629
|
+
This provides a real **separate single-row** TanStack context, not the original
|
|
1630
|
+
list's pagination, selection or row index. Reused custom cells retain their own
|
|
1631
|
+
truncation and interaction behavior.
|
|
1632
|
+
|
|
1633
|
+
### 状态徽标颜色
|
|
1634
|
+
|
|
1635
|
+
对于 `table.display: "badge"`,标量字段的 `table.options` 可设置 `badgeTone`,支持 `neutral`、`success`、`warning`、`info`。徽标保留文字标签并附带装饰圆点,未配置颜色时沿用原有徽标样式,纯文本展示不受影响。业务状态与颜色的对应关系由调用方配置。
|
|
1636
|
+
|
|
1637
|
+
### 自定义行操作的菜单上下文
|
|
1638
|
+
|
|
1639
|
+
行操作组件接收上下文中的 `MenuItem`,应使用它以保证菜单根节点和菜单项共享同一运行时上下文。组件需要在菜单中保持弹窗会话时,可在选择事件中调用 `preventDefault()`,避免菜单关闭导致组件卸载。
|
|
1640
|
+
|
|
1641
|
+
### Row action menu UI contract
|
|
1642
|
+
|
|
1643
|
+
The row action menu created by `createActionsColumn` uses the public
|
|
1644
|
+
`@wordrhyme/ui` entry (a peer dependency). Custom `component` actions, including
|
|
1645
|
+
WordRhyme Host resource permission actions, must use menu items from that same
|
|
1646
|
+
shared entry. A private Radix or `@wordrhyme/shadcn` menu item cannot be inserted
|
|
1647
|
+
into this menu.
|
|
1648
|
+
|
|
1649
|
+
The package build keeps `@wordrhyme/ui` external. In a WordRhyme plugin remote,
|
|
1650
|
+
consume the Host's existing Federation share using
|
|
1651
|
+
`'@wordrhyme/ui': { singleton: true, import: false }`. Do not alias this import to
|
|
1652
|
+
private source or substitute an unshared subpath. Independently implemented
|
|
1653
|
+
menus remain supported when their context-dependent components stay together.
|
|
1654
|
+
|
|
1655
|
+
Runtime consumers must provide `@wordrhyme/ui >=0.1.0-alpha.20 <0.2.0`, which
|
|
1656
|
+
adds the CommonJS export condition while keeping the same ESM module instance.
|
|
1657
|
+
Publish that UI version before this AutoCrud change. The development dependency
|
|
1658
|
+
is pinned to the already-published alpha.19 for reproducible ESM tests and type
|
|
1659
|
+
checks until alpha.20 is published; it is not the supported CommonJS runtime.
|
|
1660
|
+
The CommonJS export/identity regression belongs to the UI provider repository.
|
|
1661
|
+
|
|
1662
|
+
### 按 ID 隐藏或替换自定义操作
|
|
1663
|
+
|
|
1664
|
+
拥有方为 custom 操作声明稳定 `id` 后,扩展可以在相同 CRUD target 和操作区域
|
|
1665
|
+
(`row`、`toolbar` 或 `batch`)使用同 ID 替换该操作;拥有方的原位置保留。
|
|
1666
|
+
替换使用扩展提供的完整操作,不继承原操作的组件或回调。
|
|
1667
|
+
|
|
1668
|
+
```ts
|
|
1669
|
+
crudActions.register({
|
|
1670
|
+
targetId: 'products',
|
|
1671
|
+
zone: 'row',
|
|
1672
|
+
ownerId: 'consumer',
|
|
1673
|
+
actions: [{ type: 'custom', id: 'products.inspect', hidden: true }],
|
|
1674
|
+
});
|
|
1675
|
+
```
|
|
1676
|
+
|
|
1677
|
+
- `hidden: true` 屏蔽同 target、同区域内所有匹配 ID 的 custom 操作,优先于替换。
|
|
1678
|
+
- 多个扩展提供同 ID 时,按已有 `order`、`ownerId`、注册序号排序,最后一个生效。
|
|
1679
|
+
- 未匹配拥有方的 ID 只追加一次;不带 ID 的 custom 操作继续独立追加。
|
|
1680
|
+
- 注销扩展后恢复拥有方操作;内置操作继续按 `type` 合并及执行权限检查。
|
|
1681
|
+
- custom 操作仍由业务方提供权限守卫;ID 不授予权限,也不影响后端鉴权。
|
|
1682
|
+
|
|
1683
|
+
## Styles
|
|
1684
|
+
|
|
1685
|
+
Choose one mode and import only the highest-level package you use.
|
|
1686
|
+
|
|
1687
|
+
With Tailwind CSS v4, in your application stylesheet:
|
|
1688
|
+
|
|
1689
|
+
```css
|
|
1690
|
+
@import 'tailwindcss';
|
|
1691
|
+
@import '@wordrhyme/auto-crud/tailwind.css';
|
|
1692
|
+
```
|
|
1693
|
+
|
|
1694
|
+
Without Tailwind CSS, in your application entry:
|
|
1695
|
+
|
|
1696
|
+
```ts
|
|
1697
|
+
import '@wordrhyme/auto-crud/styles.css';
|
|
1698
|
+
```
|
|
1699
|
+
|
|
1700
|
+
See the [shared style guide](https://github.com/denvey/wordrhyme-components#styles)
|
|
1701
|
+
for theme setup, dark mode, and custom classes.
|