@wordrhyme/auto-crud 1.5.3 → 1.5.5

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
@@ -66,18 +66,19 @@ function DataTablePagination({ table, pageSizeOptions = [
66
66
  40,
67
67
  50
68
68
  ], className,...props }) {
69
+ const total = table.options.rowCount ?? (table.options.manualPagination ? void 0 : table.getRowCount());
69
70
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
70
71
  className: cn("flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8", className),
71
72
  ...props,
72
73
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
73
- className: "flex-1 whitespace-nowrap text-muted-foreground text-sm",
74
- children: [
74
+ className: "flex flex-1 items-center gap-6 whitespace-nowrap text-muted-foreground text-sm",
75
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
75
76
  table.getFilteredSelectedRowModel().rows.length,
76
77
  " of",
77
78
  " ",
78
79
  table.getFilteredRowModel().rows.length,
79
80
  " row(s) selected."
80
- ]
81
+ ] }), total !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["Total: ", total] })]
81
82
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
82
83
  className: "flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8",
83
84
  children: [
@@ -404,6 +405,21 @@ function useDateFormatterVersion() {
404
405
  function getHostDateFormatter() {
405
406
  return hostDateFormatters[hostDateFormatters.length - 1]?.formatter;
406
407
  }
408
+ const canonicalDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
409
+ const canonicalDateTimePrefixPattern = /^(\d{4})-(\d{2})-(\d{2})(?=[T ])/;
410
+ function isValidCalendarDate(year, month, day) {
411
+ if (!year || !month || !day) return false;
412
+ const date = /* @__PURE__ */ new Date(`${year}-${month}-${day}T00:00:00.000Z`);
413
+ return !Number.isNaN(date.getTime()) && date.getUTCFullYear() === Number(year) && date.getUTCMonth() + 1 === Number(month) && date.getUTCDate() === Number(day);
414
+ }
415
+ function isValidCanonicalDate(value) {
416
+ const match = canonicalDatePattern.exec(value);
417
+ return !!match && isValidCalendarDate(match[1], match[2], match[3]);
418
+ }
419
+ function hasValidCanonicalDateTimePrefix(value) {
420
+ const match = canonicalDateTimePrefixPattern.exec(value);
421
+ return !match || isValidCalendarDate(match[1], match[2], match[3]);
422
+ }
407
423
  /**
408
424
  * Register the host's process-wide date presentation policy without coupling
409
425
  * AutoCrud to locale or timezone selection. The returned cleanup removes only
@@ -430,18 +446,45 @@ function setDateFormatter(formatter) {
430
446
  if (hostDateFormatters.length !== previousLength && getHostDateFormatter() !== currentFormatter) notifyDateFormatterChange();
431
447
  };
432
448
  }
433
- function formatDate(date, opts = {}) {
449
+ function formatDate(date, opts = {}, preset) {
434
450
  if (date === void 0) return "";
451
+ if (preset === "date" && typeof date === "string" && canonicalDatePattern.test(date)) return isValidCanonicalDate(date) ? date : "";
452
+ if (preset === "datetime" && typeof date === "string" && !hasValidCanonicalDateTimePrefix(date)) return "";
435
453
  try {
436
454
  const value = new Date(date);
455
+ if (Number.isNaN(value.getTime())) return "";
437
456
  const options = {
438
- month: opts.month ?? "long",
439
- day: opts.day ?? "numeric",
457
+ month: opts.month ?? (preset ? "2-digit" : "long"),
458
+ day: opts.day ?? (preset ? "2-digit" : "numeric"),
440
459
  year: opts.year ?? "numeric",
460
+ ...preset === "datetime" ? {
461
+ hour: opts.hour ?? "2-digit",
462
+ minute: opts.minute ?? "2-digit",
463
+ second: opts.second ?? "2-digit",
464
+ hourCycle: opts.hourCycle ?? "h23"
465
+ } : {},
441
466
  ...opts
442
467
  };
443
468
  const hostDateFormatter = getHostDateFormatter();
444
- return hostDateFormatter ? hostDateFormatter(value, options) : new Intl.DateTimeFormat("en-US", options).format(value);
469
+ if (hostDateFormatter) return preset ? hostDateFormatter(value, options, preset) : hostDateFormatter(value, options);
470
+ if (preset) {
471
+ const parts = new Intl.DateTimeFormat("en-CA", {
472
+ timeZone: opts.timeZone,
473
+ year: "numeric",
474
+ month: "2-digit",
475
+ day: "2-digit",
476
+ ...preset === "datetime" ? {
477
+ hour: "2-digit",
478
+ minute: "2-digit",
479
+ second: "2-digit",
480
+ hourCycle: "h23"
481
+ } : {}
482
+ }).formatToParts(value);
483
+ const read = (type) => parts.find((part) => part.type === type)?.value ?? "";
484
+ const formattedDate = `${read("year")}-${read("month")}-${read("day")}`;
485
+ return preset === "datetime" ? `${formattedDate} ${read("hour")}:${read("minute")}:${read("second")}` : formattedDate;
486
+ }
487
+ return new Intl.DateTimeFormat("en-US", options).format(value);
445
488
  } catch {
446
489
  return "";
447
490
  }
@@ -4025,7 +4068,7 @@ const filterModeConfig = {
4025
4068
  tooltip: "Linear-style command filters"
4026
4069
  }
4027
4070
  };
4028
- function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4071
+ function AutoTable({ schema, data, pageCount = 1, total, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4029
4072
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
4030
4073
  const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
4031
4074
  const showToggle = modes.length > 1;
@@ -4054,23 +4097,25 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4054
4097
  exclude,
4055
4098
  actions
4056
4099
  ]);
4100
+ const stableInitialState = (0, react.useMemo)(() => ({
4101
+ sorting: initialSorting,
4102
+ columnPinning: pinnedColumns ?? {
4103
+ left: enableRowSelection ? ["select"] : [],
4104
+ right: actions ? ["actions"] : []
4105
+ }
4106
+ }), [
4107
+ initialSorting,
4108
+ pinnedColumns,
4109
+ enableRowSelection,
4110
+ actions
4111
+ ]);
4057
4112
  const { table, shallow, debounceMs, throttleMs } = useDataTable({
4058
4113
  data,
4059
4114
  columns,
4060
4115
  pageCount,
4116
+ ...total !== void 0 ? { rowCount: total } : {},
4061
4117
  enableAdvancedFilter,
4062
- initialState: (0, react.useMemo)(() => ({
4063
- sorting: initialSorting,
4064
- columnPinning: pinnedColumns ?? {
4065
- left: enableRowSelection ? ["select"] : [],
4066
- right: actions ? ["actions"] : []
4067
- }
4068
- }), [
4069
- initialSorting,
4070
- pinnedColumns,
4071
- enableRowSelection,
4072
- actions
4073
- ]),
4118
+ initialState: stableInitialState,
4074
4119
  shallow: false,
4075
4120
  clearOnDefault: true
4076
4121
  });
@@ -5975,6 +6020,16 @@ function mergeFields(base, override) {
5975
6020
  const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
5976
6021
  return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
5977
6022
  }
6023
+ function applyResourceTablePresentation(fields, resourceFields) {
6024
+ if (!fields || !resourceFields) return fields;
6025
+ return Object.fromEntries(Object.entries(fields).map(([key, config]) => {
6026
+ const table = resourceFields[key]?.table;
6027
+ return [key, table === void 0 ? config : {
6028
+ ...config,
6029
+ table: mergeFieldPart(config.table, table)
6030
+ }];
6031
+ }));
6032
+ }
5978
6033
  function normalizeFieldOptions(options) {
5979
6034
  if (!options || options.length === 0) return void 0;
5980
6035
  return options.map((option) => ({
@@ -5982,6 +6037,18 @@ function normalizeFieldOptions(options) {
5982
6037
  value: String(option.value)
5983
6038
  }));
5984
6039
  }
6040
+ function getTableConfig(config) {
6041
+ return config.table && typeof config.table === "object" ? config.table : void 0;
6042
+ }
6043
+ function getTableOptions(config) {
6044
+ const table = getTableConfig(config);
6045
+ if (table?.options) return normalizeFieldOptions(table.options);
6046
+ if (table?.dataSource) return void 0;
6047
+ return normalizeFieldOptions(config.enum);
6048
+ }
6049
+ function getTableDataSource(config) {
6050
+ return getTableConfig(config)?.dataSource ?? config.dataSource;
6051
+ }
5985
6052
  function toTableOptions(options) {
5986
6053
  return options?.map(({ label, value, searchText, count, icon }) => ({
5987
6054
  label,
@@ -6057,8 +6124,8 @@ function mergeOptionsByField(left, right) {
6057
6124
  function shouldResolveOptions(field, config, hiddenColumns) {
6058
6125
  if (!config) return false;
6059
6126
  if (hiddenColumns.has(field)) return false;
6060
- if (normalizeFieldOptions(config.enum)) return false;
6061
- return normalizeDataSourceConfig(config.dataSource) !== void 0;
6127
+ if (getTableOptions(config)) return false;
6128
+ return normalizeDataSourceConfig(getTableDataSource(config)) !== void 0;
6062
6129
  }
6063
6130
  function useRegistryVersion(subscribe) {
6064
6131
  const [version$1, setVersion] = react.useState(0);
@@ -6303,7 +6370,7 @@ function useDynamicResolveOptions(fields, rows, hiddenColumns) {
6303
6370
  const hiddenSet = new Set(hiddenColumns);
6304
6371
  return Object.entries(fields).flatMap(([field, config]) => {
6305
6372
  if (!shouldResolveOptions(field, config, hiddenSet)) return [];
6306
- const source = normalizeDataSourceConfig(config.dataSource);
6373
+ const source = normalizeDataSourceConfig(getTableDataSource(config));
6307
6374
  const values = getResolveValues(rows, field);
6308
6375
  return source && values.length > 0 ? [{
6309
6376
  field,
@@ -6400,12 +6467,16 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
6400
6467
  const result = { ...legacyOverrides };
6401
6468
  if (fields) for (const [key, config] of Object.entries(fields)) {
6402
6469
  const fieldOptions = normalizeFieldOptions(config.enum);
6470
+ const tableConfig = getTableConfig(config);
6471
+ const presentationOptions = getTableOptions(config);
6403
6472
  const tableOptions = toTableOptions(fieldOptions);
6404
6473
  const filterDataSourceRegistered = dynamicFilterState?.registeredByField[key];
6405
6474
  const filterDataSourceSearchable = dynamicFilterState?.searchableByField[key];
6406
6475
  const currentDynamicOptions = !fieldOptions && filterDataSourceRegistered ? toTableOptions(dynamicFilterState?.optionsByField[key] ?? []) : void 0;
6407
- const mergedDynamicOptions = mergeFieldOptions(!fieldOptions && filterDataSourceRegistered ? dynamicFilterState?.labelOptionsByField[key] ?? dynamicFilterState?.optionsByField[key] ?? [] : void 0, !fieldOptions ? dynamicResolveState?.optionsByField[key] : void 0);
6408
- const dynamicOptions = !fieldOptions && mergedDynamicOptions ? toTableOptions(mergedDynamicOptions) : void 0;
6476
+ const dynamicFilterLabelOptions = !fieldOptions && filterDataSourceRegistered ? dynamicFilterState?.labelOptionsByField[key] ?? dynamicFilterState?.optionsByField[key] ?? [] : void 0;
6477
+ const dynamicResolveOptions = !presentationOptions ? dynamicResolveState?.optionsByField[key] : void 0;
6478
+ const mergedSharedDynamicOptions = mergeFieldOptions(dynamicFilterLabelOptions, tableConfig?.dataSource ? void 0 : dynamicResolveOptions);
6479
+ const dynamicOptions = !fieldOptions && mergedSharedDynamicOptions ? toTableOptions(mergedSharedDynamicOptions) : void 0;
6409
6480
  const tableMeta = config.table !== false && typeof config.table === "object" ? config.table.meta : void 0;
6410
6481
  const fieldEnumMeta = tableOptions ? {
6411
6482
  options: tableOptions,
@@ -6469,11 +6540,24 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
6469
6540
  hidden: true
6470
6541
  };
6471
6542
  else if (config.table && typeof config.table === "object") {
6472
- const { meta,...tableProps } = config.table;
6543
+ const { meta, display,...tableProps } = config.table;
6544
+ delete tableProps.options;
6545
+ delete tableProps.dataSource;
6473
6546
  result[key] = {
6474
6547
  ...result[key],
6475
6548
  ...tableProps
6476
6549
  };
6550
+ const hasTableLabels = config.table.options !== void 0 || config.table.dataSource !== void 0;
6551
+ if (display && display !== "auto" || hasTableLabels) {
6552
+ const options = presentationOptions ?? dynamicResolveOptions ?? mergedSharedDynamicOptions;
6553
+ result[key] = {
6554
+ ...result[key],
6555
+ cell: ({ row }) => renderFieldValue(row.getValue(key), "string", {
6556
+ true: "true",
6557
+ false: "false"
6558
+ }, options, display ?? "auto")
6559
+ };
6560
+ }
6477
6561
  }
6478
6562
  }
6479
6563
  return result;
@@ -6521,7 +6605,9 @@ function buildHiddenColumns(fields, legacyHidden, denyFields, legacyOverrides) {
6521
6605
  for (const key of DEFAULT_HIDDEN_AUDIT_FIELDS) if (!legacyHiddenSet.has(key) && !denySet.has(key) && isTableOverrideExplicitlyVisible(legacyOverrides?.[key])) hidden.delete(key);
6522
6606
  if (fields) for (const [key, config] of Object.entries(fields)) {
6523
6607
  if (isDefaultHiddenAuditField(key) && !legacyHiddenSet.has(key) && !denySet.has(key) && isFieldTableExplicitlyVisible(config)) hidden.delete(key);
6524
- if (config.hidden) hidden.add(key);
6608
+ if (config.table && typeof config.table === "object" && config.table.hidden === false) {
6609
+ if (!legacyHiddenSet.has(key) && !denySet.has(key)) hidden.delete(key);
6610
+ } else if (config.hidden) hidden.add(key);
6525
6611
  else if (config.table === false) hidden.add(key);
6526
6612
  else if (config.table && typeof config.table === "object" && config.table.hidden) hidden.add(key);
6527
6613
  }
@@ -6571,12 +6657,32 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
6571
6657
  /**
6572
6658
  * 渲染字段值
6573
6659
  */
6574
- function renderFieldValue(value, type, booleanLocale, options) {
6660
+ function renderFieldValue(value, type, booleanLocale, options, display = "auto") {
6575
6661
  if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6576
6662
  className: "text-muted-foreground",
6577
6663
  children: "-"
6578
6664
  });
6579
- if (options && options.length > 0) {
6665
+ const renderText = (item) => getOptionLabel(item, options);
6666
+ if (display === "text") return Array.isArray(value) ? value.map(renderText).join(", ") : renderText(value);
6667
+ if (display === "date" || display === "datetime") return formatDate(value, {}, display);
6668
+ if (display === "badge" && (!options || options.length === 0)) {
6669
+ if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6670
+ className: "flex gap-1 flex-wrap",
6671
+ children: [value.slice(0, 5).map((item, index$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
6672
+ variant: "secondary",
6673
+ children: String(item)
6674
+ }, index$1)), value.length > 5 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Badge, {
6675
+ variant: "outline",
6676
+ children: ["+", value.length - 5]
6677
+ })]
6678
+ });
6679
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
6680
+ variant: "outline",
6681
+ className: "capitalize",
6682
+ children: String(value)
6683
+ });
6684
+ }
6685
+ if ((display === "badge" || display === "auto") && options && options.length > 0) {
6580
6686
  if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6581
6687
  className: "flex gap-1 flex-wrap",
6582
6688
  children: [value.slice(0, 5).map((v, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
@@ -6768,7 +6874,7 @@ function resolveActions(actionsOrFn, defaults, rowActionsLocale, context) {
6768
6874
  function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate }) {
6769
6875
  const locale = resolveLocale(localeProp);
6770
6876
  const resolvedSchema = resource.schema ?? schema;
6771
- const resolvedFields = react.useMemo(() => mergeFields(resource.fields, fields) ?? {}, [fields, resource.fields]);
6877
+ const resolvedFields = react.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
6772
6878
  const can = {
6773
6879
  create: permissions?.can?.create ?? true,
6774
6880
  update: permissions?.can?.update ?? true,
@@ -6791,7 +6897,18 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
6791
6897
  tableConfig?.overrides
6792
6898
  ]);
6793
6899
  const dynamicResolveOptions = useDynamicResolveOptions(resolvedFields, resource.tableData.data, hiddenColumns);
6794
- const dynamicOptionsByField = react.useMemo(() => mergeOptionsByField(dynamicFilterOptions.labelOptionsByField, dynamicResolveOptions.optionsByField), [dynamicFilterOptions.labelOptionsByField, dynamicResolveOptions.optionsByField]);
6900
+ const sharedResolveOptions = useDynamicResolveOptions(react.useMemo(() => Object.fromEntries(Object.entries(resolvedFields).flatMap(([field, config]) => {
6901
+ const table = getTableConfig(config);
6902
+ if (table?.options === void 0 && table?.dataSource === void 0) return [];
6903
+ const { table: _table,...sharedConfig } = config;
6904
+ return [[field, sharedConfig]];
6905
+ })), [resolvedFields]), resource.tableData.data, hiddenColumns);
6906
+ const viewDynamicOptionsByField = react.useMemo(() => mergeOptionsByField(mergeOptionsByField(dynamicFilterOptions.labelOptionsByField, sharedResolveOptions.optionsByField), Object.fromEntries(Object.entries(dynamicResolveOptions.optionsByField).filter(([field]) => !getTableConfig(resolvedFields[field] ?? {})?.dataSource))), [
6907
+ dynamicFilterOptions.labelOptionsByField,
6908
+ dynamicResolveOptions.optionsByField,
6909
+ sharedResolveOptions.optionsByField,
6910
+ resolvedFields
6911
+ ]);
6795
6912
  const resourceIdKey = resource.idKey ?? "id";
6796
6913
  const actionRegistryVersion = useCrudActionsVersion();
6797
6914
  const unifiedActions = react.useMemo(() => {
@@ -7081,6 +7198,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7081
7198
  data: resource.tableData.data,
7082
7199
  schema: resolvedSchema,
7083
7200
  pageCount: resource.tableData.pageCount,
7201
+ ...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
7084
7202
  overrides: tableOverrides,
7085
7203
  exclude: hiddenColumns,
7086
7204
  filterMode: tableConfig?.filterModes,
@@ -7122,7 +7240,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7122
7240
  data: resource.modal.selected,
7123
7241
  schema: resolvedSchema,
7124
7242
  fields: resolvedFields,
7125
- dynamicOptions: dynamicOptionsByField,
7243
+ dynamicOptions: viewDynamicOptionsByField,
7126
7244
  denyFields,
7127
7245
  locale
7128
7246
  }),
@@ -8192,6 +8310,7 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
8192
8310
  tableData: {
8193
8311
  data: tableRows,
8194
8312
  pageCount: listQuery.data?.pageCount ?? 0,
8313
+ ...typeof listQuery.data?.total === "number" ? { total: listQuery.data.total } : {},
8195
8314
  isLoading: listQuery.isLoading,
8196
8315
  isFetching: listQuery.isFetching
8197
8316
  },
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime2 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime6 from "react/jsx-runtime";
2
2
  import { z } from "zod";
3
3
  import { JsonSchemaFormScope } from "@wordrhyme/formily-shadcn";
4
4
  import * as _tanstack_react_table0 from "@tanstack/react-table";
@@ -151,6 +151,8 @@ interface UseAutoCrudResourceReturn<TSchema extends z.ZodObject<z.ZodRawShape>,
151
151
  tableData: {
152
152
  data: TListItem[];
153
153
  pageCount: number;
154
+ /** Total rows matching the current search and filters. */
155
+ total?: number;
154
156
  isLoading: boolean;
155
157
  /** 是否正在获取数据(用于显示微妙的加载指示器) */
156
158
  isFetching: boolean;
@@ -411,7 +413,7 @@ declare function AutoTableActionBar<TData>({
411
413
  extraActions,
412
414
  actions,
413
415
  deleteConfirmation
414
- }: AutoTableActionBarProps<TData>): react_jsx_runtime2.JSX.Element;
416
+ }: AutoTableActionBarProps<TData>): react_jsx_runtime6.JSX.Element;
415
417
  //#endregion
416
418
  //#region src/lib/schema-bridge/types.d.ts
417
419
  /**
@@ -519,6 +521,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
519
521
  schema: T;
520
522
  data: z.infer<T>[];
521
523
  pageCount?: number;
524
+ /** Total rows matching the current search and filters. */
525
+ total?: number;
522
526
  overrides?: ColumnOverrides<z.infer<T>>;
523
527
  enableRowSelection?: boolean;
524
528
  exclude?: (keyof z.infer<T>)[];
@@ -568,6 +572,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
568
572
  schema,
569
573
  data,
570
574
  pageCount,
575
+ total,
571
576
  overrides,
572
577
  enableRowSelection,
573
578
  exclude,
@@ -587,7 +592,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
587
592
  onSelectedCountChange,
588
593
  onSelectedRowsChange,
589
594
  getSelectedRows
590
- }: AutoTableProps<T>): react_jsx_runtime2.JSX.Element;
595
+ }: AutoTableProps<T>): react_jsx_runtime6.JSX.Element;
591
596
  //#endregion
