@wordrhyme/auto-crud 1.1.2 → 1.1.3

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
@@ -59,6 +59,8 @@ let __pixpilot_formily_shadcn = require("@pixpilot/formily-shadcn");
59
59
  __pixpilot_formily_shadcn = __toESM(__pixpilot_formily_shadcn);
60
60
  let __formily_react = require("@formily/react");
61
61
  __formily_react = __toESM(__formily_react);
62
+ let __pixpilot_shadcn_ui = require("@pixpilot/shadcn-ui");
63
+ __pixpilot_shadcn_ui = __toESM(__pixpilot_shadcn_ui);
62
64
  let sonner = require("sonner");
63
65
  sonner = __toESM(sonner);
64
66
 
@@ -2705,8 +2707,17 @@ function DataTableViewOptions({ table, disabled,...props }) {
2705
2707
 
2706
2708
  //#endregion
2707
2709
  //#region src/components/auto-crud/auto-table-simple-filters.tsx
2708
- function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilters, onFiltersChange }) {
2709
- const columns = react.useMemo(() => table.getAllColumns().filter((col) => col.getCanFilter()), [table]);
2710
+ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilters, onFiltersChange, leading }) {
2711
+ const columns = react.useMemo(() => table.getAllColumns().filter((col) => col.getCanFilter()).sort((a, b) => {
2712
+ const readOrder = (column) => {
2713
+ const metaIndex = column.columnDef.meta?.index;
2714
+ const columnIndex = column.columnDef.index;
2715
+ return typeof metaIndex === "number" ? metaIndex : typeof columnIndex === "number" ? columnIndex : 1e4;
2716
+ };
2717
+ const orderDiff = readOrder(a) - readOrder(b);
2718
+ if (orderDiff !== 0) return orderDiff;
2719
+ return a.getIndex() - b.getIndex();
2720
+ }), [table]);
2710
2721
  const queryStateOptions = table.options.meta?.queryStateOptions;
2711
2722
  const [queryFilters, setQueryFilters] = useReadableFilters(columns, {
2712
2723
  ...queryStateOptions,
@@ -2823,8 +2834,9 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
2823
2834
  if (!mounted) return null;
2824
2835
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2825
2836
  ref: containerRef,
2826
- className: "flex flex-wrap items-center gap-2 min-w-0",
2837
+ className: "flex flex-1 flex-wrap items-center gap-2 min-w-0",
2827
2838
  children: [
2839
+ leading,
2828
2840
  filterColumns.map((column, index) => {
2829
2841
  const meta = column.columnDef.meta;
2830
2842
  const value = getFilterValue(column.id);
@@ -3957,7 +3969,7 @@ function createTableSchema(schema, options) {
3957
3969
  if (cached) return [...cached];
3958
3970
  }
3959
3971
  const shape = schema.shape;
3960
- const columns = [];
3972
+ const columnEntries = [];
3961
3973
  for (const [key, fieldSchema] of Object.entries(shape)) {
3962
3974
  if (exclude.includes(key)) continue;
3963
3975
  const override = overrides?.[key];
@@ -3978,20 +3990,31 @@ function createTableSchema(schema, options) {
3978
3990
  options: override?.meta?.options ?? autoOptions
3979
3991
  };
3980
3992
  const { meta: _ignoredMeta,...restOverride } = override ?? {};
3981
- columns.push({
3982
- id: key,
3983
- accessorKey: key,
3984
- header: ({ column }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableColumnHeader, {
3985
- column,
3986
- label
3987
- }),
3988
- cell: ({ row }) => renderCell(row.getValue(key), parsed.type),
3989
- enableColumnFilter: true,
3990
- enableSorting: true,
3991
- meta,
3992
- ...restOverride
3993
+ const sourceIndex = columnEntries.length;
3994
+ const order = typeof restOverride.index === "number" ? restOverride.index : typeof meta.index === "number" ? meta.index : 1e4 + sourceIndex;
3995
+ columnEntries.push({
3996
+ order,
3997
+ sourceIndex,
3998
+ column: {
3999
+ id: key,
4000
+ accessorKey: key,
4001
+ header: ({ column }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableColumnHeader, {
4002
+ column,
4003
+ label
4004
+ }),
4005
+ cell: ({ row }) => renderCell(row.getValue(key), parsed.type),
4006
+ enableColumnFilter: true,
4007
+ enableSorting: true,
4008
+ meta,
4009
+ ...restOverride
4010
+ }
3993
4011
  });
3994
4012
  }
4013
+ const columns = columnEntries.sort((a, b) => {
4014
+ const orderDiff = a.order - b.order;
4015
+ if (orderDiff !== 0) return orderDiff;
4016
+ return a.sourceIndex - b.sourceIndex;
4017
+ }).map((entry) => entry.column);
3995
4018
  if (canCache) baseTableSchemaCache.set(schema, columns);
3996
4019
  return columns;
3997
4020
  }
@@ -4663,10 +4686,19 @@ const filterModeConfig = {
4663
4686
  tooltip: "Linear-style command filters"
4664
4687
  }
4665
4688
  };
4666
- function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode = "simple", onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, getSelectedRows }) {
4689
+ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode = "simple", search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, getSelectedRows }) {
4667
4690
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
4668
4691
  const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
4669
4692
  const showToggle = modes.length > 1;
4693
+ const [searchValue, setSearchValue] = useUrlState("search", parseAsString.withDefault(""), {
4694
+ shallow: false,
4695
+ clearOnDefault: true
4696
+ });
4697
+ const [, setSearchPage] = useUrlState("page", parseAsInteger.withDefault(1), {
4698
+ shallow: false,
4699
+ clearOnDefault: true
4700
+ });
4701
+ const searchConfig = search && typeof search === "object" ? search : {};
4670
4702
  const { table, shallow, debounceMs, throttleMs } = useDataTable({
4671
4703
  data,
4672
4704
  columns: (0, react.useMemo)(() => {
@@ -4738,11 +4770,21 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4738
4770
  })
4739
4771
  })
4740
4772
  })] }) : null;
4773
+ const searchInput = search ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Input, {
4774
+ value: searchValue,
4775
+ onChange: (event) => {
4776
+ setSearchValue(event.target.value);
4777
+ setSearchPage(1);
4778
+ },
4779
+ placeholder: searchConfig.placeholder ?? "搜索",
4780
+ className: "h-8 w-48 shrink-0"
4781
+ }) : null;
4741
4782
  const filtersContent = (0, react.useMemo)(() => {
4742
4783
  switch (currentMode) {
4743
4784
  case "simple": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTableSimpleFilters, {
4744
4785
  table,
4745
- shallow
4786
+ shallow,
4787
+ leading: searchInput
4746
4788
  });
4747
4789
  case "command": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableFilterMenu, {
4748
4790
  table,
@@ -4762,6 +4804,7 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4762
4804
  currentMode,
4763
4805
  table,
4764
4806
  shallow,
4807
+ searchInput,
4765
4808
  debounceMs,
4766
4809
  throttleMs
4767
4810
  ]);
@@ -4773,10 +4816,14 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4773
4816
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4774
4817
  className: "flex flex-1 items-start gap-2 min-h-[40px]",
4775
4818
  "data-filter-parent": true,
4776
- children: [currentMode !== "simple" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableSortList, {
4777
- table,
4778
- align: "start"
4779
- }), filtersContent]
4819
+ children: [
4820
+ currentMode !== "simple" && searchInput,
4821
+ currentMode !== "simple" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableSortList, {
4822
+ table,
4823
+ align: "start"
4824
+ }),
4825
+ filtersContent
4826
+ ]
4780
4827
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4781
4828
  className: "flex items-center gap-2",
