@wordrhyme/auto-crud 1.1.8 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +113 -44
- package/dist/index.d.cts +24 -25
- package/dist/index.d.ts +24 -25
- package/dist/index.js +113 -44
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -5235,65 +5235,59 @@ function createEditFormSchema(schema, options) {
|
|
|
5235
5235
|
//#endregion
|
|
5236
5236
|
//#region src/lib/registries.ts
|
|
5237
5237
|
function createRegistry(label) {
|
|
5238
|
-
const
|
|
5238
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5239
5239
|
const listeners = /* @__PURE__ */ new Set();
|
|
5240
|
-
let notifyQueued = false;
|
|
5241
5240
|
const notify = () => {
|
|
5242
|
-
if (notifyQueued) return;
|
|
5243
|
-
notifyQueued = true;
|
|
5244
5241
|
queueMicrotask(() => {
|
|
5245
|
-
|
|
5246
|
-
listeners.forEach((listener) => listener());
|
|
5242
|
+
for (const listener of listeners) listener();
|
|
5247
5243
|
});
|
|
5248
5244
|
};
|
|
5249
5245
|
return {
|
|
5250
5246
|
register(name, value) {
|
|
5251
|
-
|
|
5252
|
-
if (current === value) return;
|
|
5253
|
-
if (current !== void 0) {
|
|
5247
|
+
if (entries.has(name)) {
|
|
5254
5248
|
console.warn(`[AutoCrud] ${label} "${name}" is already registered.`);
|
|
5255
5249
|
return;
|
|
5256
5250
|
}
|
|
5257
|
-
|
|
5251
|
+
entries.set(name, value);
|
|
5258
5252
|
notify();
|
|
5259
5253
|
},
|
|
5260
5254
|
unregister(name) {
|
|
5261
|
-
if (!
|
|
5255
|
+
if (!entries.delete(name)) return;
|
|
5262
5256
|
notify();
|
|
5263
5257
|
},
|
|
5264
5258
|
get(name) {
|
|
5265
|
-
return
|
|
5259
|
+
return entries.get(name);
|
|
5266
5260
|
},
|
|
5267
5261
|
all() {
|
|
5268
|
-
return Object.fromEntries(
|
|
5262
|
+
return Object.fromEntries(entries);
|
|
5269
5263
|
},
|
|
5270
5264
|
subscribe(listener) {
|
|
5271
5265
|
listeners.add(listener);
|
|
5272
|
-
return () =>
|
|
5273
|
-
listeners.delete(listener);
|
|
5274
|
-
};
|
|
5266
|
+
return () => listeners.delete(listener);
|
|
5275
5267
|
}
|
|
5276
5268
|
};
|
|
5277
5269
|
}
|
|
5278
5270
|
const formComponents = createRegistry("form component");
|
|
5279
5271
|
const dataSources = createRegistry("data source");
|
|
5280
5272
|
function normalizeDataSourceConfig(config) {
|
|
5281
|
-
if (
|
|
5282
|
-
if (typeof config === "string") return {
|
|
5273
|
+
if (typeof config === "string") return config.length > 0 ? {
|
|
5283
5274
|
key: config,
|
|
5284
5275
|
dependsOn: [],
|
|
5285
5276
|
resetOnChange: false
|
|
5286
|
-
};
|
|
5277
|
+
} : void 0;
|
|
5278
|
+
if (!config?.key) return void 0;
|
|
5287
5279
|
return {
|
|
5288
5280
|
key: config.key,
|
|
5289
|
-
dependsOn: config.dependsOn
|
|
5290
|
-
resetOnChange: config.resetOnChange
|
|
5281
|
+
dependsOn: Array.isArray(config.dependsOn) ? config.dependsOn : [],
|
|
5282
|
+
resetOnChange: config.resetOnChange === true
|
|
5291
5283
|
};
|
|
5292
5284
|
}
|
|
5293
5285
|
function normalizeOptions(result) {
|
|
5294
5286
|
const options = Array.isArray(result) ? result : result?.options;
|
|
5295
|
-
if (!options) return [];
|
|
5296
|
-
return options.
|
|
5287
|
+
if (!Array.isArray(options)) return [];
|
|
5288
|
+
return options.filter((option) => {
|
|
5289
|
+
return typeof option === "object" && option !== null && typeof option.value === "string" && typeof option.label === "string";
|
|
5290
|
+
}).map((option) => ({
|
|
5297
5291
|
...option,
|
|
5298
5292
|
value: String(option.value)
|
|
5299
5293
|
}));
|
|
@@ -5347,7 +5341,7 @@ const defaultFieldComponents = {
|
|
|
5347
5341
|
decorator: "FormItem"
|
|
5348
5342
|
}
|
|
5349
5343
|
};
|
|
5350
|
-
function useRegistryVersion(subscribe) {
|
|
5344
|
+
function useRegistryVersion$1(subscribe) {
|
|
5351
5345
|
const [version, setVersion] = (0, react.useState)(0);
|
|
5352
5346
|
(0, react.useEffect)(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
|
|
5353
5347
|
return version;
|
|
@@ -5359,13 +5353,15 @@ function isDataSourceConfig(value) {
|
|
|
5359
5353
|
}
|
|
5360
5354
|
function collectDataSourceConfigs(schema, result = {}) {
|
|
5361
5355
|
const properties = schema.properties;
|
|
5362
|
-
if (!properties) return result;
|
|
5356
|
+
if (!properties || typeof properties !== "object") return result;
|
|
5363
5357
|
for (const [key, property] of Object.entries(properties)) {
|
|
5364
|
-
|
|
5365
|
-
const
|
|
5358
|
+
if (!property || typeof property !== "object" || Array.isArray(property)) continue;
|
|
5359
|
+
const record = property;
|
|
5360
|
+
const customDataSource = record["x-data-source"];
|
|
5361
|
+
const schemaDataSource = record.dataSource;
|
|
5366
5362
|
const dataSourceConfig = isDataSourceConfig(customDataSource) ? customDataSource : isDataSourceConfig(schemaDataSource) ? schemaDataSource : void 0;
|
|
5367
5363
|
if (dataSourceConfig) result[key] = dataSourceConfig;
|
|
5368
|
-
collectDataSourceConfigs(
|
|
5364
|
+
collectDataSourceConfigs(record, result);
|
|
5369
5365
|
}
|
|
5370
5366
|
return result;
|
|
5371
5367
|
}
|
|
@@ -5374,7 +5370,7 @@ function useFormDataSources(form, schema) {
|
|
|
5374
5370
|
const sourceEntries = Object.entries(collectDataSourceConfigs(schema)).map(([fieldName, config]) => {
|
|
5375
5371
|
const normalized = normalizeDataSourceConfig(config);
|
|
5376
5372
|
return normalized ? [fieldName, normalized] : void 0;
|
|
5377
|
-
}).filter(
|
|
5373
|
+
}).filter((entry) => entry !== void 0);
|
|
5378
5374
|
if (sourceEntries.length === 0) return;
|
|
5379
5375
|
let active = true;
|
|
5380
5376
|
const effectId = Symbol("autoCrudDataSources");
|
|
@@ -5410,14 +5406,12 @@ function useFormDataSources(form, schema) {
|
|
|
5410
5406
|
};
|
|
5411
5407
|
for (const [fieldName, source] of sourceEntries) loadFieldOptions(fieldName, source);
|
|
5412
5408
|
form.addEffects(effectId, () => {
|
|
5413
|
-
new Set(sourceEntries.flatMap(([, source]) => source.dependsOn)).
|
|
5414
|
-
(
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
});
|
|
5420
|
-
});
|
|
5409
|
+
for (const dependency of new Set(sourceEntries.flatMap(([, source]) => source.dependsOn))) (0, __formily_core.onFieldValueChange)(dependency, () => {
|
|
5410
|
+
for (const [fieldName, source] of sourceEntries) {
|
|
5411
|
+
if (!source.dependsOn.includes(dependency)) continue;
|
|
5412
|
+
if (source.resetOnChange) form.setValuesIn(fieldName, void 0);
|
|
5413
|
+
loadFieldOptions(fieldName, source);
|
|
5414
|
+
}
|
|
5421
5415
|
});
|
|
5422
5416
|
});
|
|
5423
5417
|
return () => {
|
|
@@ -5426,9 +5420,9 @@ function useFormDataSources(form, schema) {
|
|
|
5426
5420
|
form.removeEffects(effectId);
|
|
5427
5421
|
};
|
|
5428
5422
|
}, [
|
|
5429
|
-
useRegistryVersion(dataSources.subscribe),
|
|
5430
5423
|
form,
|
|
5431
|
-
schema
|
|
5424
|
+
schema,
|
|
5425
|
+
useRegistryVersion$1(dataSources.subscribe)
|
|
5432
5426
|
]);
|
|
5433
5427
|
}
|
|
5434
5428
|
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
|
|
@@ -5449,7 +5443,7 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
|
|
|
5449
5443
|
const fieldComponents = (0, react.useMemo)(() => ({ fields: {
|
|
5450
5444
|
...defaultFieldComponents,
|
|
5451
5445
|
...formComponents.all()
|
|
5452
|
-
} }), [useRegistryVersion(formComponents.subscribe)]);
|
|
5446
|
+
} }), [useRegistryVersion$1(formComponents.subscribe)]);
|
|
5453
5447
|
useFormDataSources(form, formSchema);
|
|
5454
5448
|
const handleSubmit = async () => {
|
|
5455
5449
|
await form.validate();
|
|
@@ -6307,6 +6301,69 @@ function toBatchOptions(options) {
|
|
|
6307
6301
|
value
|
|
6308
6302
|
}));
|
|
6309
6303
|
}
|
|
6304
|
+
function getFilterDataSource(config) {
|
|
6305
|
+
if (config.filter && typeof config.filter === "object") return config.filter.dataSource ?? config.dataSource;
|
|
6306
|
+
return config.dataSource;
|
|
6307
|
+
}
|
|
6308
|
+
function shouldLoadDynamicFilterOptions(config) {
|
|
6309
|
+
if (config.filter === false) return false;
|
|
6310
|
+
if (normalizeFieldOptions(config.enum)) return false;
|
|
6311
|
+
if (config.filter && typeof config.filter === "object") {
|
|
6312
|
+
if (config.filter.enabled === false || config.filter.hidden === true) return false;
|
|
6313
|
+
if (normalizeFieldOptions(config.filter.options)) return false;
|
|
6314
|
+
}
|
|
6315
|
+
return normalizeDataSourceConfig(getFilterDataSource(config)) !== void 0;
|
|
6316
|
+
}
|
|
6317
|
+
function useRegistryVersion(subscribe) {
|
|
6318
|
+
const [version, setVersion] = react.useState(0);
|
|
6319
|
+
react.useEffect(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
|
|
6320
|
+
return version;
|
|
6321
|
+
}
|
|
6322
|
+
function useDynamicFilterOptions(fields) {
|
|
6323
|
+
const registryVersion = useRegistryVersion(dataSources.subscribe);
|
|
6324
|
+
const [optionsByField, setOptionsByField] = react.useState({});
|
|
6325
|
+
const sourceEntries = react.useMemo(() => {
|
|
6326
|
+
if (!fields) return [];
|
|
6327
|
+
return Object.entries(fields).flatMap(([field, config]) => {
|
|
6328
|
+
if (!shouldLoadDynamicFilterOptions(config)) return [];
|
|
6329
|
+
const source = normalizeDataSourceConfig(getFilterDataSource(config));
|
|
6330
|
+
return source ? [{
|
|
6331
|
+
field,
|
|
6332
|
+
source
|
|
6333
|
+
}] : [];
|
|
6334
|
+
});
|
|
6335
|
+
}, [fields]);
|
|
6336
|
+
react.useEffect(() => {
|
|
6337
|
+
if (sourceEntries.length === 0) {
|
|
6338
|
+
setOptionsByField({});
|
|
6339
|
+
return;
|
|
6340
|
+
}
|
|
6341
|
+
let active = true;
|
|
6342
|
+
const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
|
|
6343
|
+
Promise.all(sourceEntries.map(async ({ field, source }) => {
|
|
6344
|
+
const loader = dataSources.get(source.key);
|
|
6345
|
+
if (!loader) return [field, []];
|
|
6346
|
+
try {
|
|
6347
|
+
return [field, normalizeOptions(await loader({
|
|
6348
|
+
field,
|
|
6349
|
+
values: {},
|
|
6350
|
+
signal: controller?.signal
|
|
6351
|
+
}))];
|
|
6352
|
+
} catch (error) {
|
|
6353
|
+
if (!controller?.signal.aborted) console.warn(`[AutoCrud] Failed to load filter data source "${source.key}".`, error);
|
|
6354
|
+
return [field, []];
|
|
6355
|
+
}
|
|
6356
|
+
})).then((entries) => {
|
|
6357
|
+
if (!active) return;
|
|
6358
|
+
setOptionsByField(Object.fromEntries(entries));
|
|
6359
|
+
});
|
|
6360
|
+
return () => {
|
|
6361
|
+
active = false;
|
|
6362
|
+
controller?.abort();
|
|
6363
|
+
};
|
|
6364
|
+
}, [sourceEntries, registryVersion]);
|
|
6365
|
+
return optionsByField;
|
|
6366
|
+
}
|
|
6310
6367
|
function getOptionLabel(value, options) {
|
|
6311
6368
|
const stringValue = String(value);
|
|
6312
6369
|
return options?.find((option) => option.value === stringValue)?.label ?? stringValue;
|
|
@@ -6315,15 +6372,21 @@ function getOptionLabel(value, options) {
|
|
|
6315
6372
|
* 从统一配置生成表格 overrides
|
|
6316
6373
|
* 当 filter 配置存在时,合并到 meta 中(不影响列隐藏)
|
|
6317
6374
|
*/
|
|
6318
|
-
function buildTableOverrides(fields, legacyOverrides) {
|
|
6375
|
+
function buildTableOverrides(fields, legacyOverrides, dynamicFilterOptions) {
|
|
6319
6376
|
const result = { ...legacyOverrides };
|
|
6320
6377
|
if (fields) for (const [key, config] of Object.entries(fields)) {
|
|
6321
|
-
const
|
|
6378
|
+
const fieldOptions = normalizeFieldOptions(config.enum);
|
|
6379
|
+
const tableOptions = toTableOptions(fieldOptions);
|
|
6380
|
+
const dynamicOptions = !fieldOptions ? toTableOptions(normalizeFieldOptions(dynamicFilterOptions?.[key])) : void 0;
|
|
6322
6381
|
const tableMeta = config.table !== false && typeof config.table === "object" ? config.table.meta : void 0;
|
|
6323
6382
|
const fieldEnumMeta = tableOptions ? {
|
|
6324
6383
|
options: tableOptions,
|
|
6325
6384
|
variant: "multiSelect"
|
|
6326
6385
|
} : void 0;
|
|
6386
|
+
const fieldDataSourceMeta = dynamicOptions ? {
|
|
6387
|
+
options: dynamicOptions,
|
|
6388
|
+
variant: "multiSelect"
|
|
6389
|
+
} : void 0;
|
|
6327
6390
|
let filterMeta;
|
|
6328
6391
|
if (config.filter && typeof config.filter === "object") {
|
|
6329
6392
|
if (config.filter.enabled !== false && config.filter.hidden !== true) {
|
|
@@ -6341,11 +6404,12 @@ function buildTableOverrides(fields, legacyOverrides) {
|
|
|
6341
6404
|
enableColumnFilter: false
|
|
6342
6405
|
};
|
|
6343
6406
|
}
|
|
6344
|
-
if (fieldEnumMeta || tableMeta || filterMeta) result[key] = {
|
|
6407
|
+
if (fieldEnumMeta || fieldDataSourceMeta || tableMeta || filterMeta) result[key] = {
|
|
6345
6408
|
...result[key],
|
|
6346
6409
|
meta: {
|
|
6347
6410
|
...result[key]?.meta ?? {},
|
|
6348
6411
|
...fieldEnumMeta ?? {},
|
|
6412
|
+
...fieldDataSourceMeta ?? {},
|
|
6349
6413
|
...tableMeta ?? {},
|
|
6350
6414
|
...filterMeta ?? {}
|
|
6351
6415
|
}
|
|
@@ -6658,6 +6722,7 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
6658
6722
|
const [selectedCount, setSelectedCount] = react.useState(0);
|
|
6659
6723
|
const [exporting, setExporting] = react.useState(false);
|
|
6660
6724
|
const getSelectedRowsRef = react.useRef(null);
|
|
6725
|
+
const dynamicFilterOptions = useDynamicFilterOptions(resolvedFields);
|
|
6661
6726
|
const importColumns = react.useMemo(() => {
|
|
6662
6727
|
const shape = resolvedSchema.shape;
|
|
6663
6728
|
const denySet = new Set(denyFields ?? []);
|
|
@@ -6694,7 +6759,11 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
6694
6759
|
setExporting(false);
|
|
6695
6760
|
}
|
|
6696
6761
|
}, [selectedCount, handleExport]);
|
|
6697
|
-
const tableOverrides = react.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides), [
|
|
6762
|
+
const tableOverrides = react.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides, dynamicFilterOptions), [
|
|
6763
|
+
resolvedFields,
|
|
6764
|
+
tableConfig?.overrides,
|
|
6765
|
+
dynamicFilterOptions
|
|
6766
|
+
]);
|
|
6698
6767
|
const formOverrides = react.useMemo(() => buildFormOverrides(resolvedFields, formConfig?.overrides, denyFields), [
|
|
6699
6768
|
resolvedFields,
|
|
6700
6769
|
formConfig?.overrides,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime2 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>):
|
|
365
|
+
}: AutoTableActionBarProps<TData>): react_jsx_runtime2.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>):
|
|
533
|
+
}: AutoTableProps<T>): react_jsx_runtime2.JSX.Element;
|
|
534
534
|
//#endregion
|
|
535
535
|
//#region src/i18n/locale.d.ts
|
|
536
536
|
/**
|
|
@@ -642,11 +642,10 @@ type AutoCrudDataSourceContext = {
|
|
|
642
642
|
values?: Record<string, unknown>;
|
|
643
643
|
signal?: AbortSignal;
|
|
644
644
|
};
|
|
645
|
-
type
|
|
646
|
-
options?: AutoCrudOption[];
|
|
647
|
-
}> | AutoCrudOption[] | {
|
|
645
|
+
type AutoCrudDataSourceResult = AutoCrudOption[] | {
|
|
648
646
|
options?: AutoCrudOption[];
|
|
649
647
|
};
|
|
648
|
+
type AutoCrudDataSourceLoader = (context: AutoCrudDataSourceContext) => AutoCrudDataSourceResult | Promise<AutoCrudDataSourceResult>;
|
|
650
649
|
type AutoCrudDataSourceConfig = string | {
|
|
651
650
|
key: string;
|
|
652
651
|
dependsOn?: string[];
|
|
@@ -672,9 +671,7 @@ declare function normalizeDataSourceConfig(config: AutoCrudDataSourceConfig | un
|
|
|
672
671
|
dependsOn: string[];
|
|
673
672
|
resetOnChange: boolean;
|
|
674
673
|
} | undefined;
|
|
675
|
-
declare function normalizeOptions(result: AutoCrudOption[]
|
|
676
|
-
options?: AutoCrudOption[];
|
|
677
|
-
} | undefined): AutoCrudOption[];
|
|
674
|
+
declare function normalizeOptions(result: AutoCrudDataSourceResult | undefined): AutoCrudOption[];
|
|
678
675
|
//#endregion
|
|
679
676
|
//#region src/components/auto-crud/auto-crud-table.d.ts
|
|
680
677
|
/**
|
|
@@ -688,6 +685,8 @@ interface FilterConfig {
|
|
|
688
685
|
variant?: 'text' | 'number' | 'range' | 'date' | 'dateRange' | 'boolean' | 'select' | 'multiSelect';
|
|
689
686
|
/** select/multiSelect 的选项列表 */
|
|
690
687
|
options?: FieldOption[];
|
|
688
|
+
/** select/multiSelect 的动态选项源 */
|
|
689
|
+
dataSource?: AutoCrudDataSourceConfig;
|
|
691
690
|
/** range 的最小/最大值 */
|
|
692
691
|
range?: [number, number];
|
|
693
692
|
/** number 的单位 */
|
|
@@ -936,7 +935,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
|
|
|
936
935
|
toolbarActions,
|
|
937
936
|
locale: localeProp,
|
|
938
937
|
onCreate
|
|
939
|
-
}: AutoCrudTableProps<TSchema>):
|
|
938
|
+
}: AutoCrudTableProps<TSchema>): react_jsx_runtime2.JSX.Element;
|
|
940
939
|
//#endregion
|
|
941
940
|
//#region src/components/auto-crud/auto-form.d.ts
|
|
942
941
|
interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
|
|
@@ -968,7 +967,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
968
967
|
labelAlign,
|
|
969
968
|
labelWidth,
|
|
970
969
|
showSubmitButton
|
|
971
|
-
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>):
|
|
970
|
+
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime2.JSX.Element;
|
|
972
971
|
declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
|
|
973
972
|
ref?: React.Ref<AutoFormRef>;
|
|
974
973
|
}) => ReturnType<typeof AutoFormInner>;
|
|
@@ -1182,12 +1181,12 @@ declare const filterItemSchema: z.ZodObject<{
|
|
|
1182
1181
|
variant: z.ZodEnum<{
|
|
1183
1182
|
number: "number";
|
|
1184
1183
|
boolean: "boolean";
|
|
1185
|
-
date: "date";
|
|
1186
1184
|
text: "text";
|
|
1185
|
+
range: "range";
|
|
1186
|
+
date: "date";
|
|
1187
|
+
dateRange: "dateRange";
|
|
1187
1188
|
select: "select";
|
|
1188
1189
|
multiSelect: "multiSelect";
|
|
1189
|
-
dateRange: "dateRange";
|
|
1190
|
-
range: "range";
|
|
1191
1190
|
}>;
|
|
1192
1191
|
operator: z.ZodEnum<{
|
|
1193
1192
|
iLike: "iLike";
|
|
@@ -1270,7 +1269,7 @@ declare function AutoTableSimpleFilters<TData>({
|
|
|
1270
1269
|
filters: externalFilters,
|
|
1271
1270
|
onFiltersChange,
|
|
1272
1271
|
leading
|
|
1273
|
-
}: AutoTableSimpleFiltersProps<TData>):
|
|
1272
|
+
}: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime2.JSX.Element | null;
|
|
1274
1273
|
//#endregion
|
|
1275
1274
|
//#region src/components/auto-crud/form-modal.d.ts
|
|
1276
1275
|
type ModalVariant = "dialog" | "sheet";
|
|
@@ -1312,7 +1311,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1312
1311
|
labelAlign,
|
|
1313
1312
|
labelWidth,
|
|
1314
1313
|
className
|
|
1315
|
-
}: CrudFormModalProps<T>):
|
|
1314
|
+
}: CrudFormModalProps<T>): react_jsx_runtime2.JSX.Element;
|
|
1316
1315
|
//#endregion
|
|
1317
1316
|
//#region src/components/auto-crud/import-dialog.d.ts
|
|
1318
1317
|
interface ImportDialogProps {
|
|
@@ -1334,7 +1333,7 @@ declare function ImportDialog({
|
|
|
1334
1333
|
columns,
|
|
1335
1334
|
title,
|
|
1336
1335
|
locale
|
|
1337
|
-
}: ImportDialogProps):
|
|
1336
|
+
}: ImportDialogProps): react_jsx_runtime2.JSX.Element;
|
|
1338
1337
|
//#endregion
|
|
1339
1338
|
//#region src/components/auto-crud/export-dialog.d.ts
|
|
1340
1339
|
type ExportMode = "selected" | "filtered";
|
|
@@ -1354,7 +1353,7 @@ declare function ExportDialog({
|
|
|
1354
1353
|
selectedCount,
|
|
1355
1354
|
onExport,
|
|
1356
1355
|
canExportFiltered
|
|
1357
|
-
}: ExportDialogProps):
|
|
1356
|
+
}: ExportDialogProps): react_jsx_runtime2.JSX.Element;
|
|
1358
1357
|
//#endregion
|
|
1359
1358
|
//#region src/components/data-table/data-table.d.ts
|
|
1360
1359
|
interface DataTableProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1367,7 +1366,7 @@ declare function DataTable<TData>({
|
|
|
1367
1366
|
children,
|
|
1368
1367
|
className,
|
|
1369
1368
|
...props
|
|
1370
|
-
}: DataTableProps<TData>):
|
|
1369
|
+
}: DataTableProps<TData>): react_jsx_runtime2.JSX.Element;
|
|
1371
1370
|
//#endregion
|
|
1372
1371
|
//#region src/components/data-table/data-table-advanced-toolbar.d.ts
|
|
1373
1372
|
interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1378,7 +1377,7 @@ declare function DataTableAdvancedToolbar<TData>({
|
|
|
1378
1377
|
children,
|
|
1379
1378
|
className,
|
|
1380
1379
|
...props
|
|
1381
|
-
}: DataTableAdvancedToolbarProps<TData>):
|
|
1380
|
+
}: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
|
|
1382
1381
|
//#endregion
|
|
1383
1382
|
//#region src/components/data-table/data-table-column-header.d.ts
|
|
1384
1383
|
interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
|
|
@@ -1390,7 +1389,7 @@ declare function DataTableColumnHeader<TData, TValue>({
|
|
|
1390
1389
|
label,
|
|
1391
1390
|
className,
|
|
1392
1391
|
...props
|
|
1393
|
-
}: DataTableColumnHeaderProps<TData, TValue>):
|
|
1392
|
+
}: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
|
|
1394
1393
|
//#endregion
|
|
1395
1394
|
//#region src/components/data-table/data-table-faceted-filter.d.ts
|
|
1396
1395
|
interface DataTableFacetedFilterProps<TData, TValue> {
|
|
@@ -1404,7 +1403,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
|
|
|
1404
1403
|
title,
|
|
1405
1404
|
options,
|
|
1406
1405
|
multiple
|
|
1407
|
-
}: DataTableFacetedFilterProps<TData, TValue>):
|
|
1406
|
+
}: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime2.JSX.Element;
|
|
1408
1407
|
//#endregion
|
|
1409
1408
|
//#region src/components/data-table/data-table-pagination.d.ts
|
|
1410
1409
|
interface DataTablePaginationProps<TData> extends React.ComponentProps<"div"> {
|
|
@@ -1416,7 +1415,7 @@ declare function DataTablePagination<TData>({
|
|
|
1416
1415
|
pageSizeOptions,
|
|
1417
1416
|
className,
|
|
1418
1417
|
...props
|
|
1419
|
-
}: DataTablePaginationProps<TData>):
|
|
1418
|
+
}: DataTablePaginationProps<TData>): react_jsx_runtime2.JSX.Element;
|
|
1420
1419
|
//#endregion
|
|
1421
1420
|
//#region src/components/data-table/data-table-toolbar.d.ts
|
|
1422
1421
|
interface DataTableToolbarProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1427,7 +1426,7 @@ declare function DataTableToolbar<TData>({
|
|
|
1427
1426
|
children,
|
|
1428
1427
|
className,
|
|
1429
1428
|
...props
|
|
1430
|
-
}: DataTableToolbarProps<TData>):
|
|
1429
|
+
}: DataTableToolbarProps<TData>): react_jsx_runtime2.JSX.Element;
|
|
1431
1430
|
//#endregion
|
|
1432
1431
|
//#region src/components/data-table/data-table-view-options.d.ts
|
|
1433
1432
|
interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
|
|
@@ -1438,7 +1437,7 @@ declare function DataTableViewOptions<TData>({
|
|
|
1438
1437
|
table,
|
|
1439
1438
|
disabled,
|
|
1440
1439
|
...props
|
|
1441
|
-
}: DataTableViewOptionsProps<TData>):
|
|
1440
|
+
}: DataTableViewOptionsProps<TData>): react_jsx_runtime2.JSX.Element;
|
|
1442
1441
|
//#endregion
|
|
1443
1442
|
//#region src/components/ui/multi-combobox.d.ts
|
|
1444
1443
|
interface MultiComboboxOption {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as _tanstack_react_table0 from "@tanstack/react-table";
|
|
|
4
4
|
import { Column, ColumnDef, ColumnSort, Row, RowData, Table, TableOptions, TableState } from "@tanstack/react-table";
|
|
5
5
|
import { Command, DropdownMenuTrigger, PopoverContent } from "@pixpilot/shadcn";
|
|
6
6
|
import { ClassValue } from "clsx";
|
|
7
|
-
import * as
|
|
7
|
+
import * as react_jsx_runtime3 from "react/jsx-runtime";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { ISchema } from "@formily/json-schema";
|
|
10
10
|
|
|
@@ -362,7 +362,7 @@ declare function AutoTableActionBar<TData>({
|
|
|
362
362
|
enableDelete,
|
|
363
363
|
extraActions,
|
|
364
364
|
actions
|
|
365
|
-
}: AutoTableActionBarProps<TData>):
|
|
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>):
|
|
533
|
+
}: AutoTableProps<T>): react_jsx_runtime3.JSX.Element;
|
|
534
534
|
//#endregion
|
|
535
535
|
//#region src/i18n/locale.d.ts
|
|
536
536
|
/**
|
|
@@ -642,11 +642,10 @@ type AutoCrudDataSourceContext = {
|
|
|
642
642
|
values?: Record<string, unknown>;
|
|
643
643
|
signal?: AbortSignal;
|
|
644
644
|
};
|
|
645
|
-
type
|
|
646
|
-
options?: AutoCrudOption[];
|
|
647
|
-
}> | AutoCrudOption[] | {
|
|
645
|
+
type AutoCrudDataSourceResult = AutoCrudOption[] | {
|
|
648
646
|
options?: AutoCrudOption[];
|
|
649
647
|
};
|
|
648
|
+
type AutoCrudDataSourceLoader = (context: AutoCrudDataSourceContext) => AutoCrudDataSourceResult | Promise<AutoCrudDataSourceResult>;
|
|
650
649
|
type AutoCrudDataSourceConfig = string | {
|
|
651
650
|
key: string;
|
|
652
651
|
dependsOn?: string[];
|
|
@@ -672,9 +671,7 @@ declare function normalizeDataSourceConfig(config: AutoCrudDataSourceConfig | un
|
|
|
672
671
|
dependsOn: string[];
|
|
673
672
|
resetOnChange: boolean;
|
|
674
673
|
} | undefined;
|
|
675
|
-
declare function normalizeOptions(result: AutoCrudOption[]
|
|
676
|
-
options?: AutoCrudOption[];
|
|
677
|
-
} | undefined): AutoCrudOption[];
|
|
674
|
+
declare function normalizeOptions(result: AutoCrudDataSourceResult | undefined): AutoCrudOption[];
|
|
678
675
|
//#endregion
|
|
679
676
|
//#region src/components/auto-crud/auto-crud-table.d.ts
|
|
680
677
|
/**
|
|
@@ -688,6 +685,8 @@ interface FilterConfig {
|
|
|
688
685
|
variant?: 'text' | 'number' | 'range' | 'date' | 'dateRange' | 'boolean' | 'select' | 'multiSelect';
|
|
689
686
|
/** select/multiSelect 的选项列表 */
|
|
690
687
|
options?: FieldOption[];
|
|
688
|
+
/** select/multiSelect 的动态选项源 */
|
|
689
|
+
dataSource?: AutoCrudDataSourceConfig;
|
|
691
690
|
/** range 的最小/最大值 */
|
|
692
691
|
range?: [number, number];
|
|
693
692
|
/** number 的单位 */
|
|
@@ -936,7 +935,7 @@ declare function AutoCrudTable<TSchema extends z.ZodObject<z.ZodRawShape>>({
|
|
|
936
935
|
toolbarActions,
|
|
937
936
|
locale: localeProp,
|
|
938
937
|
onCreate
|
|
939
|
-
}: AutoCrudTableProps<TSchema>):
|
|
938
|
+
}: AutoCrudTableProps<TSchema>): react_jsx_runtime3.JSX.Element;
|
|
940
939
|
//#endregion
|
|
941
940
|
//#region src/components/auto-crud/auto-form.d.ts
|
|
942
941
|
interface AutoFormProps<T extends z.ZodObject<z.ZodRawShape>> {
|
|
@@ -968,7 +967,7 @@ declare function AutoFormInner<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
968
967
|
labelAlign,
|
|
969
968
|
labelWidth,
|
|
970
969
|
showSubmitButton
|
|
971
|
-
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>):
|
|
970
|
+
}: AutoFormProps<T>, ref: React.Ref<AutoFormRef>): react_jsx_runtime3.JSX.Element;
|
|
972
971
|
declare const AutoForm: <T extends z.ZodObject<z.ZodRawShape>>(props: AutoFormProps<T> & {
|
|
973
972
|
ref?: React.Ref<AutoFormRef>;
|
|
974
973
|
}) => ReturnType<typeof AutoFormInner>;
|
|
@@ -1182,12 +1181,12 @@ declare const filterItemSchema: z.ZodObject<{
|
|
|
1182
1181
|
variant: z.ZodEnum<{
|
|
1183
1182
|
number: "number";
|
|
1184
1183
|
boolean: "boolean";
|
|
1185
|
-
date: "date";
|
|
1186
1184
|
text: "text";
|
|
1185
|
+
range: "range";
|
|
1186
|
+
date: "date";
|
|
1187
|
+
dateRange: "dateRange";
|
|
1187
1188
|
select: "select";
|
|
1188
1189
|
multiSelect: "multiSelect";
|
|
1189
|
-
dateRange: "dateRange";
|
|
1190
|
-
range: "range";
|
|
1191
1190
|
}>;
|
|
1192
1191
|
operator: z.ZodEnum<{
|
|
1193
1192
|
iLike: "iLike";
|
|
@@ -1270,7 +1269,7 @@ declare function AutoTableSimpleFilters<TData>({
|
|
|
1270
1269
|
filters: externalFilters,
|
|
1271
1270
|
onFiltersChange,
|
|
1272
1271
|
leading
|
|
1273
|
-
}: AutoTableSimpleFiltersProps<TData>):
|
|
1272
|
+
}: AutoTableSimpleFiltersProps<TData>): react_jsx_runtime3.JSX.Element | null;
|
|
1274
1273
|
//#endregion
|
|
1275
1274
|
//#region src/components/auto-crud/form-modal.d.ts
|
|
1276
1275
|
type ModalVariant = "dialog" | "sheet";
|
|
@@ -1312,7 +1311,7 @@ declare function CrudFormModal<T extends z.ZodObject<z.ZodRawShape>>({
|
|
|
1312
1311
|
labelAlign,
|
|
1313
1312
|
labelWidth,
|
|
1314
1313
|
className
|
|
1315
|
-
}: CrudFormModalProps<T>):
|
|
1314
|
+
}: CrudFormModalProps<T>): react_jsx_runtime3.JSX.Element;
|
|
1316
1315
|
//#endregion
|
|
1317
1316
|
//#region src/components/auto-crud/import-dialog.d.ts
|
|
1318
1317
|
interface ImportDialogProps {
|
|
@@ -1334,7 +1333,7 @@ declare function ImportDialog({
|
|
|
1334
1333
|
columns,
|
|
1335
1334
|
title,
|
|
1336
1335
|
locale
|
|
1337
|
-
}: ImportDialogProps):
|
|
1336
|
+
}: ImportDialogProps): react_jsx_runtime3.JSX.Element;
|
|
1338
1337
|
//#endregion
|
|
1339
1338
|
//#region src/components/auto-crud/export-dialog.d.ts
|
|
1340
1339
|
type ExportMode = "selected" | "filtered";
|
|
@@ -1354,7 +1353,7 @@ declare function ExportDialog({
|
|
|
1354
1353
|
selectedCount,
|
|
1355
1354
|
onExport,
|
|
1356
1355
|
canExportFiltered
|
|
1357
|
-
}: ExportDialogProps):
|
|
1356
|
+
}: ExportDialogProps): react_jsx_runtime3.JSX.Element;
|
|
1358
1357
|
//#endregion
|
|
1359
1358
|
//#region src/components/data-table/data-table.d.ts
|
|
1360
1359
|
interface DataTableProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1367,7 +1366,7 @@ declare function DataTable<TData>({
|
|
|
1367
1366
|
children,
|
|
1368
1367
|
className,
|
|
1369
1368
|
...props
|
|
1370
|
-
}: DataTableProps<TData>):
|
|
1369
|
+
}: DataTableProps<TData>): react_jsx_runtime3.JSX.Element;
|
|
1371
1370
|
//#endregion
|
|
1372
1371
|
//#region src/components/data-table/data-table-advanced-toolbar.d.ts
|
|
1373
1372
|
interface DataTableAdvancedToolbarProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1378,7 +1377,7 @@ declare function DataTableAdvancedToolbar<TData>({
|
|
|
1378
1377
|
children,
|
|
1379
1378
|
className,
|
|
1380
1379
|
...props
|
|
1381
|
-
}: DataTableAdvancedToolbarProps<TData>):
|
|
1380
|
+
}: DataTableAdvancedToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
|
|
1382
1381
|
//#endregion
|
|
1383
1382
|
//#region src/components/data-table/data-table-column-header.d.ts
|
|
1384
1383
|
interface DataTableColumnHeaderProps<TData, TValue> extends React.ComponentProps<typeof DropdownMenuTrigger> {
|
|
@@ -1390,7 +1389,7 @@ declare function DataTableColumnHeader<TData, TValue>({
|
|
|
1390
1389
|
label,
|
|
1391
1390
|
className,
|
|
1392
1391
|
...props
|
|
1393
|
-
}: DataTableColumnHeaderProps<TData, TValue>):
|
|
1392
|
+
}: DataTableColumnHeaderProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
|
|
1394
1393
|
//#endregion
|
|
1395
1394
|
//#region src/components/data-table/data-table-faceted-filter.d.ts
|
|
1396
1395
|
interface DataTableFacetedFilterProps<TData, TValue> {
|
|
@@ -1404,7 +1403,7 @@ declare function DataTableFacetedFilter<TData, TValue>({
|
|
|
1404
1403
|
title,
|
|
1405
1404
|
options,
|
|
1406
1405
|
multiple
|
|
1407
|
-
}: DataTableFacetedFilterProps<TData, TValue>):
|
|
1406
|
+
}: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime3.JSX.Element;
|
|
1408
1407
|
//#endregion
|
|
1409
1408
|
//#region src/components/data-table/data-table-pagination.d.ts
|
|
1410
1409
|
interface DataTablePaginationProps<TData> extends React.ComponentProps<"div"> {
|
|
@@ -1416,7 +1415,7 @@ declare function DataTablePagination<TData>({
|
|
|
1416
1415
|
pageSizeOptions,
|
|
1417
1416
|
className,
|
|
1418
1417
|
...props
|
|
1419
|
-
}: DataTablePaginationProps<TData>):
|
|
1418
|
+
}: DataTablePaginationProps<TData>): react_jsx_runtime3.JSX.Element;
|
|
1420
1419
|
//#endregion
|
|
1421
1420
|
//#region src/components/data-table/data-table-toolbar.d.ts
|
|
1422
1421
|
interface DataTableToolbarProps<TData> extends React$1.ComponentProps<"div"> {
|
|
@@ -1427,7 +1426,7 @@ declare function DataTableToolbar<TData>({
|
|
|
1427
1426
|
children,
|
|
1428
1427
|
className,
|
|
1429
1428
|
...props
|
|
1430
|
-
}: DataTableToolbarProps<TData>):
|
|
1429
|
+
}: DataTableToolbarProps<TData>): react_jsx_runtime3.JSX.Element;
|
|
1431
1430
|
//#endregion
|
|
1432
1431
|
//#region src/components/data-table/data-table-view-options.d.ts
|
|
1433
1432
|
interface DataTableViewOptionsProps<TData> extends React$1.ComponentProps<typeof PopoverContent> {
|
|
@@ -1438,7 +1437,7 @@ declare function DataTableViewOptions<TData>({
|
|
|
1438
1437
|
table,
|
|
1439
1438
|
disabled,
|
|
1440
1439
|
...props
|
|
1441
|
-
}: DataTableViewOptionsProps<TData>):
|
|
1440
|
+
}: DataTableViewOptionsProps<TData>): react_jsx_runtime3.JSX.Element;
|
|
1442
1441
|
//#endregion
|
|
1443
1442
|
//#region src/components/ui/multi-combobox.d.ts
|
|
1444
1443
|
interface MultiComboboxOption {
|
package/dist/index.js
CHANGED
|
@@ -5193,65 +5193,59 @@ function createEditFormSchema(schema, options) {
|
|
|
5193
5193
|
//#endregion
|
|
5194
5194
|
//#region src/lib/registries.ts
|
|
5195
5195
|
function createRegistry(label) {
|
|
5196
|
-
const
|
|
5196
|
+
const entries = /* @__PURE__ */ new Map();
|
|
5197
5197
|
const listeners = /* @__PURE__ */ new Set();
|
|
5198
|
-
let notifyQueued = false;
|
|
5199
5198
|
const notify = () => {
|
|
5200
|
-
if (notifyQueued) return;
|
|
5201
|
-
notifyQueued = true;
|
|
5202
5199
|
queueMicrotask(() => {
|
|
5203
|
-
|
|
5204
|
-
listeners.forEach((listener) => listener());
|
|
5200
|
+
for (const listener of listeners) listener();
|
|
5205
5201
|
});
|
|
5206
5202
|
};
|
|
5207
5203
|
return {
|
|
5208
5204
|
register(name, value) {
|
|
5209
|
-
|
|
5210
|
-
if (current === value) return;
|
|
5211
|
-
if (current !== void 0) {
|
|
5205
|
+
if (entries.has(name)) {
|
|
5212
5206
|
console.warn(`[AutoCrud] ${label} "${name}" is already registered.`);
|
|
5213
5207
|
return;
|
|
5214
5208
|
}
|
|
5215
|
-
|
|
5209
|
+
entries.set(name, value);
|
|
5216
5210
|
notify();
|
|
5217
5211
|
},
|
|
5218
5212
|
unregister(name) {
|
|
5219
|
-
if (!
|
|
5213
|
+
if (!entries.delete(name)) return;
|
|
5220
5214
|
notify();
|
|
5221
5215
|
},
|
|
5222
5216
|
get(name) {
|
|
5223
|
-
return
|
|
5217
|
+
return entries.get(name);
|
|
5224
5218
|
},
|
|
5225
5219
|
all() {
|
|
5226
|
-
return Object.fromEntries(
|
|
5220
|
+
return Object.fromEntries(entries);
|
|
5227
5221
|
},
|
|
5228
5222
|
subscribe(listener) {
|
|
5229
5223
|
listeners.add(listener);
|
|
5230
|
-
return () =>
|
|
5231
|
-
listeners.delete(listener);
|
|
5232
|
-
};
|
|
5224
|
+
return () => listeners.delete(listener);
|
|
5233
5225
|
}
|
|
5234
5226
|
};
|
|
5235
5227
|
}
|
|
5236
5228
|
const formComponents = createRegistry("form component");
|
|
5237
5229
|
const dataSources = createRegistry("data source");
|
|
5238
5230
|
function normalizeDataSourceConfig(config) {
|
|
5239
|
-
if (
|
|
5240
|
-
if (typeof config === "string") return {
|
|
5231
|
+
if (typeof config === "string") return config.length > 0 ? {
|
|
5241
5232
|
key: config,
|
|
5242
5233
|
dependsOn: [],
|
|
5243
5234
|
resetOnChange: false
|
|
5244
|
-
};
|
|
5235
|
+
} : void 0;
|
|
5236
|
+
if (!config?.key) return void 0;
|
|
5245
5237
|
return {
|
|
5246
5238
|
key: config.key,
|
|
5247
|
-
dependsOn: config.dependsOn
|
|
5248
|
-
resetOnChange: config.resetOnChange
|
|
5239
|
+
dependsOn: Array.isArray(config.dependsOn) ? config.dependsOn : [],
|
|
5240
|
+
resetOnChange: config.resetOnChange === true
|
|
5249
5241
|
};
|
|
5250
5242
|
}
|
|
5251
5243
|
function normalizeOptions(result) {
|
|
5252
5244
|
const options = Array.isArray(result) ? result : result?.options;
|
|
5253
|
-
if (!options) return [];
|
|
5254
|
-
return options.
|
|
5245
|
+
if (!Array.isArray(options)) return [];
|
|
5246
|
+
return options.filter((option) => {
|
|
5247
|
+
return typeof option === "object" && option !== null && typeof option.value === "string" && typeof option.label === "string";
|
|
5248
|
+
}).map((option) => ({
|
|
5255
5249
|
...option,
|
|
5256
5250
|
value: String(option.value)
|
|
5257
5251
|
}));
|
|
@@ -5305,7 +5299,7 @@ const defaultFieldComponents = {
|
|
|
5305
5299
|
decorator: "FormItem"
|
|
5306
5300
|
}
|
|
5307
5301
|
};
|
|
5308
|
-
function useRegistryVersion(subscribe) {
|
|
5302
|
+
function useRegistryVersion$1(subscribe) {
|
|
5309
5303
|
const [version, setVersion] = useState(0);
|
|
5310
5304
|
useEffect(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
|
|
5311
5305
|
return version;
|
|
@@ -5317,13 +5311,15 @@ function isDataSourceConfig(value) {
|
|
|
5317
5311
|
}
|
|
5318
5312
|
function collectDataSourceConfigs(schema, result = {}) {
|
|
5319
5313
|
const properties = schema.properties;
|
|
5320
|
-
if (!properties) return result;
|
|
5314
|
+
if (!properties || typeof properties !== "object") return result;
|
|
5321
5315
|
for (const [key, property] of Object.entries(properties)) {
|
|
5322
|
-
|
|
5323
|
-
const
|
|
5316
|
+
if (!property || typeof property !== "object" || Array.isArray(property)) continue;
|
|
5317
|
+
const record = property;
|
|
5318
|
+
const customDataSource = record["x-data-source"];
|
|
5319
|
+
const schemaDataSource = record.dataSource;
|
|
5324
5320
|
const dataSourceConfig = isDataSourceConfig(customDataSource) ? customDataSource : isDataSourceConfig(schemaDataSource) ? schemaDataSource : void 0;
|
|
5325
5321
|
if (dataSourceConfig) result[key] = dataSourceConfig;
|
|
5326
|
-
collectDataSourceConfigs(
|
|
5322
|
+
collectDataSourceConfigs(record, result);
|
|
5327
5323
|
}
|
|
5328
5324
|
return result;
|
|
5329
5325
|
}
|
|
@@ -5332,7 +5328,7 @@ function useFormDataSources(form, schema) {
|
|
|
5332
5328
|
const sourceEntries = Object.entries(collectDataSourceConfigs(schema)).map(([fieldName, config]) => {
|
|
5333
5329
|
const normalized = normalizeDataSourceConfig(config);
|
|
5334
5330
|
return normalized ? [fieldName, normalized] : void 0;
|
|
5335
|
-
}).filter(
|
|
5331
|
+
}).filter((entry) => entry !== void 0);
|
|
5336
5332
|
if (sourceEntries.length === 0) return;
|
|
5337
5333
|
let active = true;
|
|
5338
5334
|
const effectId = Symbol("autoCrudDataSources");
|
|
@@ -5368,14 +5364,12 @@ function useFormDataSources(form, schema) {
|
|
|
5368
5364
|
};
|
|
5369
5365
|
for (const [fieldName, source] of sourceEntries) loadFieldOptions(fieldName, source);
|
|
5370
5366
|
form.addEffects(effectId, () => {
|
|
5371
|
-
new Set(sourceEntries.flatMap(([, source]) => source.dependsOn))
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
});
|
|
5378
|
-
});
|
|
5367
|
+
for (const dependency of new Set(sourceEntries.flatMap(([, source]) => source.dependsOn))) onFieldValueChange(dependency, () => {
|
|
5368
|
+
for (const [fieldName, source] of sourceEntries) {
|
|
5369
|
+
if (!source.dependsOn.includes(dependency)) continue;
|
|
5370
|
+
if (source.resetOnChange) form.setValuesIn(fieldName, void 0);
|
|
5371
|
+
loadFieldOptions(fieldName, source);
|
|
5372
|
+
}
|
|
5379
5373
|
});
|
|
5380
5374
|
});
|
|
5381
5375
|
return () => {
|
|
@@ -5384,9 +5378,9 @@ function useFormDataSources(form, schema) {
|
|
|
5384
5378
|
form.removeEffects(effectId);
|
|
5385
5379
|
};
|
|
5386
5380
|
}, [
|
|
5387
|
-
useRegistryVersion(dataSources.subscribe),
|
|
5388
5381
|
form,
|
|
5389
|
-
schema
|
|
5382
|
+
schema,
|
|
5383
|
+
useRegistryVersion$1(dataSources.subscribe)
|
|
5390
5384
|
]);
|
|
5391
5385
|
}
|
|
5392
5386
|
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
|
|
@@ -5407,7 +5401,7 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
|
|
|
5407
5401
|
const fieldComponents = useMemo(() => ({ fields: {
|
|
5408
5402
|
...defaultFieldComponents,
|
|
5409
5403
|
...formComponents.all()
|
|
5410
|
-
} }), [useRegistryVersion(formComponents.subscribe)]);
|
|
5404
|
+
} }), [useRegistryVersion$1(formComponents.subscribe)]);
|
|
5411
5405
|
useFormDataSources(form, formSchema);
|
|
5412
5406
|
const handleSubmit = async () => {
|
|
5413
5407
|
await form.validate();
|
|
@@ -6265,6 +6259,69 @@ function toBatchOptions(options) {
|
|
|
6265
6259
|
value
|
|
6266
6260
|
}));
|
|
6267
6261
|
}
|
|
6262
|
+
function getFilterDataSource(config) {
|
|
6263
|
+
if (config.filter && typeof config.filter === "object") return config.filter.dataSource ?? config.dataSource;
|
|
6264
|
+
return config.dataSource;
|
|
6265
|
+
}
|
|
6266
|
+
function shouldLoadDynamicFilterOptions(config) {
|
|
6267
|
+
if (config.filter === false) return false;
|
|
6268
|
+
if (normalizeFieldOptions(config.enum)) return false;
|
|
6269
|
+
if (config.filter && typeof config.filter === "object") {
|
|
6270
|
+
if (config.filter.enabled === false || config.filter.hidden === true) return false;
|
|
6271
|
+
if (normalizeFieldOptions(config.filter.options)) return false;
|
|
6272
|
+
}
|
|
6273
|
+
return normalizeDataSourceConfig(getFilterDataSource(config)) !== void 0;
|
|
6274
|
+
}
|
|
6275
|
+
function useRegistryVersion(subscribe) {
|
|
6276
|
+
const [version, setVersion] = React.useState(0);
|
|
6277
|
+
React.useEffect(() => subscribe(() => setVersion((current) => current + 1)), [subscribe]);
|
|
6278
|
+
return version;
|
|
6279
|
+
}
|
|
6280
|
+
function useDynamicFilterOptions(fields) {
|
|
6281
|
+
const registryVersion = useRegistryVersion(dataSources.subscribe);
|
|
6282
|
+
const [optionsByField, setOptionsByField] = React.useState({});
|
|
6283
|
+
const sourceEntries = React.useMemo(() => {
|
|
6284
|
+
if (!fields) return [];
|
|
6285
|
+
return Object.entries(fields).flatMap(([field, config]) => {
|
|
6286
|
+
if (!shouldLoadDynamicFilterOptions(config)) return [];
|
|
6287
|
+
const source = normalizeDataSourceConfig(getFilterDataSource(config));
|
|
6288
|
+
return source ? [{
|
|
6289
|
+
field,
|
|
6290
|
+
source
|
|
6291
|
+
}] : [];
|
|
6292
|
+
});
|
|
6293
|
+
}, [fields]);
|
|
6294
|
+
React.useEffect(() => {
|
|
6295
|
+
if (sourceEntries.length === 0) {
|
|
6296
|
+
setOptionsByField({});
|
|
6297
|
+
return;
|
|
6298
|
+
}
|
|
6299
|
+
let active = true;
|
|
6300
|
+
const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
|
|
6301
|
+
Promise.all(sourceEntries.map(async ({ field, source }) => {
|
|
6302
|
+
const loader = dataSources.get(source.key);
|
|
6303
|
+
if (!loader) return [field, []];
|
|
6304
|
+
try {
|
|
6305
|
+
return [field, normalizeOptions(await loader({
|
|
6306
|
+
field,
|
|
6307
|
+
values: {},
|
|
6308
|
+
signal: controller?.signal
|
|
6309
|
+
}))];
|
|
6310
|
+
} catch (error) {
|
|
6311
|
+
if (!controller?.signal.aborted) console.warn(`[AutoCrud] Failed to load filter data source "${source.key}".`, error);
|
|
6312
|
+
return [field, []];
|
|
6313
|
+
}
|
|
6314
|
+
})).then((entries) => {
|
|
6315
|
+
if (!active) return;
|
|
6316
|
+
setOptionsByField(Object.fromEntries(entries));
|
|
6317
|
+
});
|
|
6318
|
+
return () => {
|
|
6319
|
+
active = false;
|
|
6320
|
+
controller?.abort();
|
|
6321
|
+
};
|
|
6322
|
+
}, [sourceEntries, registryVersion]);
|
|
6323
|
+
return optionsByField;
|
|
6324
|
+
}
|
|
6268
6325
|
function getOptionLabel(value, options) {
|
|
6269
6326
|
const stringValue = String(value);
|
|
6270
6327
|
return options?.find((option) => option.value === stringValue)?.label ?? stringValue;
|
|
@@ -6273,15 +6330,21 @@ function getOptionLabel(value, options) {
|
|
|
6273
6330
|
* 从统一配置生成表格 overrides
|
|
6274
6331
|
* 当 filter 配置存在时,合并到 meta 中(不影响列隐藏)
|
|
6275
6332
|
*/
|
|
6276
|
-
function buildTableOverrides(fields, legacyOverrides) {
|
|
6333
|
+
function buildTableOverrides(fields, legacyOverrides, dynamicFilterOptions) {
|
|
6277
6334
|
const result = { ...legacyOverrides };
|
|
6278
6335
|
if (fields) for (const [key, config] of Object.entries(fields)) {
|
|
6279
|
-
const
|
|
6336
|
+
const fieldOptions = normalizeFieldOptions(config.enum);
|
|
6337
|
+
const tableOptions = toTableOptions(fieldOptions);
|
|
6338
|
+
const dynamicOptions = !fieldOptions ? toTableOptions(normalizeFieldOptions(dynamicFilterOptions?.[key])) : void 0;
|
|
6280
6339
|
const tableMeta = config.table !== false && typeof config.table === "object" ? config.table.meta : void 0;
|
|
6281
6340
|
const fieldEnumMeta = tableOptions ? {
|
|
6282
6341
|
options: tableOptions,
|
|
6283
6342
|
variant: "multiSelect"
|
|
6284
6343
|
} : void 0;
|
|
6344
|
+
const fieldDataSourceMeta = dynamicOptions ? {
|
|
6345
|
+
options: dynamicOptions,
|
|
6346
|
+
variant: "multiSelect"
|
|
6347
|
+
} : void 0;
|
|
6285
6348
|
let filterMeta;
|
|
6286
6349
|
if (config.filter && typeof config.filter === "object") {
|
|
6287
6350
|
if (config.filter.enabled !== false && config.filter.hidden !== true) {
|
|
@@ -6299,11 +6362,12 @@ function buildTableOverrides(fields, legacyOverrides) {
|
|
|
6299
6362
|
enableColumnFilter: false
|
|
6300
6363
|
};
|
|
6301
6364
|
}
|
|
6302
|
-
if (fieldEnumMeta || tableMeta || filterMeta) result[key] = {
|
|
6365
|
+
if (fieldEnumMeta || fieldDataSourceMeta || tableMeta || filterMeta) result[key] = {
|
|
6303
6366
|
...result[key],
|
|
6304
6367
|
meta: {
|
|
6305
6368
|
...result[key]?.meta ?? {},
|
|
6306
6369
|
...fieldEnumMeta ?? {},
|
|
6370
|
+
...fieldDataSourceMeta ?? {},
|
|
6307
6371
|
...tableMeta ?? {},
|
|
6308
6372
|
...filterMeta ?? {}
|
|
6309
6373
|
}
|
|
@@ -6616,6 +6680,7 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
6616
6680
|
const [selectedCount, setSelectedCount] = React.useState(0);
|
|
6617
6681
|
const [exporting, setExporting] = React.useState(false);
|
|
6618
6682
|
const getSelectedRowsRef = React.useRef(null);
|
|
6683
|
+
const dynamicFilterOptions = useDynamicFilterOptions(resolvedFields);
|
|
6619
6684
|
const importColumns = React.useMemo(() => {
|
|
6620
6685
|
const shape = resolvedSchema.shape;
|
|
6621
6686
|
const denySet = new Set(denyFields ?? []);
|
|
@@ -6652,7 +6717,11 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
|
|
|
6652
6717
|
setExporting(false);
|
|
6653
6718
|
}
|
|
6654
6719
|
}, [selectedCount, handleExport]);
|
|
6655
|
-
const tableOverrides = React.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides), [
|
|
6720
|
+
const tableOverrides = React.useMemo(() => buildTableOverrides(resolvedFields, tableConfig?.overrides, dynamicFilterOptions), [
|
|
6721
|
+
resolvedFields,
|
|
6722
|
+
tableConfig?.overrides,
|
|
6723
|
+
dynamicFilterOptions
|
|
6724
|
+
]);
|
|
6656
6725
|
const formOverrides = React.useMemo(() => buildFormOverrides(resolvedFields, formConfig?.overrides, denyFields), [
|
|
6657
6726
|
resolvedFields,
|
|
6658
6727
|
formConfig?.overrides,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordrhyme/auto-crud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
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.
|
|
70
|
-
"@pixpilot/shadcn
|
|
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",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"typescript": "^5.9.3",
|
|
85
85
|
"@internal/eslint-config": "0.3.0",
|
|
86
86
|
"@internal/prettier-config": "0.0.1",
|
|
87
|
-
"@internal/tsconfig": "0.1.0",
|
|
88
87
|
"@internal/tsdown-config": "0.1.0",
|
|
89
|
-
"@internal/vitest-config": "0.1.0"
|
|
88
|
+
"@internal/vitest-config": "0.1.0",
|
|
89
|
+
"@internal/tsconfig": "0.1.0"
|
|
90
90
|
},
|
|
91
91
|
"prettier": "@internal/prettier-config",
|
|
92
92
|
"scripts": {
|