@wordrhyme/auto-crud 1.1.7 → 1.1.8

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
@@ -5232,6 +5232,73 @@ function createEditFormSchema(schema, options) {
5232
5232
  });
5233
5233
  }
5234
5234
 
5235
+ //#endregion
5236
+ //#region src/lib/registries.ts
5237
+ function createRegistry(label) {
5238
+ const items = /* @__PURE__ */ new Map();
5239
+ const listeners = /* @__PURE__ */ new Set();
5240
+ let notifyQueued = false;
5241
+ const notify = () => {
5242
+ if (notifyQueued) return;
5243
+ notifyQueued = true;
5244
+ queueMicrotask(() => {
5245
+ notifyQueued = false;
5246
+ listeners.forEach((listener) => listener());
5247
+ });
5248
+ };
5249
+ return {
5250
+ register(name, value) {
5251
+ const current = items.get(name);
5252
+ if (current === value) return;
5253
+ if (current !== void 0) {
5254
+ console.warn(`[AutoCrud] ${label} "${name}" is already registered.`);
5255
+ return;
5256
+ }
5257
+ items.set(name, value);
5258
+ notify();
5259
+ },
5260
+ unregister(name) {
5261
+ if (!items.delete(name)) return;
5262
+ notify();
5263
+ },
5264
+ get(name) {
5265
+ return items.get(name);
5266
+ },
5267
+ all() {
5268
+ return Object.fromEntries(items);
5269
+ },
5270
+ subscribe(listener) {
5271
+ listeners.add(listener);
5272
+ return () => {
5273
+ listeners.delete(listener);
5274
+ };
5275
+ }
5276
+ };
5277
+ }
5278
+ const formComponents = createRegistry("form component");
5279
+ const dataSources = createRegistry("data source");
5280
+ function normalizeDataSourceConfig(config) {
5281
+ if (!config) return void 0;
5282
+ if (typeof config === "string") return {
5283
+ key: config,
5284
+ dependsOn: [],
5285
+ resetOnChange: false
5286
+ };
5287
+ return {
5288
+ key: config.key,
5289
+ dependsOn: config.dependsOn ?? [],
5290
+ resetOnChange: config.resetOnChange ?? false
5291
+ };
5292
+ }
5293
+ function normalizeOptions(result) {
5294
+ const options = Array.isArray(result) ? result : result?.options;
5295
+ if (!options) return [];
5296
+ return options.map((option) => ({
5297
+ ...option,
5298
+ value: String(option.value)
5299
+ }));
5300
+ }
5301
+
5235
5302
  //#endregion
5236
5303
  //#region src/components/auto-crud/auto-form.tsx
5237
5304
  const COMBOBOX_LIST_CLASS = "[&_[cmdk-list]]:max-h-[360px] [&_[cmdk-list]]:overflow-x-hidden [&_[cmdk-list]]:overflow-y-auto";
@@ -5266,6 +5333,104 @@ function AutoCrudMultiCombobox({ options = [],...props }) {
5266
5333
  options
5267
5334
  });
5268
5335
  }
5336
+ const defaultFieldComponents = {
5337
+ Combobox: {
5338
+ component: FormilyCombobox,
5339
+ decorator: "FormItem"
5340
+ },
5341
+ MultiCombobox: {
5342
+ component: FormilyMultiCombobox,
5343
+ decorator: "FormItem"
5344
+ },
5345
+ Switch: {
5346
+ component: FormilySwitch,
5347
+ decorator: "FormItem"
5348
+ }
5349
+ };
5350
+ function useRegistryVersion(subscribe) {
5351
+ const [version, setVersion] = (0, react.useState)(0);
5352
+ (0, react.useEffect)(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
5353
+ return version;
5354
+ }
5355
+ function isDataSourceConfig(value) {
5356
+ if (typeof value === "string") return value.length > 0;
5357
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
5358
+ return typeof value.key === "string";
5359
+ }
5360
+ function collectDataSourceConfigs(schema, result = {}) {
5361
+ const properties = schema.properties;
5362
+ if (!properties) return result;
5363
+ for (const [key, property] of Object.entries(properties)) {
5364
+ const customDataSource = property["x-data-source"];
5365
+ const schemaDataSource = property.dataSource;
5366
+ const dataSourceConfig = isDataSourceConfig(customDataSource) ? customDataSource : isDataSourceConfig(schemaDataSource) ? schemaDataSource : void 0;
5367
+ if (dataSourceConfig) result[key] = dataSourceConfig;
5368
+ collectDataSourceConfigs(property, result);
5369
+ }
5370
+ return result;
5371
+ }
5372
+ function useFormDataSources(form, schema) {
5373
+ (0, react.useEffect)(() => {
5374
+ const sourceEntries = Object.entries(collectDataSourceConfigs(schema)).map(([fieldName, config]) => {
5375
+ const normalized = normalizeDataSourceConfig(config);
5376
+ return normalized ? [fieldName, normalized] : void 0;
5377
+ }).filter(Boolean);
5378
+ if (sourceEntries.length === 0) return;
5379
+ let active = true;
5380
+ const effectId = Symbol("autoCrudDataSources");
5381
+ const loadVersions = /* @__PURE__ */ new Map();
5382
+ const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
5383
+ const loadFieldOptions = async (fieldName, source) => {
5384
+ const version = (loadVersions.get(fieldName) ?? 0) + 1;
5385
+ loadVersions.set(fieldName, version);
5386
+ const loader = dataSources.get(source.key);
5387
+ if (!loader) {
5388
+ form.setFieldState(fieldName, (state) => {
5389
+ state.dataSource = [];
5390
+ });
5391
+ return;
5392
+ }
5393
+ try {
5394
+ const options = normalizeOptions(await loader({
5395
+ field: fieldName,
5396
+ values: Object.fromEntries(source.dependsOn.map((dependency) => [dependency, form.getValuesIn(dependency)])),
5397
+ signal: controller?.signal
5398
+ }));
5399
+ if (!active || loadVersions.get(fieldName) !== version) return;
5400
+ form.setFieldState(fieldName, (state) => {
5401
+ state.dataSource = options;
5402
+ });
5403
+ } catch (error) {
5404
+ if (!active || controller?.signal.aborted) return;
5405
+ console.warn(`[AutoCrud] Failed to load data source "${source.key}".`, error);
5406
+ form.setFieldState(fieldName, (state) => {
5407
+ state.dataSource = [];
5408
+ });
5409
+ }
5410
+ };
5411
+ for (const [fieldName, source] of sourceEntries) loadFieldOptions(fieldName, source);
5412
+ form.addEffects(effectId, () => {
5413
+ new Set(sourceEntries.flatMap(([, source]) => source.dependsOn)).forEach((dependency) => {
5414
+ (0, __formily_core.onFieldValueChange)(dependency, () => {
5415
+ sourceEntries.forEach(([fieldName, source]) => {
5416
+ if (!source.dependsOn.includes(dependency)) return;
5417
+ if (source.resetOnChange) form.setValuesIn(fieldName, void 0);
5418
+ loadFieldOptions(fieldName, source);
5419
+ });
5420
+ });
5421
+ });
5422
+ });
5423
+ return () => {
5424
+ active = false;
5425
+ controller?.abort();
5426
+ form.removeEffects(effectId);
5427
+ };
5428
+ }, [
5429
+ useRegistryVersion(dataSources.subscribe),
5430
+ form,
5431
+ schema
5432
+ ]);
5433
+ }
5269
5434
  function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
5270
5435
  const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({ initialValues }), [JSON.stringify(initialValues)]);
