@wordrhyme/auto-crud 1.12.1 → 1.12.2

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/dist/index.cjs CHANGED
@@ -4172,6 +4172,14 @@ function inferFilterVariantByFieldName(fieldName) {
4172
4172
  //#region src/lib/schema-bridge/zod-to-columns.tsx
4173
4173
  const parsedFieldCache = /* @__PURE__ */ new WeakMap();
4174
4174
  const baseTableSchemaCache = /* @__PURE__ */ new WeakMap();
4175
+ /** Cache generated value cells; custom cells keep observing every table state update. */
4176
+ function memoCell(render) {
4177
+ const ValueCell = react.memo(function ValueCell$1(context) {
4178
+ useDateFormatterVersion();
4179
+ return render(context);
4180
+ });
4181
+ return (context) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ValueCell, { ...context });
4182
+ }
4175
4183
  /**
4176
4184
  * 解析 Zod 字段类型
4177
4185
  */
@@ -4392,7 +4400,7 @@ function createTableSchema(schema, options) {
4392
4400
  column,
4393
4401
  label
4394
4402
  }),
4395
- cell: ({ row }) => renderCell(row.getValue(key), parsed.type, meta.options),
4403
+ cell: memoCell(({ row }) => renderCell(row.getValue(key), parsed.type, meta.options)),
4396
4404
  enableColumnFilter: true,
4397
4405
  enableSorting: true,
4398
4406
  meta,
@@ -5388,6 +5396,37 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
5388
5396
  debounceMs,
5389
5397
  throttleMs
5390
5398
  ]);
5399
+ const state = table.getState();
5400
+ const tableContent = (0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
5401
+ pagination,
5402
+ table,
5403
+ classNames,
5404
+ expandedRow
5405
+ }), [
5406
+ table,
5407
+ data,
5408
+ columns,
5409
+ getRowId,
5410
+ pageCount,
5411
+ total,
5412
+ stableInitialState,
5413
+ pagination,
5414
+ classNames,
5415
+ expandedRow,
5416
+ state.columnFilters,
5417
+ state.columnOrder,
5418
+ state.columnPinning,
5419
+ state.columnSizing,
5420
+ state.columnSizingInfo,
5421
+ state.columnVisibility,
5422
+ state.expanded,
5423
+ state.globalFilter,
5424
+ state.grouping,
5425
+ state.pagination,
5426
+ state.rowPinning,
5427
+ state.rowSelection,
5428
+ state.sorting
5429
+ ]);
5391
5430
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5392
5431
  className: "space-y-4",
5393
5432
  children: [
@@ -5415,12 +5454,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
5415
5454
  ]
5416
5455
  })]
5417
5456
  }),