592
597
  //#region src/i18n/locale.d.ts
593
598
  /**
@@ -803,6 +808,7 @@ interface FieldOption {
803
808
  icon?: React$1.FC<React$1.SVGProps<SVGSVGElement>>;
804
809
  disabled?: boolean;
805
810
  }
811
+ type FieldTableDisplay = 'auto' | 'text' | 'badge' | 'date' | 'datetime';
806
812
  /**
807
813
  * 统一字段配置
808
814
  * 支持共用配置 + 表格/表单特定配置
@@ -833,8 +839,16 @@ interface Field {
833
839
  table?: {
834
840
  /** 是否在表格中隐藏 */
835
841
  hidden?: boolean;
842
+ /** 表格列标签 */
843
+ label?: string;
836
844
  /** 排序权重,数值越小越靠前 */
837
845
  index?: number;
846
+ /** 仅用于表格展示的静态值标签 */
847
+ options?: FieldOption[];
848
+ /** 仅用于表格展示的动态值标签源 */
849
+ dataSource?: AutoCrudDataSourceConfig;
850
+ /** 声明式单元格展示模式;非 auto 模式会覆盖拥有方自定义 cell */
851
+ display?: FieldTableDisplay;
838
852
  /** 筛选器配置 */
839
853
  meta?: Record<string, unknown>;