5271
5436
  const formSchema = (0, react.useMemo)(() => createEditFormSchema(zodSchema, {
@@ -5281,6 +5446,11 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
5281
5446
  labelAlign,
5282
5447
  labelWidth
5283
5448
  ]);
5449
+ const fieldComponents = (0, react.useMemo)(() => ({ fields: {
5450
+ ...defaultFieldComponents,
5451
+ ...formComponents.all()
5452
+ } }), [useRegistryVersion(formComponents.subscribe)]);
5453
+ useFormDataSources(form, formSchema);
5284
5454
  const handleSubmit = async () => {
5285
5455
  await form.validate();
5286
5456
  if (form.valid) await onSubmit(form.values);
@@ -5290,20 +5460,7 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
5290
5460
  form,
5291
5461
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_formily_shadcn.JsonSchemaField, {
5292
5462
  schema: formSchema,
5293
- components: { fields: {
5294
- Combobox: {
5295
- component: FormilyCombobox,
5296
- decorator: "FormItem"
5297
- },
5298
- MultiCombobox: {
5299
- component: FormilyMultiCombobox,
5300
- decorator: "FormItem"
5301
- },
5302
- Switch: {
5303
- component: FormilySwitch,
5304
- decorator: "FormItem"
5305
- }
5306
- } }
5463
+ components: fieldComponents
5307
5464
  }), showSubmitButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5308
5465
  className: "flex justify-end gap-2 mt-6",
5309
5466
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
@@ -6117,6 +6274,7 @@ function mergeFieldConfig(base, override) {
6117
6274
  ...base,
6118
6275
  ...override,
6119
6276
  enum: override?.enum ?? base?.enum,
6277
+ dataSource: override?.dataSource ?? base?.dataSource,
6120
6278
  table: mergeFieldPart(base?.table, override?.table),
6121
6279
  filter: mergeFieldPart(base?.filter, override?.filter),
6122
6280
  form: mergeFieldPart(base?.form, override?.form)
@@ -6225,7 +6383,8 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
6225
6383
  "x-hidden": true
6226
6384
  };
6227
6385
  if (fields) for (const [key, config] of Object.entries(fields)) {
6228
- const fieldOptions = normalizeFieldOptions(config.enum);
6386
+ const fieldOptions = normalizeFieldOptions((config.form && typeof config.form === "object" ? config.form : void 0)?.enum) ?? normalizeFieldOptions(config.enum);
6387
+ const fieldDataSource = fieldOptions || !config.dataSource ? void 0 : normalizeDataSourceConfig(config.dataSource);
6229
6388
  if (config.label) result[key] = {
6230
6389
  ...result[key],
6231
6390
  title: config.label
@@ -6238,6 +6397,10 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
6238
6397
  ...result[key],
6239
6398
  enum: fieldOptions
6240
6399
  };
6400
+ if (fieldDataSource) result[key] = {
6401
+ ...result[key],
6402
+ "x-data-source": config.dataSource
6403
+ };
6241
6404
  if (config.form === false) result[key] = {
6242
6405
  ...result[key],
6243
6406
  "x-hidden": true
@@ -8104,6 +8267,7 @@ exports.createMemoryDataSource = createMemoryDataSource;
8104
8267
  exports.createSelectColumn = createSelectColumn;
8105
8268
  exports.createTRPCDataSource = createTRPCDataSource;
8106
8269
  exports.createTableSchema = createTableSchema;
8270
+ exports.dataSources = dataSources;
8107
8271
  exports.dataToCSV = dataToCSV;
8108
8272
  exports.deDE = deDE;
8109
8273
  exports.downloadCSVTemplate = downloadCSVTemplate;
@@ -8111,6 +8275,7 @@ exports.enUS = enUS;
8111
8275
  exports.esES = esES;
8112
8276
  exports.exportAllToCSV = exportAllToCSV;
8113
8277
  exports.exportTableToCSV = exportTableToCSV;
8278
+ exports.formComponents = formComponents;
8114
8279
  exports.formatDate = formatDate;
8115
8280
  exports.frFR = frFR;
8116
8281
  exports.generateCSVTemplate = generateCSVTemplate;
@@ -8119,6 +8284,8 @@ exports.humanize = humanize;
8119
8284
  exports.jaJP = jaJP;
8120
8285
  exports.koKR = koKR;
8121
8286
  exports.noopToastAdapter = noopToastAdapter;
8287
+ exports.normalizeDataSourceConfig = normalizeDataSourceConfig;
8288
+ exports.normalizeOptions = normalizeOptions;
8122
8289
  exports.parseAsArrayOf = parseAsArrayOf;
8123
8290
  exports.parseAsInteger = parseAsInteger;
8124
8291
  exports.parseAsString = parseAsString;
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_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";
@@ -362,7 +362,7 @@ declare function AutoTableActionBar<TData>({
362
362
  enableDelete,
363
363
  extraActions,
364
364
  actions
365
- }: AutoTableActionBarProps<TData>): react_jsx_runtime2.JSX.Element;
365
+ }: AutoTableActionBarProps<TData>): react_jsx_runtime3.JSX.Element;
366
366
  //#endregion
367
367
  //#region src/lib/schema-bridge/types.d.ts
368
368
  /**
@@ -530,7 +530,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
530
530
  showDefaultExport,
531
531
  onSelectedCountChange,
532
532
  getSelectedRows
533
- }: AutoTableProps<T>): react_jsx_runtime2.JSX.Element;
533
+ }: AutoTableProps<T>): react_jsx_runtime3.JSX.Element;
534
534
  //#endregion
535
535
  //#region src/i18n/locale.d.ts
536
536
  /**
@@ -622,6 +622,60 @@ type LocaleProp = string | DeepPartial<AutoCrudLocale>;
622
622
  */
623
623
  declare function resolveLocale(localeProp?: LocaleProp): AutoCrudLocale;
624
624
  //#endregion
625
+ //#region src/lib/registries.d.ts
626
+ type AutoCrudFormComponentConfig = {
627
+ component: React$1.ComponentType<any>;
628
+ decorator?: string | React$1.ComponentType<any>;
629
+ [key: string]: unknown;
630
+ };
631
+ type AutoCrudOption = {
632
+ value: string;
633
+ label: string;
634
+ searchText?: string | string[];
635
+ keywords?: string[];
636
+ count?: number;
637
+ disabled?: boolean;
638
+ };
639
+ type AutoCrudDataSourceContext = {
640
+ field: string;
641
+ search?: string;
642
+ values?: Record<string, unknown>;
643
+ signal?: AbortSignal;
644
+ };
645
+ type AutoCrudDataSourceLoader = (context: AutoCrudDataSourceContext) => Promise<AutoCrudOption[] | {
646
+ options?: AutoCrudOption[];
647
+ }> | AutoCrudOption[] | {
648
+ options?: AutoCrudOption[];
649
+ };
650
+ type AutoCrudDataSourceConfig = string | {
651
+ key: string;
652
+ dependsOn?: string[];
653
+ resetOnChange?: boolean;
654
+ };
655
+ type RegistryListener = () => void;
656
+ declare const formComponents: {
657
+ register(name: string, value: AutoCrudFormComponentConfig): void;
658
+ unregister(name: string): void;
659
+ get(name: string): AutoCrudFormComponentConfig | undefined;
660
+ all(): Record<string, AutoCrudFormComponentConfig>;
661
+ subscribe(listener: RegistryListener): () => void;
662
+ };
663
+ declare const dataSources: {
664
+ register(name: string, value: AutoCrudDataSourceLoader): void;
665
+ unregister(name: string): void;
666
+ get(name: string): AutoCrudDataSourceLoader | undefined;
667
+ all(): Record<string, AutoCrudDataSourceLoader>;
668
+ subscribe(listener: RegistryListener): () => void;
669
+ };
670
+ declare function normalizeDataSourceConfig(config: AutoCrudDataSourceConfig | undefined): {
671
+ key: string;
672
+ dependsOn: string[];
673
+ resetOnChange: boolean;
674
+ } | undefined;
675
+ declare function normalizeOptions(result: AutoCrudOption[] | {
676
+ options?: AutoCrudOption[];
677
+ } | undefined): AutoCrudOption[];
678
+ //#endregion
625
679
  //#region src/components/auto-crud/auto-crud-table.d.ts
626
680
  /**
627
681
  * 筛选器独立配置
@@ -664,6 +718,8 @@ interface Field {
664
718
  label?: string;
665
719
  /** 字段级静态选项(表单、筛选、展示共用) */
666
720
  enum?: FieldOption[];
721
+ /** 字段级动态选项源(表单、筛选、展示共用) */
722
+ dataSource?: AutoCrudDataSourceConfig;
667
723
  /** 是否隐藏(表格和表单都隐藏) */
668
724
  hidden?: boolean;
669
725
  /** 是否参与 AutoCrud 全局搜索 */
@@ -880,7 +936,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
880
936
  toolbarActions,
881
937
  locale: localeProp,
882
938
  onCreate
883
- }: AutoCrudTableProps<TSchema>): react_jsx_runtime2.JSX.Element;
939
+ }: AutoCrudTableProps<TSchema>): react_jsx_runtime3.JSX.Element;
884
940
  //#endregion