5418
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
5419
- pagination,
5420
- table,
5421
- classNames,
5422
- expandedRow
5423
- }),
5457
+ tableContent,
5424
5458
  enableRowSelection && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTableActionBar, {
5425
5459
  table,
5426
5460
  onDeleteSelected,
@@ -7167,7 +7201,7 @@ function useDynamicFilterOptions(fields) {
7167
7201
  react.useEffect(() => () => {
7168
7202
  for (const field of Object.keys(controllersRef.current)) clearFieldRequest(field);
7169
7203
  }, [clearFieldRequest]);
7170
- return {
7204
+ return react.useMemo(() => ({
7171
7205
  hasMoreByField,
7172
7206
  labelOptionsByField,
7173
7207
  loadingByField,
@@ -7177,7 +7211,17 @@ function useDynamicFilterOptions(fields) {
7177
7211
  searchableByField,
7178
7212
  loadMore: (field) => loadFieldOptions(field, true),
7179
7213
  setSearchValue
7180
- };
7214
+ }), [
7215
+ hasMoreByField,
7216
+ labelOptionsByField,
7217
+ loadingByField,
7218
+ optionsByField,
7219
+ registeredByField,
7220
+ searchValues,
7221
+ searchableByField,
7222
+ loadFieldOptions,
7223
+ setSearchValue
7224
+ ]);
7181
7225
  }
7182
7226
  function rowHasResolveValue(row, field, value) {
7183
7227
  const rowValue = row[field];
@@ -7288,15 +7332,22 @@ function useDynamicResolveOptions(fields, rows, hiddenColumns) {
7288
7332
  rows,
7289
7333
  sourceEntries
7290
7334
  ]);
7291
- const displayOptionsByField = { ...optionsByField };
7292
- for (const field of Object.keys(fields ?? {}).filter((key) => !hiddenColumns.includes(key))) {
7293
- const projectedOptions = rows.flatMap((row) => {
7294
- const option = readCrudReferenceOption(row, field, row[field]);
7295
- return option ? [option] : [];
7296
- });
7297
- if (projectedOptions.length > 0) displayOptionsByField[field] = mergeFilterOptions(projectedOptions, optionsByField[field] ?? []);
7298
- }
7299
- return { optionsByField: displayOptionsByField };
7335
+ return react.useMemo(() => {
7336
+ const displayOptionsByField = { ...optionsByField };
7337
+ for (const field of Object.keys(fields ?? {}).filter((key) => !hiddenColumns.includes(key))) {
7338
+ const projectedOptions = rows.flatMap((row) => {
7339
+ const option = readCrudReferenceOption(row, field, row[field]);
7340
+ return option ? [option] : [];
7341
+ });
7342
+ if (projectedOptions.length > 0) displayOptionsByField[field] = mergeFilterOptions(projectedOptions, optionsByField[field] ?? []);
7343
+ }
7344
+ return { optionsByField: displayOptionsByField };
7345
+ }, [
7346
+ optionsByField,
7347
+ fields,
7348
+ hiddenColumns,
7349
+ rows
7350
+ ]);
7300
7351
  }
7301
7352
  function getOptionLabel(value, options) {
7302
7353
  const stringValue = String(value);
@@ -7404,7 +7455,7 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
7404
7455
  const options = tableConfig?.dataSource ? mergeFieldOptions(dynamicResolveOptions, presentationOptions) : presentationOptions ?? mergedSharedDynamicOptions;
7405
7456
  result[key] = {
7406
7457
  ...result[key],
7407
- cell: ({ row, getValue }) => {
7458
+ cell: memoCell(({ row, getValue }) => {
7408
7459
  const value = getValue();
7409
7460
  return config.format?.(value, {
7410
7461
  row: row.original,
@@ -7413,7 +7464,7 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
7413
7464
  true: "true",
7414
7465
  false: "false"
7415
7466
  }, options, display ?? "auto");
7416
- }
7467
+ })
7417
7468
  };
7418
7469
  }
7419
7470
  }
@@ -7742,10 +7793,14 @@ function resolveActions(actions, defaults, rowActionsLocale, context) {
7742
7793
  * 高级 CRUD 表格组件,封装了完整的增删改查流程
7743
7794
  */
7744
7795
  function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, view: viewConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate, onExport }) {
7745
- const locale = resolveLocale(localeProp);
7796
+ const locale = react.useMemo(() => resolveLocale(localeProp), [localeProp]);
7746
7797
  const getPagination = react.useCallback(() => id ? tablePagination.get(id) : void 0, [id]);
7747
7798
  const registeredPagination = react.useSyncExternalStore(tablePagination.subscribe, getPagination, getPagination);
7748
7799
  const pagination = tableConfig?.pagination ?? registeredPagination;
7800
+ const paginationOptions = react.useMemo(() => pagination ? {
7801
+ pageJumpLabel: locale.pagination?.pageJump,
7802
+ ...pagination
7803
+ } : void 0, [pagination, locale.pagination?.pageJump]);
7749
7804
  const resolvedSchema = resource.schema ?? schema;
7750
7805
  const resolvedFields = react.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
7751
7806
  const can = {
@@ -7777,6 +7832,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7777
7832
  denyFields,
7778
7833
  tableConfig?.overrides
7779
7834
  ]);
7835
+ const excludedColumns = react.useMemo(() => hiddenColumns.filter((key) => !filterOnly.includes(key)), [hiddenColumns, filterOnly]);
7780
7836
  const dynamicResolveOptions = useDynamicResolveOptions(resolvedFields, resource.tableData.data, hiddenColumns);