840
854
  /** 其他列配置 */
@@ -1079,7 +1093,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
1079
1093
  toolbarActions,
1080
1094
  locale: localeProp,
1081
1095
  onCreate
1082
- }: AutoCrudTableProps<TSchema>): react_jsx_runtime2.JSX.Element;
1096
+ }: AutoCrudTableProps<TSchema>): react_jsx_runtime6.JSX.Element;
1083
1097
  //#endregion
1084
1098
  //#region src/components/auto-crud/auto-form.d.ts
1085
1099
  interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
@@ -1118,7 +1132,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
1118
1132
  labelAlign,
1119
1133
  labelWidth,
1120
1134
  showSubmitButton
1121
- }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime2.JSX.Element;
1135
+ }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime6.JSX.Element;
1122
1136
  declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
1123
1137
  ref?: React.Ref<AutoFormRef>;
1124
1138
  }) => ReturnType<typeof AutoFormInner>;
@@ -1434,7 +1448,7 @@ declare function AutoTableSimpleFilters<TData>({
1434
1448
  filters: externalFilters,
1435
1449
  onFiltersChange,
1436
1450
  leading
1437
- }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime2.JSX.Element | null;
1451
+ }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime6.JSX.Element | null;
1438
1452
  //#endregion
1439
1453
  //#region src/components/auto-crud/form-modal.d.ts
1440
1454
  type ModalVariant = 'dialog' | 'sheet';
@@ -1478,7 +1492,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
1478
1492
  labelAlign,
1479
1493
  labelWidth,
1480
1494
  className
1481
- }: CrudFormModalProps<T>): react_jsx_runtime2.JSX.Element;
1495
+ }: CrudFormModalProps<T>): react_jsx_runtime6.JSX.Element;
1482
1496
  //#endregion
1483
1497
  //#region src/components/auto-crud/import-dialog.d.ts
1484
1498
  interface ImportDialogProps {
@@ -1500,7 +1514,7 @@ declare function ImportDialog({
1500
1514
  columns,
1501
1515
  title,
1502
1516
  locale
1503
- }: ImportDialogProps): react_jsx_runtime2.JSX.Element;
1517
+ }: ImportDialogProps): react_jsx_runtime6.JSX.Element;
1504
1518
  //#endregion
1505
1519
  //#region src/components/auto-crud/export-dialog.d.ts
1506
1520
  type ExportMode = 'selected' | 'filtered';
@@ -1520,7 +1534,7 @@ declare function ExportDialog({
1520
1534
  selectedCount,
1521
1535
  onExport,
1522
1536
  canExportFiltered
1523
- }: ExportDialogProps): react_jsx_runtime2.JSX.Element;
1537
+ }: ExportDialogProps): react_jsx_runtime6.JSX.Element;
1524
1538
  //#endregion
1525
1539
  //#region src/components/data-table/data-table.d.ts
1526
1540
  interface DataTableProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1533,7 +1547,7 @@ declare function DataTable<TData>({
1533
1547
  children,
1534
1548
  className,
1535
1549
  ...props
1536
- }: DataTableProps<TData>): react_jsx_runtime2.JSX.Element;
1550
+ }: DataTableProps<TData>): react_jsx_runtime6.JSX.Element;
1537
1551
  //#endregion
1538
1552
  //#region src/components/data-table/data-table-advanced-toolbar.d.ts
1539
1553
  interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1544,7 +1558,7 @@ declare function DataTableAdvancedToolbar<TData>({
1544
1558
  children,
1545
1559
  className,
1546
1560
  ...props
1547
- }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1561
+ }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime6.JSX.Element;
1548
1562
  //#endregion
1549
1563
  //#region src/components/data-table/data-table-column-header.d.ts
1550
1564
  interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
@@ -1556,7 +1570,7 @@ declare function DataTableColumnHeader<TData, TValue>({
1556
1570
  label,
1557
1571
  className,
1558
1572
  ...props
1559
- }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1573
+ }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime6.JSX.Element;
1560
1574
  //#endregion
1561
1575
  //#region src/components/data-table/data-table-faceted-filter.d.ts