885
941
  //#region src/components/auto-crud/auto-form.d.ts
886
942
  interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
@@ -912,7 +968,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
912
968
  labelAlign,
913
969
  labelWidth,
914
970
  showSubmitButton
915
- }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime2.JSX.Element;
971
+ }: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime3.JSX.Element;
916
972
  declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
917
973
  ref?: React.Ref<AutoFormRef>;
918
974
  }) => ReturnType<typeof AutoFormInner>;
@@ -1126,12 +1182,12 @@ declare const filterItemSchema: z.ZodObject<{
1126
1182
  variant: z.ZodEnum<{
1127
1183
  number: "number";
1128
1184
  boolean: "boolean";
1129
- text: "text";
1130
- range: "range";
1131
1185
  date: "date";
1132
- dateRange: "dateRange";
1186
+ text: "text";
1133
1187
  select: "select";
1134
1188
  multiSelect: "multiSelect";
1189
+ dateRange: "dateRange";
1190
+ range: "range";
1135
1191
  }>;
1136
1192
  operator: z.ZodEnum<{
1137
1193
  iLike: "iLike";
@@ -1214,7 +1270,7 @@ declare function AutoTableSimpleFilters<TData>({
1214
1270
  filters: externalFilters,
1215
1271
  onFiltersChange,
1216
1272
  leading
1217
- }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime2.JSX.Element | null;
1273
+ }: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime3.JSX.Element | null;
1218
1274
  //#endregion
1219
1275
  //#region src/components/auto-crud/form-modal.d.ts
1220
1276
  type ModalVariant = "dialog" | "sheet";
@@ -1256,7 +1312,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
1256
1312
  labelAlign,
1257
1313
  labelWidth,
1258
1314
  className
1259
- }: CrudFormModalProps<T>): react_jsx_runtime2.JSX.Element;
1315
+ }: CrudFormModalProps<T>): react_jsx_runtime3.JSX.Element;
1260
1316
  //#endregion