7781
7837
  const resourceIdKey = resource.idKey ?? "id";
7782
7838
  const actionRegistryVersion = useCrudActionsVersion();
@@ -7968,13 +8024,13 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7968
8024
  const { type } = parseZodField(resolvedSchema.shape[key]);
7969
8025
  formattedOverrides[key] = {
7970
8026
  ...override,
7971
- cell: (context) => {
8027
+ cell: memoCell((context) => {
7972
8028
  const value = context.getValue();
7973
8029
  return config.format?.(value, {
7974
8030
  row: context.row.original,
7975
8031
  target: "display"
7976
8032
  }) ?? renderCell(value, type, context.column.columnDef.meta?.options);
7977
- }
8033
+ })
7978
8034
  };
7979
8035
  }
7980
8036
  }
@@ -8136,17 +8192,14 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
8136
8192
  data: resource.tableData.data,
8137
8193
  schema: resolvedSchema,
8138
8194
  pageCount: resource.tableData.pageCount,
8139
- pagination: pagination ? {
8140
- pageJumpLabel: locale.pagination?.pageJump,
8141
- ...pagination
8142
- } : void 0,
8195
+ pagination: paginationOptions,
8143
8196
  ...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
8144
8197
  getRowId: tableConfig?.getRowId,
8145
8198
  expandedRow: tableConfig?.expandedRow,
8146
8199
  defaultExpanded: tableConfig?.defaultExpanded,
8147
8200
  overrides: tableOverrides,
8148
8201
  classNames: tableConfig?.classNames,
8149
- exclude: hiddenColumns.filter((key) => !filterOnly.includes(key)),
8202
+ exclude: excludedColumns,
8150
8203
  filterOnly,
8151
8204
  filterMode: tableConfig?.filterModes,
8152
8205
  search: searchConfig,
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 react_jsx_runtime9 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime8 from "react/jsx-runtime";
3
3
  import * as React$1 from "react";
4
4
  import { ComponentProps, ReactNode } from "react";
5
5
  import * as _tanstack_react_table0 from "@tanstack/react-table";
@@ -672,7 +672,7 @@ declare function DataTable<TData>({
672
672
  className,
673
673
  classNames,
674
674
  ...props
675
- }: DataTableProps<TData>): react_jsx_runtime9.JSX.Element;
675
+ }: DataTableProps<TData>): react_jsx_runtime8.JSX.Element;
676
676
  //#endregion
677
677
  //#region src/components/auto-crud/auto-table-action-bar.d.ts
678
678
  /** 批量更新字段配置 */
@@ -761,7 +761,7 @@ declare function AutoTableActionBar<TData>({
761
761
  extraActions,
762
762
  actions,
763
763
  deleteConfirmation
764
- }: AutoTableActionBarProps<TData>): react_jsx_runtime9.JSX.Element;
764
+ }: AutoTableActionBarProps<TData>): react_jsx_runtime8.JSX.Element;
765
765
  //#endregion
766
766
  //#region src/lib/schema-bridge/types.d.ts