4782
4829
  children: [
@@ -4965,10 +5012,44 @@ function createEditFormSchema(schema, options) {
4965
5012
 
4966
5013
  //#endregion
4967
5014
  //#region src/components/auto-crud/auto-form.tsx
5015
+ const COMBOBOX_LIST_CLASS = "[&_[cmdk-list]]:max-h-[360px]";
4968
5016
  const FormilySwitch = (0, __formily_react.connect)(__pixpilot_shadcn.Switch, (0, __formily_react.mapProps)({
4969
5017
  value: "checked",
4970
5018
  onInput: "onCheckedChange"
4971
5019
  }));
5020
+ const FormilyCombobox = (0, __formily_react.connect)(AutoCrudCombobox, (0, __formily_react.mapProps)({ dataSource: "options" }));
5021
+ function AutoCrudCombobox({ options = [], filter, className,...props }) {
5022
+ const resolvedFilter = (0, react.useMemo)(() => {
5023
+ if (typeof filter === "function") return filter;
5024
+ return createComboboxFilter(options);
5025
+ }, [filter, options]);
5026
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn_ui.Combobox, {
5027
+ ...props,
5028
+ options,
5029
+ filter: resolvedFilter,
5030
+ className: (0, __pixpilot_shadcn.cn)(COMBOBOX_LIST_CLASS, className)
5031
+ });
5032
+ }
5033
+ function createComboboxFilter(options) {
5034
+ const searchTextByValue = new Map(options.map((option) => [option.value, collectSearchText(option.value, option.label, option.searchText, option.keywords).toLocaleLowerCase()]));
5035
+ return (value, search, keywords) => {
5036
+ const query = search.trim().toLocaleLowerCase();
5037
+ if (!query) return 1;
5038
+ const searchText = collectSearchText(searchTextByValue.get(value), keywords).toLocaleLowerCase();
5039
+ if (searchText === query) return 2;
5040
+ return searchText.includes(query) ? 1 : 0;
5041
+ };
5042
+ }
5043
+ function collectSearchText(...parts) {
5044
+ const texts = [];
5045
+ for (const part of parts) {
5046
+ if (!part) continue;
5047
+ if (Array.isArray(part)) texts.push(...part.map(String));
5048
+ else if (typeof part === "object") texts.push(...Object.values(part).filter(Boolean).map(String));
5049
+ else texts.push(String(part));
5050
+ }
5051
+ return texts.join(" ");
5052
+ }
4972
5053
  function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
4973
5054
  const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({ initialValues }), [JSON.stringify(initialValues)]);
4974
5055
  const formSchema = (0, react.useMemo)(() => createEditFormSchema(zodSchema, {
@@ -4993,10 +5074,16 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
4993
5074
  form,
4994
5075
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_formily_shadcn.JsonSchemaField, {
4995
5076
  schema: formSchema,
4996
- components: { fields: { Switch: {
4997
- component: FormilySwitch,
4998
- decorator: "FormItem"
4999
- } } }
5077
+ components: { fields: {
5078
+ Combobox: {
5079
+ component: FormilyCombobox,
5080
+ decorator: "FormItem"
5081
+ },
5082
+ Switch: {
5083
+ component: FormilySwitch,
5084
+ decorator: "FormItem"
5085
+ }
5086
+ } }
5000
5087
  }), showSubmitButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5001
5088
  className: "flex justify-end gap-2 mt-6",
5002
5089
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
@@ -6088,6 +6175,11 @@ function resolveActions(actionsOrFn, defaults, rowActionsLocale) {
6088
6175
  */
6089
6176
  function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, permissions, actions: actionItems, toolbarActions, locale: localeProp, onCreate }) {
6090
6177
  const locale = resolveLocale(localeProp);
6178
+ const resolvedSchema = resource.schema ?? schema;
6179
+ const resolvedFields = react.useMemo(() => ({
6180
+ ...fields,
6181
+ ...resource.fields
6182
+ }), [fields, resource.fields]);
6091
6183
  const can = {
6092
6184
  create: permissions?.can?.create ?? true,
6093
6185
  update: permissions?.can?.update ?? true,
@@ -6103,10 +6195,10 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6103
6195
  const [exporting, setExporting] = react.useState(false);
6104
6196
  const getSelectedRowsRef = react.useRef(null);
6105
6197
  const importColumns = react.useMemo(() => {
6106
- const shape = schema.shape;
6198
+ const shape = resolvedSchema.shape;
6107
6199
  const denySet = new Set(denyFields ?? []);
6108
6200
  return Object.keys(shape).filter((key) => !denySet.has(key));
6109
- }, [schema, denyFields]);
6201
+ }, [resolvedSchema, denyFields]);
6110
6202
  const handleExport = react.useCallback(async (mode) => {
6111
6203
  const filename = title ?? "export";
6112
6204
  const excludeColumns = denyFields;
@@ -6138,21 +6230,34 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6138
6230
  setExporting(false);
6139
6231
  }
6140
6232
  }, [selectedCount, handleExport]);
6141
- const tableOverrides = react.useMemo(() => buildTableOverrides(fields, tableConfig?.overrides), [fields, tableConfig?.overrides]);
6142
- const formOverrides = react.useMemo(() => buildFormOverrides(fields, formConfig?.overrides, denyFields), [
6143
- fields,
6233
+ const tableOverrides = react.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides), [resolvedFields, tableConfig?.overrides]);
6234
+ const formOverrides = react.useMemo(() => buildFormOverrides(resolvedFields, formConfig?.overrides, denyFields), [
6235
+ resolvedFields,
6144
6236
  formConfig?.overrides,
6145
6237
  denyFields
6146
6238
  ]);