1261
1317
  //#region src/components/auto-crud/import-dialog.d.ts
1262
1318
  interface ImportDialogProps {
@@ -1278,7 +1334,7 @@ declare function ImportDialog({
1278
1334
  columns,
1279
1335
  title,
1280
1336
  locale
1281
- }: ImportDialogProps): react_jsx_runtime2.JSX.Element;
1337
+ }: ImportDialogProps): react_jsx_runtime3.JSX.Element;
1282
1338
  //#endregion
1283
1339
  //#region src/components/auto-crud/export-dialog.d.ts
1284
1340
  type ExportMode = "selected" | "filtered";
@@ -1298,7 +1354,7 @@ declare function ExportDialog({
1298
1354
  selectedCount,
1299
1355
  onExport,
1300
1356
  canExportFiltered
1301
- }: ExportDialogProps): react_jsx_runtime2.JSX.Element;
1357
+ }: ExportDialogProps): react_jsx_runtime3.JSX.Element;
1302
1358
  //#endregion
1303
1359
  //#region src/components/data-table/data-table.d.ts
1304
1360
  interface DataTableProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1311,7 +1367,7 @@ declare function DataTable<TData>({
1311
1367
  children,
1312
1368
  className,
1313
1369
  ...props
1314
- }: DataTableProps<TData>): react_jsx_runtime2.JSX.Element;
1370
+ }: DataTableProps<TData>): react_jsx_runtime3.JSX.Element;
1315
1371
  //#endregion
1316
1372
  //#region src/components/data-table/data-table-advanced-toolbar.d.ts
1317
1373
  interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1322,7 +1378,7 @@ declare function DataTableAdvancedToolbar<TData>({
1322
1378
  children,
1323
1379
  className,
1324
1380
  ...props
1325
- }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1381
+ }: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1326
1382
  //#endregion
1327
1383
  //#region src/components/data-table/data-table-column-header.d.ts
1328
1384
  interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
@@ -1334,7 +1390,7 @@ declare function DataTableColumnHeader<TData, TValue>({
1334
1390
  label,
1335
1391
  className,
1336
1392
  ...props
1337
- }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1393
+ }: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1338
1394
  //#endregion
1339
1395
  //#region src/components/data-table/data-table-faceted-filter.d.ts
1340
1396
  interface DataTableFacetedFilterProps<TData, TValue> {
@@ -1348,7 +1404,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
1348
1404
  title,
1349
1405
  options,
1350
1406
  multiple
1351
- }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
1407
+ }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
1352
1408
  //#endregion
1353
1409
  //#region src/components/data-table/data-table-pagination.d.ts
1354
1410
  interface DataTablePaginationProps<TData> extends React.ComponentProps<"div"> {
@@ -1360,7 +1416,7 @@ declare function DataTablePagination<TData>({
1360
1416
  pageSizeOptions,
1361
1417
  className,
1362
1418
  ...props
1363
- }: DataTablePaginationProps<TData>): react_jsx_runtime2.JSX.Element;
1419
+ }: DataTablePaginationProps<TData>): react_jsx_runtime3.JSX.Element;
1364
1420
  //#endregion
1365
1421
  //#region src/components/data-table/data-table-toolbar.d.ts