1562
1576
  interface DataTableFacetedFilterProps<TData, TValue> {
@@ -1570,7 +1584,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
1570
1584
  title,
1571
1585
  options,
1572
1586
  multiple
1573
- }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1587
+ }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime6.JSX.Element;
1574
1588
  //#endregion
1575
1589
  //#region src/components/data-table/data-table-pagination.d.ts
1576
1590
  interface DataTablePaginationProps<TData> extends React.ComponentProps<'div'> {
@@ -1582,7 +1596,7 @@ declare function DataTablePagination<TData>({
1582
1596
  pageSizeOptions,
1583
1597
  className,
1584
1598
  ...props
1585
- }: DataTablePaginationProps<TData>): react_jsx_runtime2.JSX.Element;
1599
+ }: DataTablePaginationProps<TData>): react_jsx_runtime6.JSX.Element;
1586
1600
  //#endregion
1587
1601
  //#region src/components/data-table/data-table-toolbar.d.ts
1588
1602
  interface DataTableToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1593,7 +1607,7 @@ declare function DataTableToolbar<TData>({
1593
1607
  children,
1594
1608
  className,
1595
1609
  ...props
1596
- }: DataTableToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1610
+ }: DataTableToolbarProps<TData>): react_jsx_runtime6.JSX.Element;
1597
1611
  //#endregion
1598
1612
  //#region src/components/data-table/data-table-view-options.d.ts
1599
1613
  interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
@@ -1604,7 +1618,7 @@ declare function DataTableViewOptions<TData>({
1604
1618
  table,
1605
1619
  disabled,
1606
1620
  ...props
1607
- }: DataTableViewOptionsProps<TData>): react_jsx_runtime2.JSX.Element;
1621
+ }: DataTableViewOptionsProps<TData>): react_jsx_runtime6.JSX.Element;
1608
1622
  //#endregion
1609
1623
  //#region src/lib/crud-actions.d.ts
1610
1624
  type CrudActionZone = 'toolbar' | 'row' | 'batch';
@@ -1899,7 +1913,8 @@ declare function createMemoryDataSource<T extends {
1899
1913
  }>(initialData?: T[]): DataSource<T>;
1900
1914
  //#endregion
1901
1915
  //#region src/lib/format.d.ts
1902
- type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions) => string;
1916
+ type DateFormatPreset = 'date' | 'datetime';
1917
+ type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions, preset?: DateFormatPreset) => string;
1903
1918
  /**
1904
1919
  * Register the host's process-wide date presentation policy without coupling
1905
1920
  * AutoCrud to locale or timezone selection. The returned cleanup removes only
@@ -1907,7 +1922,7 @@ type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions) => string
1907
1922
  * Passing undefined clears every registration.
1908
1923
  */
1909
1924
  declare function setDateFormatter(formatter?: DateFormatter): () => void;
1910
- declare function formatDate(date: Date | string | number | undefined, opts?: Intl.DateTimeFormatOptions): string;
1925
+ declare function formatDate(date: Date | string | number | undefined, opts?: Intl.DateTimeFormatOptions, preset?: DateFormatPreset): string;
1911
1926
  //#endregion
1912
1927
  //#region src/lib/humanize.d.ts
1913
1928
  /**
@@ -1987,4 +2002,4 @@ declare function exportAllToCSV<T extends Record<string, unknown>>(data: T[], op
1987
2002
  */
1988
2003
  declare function downloadCSVTemplate(headers: string[], filename?: string): void;
1989
2004
  //#endregion
1990
- export { type ActionConfig, type ActionItem, type ActionsColumnConfig, type AutoCrudActionConfig, type AutoCrudActionsConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceEntry, type AutoCrudDataSourceLoader, type AutoCrudDataSourceRegistration, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, type AutoCrudQueryCapabilities, type AutoCrudRowActionContext, AutoCrudTable, type AutoCrudTableProps, type AutoCrudToolbarContext, type AutoCrudToolbarResolver, AutoForm, type AutoFormProps, type AutoQueryParams, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, type BatchActionConfig, type BatchActionContext, type BatchActionItem, type BatchBuiltinActionItem, type BatchBuiltinActionType, type BatchCustomActionItem, type BatchUpdateField, type ColumnOverrides, type CreateFormSchemaOptions, type CreateTableSchemaOptions, type CrudActionBase, type CrudActionEntry, type CrudActionRegistration, type CrudActionZone, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, type DateFormatter, type EnumOption, ExportDialog, type ExportDialogProps, type ExportMode, ExtendedColumnFilter, ExtendedColumnSort, type Field, type FieldOption, type FieldType, type Fields, type FilterConfig, FilterOperator, type FilterVariant, type FormSchemaOverrides, ImportDialog, type ImportDialogProps, type ImportResult, type JSONSchema, type JSONSchemaProperty, JoinOperator, type ListParams, type ListResult, type LocaleProp, MultiCombobox, type MultiComboboxOption, type MultiComboboxProps, type MultiComboboxTriggerRenderProps, Option, type ParsedImportData, type ParsedZodField, type Parser, QueryKeys, type RowActionConfig, type RowActionItem, type RowBuiltinActionItem, type RowBuiltinActionType, type RowCustomActionItem, SchemaAdapter, Select, type SelectMode, type SelectOption, type SelectProps, type SelectSearchableDynamicProps, type SelectSearchableMultipleProps, type SelectSearchableProps, type SelectSearchableSingleProps, type SelectSimpleProps, type SelectTriggerRenderProps, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionConfig, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarBuiltinActionType, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, components, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, crudActions, dataSources, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formComponents, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, normalizeDataSourceConfig, normalizeOptions, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setDateFormatter, setSearchParams, setToolbarResolver, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
2005
+ export { type ActionConfig, type ActionItem, type ActionsColumnConfig, type AutoCrudActionConfig, type AutoCrudActionsConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceEntry, type AutoCrudDataSourceLoader, type AutoCrudDataSourceRegistration, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, type AutoCrudQueryCapabilities, type AutoCrudRowActionContext, AutoCrudTable, type AutoCrudTableProps, type AutoCrudToolbarContext, type AutoCrudToolbarResolver, AutoForm, type AutoFormProps, type AutoQueryParams, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, type BatchActionConfig, type BatchActionContext, type BatchActionItem, type BatchBuiltinActionItem, type BatchBuiltinActionType, type BatchCustomActionItem, type BatchUpdateField, type ColumnOverrides, type CreateFormSchemaOptions, type CreateTableSchemaOptions, type CrudActionBase, type CrudActionEntry, type CrudActionRegistration, type CrudActionZone, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, type DateFormatPreset, type DateFormatter, type EnumOption, ExportDialog, type ExportDialogProps, type ExportMode, ExtendedColumnFilter, ExtendedColumnSort, type Field, type FieldOption, type FieldTableDisplay, type FieldType, type Fields, type FilterConfig, FilterOperator, type FilterVariant, type FormSchemaOverrides, ImportDialog, type ImportDialogProps, type ImportResult, type JSONSchema, type JSONSchemaProperty, JoinOperator, type ListParams, type ListResult, type LocaleProp, MultiCombobox, type MultiComboboxOption, type MultiComboboxProps, type MultiComboboxTriggerRenderProps, Option, type ParsedImportData, type ParsedZodField, type Parser, QueryKeys, type RowActionConfig, type RowActionItem, type RowBuiltinActionItem, type RowBuiltinActionType, type RowCustomActionItem, SchemaAdapter, Select, type SelectMode, type SelectOption, type SelectProps, type SelectSearchableDynamicProps, type SelectSearchableMultipleProps, type SelectSearchableProps, type SelectSearchableSingleProps, type SelectSimpleProps, type SelectTriggerRenderProps, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionConfig, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarBuiltinActionType, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, components, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, crudActions, dataSources, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formComponents, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, normalizeDataSourceConfig, normalizeOptions, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setDateFormatter, setSearchParams, setToolbarResolver, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _tanstack_react_table0 from "@tanstack/react-table";
3
3
  import { Column, ColumnDef, ColumnSort, Row, RowData, Table, TableOptions, TableState } from "@tanstack/react-table";
4
4
  import { DropdownMenuTrigger, PopoverContent } from "@wordrhyme/shadcn";
5
5
  import { ClassValue } from "clsx";
6
- import * as react_jsx_runtime3 from "react/jsx-runtime";
6
+ import * as react_jsx_runtime2 from "react/jsx-runtime";
7
7
  import { MultiCombobox, MultiComboboxOption, MultiComboboxProps, MultiComboboxTriggerRenderProps, Select, SelectMode, SelectOption, SelectProps, SelectSearchableDynamicProps, SelectSearchableMultipleProps, SelectSearchableProps, SelectSearchableSingleProps, SelectSimpleProps, SelectTriggerRenderProps } from "@wordrhyme/shadcn-ui";
8
8
  import { z } from "zod";
9
9
  import { JsonSchemaFormScope } from "@wordrhyme/formily-shadcn";
@@ -151,6 +151,8 @@ interface UseAutoCrudResourceReturn<TSchema extends z.ZodObject<z.ZodRawShape>,
151
151
  tableData: {
152
152
  data: TListItem[];
153
153
  pageCount: number;
154
+ /** Total rows matching the current search and filters. */
155
+ total?: number;
154
156
  isLoading: boolean;
155
157
  /** 是否正在获取数据(用于显示微妙的加载指示器) */
156
158
  isFetching: boolean;
@@ -411,7 +413,7 @@ declare function AutoTableActionBar<TData>({
411
413
  extraActions,
412
414
  actions,
413
415
  deleteConfirmation
414
- }: AutoTableActionBarProps<TData>): react_jsx_runtime3.JSX.Element;
416
+ }: AutoTableActionBarProps<TData>): react_jsx_runtime2.JSX.Element;
415
417
  //#endregion
416
418
  //#region src/lib/schema-bridge/types.d.ts
417
419
  /**
@@ -519,6 +521,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
519
521
  schema: T;
520
522
  data: z.infer<T>[];
521
523
  pageCount?: number;
524
+ /** Total rows matching the current search and filters. */
525
+ total?: number;
522
526
  overrides?: ColumnOverrides<z.infer<T>>;
523
527
  enableRowSelection?: boolean;
524
528
  exclude?: (keyof z.infer<T>)[];
@@ -568,6 +572,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
568
572
  schema,
569
573
  data,
570
574
  pageCount,
575
+ total,
571
576
  overrides,
572
577
  enableRowSelection,
573
578
  exclude,
@@ -587,7 +592,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
587
592
  onSelectedCountChange,
588
593
  onSelectedRowsChange,
589
594
  getSelectedRows
590
- }: AutoTableProps<T>): react_jsx_runtime3.JSX.Element;
595
+ }: AutoTableProps<T>): react_jsx_runtime2.JSX.Element;
591
596
  //#endregion