6147
- const hiddenColumns = react.useMemo(() => buildHiddenColumns(fields, tableConfig?.hidden, denyFields), [
6148
- fields,
6239
+ const hiddenColumns = react.useMemo(() => buildHiddenColumns(resolvedFields, tableConfig?.hidden, denyFields), [
6240
+ resolvedFields,
6149
6241
  tableConfig?.hidden,
6150
6242
  denyFields
6151
6243
  ]);
6152
- const batchFields = react.useMemo(() => buildBatchUpdateFields(schema, tableConfig?.batchFields, fields), [
6153
- schema,
6244
+ const searchConfig = react.useMemo(() => {
6245
+ const tableSearch = tableConfig?.search;
6246
+ if (tableSearch === false) return false;
6247
+ if (tableSearch && typeof tableSearch === "object") return tableSearch;
6248
+ return Object.values(resolvedFields).some((field) => field?.search === true) ? true : false;
6249
+ }, [resolvedFields, tableConfig?.search]);
6250
+ const batchFields = react.useMemo(() => buildBatchUpdateFields(resolvedSchema, tableConfig?.batchFields, resolvedFields), [
6251
+ resolvedSchema,
6154
6252
  tableConfig?.batchFields,
6155
- fields
6253
+ resolvedFields
6254
+ ]);
6255
+ const formInitialValues = react.useMemo(() => {
6256
+ return resource.modal.createOpen ? resource.modal.copySource ?? void 0 : resource.modal.selected ?? void 0;
6257
+ }, [
6258
+ resource.modal.createOpen,
6259
+ resource.modal.copySource,
6260
+ resource.modal.selected
6156
6261
  ]);
6157
6262
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6158
6263
  className: "space-y-4",
@@ -6233,11 +6338,12 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6233
6338
  }),
6234
6339
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTable, {
6235
6340
  data: resource.tableData.data,
6236
- schema,
6341
+ schema: resolvedSchema,
6237
6342
  pageCount: resource.tableData.pageCount,
6238
6343
  overrides: tableOverrides,
6239
6344
  exclude: hiddenColumns,
6240
6345
  filterMode: tableConfig?.filterModes,
6346
+ search: searchConfig,
6241
6347
  actions: resolveActions(actionItems, {
6242
6348
  openView: resource.handlers.openView,
6243
6349
  openEdit: can.update ? resource.handlers.openEdit : void 0,
@@ -6258,8 +6364,8 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6258
6364
  open: resource.modal.createOpen || resource.modal.editOpen,
6259
6365
  onOpenChange: (open) => !open && resource.handlers.closeModals(),
6260
6366
  mode: resource.modal.createOpen ? "create" : "edit",
6261
- schema,
6262
- initialValues: resource.modal.createOpen ? resource.modal.copySource ?? void 0 : resource.modal.selected ?? void 0,
6367
+ schema: resolvedSchema,
6368
+ initialValues: formInitialValues,
6263
6369
  onSubmit: (values) => {
6264
6370
  if (resource.modal.createOpen) resource.handlers.submitCreate(values);
6265
6371
  else resource.handlers.submitUpdate(values);
@@ -6276,8 +6382,8 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6276
6382
  onOpenChange: (open) => !open && resource.handlers.closeModals(),
6277
6383
  variant: resource.modal.variant,
6278
6384
  data: resource.modal.selected,
6279
- schema,
6280
- fields,
6385
+ schema: resolvedSchema,
6386
+ fields: resolvedFields,
6281
6387
  denyFields,
6282
6388
  locale
6283
6389
  }),
@@ -6996,6 +7102,53 @@ const noopToastAdapter = {
6996
7102
  info: () => {},
6997
7103
  warning: () => {}
6998
7104
  };
7105
+ function isRecord(value) {
7106
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7107
+ }
7108
+ function isJsonSchemaObject(value) {
7109
+ return isRecord(value) && isRecord(value.properties);
7110
+ }
7111
+ function readJsonSchemaType(property) {
7112
+ return Array.isArray(property.type) ? property.type.find((item) => item !== "null") : property.type;
7113
+ }
7114
+ function jsonPropertyToZod(property, required) {
7115
+ const enumValues = property.enum?.filter((value) => typeof value === "string");
7116
+ let schema;
7117
+ if (enumValues && enumValues.length > 0) schema = zod.z.enum(enumValues);
7118
+ else switch (readJsonSchemaType(property)) {
7119
+ case "number":
7120
+ case "integer":
7121
+ schema = zod.z.number();
7122
+ break;
7123
+ case "boolean":
7124
+ schema = zod.z.boolean();
7125
+ break;
7126
+ case "array":
7127
+ schema = zod.z.array(zod.z.unknown());
7128
+ break;
7129
+ case "object":
7130
+ schema = zod.z.record(zod.z.string(), zod.z.unknown());
7131
+ break;
7132
+ case "string":
7133
+ schema = property.format === "date" || property.format === "date-time" ? zod.z.coerce.date() : zod.z.string();
7134
+ break;
7135
+ default: schema = zod.z.unknown();
7136
+ }
7137
+ return required ? schema : schema.optional();
7138
+ }
7139
+ function mergeMetadataSchema(baseSchema, metadataSchema) {
7140
+ if (!isJsonSchemaObject(metadataSchema)) return baseSchema;
7141
+ const required = new Set(Array.isArray(metadataSchema.required) ? metadataSchema.required.filter((field) => typeof field === "string") : []);
7142
+ const extensionShape = {};
7143
+ for (const [field, property] of Object.entries(metadataSchema.properties ?? {})) {
7144
+ if (field in baseSchema.shape) continue;
7145
+ extensionShape[field] = jsonPropertyToZod(property, required.has(field));
7146
+ }
7147
+ return Object.keys(extensionShape).length > 0 ? baseSchema.extend(extensionShape) : baseSchema;
7148
+ }
7149
+ function readMetadataFields(fields) {
7150
+ return isRecord(fields) ? fields : void 0;
7151
+ }
6999
7152
  /**
7000
7153
  * Modal 状态 Reducer
7001
7154
  */
@@ -7054,12 +7207,16 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7054
7207
  (0, react.useEffect)(() => {
7055
7208
  hooksRef.current = hooks;
7056
7209
  }, [hooks]);
7057
- const columns = (0, react.useMemo)(() => createTableSchema(schema), [schema]);
7210
+ const metadata = (router.meta?.useQuery(void 0, { staleTime: 3e4 }))?.data;
7211
+ const resolvedSchema = (0, react.useMemo)(() => mergeMetadataSchema(schema, metadata?.schema), [schema, metadata?.schema]);
7212
+ const metadataFields = (0, react.useMemo)(() => readMetadataFields(metadata?.fields), [metadata?.fields]);
7213
+ const columns = (0, react.useMemo)(() => createTableSchema(resolvedSchema), [resolvedSchema]);
7058
7214
  const [urlParams] = useQueryStates({
7059
7215
  page: parseAsInteger.withDefault(1),
7060
7216
  perPage: parseAsInteger.withDefault(10),
7061
7217
  sort: getSortingStateParser().withDefault([]),
7062
- joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and")
7218
+ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
7219
+ search: parseAsString.withDefault("")
7063
7220
  }, { shallow: false });
7064
7221
  const [filters] = useReadableFilters(columns, { shallow: false });
7065
7222
  const queryInput = (0, react.useMemo)(() => {
@@ -7068,7 +7225,8 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7068
7225
  perPage: urlParams.perPage,
7069
7226
  sort: urlParams.sort,
7070
7227
  filters,
7071
- joinOperator: urlParams.joinOperator
7228
+ joinOperator: urlParams.joinOperator,
7229
+ ...urlParams.search.trim() ? { search: urlParams.search.trim() } : {}
7072
7230
  };
7073
7231
  return queryTransform ? queryTransform(autoParams) : autoParams;
7074
7232
  }, [
@@ -7080,6 +7238,7 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7080
7238
  placeholderData: keepPreviousData,
7081
7239
  staleTime: 0
7082
7240
  });
7241
+ const tableRows = listQuery.data?.data ?? [];
7083
7242
  const createMutation = router.create.useMutation();
7084
7243
  const updateMutation = router.update.useMutation();
7085
7244
  const deleteMutation = router.delete.useMutation();
@@ -7332,11 +7491,13 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7332
7491
  const canExport = !!(exportFetcher || exportQuery);
7333
7492
  return {
7334
7493
  tableData: {
7335
- data: listQuery.data?.data ?? [],
7494
+ data: tableRows,
7336
7495
  pageCount: listQuery.data?.pageCount ?? 0,
7337
7496
  isLoading: listQuery.isLoading,
7338
7497
  isFetching: listQuery.isFetching
7339
7498
  },
7499
+ schema: resolvedSchema,
7500
+ fields: metadataFields,
7340
7501
  modal,
7341
7502
  mutations: {
7342
7503
  isCreating: createMutation.isPending,
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react_jsx_runtime6 from "react/jsx-runtime";
1
+ import * as react_jsx_runtime3 from "react/jsx-runtime";
2
2
  import { z } from "zod";
3
3
  import * as _tanstack_react_table0 from "@tanstack/react-table";
4
4
  import { Column, ColumnDef, ColumnSort, Row, RowData, Table, TableOptions, TableState } from "@tanstack/react-table";
@@ -125,6 +125,10 @@ interface UseAutoCrudResourceReturn<TSchema extends z.ZodObject<z.ZodRawShape>,
125
125
  /** 是否正在获取数据(用于显示微妙的加载指示器) */
126
126
  isFetching: boolean;
127
127
  };
128
+ /** Optional schema override from host metadata. */
129
+ schema?: z.ZodObject<z.ZodRawShape>;
130
+ /** Optional field config override from host metadata. */
131
+ fields?: Fields;
128
132
  modal: ModalState<TListItem>;
129
133
  mutations: {
130
134
  isCreating: boolean;
@@ -182,6 +186,10 @@ interface CrudRouter {
182
186
  export?: {
183
187
  useQuery: (input?: any, opts?: any) => any;
184
188
  };
189
+ /** 元数据路由(query,由 createCrudRouter 自动生成) */
190
+ meta?: {
191
+ useQuery: (input?: any, opts?: any) => any;
192
+ };
185
193
  }
186
194
  /**
187
195
  * 自动生成的查询参数(由内部 URL 状态管理生成)
@@ -193,6 +201,7 @@ interface AutoQueryParams {
193
201
  id: string;
194
202
  desc: boolean;
195
203
  }>;
204
+ search?: string;
196
205
  filters: any[];
197
206
  joinOperator: "and" | "or";
198
207
  }
@@ -352,7 +361,7 @@ declare function AutoTableActionBar<TData>({
352
361
  enableDelete,
353
362
  extraActions,
354
363
  actions
355
- }: AutoTableActionBarProps<TData>): react_jsx_runtime6.JSX.Element;
364
+ }: AutoTableActionBarProps<TData>): react_jsx_runtime3.JSX.Element;
356
365
  //#endregion
357
366
  //#region src/lib/schema-bridge/types.d.ts
358
367
  /**
@@ -379,6 +388,7 @@ interface ParsedZodField {
379
388
  type ColumnOverrides<T> = Partial<{ [K in keyof T]: Partial<ColumnDef<T, unknown>> & {
380
389
  hidden?: boolean;
381
390
  label?: string;
391
+ index?: number;
382
392
  } }>;
383
393
  /**
384
394
  * Formily Schema 覆盖选项
@@ -473,6 +483,10 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
473
483
  * 默认: ["simple", "advanced", "command"] (全部显示)
474
484
  */
475
485
  filterMode?: FilterMode | FilterMode[];
486
+ /** 全局搜索框 */
487
+ search?: boolean | {
488
+ placeholder?: string;
489
+ };
476
490
  /** 批量删除回调 */
477
491
  onDeleteSelected?: (rows: z.infer<T>[]) => void;
478
492
  /** 批量更新回调 */
@@ -504,6 +518,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
504
518
  actions,
505
519
  pinnedColumns,
506
520
  filterMode,
521
+ search,
507
522
  onDeleteSelected,
508
523
  onUpdateSelected,
509
524
  batchUpdateFields,
@@ -514,7 +529,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
514
529
  showDefaultExport,
515
530
  onSelectedCountChange,
516
531
  getSelectedRows
517
- }: AutoTableProps<T>): react_jsx_runtime6.JSX.Element;
532
+ }: AutoTableProps<T>): react_jsx_runtime3.JSX.Element;
518
533
  //#endregion
519
534
  //#region src/i18n/locale.d.ts
520
535
  /**
@@ -629,6 +644,8 @@ interface FilterConfig {
629
644
  unit?: string;
630
645
  /** 过滤器占位符 */
631
646
  placeholder?: string;
647
+ /** 排序权重,数值越小越靠前 */
648
+ index?: number;
632
649
  /** 是否在筛选栏中隐藏(隐藏筛选但不影响表格列显示) */
633
650
  hidden?: boolean;
634
651
  /** 控制在哪些筛选模式下显示(未设置则在所有模式显示) */
@@ -643,6 +660,8 @@ interface Field {
643
660
  label?: string;
644
661
  /** 是否隐藏(表格和表单都隐藏) */
645
662
  hidden?: boolean;
663
+ /** 是否参与 AutoCrud 全局搜索 */
664
+ search?: boolean;
646
665
  /**
647
666
  * 筛选器独立配置
648
667
  * - FilterConfig: 详细配置
@@ -658,6 +677,8 @@ interface Field {
658
677
  table?: {
659
678
  /** 是否在表格中隐藏 */
660
679
  hidden?: boolean;
680
+ /** 排序权重,数值越小越靠前 */
681
+ index?: number;
661
682
  /** 筛选器配置 */
662
683
  meta?: Record<string, unknown>;
663
684
  /** 其他列配置 */
@@ -734,6 +755,8 @@ type ToolbarActionConfig = ToolbarActionItem[] | ((defaults: ToolbarBuiltinActio
734
755
  * AutoCrudTable Props 接口
735
756
  */
736
757
  interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
758
+ /** Public CRUD id. Used by hosts to document the extension target. */
759
+ id?: string;
737
760
  /** 页面标题 */
738
761
  title?: string;
739
762
  /** 页面描述 */
@@ -759,6 +782,10 @@ interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
759
782
  * - 数组: 第一个为默认值,显示切换按钮
760
783
  */
761
784
  filterModes?: FilterMode | FilterMode[];
785
+ /** 全局搜索框;默认在存在 search: true 字段时显示 */
786
+ search?: boolean | {
787
+ placeholder?: string;
788
+ };
762
789
  /**
763
790
  * 批量更新字段配置
764
791
  * - 只需传字段名数组,options 自动从 schema enum 推导
@@ -847,7 +874,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
847
874
  toolbarActions,
848
875
  locale: localeProp,
849
876
  onCreate
850
- }: AutoCrudTableProps<TSchema>): react_jsx_runtime6.JSX.Element;
877
+ }: AutoCrudTableProps<TSchema>): react_jsx_runtime3.JSX.Element;
851
878
  //#endregion
852
879
  //#region src/components/auto-crud/auto-form.d.ts
853
880
  interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
@@ -879,7 +906,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
879
906
  labelAlign,
880
907
  labelWidth,
881
908
  showSubmitButton
882
- }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime6.JSX.Element;
909
+ }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime3.JSX.Element;
883
910
  declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
884
911
  ref?: React.Ref<AutoFormRef>;
885
912
  }) => ReturnType<typeof AutoFormInner>;
@@ -1093,12 +1120,12 @@ declare const filterItemSchema: z.ZodObject<{
1093
1120
  variant: z.ZodEnum<{
1094
1121
  number: "number";
1095
1122
  boolean: "boolean";
1096
- date: "date";
1097
1123
  text: "text";
1124
+ range: "range";
1125
+ date: "date";
1126
+ dateRange: "dateRange";
1098
1127
  select: "select";
1099
1128
  multiSelect: "multiSelect";
1100
- dateRange: "dateRange";
1101
- range: "range";
1102
1129
  }>;
1103
1130
  operator: z.ZodEnum<{
1104
1131
  iLike: "iLike";
@@ -1128,6 +1155,7 @@ declare module "@tanstack/react-table" {
1128
1155
  }
1129
1156
  interface ColumnMeta<TData extends RowData, TValue> {
1130
1157
  label?: string;
1158
+ index?: number;
1131
1159
  placeholder?: string;
1132
1160
  variant?: FilterVariant$1;
1133
1161
  options?: Option[];
@@ -1171,13 +1199,15 @@ interface AutoTableSimpleFiltersProps<TData> {
1171
1199
  shallow?: boolean;
1172
1200
  filters?: ExtendedColumnFilter<TData>[];
1173
1201
  onFiltersChange?: (filters: ExtendedColumnFilter<TData>[]) => void;
1202
+ leading?: React$1.ReactNode;
1174
1203
  }
1175
1204
  declare function AutoTableSimpleFilters<TData>({
1176
1205
  table,
1177
1206
  shallow,
1178
1207
  filters: externalFilters,
1179
- onFiltersChange
1180
- }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime6.JSX.Element | null;
1208
+ onFiltersChange,
1209
+ leading
1210
+ }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime3.JSX.Element | null;
1181
1211
  //#endregion
1182
1212
  //#region src/components/auto-crud/form-modal.d.ts
1183
1213
  type ModalVariant = "dialog" | "sheet";
@@ -1219,7 +1249,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
1219
1249
  labelAlign,
1220
1250
  labelWidth,
1221
1251
  className
1222
- }: CrudFormModalProps<T>): react_jsx_runtime6.JSX.Element;
1252
+ }: CrudFormModalProps<T>): react_jsx_runtime3.JSX.Element;
1223
1253
  //#endregion
1224
1254
  //#region src/components/auto-crud/import-dialog.d.ts
1225
1255
  interface ImportDialogProps {
@@ -1241,7 +1271,7 @@ declare function ImportDialog({
1241
1271
  columns,
1242
1272
  title,
1243
1273
  locale
1244
- }: ImportDialogProps): react_jsx_runtime6.JSX.Element;
1274
+ }: ImportDialogProps): react_jsx_runtime3.JSX.Element;
1245
1275
  //#endregion
1246
1276
  //#region src/components/auto-crud/export-dialog.d.ts
1247
1277
  type ExportMode = "selected" | "filtered";
@@ -1261,7 +1291,7 @@ declare function ExportDialog({
1261
1291
  selectedCount,
1262
1292
  onExport,
1263
1293
  canExportFiltered
1264
- }: ExportDialogProps): react_jsx_runtime6.JSX.Element;
1294
+ }: ExportDialogProps): react_jsx_runtime3.JSX.Element;
1265
1295
  //#endregion
1266
1296
  //#region src/components/data-table/data-table.d.ts
1267
1297
  interface DataTableProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1274,7 +1304,7 @@ declare function DataTable<TData>({
1274
1304
  children,
1275
1305
  className,
1276
1306
  ...props
1277
- }: DataTableProps<TData>): react_jsx_runtime6.JSX.Element;
1307
+ }: DataTableProps<TData>): react_jsx_runtime3.JSX.Element;
1278
1308
  //#endregion
1279
1309
  //#region src/components/data-table/data-table-advanced-toolbar.d.ts
1280
1310
  interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1285,7 +1315,7 @@ declare function DataTableAdvancedToolbar<TData>({
1285
1315
  children,
1286
1316
  className,
1287
1317
  ...props
1288
- }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime6.JSX.Element;
1318
+ }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1289
1319
  //#endregion
1290
1320
  //#region src/components/data-table/data-table-column-header.d.ts
1291
1321
  interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
@@ -1297,7 +1327,7 @@ declare function DataTableColumnHeader<TData, TValue>({
1297
1327
  label,
1298
1328
  className,
1299
1329
  ...props
1300
- }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime6.JSX.Element;
1330
+ }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1301
1331
  //#endregion
1302
1332
  //#region src/components/data-table/data-table-faceted-filter.d.ts
1303
1333
  interface DataTableFacetedFilterProps<TData, TValue> {
@@ -1311,7 +1341,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
1311
1341
  title,
1312
1342
  options,
1313
1343
  multiple
1314
- }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime6.JSX.Element;
1344
+ }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1315
1345
  //#endregion
1316
1346
  //#region src/components/data-table/data-table-pagination.d.ts
1317
1347
  interface DataTablePaginationProps<TData> extends React.ComponentProps<"div"> {
@@ -1323,7 +1353,7 @@ declare function DataTablePagination<TData>({
1323
1353
  pageSizeOptions,
1324
1354
  className,
1325
1355
  ...props
1326
- }: DataTablePaginationProps<TData>): react_jsx_runtime6.JSX.Element;
1356
+ }: DataTablePaginationProps<TData>): react_jsx_runtime3.JSX.Element;
1327
1357
  //#endregion
1328
1358
  //#region src/components/data-table/data-table-toolbar.d.ts
1329
1359
  interface DataTableToolbarProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1334,7 +1364,7 @@ declare function DataTableToolbar<TData>({
1334
1364
  children,
1335
1365
  className,
1336
1366
  ...props
1337
- }: DataTableToolbarProps<TData>): react_jsx_runtime6.JSX.Element;
1367
+ }: DataTableToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1338
1368
  //#endregion
1339
1369
  //#region src/components/data-table/data-table-view-options.d.ts
1340
1370
  interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
@@ -1345,7 +1375,7 @@ declare function DataTableViewOptions<TData>({
1345
1375
  table,
1346
1376
  disabled,
1347
1377
  ...props
1348
- }: DataTableViewOptionsProps<TData>): react_jsx_runtime6.JSX.Element;
1378
+ }: DataTableViewOptionsProps<TData>): react_jsx_runtime3.JSX.Element;
1349
1379
  //#endregion
1350
1380
  //#region src/hooks/use-data-table.d.ts
1351
1381
  interface UseDataTableProps<TData> extends Omit<TableOptions<TData>, "state" | "pageCount" | "getCoreRowModel" | "manualFiltering" | "manualPagination" | "manualSorting">, Required<Pick<TableOptions<TData>, "pageCount">> {
@@ -1512,6 +1542,7 @@ interface ListParams {
1512
1542
  id: string;
1513
1543
  desc: boolean;
1514
1544
  }>;
1545
+ search?: string;
1515
1546
  filters?: Array<{
1516
1547
  id: string;
1517
1548
  value: any;
package/dist/index.d.ts CHANGED
@@ -125,6 +125,10 @@ interface UseAutoCrudResourceReturn<TSchema extends z.ZodObject<z.ZodRawShape>,
125
125
  /** 是否正在获取数据(用于显示微妙的加载指示器) */
126
126
  isFetching: boolean;
127
127
  };
128
+ /** Optional schema override from host metadata. */
129
+ schema?: z.ZodObject<z.ZodRawShape>;
130
+ /** Optional field config override from host metadata. */
131
+ fields?: Fields;
128
132
  modal: ModalState<TListItem>;
129
133
  mutations: {
130
134
  isCreating: boolean;
@@ -182,6 +186,10 @@ interface CrudRouter {
182
186
  export?: {
183
187
  useQuery: (input?: any, opts?: any) => any;
184
188
  };
189
+ /** 元数据路由(query,由 createCrudRouter 自动生成) */
190
+ meta?: {
191
+ useQuery: (input?: any, opts?: any) => any;
192
+ };
185
193
  }
186
194
  /**
187
195
  * 自动生成的查询参数(由内部 URL 状态管理生成)
@@ -193,6 +201,7 @@ interface AutoQueryParams {
193
201
  id: string;
194
202
  desc: boolean;
195
203
  }>;
204
+ search?: string;
196
205
  filters: any[];
197
206
  joinOperator: "and" | "or";
198
207
  }
@@ -379,6 +388,7 @@ interface ParsedZodField {
379
388
  type ColumnOverrides<T> = Partial<{ [K in keyof T]: Partial<ColumnDef<T, unknown>> & {
380
389
  hidden?: boolean;
381
390
  label?: string;
391
+ index?: number;
382
392
  } }>;
383
393
  /**
384
394
  * Formily Schema 覆盖选项
@@ -473,6 +483,10 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> {
473
483
  * 默认: ["simple", "advanced", "command"] (全部显示)
474
484
  */
475
485
  filterMode?: FilterMode | FilterMode[];
486
+ /** 全局搜索框 */
487
+ search?: boolean | {
488
+ placeholder?: string;
489
+ };
476
490
  /** 批量删除回调 */
477
491
  onDeleteSelected?: (rows: z.infer<T>[]) => void;
478
492
  /** 批量更新回调 */
@@ -504,6 +518,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
504
518
  actions,
505
519
  pinnedColumns,
506
520
  filterMode,
521
+ search,
507
522
  onDeleteSelected,
508
523
  onUpdateSelected,
509
524
  batchUpdateFields,
@@ -629,6 +644,8 @@ interface FilterConfig {
629
644
  unit?: string;
630
645
  /** 过滤器占位符 */
631
646
  placeholder?: string;
647
+ /** 排序权重,数值越小越靠前 */
648
+ index?: number;
632
649
  /** 是否在筛选栏中隐藏(隐藏筛选但不影响表格列显示) */
633
650
  hidden?: boolean;
634
651
  /** 控制在哪些筛选模式下显示(未设置则在所有模式显示) */
@@ -643,6 +660,8 @@ interface Field {
643
660
  label?: string;
644
661
  /** 是否隐藏(表格和表单都隐藏) */
645
662
  hidden?: boolean;
663
+ /** 是否参与 AutoCrud 全局搜索 */
664
+ search?: boolean;
646
665
  /**
647
666
  * 筛选器独立配置
648
667
  * - FilterConfig: 详细配置
@@ -658,6 +677,8 @@ interface Field {
658
677
  table?: {
659
678
  /** 是否在表格中隐藏 */
660
679
  hidden?: boolean;
680
+ /** 排序权重,数值越小越靠前 */
681
+ index?: number;
661
682
  /** 筛选器配置 */
662
683
  meta?: Record<string, unknown>;
663
684
  /** 其他列配置 */
@@ -734,6 +755,8 @@ type ToolbarActionConfig = ToolbarActionItem[] | ((defaults: ToolbarBuiltinActio
734
755
  * AutoCrudTable Props 接口
735
756
  */
736
757
  interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
758
+ /** Public CRUD id. Used by hosts to document the extension target. */
759
+ id?: string;
737
760
  /** 页面标题 */
738
761
  title?: string;
739
762
  /** 页面描述 */
@@ -759,6 +782,10 @@ interface AutoCrudTableProps<TSchema extends z.ZodObject<z.ZodRawShape>> {
759
782
  * - 数组: 第一个为默认值,显示切换按钮
760
783
  */
761
784
  filterModes?: FilterMode | FilterMode[];
785
+ /** 全局搜索框;默认在存在 search: true 字段时显示 */
786
+ search?: boolean | {
787
+ placeholder?: string;
788
+ };
762
789
  /**
763
790
  * 批量更新字段配置
764
791
  * - 只需传字段名数组,options 自动从 schema enum 推导
@@ -1093,12 +1120,12 @@ declare const filterItemSchema: z.ZodObject<{
1093
1120
  variant: z.ZodEnum<{
1094
1121
  number: "number";
1095
1122
  boolean: "boolean";
1096
- date: "date";
1097
1123
  text: "text";
1124
+ range: "range";
1125
+ date: "date";
1126
+ dateRange: "dateRange";
1098
1127
  select: "select";
1099
1128
  multiSelect: "multiSelect";
1100
- dateRange: "dateRange";
1101
- range: "range";
1102
1129
  }>;
1103
1130
  operator: z.ZodEnum<{
1104
1131
  iLike: "iLike";
@@ -1128,6 +1155,7 @@ declare module "@tanstack/react-table" {
1128
1155
  }
1129
1156
  interface ColumnMeta<TData extends RowData, TValue> {
1130
1157
  label?: string;
1158
+ index?: number;
1131
1159
  placeholder?: string;
1132
1160
  variant?: FilterVariant$1;
1133
1161
  options?: Option[];
@@ -1171,12 +1199,14 @@ interface AutoTableSimpleFiltersProps<TData> {
1171
1199
  shallow?: boolean;
1172
1200
  filters?: ExtendedColumnFilter<TData>[];
1173
1201
  onFiltersChange?: (filters: ExtendedColumnFilter<TData>[]) => void;
1202
+ leading?: React$1.ReactNode;
1174
1203
  }
1175
1204
  declare function AutoTableSimpleFilters<TData>({
1176
1205
  table,
1177
1206
  shallow,
1178
1207
  filters: externalFilters,
1179
- onFiltersChange
1208
+ onFiltersChange,
1209
+ leading
1180
1210
  }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime2.JSX.Element | null;
1181
1211
  //#endregion
1182
1212
  //#region src/components/auto-crud/form-modal.d.ts
@@ -1512,6 +1542,7 @@ interface ListParams {
1512
1542
  id: string;
1513
1543
  desc: boolean;
1514
1544
  }>;
1545
+ search?: string;
1515
1546
  filters?: Array<{
1516
1547
  id: string;
1517
1548
  value: any;
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef } from "react";
3
3
  import { ArrowDownUp, BadgeCheck, CalendarIcon, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ChevronsLeft, ChevronsRight, ChevronsUpDown, CommandIcon, Download, Ellipsis, EyeOff, FileDown, FileSpreadsheetIcon, GripVertical, ListFilter, ListFilterIcon, Loader2, PlusCircle, Settings2, Text, Trash2, Upload, X, XCircle } from "lucide-react";
4
4
  import { flexRender, getCoreRowModel, getFacetedMinMaxValues, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
5
- import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Calendar, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Label, Popover, PopoverContent, PopoverTrigger, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, Slider, Switch } from "@pixpilot/shadcn";
5
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Calendar, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Label, Popover, PopoverContent, PopoverTrigger, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, Slider, Switch, cn as cn$1 } from "@pixpilot/shadcn";
6
6
  import { clsx } from "clsx";
7
7
  import { twMerge } from "tailwind-merge";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -18,6 +18,7 @@ import { z } from "zod";
18
18
  import { createForm } from "@formily/core";
19
19
  import { Form, JsonSchemaField } from "@pixpilot/formily-shadcn";
20
20
  import { connect, mapProps } from "@formily/react";
21
+ import { Combobox } from "@pixpilot/shadcn-ui";
21
22
  import { toast } from "sonner";
22
23
 
23
24
  //#region src/lib/utils.ts
@@ -2663,8 +2664,17 @@ function DataTableViewOptions({ table, disabled,...props }) {
2663
2664
 
2664
2665
  //#endregion
2665
2666
  //#region src/components/auto-crud/auto-table-simple-filters.tsx
2666
- function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilters, onFiltersChange }) {
2667
- const columns = React.useMemo(() => table.getAllColumns().filter((col) => col.getCanFilter()), [table]);
2667
+ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilters, onFiltersChange, leading }) {
2668
+ const columns = React.useMemo(() => table.getAllColumns().filter((col) => col.getCanFilter()).sort((a, b) => {
2669
+ const readOrder = (column) => {
2670
+ const metaIndex = column.columnDef.meta?.index;
2671
+ const columnIndex = column.columnDef.index;
2672
+ return typeof metaIndex === "number" ? metaIndex : typeof columnIndex === "number" ? columnIndex : 1e4;
2673
+ };
2674
+ const orderDiff = readOrder(a) - readOrder(b);
2675
+ if (orderDiff !== 0) return orderDiff;
2676
+ return a.getIndex() - b.getIndex();
2677
+ }), [table]);
2668
2678
  const queryStateOptions = table.options.meta?.queryStateOptions;
2669
2679
  const [queryFilters, setQueryFilters] = useReadableFilters(columns, {
2670
2680
  ...queryStateOptions,
@@ -2781,8 +2791,9 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
2781
2791
  if (!mounted) return null;
2782
2792
  return /* @__PURE__ */ jsxs("div", {
2783
2793
  ref: containerRef,
2784
- className: "flex flex-wrap items-center gap-2 min-w-0",
2794
+ className: "flex flex-1 flex-wrap items-center gap-2 min-w-0",
2785
2795
  children: [
2796
+ leading,
2786
2797
  filterColumns.map((column, index) => {
2787
2798
  const meta = column.columnDef.meta;
2788
2799
  const value = getFilterValue(column.id);
@@ -3915,7 +3926,7 @@ function createTableSchema(schema, options) {
3915
3926
  if (cached) return [...cached];
3916
3927
  }
3917
3928
  const shape = schema.shape;
3918
- const columns = [];
3929
+ const columnEntries = [];
3919
3930
  for (const [key, fieldSchema] of Object.entries(shape)) {
3920
3931
  if (exclude.includes(key)) continue;
3921
3932
  const override = overrides?.[key];
@@ -3936,20 +3947,31 @@ function createTableSchema(schema, options) {
3936
3947
  options: override?.meta?.options ?? autoOptions
3937
3948
  };
3938
3949
  const { meta: _ignoredMeta,...restOverride } = override ?? {};
3939
- columns.push({
3940
- id: key,
3941
- accessorKey: key,
3942
- header: ({ column }) => /* @__PURE__ */ jsx(DataTableColumnHeader, {
3943
- column,
3944
- label
3945
- }),
3946
- cell: ({ row }) => renderCell(row.getValue(key), parsed.type),
3947
- enableColumnFilter: true,
3948
- enableSorting: true,
3949
- meta,
3950
- ...restOverride
3950
+ const sourceIndex = columnEntries.length;
3951
+ const order = typeof restOverride.index === "number" ? restOverride.index : typeof meta.index === "number" ? meta.index : 1e4 + sourceIndex;
3952
+ columnEntries.push({
3953
+ order,
3954
+ sourceIndex,
3955
+ column: {
3956
+ id: key,
3957
+ accessorKey: key,
3958
+ header: ({ column }) => /* @__PURE__ */ jsx(DataTableColumnHeader, {
3959
+ column,
3960
+ label
3961
+ }),
3962
+ cell: ({ row }) => renderCell(row.getValue(key), parsed.type),
3963
+ enableColumnFilter: true,
3964
+ enableSorting: true,
3965
+ meta,
3966
+ ...restOverride
3967
+ }
3951
3968
  });
3952
3969
  }
3970
+ const columns = columnEntries.sort((a, b) => {
3971
+ const orderDiff = a.order - b.order;
3972
+ if (orderDiff !== 0) return orderDiff;
3973
+ return a.sourceIndex - b.sourceIndex;
3974
+ }).map((entry) => entry.column);
3953
3975
  if (canCache) baseTableSchemaCache.set(schema, columns);
3954
3976
  return columns;
3955
3977
  }
@@ -4621,10 +4643,19 @@ const filterModeConfig = {
4621
4643
  tooltip: "Linear-style command filters"
4622
4644
  }
4623
4645
  };
4624
- function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode = "simple", onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, getSelectedRows }) {
4646
+ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection = true, exclude, actions, pinnedColumns, filterMode = "simple", search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, getSelectedRows }) {
4625
4647
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
4626
4648
  const [currentMode, setCurrentMode] = useQueryState("filterMode", parseAsStringEnum(modes).withDefault(modes[0] ?? "simple"));
4627
4649
  const showToggle = modes.length > 1;
4650
+ const [searchValue, setSearchValue] = useUrlState("search", parseAsString.withDefault(""), {
4651
+ shallow: false,
4652
+ clearOnDefault: true
4653
+ });
4654
+ const [, setSearchPage] = useUrlState("page", parseAsInteger.withDefault(1), {
4655
+ shallow: false,
4656
+ clearOnDefault: true
4657
+ });
4658
+ const searchConfig = search && typeof search === "object" ? search : {};
4628
4659
  const { table, shallow, debounceMs, throttleMs } = useDataTable({
4629
4660
  data,
4630
4661
  columns: useMemo(() => {
@@ -4696,11 +4727,21 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4696
4727
  })
4697
4728
  })
4698
4729
  })] }) : null;
4730
+ const searchInput = search ? /* @__PURE__ */ jsx(Input, {
4731
+ value: searchValue,
4732
+ onChange: (event) => {
4733
+ setSearchValue(event.target.value);
4734
+ setSearchPage(1);
4735
+ },
4736
+ placeholder: searchConfig.placeholder ?? "搜索",
4737
+ className: "h-8 w-48 shrink-0"
4738
+ }) : null;
4699
4739
  const filtersContent = useMemo(() => {
4700
4740
  switch (currentMode) {
4701
4741
  case "simple": return /* @__PURE__ */ jsx(AutoTableSimpleFilters, {
4702
4742
  table,
4703
- shallow
4743
+ shallow,
4744
+ leading: searchInput
4704
4745
  });
4705
4746
  case "command": return /* @__PURE__ */ jsx(DataTableFilterMenu, {
4706
4747
  table,
@@ -4720,6 +4761,7 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4720
4761
  currentMode,
4721
4762
  table,
4722
4763
  shallow,
4764
+ searchInput,
4723
4765
  debounceMs,
4724
4766
  throttleMs
4725
4767
  ]);
@@ -4731,10 +4773,14 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
4731
4773
  children: [/* @__PURE__ */ jsxs("div", {
4732
4774
  className: "flex flex-1 items-start gap-2 min-h-[40px]",
4733
4775
  "data-filter-parent": true,
4734
- children: [currentMode !== "simple" && /* @__PURE__ */ jsx(DataTableSortList, {
4735
- table,
4736
- align: "start"
4737
- }), filtersContent]
4776
+ children: [
4777
+ currentMode !== "simple" && searchInput,
4778
+ currentMode !== "simple" && /* @__PURE__ */ jsx(DataTableSortList, {
4779
+ table,
4780
+ align: "start"
4781
+ }),
4782
+ filtersContent
4783
+ ]
4738
4784
  }), /* @__PURE__ */ jsxs("div", {
4739
4785
  className: "flex items-center gap-2",
4740
4786
  children: [
@@ -4923,10 +4969,44 @@ function createEditFormSchema(schema, options) {
4923
4969
 
4924
4970
  //#endregion
4925
4971
  //#region src/components/auto-crud/auto-form.tsx
4972
+ const COMBOBOX_LIST_CLASS = "[&_[cmdk-list]]:max-h-[360px]";
4926
4973
  const FormilySwitch = connect(Switch, mapProps({
4927
4974
  value: "checked",
4928
4975
  onInput: "onCheckedChange"
4929
4976
  }));
4977
+ const FormilyCombobox = connect(AutoCrudCombobox, mapProps({ dataSource: "options" }));
4978
+ function AutoCrudCombobox({ options = [], filter, className,...props }) {
4979
+ const resolvedFilter = useMemo(() => {
4980
+ if (typeof filter === "function") return filter;
4981
+ return createComboboxFilter(options);
4982
+ }, [filter, options]);
4983
+ return /* @__PURE__ */ jsx(Combobox, {
4984
+ ...props,
4985
+ options,
4986
+ filter: resolvedFilter,
4987
+ className: cn$1(COMBOBOX_LIST_CLASS, className)
4988
+ });
4989
+ }
4990
+ function createComboboxFilter(options) {
4991
+ const searchTextByValue = new Map(options.map((option) => [option.value, collectSearchText(option.value, option.label, option.searchText, option.keywords).toLocaleLowerCase()]));
4992
+ return (value, search, keywords) => {
4993
+ const query = search.trim().toLocaleLowerCase();
4994
+ if (!query) return 1;
4995
+ const searchText = collectSearchText(searchTextByValue.get(value), keywords).toLocaleLowerCase();
4996
+ if (searchText === query) return 2;
4997
+ return searchText.includes(query) ? 1 : 0;
4998
+ };
4999
+ }
5000
+ function collectSearchText(...parts) {
5001
+ const texts = [];
5002
+ for (const part of parts) {
5003
+ if (!part) continue;
5004
+ if (Array.isArray(part)) texts.push(...part.map(String));
5005
+ else if (typeof part === "object") texts.push(...Object.values(part).filter(Boolean).map(String));
5006
+ else texts.push(String(part));
5007
+ }
5008
+ return texts.join(" ");
5009
+ }
4930
5010
  function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
4931
5011
  const form = useMemo(() => createForm({ initialValues }), [JSON.stringify(initialValues)]);
4932
5012
  const formSchema = useMemo(() => createEditFormSchema(zodSchema, {
@@ -4951,10 +5031,16 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
4951
5031
  form,
4952
5032
  children: [/* @__PURE__ */ jsx(JsonSchemaField, {
4953
5033
  schema: formSchema,
4954
- components: { fields: { Switch: {
4955
- component: FormilySwitch,
4956
- decorator: "FormItem"
4957
- } } }
5034
+ components: { fields: {
5035
+ Combobox: {
5036
+ component: FormilyCombobox,
5037
+ decorator: "FormItem"
5038
+ },
5039
+ Switch: {
5040
+ component: FormilySwitch,
5041
+ decorator: "FormItem"
5042
+ }
5043
+ } }
4958
5044
  }), showSubmitButton && /* @__PURE__ */ jsx("div", {
4959
5045
  className: "flex justify-end gap-2 mt-6",
4960
5046
  children: /* @__PURE__ */ jsx(Button, {
@@ -6046,6 +6132,11 @@ function resolveActions(actionsOrFn, defaults, rowActionsLocale) {
6046
6132
  */
6047
6133
  function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, permissions, actions: actionItems, toolbarActions, locale: localeProp, onCreate }) {
6048
6134
  const locale = resolveLocale(localeProp);
6135
+ const resolvedSchema = resource.schema ?? schema;
6136
+ const resolvedFields = React.useMemo(() => ({
6137
+ ...fields,
6138
+ ...resource.fields
6139
+ }), [fields, resource.fields]);
6049
6140
  const can = {
6050
6141
  create: permissions?.can?.create ?? true,
6051
6142
  update: permissions?.can?.update ?? true,
@@ -6061,10 +6152,10 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6061
6152
  const [exporting, setExporting] = React.useState(false);
6062
6153
  const getSelectedRowsRef = React.useRef(null);
6063
6154
  const importColumns = React.useMemo(() => {
6064
- const shape = schema.shape;
6155
+ const shape = resolvedSchema.shape;
6065
6156
  const denySet = new Set(denyFields ?? []);
6066
6157
  return Object.keys(shape).filter((key) => !denySet.has(key));
6067
- }, [schema, denyFields]);
6158
+ }, [resolvedSchema, denyFields]);
6068
6159
  const handleExport = React.useCallback(async (mode) => {
6069
6160
  const filename = title ?? "export";
6070
6161
  const excludeColumns = denyFields;
@@ -6096,21 +6187,34 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6096
6187
  setExporting(false);
6097
6188
  }
6098
6189
  }, [selectedCount, handleExport]);
6099
- const tableOverrides = React.useMemo(() => buildTableOverrides(fields, tableConfig?.overrides), [fields, tableConfig?.overrides]);
6100
- const formOverrides = React.useMemo(() => buildFormOverrides(fields, formConfig?.overrides, denyFields), [
6101
- fields,
6190
+ const tableOverrides = React.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides), [resolvedFields, tableConfig?.overrides]);
6191
+ const formOverrides = React.useMemo(() => buildFormOverrides(resolvedFields, formConfig?.overrides, denyFields), [
6192
+ resolvedFields,
6102
6193
  formConfig?.overrides,
6103
6194
  denyFields
6104
6195
  ]);
6105
- const hiddenColumns = React.useMemo(() => buildHiddenColumns(fields, tableConfig?.hidden, denyFields), [
6106
- fields,
6196
+ const hiddenColumns = React.useMemo(() => buildHiddenColumns(resolvedFields, tableConfig?.hidden, denyFields), [
6197
+ resolvedFields,
6107
6198
  tableConfig?.hidden,
6108
6199
  denyFields
6109
6200
  ]);
6110
- const batchFields = React.useMemo(() => buildBatchUpdateFields(schema, tableConfig?.batchFields, fields), [
6111
- schema,
6201
+ const searchConfig = React.useMemo(() => {
6202
+ const tableSearch = tableConfig?.search;
6203
+ if (tableSearch === false) return false;
6204
+ if (tableSearch && typeof tableSearch === "object") return tableSearch;
6205
+ return Object.values(resolvedFields).some((field) => field?.search === true) ? true : false;
6206
+ }, [resolvedFields, tableConfig?.search]);
6207
+ const batchFields = React.useMemo(() => buildBatchUpdateFields(resolvedSchema, tableConfig?.batchFields, resolvedFields), [
6208
+ resolvedSchema,
6112
6209
  tableConfig?.batchFields,
6113
- fields
6210
+ resolvedFields
6211
+ ]);
6212
+ const formInitialValues = React.useMemo(() => {
6213
+ return resource.modal.createOpen ? resource.modal.copySource ?? void 0 : resource.modal.selected ?? void 0;
6214
+ }, [
6215
+ resource.modal.createOpen,
6216
+ resource.modal.copySource,
6217
+ resource.modal.selected
6114
6218
  ]);
6115
6219
  return /* @__PURE__ */ jsxs("div", {
6116
6220
  className: "space-y-4",
@@ -6191,11 +6295,12 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6191
6295
  }),
6192
6296
  /* @__PURE__ */ jsx(AutoTable, {
6193
6297
  data: resource.tableData.data,
6194
- schema,
6298
+ schema: resolvedSchema,
6195
6299
  pageCount: resource.tableData.pageCount,
6196
6300
  overrides: tableOverrides,
6197
6301
  exclude: hiddenColumns,
6198
6302
  filterMode: tableConfig?.filterModes,
6303
+ search: searchConfig,
6199
6304
  actions: resolveActions(actionItems, {
6200
6305
  openView: resource.handlers.openView,
6201
6306
  openEdit: can.update ? resource.handlers.openEdit : void 0,
@@ -6216,8 +6321,8 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6216
6321
  open: resource.modal.createOpen || resource.modal.editOpen,
6217
6322
  onOpenChange: (open) => !open && resource.handlers.closeModals(),
6218
6323
  mode: resource.modal.createOpen ? "create" : "edit",
6219
- schema,
6220
- initialValues: resource.modal.createOpen ? resource.modal.copySource ?? void 0 : resource.modal.selected ?? void 0,
6324
+ schema: resolvedSchema,
6325
+ initialValues: formInitialValues,
6221
6326
  onSubmit: (values) => {
6222
6327
  if (resource.modal.createOpen) resource.handlers.submitCreate(values);
6223
6328
  else resource.handlers.submitUpdate(values);
@@ -6234,8 +6339,8 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
6234
6339
  onOpenChange: (open) => !open && resource.handlers.closeModals(),
6235
6340
  variant: resource.modal.variant,
6236
6341
  data: resource.modal.selected,
6237
- schema,
6238
- fields,
6342
+ schema: resolvedSchema,
6343
+ fields: resolvedFields,
6239
6344
  denyFields,
6240
6345
  locale
6241
6346
  }),
@@ -6954,6 +7059,53 @@ const noopToastAdapter = {
6954
7059
  info: () => {},
6955
7060
  warning: () => {}
6956
7061
  };
7062
+ function isRecord(value) {
7063
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7064
+ }
7065
+ function isJsonSchemaObject(value) {
7066
+ return isRecord(value) && isRecord(value.properties);
7067
+ }
7068
+ function readJsonSchemaType(property) {
7069
+ return Array.isArray(property.type) ? property.type.find((item) => item !== "null") : property.type;
7070
+ }
7071
+ function jsonPropertyToZod(property, required) {
7072
+ const enumValues = property.enum?.filter((value) => typeof value === "string");
7073
+ let schema;
7074
+ if (enumValues && enumValues.length > 0) schema = z.enum(enumValues);
7075
+ else switch (readJsonSchemaType(property)) {
7076
+ case "number":
7077
+ case "integer":
7078
+ schema = z.number();
7079
+ break;
7080
+ case "boolean":
7081
+ schema = z.boolean();
7082
+ break;
7083
+ case "array":
7084
+ schema = z.array(z.unknown());
7085
+ break;
7086
+ case "object":
7087
+ schema = z.record(z.string(), z.unknown());
7088
+ break;
7089
+ case "string":
7090
+ schema = property.format === "date" || property.format === "date-time" ? z.coerce.date() : z.string();
7091
+ break;
7092
+ default: schema = z.unknown();
7093
+ }
7094
+ return required ? schema : schema.optional();
7095
+ }
7096
+ function mergeMetadataSchema(baseSchema, metadataSchema) {
7097
+ if (!isJsonSchemaObject(metadataSchema)) return baseSchema;
7098
+ const required = new Set(Array.isArray(metadataSchema.required) ? metadataSchema.required.filter((field) => typeof field === "string") : []);
7099
+ const extensionShape = {};
7100
+ for (const [field, property] of Object.entries(metadataSchema.properties ?? {})) {
7101
+ if (field in baseSchema.shape) continue;
7102
+ extensionShape[field] = jsonPropertyToZod(property, required.has(field));
7103
+ }
7104
+ return Object.keys(extensionShape).length > 0 ? baseSchema.extend(extensionShape) : baseSchema;
7105
+ }
7106
+ function readMetadataFields(fields) {
7107
+ return isRecord(fields) ? fields : void 0;
7108
+ }
6957
7109
  /**
6958
7110
  * Modal 状态 Reducer
6959
7111
  */
@@ -7012,12 +7164,16 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7012
7164
  useEffect(() => {
7013
7165
  hooksRef.current = hooks;
7014
7166
  }, [hooks]);
7015
- const columns = useMemo(() => createTableSchema(schema), [schema]);
7167
+ const metadata = (router.meta?.useQuery(void 0, { staleTime: 3e4 }))?.data;
7168
+ const resolvedSchema = useMemo(() => mergeMetadataSchema(schema, metadata?.schema), [schema, metadata?.schema]);
7169
+ const metadataFields = useMemo(() => readMetadataFields(metadata?.fields), [metadata?.fields]);
7170
+ const columns = useMemo(() => createTableSchema(resolvedSchema), [resolvedSchema]);
7016
7171
  const [urlParams] = useQueryStates({
7017
7172
  page: parseAsInteger.withDefault(1),
7018
7173
  perPage: parseAsInteger.withDefault(10),
7019
7174
  sort: getSortingStateParser().withDefault([]),
7020
- joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and")
7175
+ joinOperator: parseAsStringEnum(["and", "or"]).withDefault("and"),
7176
+ search: parseAsString.withDefault("")
7021
7177
  }, { shallow: false });
7022
7178
  const [filters] = useReadableFilters(columns, { shallow: false });
7023
7179
  const queryInput = useMemo(() => {
@@ -7026,7 +7182,8 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7026
7182
  perPage: urlParams.perPage,
7027
7183
  sort: urlParams.sort,
7028
7184
  filters,
7029
- joinOperator: urlParams.joinOperator
7185
+ joinOperator: urlParams.joinOperator,
7186
+ ...urlParams.search.trim() ? { search: urlParams.search.trim() } : {}
7030
7187
  };
7031
7188
  return queryTransform ? queryTransform(autoParams) : autoParams;
7032
7189
  }, [
@@ -7038,6 +7195,7 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7038
7195
  placeholderData: keepPreviousData,
7039
7196
  staleTime: 0
7040
7197
  });
7198
+ const tableRows = listQuery.data?.data ?? [];
7041
7199
  const createMutation = router.create.useMutation();
7042
7200
  const updateMutation = router.update.useMutation();
7043
7201
  const deleteMutation = router.delete.useMutation();
@@ -7290,11 +7448,13 @@ function useAutoCrudResource({ router, schema, query: queryTransform, options =
7290
7448
  const canExport = !!(exportFetcher || exportQuery);
7291
7449
  return {
7292
7450
  tableData: {
7293
- data: listQuery.data?.data ?? [],
7451
+ data: tableRows,
7294
7452
  pageCount: listQuery.data?.pageCount ?? 0,
7295
7453
  isLoading: listQuery.isLoading,
7296
7454
  isFetching: listQuery.isFetching
7297
7455
  },
7456
+ schema: resolvedSchema,
7457
+ fields: metadataFields,
7298
7458
  modal,
7299
7459
  mutations: {
7300
7460
  isCreating: createMutation.isPending,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordrhyme/auto-crud",
3
3
  "type": "module",
4
- "version": "1.1.2",
4
+ "version": "1.1.3",
5
5
  "description": "Schema-first CRUD components with auto-generated tables and forms",
6
6
  "author": "wordrhyme",
7
7
  "license": "MIT",
@@ -66,8 +66,8 @@
66
66
  "tailwind-merge": "^3.5.0",
67
67
  "vaul": "^1.1.2",
68
68
  "@pixpilot/formily-shadcn": "1.11.20",
69
- "@pixpilot/shadcn": "1.2.7",
70
- "@pixpilot/shadcn-ui": "1.21.1"
69
+ "@pixpilot/shadcn-ui": "1.21.1",
70
+ "@pixpilot/shadcn": "1.2.7"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@tanstack/react-query": "^5.90.15",
@@ -82,11 +82,11 @@
82
82
  "react-dom": "19.2.4",
83
83
  "tsdown": "^0.15.12",
84
84
  "typescript": "^5.9.3",
85
- "@internal/prettier-config": "0.0.1",
86
- "@internal/tsconfig": "0.1.0",
87
85
  "@internal/eslint-config": "0.3.0",
88
- "@internal/vitest-config": "0.1.0",
89
- "@internal/tsdown-config": "0.1.0"
86
+ "@internal/tsconfig": "0.1.0",
87
+ "@internal/tsdown-config": "0.1.0",
88
+ "@internal/prettier-config": "0.0.1",
89
+ "@internal/vitest-config": "0.1.0"
90
90
  },
91
91
  "prettier": "@internal/prettier-config",
92
92
  "scripts": {