1366
1422
  interface DataTableToolbarProps<TData> extends React$1.ComponentProps<"div"> {
@@ -1371,7 +1427,7 @@ declare function DataTableToolbar<TData>({
1371
1427
  children,
1372
1428
  className,
1373
1429
  ...props
1374
- }: DataTableToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
1430
+ }: DataTableToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
1375
1431
  //#endregion
1376
1432
  //#region src/components/data-table/data-table-view-options.d.ts
1377
1433
  interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
@@ -1382,7 +1438,7 @@ declare function DataTableViewOptions<TData>({
1382
1438
  table,
1383
1439
  disabled,
1384
1440
  ...props
1385
- }: DataTableViewOptionsProps<TData>): react_jsx_runtime2.JSX.Element;
1441
+ }: DataTableViewOptionsProps<TData>): react_jsx_runtime3.JSX.Element;
1386
1442
  //#endregion
1387
1443
  //#region src/components/ui/multi-combobox.d.ts
1388
1444
  interface MultiComboboxOption {
@@ -1404,7 +1460,7 @@ interface MultiComboboxTriggerRenderProps {
1404
1460
  disabled?: boolean;
1405
1461
  readOnly?: boolean;
1406
1462
  }
1407
- interface MultiComboboxProps extends Omit<ComponentProps<typeof Command>, 'value' | 'onChange' | 'onValueChange'> {
1463
+ interface MultiComboboxProps extends Omit<ComponentProps<typeof Command>, 'value' | 'defaultValue' | 'onChange' | 'onValueChange'> {
1408
1464
  value?: string[];
1409
1465
  defaultValue?: string[];
1410
1466
  onChange?: (value: string[]) => void;
@@ -1759,4 +1815,4 @@ declare function exportAllToCSV<T extends Record<string, unknown>>(data: T[], op
1759
1815
  */
1760
1816
  declare function downloadCSVTemplate(headers: string[], filename?: string): void;
1761
1817
  //#endregion
1762
- export { type ActionItem, type ActionsColumnConfig, type AutoCrudLocale, AutoCrudTable, type AutoCrudTableProps, AutoForm, 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, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, 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, SchemaAdapter, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
1818
+ export { type ActionItem, type ActionsColumnConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceLoader, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, AutoCrudTable, type AutoCrudTableProps, AutoForm, 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, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, 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, SchemaAdapter, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, 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, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
package/dist/index.d.ts CHANGED
@@ -622,6 +622,60 @@ type LocaleProp = string | DeepPartial<AutoCrudLocale>;
622
622
  */
623
623
  declare function resolveLocale(localeProp?: LocaleProp): AutoCrudLocale;
624
624
  //#endregion
625
+ //#region src/lib/registries.d.ts
626
+ type AutoCrudFormComponentConfig = {
627
+ component: React$1.ComponentType<any>;
628
+ decorator?: string | React$1.ComponentType<any>;
629
+ [key: string]: unknown;
630
+ };
631
+ type AutoCrudOption = {
632
+ value: string;
633
+ label: string;
634
+ searchText?: string | string[];
635
+ keywords?: string[];
636
+ count?: number;
637
+ disabled?: boolean;
638
+ };
639
+ type AutoCrudDataSourceContext = {
640
+ field: string;
641
+ search?: string;
642
+ values?: Record<string, unknown>;
643
+ signal?: AbortSignal;
644
+ };
645
+ type AutoCrudDataSourceLoader = (context: AutoCrudDataSourceContext) => Promise<AutoCrudOption[] | {
646
+ options?: AutoCrudOption[];
647
+ }> | AutoCrudOption[] | {
648
+ options?: AutoCrudOption[];
649
+ };
650
+ type AutoCrudDataSourceConfig = string | {
651
+ key: string;
652
+ dependsOn?: string[];
653
+ resetOnChange?: boolean;
654
+ };
655
+ type RegistryListener = () => void;
656
+ declare const formComponents: {
657
+ register(name: string, value: AutoCrudFormComponentConfig): void;
658
+ unregister(name: string): void;
659
+ get(name: string): AutoCrudFormComponentConfig | undefined;
660
+ all(): Record<string, AutoCrudFormComponentConfig>;
661
+ subscribe(listener: RegistryListener): () => void;
662
+ };
663
+ declare const dataSources: {
664
+ register(name: string, value: AutoCrudDataSourceLoader): void;
665
+ unregister(name: string): void;
666
+ get(name: string): AutoCrudDataSourceLoader | undefined;
667
+ all(): Record<string, AutoCrudDataSourceLoader>;
668
+ subscribe(listener: RegistryListener): () => void;
669
+ };
670
+ declare function normalizeDataSourceConfig(config: AutoCrudDataSourceConfig | undefined): {
671
+ key: string;
672
+ dependsOn: string[];
673
+ resetOnChange: boolean;
674
+ } | undefined;
675
+ declare function normalizeOptions(result: AutoCrudOption[] | {
676
+ options?: AutoCrudOption[];
677
+ } | undefined): AutoCrudOption[];
678
+ //#endregion
625
679
  //#region src/components/auto-crud/auto-crud-table.d.ts
626
680
  /**
627
681
  * 筛选器独立配置
@@ -664,6 +718,8 @@ interface Field {
664
718
  label?: string;
665
719
  /** 字段级静态选项(表单、筛选、展示共用) */
666
720
  enum?: FieldOption[];
721
+ /** 字段级动态选项源(表单、筛选、展示共用) */
722
+ dataSource?: AutoCrudDataSourceConfig;
667
723
  /** 是否隐藏(表格和表单都隐藏) */
668
724
  hidden?: boolean;
669
725
  /** 是否参与 AutoCrud 全局搜索 */
@@ -1126,12 +1182,12 @@ declare const filterItemSchema: z.ZodObject<{
1126
1182
  variant: z.ZodEnum<{
1127
1183
  number: "number";
1128
1184
  boolean: "boolean";
1129
- text: "text";
1130
- range: "range";
1131
1185
  date: "date";
1132
- dateRange: "dateRange";
1186
+ text: "text";
1133
1187
  select: "select";
1134
1188
  multiSelect: "multiSelect";
1189
+ dateRange: "dateRange";
1190
+ range: "range";
1135
1191
  }>;
1136
1192
  operator: z.ZodEnum<{
1137
1193
  iLike: "iLike";
@@ -1404,7 +1460,7 @@ interface MultiComboboxTriggerRenderProps {
1404
1460
  disabled?: boolean;
1405
1461
  readOnly?: boolean;
1406
1462
  }
1407
- interface MultiComboboxProps extends Omit<ComponentProps<typeof Command>, 'value' | 'onChange' | 'onValueChange'> {
1463
+ interface MultiComboboxProps extends Omit<ComponentProps<typeof Command>, 'value' | 'defaultValue' | 'onChange' | 'onValueChange'> {
1408
1464
  value?: string[];
1409
1465
  defaultValue?: string[];
1410
1466
  onChange?: (value: string[]) => void;
@@ -1759,4 +1815,4 @@ declare function exportAllToCSV<T extends Record<string, unknown>>(data: T[], op
1759
1815
  */
1760
1816
  declare function downloadCSVTemplate(headers: string[], filename?: string): void;
1761
1817
  //#endregion
1762
- export { type ActionItem, type ActionsColumnConfig, type AutoCrudLocale, AutoCrudTable, type AutoCrudTableProps, AutoForm, 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, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, 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, SchemaAdapter, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
1818
+ export { type ActionItem, type ActionsColumnConfig, type AutoCrudDataSourceConfig, type AutoCrudDataSourceContext, type AutoCrudDataSourceLoader, type AutoCrudFormComponentConfig, type AutoCrudLocale, type AutoCrudOption, AutoCrudTable, type AutoCrudTableProps, AutoForm, 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, CrudFormModal, type CrudHooks, type CrudOperationPermissions, type CrudPermissions, type DataSource, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableRowAction, DataTableToolbar, DataTableViewOptions, 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, SchemaAdapter, type SimpleFieldConfig, type SimpleFieldsConfig, type ToastAdapter, type ToolbarActionItem, type ToolbarBuiltinActionItem, type ToolbarCustomActionItem, type UnifiedField, type UnifiedSchema, type UrlStateOptions, type UseAutoCrudResourceOptions, type UseAutoCrudResourceParams, type UseAutoCrudResourceReturn, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, 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, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef } from "react";
2
+ import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef, useState } 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
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";
@@ -15,7 +15,7 @@ import { Slot } from "@radix-ui/react-slot";
15
15
  import * as ReactDOM from "react-dom";
16
16
  import { useDirection } from "@radix-ui/react-direction";
17
17
  import { z } from "zod";
18
- import { createForm } from "@formily/core";
18
+ import { createForm, onFieldValueChange } from "@formily/core";
19
19
  import { Form, JsonSchemaField } from "@pixpilot/formily-shadcn";
20
20
  import { connect, mapProps } from "@formily/react";
21
21
  import { toast } from "sonner";
@@ -5190,6 +5190,73 @@ function createEditFormSchema(schema, options) {
5190
5190
  });
5191
5191
  }
5192
5192
 
5193
+ //#endregion
5194
+ //#region src/lib/registries.ts
5195
+ function createRegistry(label) {
5196
+ const items = /* @__PURE__ */ new Map();
5197
+ const listeners = /* @__PURE__ */ new Set();
5198
+ let notifyQueued = false;
5199
+ const notify = () => {
5200
+ if (notifyQueued) return;
5201
+ notifyQueued = true;
5202
+ queueMicrotask(() => {
5203
+ notifyQueued = false;
5204
+ listeners.forEach((listener) => listener());
5205
+ });
5206
+ };
5207
+ return {
5208
+ register(name, value) {
5209
+ const current = items.get(name);
5210
+ if (current === value) return;
5211
+ if (current !== void 0) {
5212
+ console.warn(`[AutoCrud] ${label} "${name}" is already registered.`);
5213
+ return;
5214
+ }
5215
+ items.set(name, value);
5216
+ notify();
5217
+ },
5218
+ unregister(name) {
5219
+ if (!items.delete(name)) return;
5220
+ notify();
5221
+ },
5222
+ get(name) {
5223
+ return items.get(name);
5224
+ },
5225
+ all() {
5226
+ return Object.fromEntries(items);
5227
+ },
5228
+ subscribe(listener) {
5229
+ listeners.add(listener);
5230
+ return () => {
5231
+ listeners.delete(listener);
5232
+ };
5233
+ }
5234
+ };
5235
+ }
5236
+ const formComponents = createRegistry("form component");
5237
+ const dataSources = createRegistry("data source");
5238
+ function normalizeDataSourceConfig(config) {
5239
+ if (!config) return void 0;
5240
+ if (typeof config === "string") return {
5241
+ key: config,
5242
+ dependsOn: [],
5243
+ resetOnChange: false
5244
+ };
5245
+ return {
5246
+ key: config.key,
5247
+ dependsOn: config.dependsOn ?? [],
5248
+ resetOnChange: config.resetOnChange ?? false
5249
+ };
5250
+ }
5251
+ function normalizeOptions(result) {
5252
+ const options = Array.isArray(result) ? result : result?.options;
5253
+ if (!options) return [];
5254
+ return options.map((option) => ({
5255
+ ...option,
5256
+ value: String(option.value)
5257
+ }));
5258
+ }
5259
+
5193
5260
  //#endregion
5194
5261
  //#region src/components/auto-crud/auto-form.tsx
5195
5262
  const COMBOBOX_LIST_CLASS = "[&_[cmdk-list]]:max-h-[360px] [&_[cmdk-list]]:overflow-x-hidden [&_[cmdk-list]]:overflow-y-auto";
@@ -5224,6 +5291,104 @@ function AutoCrudMultiCombobox({ options = [],...props }) {
5224
5291
  options
5225
5292
  });
5226
5293
  }
5294
+ const defaultFieldComponents = {
5295
+ Combobox: {
5296
+ component: FormilyCombobox,
5297
+ decorator: "FormItem"
5298
+ },
5299
+ MultiCombobox: {
5300
+ component: FormilyMultiCombobox,
5301
+ decorator: "FormItem"
5302
+ },
5303
+ Switch: {
5304
+ component: FormilySwitch,
5305
+ decorator: "FormItem"
5306
+ }
5307
+ };
5308
+ function useRegistryVersion(subscribe) {
5309
+ const [version, setVersion] = useState(0);
5310
+ useEffect(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
5311
+ return version;
5312
+ }
5313
+ function isDataSourceConfig(value) {
5314
+ if (typeof value === "string") return value.length > 0;
5315
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
5316
+ return typeof value.key === "string";
5317
+ }
5318
+ function collectDataSourceConfigs(schema, result = {}) {
5319
+ const properties = schema.properties;
5320
+ if (!properties) return result;
5321
+ for (const [key, property] of Object.entries(properties)) {
5322
+ const customDataSource = property["x-data-source"];
5323
+ const schemaDataSource = property.dataSource;
5324
+ const dataSourceConfig = isDataSourceConfig(customDataSource) ? customDataSource : isDataSourceConfig(schemaDataSource) ? schemaDataSource : void 0;
5325
+ if (dataSourceConfig) result[key] = dataSourceConfig;
5326
+ collectDataSourceConfigs(property, result);
5327
+ }
5328
+ return result;
5329
+ }
5330
+ function useFormDataSources(form, schema) {
5331
+ useEffect(() => {
5332
+ const sourceEntries = Object.entries(collectDataSourceConfigs(schema)).map(([fieldName, config]) => {
5333
+ const normalized = normalizeDataSourceConfig(config);
5334
+ return normalized ? [fieldName, normalized] : void 0;
5335
+ }).filter(Boolean);
5336
+ if (sourceEntries.length === 0) return;
5337
+ let active = true;
5338
+ const effectId = Symbol("autoCrudDataSources");
5339
+ const loadVersions = /* @__PURE__ */ new Map();
5340
+ const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
5341
+ const loadFieldOptions = async (fieldName, source) => {
5342
+ const version = (loadVersions.get(fieldName) ?? 0) + 1;
5343
+ loadVersions.set(fieldName, version);
5344
+ const loader = dataSources.get(source.key);
5345
+ if (!loader) {
5346
+ form.setFieldState(fieldName, (state) => {
5347
+ state.dataSource = [];
5348
+ });
5349
+ return;
5350
+ }
5351
+ try {
5352
+ const options = normalizeOptions(await loader({
5353
+ field: fieldName,
5354
+ values: Object.fromEntries(source.dependsOn.map((dependency) => [dependency, form.getValuesIn(dependency)])),
5355
+ signal: controller?.signal
5356
+ }));
5357
+ if (!active || loadVersions.get(fieldName) !== version) return;
5358
+ form.setFieldState(fieldName, (state) => {
5359
+ state.dataSource = options;
5360
+ });
5361
+ } catch (error) {
5362
+ if (!active || controller?.signal.aborted) return;
5363
+ console.warn(`[AutoCrud] Failed to load data source "${source.key}".`, error);
5364
+ form.setFieldState(fieldName, (state) => {
5365
+ state.dataSource = [];
5366
+ });
5367
+ }
5368
+ };
5369
+ for (const [fieldName, source] of sourceEntries) loadFieldOptions(fieldName, source);
5370
+ form.addEffects(effectId, () => {
5371
+ new Set(sourceEntries.flatMap(([, source]) => source.dependsOn)).forEach((dependency) => {
5372
+ onFieldValueChange(dependency, () => {
5373
+ sourceEntries.forEach(([fieldName, source]) => {
5374
+ if (!source.dependsOn.includes(dependency)) return;
5375
+ if (source.resetOnChange) form.setValuesIn(fieldName, void 0);
5376
+ loadFieldOptions(fieldName, source);
5377
+ });
5378
+ });
5379
+ });
5380
+ });
5381
+ return () => {
5382
+ active = false;
5383
+ controller?.abort();
5384
+ form.removeEffects(effectId);
5385
+ };
5386
+ }, [
5387
+ useRegistryVersion(dataSources.subscribe),
5388
+ form,
5389
+ schema
5390
+ ]);
5391
+ }
5227
5392
  function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
5228
5393
  const form = useMemo(() => createForm({ initialValues }), [JSON.stringify(initialValues)]);
5229
5394
  const formSchema = useMemo(() => createEditFormSchema(zodSchema, {
@@ -5239,6 +5404,11 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
5239
5404
  labelAlign,
5240
5405
  labelWidth
5241
5406
  ]);
5407
+ const fieldComponents = useMemo(() => ({ fields: {
5408
+ ...defaultFieldComponents,
5409
+ ...formComponents.all()
5410
+ } }), [useRegistryVersion(formComponents.subscribe)]);
5411
+ useFormDataSources(form, formSchema);
5242
5412
  const handleSubmit = async () => {
5243
5413
  await form.validate();
5244
5414
  if (form.valid) await onSubmit(form.values);
@@ -5248,20 +5418,7 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
5248
5418
  form,
5249
5419
  children: [/* @__PURE__ */ jsx(JsonSchemaField, {
5250
5420
  schema: formSchema,
5251
- components: { fields: {
5252
- Combobox: {
5253
- component: FormilyCombobox,
5254
- decorator: "FormItem"
5255
- },
5256
- MultiCombobox: {
5257
- component: FormilyMultiCombobox,
5258
- decorator: "FormItem"
5259
- },
5260
- Switch: {
5261
- component: FormilySwitch,
5262
- decorator: "FormItem"
5263
- }
5264
- } }
5421
+ components: fieldComponents
5265
5422
  }), showSubmitButton && /* @__PURE__ */ jsx("div", {
5266
5423
  className: "flex justify-end gap-2 mt-6",
5267
5424
  children: /* @__PURE__ */ jsx(Button, {
@@ -6075,6 +6232,7 @@ function mergeFieldConfig(base, override) {
6075
6232
  ...base,
6076
6233
  ...override,
6077
6234
  enum: override?.enum ?? base?.enum,
6235
+ dataSource: override?.dataSource ?? base?.dataSource,
6078
6236
  table: mergeFieldPart(base?.table, override?.table),
6079
6237
  filter: mergeFieldPart(base?.filter, override?.filter),
6080
6238
  form: mergeFieldPart(base?.form, override?.form)
@@ -6183,7 +6341,8 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
6183
6341
  "x-hidden": true
6184
6342
  };
6185
6343
  if (fields) for (const [key, config] of Object.entries(fields)) {
6186
- const fieldOptions = normalizeFieldOptions(config.enum);
6344
+ const fieldOptions = normalizeFieldOptions((config.form && typeof config.form === "object" ? config.form : void 0)?.enum) ?? normalizeFieldOptions(config.enum);
6345
+ const fieldDataSource = fieldOptions || !config.dataSource ? void 0 : normalizeDataSourceConfig(config.dataSource);
6187
6346
  if (config.label) result[key] = {
6188
6347
  ...result[key],
6189
6348
  title: config.label
@@ -6196,6 +6355,10 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
6196
6355
  ...result[key],
6197
6356
  enum: fieldOptions
6198
6357
  };
6358
+ if (fieldDataSource) result[key] = {
6359
+ ...result[key],
6360
+ "x-data-source": config.dataSource
6361
+ };
6199
6362
  if (config.form === false) result[key] = {
6200
6363
  ...result[key],
6201
6364
  "x-hidden": true
@@ -8036,4 +8199,4 @@ function createMemoryDataSource(initialData = []) {
8036
8199
  }
8037
8200
 
8038
8201
  //#endregion
8039
- export { AutoCrudTable, AutoForm, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, CrudFormModal, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableToolbar, DataTableViewOptions, ExportDialog, ImportDialog, MultiCombobox, SchemaAdapter, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, dataToCSV, deDE, downloadCSVTemplate, enUS, esES, exportAllToCSV, exportTableToCSV, formatDate, frFR, generateCSVTemplate, getUrlParams, humanize, jaJP, koKR, noopToastAdapter, parseAsArrayOf, parseAsInteger, parseAsString, parseAsStringEnum, parseCSV, parseImportFile, parseJSON, parseZodField, resolveLocale, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
8202
+ export { AutoCrudTable, AutoForm, AutoTable, AutoTableActionBar, AutoTableSimpleFilters, CrudFormModal, DataTable, DataTableAdvancedToolbar, DataTableColumnHeader, DataTableFacetedFilter, DataTablePagination, DataTableToolbar, DataTableViewOptions, ExportDialog, ImportDialog, MultiCombobox, SchemaAdapter, cn, coerceRowValues, createActionsColumn, createEditFormSchema, createFormSchema, createMemoryDataSource, createSelectColumn, createTRPCDataSource, createTableSchema, 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, setSearchParams, useAutoCrudResource, useDataTable, useQueryState, useQueryStates, useReadableFilters, useUrlState, useUrlStates, zhCN };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordrhyme/auto-crud",
3
3
  "type": "module",
4
- "version": "1.1.7",
4
+ "version": "1.1.8",
5
5
  "description": "Schema-first CRUD components with auto-generated tables and forms",
6
6
  "author": "wordrhyme",
7
7
  "license": "MIT",
@@ -65,8 +65,8 @@
65
65
  "nanoid": "^5.1.6",
66
66
  "tailwind-merge": "^3.5.0",
67
67
  "vaul": "^1.1.2",
68
- "@pixpilot/shadcn": "1.2.7",
69
68
  "@pixpilot/formily-shadcn": "1.11.20",
69
+ "@pixpilot/shadcn": "1.2.7",
70
70
  "@pixpilot/shadcn-ui": "1.21.1"
71
71
  },
72
72
  "devDependencies": {
@@ -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
85
  "@internal/eslint-config": "0.3.0",
86
+ "@internal/prettier-config": "0.0.1",
87
87
  "@internal/tsconfig": "0.1.0",
88
- "@internal/vitest-config": "0.1.0",
89
- "@internal/tsdown-config": "0.1.0"
88
+ "@internal/tsdown-config": "0.1.0",
89
+ "@internal/vitest-config": "0.1.0"
90
90
  },
91
91
  "prettier": "@internal/prettier-config",
92
92
  "scripts": {