767
767
  /**
@@ -1099,7 +1099,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
1099
1099
  onSelectedRowsChange,
1100
1100
  getSelectedRows,
1101
1101
  exportTableRef
1102
- }: AutoTableProps<T>): react_jsx_runtime9.JSX.Element;
1102
+ }: AutoTableProps<T>): react_jsx_runtime8.JSX.Element;
1103
1103
  //#endregion
1104
1104
  //#region src/lib/row-action-dialog.d.ts
1105
1105
  interface RowActionDialogProps {
@@ -1562,7 +1562,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
1562
1562
  locale: localeProp,
1563
1563
  onCreate,
1564
1564
  onExport
1565
- }: AutoCrudTableProps<TSchema>): react_jsx_runtime9.JSX.Element;
1565
+ }: AutoCrudTableProps<TSchema>): react_jsx_runtime8.JSX.Element;
1566
1566
  //#endregion
1567
1567
  //#region src/components/auto-crud/auto-form.d.ts
1568
1568
  interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
@@ -1601,7 +1601,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
1601
1601
  labelAlign,
1602
1602
  labelWidth,
1603
1603
  showSubmitButton
1604
- }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime9.JSX.Element;
1604
+ }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime8.JSX.Element;
1605
1605
  declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
1606
1606
  ref?: React.Ref<AutoFormRef>;
1607
1607
  }) => ReturnType<typeof AutoFormInner>;
@@ -1620,7 +1620,7 @@ declare function AutoTableSimpleFilters<TData>({
1620
1620
  filters: externalFilters,
1621
1621
  onFiltersChange,
1622
1622
  leading
1623
- }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime9.JSX.Element | null;
1623
+ }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime8.JSX.Element | null;
1624
1624
  //#endregion
1625
1625
  //#region src/components/auto-crud/form-modal.d.ts
1626
1626
  type ModalVariant = 'dialog' | 'sheet';
@@ -1664,7 +1664,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
1664
1664
  labelAlign,
1665
1665
  labelWidth,
1666
1666
  className
1667
- }: CrudFormModalProps<T>): react_jsx_runtime9.JSX.Element;
1667
+ }: CrudFormModalProps<T>): react_jsx_runtime8.JSX.Element;
1668
1668
  //#endregion
1669
1669
  //#region src/components/auto-crud/import-dialog.d.ts
1670
1670
  interface ImportDialogProps {
@@ -1686,7 +1686,7 @@ declare function ImportDialog({
1686
1686
  columns,
1687
1687
  title,
1688
1688
  locale
1689
- }: ImportDialogProps): react_jsx_runtime9.JSX.Element;
1689
+ }: ImportDialogProps): react_jsx_runtime8.JSX.Element;
1690
1690
  //#endregion
1691
1691
  //#region src/components/auto-crud/export-dialog.d.ts
1692
1692
  type ExportMode = 'selected' | 'filtered';
@@ -1706,7 +1706,7 @@ declare function ExportDialog({
1706
1706
  selectedCount,
1707
1707
  onExport,
1708
1708
  canExportFiltered
1709
- }: ExportDialogProps): react_jsx_runtime9.JSX.Element;
1709
+ }: ExportDialogProps): react_jsx_runtime8.JSX.Element;
1710
1710
  //#endregion
1711
1711
  //#region src/components/data-table/data-table-advanced-toolbar.d.ts
1712
1712
  interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1717,7 +1717,7 @@ declare function DataTableAdvancedToolbar<TData>({
1717
1717
  children,
1718
1718
  className,
1719
1719
  ...props
1720
- }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime9.JSX.Element;
1720
+ }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime8.JSX.Element;
1721
1721
  //#endregion
1722
1722
  //#region src/components/data-table/data-table-column-header.d.ts
1723
1723
  interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
@@ -1729,7 +1729,7 @@ declare function DataTableColumnHeader<TData, TValue>({
1729
1729
  label,
1730
1730
  className,
1731
1731
  ...props
1732
- }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime9.JSX.Element;
1732
+ }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime8.JSX.Element;
1733
1733
  //#endregion
1734
1734
  //#region src/components/data-table/data-table-faceted-filter.d.ts
1735
1735
  interface DataTableFacetedFilterProps<TData, TValue> {
@@ -1743,7 +1743,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
1743
1743
  title,
1744
1744
  options,
1745
1745
  multiple
1746
- }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime9.JSX.Element;
1746
+ }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime8.JSX.Element;
1747
1747
  //#endregion
1748
1748
  //#region src/components/data-table/data-table-pagination.d.ts
1749
1749
  interface DataTablePaginationProps<TData> extends React.ComponentProps<'div'>, TablePaginationOptions {
@@ -1759,7 +1759,7 @@ declare function DataTablePagination<TData>({
1759
1759
  pageJumpLabel,
1760
1760
  className,
1761
1761
  ...props
1762
- }: DataTablePaginationProps<TData>): react_jsx_runtime9.JSX.Element;
1762
+ }: DataTablePaginationProps<TData>): react_jsx_runtime8.JSX.Element;
1763
1763
  //#endregion
1764
1764
  //#region src/components/data-table/data-table-toolbar.d.ts
1765
1765
  interface DataTableToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1770,7 +1770,7 @@ declare function DataTableToolbar<TData>({
1770
1770
  children,
1771
1771
  className,
1772
1772
  ...props
1773
- }: DataTableToolbarProps<TData>): react_jsx_runtime9.JSX.Element;
1773
+ }: DataTableToolbarProps<TData>): react_jsx_runtime8.JSX.Element;
1774
1774
  //#endregion
1775
1775
  //#region src/components/data-table/data-table-view-options.d.ts
1776
1776
  interface DataTableViewOptionsProps<TData> extends PopoverContentProps {
@@ -1783,7 +1783,7 @@ declare function DataTableViewOptions<TData>({
1783
1783
  disabled,
1784
1784
  locale,
1785
1785
  ...props
1786
- }: DataTableViewOptionsProps<TData>): react_jsx_runtime9.JSX.Element;
1786
+ }: DataTableViewOptionsProps<TData>): react_jsx_runtime8.JSX.Element;
1787
1787
  //#endregion
1788
1788
  //#region src/lib/crud-actions.d.ts
1789
1789
  type CrudActionZone = 'toolbar' | 'row' | 'batch';
package/dist/index.js CHANGED
@@ -4157,6 +4157,14 @@ function inferFilterVariantByFieldName(fieldName) {
4157
4157
  //#region src/lib/schema-bridge/zod-to-columns.tsx
4158
4158
  const parsedFieldCache = /* @__PURE__ */ new WeakMap();