592
597
  //#region src/i18n/locale.d.ts
593
598
  /**
@@ -803,6 +808,7 @@ interface FieldOption {
803
808
  icon?: React$1.FC<React$1.SVGProps<SVGSVGElement>>;
804
809
  disabled?: boolean;
805
810
  }
811
+ type FieldTableDisplay = 'auto' | 'text' | 'badge' | 'date' | 'datetime';
806
812
  /**
807
813
  * 统一字段配置
808
814
  * 支持共用配置 + 表格/表单特定配置
@@ -833,8 +839,16 @@ interface Field {
833
839
  table?: {
834
840
  /** 是否在表格中隐藏 */
835
841
  hidden?: boolean;
842
+ /** 表格列标签 */
843
+ label?: string;
836
844
  /** 排序权重,数值越小越靠前 */
837
845
  index?: number;
846
+ /** 仅用于表格展示的静态值标签 */
847
+ options?: FieldOption[];
848
+ /** 仅用于表格展示的动态值标签源 */
849
+ dataSource?: AutoCrudDataSourceConfig;
850
+ /** 声明式单元格展示模式;非 auto 模式会覆盖拥有方自定义 cell */
851
+ display?: FieldTableDisplay;
838
852
  /** 筛选器配置 */
839
853
  meta?: Record<string, unknown>;
840
854
  /** 其他列配置 */
@@ -1079,7 +1093,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
1079
1093
  toolbarActions,
1080
1094
  locale: localeProp,
1081
1095
  onCreate
1082
- }: AutoCrudTableProps<TSchema>): react_jsx_runtime3.JSX.Element;
1096
+ }: AutoCrudTableProps<TSchema>): react_jsx_runtime2.JSX.Element;
1083
1097
  //#endregion
1084
1098
  //#region src/components/auto-crud/auto-form.d.ts
1085
1099
  interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
@@ -1118,7 +1132,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
1118
1132
  labelAlign,
1119
1133
  labelWidth,
1120
1134
  showSubmitButton
1121
- }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime3.JSX.Element;
1135
+ }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime2.JSX.Element;
1122
1136
  declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
1123
1137
  ref?: React.Ref<AutoFormRef>;
1124
1138
  }) => ReturnType<typeof AutoFormInner>;
@@ -1434,7 +1448,7 @@ declare function AutoTableSimpleFilters<TData>({
1434
1448
  filters: externalFilters,
1435
1449
  onFiltersChange,
1436
1450
  leading
1437
- }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime3.JSX.Element | null;
1451
+ }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime2.JSX.Element | null;
1438
1452
  //#endregion
1439
1453
  //#region src/components/auto-crud/form-modal.d.ts
1440
1454
  type ModalVariant = 'dialog' | 'sheet';
@@ -1478,7 +1492,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
1478
1492
  labelAlign,
1479
1493
  labelWidth,
1480
1494
  className
1481
- }: CrudFormModalProps<T>): react_jsx_runtime3.JSX.Element;
1495
+ }: CrudFormModalProps<T>): react_jsx_runtime2.JSX.Element;
1482
1496
  //#endregion
1483
1497
  //#region src/components/auto-crud/import-dialog.d.ts
1484
1498
  interface ImportDialogProps {
@@ -1500,7 +1514,7 @@ declare function ImportDialog({
1500
1514
  columns,
1501
1515
  title,
1502
1516
  locale
1503
- }: ImportDialogProps): react_jsx_runtime3.JSX.Element;
1517
+ }: ImportDialogProps): react_jsx_runtime2.JSX.Element;
1504
1518
  //#endregion
1505
1519
  //#region src/components/auto-crud/export-dialog.d.ts
1506
1520
  type ExportMode = 'selected' | 'filtered';
@@ -1520,7 +1534,7 @@ declare function ExportDialog({
1520
1534
  selectedCount,
1521
1535
  onExport,
1522
1536
  canExportFiltered
1523
- }: ExportDialogProps): react_jsx_runtime3.JSX.Element;
1537
+ }: ExportDialogProps): react_jsx_runtime2.JSX.Element;
1524
1538
  //#endregion
1525
1539
  //#region src/components/data-table/data-table.d.ts
1526
1540
  interface DataTableProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1533,7 +1547,7 @@ declare function DataTable<TData>({
1533
1547
  children,
1534
1548
  className,
1535
1549
  ...props
1536
- }: DataTableProps<TData>): react_jsx_runtime3.JSX.Element;
1550
+ }: DataTableProps<TData>): react_jsx_runtime2.JSX.Element;
1537
1551
  //#endregion
1538
1552
  //#region src/components/data-table/data-table-advanced-toolbar.d.ts
1539
1553
  interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1544,7 +1558,7 @@ declare function DataTableAdvancedToolbar<TData>({
1544
1558
  children,
1545
1559
  className,
1546
1560
  ...props
1547
- }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1561
+ }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1548
1562
  //#endregion
1549
1563
  //#region src/components/data-table/data-table-column-header.d.ts
1550
1564
  interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
@@ -1556,7 +1570,7 @@ declare function DataTableColumnHeader<TData, TValue>({
1556
1570
  label,
1557
1571
  className,
1558
1572
  ...props
1559
- }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1573
+ }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1560
1574
  //#endregion
1561
1575
  //#region src/components/data-table/data-table-faceted-filter.d.ts
1562
1576
  interface DataTableFacetedFilterProps<TData, TValue> {
@@ -1570,7 +1584,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
1570
1584
  title,
1571
1585
  options,
1572
1586
  multiple
1573
- }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1587
+ }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1574
1588
  //#endregion
1575
1589
  //#region src/components/data-table/data-table-pagination.d.ts
1576
1590
  interface DataTablePaginationProps<TData> extends React.ComponentProps<'div'> {
@@ -1582,7 +1596,7 @@ declare function DataTablePagination<TData>({
1582
1596
  pageSizeOptions,
1583
1597
  className,
1584
1598
  ...props
1585
- }: DataTablePaginationProps<TData>): react_jsx_runtime3.JSX.Element;
1599
+ }: DataTablePaginationProps<TData>): react_jsx_runtime2.JSX.Element;
1586
1600
  //#endregion
1587
1601
  //#region src/components/data-table/data-table-toolbar.d.ts
1588
1602
  interface DataTableToolbarProps<TData> extends React$1.ComponentProps<'div'> {
@@ -1593,7 +1607,7 @@ declare function DataTableToolbar<TData>({
1593
1607
  children,
1594
1608
  className,
1595
1609
  ...props
1596
- }: DataTableToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1610
+ }: DataTableToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1597
1611
  //#endregion
1598
1612
  //#region src/components/data-table/data-table-view-options.d.ts
1599
1613
  interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
@@ -1604,7 +1618,7 @@ declare function DataTableViewOptions<TData>({
1604
1618
  table,
1605
1619
  disabled,
1606
1620
  ...props
1607
- }: DataTableViewOptionsProps<TData>): react_jsx_runtime3.JSX.Element;
1621
+ }: DataTableViewOptionsProps<TData>): react_jsx_runtime2.JSX.Element;
1608
1622
  //#endregion
1609
1623
  //#region src/lib/crud-actions.d.ts
1610
1624
  type CrudActionZone = 'toolbar' | 'row' | 'batch';
@@ -1899,7 +1913,8 @@ declare function createMemoryDataSource<T extends {
1899
1913
  }>(initialData?: T[]): DataSource<T>;
