@wordrhyme/auto-crud 1.12.2 → 1.14.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/README.md +67 -22
- package/dist/index.cjs +262 -128
- package/dist/index.d.cts +87 -64
- package/dist/index.d.ts +73 -50
- package/dist/index.js +263 -130
- package/dist/styles.css +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,8 @@ let __wordrhyme_formily_shadcn = require("@wordrhyme/formily-shadcn");
|
|
|
25
25
|
__wordrhyme_formily_shadcn = require_position.__toESM(__wordrhyme_formily_shadcn);
|
|
26
26
|
let __formily_core = require("@formily/core");
|
|
27
27
|
__formily_core = require_position.__toESM(__formily_core);
|
|
28
|
+
let __formily_react = require("@formily/react");
|
|
29
|
+
__formily_react = require_position.__toESM(__formily_react);
|
|
28
30
|
let __formily_reactive = require("@formily/reactive");
|
|
29
31
|
__formily_reactive = require_position.__toESM(__formily_reactive);
|
|
30
32
|
let sonner = require("sonner");
|
|
@@ -5120,7 +5122,7 @@ function useDataTable(props) {
|
|
|
5120
5122
|
...tableProps.defaultColumn,
|
|
5121
5123
|
enableColumnFilter: false
|
|
5122
5124
|
},
|
|
5123
|
-
enableRowSelection: true,
|
|
5125
|
+
enableRowSelection: tableProps.enableRowSelection ?? true,
|
|
5124
5126
|
onRowSelectionChange: setRowSelection,
|
|
5125
5127
|
onPaginationChange,
|
|
5126
5128
|
onSortingChange,
|
|
@@ -5186,7 +5188,7 @@ const filterModeConfig = {
|
|
|
5186
5188
|
tooltip: "Linear-style command filters"
|
|
5187
5189
|
}
|
|
5188
5190
|
};
|
|
5189
|
-
function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, toolbarExtra, locale = enUSTableControls, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows, exportTableRef }) {
|
|
5191
|
+
function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, queryKeys, initialColumnVisibility, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, toolbarExtra, locale = enUSTableControls, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows, exportTableRef }) {
|
|
5190
5192
|
if (expandedRow && !getRowId) throw new Error("AutoTable requires getRowId when expandedRow is provided.");
|
|
5191
5193
|
const enableExpansion = !!expandedRow;
|
|
5192
5194
|
const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
|
|
@@ -5196,7 +5198,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5196
5198
|
shallow: false,
|
|
5197
5199
|
clearOnDefault: true
|
|
5198
5200
|
});
|
|
5199
|
-
const [, setSearchPage] = useUrlState("page", parseAsInteger.withDefault(1), {
|
|
5201
|
+
const [, setSearchPage] = useUrlState(queryKeys?.page ?? "page", parseAsInteger.withDefault(1), {
|
|
5200
5202
|
shallow: false,
|
|
5201
5203
|
clearOnDefault: true
|
|
5202
5204
|
});
|
|
@@ -5263,6 +5265,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5263
5265
|
]);
|
|
5264
5266
|
const stableInitialState = (0, react.useMemo)(() => ({
|
|
5265
5267
|
sorting: initialSorting,
|
|
5268
|
+
columnVisibility: initialColumnVisibility,
|
|
5266
5269
|
expanded: enableExpansion && defaultExpanded ? true : {},
|
|
5267
5270
|
columnPinning: pinnedColumns ?? {
|
|
5268
5271
|
left: [...enableExpansion ? [expandColumnId] : [], ...enableRowSelection ? ["select"] : []],
|
|
@@ -5270,6 +5273,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5270
5273
|
}
|
|
5271
5274
|
}), [
|
|
5272
5275
|
initialSorting,
|
|
5276
|
+
initialColumnVisibility,
|
|
5273
5277
|
pinnedColumns,
|
|
5274
5278
|
enableRowSelection,
|
|
5275
5279
|
enableExpansion,
|
|
@@ -5281,6 +5285,8 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
|
|
|
5281
5285
|
const { table, shallow, debounceMs, throttleMs } = useDataTable({
|
|
5282
5286
|
data,
|
|
5283
5287
|
columns,
|
|
5288
|
+
queryKeys,
|
|
5289
|
+
enableRowSelection,
|
|
5284
5290
|
getRowId,
|
|
5285
5291
|
getRowCanExpand: () => enableExpansion,
|
|
5286
5292
|
getExpandedRowModel: enableExpansion ? expandedRowModel : void 0,
|
|
@@ -5478,6 +5484,7 @@ function FormModal({ open, onOpenChange, title, description, children, variant =
|
|
|
5478
5484
|
open,
|
|
5479
5485
|
onOpenChange,
|
|
5480
5486
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.SheetContent, {
|
|
5487
|
+
...!description ? { "aria-describedby": void 0 } : {},
|
|
5481
5488
|
side,
|
|
5482
5489
|
className: cn("sm:max-w-lg flex flex-col p-0", className),
|
|
5483
5490
|
children: [
|
|
@@ -5503,6 +5510,7 @@ function FormModal({ open, onOpenChange, title, description, children, variant =
|
|
|
5503
5510
|
open,
|
|
5504
5511
|
onOpenChange,
|
|
5505
5512
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.DialogContent, {
|
|
5513
|
+
...!description ? { "aria-describedby": void 0 } : {},
|
|
5506
5514
|
className: cn("max-w-2xl sm:max-w-2xl flex flex-col max-h-[85vh] overflow-hidden p-0", className),
|
|
5507
5515
|
children: [
|
|
5508
5516
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.DialogHeader, {
|
|
@@ -5624,6 +5632,8 @@ function createFormSchema(schema, options) {
|
|
|
5624
5632
|
const inferredByName = inferComponentByFieldName(key);
|
|
5625
5633
|
const component = inferredByName?.component ?? fieldTypeToFormilyComponent[parsed.type];
|
|
5626
5634
|
const inferredProps = inferredByName?.props ?? {};
|
|
5635
|
+
const componentProps = getComponentProps(parsed.type, parsed);
|
|
5636
|
+
if (parsed.type === "enum" && override?.enum) componentProps.options = override.enum;
|
|
5627
5637
|
properties[key] = {
|
|
5628
5638
|
type: mapToJsonSchemaType(parsed.type),
|
|
5629
5639
|
title: humanize$1(key),
|
|
@@ -5632,7 +5642,7 @@ function createFormSchema(schema, options) {
|
|
|
5632
5642
|
"x-decorator-props": decoratorProps,
|
|
5633
5643
|
"x-component": component,
|
|
5634
5644
|
"x-component-props": {
|
|
5635
|
-
...
|
|
5645
|
+
...componentProps,
|
|
5636
5646
|
...inferredProps
|
|
5637
5647
|
},
|
|
5638
5648
|
...parsed.enumValues && { enum: parsed.enumValues.map((v) => ({
|
|
@@ -5666,6 +5676,51 @@ function createEditFormSchema(schema, options) {
|
|
|
5666
5676
|
});
|
|
5667
5677
|
}
|
|
5668
5678
|
|
|
5679
|
+
//#endregion
|
|
5680
|
+
//#region src/components/auto-crud/read-pretty-field.tsx
|
|
5681
|
+
const ReadPrettyBooleanLocale = (0, react.createContext)(zhCN.boolean);
|
|
5682
|
+
const ReadPrettyRenderers = (0, react.createContext)({});
|
|
5683
|
+
function ReadPrettyField({ options }) {
|
|
5684
|
+
const field = (0, __formily_react.useField)();
|
|
5685
|
+
const schema = (0, __formily_react.useFieldSchema)();
|
|
5686
|
+
const renderCustomValue = (0, react.useContext)(ReadPrettyRenderers)[field.path.toString()];
|
|
5687
|
+
return renderCustomValue ? renderCustomValue() : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadPrettyValue, {
|
|
5688
|
+
value: field.value,
|
|
5689
|
+
options: options?.length ? options : field.dataSource,
|
|
5690
|
+
date: schema["x-component"] === "DatePicker"
|
|
5691
|
+
});
|
|
5692
|
+
}
|
|
5693
|
+
function ReadPrettyValue({ value, options: choices, date }) {
|
|
5694
|
+
const booleanLocale = (0, react.useContext)(ReadPrettyBooleanLocale);
|
|
5695
|
+
useDateFormatterVersion();
|
|
5696
|
+
const renderValue = (item) => {
|
|
5697
|
+
if (item == null || item === "") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5698
|
+
className: "text-muted-foreground",
|
|
5699
|
+
children: "-"
|
|
5700
|
+
});
|
|
5701
|
+
const option = choices?.find((choice) => String(choice.value) === String(item));
|
|
5702
|
+
if (option) return Array.isArray(value) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Badge, {
|
|
5703
|
+
variant: "secondary",
|
|
5704
|
+
className: "font-normal",
|
|
5705
|
+
children: option.label
|
|
5706
|
+
}) : option.label;
|
|
5707
|
+
if (typeof item === "boolean") return item ? booleanLocale.true : booleanLocale.false;
|
|
5708
|
+
if (item instanceof Date || date) return formatDate(item);
|
|
5709
|
+
if (typeof item === "object") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
5710
|
+
className: "rounded-md bg-muted/50 p-3 text-sm whitespace-pre-wrap break-words",
|
|
5711
|
+
children: JSON.stringify(item, null, 2)
|
|
5712
|
+
});
|
|
5713
|
+
return String(item);
|
|
5714
|
+
};
|
|
5715
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5716
|
+
className: "min-w-0 whitespace-pre-wrap break-words text-base leading-6 text-foreground",
|
|
5717
|
+
children: Array.isArray(value) ? value.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5718
|
+
className: "flex flex-wrap gap-2",
|
|
5719
|
+
children: value.map((item, index$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: renderValue(item) }, index$1))
|
|
5720
|
+
}) : renderValue(null) : renderValue(value)
|
|
5721
|
+
});
|
|
5722
|
+
}
|
|
5723
|
+
|
|
5669
5724
|
//#endregion
|
|
5670
5725
|
//#region src/lib/crud-reference-projection.ts
|
|
5671
5726
|
function isRecord$1(value) {
|
|
@@ -5814,12 +5869,8 @@ function normalizeFieldOptions$1(options) {
|
|
|
5814
5869
|
* 从统一字段配置生成 Formily overrides。
|
|
5815
5870
|
* `legacyOverrides` 保持兼容旧 API,字段级 `form` 配置优先级最高。
|
|
5816
5871
|
*/
|
|
5817
|
-
function buildFormOverrides(fields, legacyOverrides, denyFields) {
|
|
5872
|
+
function buildFormOverrides(fields, legacyOverrides, denyFields, mode = "edit") {
|
|
5818
5873
|
const result = { ...legacyOverrides };
|
|
5819
|
-
if (denyFields) for (const field of denyFields) result[field] = {
|
|
5820
|
-
...result[field],
|
|
5821
|
-
"x-hidden": true
|
|
5822
|
-
};
|
|
5823
5874
|
if (fields) for (const [key, config] of Object.entries(fields)) {
|
|
5824
5875
|
const fieldOptions = normalizeFieldOptions$1((config.form && typeof config.form === "object" ? config.form : void 0)?.enum) ?? normalizeFieldOptions$1(config.enum);
|
|
5825
5876
|
const fieldDataSource = fieldOptions || !config.dataSource ? void 0 : normalizeDataSourceConfig(config.dataSource);
|
|
@@ -5827,10 +5878,6 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
|
|
|
5827
5878
|
...result[key],
|
|
5828
5879
|
title: config.label
|
|
5829
5880
|
};
|
|
5830
|
-
if (config.hidden) result[key] = {
|
|
5831
|
-
...result[key],
|
|
5832
|
-
"x-hidden": true
|
|
5833
|
-
};
|
|
5834
5881
|
if (fieldOptions) result[key] = {
|
|
5835
5882
|
...result[key],
|
|
5836
5883
|
enum: fieldOptions
|
|
@@ -5839,15 +5886,27 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
|
|
|
5839
5886
|
...result[key],
|
|
5840
5887
|
"x-data-source": config.dataSource
|
|
5841
5888
|
};
|
|
5842
|
-
if (config.form === false) result[key] = {
|
|
5889
|
+
if (config.form === false && mode !== "view") result[key] = {
|
|
5843
5890
|
...result[key],
|
|
5844
5891
|
"x-hidden": true
|
|
5845
5892
|
};
|
|
5846
|
-
else if (config.form && typeof config.form === "object")
|
|
5893
|
+
else if (config.form && typeof config.form === "object") {
|
|
5894
|
+
const { "x-hidden": formHidden,...sharedFormConfig } = config.form;
|
|
5895
|
+
result[key] = {
|
|
5896
|
+
...result[key],
|
|
5897
|
+
...sharedFormConfig,
|
|
5898
|
+
...mode !== "view" && formHidden !== void 0 ? { "x-hidden": formHidden } : {}
|
|
5899
|
+
};
|
|
5900
|
+
}
|
|
5901
|
+
if (config.hidden) result[key] = {
|
|
5847
5902
|
...result[key],
|
|
5848
|
-
|
|
5903
|
+
"x-hidden": true
|
|
5849
5904
|
};
|
|
5850
5905
|
}
|
|
5906
|
+
for (const field of denyFields ?? []) result[field] = {
|
|
5907
|
+
...result[field],
|
|
5908
|
+
"x-hidden": true
|
|
5909
|
+
};
|
|
5851
5910
|
return result;
|
|
5852
5911
|
}
|
|
5853
5912
|
|
|
@@ -5910,6 +5969,13 @@ const defaultFieldComponents = {
|
|
|
5910
5969
|
decorator: "FormItem"
|
|
5911
5970
|
}
|
|
5912
5971
|
};
|
|
5972
|
+
const readPrettyFieldComponents = Object.fromEntries(Object.entries({
|
|
5973
|
+
...__wordrhyme_formily_shadcn.defaultComponentRegistry,
|
|
5974
|
+
...defaultFieldComponents
|
|
5975
|
+
}).filter(([, config]) => "decorator" in config).map(([name, config]) => [name, {
|
|
5976
|
+
...config,
|
|
5977
|
+
component: (0, __wordrhyme_formily_shadcn.connect)(config.component, (0, __formily_react.mapReadPretty)(ReadPrettyField))
|
|
5978
|
+
}]));
|
|
5913
5979
|
const AUTO_CRUD_DATA_SOURCE_SCOPE_KEY = "$autoCrudDataSource";
|
|
5914
5980
|
const POPUP_SCROLL_LOAD_THRESHOLD$1 = 24;
|
|
5915
5981
|
const dataSourceReactionStates = /* @__PURE__ */ new WeakMap();
|
|
@@ -5938,7 +6004,8 @@ function mergeReactions(existing, reaction) {
|
|
|
5938
6004
|
if (Array.isArray(existing)) return existing.includes(reaction) ? existing : [...existing, reaction];
|
|
5939
6005
|
return [existing, reaction];
|
|
5940
6006
|
}
|
|
5941
|
-
function applyDataSourceReactions(schema) {
|
|
6007
|
+
function applyDataSourceReactions(schema, readPretty = false) {
|
|
6008
|
+
if (readPretty) schema["x-pattern"] = "readPretty";
|
|
5942
6009
|
const dataSourceConfig = getSchemaDataSourceConfig(schema);
|
|
5943
6010
|
if (dataSourceConfig) {
|
|
5944
6011
|
const reaction = `{{${AUTO_CRUD_DATA_SOURCE_SCOPE_KEY}(${JSON.stringify(dataSourceConfig)})}}`;
|
|
@@ -5946,12 +6013,12 @@ function applyDataSourceReactions(schema) {
|
|
|
5946
6013
|
}
|
|
5947
6014
|
const properties = schema.properties;
|
|
5948
6015
|
if (properties && typeof properties === "object" && !Array.isArray(properties)) {
|
|
5949
|
-
for (const property of Object.values(properties)) if (property && typeof property === "object" && !Array.isArray(property)) applyDataSourceReactions(property);
|
|
6016
|
+
for (const property of Object.values(properties)) if (property && typeof property === "object" && !Array.isArray(property)) applyDataSourceReactions(property, readPretty);
|
|
5950
6017
|
}
|
|
5951
6018
|
const items = schema.items;
|
|
5952
6019
|
if (Array.isArray(items)) {
|
|
5953
|
-
for (const item of items) if (item && typeof item === "object") applyDataSourceReactions(item);
|
|
5954
|
-
} else if (items && typeof items === "object") applyDataSourceReactions(items);
|
|
6020
|
+
for (const item of items) if (item && typeof item === "object") applyDataSourceReactions(item, readPretty);
|
|
6021
|
+
} else if (items && typeof items === "object") applyDataSourceReactions(items, readPretty);
|
|
5955
6022
|
}
|
|
5956
6023
|
function getDataSourceReactionState(field) {
|
|
5957
6024
|
const existing = dataSourceReactionStates.get(field);
|
|
@@ -5996,7 +6063,7 @@ function loadAutoCrudDataSource({ entry, field, registryVersion, search, sourceK
|
|
|
5996
6063
|
});
|
|
5997
6064
|
setAutoCrudDataSourceOptions(field, state.options);
|
|
5998
6065
|
if (!append && state.loadKey === loadKey && state.registryVersion === registryVersion) return;
|
|
5999
|
-
if (entry.reset && state.dependencyKey !== void 0 && state.dependencyKey !== dependencyKey) field.setValue(void 0);
|
|
6066
|
+
if (entry.reset && !field.readPretty && state.dependencyKey !== void 0 && state.dependencyKey !== dependencyKey) field.setValue(void 0);
|
|
6000
6067
|
state.dependencyKey = dependencyKey;
|
|
6001
6068
|
if (!append) {
|
|
6002
6069
|
state.loadKey = loadKey;
|
|
@@ -6172,7 +6239,10 @@ function createAutoCrudDataSourceReaction(config, registryState) {
|
|
|
6172
6239
|
};
|
|
6173
6240
|
}
|
|
6174
6241
|
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, fields, overrides, scope: scopeProp, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
|
|
6175
|
-
const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({
|
|
6242
|
+
const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({
|
|
6243
|
+
initialValues,
|
|
6244
|
+
pattern: mode === "view" ? "readPretty" : "editable"
|
|
6245
|
+
}), [JSON.stringify(initialValues), mode]);
|
|
6176
6246
|
const dataSourceRegistryState = (0, react.useMemo)(() => (0, __formily_reactive.observable)({ version: 0 }), []);
|
|
6177
6247
|
const updateDataSourceRegistryState = (0, react.useCallback)(() => {
|
|
6178
6248
|
(0, __formily_reactive.action)(() => {
|
|
@@ -6180,40 +6250,75 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, fields, ove
|
|
|
6180
6250
|
});
|
|
6181
6251
|
}, [dataSourceRegistryState]);
|
|
6182
6252
|
const dataSourceRegistryVersion = useRegistryVersion$1(dataSources.subscribe, updateDataSourceRegistryState);
|
|
6183
|
-
const formOverrides = (0, react.useMemo)(() => buildFormOverrides(fields, overrides
|
|
6253
|
+
const formOverrides = (0, react.useMemo)(() => buildFormOverrides(fields, overrides, void 0, mode), [
|
|
6254
|
+
fields,
|
|
6255
|
+
overrides,
|
|
6256
|
+
mode
|
|
6257
|
+
]);
|
|
6184
6258
|
const formSchema = (0, react.useMemo)(() => {
|
|
6185
|
-
const nextSchema = createEditFormSchema(zodSchema, {
|
|
6259
|
+
const nextSchema = (mode === "view" ? createFormSchema : createEditFormSchema)(zodSchema, {
|
|
6186
6260
|
overrides: formOverrides,
|
|
6187
6261
|
layout: "grid",
|
|
6188
6262
|
gridColumns
|
|
6189
6263
|
});
|
|
6190
|
-
|
|
6264
|
+
const grid = typeof nextSchema.properties === "object" ? nextSchema.properties.layout : void 0;
|
|
6265
|
+
if (mode === "view" && grid && typeof grid === "object") {
|
|
6266
|
+
grid["x-component-props"] = {
|
|
6267
|
+
...grid["x-component-props"],
|
|
6268
|
+
className: (0, __wordrhyme_shadcn.cn)(grid["x-component-props"]?.className, "gap-x-10 gap-y-7 py-2")
|
|
6269
|
+
};
|
|
6270
|
+
const properties = typeof grid.properties === "object" ? grid.properties : {};
|
|
6271
|
+
for (const property of Object.values(properties)) {
|
|
6272
|
+
const decoratorProps = property["x-decorator-props"];
|
|
6273
|
+
const fullWidth = property.type === "object" || property.type === "array" || ["Textarea", "RichTextEditor"].includes(property["x-component"]);
|
|
6274
|
+
property["x-decorator-props"] = {
|
|
6275
|
+
colon: false,
|
|
6276
|
+
...decoratorProps,
|
|
6277
|
+
className: (0, __wordrhyme_shadcn.cn)(fullWidth && decoratorProps?.gridSpan == null && "col-span-full", decoratorProps?.className)
|
|
6278
|
+
};
|
|
6279
|
+
}
|
|
6280
|
+
}
|
|
6281
|
+
applyDataSourceReactions(nextSchema, mode === "view");
|
|
6191
6282
|
return nextSchema;
|
|
6192
6283
|
}, [
|
|
6193
6284
|
zodSchema,
|
|
6194
6285
|
formOverrides,
|
|
6195
6286
|
gridColumns,
|
|
6196
|
-
dataSourceRegistryVersion
|
|
6287
|
+
dataSourceRegistryVersion,
|
|
6288
|
+
mode
|
|
6197
6289
|
]);
|
|
6198
6290
|
const formLayout = (0, react.useMemo)(() => {
|
|
6199
6291
|
const inlineLabel = labelAlign === "left" || labelAlign === "right";
|
|
6200
|
-
return {
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6292
|
+
return { itemProps: {
|
|
6293
|
+
container: mode === "view" ? { className: "min-w-0 space-y-0 gap-2" } : void 0,
|
|
6294
|
+
label: {
|
|
6295
|
+
placement: inlineLabel ? "start" : "top",
|
|
6296
|
+
className: (0, __wordrhyme_shadcn.cn)(mode === "view" && "mb-0 text-sm font-normal text-muted-foreground leading-5", labelAlign === "right" && "text-right"),
|
|
6297
|
+
style: inlineLabel && labelWidth != null ? { width: labelWidth } : void 0
|
|
6298
|
+
}
|
|
6299
|
+
} };
|
|
6300
|
+
}, [
|
|
6301
|
+
labelAlign,
|
|
6302
|
+
labelWidth,
|
|
6303
|
+
mode
|
|
6304
|
+
]);
|
|
6208
6305
|
const fieldComponents = (0, react.useMemo)(() => ({ fields: {
|
|
6209
6306
|
...defaultFieldComponents,
|
|
6307
|
+
...mode === "view" ? {
|
|
6308
|
+
...readPrettyFieldComponents,
|
|
6309
|
+
ObjectField: {
|
|
6310
|
+
component: ReadPrettyField,
|
|
6311
|
+
decorator: "FormItem"
|
|
6312
|
+
}
|
|
6313
|
+
} : {},
|
|
6210
6314
|
...components.all()
|
|
6211
|
-
} }), [useRegistryVersion$1(components.subscribe)]);
|
|
6315
|
+
} }), [useRegistryVersion$1(components.subscribe), mode]);
|
|
6212
6316
|
const scope = (0, react.useMemo)(() => ({
|
|
6213
6317
|
...scopeProp,
|
|
6214
6318
|
[AUTO_CRUD_DATA_SOURCE_SCOPE_KEY]: (config) => createAutoCrudDataSourceReaction(config, dataSourceRegistryState)
|
|
6215
6319
|
}), [dataSourceRegistryState, scopeProp]);
|
|
6216
6320
|
const handleSubmit = async () => {
|
|
6321
|
+
if (mode === "view" || !onSubmit) return;
|
|
6217
6322
|
await form.validate();
|
|
6218
6323
|
if (form.valid) await onSubmit(form.values);
|
|
6219
6324
|
};
|
|
@@ -6225,7 +6330,7 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, fields, ove
|
|
|
6225
6330
|
schema: formSchema,
|
|
6226
6331
|
components: fieldComponents,
|
|
6227
6332
|
scope
|
|
6228
|
-
}), showSubmitButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6333
|
+
}), mode !== "view" && showSubmitButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6229
6334
|
className: "flex justify-end gap-2 mt-6",
|
|
6230
6335
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
|
|
6231
6336
|
type: "button",
|
|
@@ -6241,7 +6346,7 @@ const AutoForm = (0, react.forwardRef)(AutoFormInner);
|
|
|
6241
6346
|
//#endregion
|
|
6242
6347
|
//#region src/components/auto-crud/crud-form-modal.tsx
|
|
6243
6348
|
function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubmit, loading = false, variant = "dialog", overrides, scope, title, locale = zhCN.formModal, gridColumns, labelAlign, labelWidth, className }) {
|
|
6244
|
-
const defaultTitle = mode === "create" ? locale.createTitle : locale.editTitle;
|
|
6349
|
+
const defaultTitle = mode === "create" ? locale.createTitle : mode === "edit" ? locale.editTitle : zhCN.viewModal.title;
|
|
6245
6350
|
const formRef = (0, react.useRef)(null);
|
|
6246
6351
|
const handleSubmit = async () => {
|
|
6247
6352
|
await formRef.current?.submit();
|
|
@@ -6252,7 +6357,7 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
|
|
|
6252
6357
|
title: title ?? defaultTitle,
|
|
6253
6358
|
variant,
|
|
6254
6359
|
className,
|
|
6255
|
-
footer: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6360
|
+
footer: mode !== "view" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6256
6361
|
className: "flex justify-end gap-2",
|
|
6257
6362
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
|
|
6258
6363
|
type: "button",
|
|
@@ -6265,14 +6370,16 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
|
|
|
6265
6370
|
disabled: loading,
|
|
6266
6371
|
children: loading ? locale.submitting : mode === "create" ? locale.create : locale.save
|
|
6267
6372
|
})]
|
|
6268
|
-
}),
|
|
6373
|
+
}) : void 0,
|
|
6269
6374
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoForm, {
|
|
6270
6375
|
ref: formRef,
|
|
6271
6376
|
schema,
|
|
6272
|
-
mode
|
|
6377
|
+
...mode === "view" ? { mode } : {
|
|
6378
|
+
mode,
|
|
6379
|
+
onSubmit
|
|
6380
|
+
},
|
|
6273
6381
|
initialValues,
|
|
6274
6382
|
loading,
|
|
6275
|
-
onSubmit,
|
|
6276
6383
|
overrides,
|
|
6277
6384
|
scope,
|
|
6278
6385
|
gridColumns,
|
|
@@ -7652,7 +7759,7 @@ function ViewModal(props) {
|
|
|
7652
7759
|
if (!props.open || !props.data) return null;
|
|
7653
7760
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModalContent, { ...props });
|
|
7654
7761
|
}
|
|
7655
|
-
function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: fieldConfig, dynamicOptions, denyFields, locale, tableOverrides, view }) {
|
|
7762
|
+
function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: fieldConfig, dynamicOptions, denyFields, locale, tableOverrides, view, form }) {
|
|
7656
7763
|
const excluded = react.useMemo(() => {
|
|
7657
7764
|
const denied = new Set(denyFields ?? []);
|
|
7658
7765
|
return Object.keys(schema.shape).filter((key) => {
|
|
@@ -7667,70 +7774,82 @@ function ViewModalContent({ open, onOpenChange, variant, data, schema, fields: f
|
|
|
7667
7774
|
]);
|
|
7668
7775
|
const rows = react.useMemo(() => data ? [data] : [], [data]);
|
|
7669
7776
|
const resolvedOptions = useDynamicResolveOptions(fieldConfig, rows, excluded);
|
|
7670
|
-
const
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
const
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
|
|
7714
|
-
className: "text-sm font-medium text-muted-foreground",
|
|
7715
|
-
children: cell.column.columnDef.meta?.label ?? humanize(cell.column.id)
|
|
7716
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
7717
|
-
className: "col-span-2 min-w-0 whitespace-pre-wrap break-words text-sm",
|
|
7718
|
-
children: (0, __tanstack_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext())
|
|
7719
|
-
})]
|
|
7720
|
-
}, cell.id))
|
|
7721
|
-
});
|
|
7722
|
-
if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.Sheet, {
|
|
7723
|
-
open,
|
|
7724
|
-
onOpenChange,
|
|
7725
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_ui.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.SheetTitle, { children: locale.viewModal.title }) }), content] })
|
|
7777
|
+
const table = (0, __tanstack_react_table.useReactTable)({
|
|
7778
|
+
data: rows,
|
|
7779
|
+
columns: react.useMemo(() => {
|
|
7780
|
+
const overrides$1 = {};
|
|
7781
|
+
for (const [key, fieldSchema] of Object.entries(schema.shape).filter(([fieldKey]) => !excluded.includes(fieldKey))) {
|
|
7782
|
+
const config = fieldConfig?.[key] ?? {};
|
|
7783
|
+
const tableConfig = getTableConfig(config);
|
|
7784
|
+
const listOverride = tableOverrides?.[key];
|
|
7785
|
+
const options = getTableOptions(config) ?? resolvedOptions.optionsByField[key] ?? (tableConfig?.dataSource !== void 0 ? void 0 : dynamicOptions?.[key]);
|
|
7786
|
+
overrides$1[key] = {
|
|
7787
|
+
label: tableConfig?.label ?? config.label ?? listOverride?.label ?? humanize(key),
|
|
7788
|
+
index: tableConfig?.index ?? listOverride?.index,
|
|
7789
|
+
cell: ({ getValue, row }) => {
|
|
7790
|
+
const value = getValue();
|
|
7791
|
+
return config.format?.(value, {
|
|
7792
|
+
row: row.original,
|
|
7793
|
+
target: "display"
|
|
7794
|
+
}) ?? (tableConfig?.display && tableConfig.display !== "auto" || options?.some((option) => option.badgeTone) ? renderFieldValue(value, parseZodField(fieldSchema).type, locale.boolean, options, tableConfig?.display ?? "auto", Infinity) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadPrettyValue, {
|
|
7795
|
+
value,
|
|
7796
|
+
options,
|
|
7797
|
+
date: parseZodField(fieldSchema).type === "date"
|
|
7798
|
+
}));
|
|
7799
|
+
},
|
|
7800
|
+
...view?.presentation === "table" ? listOverride : void 0,
|
|
7801
|
+
hidden: false,
|
|
7802
|
+
...view?.overrides?.[key]
|
|
7803
|
+
};
|
|
7804
|
+
}
|
|
7805
|
+
return createTableSchema(schema, {
|
|
7806
|
+
overrides: overrides$1,
|
|
7807
|
+
exclude: excluded
|
|
7808
|
+
});
|
|
7809
|
+
}, [
|
|
7810
|
+
schema,
|
|
7811
|
+
excluded,
|
|
7812
|
+
fieldConfig,
|
|
7813
|
+
tableOverrides,
|
|
7814
|
+
view,
|
|
7815
|
+
resolvedOptions.optionsByField,
|
|
7816
|
+
dynamicOptions,
|
|
7817
|
+
locale.boolean
|
|
7818
|
+
]),
|
|
7819
|
+
getCoreRowModel: (0, __tanstack_react_table.getCoreRowModel)()
|
|
7726
7820
|
});
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7821
|
+
const detailSchema = react.useMemo(() => schema.omit(Object.fromEntries(excluded.map((key) => [key, true]))), [schema, excluded]);
|
|
7822
|
+
const overrides = buildFormOverrides(fieldConfig, form?.overrides, denyFields, "view");
|
|
7823
|
+
const renderers = {};
|
|
7824
|
+
for (const [index$1, cell] of (table.getRowModel().rows[0]?.getAllCells() ?? []).entries()) {
|
|
7825
|
+
const key = cell.column.id;
|
|
7826
|
+
overrides[key] = {
|
|
7827
|
+
...overrides[key],
|
|
7828
|
+
title: cell.column.columnDef.meta?.label ?? humanize(key),
|
|
7829
|
+
"x-index": index$1
|
|
7830
|
+
};
|
|
7831
|
+
renderers[key] = () => (0, __tanstack_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext());
|
|
7832
|
+
delete overrides[key]["x-data-source"];
|
|
7833
|
+
}
|
|
7834
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadPrettyBooleanLocale.Provider, {
|
|
7835
|
+
value: locale.boolean,
|
|
7836
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadPrettyRenderers.Provider, {
|
|
7837
|
+
value: renderers,
|
|
7838
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CrudFormModal, {
|
|
7839
|
+
open,
|
|
7840
|
+
onOpenChange,
|
|
7841
|
+
mode: "view",
|
|
7842
|
+
variant,
|
|
7843
|
+
schema: detailSchema,
|
|
7844
|
+
initialValues: data ?? void 0,
|
|
7845
|
+
overrides,
|
|
7846
|
+
scope: form?.scope,
|
|
7847
|
+
title: locale.viewModal.title,
|
|
7848
|
+
gridColumns: form?.columns,
|
|
7849
|
+
labelAlign: form?.labelAlign,
|
|
7850
|
+
labelWidth: form?.labelWidth,
|
|
7851
|
+
className: form?.className
|
|
7852
|
+
})
|
|
7734
7853
|
})
|
|
7735
7854
|
});
|
|
7736
7855
|
}
|
|
@@ -8194,6 +8313,9 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
8194
8313
|
pageCount: resource.tableData.pageCount,
|
|
8195
8314
|
pagination: paginationOptions,
|
|
8196
8315
|
...resource.tableData.total !== void 0 ? { total: resource.tableData.total } : {},
|
|
8316
|
+
queryKeys: tableConfig?.queryKeys ?? resource.queryKeys,
|
|
8317
|
+
enableRowSelection: tableConfig?.enableRowSelection,
|
|
8318
|
+
initialColumnVisibility: tableConfig?.initialColumnVisibility,
|
|
8197
8319
|
getRowId: tableConfig?.getRowId,
|
|
8198
8320
|
expandedRow: tableConfig?.expandedRow,
|
|
8199
8321
|
defaultExpanded: tableConfig?.defaultExpanded,
|
|
@@ -8235,6 +8357,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
8235
8357
|
scope: formConfig?.scope,
|
|
8236
8358
|
locale: locale.formModal,
|
|
8237
8359
|
gridColumns: formConfig?.columns,
|
|
8360
|
+
labelAlign: formConfig?.labelAlign,
|
|
8361
|
+
labelWidth: formConfig?.labelWidth,
|
|
8238
8362
|
className: formConfig?.className
|
|
8239
8363
|
}),
|
|
8240
8364
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModal, {
|
|
@@ -8248,7 +8372,8 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
|
|
|
8248
8372
|
denyFields,
|
|
8249
8373
|
locale,
|
|
8250
8374
|
tableOverrides: detailTableOverrides,
|
|
8251
|
-
view: viewConfig
|
|
8375
|
+
view: viewConfig,
|
|
8376
|
+
form: formConfig
|
|
8252
8377
|
}),
|
|
8253
8378
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_ui.AlertDialog, {
|
|
8254
8379
|
open: resource.modal.deleteOpen,
|
|
@@ -9036,7 +9161,7 @@ function modalReducer(state, action$1) {
|
|
|
9036
9161
|
/**
|
|
9037
9162
|
* Hook 主函数
|
|
9038
9163
|
*/
|
|
9039
|
-
function useAutoCrudResource({ router, schema, query: queryTransform, fields, options = {} }) {
|
|
9164
|
+
function useAutoCrudResource({ router, queryKeys, schema, query: queryTransform, fields, options = {} }) {
|
|
9040
9165
|
const { idKey = "id", defaultVariant = "dialog", hooks, toast: toastAdapter, exportFetcher, defaultSort: defaultSortOption } = options;
|
|
9041
9166
|
const toast$1 = (0, react.useMemo)(() => toastAdapter === false ? noopToastAdapter : toastAdapter ?? defaultToastAdapter, [toastAdapter]);
|
|
9042
9167
|
const hooksRef = (0, react.useRef)(hooks);
|
|
@@ -9057,31 +9182,36 @@ function useAutoCrudResource({ router, schema, query: queryTransform, fields, op
|
|
|
9057
9182
|
fields,
|
|
9058
9183
|
metadataFields
|
|
9059
9184
|
]);
|
|
9060
|
-
const [
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9185
|
+
const [page] = useQueryState(queryKeys?.page ?? "page", parseAsInteger.withDefault(1));
|
|
9186
|
+
const [perPage] = useQueryState(queryKeys?.perPage ?? "perPage", parseAsInteger.withDefault(10));
|
|
9187
|
+
const [sort] = useQueryState(queryKeys?.sort ?? "sort", getSortingStateParser().withDefault(defaultSorting));
|
|
9188
|
+
const [joinOperator] = useQueryState(queryKeys?.joinOperator ?? "joinOperator", parseAsStringEnum(["and", "or"]).withDefault("and"));
|
|
9189
|
+
const [search] = useQueryState("search", parseAsString.withDefault(""), { shallow: false });
|
|
9190
|
+
const [filters] = useReadableFilters(columns, {
|
|
9191
|
+
shallow: false,
|
|
9192
|
+
resetPageKey: queryKeys?.page ?? "page"
|
|
9193
|
+
});
|
|
9068
9194
|
const metadataPending = Boolean(metadataQuery?.isPending);
|
|
9069
9195
|
const [filtersReady, setFiltersReady] = (0, react.useState)(!metadataPending);
|
|
9070
9196
|
(0, react.useEffect)(() => setFiltersReady(!metadataPending), [metadataPending]);
|
|
9071
9197
|
const listReady = !metadataPending && filtersReady;
|
|
9072
9198
|
const queryInput = (0, react.useMemo)(() => {
|
|
9073
9199
|
const autoParams = {
|
|
9074
|
-
page
|
|
9075
|
-
perPage
|
|
9076
|
-
sort
|
|
9200
|
+
page,
|
|
9201
|
+
perPage,
|
|
9202
|
+
sort,
|
|
9077
9203
|
filters,
|
|
9078
|
-
joinOperator
|
|
9079
|
-
...
|
|
9204
|
+
joinOperator,
|
|
9205
|
+
...search.trim() ? { search: search.trim() } : {}
|
|
9080
9206
|
};
|
|
9081
9207
|
return queryTransform ? queryTransform(autoParams) : autoParams;
|
|
9082
9208
|
}, [
|
|
9083
|
-
|
|
9209
|
+
page,
|
|
9210
|
+
perPage,
|
|
9211
|
+
sort,
|
|
9084
9212
|
filters,
|
|
9213
|
+
joinOperator,
|
|
9214
|
+
search,
|
|
9085
9215
|
queryTransform
|
|
9086
9216
|
]);
|
|
9087
9217
|
const hasReadyListData = (0, react.useRef)(false);
|
|
@@ -9357,6 +9487,7 @@ function useAutoCrudResource({ router, schema, query: queryTransform, fields, op
|
|
|
9357
9487
|
}, [listQuery, listReady]);
|
|
9358
9488
|
return {
|
|
9359
9489
|
idKey,
|
|
9490
|
+
queryKeys,
|
|
9360
9491
|
tableData: {
|
|
9361
9492
|
data: tableRows,
|
|
9362
9493
|
pageCount: listData?.pageCount ?? 0,
|
|
@@ -9644,18 +9775,21 @@ function createMemoryDataSource(initialData = []) {
|
|
|
9644
9775
|
let filtered = [...data];
|
|
9645
9776
|
if (params.filters) filtered = filtered.filter((item) => {
|
|
9646
9777
|
return params.filters.every((filter) => {
|
|
9647
|
-
|
|
9778
|
+
const value = item[filter.id];
|
|
9779
|
+
if (filter.operator === "inArray") return Array.isArray(filter.value) && filter.value.includes(value);
|
|
9780
|
+
if (!filter.operator || filter.operator === "eq") return value === filter.value;
|
|
9781
|
+
throw new Error(`Unsupported memory filter operator: ${filter.operator}`);
|
|
9648
9782
|
});
|
|
9649
9783
|
});
|
|
9650
|
-
if (params.sort && params.sort.length > 0) {
|
|
9651
|
-
const sortItem
|
|
9652
|
-
filtered.sort((a, b) => {
|
|
9784
|
+
if (params.sort && params.sort.length > 0) filtered.sort((a, b) => {
|
|
9785
|
+
for (const sortItem of params.sort) {
|
|
9653
9786
|
const aVal = a[sortItem.id];
|
|
9654
9787
|
const bVal = b[sortItem.id];
|
|
9655
9788
|
const result = aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
|
|
9656
|
-
return sortItem.desc ? -result : result;
|
|
9657
|
-
}
|
|
9658
|
-
|
|
9789
|
+
if (result) return sortItem.desc ? -result : result;
|
|
9790
|
+
}
|
|
9791
|
+
return 0;
|
|
9792
|
+
});
|
|
9659
9793
|
const start = (params.page - 1) * params.perPage;
|
|
9660
9794
|
const end = start + params.perPage;
|
|
9661
9795
|
return {
|