4159
4159
  const baseTableSchemaCache = /* @__PURE__ */ new WeakMap();
4160
+ /** Cache generated value cells; custom cells keep observing every table state update. */
4161
+ function memoCell(render) {
4162
+ const ValueCell = React.memo(function ValueCell$1(context) {
4163
+ useDateFormatterVersion();
4164
+ return render(context);
4165
+ });
4166
+ return (context) => /* @__PURE__ */ jsx(ValueCell, { ...context });
4167
+ }
4160
4168
  /**
4161
4169
  * 解析 Zod 字段类型
4162
4170
  */
@@ -4377,7 +4385,7 @@ function createTableSchema(schema, options) {
4377
4385
  column,
4378
4386
  label
4379
4387
  }),
4380
- cell: ({ row }) => renderCell(row.getValue(key), parsed.type, meta.options),
4388
+ cell: memoCell(({ row }) => renderCell(row.getValue(key), parsed.type, meta.options)),
4381
4389
  enableColumnFilter: true,
4382
4390
  enableSorting: true,
4383
4391
  meta,
@@ -5373,6 +5381,37 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
5373
5381
  debounceMs,
5374
5382
  throttleMs
5375
5383
  ]);
5384
+ const state = table.getState();
5385
+ const tableContent = useMemo(() => /* @__PURE__ */ jsx(DataTable, {
5386
+ pagination,
5387
+ table,
5388
+ classNames,
5389
+ expandedRow
5390
+ }), [
5391
+ table,
5392
+ data,
5393
+ columns,
5394
+ getRowId,
5395
+ pageCount,
5396
+ total,
5397
+ stableInitialState,
5398
+ pagination,
5399
+ classNames,
5400
+ expandedRow,
5401
+ state.columnFilters,
5402
+ state.columnOrder,
5403
+ state.columnPinning,
5404
+ state.columnSizing,
5405
+ state.columnSizingInfo,
5406
+ state.columnVisibility,
5407
+ state.expanded,
5408
+ state.globalFilter,
5409
+ state.grouping,
5410
+ state.pagination,
5411
+ state.rowPinning,
5412
+ state.rowSelection,
5413
+ state.sorting
5414
+ ]);
5376
5415
  return /* @__PURE__ */ jsxs("div", {
5377
5416
  className: "space-y-4",
5378
5417
  children: [
@@ -5400,12 +5439,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
5400
5439
  ]
5401
5440
  })]
5402
5441
  }),