1900
1914
  //#endregion
1901
1915
  //#region src/lib/format.d.ts
1902
- type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions) => string;
1916
+ type DateFormatPreset = 'date' | 'datetime';
1917
+ type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions, preset?: DateFormatPreset) => string;
1903
1918
  /**
1904
1919
  * Register the host's process-wide date presentation policy without coupling
1905
1920
  * AutoCrud to locale or timezone selection. The returned cleanup removes only
@@ -1907,7 +1922,7 @@ type DateFormatter = (date: Date, options: Intl.DateTimeFormatOptions) => string
1907
1922
  * Passing undefined clears every registration.
1908
1923
  */
1909
1924
  declare function setDateFormatter(formatter?: DateFormatter): () => void;
1910
- declare function formatDate(date: Date | string | number | undefined, opts?: Intl.DateTimeFormatOptions): string;
1925
+ declare function formatDate(date: Date | string | number | undefined, opts?: Intl.DateTimeFormatOptions, preset?: DateFormatPreset): string;
1911
1926
  //#endregion
1912
1927
  //#region src/lib/humanize.d.ts
1913
1928
  /**
@@ -1987,4 +2002,4 @@ declare function exportAllToCSV<T extends Record<string, unknown>>(data: T[], op
1987
2002
  */
1988
2003
  declare function downloadCSVTemplate(headers: string[], filename?: string): void;
1989
2004
  //#endregion