5403
- /* @__PURE__ */ jsx(DataTable, {
5404
- pagination,
5405
- table,
5406
- classNames,
5407
- expandedRow
5408
- }),
5442
+ tableContent,
5409
5443
  enableRowSelection && /* @__PURE__ */ jsx(AutoTableActionBar, {
5410
5444
  table,
5411
5445
  onDeleteSelected,
@@ -7152,7 +7186,7 @@ function useDynamicFilterOptions(fields) {
7152
7186
  React.useEffect(() => () => {
7153
7187
  for (const field of Object.keys(controllersRef.current)) clearFieldRequest(field);
7154
7188
  }, [clearFieldRequest]);
7155
- return {
7189
+ return React.useMemo(() => ({
7156
7190
  hasMoreByField,
7157
7191
  labelOptionsByField,
7158
7192
  loadingByField,
@@ -7162,7 +7196,17 @@ function useDynamicFilterOptions(fields) {
7162
7196
  searchableByField,
7163
7197
  loadMore: (field) => loadFieldOptions(field, true),
7164
7198
  setSearchValue
7165
- };
7199
+ }), [
7200
+ hasMoreByField,
7201
+ labelOptionsByField,
7202
+ loadingByField,
7203
+ optionsByField,
7204
+ registeredByField,
7205
+ searchValues,
7206
+ searchableByField,
7207
+ loadFieldOptions,
7208
+ setSearchValue
7209
+ ]);
7166
7210
  }
7167
7211
  function rowHasResolveValue(row, field, value) {
7168
7212
  const rowValue = row[field];
@@ -7273,15 +7317,22 @@ function useDynamicResolveOptions(fields, rows, hiddenColumns) {
7273
7317
  rows,
7274
7318
  sourceEntries
7275
7319
  ]);
7276
- const displayOptionsByField = { ...optionsByField };
7277
- for (const field of Object.keys(fields ?? {}).filter((key) => !hiddenColumns.includes(key))) {
7278
- const projectedOptions = rows.flatMap((row) => {
7279
- const option = readCrudReferenceOption(row, field, row[field]);
7280
- return option ? [option] : [];
7281
- });
7282
- if (projectedOptions.length > 0) displayOptionsByField[field] = mergeFilterOptions(projectedOptions, optionsByField[field] ?? []);
7283
- }
7284
- return { optionsByField: displayOptionsByField };
7320
+ return React.useMemo(() => {
7321
+ const displayOptionsByField = { ...optionsByField };
7322
+ for (const field of Object.keys(fields ?? {}).filter((key) => !hiddenColumns.includes(key))) {
7323
+ const projectedOptions = rows.flatMap((row) => {
7324
+ const option = readCrudReferenceOption(row, field, row[field]);
7325
+ return option ? [option] : [];
7326
+ });
7327
+ if (projectedOptions.length > 0) displayOptionsByField[field] = mergeFilterOptions(projectedOptions, optionsByField[field] ?? []);
7328
+ }
7329
+ return { optionsByField: displayOptionsByField };
7330
+ }, [
7331
+ optionsByField,
7332
+ fields,
7333
+ hiddenColumns,
7334
+ rows
7335
+ ]);
7285
7336
  }
7286
7337
  function getOptionLabel(value, options) {
7287
7338
  const stringValue = String(value);
@@ -7389,7 +7440,7 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
7389
7440
  const options = tableConfig?.dataSource ? mergeFieldOptions(dynamicResolveOptions, presentationOptions) : presentationOptions ?? mergedSharedDynamicOptions;
7390
7441
  result[key] = {
7391
7442
  ...result[key],
7392
- cell: ({ row, getValue }) => {
7443
+ cell: memoCell(({ row, getValue }) => {
7393
7444
  const value = getValue();
7394
7445
  return config.format?.(value, {
7395
7446
  row: row.original,
@@ -7398,7 +7449,7 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
7398
7449
  true: "true",
7399
7450
  false: "false"
7400
7451
  }, options, display ?? "auto");
7401
- }
7452
+ })
7402
7453
  };
7403
7454
  }
7404
7455
  }
@@ -7727,10 +7778,14 @@ function resolveActions(actions, defaults, rowActionsLocale, context) {
7727
7778
  * 高级 CRUD 表格组件,封装了完整的增删改查流程
7728
7779
  */
7729
7780
  function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, view: viewConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate, onExport }) {
7730
- const locale = resolveLocale(localeProp);
7781
+ const locale = React.useMemo(() => resolveLocale(localeProp), [localeProp]);
7731
7782
  const getPagination = React.useCallback(() => id ? tablePagination.get(id) : void 0, [id]);
7732
7783
  const registeredPagination = React.useSyncExternalStore(tablePagination.subscribe, getPagination, getPagination);
7733
7784
  const pagination = tableConfig?.pagination ?? registeredPagination;
7785
+ const paginationOptions = React.useMemo(() => pagination ? {
7786
+ pageJumpLabel: locale.pagination?.pageJump,
7787
+ ...pagination
7788
+ } : void 0, [pagination, locale.pagination?.pageJump]);
7734
7789
  const resolvedSchema = resource.schema ?? schema;
7735
7790
  const resolvedFields = React.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
7736
7791
  const can = {
@@ -7762,6 +7817,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7762
7817
  denyFields,
7763
7818
  tableConfig?.overrides
7764
7819
  ]);