1990
- export { type ActionConfig, type ActionItem, type ActionsColumnConfig, type AutoCrudActionConfig, type AutoCrudActionsConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceEntry, type AutoCrudDataSourceLoader, type AutoCrudDataSourceRegistration, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, type AutoCrudQueryCapabilities, type AutoCrudRowActionContext, AutoCrudTable, type AutoCrudTableProps, type AutoCrudToolbarContext, type AutoCrudToolbarResolver, AutoForm, type AutoFormProps, type AutoQueryParams, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, type BatchActionConfig, type BatchActionContext, type BatchActionItem, type BatchBuiltinActionItem, type BatchBuiltinActionType, type BatchCustomActionItem, type BatchUpdateField, type ColumnOverrides, type CreateFormSchemaOptions, type CreateTableSchemaOptions, type CrudActionBase, type CrudActionEntry, type CrudActionRegistration, type CrudActionZone, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, type DateFormatter, type EnumOption, ExportDialog, type ExportDialogProps, type ExportMode, ExtendedColumnFilter, ExtendedColumnSort, type Field, type FieldOption, type FieldType, type Fields, type FilterConfig, FilterOperator, type FilterVariant, type FormSchemaOverrides, ImportDialog, type ImportDialogProps, type ImportResult, type JSONSchema, type JSONSchemaProperty, JoinOperator, type ListParams, type ListResult, type LocaleProp, MultiCombobox, type MultiComboboxOption, type MultiComboboxProps, type MultiComboboxTriggerRenderProps, Option, type ParsedImportData, type ParsedZodField, type Parser, QueryKeys, type RowActionConfig, type RowActionItem, type RowBuiltinActionItem, type RowBuiltinActionType, type RowCustomActionItem, SchemaAdapter, Select, type SelectMode, type SelectOption, type SelectProps, type SelectSearchableDynamicProps, type SelectSearchableMultipleProps, type SelectSearchableProps, type SelectSearchableSingleProps, type SelectSimpleProps, type SelectTriggerRenderProps, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionConfig, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarBuiltinActionType, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, components, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, crudActions, dataSources, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formComponents, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, normalizeDataSourceConfig, normalizeOptions, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setDateFormatter, setSearchParams, setToolbarResolver, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
2005
+ export { type ActionConfig, type ActionItem, type ActionsColumnConfig, type AutoCrudActionConfig, type AutoCrudActionsConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceEntry, type AutoCrudDataSourceLoader, type AutoCrudDataSourceRegistration, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, type AutoCrudQueryCapabilities, type AutoCrudRowActionContext, AutoCrudTable, type AutoCrudTableProps, type AutoCrudToolbarContext, type AutoCrudToolbarResolver, AutoForm, type AutoFormProps, type AutoQueryParams, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, type BatchActionConfig, type BatchActionContext, type BatchActionItem, type BatchBuiltinActionItem, type BatchBuiltinActionType, type BatchCustomActionItem, type BatchUpdateField, type ColumnOverrides, type CreateFormSchemaOptions, type CreateTableSchemaOptions, type CrudActionBase, type CrudActionEntry, type CrudActionRegistration, type CrudActionZone, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, type DateFormatPreset, type DateFormatter, type EnumOption, ExportDialog, type ExportDialogProps, type ExportMode, ExtendedColumnFilter, ExtendedColumnSort, type Field, type FieldOption, type FieldTableDisplay, type FieldType, type Fields, type FilterConfig, FilterOperator, type FilterVariant, type FormSchemaOverrides, ImportDialog, type ImportDialogProps, type ImportResult, type JSONSchema, type JSONSchemaProperty, JoinOperator, type ListParams, type ListResult, type LocaleProp, MultiCombobox, type MultiComboboxOption, type MultiComboboxProps, type MultiComboboxTriggerRenderProps, Option, type ParsedImportData, type ParsedZodField, type Parser, QueryKeys, type RowActionConfig, type RowActionItem, type RowBuiltinActionItem, type RowBuiltinActionType, type RowCustomActionItem, SchemaAdapter, Select, type SelectMode, type SelectOption, type SelectProps, type SelectSearchableDynamicProps, type SelectSearchableMultipleProps, type SelectSearchableProps, type SelectSearchableSingleProps, type SelectSimpleProps, type SelectTriggerRenderProps, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionConfig, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarBuiltinActionType, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, components, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, crudActions, dataSources, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formComponents, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, normalizeDataSourceConfig, normalizeOptions, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setDateFormatter, setSearchParams, setToolbarResolver, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
package/dist/index.js CHANGED
@@ -29,18 +29,19 @@ function DataTablePagination({ table, pageSizeOptions = [
29
29
  40,
30
30
  50
31
31
  ], className,...props }) {
32
+ const total = table.options.rowCount ?? (table.options.manualPagination ? void 0 : table.getRowCount());
32
33
  return /* @__PURE__ */ jsxs("div", {
33
34
  className: cn("flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8", className),
34
35
  ...props,
35
36
  children: [/* @__PURE__ */ jsxs("div", {
36
- className: "flex-1 whitespace-nowrap text-muted-foreground text-sm",
37
- children: [
37
+ className: "flex flex-1 items-center gap-6 whitespace-nowrap text-muted-foreground text-sm",
38
+ children: [/* @__PURE__ */ jsxs("span", { children: [
38
39
  table.getFilteredSelectedRowModel().rows.length,
39
40
  " of",
40
41
  " ",
41
42
  table.getFilteredRowModel().rows.length,
42
43
  " row(s) selected."
43
- ]
44
+ ] }), total !== void 0 && /* @__PURE__ */ jsxs("span", { children: ["Total: ", total] })]
44
45
  }), /* @__PURE__ */ jsxs("div", {
45
46
  className: "flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8",
46
47
  children: [
@@ -367,6 +368,21 @@ function useDateFormatterVersion() {
367
368
  function getHostDateFormatter() {
368
369
  return hostDateFormatters[hostDateFormatters.length - 1]?.formatter;
369
370
  }
371
+ const canonicalDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
372
+ const canonicalDateTimePrefixPattern = /^(\d{4})-(\d{2})-(\d{2})(?=[T ])/;
373
+ function isValidCalendarDate(year, month, day) {
374
+ if (!year || !month || !day) return false;
375
+ const date = /* @__PURE__ */ new Date(`${year}-${month}-${day}T00:00:00.000Z`);
376
+ return !Number.isNaN(date.getTime()) && date.getUTCFullYear() === Number(year) && date.getUTCMonth() + 1 === Number(month) && date.getUTCDate() === Number(day);
377
+ }
378
+ function isValidCanonicalDate(value) {
379
+ const match = canonicalDatePattern.exec(value);
380
+ return !!match && isValidCalendarDate(match[1], match[2], match[3]);
381
+ }
382
+ function hasValidCanonicalDateTimePrefix(value) {
383
+ const match = canonicalDateTimePrefixPattern.exec(value);
384
+ return !match || isValidCalendarDate(match[1], match[2], match[3]);
385
+ }
370
386
  /**
371
387
  * Register the host's process-wide date presentation policy without coupling
372
388
  * AutoCrud to locale or timezone selection. The returned cleanup removes only
@@ -393,18 +409,45 @@ function setDateFormatter(formatter) {
393
409
  if (hostDateFormatters.length !== previousLength && getHostDateFormatter() !== currentFormatter) notifyDateFormatterChange();
394
410
  };
395
411
  }
396
- function formatDate(date, opts = {}) {
412
+ function formatDate(date, opts = {}, preset) {
397
413
  if (date === void 0) return "";
414
+ if (preset === "date" && typeof date === "string" && canonicalDatePattern.test(date)) return isValidCanonicalDate(date) ? date : "";
415
+ if (preset === "datetime" && typeof date === "string" && !hasValidCanonicalDateTimePrefix(date)) return "";
398
416
  try {
399
417
  const value = new Date(date);
418
+ if (Number.isNaN(value.getTime())) return "";
400
419
  const options = {
401
- month: opts.month ?? "long",
402
- day: opts.day ?? "numeric",
420
+ month: opts.month ?? (preset ? "2-digit" : "long"),
421
+ day: opts.day ?? (preset ? "2-digit" : "numeric"),
403
422
  year: opts.year ?? "numeric",
423
+ ...preset === "datetime" ? {
424
+ hour: opts.hour ?? "2-digit",
425
+ minute: opts.minute ?? "2-digit",
426
+ second: opts.second ?? "2-digit",
427
+ hourCycle: opts.hourCycle ?? "h23"
428
+ } : {},
404
429
  ...opts
405
430
  };
406
431
  const hostDateFormatter = getHostDateFormatter();
407
- return hostDateFormatter ? hostDateFormatter(value, options) : new Intl.DateTimeFormat("en-US", options).format(value);
432
+ if (hostDateFormatter) return preset ? hostDateFormatter(value, options, preset) : hostDateFormatter(value, options);
433
+ if (preset) {
434
+ const parts = new Intl.DateTimeFormat("en-CA", {
435
+ timeZone: opts.timeZone,
436
+ year: "numeric",
437
+ month: "2-digit",
438
+ day: "2-digit",
439
+ ...preset === "datetime" ? {
440
+ hour: "2-digit",
441
+ minute: "2-digit",
442
+ second: "2-digit",
443
+ hourCycle: "h23"
444
+ } : {}
445
+ }).formatToParts(value);
446
+ const read = (type) => parts.find((part) => part.type === type)?.value ?? "";
447
+ const formattedDate = `${read("year")}-${read("month")}-${read("day")}`;
448
+ return preset === "datetime" ? `${formattedDate} ${read("hour")}:${read("minute")}:${read("second")}` : formattedDate;
449
+ }
450
+ return new Intl.DateTimeFormat("en-US", options).format(value);
408
451
  } catch {
409
452
  return "";
410
453
  }
@@ -3988,7 +4031,7 @@ const filterModeConfig = {
3988
4031
  tooltip: "Linear-style command filters"
3989
4032
  }
3990
4033
  };
3991
- function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4034
+ function AutoTable({ schema, data, pageCount = 1, total, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
3992
4035
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
3993
4036
  const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
3994
4037
  const showToggle = modes.length > 1;
@@ -4017,23 +4060,25 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4017
4060
  exclude,
4018
4061
  actions
4019
4062
  ]);
4063
+ const stableInitialState = useMemo(() => ({
4064
+ sorting: initialSorting,
4065
+ columnPinning: pinnedColumns ?? {
4066
+ left: enableRowSelection ? ["select"] : [],
4067
+ right: actions ? ["actions"] : []
4068
+ }
4069
+ }), [
4070
+ initialSorting,
4071
+ pinnedColumns,
4072
+ enableRowSelection,
4073
+ actions
4074
+ ]);
4020
4075
  const { table, shallow, debounceMs, throttleMs } = useDataTable({
4021
4076
  data,
4022
4077
  columns,
4023
4078
  pageCount,
4079
+ ...total !== void 0 ? { rowCount: total } : {},
4024
4080
  enableAdvancedFilter,
4025
- initialState: useMemo(() => ({
4026
- sorting: initialSorting,
4027
- columnPinning: pinnedColumns ?? {
4028
- left: enableRowSelection ? ["select"] : [],
4029
- right: actions ? ["actions"] : []
4030
- }
4031
- }), [
4032
- initialSorting,
4033
- pinnedColumns,
4034
- enableRowSelection,
4035
- actions
4036
- ]),
4081
+ initialState: stableInitialState,
4037
4082
  shallow: false,
4038
4083
  clearOnDefault: true
4039
4084
  });
@@ -5938,6 +5983,16 @@ function mergeFields(base, override) {
5938
5983
  const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
5939
5984
  return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
5940
5985
  }
5986
+ function applyResourceTablePresentation(fields, resourceFields) {
5987
+ if (!fields || !resourceFields) return fields;
5988
+ return Object.fromEntries(Object.entries(fields).map(([key, config]) => {
5989
+ const table = resourceFields[key]?.table;
5990
+ return [key, table === void 0 ? config : {
5991
+ ...config,
5992
+ table: mergeFieldPart(config.table, table)
5993
+ }];
5994
+ }));
5995
+ }
5941
5996
  function normalizeFieldOptions(options) {
5942
5997
  if (!options || options.length === 0) return void 0;
5943
5998
  return options.map((option) => ({
@@ -5945,6 +6000,18 @@ function normalizeFieldOptions(options) {
5945
6000
  value: String(option.value)
5946
6001
  }));
5947
6002
  }
6003
+ function getTableConfig(config) {
6004
+ return config.table && typeof config.table === "object" ? config.table : void 0;
6005
+ }
6006
+ function getTableOptions(config) {
6007
+ const table = getTableConfig(config);
6008
+ if (table?.options) return normalizeFieldOptions(table.options);
6009
+ if (table?.dataSource) return void 0;
6010
+ return normalizeFieldOptions(config.enum);
6011
+ }
6012
+ function getTableDataSource(config) {
6013
+ return getTableConfig(config)?.dataSource ?? config.dataSource;
6014
+ }
5948
6015
  function toTableOptions(options) {
5949
6016
  return options?.map(({ label, value, searchText, count, icon }) => ({
5950
6017
  label,
@@ -6020,8 +6087,8 @@ function mergeOptionsByField(left, right) {
6020
6087
  function shouldResolveOptions(field, config, hiddenColumns) {
6021
6088
  if (!config) return false;
6022
6089
  if (hiddenColumns.has(field)) return false;
6023
- if (normalizeFieldOptions(config.enum)) return false;
6024
- return normalizeDataSourceConfig(config.dataSource) !== void 0;
6090
+ if (getTableOptions(config)) return false;
6091
+ return normalizeDataSourceConfig(getTableDataSource(config)) !== void 0;
6025
6092
  }
6026
6093
  function useRegistryVersion(subscribe) {
6027
6094
  const [version$1, setVersion] = React.useState(0);
@@ -6266,7 +6333,7 @@ function useDynamicResolveOptions(fields, rows, hiddenColumns) {
6266
6333
  const hiddenSet = new Set(hiddenColumns);
6267
6334
  return Object.entries(fields).flatMap(([field, config]) => {
6268
6335
  if (!shouldResolveOptions(field, config, hiddenSet)) return [];
6269
- const source = normalizeDataSourceConfig(config.dataSource);
6336
+ const source = normalizeDataSourceConfig(getTableDataSource(config));
6270
6337
  const values = getResolveValues(rows, field);
6271
6338
  return source && values.length > 0 ? [{
6272
6339
  field,
@@ -6363,12 +6430,16 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
6363
6430
  const result = { ...legacyOverrides };
6364
6431
  if (fields) for (const [key, config] of Object.entries(fields)) {
6365
6432
  const fieldOptions = normalizeFieldOptions(config.enum);
6433
+ const tableConfig = getTableConfig(config);
6434
+ const presentationOptions = getTableOptions(config);
6366
6435
  const tableOptions = toTableOptions(fieldOptions);
6367
6436
  const filterDataSourceRegistered = dynamicFilterState?.registeredByField[key];
6368
6437
  const filterDataSourceSearchable = dynamicFilterState?.searchableByField[key];
6369
6438
  const currentDynamicOptions = !fieldOptions && filterDataSourceRegistered ? toTableOptions(dynamicFilterState?.optionsByField[key] ?? []) : void 0;
6370
- const mergedDynamicOptions = mergeFieldOptions(!fieldOptions && filterDataSourceRegistered ? dynamicFilterState?.labelOptionsByField[key] ?? dynamicFilterState?.optionsByField[key] ?? [] : void 0, !fieldOptions ? dynamicResolveState?.optionsByField[key] : void 0);
6371
- const dynamicOptions = !fieldOptions && mergedDynamicOptions ? toTableOptions(mergedDynamicOptions) : void 0;
6439
+ const dynamicFilterLabelOptions = !fieldOptions && filterDataSourceRegistered ? dynamicFilterState?.labelOptionsByField[key] ?? dynamicFilterState?.optionsByField[key] ?? [] : void 0;
6440
+ const dynamicResolveOptions = !presentationOptions ? dynamicResolveState?.optionsByField[key] : void 0;
6441
+ const mergedSharedDynamicOptions = mergeFieldOptions(dynamicFilterLabelOptions, tableConfig?.dataSource ? void 0 : dynamicResolveOptions);
6442
+ const dynamicOptions = !fieldOptions && mergedSharedDynamicOptions ? toTableOptions(mergedSharedDynamicOptions) : void 0;
6372
6443
  const tableMeta = config.table !== false && typeof config.table === "object" ? config.table.meta : void 0;
6373
6444
  const fieldEnumMeta = tableOptions ? {
6374
6445
  options: tableOptions,
@@ -6432,11 +6503,24 @@ function buildTableOverrides(fields, legacyOverrides, dynamicFilterState, dynami
6432
6503
  hidden: true
6433
6504
  };
6434
6505
  else if (config.table && typeof config.table === "object") {
6435
- const { meta,...tableProps } = config.table;
6506
+ const { meta, display,...tableProps } = config.table;
6507
+ delete tableProps.options;
6508
+ delete tableProps.dataSource;
6436
6509
  result[key] = {
6437
6510
  ...result[key],
6438
6511
  ...tableProps
6439
6512
  };
6513
+ const hasTableLabels = config.table.options !== void 0 || config.table.dataSource !== void 0;
6514
+ if (display && display !== "auto" || hasTableLabels) {
6515
+ const options = presentationOptions ?? dynamicResolveOptions ?? mergedSharedDynamicOptions;
6516
+ result[key] = {
6517
+ ...result[key],
6518
+ cell: ({ row }) => renderFieldValue(row.getValue(key), "string", {
6519
+ true: "true",
6520
+ false: "false"
6521
+ }, options, display ?? "auto")
6522
+ };
6523
+ }
6440
6524
  }
6441
6525
  }
6442
6526
  return result;
@@ -6484,7 +6568,9 @@ function buildHiddenColumns(fields, legacyHidden, denyFields, legacyOverrides) {
6484
6568
  for (const key of DEFAULT_HIDDEN_AUDIT_FIELDS) if (!legacyHiddenSet.has(key) && !denySet.has(key) && isTableOverrideExplicitlyVisible(legacyOverrides?.[key])) hidden.delete(key);
6485
6569
  if (fields) for (const [key, config] of Object.entries(fields)) {
6486
6570
  if (isDefaultHiddenAuditField(key) && !legacyHiddenSet.has(key) && !denySet.has(key) && isFieldTableExplicitlyVisible(config)) hidden.delete(key);
6487
- if (config.hidden) hidden.add(key);
6571
+ if (config.table && typeof config.table === "object" && config.table.hidden === false) {
6572
+ if (!legacyHiddenSet.has(key) && !denySet.has(key)) hidden.delete(key);
6573
+ } else if (config.hidden) hidden.add(key);
6488
6574
  else if (config.table === false) hidden.add(key);
6489
6575
  else if (config.table && typeof config.table === "object" && config.table.hidden) hidden.add(key);
6490
6576
  }
@@ -6534,12 +6620,32 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
6534
6620
  /**
6535
6621
  * 渲染字段值
6536
6622
  */
6537
- function renderFieldValue(value, type, booleanLocale, options) {
6623
+ function renderFieldValue(value, type, booleanLocale, options, display = "auto") {
6538
6624
  if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", {
6539
6625
  className: "text-muted-foreground",
6540
6626
  children: "-"
6541
6627
  });
6542
- if (options && options.length > 0) {
6628
+ const renderText = (item) => getOptionLabel(item, options);
6629
+ if (display === "text") return Array.isArray(value) ? value.map(renderText).join(", ") : renderText(value);
6630
+ if (display === "date" || display === "datetime") return formatDate(value, {}, display);
6631
+ if (display === "badge" && (!options || options.length === 0)) {
6632
+ if (Array.isArray(value)) return /* @__PURE__ */ jsxs("div", {
6633
+ className: "flex gap-1 flex-wrap",
6634
+ children: [value.slice(0, 5).map((item, index$1) => /* @__PURE__ */ jsx(Badge, {
6635
+ variant: "secondary",
6636
+ children: String(item)
6637
+ }, index$1)), value.length > 5 && /* @__PURE__ */ jsxs(Badge, {
6638
+ variant: "outline",
6639
+ children: ["+", value.length - 5]
6640
+ })]
6641
+ });
6642
+ return /* @__PURE__ */ jsx(Badge, {
6643
+ variant: "outline",
6644
+ className: "capitalize",
6645
+ children: String(value)
6646
+ });
6647
+ }
6648
+ if ((display === "badge" || display === "auto") && options && options.length > 0) {
6543
6649
  if (Array.isArray(value)) return /* @__PURE__ */ jsxs("div", {
6544
6650
  className: "flex gap-1 flex-wrap",
6545
6651
  children: [value.slice(0, 5).map((v, i) => /* @__PURE__ */ jsx(Badge, {
@@ -6731,7 +6837,7 @@ function resolveActions(actionsOrFn, defaults, rowActionsLocale, context) {
6731
6837
  function AutoCrudTable({ id, title, description, schema, resource, fields, table: tableConfig, form: formConfig, permissions, actions: actionItems, toolbar, toolbarActions, locale: localeProp, onCreate }) {
6732
6838
  const locale = resolveLocale(localeProp);
6733
6839
  const resolvedSchema = resource.schema ?? schema;
6734
- const resolvedFields = React.useMemo(() => mergeFields(resource.fields, fields) ?? {}, [fields, resource.fields]);
6840
+ const resolvedFields = React.useMemo(() => applyResourceTablePresentation(mergeFields(resource.fields, fields), resource.fields) ?? {}, [fields, resource.fields]);
6735
6841
  const can = {
6736
6842
  create: permissions?.can?.create ?? true,
6737
6843
  update: permissions?.can?.update ?? true,
@@ -6754,7 +6860,18 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
6754
6860
  tableConfig?.overrides
6755
6861
  ]);
6756
6862
  const dynamicResolveOptions = useDynamicResolveOptions(resolvedFields, resource.tableData.data, hiddenColumns);
6757
- const dynamicOptionsByField = React.useMemo(() => mergeOptionsByField(dynamicFilterOptions.labelOptionsByField, dynamicResolveOptions.optionsByField), [dynamicFilterOptions.labelOptionsByField, dynamicResolveOptions.optionsByField]);
6863
+ const sharedResolveOptions = useDynamicResolveOptions(React.useMemo(() => Object.fromEntries(Object.entries(resolvedFields).flatMap(([field, config]) => {
6864
+ const table = getTableConfig(config);
6865
+ if (table?.options === void 0 && table?.dataSource === void 0) return [];
6866
+ const { table: _table,...sharedConfig } = config;
6867
+ return [[field, sharedConfig]];
6868
+ })), [resolvedFields]), resource.tableData.data, hiddenColumns);
6869
+ const viewDynamicOptionsByField = React.useMemo(() => mergeOptionsByField(mergeOptionsByField(dynamicFilterOptions.labelOptionsByField, sharedResolveOptions.optionsByField), Object.fromEntries(Object.entries(dynamicResolveOptions.optionsByField).filter(([field]) => !getTableConfig(resolvedFields[field] ?? {})?.dataSource))), [
6870
+ dynamicFilterOptions.labelOptionsByField,
6871
+ dynamicResolveOptions.optionsByField,
6872
+ sharedResolveOptions.optionsByField,
6873
+ resolvedFields
6874
+ ]);
6758
6875
  const resourceIdKey = resource.idKey ?? "id";
6759
6876
  const actionRegistryVersion = useCrudActionsVersion();
6760
6877
  const unifiedActions = React.useMemo(() => {
@@ -7044,6 +7161,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7044
7161
  data: resource.tableData.data,
7045
7162
  schema: resolvedSchema,
7046
7163
  pageCount: resource.tableData.pageCount,
7164
+ ...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
7047
7165
  overrides: tableOverrides,
7048
7166
  exclude: hiddenColumns,
7049
7167
  filterMode: tableConfig?.filterModes,
@@ -7085,7 +7203,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7085
7203
  data: resource.modal.selected,
7086
7204
  schema: resolvedSchema,
7087
7205
  fields: resolvedFields,
7088
- dynamicOptions: dynamicOptionsByField,
7206
+ dynamicOptions: viewDynamicOptionsByField,
7089
7207
  denyFields,
7090
7208
  locale
7091
7209
  }),
@@ -8155,6 +8273,7 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
8155
8273
  tableData: {
8156
8274
  data: tableRows,
8157
8275
  pageCount: listQuery.data?.pageCount ?? 0,
8276
+ ...typeof listQuery.data?.total === "number" ? { total: listQuery.data.total } : {},
8158
8277
  isLoading: listQuery.isLoading,
8159
8278
  isFetching: listQuery.isFetching
8160
8279
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordrhyme/auto-crud",
3
3
  "type": "module",
4
- "version": "1.5.3",
4
+ "version": "1.5.5",
5
5
  "description": "Schema-first CRUD components with auto-generated tables and forms",
6
6
  "author": "wordrhyme",
7
7
  "license": "MIT",
@@ -63,8 +63,8 @@
63
63
  "tailwind-merge": "^3.5.0",
64
64
  "vaul": "^1.1.2",
65
65
  "@wordrhyme/formily-shadcn": "1.13.4",
66
- "@wordrhyme/shadcn": "1.3.4",
67
- "@wordrhyme/shadcn-ui": "1.32.9"
66
+ "@wordrhyme/shadcn-ui": "1.32.9",
67
+ "@wordrhyme/shadcn": "1.3.4"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@storybook/react": "^8.6.18",