7820
+ const excludedColumns = React.useMemo(() => hiddenColumns.filter((key) => !filterOnly.includes(key)), [hiddenColumns, filterOnly]);
7765
7821
  const dynamicResolveOptions = useDynamicResolveOptions(resolvedFields, resource.tableData.data, hiddenColumns);
7766
7822
  const resourceIdKey = resource.idKey ?? "id";
7767
7823
  const actionRegistryVersion = useCrudActionsVersion();
@@ -7953,13 +8009,13 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7953
8009
  const { type } = parseZodField(resolvedSchema.shape[key]);
7954
8010
  formattedOverrides[key] = {
7955
8011
  ...override,
7956
- cell: (context) => {
8012
+ cell: memoCell((context) => {
7957
8013
  const value = context.getValue();
7958
8014
  return config.format?.(value, {
7959
8015
  row: context.row.original,
7960
8016
  target: "display"
7961
8017
  }) ?? renderCell(value, type, context.column.columnDef.meta?.options);
7962
- }
8018
+ })
7963
8019
  };
7964
8020
  }
7965
8021
  }
@@ -8121,17 +8177,14 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
8121
8177
  data: resource.tableData.data,
8122
8178
  schema: resolvedSchema,
8123
8179
  pageCount: resource.tableData.pageCount,
8124
- pagination: pagination ? {
8125
- pageJumpLabel: locale.pagination?.pageJump,
8126
- ...pagination
8127
- } : void 0,
8180
+ pagination: paginationOptions,
8128
8181
  ...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
8129
8182
  getRowId: tableConfig?.getRowId,
8130
8183
  expandedRow: tableConfig?.expandedRow,
8131
8184
  defaultExpanded: tableConfig?.defaultExpanded,
8132
8185
  overrides: tableOverrides,
8133
8186
  classNames: tableConfig?.classNames,
8134
- exclude: hiddenColumns.filter((key) => !filterOnly.includes(key)),
8187
+ exclude: excludedColumns,
8135
8188
  filterOnly,
8136
8189
  filterMode: tableConfig?.filterModes,
8137
8190
  search: searchConfig,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordrhyme/auto-crud",
3
3
  "type": "module",
4
- "version": "1.12.1",
4
+ "version": "1.12.2",
5
5
  "description": "Schema-first CRUD components with auto-generated tables and forms",
6
6
  "author": "wordrhyme",
7
7
  "license": "MIT",
@@ -94,11 +94,11 @@
94
94
  "tsdown": "^0.15.12",
95
95
  "typescript": "^5.9.3",
96
96
  "vitest": "^3.2.4",
97
- "@internal/eslint-config": "0.3.0",
97
+ "@internal/prettier-config": "0.0.1",
98
98
  "@internal/tsconfig": "0.1.0",
99
- "@internal/tsdown-config": "0.1.0",
99
+ "@internal/eslint-config": "0.3.0",
100
100
  "@internal/vitest-config": "0.1.0",
101
- "@internal/prettier-config": "0.0.1"
101
+ "@internal/tsdown-config": "0.1.0"
102
102
  },
103
103
  "prettier": "@internal/prettier-config",
104
104
  "scripts": {