imean-service-engine-htmx-plugin 2.6.0 → 2.8.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.d.mts +397 -27
- package/dist/index.d.ts +397 -27
- package/dist/index.js +878 -625
- package/dist/index.mjs +866 -626
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx, jsxs, Fragment } from 'hono/jsx/jsx-runtime';
|
|
|
2
2
|
import { promises } from 'fs';
|
|
3
3
|
import { logger, PluginPriority } from 'imean-service-engine';
|
|
4
4
|
import { join } from 'path';
|
|
5
|
+
import { z } from 'zod';
|
|
5
6
|
import { getCookie } from 'hono/cookie';
|
|
6
7
|
import { html } from 'hono/html';
|
|
7
8
|
|
|
@@ -421,6 +422,212 @@ var PageModel = class {
|
|
|
421
422
|
}
|
|
422
423
|
};
|
|
423
424
|
|
|
425
|
+
// src/utils/schema-utils.ts
|
|
426
|
+
function parseSchemaToFields(schema) {
|
|
427
|
+
const def = schema._def;
|
|
428
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
429
|
+
if (!shape || typeof shape !== "object") {
|
|
430
|
+
return [];
|
|
431
|
+
}
|
|
432
|
+
const fields = [];
|
|
433
|
+
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
434
|
+
if (["id", "createdAt", "updatedAt"].includes(fieldName)) {
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
const field = parseFieldSchema(fieldName, fieldSchema);
|
|
438
|
+
if (field) {
|
|
439
|
+
fields.push(field);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return fields;
|
|
443
|
+
}
|
|
444
|
+
function parseFieldSchema(fieldName, fieldSchema) {
|
|
445
|
+
if (!fieldSchema || !fieldSchema._def) {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
const label = getFieldDescription(fieldSchema) || fieldName;
|
|
449
|
+
const { type, required, options, innerSchema, step } = analyzeFieldType(fieldSchema);
|
|
450
|
+
return {
|
|
451
|
+
name: fieldName,
|
|
452
|
+
label,
|
|
453
|
+
type,
|
|
454
|
+
required,
|
|
455
|
+
options,
|
|
456
|
+
step,
|
|
457
|
+
schema: innerSchema || fieldSchema
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function getFieldDescription(schema) {
|
|
461
|
+
if (schema?.description) {
|
|
462
|
+
return schema.description;
|
|
463
|
+
}
|
|
464
|
+
const schemaDef = schema._def;
|
|
465
|
+
if (schemaDef?.description) {
|
|
466
|
+
return schemaDef.description;
|
|
467
|
+
}
|
|
468
|
+
if (schemaDef?.innerType) {
|
|
469
|
+
return getFieldDescription(schemaDef.innerType);
|
|
470
|
+
}
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
function analyzeFieldType(schema) {
|
|
474
|
+
const def = schema._def;
|
|
475
|
+
const typeName = def?.type || def?.typeName;
|
|
476
|
+
if (typeName === "optional" || typeName === "ZodOptional") {
|
|
477
|
+
const inner = analyzeFieldType(def.innerType);
|
|
478
|
+
return {
|
|
479
|
+
...inner,
|
|
480
|
+
required: false,
|
|
481
|
+
innerSchema: def.innerType
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if (typeName === "nullable" || typeName === "ZodNullable") {
|
|
485
|
+
const inner = analyzeFieldType(def.innerType);
|
|
486
|
+
return {
|
|
487
|
+
...inner,
|
|
488
|
+
innerSchema: def.innerType
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
if (typeName === "enum" || typeName === "ZodEnum") {
|
|
492
|
+
const options = extractEnumValues(def);
|
|
493
|
+
return {
|
|
494
|
+
type: "select",
|
|
495
|
+
required: true,
|
|
496
|
+
options,
|
|
497
|
+
innerSchema: schema
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
if (typeName === "nativeEnum" || typeName === "ZodNativeEnum") {
|
|
501
|
+
const options = extractNativeEnumValues(def);
|
|
502
|
+
return {
|
|
503
|
+
type: "select",
|
|
504
|
+
required: true,
|
|
505
|
+
options,
|
|
506
|
+
innerSchema: schema
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
if (typeName === "string" || typeName === "ZodString") {
|
|
510
|
+
let fieldType = "text";
|
|
511
|
+
if (def?.checks) {
|
|
512
|
+
const hasEmailCheck = def.checks.some(
|
|
513
|
+
(check) => check.format === "email" || check.constructor?.name === "ZodEmail" || check._zod?.def?.format === "email"
|
|
514
|
+
);
|
|
515
|
+
if (hasEmailCheck) {
|
|
516
|
+
fieldType = "email";
|
|
517
|
+
} else {
|
|
518
|
+
const maxLengthCheck = def.checks.find(
|
|
519
|
+
(check) => check.constructor?.name === "$ZodCheckMaxLength" || check._zod?.def?.check === "max_length" || check._zod?.def?.maximum !== void 0
|
|
520
|
+
);
|
|
521
|
+
if (maxLengthCheck) {
|
|
522
|
+
const maxLength = maxLengthCheck._zod?.def?.maximum ?? maxLengthCheck.value ?? maxLengthCheck.maximum;
|
|
523
|
+
if (maxLength !== void 0 && maxLength > 50) {
|
|
524
|
+
fieldType = "textarea";
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
type: fieldType,
|
|
531
|
+
required: true,
|
|
532
|
+
innerSchema: schema
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
if (typeName === "number" || typeName === "ZodNumber") {
|
|
536
|
+
let step = void 0;
|
|
537
|
+
if (def?.checks) {
|
|
538
|
+
const hasIntCheck = def.checks.some(
|
|
539
|
+
(check) => check.isInt === true || check.format === "safeint" || check.def?.format === "safeint" || check.kind === "int" || check.constructor?.name === "ZodInt" || check._zod?.def?.check === "int" || check._zod?.def?.kind === "int"
|
|
540
|
+
);
|
|
541
|
+
if (!hasIntCheck) {
|
|
542
|
+
step = "any";
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
step = "any";
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
type: "number",
|
|
549
|
+
required: true,
|
|
550
|
+
innerSchema: schema,
|
|
551
|
+
step
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
if (typeName === "date" || typeName === "ZodDate") {
|
|
555
|
+
return {
|
|
556
|
+
type: "date",
|
|
557
|
+
required: true,
|
|
558
|
+
innerSchema: schema
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
if (typeName === "boolean" || typeName === "ZodBoolean") {
|
|
562
|
+
return {
|
|
563
|
+
type: "checkbox",
|
|
564
|
+
required: true,
|
|
565
|
+
innerSchema: schema
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
type: "text",
|
|
570
|
+
required: true,
|
|
571
|
+
innerSchema: schema
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function extractEnumValues(def) {
|
|
575
|
+
let values;
|
|
576
|
+
if (def?.values && Array.isArray(def.values)) {
|
|
577
|
+
values = def.values;
|
|
578
|
+
} else if (def?.entries && typeof def.entries === "object") {
|
|
579
|
+
values = Object.keys(def.entries);
|
|
580
|
+
}
|
|
581
|
+
if (values && values.length > 0) {
|
|
582
|
+
return values.map((value) => ({
|
|
583
|
+
value,
|
|
584
|
+
label: String(value)
|
|
585
|
+
}));
|
|
586
|
+
}
|
|
587
|
+
return void 0;
|
|
588
|
+
}
|
|
589
|
+
function extractNativeEnumValues(def) {
|
|
590
|
+
const enumValues = def.values || def._def?.values || {};
|
|
591
|
+
if (enumValues && typeof enumValues === "object") {
|
|
592
|
+
return Object.entries(enumValues).filter(
|
|
593
|
+
([_, value]) => typeof value === "string" || typeof value === "number"
|
|
594
|
+
).map(([key, value]) => ({
|
|
595
|
+
value,
|
|
596
|
+
label: key
|
|
597
|
+
}));
|
|
598
|
+
}
|
|
599
|
+
return void 0;
|
|
600
|
+
}
|
|
601
|
+
function filterFieldsByNames(fields, fieldNames) {
|
|
602
|
+
if (fieldNames === void 0) {
|
|
603
|
+
return fields;
|
|
604
|
+
}
|
|
605
|
+
if (fieldNames.length === 0) {
|
|
606
|
+
return [];
|
|
607
|
+
}
|
|
608
|
+
return fields.filter((field) => fieldNames.includes(field.name));
|
|
609
|
+
}
|
|
610
|
+
function modelFieldsToFormFields(fields) {
|
|
611
|
+
return fields.map((field) => ({
|
|
612
|
+
name: field.name,
|
|
613
|
+
type: field.type,
|
|
614
|
+
label: field.label,
|
|
615
|
+
required: field.required,
|
|
616
|
+
options: field.options,
|
|
617
|
+
step: field.step
|
|
618
|
+
}));
|
|
619
|
+
}
|
|
620
|
+
function getFieldNamesFromFields(fields) {
|
|
621
|
+
return fields.map((field) => field.name);
|
|
622
|
+
}
|
|
623
|
+
function getFieldByName(fields, fieldName) {
|
|
624
|
+
return fields.find((field) => field.name === fieldName);
|
|
625
|
+
}
|
|
626
|
+
function getFieldLabelFromFields(fields, fieldName) {
|
|
627
|
+
const field = getFieldByName(fields, fieldName);
|
|
628
|
+
return field?.label || fieldName;
|
|
629
|
+
}
|
|
630
|
+
|
|
424
631
|
// src/features/base-feature.ts
|
|
425
632
|
var BaseFeature = class {
|
|
426
633
|
/** Feature 名称 */
|
|
@@ -434,15 +641,19 @@ var BaseFeature = class {
|
|
|
434
641
|
/** 是否允许点击遮罩区域关闭弹窗(默认 true,设置为 false 时只能通过关闭按钮关闭) */
|
|
435
642
|
closeOnBackdropClick;
|
|
436
643
|
/** Schema(可选,由子类在构造函数中设置) */
|
|
437
|
-
schema;
|
|
644
|
+
schema = z.object({});
|
|
438
645
|
/** 解析后的字段列表(可选,由子类在构造函数中设置) */
|
|
439
|
-
fields;
|
|
646
|
+
fields = [];
|
|
440
647
|
constructor(options) {
|
|
441
648
|
this.name = options.name;
|
|
442
649
|
this.type = options.type;
|
|
443
650
|
this.permission = options.permission;
|
|
444
651
|
this.dialogSize = options.dialogSize;
|
|
445
652
|
this.closeOnBackdropClick = options.closeOnBackdropClick;
|
|
653
|
+
this.schema = options.schema || z.object({});
|
|
654
|
+
if (this.schema) {
|
|
655
|
+
this.fields = parseSchemaToFields(this.schema);
|
|
656
|
+
}
|
|
446
657
|
}
|
|
447
658
|
/**
|
|
448
659
|
* 获取动态标题(默认实现:返回 PageMetadata 的 title)
|
|
@@ -474,26 +685,6 @@ var BaseFeature = class {
|
|
|
474
685
|
return await this.render?.(context) ?? null;
|
|
475
686
|
}
|
|
476
687
|
};
|
|
477
|
-
function getFieldValue(field, initialData) {
|
|
478
|
-
if (initialData && Object.prototype.hasOwnProperty.call(initialData, field.name)) {
|
|
479
|
-
const value = initialData[field.name];
|
|
480
|
-
if (value === null || value === void 0) {
|
|
481
|
-
return "";
|
|
482
|
-
}
|
|
483
|
-
if (typeof value === "object") {
|
|
484
|
-
if (value instanceof Date) {
|
|
485
|
-
return value.toISOString();
|
|
486
|
-
}
|
|
487
|
-
try {
|
|
488
|
-
return JSON.stringify(value);
|
|
489
|
-
} catch (e) {
|
|
490
|
-
return "";
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
return String(value);
|
|
494
|
-
}
|
|
495
|
-
return "";
|
|
496
|
-
}
|
|
497
688
|
function isJsonString(value) {
|
|
498
689
|
if (!value || typeof value !== "string") {
|
|
499
690
|
return false;
|
|
@@ -513,7 +704,9 @@ function formatJsonString(value) {
|
|
|
513
704
|
}
|
|
514
705
|
}
|
|
515
706
|
function renderFormField(field, initialData, formFieldRenderers) {
|
|
516
|
-
const value =
|
|
707
|
+
const value = initialData?.[field.name];
|
|
708
|
+
field.label || field.name;
|
|
709
|
+
const fieldSchema = field.schema;
|
|
517
710
|
const customRenderer = formFieldRenderers?.[field.name];
|
|
518
711
|
if (customRenderer) {
|
|
519
712
|
let parsedValue = null;
|
|
@@ -547,10 +740,10 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
547
740
|
/* @__PURE__ */ jsx("div", { children: customRenderer({
|
|
548
741
|
field,
|
|
549
742
|
value: parsedValue,
|
|
550
|
-
item: initialData,
|
|
551
|
-
name: field.name
|
|
552
|
-
|
|
553
|
-
|
|
743
|
+
item: initialData || {},
|
|
744
|
+
name: field.name,
|
|
745
|
+
label: field.label
|
|
746
|
+
}) })
|
|
554
747
|
]
|
|
555
748
|
},
|
|
556
749
|
field.name
|
|
@@ -558,41 +751,38 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
558
751
|
}
|
|
559
752
|
if (field.type === "checkbox") {
|
|
560
753
|
const isChecked = value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true";
|
|
561
|
-
return /* @__PURE__ */
|
|
754
|
+
return /* @__PURE__ */ jsx(
|
|
562
755
|
"div",
|
|
563
756
|
{
|
|
564
757
|
className: "space-y-2",
|
|
565
758
|
"data-testid": `field-${field.name}`,
|
|
566
|
-
children:
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
),
|
|
594
|
-
field.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 ml-8", children: field.description })
|
|
595
|
-
]
|
|
759
|
+
children: /* @__PURE__ */ jsxs(
|
|
760
|
+
"label",
|
|
761
|
+
{
|
|
762
|
+
htmlFor: field.name,
|
|
763
|
+
className: "flex items-center gap-3 cursor-pointer group py-2.5 px-3 rounded-lg hover:bg-gray-50 transition-colors border border-transparent hover:border-gray-200",
|
|
764
|
+
"data-testid": `label-${field.name}`,
|
|
765
|
+
children: [
|
|
766
|
+
/* @__PURE__ */ jsx(
|
|
767
|
+
"input",
|
|
768
|
+
{
|
|
769
|
+
type: "checkbox",
|
|
770
|
+
id: field.name,
|
|
771
|
+
name: field.name,
|
|
772
|
+
value: "true",
|
|
773
|
+
checked: isChecked,
|
|
774
|
+
required: field.required,
|
|
775
|
+
className: "w-5 h-5 text-blue-600 border-gray-300 rounded focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 cursor-pointer transition-all flex-shrink-0",
|
|
776
|
+
"data-testid": `input-${field.name}`
|
|
777
|
+
}
|
|
778
|
+
),
|
|
779
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-semibold text-gray-700 select-none flex-1", children: [
|
|
780
|
+
field.label,
|
|
781
|
+
field.required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
782
|
+
] })
|
|
783
|
+
]
|
|
784
|
+
}
|
|
785
|
+
)
|
|
596
786
|
},
|
|
597
787
|
field.name
|
|
598
788
|
);
|
|
@@ -622,7 +812,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
622
812
|
id: field.name,
|
|
623
813
|
name: field.name,
|
|
624
814
|
required: field.required,
|
|
625
|
-
placeholder:
|
|
815
|
+
placeholder: fieldSchema.description || (isJsonString(value) ? "JSON \u683C\u5F0F\u6570\u636E" : ""),
|
|
626
816
|
rows: isJsonString(value) ? Math.max(10, value.split("\n").length) : Math.max(5, Math.ceil(value.length / 100)),
|
|
627
817
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 resize-y font-mono text-sm",
|
|
628
818
|
"data-testid": `input-${field.name}`,
|
|
@@ -662,7 +852,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
662
852
|
id: field.name,
|
|
663
853
|
name: field.name,
|
|
664
854
|
required: field.required,
|
|
665
|
-
placeholder:
|
|
855
|
+
placeholder: fieldSchema.description || "",
|
|
666
856
|
step: field.type === "number" ? field.step ?? void 0 : void 0,
|
|
667
857
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200",
|
|
668
858
|
value,
|
|
@@ -670,7 +860,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
670
860
|
},
|
|
671
861
|
`${field.name}-${value}`
|
|
672
862
|
),
|
|
673
|
-
|
|
863
|
+
fieldSchema.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: fieldSchema.description })
|
|
674
864
|
]
|
|
675
865
|
},
|
|
676
866
|
field.name
|
|
@@ -678,7 +868,6 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
678
868
|
}
|
|
679
869
|
function FormPage(props) {
|
|
680
870
|
const {
|
|
681
|
-
fields,
|
|
682
871
|
groups,
|
|
683
872
|
submitUrl,
|
|
684
873
|
method = "post",
|
|
@@ -688,12 +877,6 @@ function FormPage(props) {
|
|
|
688
877
|
formFieldRenderers
|
|
689
878
|
} = props;
|
|
690
879
|
const finalFormId = formId || `form-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
691
|
-
if (process.env.NODE_ENV === "development" && initialData) {
|
|
692
|
-
const fieldNames = fields ? fields.map((f) => f.name).join(", ") : groups ? groups.map((g) => g.fields.map((f) => f.name).join(", ")).join(" | ") : "";
|
|
693
|
-
console.log(
|
|
694
|
-
`[FormPage] initialData: ${JSON.stringify(initialData)}, fields: ${fieldNames}`
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
880
|
return /* @__PURE__ */ jsxs(
|
|
698
881
|
"div",
|
|
699
882
|
{
|
|
@@ -741,7 +924,7 @@ function FormPage(props) {
|
|
|
741
924
|
]
|
|
742
925
|
}
|
|
743
926
|
),
|
|
744
|
-
groups && groups.length >
|
|
927
|
+
groups && groups.length > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
745
928
|
/* @__PURE__ */ jsx(
|
|
746
929
|
"div",
|
|
747
930
|
{
|
|
@@ -793,26 +976,25 @@ function FormPage(props) {
|
|
|
793
976
|
)) }) })
|
|
794
977
|
}
|
|
795
978
|
)
|
|
796
|
-
] }) : (
|
|
797
|
-
/*
|
|
979
|
+
] }) : groups && groups.length === 1 ? (
|
|
980
|
+
/* 平铺模式 - 单个分组时不显示 Tab */
|
|
798
981
|
/* @__PURE__ */ jsx(
|
|
799
982
|
"form",
|
|
800
983
|
{
|
|
801
984
|
id: finalFormId,
|
|
802
985
|
method: method === "put" ? "post" : method,
|
|
803
986
|
action: submitUrl,
|
|
804
|
-
"hx-
|
|
805
|
-
"hx-trigger": "click from:#form-submit-button",
|
|
806
|
-
...method === "put" ? { "hx-put": submitUrl } : {},
|
|
987
|
+
...method === "put" ? { "hx-put": submitUrl } : { "hx-post": submitUrl },
|
|
807
988
|
"hx-indicator": "#form-loading-indicator",
|
|
989
|
+
"hx-sync": "this:abort",
|
|
808
990
|
className: "space-y-6",
|
|
809
991
|
"data-testid": "form",
|
|
810
|
-
children:
|
|
992
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg border border-gray-200 shadow-sm", children: /* @__PURE__ */ jsx("div", { className: "p-6 space-y-6", children: groups[0].fields.map(
|
|
811
993
|
(field) => renderFormField(field, initialData, formFieldRenderers)
|
|
812
994
|
) }) })
|
|
813
995
|
}
|
|
814
996
|
)
|
|
815
|
-
)
|
|
997
|
+
) : null
|
|
816
998
|
]
|
|
817
999
|
}
|
|
818
1000
|
);
|
|
@@ -998,180 +1180,52 @@ function compressArrays(obj, arrayIndicesMap) {
|
|
|
998
1180
|
}
|
|
999
1181
|
|
|
1000
1182
|
// src/utils/form-data-processor.ts
|
|
1001
|
-
function
|
|
1002
|
-
return
|
|
1003
|
-
}
|
|
1004
|
-
function preprocessFormData(data, zodSchema) {
|
|
1005
|
-
if (!zodSchema) {
|
|
1006
|
-
return data;
|
|
1007
|
-
}
|
|
1008
|
-
const processed = { ...data };
|
|
1009
|
-
const def = zodSchema._zod?.def || zodSchema._def;
|
|
1010
|
-
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
1011
|
-
if (!shape || typeof shape !== "object") {
|
|
1012
|
-
return processed;
|
|
1013
|
-
}
|
|
1014
|
-
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1015
|
-
const value = processed[fieldName];
|
|
1016
|
-
if (value === void 0) {
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
if (value === null) {
|
|
1020
|
-
processed[fieldName] = void 0;
|
|
1021
|
-
continue;
|
|
1022
|
-
}
|
|
1023
|
-
if (value === "") {
|
|
1024
|
-
processed[fieldName] = void 0;
|
|
1025
|
-
continue;
|
|
1026
|
-
}
|
|
1027
|
-
const fieldDef = fieldSchema._zod?.def || fieldSchema._def;
|
|
1028
|
-
let typeName = fieldDef?.type;
|
|
1029
|
-
let actualSchema = fieldSchema;
|
|
1030
|
-
if (typeName === "optional") {
|
|
1031
|
-
const innerType = fieldDef?.innerType;
|
|
1032
|
-
if (innerType) {
|
|
1033
|
-
actualSchema = innerType;
|
|
1034
|
-
const innerDef = innerType._zod?.def || innerType._def;
|
|
1035
|
-
typeName = innerDef?.type;
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
if (typeName === "number" || typeName === "int") {
|
|
1039
|
-
if (typeof value === "string") {
|
|
1040
|
-
const trimmed = value.trim();
|
|
1041
|
-
if (trimmed !== "") {
|
|
1042
|
-
const numValue = Number(trimmed);
|
|
1043
|
-
if (!isNaN(numValue)) {
|
|
1044
|
-
processed[fieldName] = numValue;
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
} else if (typeof value === "number") {
|
|
1048
|
-
processed[fieldName] = value;
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
if (typeName === "boolean") {
|
|
1052
|
-
if (typeof value === "string") {
|
|
1053
|
-
const trimmed = value.trim().toLowerCase();
|
|
1054
|
-
if (trimmed === "true" || trimmed === "1" || trimmed === "on") {
|
|
1055
|
-
processed[fieldName] = true;
|
|
1056
|
-
} else if (trimmed === "false" || trimmed === "0" || trimmed === "off" || trimmed === "") {
|
|
1057
|
-
processed[fieldName] = false;
|
|
1058
|
-
}
|
|
1059
|
-
} else if (typeof value === "boolean") {
|
|
1060
|
-
processed[fieldName] = value;
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
if (typeName === "array") {
|
|
1064
|
-
if (Array.isArray(value)) {
|
|
1065
|
-
const arraySchema = actualSchema;
|
|
1066
|
-
const arrayDef = arraySchema._zod?.def || arraySchema._def;
|
|
1067
|
-
let elementType = arrayDef?.element;
|
|
1068
|
-
if (!elementType) {
|
|
1069
|
-
processed[fieldName] = value;
|
|
1070
|
-
} else {
|
|
1071
|
-
const elementDef = elementType._zod?.def || elementType._def;
|
|
1072
|
-
let elementTypeName = elementDef?.type;
|
|
1073
|
-
if (elementTypeName === "optional") {
|
|
1074
|
-
const innerElementType = elementDef?.innerType;
|
|
1075
|
-
if (innerElementType) {
|
|
1076
|
-
elementType = innerElementType;
|
|
1077
|
-
const innerElementDef = innerElementType._zod?.def || innerElementType._def;
|
|
1078
|
-
elementTypeName = innerElementDef?.type;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
processed[fieldName] = value.map((item) => {
|
|
1082
|
-
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
1083
|
-
if (elementTypeName === "object") {
|
|
1084
|
-
const processedItem = preprocessFormData(
|
|
1085
|
-
item,
|
|
1086
|
-
elementType
|
|
1087
|
-
);
|
|
1088
|
-
return { ...item, ...processedItem };
|
|
1089
|
-
}
|
|
1090
|
-
return item;
|
|
1091
|
-
}
|
|
1092
|
-
if (typeof item === "string") {
|
|
1093
|
-
return convertValueByType(item, elementType);
|
|
1094
|
-
}
|
|
1095
|
-
if (Array.isArray(item)) {
|
|
1096
|
-
const elementDef2 = elementType._zod?.def || elementType._def;
|
|
1097
|
-
const nestedInnerType = elementDef2?.element;
|
|
1098
|
-
if (nestedInnerType) {
|
|
1099
|
-
return item.map((subItem) => {
|
|
1100
|
-
if (typeof subItem === "string") {
|
|
1101
|
-
return convertValueByType(subItem, nestedInnerType);
|
|
1102
|
-
}
|
|
1103
|
-
if (typeof subItem === "object" && subItem !== null) {
|
|
1104
|
-
const subItemDef = nestedInnerType._zod?.def || nestedInnerType._def;
|
|
1105
|
-
if (subItemDef?.type === "object") {
|
|
1106
|
-
return preprocessFormData(
|
|
1107
|
-
subItem,
|
|
1108
|
-
nestedInnerType
|
|
1109
|
-
);
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
return subItem;
|
|
1113
|
-
});
|
|
1114
|
-
}
|
|
1115
|
-
return item;
|
|
1116
|
-
}
|
|
1117
|
-
return item;
|
|
1118
|
-
});
|
|
1119
|
-
}
|
|
1120
|
-
} else if (typeof value === "string") {
|
|
1121
|
-
const trimmed = value.trim();
|
|
1122
|
-
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1123
|
-
try {
|
|
1124
|
-
const parsed = JSON.parse(trimmed);
|
|
1125
|
-
processed[fieldName] = parsed;
|
|
1126
|
-
} catch (e) {
|
|
1127
|
-
}
|
|
1128
|
-
} else {
|
|
1129
|
-
const parts = trimmed.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
1130
|
-
processed[fieldName] = parts;
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
if (typeName === "object") {
|
|
1135
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1136
|
-
const objectSchema = actualSchema;
|
|
1137
|
-
processed[fieldName] = preprocessFormData(value, objectSchema);
|
|
1138
|
-
} else if (typeof value === "string" && value.trim() !== "") {
|
|
1139
|
-
try {
|
|
1140
|
-
const trimmed = value.trim();
|
|
1141
|
-
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1142
|
-
const parsed = JSON.parse(trimmed);
|
|
1143
|
-
processed[fieldName] = parsed;
|
|
1144
|
-
}
|
|
1145
|
-
} catch (e) {
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
if (typeName === "any" || typeName === "unknown") {
|
|
1150
|
-
if (typeof value === "string" && value.trim() !== "") {
|
|
1151
|
-
try {
|
|
1152
|
-
const trimmed = value.trim();
|
|
1153
|
-
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1154
|
-
const parsed = JSON.parse(trimmed);
|
|
1155
|
-
processed[fieldName] = parsed;
|
|
1156
|
-
}
|
|
1157
|
-
} catch (e) {
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
return processed;
|
|
1183
|
+
function getZodDef(schema) {
|
|
1184
|
+
return schema._zod?.def || schema._def;
|
|
1163
1185
|
}
|
|
1164
|
-
function
|
|
1165
|
-
|
|
1186
|
+
function resolveZodType(schema) {
|
|
1187
|
+
let currentSchema = schema;
|
|
1188
|
+
let isOptional = false;
|
|
1189
|
+
let def = getZodDef(currentSchema);
|
|
1166
1190
|
let typeName = def?.type;
|
|
1167
1191
|
if (typeName === "optional") {
|
|
1192
|
+
isOptional = true;
|
|
1168
1193
|
const innerType = def?.innerType;
|
|
1169
1194
|
if (innerType) {
|
|
1170
|
-
|
|
1171
|
-
|
|
1195
|
+
currentSchema = innerType;
|
|
1196
|
+
def = getZodDef(innerType);
|
|
1197
|
+
typeName = def?.type;
|
|
1172
1198
|
}
|
|
1173
1199
|
}
|
|
1174
|
-
if (typeName === "
|
|
1200
|
+
if (typeName === "default" || typeName === "ZodDefault") {
|
|
1201
|
+
const innerType = def?.innerType;
|
|
1202
|
+
if (innerType) {
|
|
1203
|
+
currentSchema = innerType;
|
|
1204
|
+
def = getZodDef(innerType);
|
|
1205
|
+
typeName = def?.type;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
while (typeName === "refinement" || typeName === "ZodEffects") {
|
|
1209
|
+
const innerType = def?.schema || def?.innerType;
|
|
1210
|
+
if (innerType) {
|
|
1211
|
+
currentSchema = innerType;
|
|
1212
|
+
def = getZodDef(innerType);
|
|
1213
|
+
typeName = def?.type;
|
|
1214
|
+
} else {
|
|
1215
|
+
break;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return {
|
|
1219
|
+
typeName: typeName || "any",
|
|
1220
|
+
actualSchema: currentSchema,
|
|
1221
|
+
isOptional
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
function parseNestedFormData2(flatData) {
|
|
1225
|
+
return parseNestedFormData(flatData);
|
|
1226
|
+
}
|
|
1227
|
+
function convertNumber(value) {
|
|
1228
|
+
if (typeof value === "string") {
|
|
1175
1229
|
const trimmed = value.trim();
|
|
1176
1230
|
if (trimmed !== "") {
|
|
1177
1231
|
const numValue = Number(trimmed);
|
|
@@ -1180,222 +1234,172 @@ function convertValueByType(value, schema) {
|
|
|
1180
1234
|
}
|
|
1181
1235
|
}
|
|
1182
1236
|
return value;
|
|
1183
|
-
}
|
|
1237
|
+
}
|
|
1238
|
+
if (typeof value === "number") {
|
|
1239
|
+
return value;
|
|
1240
|
+
}
|
|
1241
|
+
return value;
|
|
1242
|
+
}
|
|
1243
|
+
function convertBoolean(value) {
|
|
1244
|
+
if (typeof value === "string") {
|
|
1184
1245
|
const trimmed = value.trim().toLowerCase();
|
|
1185
1246
|
if (trimmed === "true" || trimmed === "1" || trimmed === "on") {
|
|
1186
1247
|
return true;
|
|
1187
|
-
}
|
|
1248
|
+
}
|
|
1249
|
+
if (trimmed === "false" || trimmed === "0" || trimmed === "off" || trimmed === "") {
|
|
1188
1250
|
return false;
|
|
1189
1251
|
}
|
|
1190
1252
|
return value;
|
|
1191
1253
|
}
|
|
1254
|
+
if (typeof value === "boolean") {
|
|
1255
|
+
return value;
|
|
1256
|
+
}
|
|
1192
1257
|
return value;
|
|
1193
1258
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1204
|
-
if (["id", "createdAt", "updatedAt"].includes(fieldName)) {
|
|
1205
|
-
continue;
|
|
1206
|
-
}
|
|
1207
|
-
const field = parseFieldSchema(fieldName, fieldSchema);
|
|
1208
|
-
if (field) {
|
|
1209
|
-
fields.push(field);
|
|
1259
|
+
function processArrayElement(item, elementType) {
|
|
1260
|
+
if (typeof item === "object" && item !== null && !Array.isArray(item)) {
|
|
1261
|
+
const { typeName } = resolveZodType(elementType);
|
|
1262
|
+
if (typeName === "object") {
|
|
1263
|
+
const processedItem = preprocessFormData(
|
|
1264
|
+
item,
|
|
1265
|
+
elementType
|
|
1266
|
+
);
|
|
1267
|
+
return { ...item, ...processedItem };
|
|
1210
1268
|
}
|
|
1269
|
+
return item;
|
|
1211
1270
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
function parseFieldSchema(fieldName, fieldSchema) {
|
|
1215
|
-
if (!fieldSchema || !fieldSchema._def) {
|
|
1216
|
-
return null;
|
|
1217
|
-
}
|
|
1218
|
-
const label = getFieldDescription(fieldSchema) || fieldName;
|
|
1219
|
-
const { type, required, options, innerSchema, step } = analyzeFieldType(fieldSchema);
|
|
1220
|
-
return {
|
|
1221
|
-
name: fieldName,
|
|
1222
|
-
label,
|
|
1223
|
-
type,
|
|
1224
|
-
required,
|
|
1225
|
-
options,
|
|
1226
|
-
step,
|
|
1227
|
-
schema: innerSchema || fieldSchema
|
|
1228
|
-
};
|
|
1229
|
-
}
|
|
1230
|
-
function getFieldDescription(schema) {
|
|
1231
|
-
if (schema?.description) {
|
|
1232
|
-
return schema.description;
|
|
1233
|
-
}
|
|
1234
|
-
const schemaDef = schema._def;
|
|
1235
|
-
if (schemaDef?.description) {
|
|
1236
|
-
return schemaDef.description;
|
|
1237
|
-
}
|
|
1238
|
-
if (schemaDef?.innerType) {
|
|
1239
|
-
return getFieldDescription(schemaDef.innerType);
|
|
1240
|
-
}
|
|
1241
|
-
return void 0;
|
|
1242
|
-
}
|
|
1243
|
-
function analyzeFieldType(schema) {
|
|
1244
|
-
const def = schema._def;
|
|
1245
|
-
const typeName = def?.type || def?.typeName;
|
|
1246
|
-
if (typeName === "optional" || typeName === "ZodOptional") {
|
|
1247
|
-
const inner = analyzeFieldType(def.innerType);
|
|
1248
|
-
return {
|
|
1249
|
-
...inner,
|
|
1250
|
-
required: false,
|
|
1251
|
-
innerSchema: def.innerType
|
|
1252
|
-
};
|
|
1253
|
-
}
|
|
1254
|
-
if (typeName === "nullable" || typeName === "ZodNullable") {
|
|
1255
|
-
const inner = analyzeFieldType(def.innerType);
|
|
1256
|
-
return {
|
|
1257
|
-
...inner,
|
|
1258
|
-
innerSchema: def.innerType
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
if (typeName === "enum" || typeName === "ZodEnum") {
|
|
1262
|
-
const options = extractEnumValues(def);
|
|
1263
|
-
return {
|
|
1264
|
-
type: "select",
|
|
1265
|
-
required: true,
|
|
1266
|
-
options,
|
|
1267
|
-
innerSchema: schema
|
|
1268
|
-
};
|
|
1269
|
-
}
|
|
1270
|
-
if (typeName === "nativeEnum" || typeName === "ZodNativeEnum") {
|
|
1271
|
-
const options = extractNativeEnumValues(def);
|
|
1272
|
-
return {
|
|
1273
|
-
type: "select",
|
|
1274
|
-
required: true,
|
|
1275
|
-
options,
|
|
1276
|
-
innerSchema: schema
|
|
1277
|
-
};
|
|
1271
|
+
if (typeof item === "string") {
|
|
1272
|
+
return convertValueByType(item, elementType);
|
|
1278
1273
|
}
|
|
1279
|
-
if (
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
(
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
fieldType = "textarea";
|
|
1274
|
+
if (Array.isArray(item)) {
|
|
1275
|
+
const elementDef = getZodDef(elementType);
|
|
1276
|
+
const nestedInnerType = elementDef?.element;
|
|
1277
|
+
if (nestedInnerType) {
|
|
1278
|
+
return item.map((subItem) => {
|
|
1279
|
+
if (typeof subItem === "string") {
|
|
1280
|
+
return convertValueByType(subItem, nestedInnerType);
|
|
1281
|
+
}
|
|
1282
|
+
if (typeof subItem === "object" && subItem !== null) {
|
|
1283
|
+
const subItemDef = getZodDef(nestedInnerType);
|
|
1284
|
+
if (subItemDef?.type === "object") {
|
|
1285
|
+
return preprocessFormData(
|
|
1286
|
+
subItem,
|
|
1287
|
+
nestedInnerType
|
|
1288
|
+
);
|
|
1295
1289
|
}
|
|
1296
1290
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
return {
|
|
1300
|
-
type: fieldType,
|
|
1301
|
-
required: true,
|
|
1302
|
-
innerSchema: schema
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
if (typeName === "number" || typeName === "ZodNumber") {
|
|
1306
|
-
let step = void 0;
|
|
1307
|
-
if (def?.checks) {
|
|
1308
|
-
const hasIntCheck = def.checks.some(
|
|
1309
|
-
(check) => check.isInt === true || check.format === "safeint" || check.def?.format === "safeint" || check.kind === "int" || check.constructor?.name === "ZodInt" || check._zod?.def?.check === "int" || check._zod?.def?.kind === "int"
|
|
1310
|
-
);
|
|
1311
|
-
if (!hasIntCheck) {
|
|
1312
|
-
step = "any";
|
|
1313
|
-
}
|
|
1314
|
-
} else {
|
|
1315
|
-
step = "any";
|
|
1291
|
+
return subItem;
|
|
1292
|
+
});
|
|
1316
1293
|
}
|
|
1317
|
-
return
|
|
1318
|
-
type: "number",
|
|
1319
|
-
required: true,
|
|
1320
|
-
innerSchema: schema,
|
|
1321
|
-
step
|
|
1322
|
-
};
|
|
1323
|
-
}
|
|
1324
|
-
if (typeName === "date" || typeName === "ZodDate") {
|
|
1325
|
-
return {
|
|
1326
|
-
type: "date",
|
|
1327
|
-
required: true,
|
|
1328
|
-
innerSchema: schema
|
|
1329
|
-
};
|
|
1330
|
-
}
|
|
1331
|
-
if (typeName === "boolean" || typeName === "ZodBoolean") {
|
|
1332
|
-
return {
|
|
1333
|
-
type: "checkbox",
|
|
1334
|
-
required: true,
|
|
1335
|
-
innerSchema: schema
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
return {
|
|
1339
|
-
type: "text",
|
|
1340
|
-
required: true,
|
|
1341
|
-
innerSchema: schema
|
|
1342
|
-
};
|
|
1343
|
-
}
|
|
1344
|
-
function extractEnumValues(def) {
|
|
1345
|
-
let values;
|
|
1346
|
-
if (def?.values && Array.isArray(def.values)) {
|
|
1347
|
-
values = def.values;
|
|
1348
|
-
} else if (def?.entries && typeof def.entries === "object") {
|
|
1349
|
-
values = Object.keys(def.entries);
|
|
1350
|
-
}
|
|
1351
|
-
if (values && values.length > 0) {
|
|
1352
|
-
return values.map((value) => ({
|
|
1353
|
-
value,
|
|
1354
|
-
label: String(value)
|
|
1355
|
-
}));
|
|
1356
|
-
}
|
|
1357
|
-
return void 0;
|
|
1358
|
-
}
|
|
1359
|
-
function extractNativeEnumValues(def) {
|
|
1360
|
-
const enumValues = def.values || def._def?.values || {};
|
|
1361
|
-
if (enumValues && typeof enumValues === "object") {
|
|
1362
|
-
return Object.entries(enumValues).filter(
|
|
1363
|
-
([_, value]) => typeof value === "string" || typeof value === "number"
|
|
1364
|
-
).map(([key, value]) => ({
|
|
1365
|
-
value,
|
|
1366
|
-
label: key
|
|
1367
|
-
}));
|
|
1294
|
+
return item;
|
|
1368
1295
|
}
|
|
1369
|
-
return
|
|
1296
|
+
return item;
|
|
1370
1297
|
}
|
|
1371
|
-
function
|
|
1372
|
-
if (
|
|
1373
|
-
|
|
1298
|
+
function processArrayType(value, actualSchema) {
|
|
1299
|
+
if (Array.isArray(value)) {
|
|
1300
|
+
const arrayDef = getZodDef(actualSchema);
|
|
1301
|
+
let elementType = arrayDef?.element;
|
|
1302
|
+
if (!elementType) {
|
|
1303
|
+
return value;
|
|
1304
|
+
}
|
|
1305
|
+
const { actualSchema: resolvedElementType } = resolveZodType(elementType);
|
|
1306
|
+
return value.map((item) => processArrayElement(item, resolvedElementType));
|
|
1374
1307
|
}
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1308
|
+
if (typeof value === "string") {
|
|
1309
|
+
const trimmed = value.trim();
|
|
1310
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1311
|
+
try {
|
|
1312
|
+
return JSON.parse(trimmed);
|
|
1313
|
+
} catch {
|
|
1314
|
+
}
|
|
1315
|
+
} else {
|
|
1316
|
+
return trimmed.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
1317
|
+
}
|
|
1377
1318
|
}
|
|
1378
|
-
return
|
|
1319
|
+
return value;
|
|
1379
1320
|
}
|
|
1380
|
-
function
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1321
|
+
function processObjectType(value, actualSchema) {
|
|
1322
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1323
|
+
return preprocessFormData(value, actualSchema);
|
|
1324
|
+
}
|
|
1325
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1326
|
+
const trimmed = value.trim();
|
|
1327
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
1328
|
+
try {
|
|
1329
|
+
return JSON.parse(trimmed);
|
|
1330
|
+
} catch {
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
return value;
|
|
1389
1335
|
}
|
|
1390
|
-
function
|
|
1391
|
-
|
|
1336
|
+
function processAnyType(value) {
|
|
1337
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
1338
|
+
const trimmed = value.trim();
|
|
1339
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1340
|
+
try {
|
|
1341
|
+
return JSON.parse(trimmed);
|
|
1342
|
+
} catch {
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
return value;
|
|
1392
1347
|
}
|
|
1393
|
-
function
|
|
1394
|
-
|
|
1348
|
+
function preprocessFormData(data, zodSchema) {
|
|
1349
|
+
if (!zodSchema) {
|
|
1350
|
+
return data;
|
|
1351
|
+
}
|
|
1352
|
+
const processed = { ...data };
|
|
1353
|
+
const def = getZodDef(zodSchema);
|
|
1354
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
1355
|
+
if (!shape || typeof shape !== "object") {
|
|
1356
|
+
return processed;
|
|
1357
|
+
}
|
|
1358
|
+
for (const [fieldName, fieldSchema] of Object.entries(shape)) {
|
|
1359
|
+
const value = processed[fieldName];
|
|
1360
|
+
if (value === void 0) {
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
if (value === null || value === "") {
|
|
1364
|
+
processed[fieldName] = void 0;
|
|
1365
|
+
continue;
|
|
1366
|
+
}
|
|
1367
|
+
const { typeName, actualSchema } = resolveZodType(
|
|
1368
|
+
fieldSchema
|
|
1369
|
+
);
|
|
1370
|
+
switch (typeName) {
|
|
1371
|
+
case "number":
|
|
1372
|
+
case "int":
|
|
1373
|
+
processed[fieldName] = convertNumber(value);
|
|
1374
|
+
break;
|
|
1375
|
+
case "boolean":
|
|
1376
|
+
processed[fieldName] = convertBoolean(value);
|
|
1377
|
+
break;
|
|
1378
|
+
case "array":
|
|
1379
|
+
processed[fieldName] = processArrayType(value, actualSchema);
|
|
1380
|
+
break;
|
|
1381
|
+
case "object":
|
|
1382
|
+
processed[fieldName] = processObjectType(value, actualSchema);
|
|
1383
|
+
break;
|
|
1384
|
+
case "any":
|
|
1385
|
+
case "unknown":
|
|
1386
|
+
processed[fieldName] = processAnyType(value);
|
|
1387
|
+
break;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
return processed;
|
|
1395
1391
|
}
|
|
1396
|
-
function
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1392
|
+
function convertValueByType(value, schema) {
|
|
1393
|
+
const { typeName } = resolveZodType(schema);
|
|
1394
|
+
switch (typeName) {
|
|
1395
|
+
case "number":
|
|
1396
|
+
case "int":
|
|
1397
|
+
return convertNumber(value);
|
|
1398
|
+
case "boolean":
|
|
1399
|
+
return convertBoolean(value);
|
|
1400
|
+
default:
|
|
1401
|
+
return value;
|
|
1402
|
+
}
|
|
1399
1403
|
}
|
|
1400
1404
|
var BaseFormFeature = class extends BaseFeature {
|
|
1401
1405
|
titleGetter;
|
|
@@ -1419,7 +1423,8 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1419
1423
|
type: options.type,
|
|
1420
1424
|
permission: options.permission,
|
|
1421
1425
|
dialogSize: options.dialogSize,
|
|
1422
|
-
closeOnBackdropClick: options.closeOnBackdropClick
|
|
1426
|
+
closeOnBackdropClick: options.closeOnBackdropClick,
|
|
1427
|
+
schema: options.schema
|
|
1423
1428
|
});
|
|
1424
1429
|
this.titleGetter = options.getTitle;
|
|
1425
1430
|
this.descriptionGetter = options.getDescription;
|
|
@@ -1432,7 +1437,7 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1432
1437
|
if (this.getFormAction() === "edit") {
|
|
1433
1438
|
try {
|
|
1434
1439
|
const initialData = await this.getInitialData(context);
|
|
1435
|
-
if (initialData
|
|
1440
|
+
if (initialData) {
|
|
1436
1441
|
return await this.titleGetter(context, initialData);
|
|
1437
1442
|
}
|
|
1438
1443
|
} catch (error) {
|
|
@@ -1452,7 +1457,7 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1452
1457
|
if (this.getFormAction() === "edit") {
|
|
1453
1458
|
try {
|
|
1454
1459
|
const initialData = await this.getInitialData(context);
|
|
1455
|
-
if (initialData
|
|
1460
|
+
if (initialData) {
|
|
1456
1461
|
return await this.descriptionGetter(context, initialData);
|
|
1457
1462
|
}
|
|
1458
1463
|
} catch (error) {
|
|
@@ -1476,17 +1481,13 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1476
1481
|
* 处理请求
|
|
1477
1482
|
*/
|
|
1478
1483
|
async handle(context) {
|
|
1479
|
-
|
|
1480
|
-
this.currentFormId = void 0;
|
|
1481
|
-
if (ctx.req.method === "GET") {
|
|
1484
|
+
if (context.ctx.req.method === "GET") {
|
|
1482
1485
|
return this.render(context);
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
throw new Error("Schema is required for form validation");
|
|
1489
|
-
}
|
|
1486
|
+
}
|
|
1487
|
+
const formData = this.preprocessFormData(context.body);
|
|
1488
|
+
const nestedData = parseNestedFormData2(formData);
|
|
1489
|
+
let data = this.preprocessFormData(nestedData);
|
|
1490
|
+
if (this.schema) {
|
|
1490
1491
|
const parseResult = this.schema.safeParse(data);
|
|
1491
1492
|
if (!parseResult.success) {
|
|
1492
1493
|
const issues = parseResult.error.issues || [];
|
|
@@ -1495,35 +1496,33 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1495
1496
|
const errorMessage = firstError.message;
|
|
1496
1497
|
const errorText = fieldName ? `${fieldName}: ${errorMessage}` : errorMessage;
|
|
1497
1498
|
context.sendError("\u9A8C\u8BC1\u5931\u8D25", errorText);
|
|
1498
|
-
return
|
|
1499
|
-
}
|
|
1500
|
-
const item = await this.handleSubmit(
|
|
1501
|
-
context,
|
|
1502
|
-
parseResult.data
|
|
1503
|
-
);
|
|
1504
|
-
if (!item) {
|
|
1505
|
-
context.sendError(
|
|
1506
|
-
this.getFormAction() === "create" ? "\u521B\u5EFA\u5931\u8D25" : "\u66F4\u65B0\u5931\u8D25",
|
|
1507
|
-
"\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
1508
|
-
);
|
|
1509
|
-
return this.render(context, originalData);
|
|
1499
|
+
return null;
|
|
1510
1500
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1501
|
+
data = parseResult.data;
|
|
1502
|
+
}
|
|
1503
|
+
const item = await this.handleSubmit(context, data);
|
|
1504
|
+
if (!item) {
|
|
1505
|
+
context.sendError(
|
|
1506
|
+
this.getFormAction() === "create" ? "\u521B\u5EFA\u5931\u8D25" : "\u66F4\u65B0\u5931\u8D25",
|
|
1507
|
+
"\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
1515
1508
|
);
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1509
|
+
return null;
|
|
1510
|
+
}
|
|
1511
|
+
const actionText = this.getFormAction() === "create" ? "\u521B\u5EFA" : "\u66F4\u65B0";
|
|
1512
|
+
context.sendSuccess(
|
|
1513
|
+
`${actionText}\u6210\u529F`,
|
|
1514
|
+
`${context.model.getMetadata().title}\u5DF2\u6210\u529F${actionText}`
|
|
1515
|
+
);
|
|
1516
|
+
if (context.isDialog) {
|
|
1517
|
+
context.setRefresh(true);
|
|
1518
|
+
if (context.redirectUrl) {
|
|
1519
|
+
context.redirectUrl = void 0;
|
|
1526
1520
|
}
|
|
1521
|
+
return null;
|
|
1522
|
+
} else {
|
|
1523
|
+
const redirectUrl = this.getSuccessRedirectUrl(context, item);
|
|
1524
|
+
context.redirect(redirectUrl);
|
|
1525
|
+
return null;
|
|
1527
1526
|
}
|
|
1528
1527
|
}
|
|
1529
1528
|
formFieldNames;
|
|
@@ -1532,15 +1531,9 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1532
1531
|
* 渲染表单页面
|
|
1533
1532
|
*/
|
|
1534
1533
|
async render(context, initialData) {
|
|
1535
|
-
let formData;
|
|
1536
|
-
if (
|
|
1537
|
-
|
|
1538
|
-
formData = initialData;
|
|
1539
|
-
} else {
|
|
1540
|
-
formData = await this.getInitialData(context);
|
|
1541
|
-
}
|
|
1542
|
-
} else {
|
|
1543
|
-
formData = initialData;
|
|
1534
|
+
let formData = initialData;
|
|
1535
|
+
if (!initialData) {
|
|
1536
|
+
formData = await this.getInitialData(context);
|
|
1544
1537
|
}
|
|
1545
1538
|
let submitUrl = this.getSubmitUrl(context);
|
|
1546
1539
|
if (context.isDialog) {
|
|
@@ -1550,12 +1543,9 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1550
1543
|
}
|
|
1551
1544
|
const method = this.getFormAction() === "create" ? "post" : "put";
|
|
1552
1545
|
const formId = this.getFormId(context);
|
|
1546
|
+
let formGroups = [];
|
|
1553
1547
|
if (this.groups && this.groups.length > 0) {
|
|
1554
|
-
|
|
1555
|
-
throw new Error("Schema is required when using groups");
|
|
1556
|
-
}
|
|
1557
|
-
const schema = this.schema;
|
|
1558
|
-
const groupSchemas = this.groups.map((group) => {
|
|
1548
|
+
formGroups = this.groups.map((group) => {
|
|
1559
1549
|
const pickObject = group.fields.reduce(
|
|
1560
1550
|
(acc, fieldName) => {
|
|
1561
1551
|
acc[fieldName] = true;
|
|
@@ -1565,39 +1555,27 @@ var BaseFormFeature = class extends BaseFeature {
|
|
|
1565
1555
|
);
|
|
1566
1556
|
return {
|
|
1567
1557
|
label: group.label,
|
|
1568
|
-
schema: schema.pick(pickObject),
|
|
1569
|
-
fields: group.fields
|
|
1558
|
+
schema: this.schema.pick(pickObject),
|
|
1559
|
+
fields: group.fields.map((name) => {
|
|
1560
|
+
const field = this.fields.find((f) => f.name === name);
|
|
1561
|
+
return field;
|
|
1562
|
+
})
|
|
1570
1563
|
};
|
|
1571
1564
|
});
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
const formFields = modelFieldsToFormFields(groupFields2);
|
|
1576
|
-
return {
|
|
1577
|
-
label,
|
|
1578
|
-
fields: formFields
|
|
1579
|
-
};
|
|
1580
|
-
}
|
|
1581
|
-
);
|
|
1582
|
-
return /* @__PURE__ */ jsx(
|
|
1583
|
-
FormPage,
|
|
1565
|
+
} else {
|
|
1566
|
+
const formFields = !this.formFieldNames ? this.fields : this.fields.filter((f) => this.formFieldNames?.includes(f.name));
|
|
1567
|
+
formGroups = [
|
|
1584
1568
|
{
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
initialData: formData,
|
|
1589
|
-
formId,
|
|
1590
|
-
isDialog: context.isDialog,
|
|
1591
|
-
formFieldRenderers: this.formFieldRenderers
|
|
1569
|
+
label: "\u9ED8\u8BA4\u5206\u7EC4",
|
|
1570
|
+
fields: formFields,
|
|
1571
|
+
schema: this.schema
|
|
1592
1572
|
}
|
|
1593
|
-
|
|
1573
|
+
];
|
|
1594
1574
|
}
|
|
1595
|
-
const filteredFields = this.formFieldNames ? filterFieldsByNames(this.fields || [], this.formFieldNames) : this.fields || [];
|
|
1596
|
-
const fields = modelFieldsToFormFields(filteredFields);
|
|
1597
1575
|
return /* @__PURE__ */ jsx(
|
|
1598
1576
|
FormPage,
|
|
1599
1577
|
{
|
|
1600
|
-
|
|
1578
|
+
groups: formGroups,
|
|
1601
1579
|
submitUrl,
|
|
1602
1580
|
method,
|
|
1603
1581
|
initialData: formData,
|
|
@@ -1798,90 +1776,259 @@ function Card(props) {
|
|
|
1798
1776
|
}
|
|
1799
1777
|
);
|
|
1800
1778
|
}
|
|
1801
|
-
function
|
|
1779
|
+
function renderEmptyValue() {
|
|
1780
|
+
return /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "-" });
|
|
1781
|
+
}
|
|
1782
|
+
function renderBoolean(value) {
|
|
1783
|
+
return /* @__PURE__ */ jsx(
|
|
1784
|
+
"span",
|
|
1785
|
+
{
|
|
1786
|
+
className: `px-2 py-1 rounded text-sm font-medium ${value ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-600"}`,
|
|
1787
|
+
children: value ? "\u662F" : "\u5426"
|
|
1788
|
+
}
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1791
|
+
function renderNumber(value) {
|
|
1792
|
+
return /* @__PURE__ */ jsx("span", { children: value.toLocaleString() });
|
|
1793
|
+
}
|
|
1794
|
+
function renderDate(value) {
|
|
1795
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1796
|
+
if (isNaN(date.getTime())) {
|
|
1797
|
+
return renderEmptyValue();
|
|
1798
|
+
}
|
|
1799
|
+
return /* @__PURE__ */ jsx("span", { children: date.toLocaleString() });
|
|
1800
|
+
}
|
|
1801
|
+
function renderSimpleArray(value) {
|
|
1802
|
+
if (value.length === 0) {
|
|
1803
|
+
return /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "\u6682\u65E0\u6570\u636E" });
|
|
1804
|
+
}
|
|
1805
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: value.map((item, index) => /* @__PURE__ */ jsx(
|
|
1806
|
+
"span",
|
|
1807
|
+
{
|
|
1808
|
+
className: "px-2 py-1 bg-gray-100 text-gray-700 rounded text-sm",
|
|
1809
|
+
children: String(item)
|
|
1810
|
+
},
|
|
1811
|
+
index
|
|
1812
|
+
)) });
|
|
1813
|
+
}
|
|
1814
|
+
function renderObjectArray(value) {
|
|
1815
|
+
return /* @__PURE__ */ jsxs("span", { className: "text-gray-600", children: [
|
|
1816
|
+
"\u5305\u542B ",
|
|
1817
|
+
value.length,
|
|
1818
|
+
" \u9879\uFF08\u5BF9\u8C61\u6570\u7EC4\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u81EA\u5B9A\u4E49\u6E32\u67D3\uFF09"
|
|
1819
|
+
] });
|
|
1820
|
+
}
|
|
1821
|
+
function renderObject(value) {
|
|
1822
|
+
return /* @__PURE__ */ jsx("pre", { className: "bg-gray-50 border border-gray-200 rounded p-3 text-xs overflow-x-auto", children: JSON.stringify(value, null, 2) });
|
|
1823
|
+
}
|
|
1824
|
+
function DetailFieldRenderer(props) {
|
|
1825
|
+
const { value, field } = props;
|
|
1802
1826
|
if (value === null || value === void 0) {
|
|
1803
|
-
return
|
|
1827
|
+
return renderEmptyValue();
|
|
1828
|
+
}
|
|
1829
|
+
if (field) {
|
|
1830
|
+
switch (field.type) {
|
|
1831
|
+
case "checkbox":
|
|
1832
|
+
if (typeof value === "boolean") {
|
|
1833
|
+
return renderBoolean(value);
|
|
1834
|
+
}
|
|
1835
|
+
if (value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true") {
|
|
1836
|
+
return renderBoolean(true);
|
|
1837
|
+
}
|
|
1838
|
+
if (value === "false" || value === "0" || String(value).toLowerCase() === "false") {
|
|
1839
|
+
return renderBoolean(false);
|
|
1840
|
+
}
|
|
1841
|
+
break;
|
|
1842
|
+
case "number":
|
|
1843
|
+
if (typeof value === "number") {
|
|
1844
|
+
return renderNumber(value);
|
|
1845
|
+
}
|
|
1846
|
+
const numValue = Number(value);
|
|
1847
|
+
if (!isNaN(numValue)) {
|
|
1848
|
+
return renderNumber(numValue);
|
|
1849
|
+
}
|
|
1850
|
+
break;
|
|
1851
|
+
case "date":
|
|
1852
|
+
if (value instanceof Date) {
|
|
1853
|
+
return renderDate(value);
|
|
1854
|
+
}
|
|
1855
|
+
if (typeof value === "string") {
|
|
1856
|
+
return renderDate(value);
|
|
1857
|
+
}
|
|
1858
|
+
break;
|
|
1859
|
+
case "email":
|
|
1860
|
+
case "url":
|
|
1861
|
+
if (typeof value === "string" && value.trim()) {
|
|
1862
|
+
return /* @__PURE__ */ jsx(
|
|
1863
|
+
"a",
|
|
1864
|
+
{
|
|
1865
|
+
href: value,
|
|
1866
|
+
target: "_blank",
|
|
1867
|
+
rel: "noopener noreferrer",
|
|
1868
|
+
className: "text-blue-600 hover:text-blue-800 hover:underline",
|
|
1869
|
+
children: value
|
|
1870
|
+
}
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
break;
|
|
1874
|
+
case "select":
|
|
1875
|
+
if (field.options && field.options.length > 0) {
|
|
1876
|
+
const option = field.options.find(
|
|
1877
|
+
(opt) => String(opt.value) === String(value)
|
|
1878
|
+
);
|
|
1879
|
+
if (option) {
|
|
1880
|
+
return /* @__PURE__ */ jsx("span", { children: option.label });
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
break;
|
|
1884
|
+
}
|
|
1804
1885
|
}
|
|
1805
1886
|
if (Array.isArray(value)) {
|
|
1806
1887
|
if (value.length === 0) {
|
|
1807
|
-
return
|
|
1888
|
+
return renderEmptyValue();
|
|
1808
1889
|
}
|
|
1809
1890
|
if (value.length > 0 && typeof value[0] === "object" && value[0] !== null) {
|
|
1810
|
-
return
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1891
|
+
return renderObjectArray(value);
|
|
1892
|
+
}
|
|
1893
|
+
return renderSimpleArray(value);
|
|
1894
|
+
}
|
|
1895
|
+
if (typeof value === "object") {
|
|
1896
|
+
if (value instanceof Date) {
|
|
1897
|
+
return renderDate(value);
|
|
1898
|
+
}
|
|
1899
|
+
return renderObject(value);
|
|
1900
|
+
}
|
|
1901
|
+
if (typeof value === "boolean") {
|
|
1902
|
+
return renderBoolean(value);
|
|
1903
|
+
}
|
|
1904
|
+
if (typeof value === "number") {
|
|
1905
|
+
return renderNumber(value);
|
|
1906
|
+
}
|
|
1907
|
+
return /* @__PURE__ */ jsx("span", { children: String(value) });
|
|
1908
|
+
}
|
|
1909
|
+
function ColumnRenderer(value, field) {
|
|
1910
|
+
if (value === null || value === void 0) {
|
|
1911
|
+
return renderEmptyValue();
|
|
1912
|
+
}
|
|
1913
|
+
if (field) {
|
|
1914
|
+
switch (field.type) {
|
|
1915
|
+
case "checkbox":
|
|
1916
|
+
if (typeof value === "boolean") {
|
|
1917
|
+
return renderBoolean(value);
|
|
1918
|
+
}
|
|
1919
|
+
if (value === "true" || value === "1" || value === "on" || String(value).toLowerCase() === "true") {
|
|
1920
|
+
return renderBoolean(true);
|
|
1921
|
+
}
|
|
1922
|
+
if (value === "false" || value === "0" || String(value).toLowerCase() === "false") {
|
|
1923
|
+
return renderBoolean(false);
|
|
1924
|
+
}
|
|
1925
|
+
break;
|
|
1926
|
+
case "number":
|
|
1927
|
+
if (typeof value === "number") {
|
|
1928
|
+
return renderNumber(value);
|
|
1929
|
+
}
|
|
1930
|
+
const numValue = Number(value);
|
|
1931
|
+
if (!isNaN(numValue)) {
|
|
1932
|
+
return renderNumber(numValue);
|
|
1933
|
+
}
|
|
1934
|
+
break;
|
|
1935
|
+
case "date":
|
|
1936
|
+
if (value instanceof Date) {
|
|
1937
|
+
return renderDate(value);
|
|
1938
|
+
}
|
|
1939
|
+
if (typeof value === "string") {
|
|
1940
|
+
return renderDate(value);
|
|
1941
|
+
}
|
|
1942
|
+
break;
|
|
1943
|
+
case "email":
|
|
1944
|
+
case "url":
|
|
1945
|
+
if (typeof value === "string" && value.trim()) {
|
|
1946
|
+
return /* @__PURE__ */ jsx("span", { className: "text-blue-600", children: value });
|
|
1947
|
+
}
|
|
1948
|
+
break;
|
|
1949
|
+
case "select":
|
|
1950
|
+
if (field.options && field.options.length > 0) {
|
|
1951
|
+
const option = field.options.find(
|
|
1952
|
+
(opt) => String(opt.value) === String(value)
|
|
1953
|
+
);
|
|
1954
|
+
if (option) {
|
|
1955
|
+
return /* @__PURE__ */ jsx("span", { children: option.label });
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
break;
|
|
1959
|
+
case "textarea":
|
|
1960
|
+
if (typeof value === "string" && value.length > 50) {
|
|
1961
|
+
return /* @__PURE__ */ jsxs("span", { title: value, className: "truncate max-w-xs block", children: [
|
|
1962
|
+
value.substring(0, 50),
|
|
1963
|
+
"..."
|
|
1964
|
+
] });
|
|
1965
|
+
}
|
|
1966
|
+
break;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
if (Array.isArray(value)) {
|
|
1970
|
+
if (value.length === 0) {
|
|
1971
|
+
return renderEmptyValue();
|
|
1972
|
+
}
|
|
1973
|
+
if (value.length > 0 && typeof value[0] !== "object") {
|
|
1974
|
+
const displayItems = value.slice(0, 3).map(String);
|
|
1975
|
+
const remaining = value.length - 3;
|
|
1976
|
+
return /* @__PURE__ */ jsxs("span", { className: "text-sm", children: [
|
|
1977
|
+
displayItems.join(", "),
|
|
1978
|
+
remaining > 0 && ` +${remaining}`
|
|
1814
1979
|
] });
|
|
1815
1980
|
}
|
|
1816
|
-
return /* @__PURE__ */
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
children: String(item)
|
|
1821
|
-
},
|
|
1822
|
-
index
|
|
1823
|
-
)) });
|
|
1981
|
+
return /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-600", children: [
|
|
1982
|
+
value.length,
|
|
1983
|
+
" \u9879"
|
|
1984
|
+
] });
|
|
1824
1985
|
}
|
|
1825
1986
|
if (typeof value === "object") {
|
|
1826
1987
|
if (value instanceof Date) {
|
|
1827
|
-
return
|
|
1988
|
+
return renderDate(value);
|
|
1828
1989
|
}
|
|
1829
|
-
return /* @__PURE__ */ jsx("
|
|
1990
|
+
return /* @__PURE__ */ jsx("span", { className: "text-gray-500 text-sm", children: "[\u5BF9\u8C61]" });
|
|
1830
1991
|
}
|
|
1831
1992
|
if (typeof value === "boolean") {
|
|
1832
|
-
return
|
|
1833
|
-
"span",
|
|
1834
|
-
{
|
|
1835
|
-
className: `px-2 py-1 rounded text-sm font-medium ${value ? "bg-green-100 text-green-800" : "bg-gray-100 text-gray-600"}`,
|
|
1836
|
-
children: value ? "\u662F" : "\u5426"
|
|
1837
|
-
}
|
|
1838
|
-
);
|
|
1993
|
+
return renderBoolean(value);
|
|
1839
1994
|
}
|
|
1840
1995
|
if (typeof value === "number") {
|
|
1841
|
-
return
|
|
1996
|
+
return renderNumber(value);
|
|
1997
|
+
}
|
|
1998
|
+
if (typeof value === "string" && value.length > 50) {
|
|
1999
|
+
return /* @__PURE__ */ jsxs("span", { title: value, className: "truncate max-w-xs block", children: [
|
|
2000
|
+
value.substring(0, 50),
|
|
2001
|
+
"..."
|
|
2002
|
+
] });
|
|
1842
2003
|
}
|
|
1843
2004
|
return /* @__PURE__ */ jsx("span", { children: String(value) });
|
|
1844
2005
|
}
|
|
1845
|
-
function
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
} else {
|
|
1854
|
-
content = rendered;
|
|
2006
|
+
function getFieldLabel(fieldName, fieldLabels) {
|
|
2007
|
+
return fieldLabels?.[fieldName] || fieldName;
|
|
2008
|
+
}
|
|
2009
|
+
function getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions) {
|
|
2010
|
+
if (fieldRenderers) {
|
|
2011
|
+
const customRenderer = fieldRenderers[fieldName];
|
|
2012
|
+
if (customRenderer) {
|
|
2013
|
+
return customRenderer;
|
|
1855
2014
|
}
|
|
1856
|
-
} else {
|
|
1857
|
-
content = renderDefaultValue(value);
|
|
1858
2015
|
}
|
|
1859
|
-
return
|
|
1860
|
-
|
|
1861
|
-
{
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
"dd",
|
|
1873
|
-
{
|
|
1874
|
-
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
1875
|
-
children: /* @__PURE__ */ jsx("div", { className: "min-w-0", children: content })
|
|
1876
|
-
}
|
|
1877
|
-
)
|
|
1878
|
-
]
|
|
1879
|
-
},
|
|
1880
|
-
field.key
|
|
1881
|
-
);
|
|
2016
|
+
return ((props) => {
|
|
2017
|
+
const field = fieldDefinitions?.[fieldName];
|
|
2018
|
+
return DetailFieldRenderer({ ...props, field });
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
function renderFieldValue(rendered) {
|
|
2022
|
+
if (rendered === null || rendered === void 0) {
|
|
2023
|
+
return /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: "-" });
|
|
2024
|
+
}
|
|
2025
|
+
if (typeof rendered === "string" || typeof rendered === "number" || typeof rendered === "boolean") {
|
|
2026
|
+
return /* @__PURE__ */ jsx("span", { children: String(rendered) });
|
|
2027
|
+
}
|
|
2028
|
+
return rendered;
|
|
1882
2029
|
}
|
|
1883
2030
|
function DetailPage(props) {
|
|
1884
|
-
const { item, fields, groups } = props;
|
|
2031
|
+
const { item, fields, groups, fieldLabels, fieldDefinitions, fieldRenderers } = props;
|
|
1885
2032
|
if (groups && groups.length > 0) {
|
|
1886
2033
|
return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: groups.map((group, groupIndex) => /* @__PURE__ */ jsx(
|
|
1887
2034
|
Card,
|
|
@@ -1890,18 +2037,78 @@ function DetailPage(props) {
|
|
|
1890
2037
|
shadow: true,
|
|
1891
2038
|
bordered: true,
|
|
1892
2039
|
noPadding: true,
|
|
1893
|
-
children: /* @__PURE__ */ jsx("dl", { className: "divide-y divide-gray-100", children: group.fields.map((
|
|
1894
|
-
const value = group.values[
|
|
1895
|
-
|
|
2040
|
+
children: /* @__PURE__ */ jsx("dl", { className: "divide-y divide-gray-100", children: group.fields.map((fieldName) => {
|
|
2041
|
+
const value = group.values[fieldName];
|
|
2042
|
+
const label = getFieldLabel(fieldName, fieldLabels);
|
|
2043
|
+
const Renderer = getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions);
|
|
2044
|
+
const rendered = Renderer({
|
|
2045
|
+
value,
|
|
2046
|
+
item,
|
|
2047
|
+
name: fieldName,
|
|
2048
|
+
label
|
|
2049
|
+
});
|
|
2050
|
+
return /* @__PURE__ */ jsxs(
|
|
2051
|
+
"div",
|
|
2052
|
+
{
|
|
2053
|
+
className: "\r\n px-4 py-4 sm:px-6 sm:py-5\r\n flex flex-col\r\n hover:bg-gray-50/50 transition-colors duration-150\r\n group\r\n gap-1.5\r\n ",
|
|
2054
|
+
children: [
|
|
2055
|
+
/* @__PURE__ */ jsx(
|
|
2056
|
+
"dt",
|
|
2057
|
+
{
|
|
2058
|
+
className: "\r\n text-xs sm:text-sm font-semibold text-gray-600 sm:text-gray-700\r\n flex items-start\r\n leading-tight sm:leading-5\r\n tracking-wide\r\n ",
|
|
2059
|
+
children: /* @__PURE__ */ jsx("span", { className: "min-w-0 uppercase sm:normal-case", children: label })
|
|
2060
|
+
}
|
|
2061
|
+
),
|
|
2062
|
+
/* @__PURE__ */ jsx(
|
|
2063
|
+
"dd",
|
|
2064
|
+
{
|
|
2065
|
+
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
2066
|
+
children: /* @__PURE__ */ jsx("div", { className: "min-w-0", children: renderFieldValue(rendered) })
|
|
2067
|
+
}
|
|
2068
|
+
)
|
|
2069
|
+
]
|
|
2070
|
+
},
|
|
2071
|
+
fieldName
|
|
2072
|
+
);
|
|
1896
2073
|
}) })
|
|
1897
2074
|
},
|
|
1898
2075
|
groupIndex
|
|
1899
2076
|
)) });
|
|
1900
2077
|
}
|
|
1901
2078
|
if (fields && fields.length > 0) {
|
|
1902
|
-
return /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden", children: /* @__PURE__ */ jsx("dl", { className: "divide-y divide-gray-100", children: fields.map((
|
|
1903
|
-
const value = item[
|
|
1904
|
-
|
|
2079
|
+
return /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden", children: /* @__PURE__ */ jsx("dl", { className: "divide-y divide-gray-100", children: fields.map((fieldName) => {
|
|
2080
|
+
const value = item[fieldName];
|
|
2081
|
+
const label = getFieldLabel(fieldName, fieldLabels);
|
|
2082
|
+
const Renderer = getFieldRenderer(fieldName, fieldRenderers, fieldDefinitions);
|
|
2083
|
+
const rendered = Renderer({
|
|
2084
|
+
value,
|
|
2085
|
+
item,
|
|
2086
|
+
name: fieldName,
|
|
2087
|
+
label
|
|
2088
|
+
});
|
|
2089
|
+
return /* @__PURE__ */ jsxs(
|
|
2090
|
+
"div",
|
|
2091
|
+
{
|
|
2092
|
+
className: "\r\n px-4 py-4 sm:px-6 sm:py-5\r\n flex flex-col\r\n hover:bg-gray-50/50 transition-colors duration-150\r\n group\r\n gap-1.5\r\n ",
|
|
2093
|
+
children: [
|
|
2094
|
+
/* @__PURE__ */ jsx(
|
|
2095
|
+
"dt",
|
|
2096
|
+
{
|
|
2097
|
+
className: "\r\n text-xs sm:text-sm font-semibold text-gray-600 sm:text-gray-700\r\n flex items-start\r\n leading-tight sm:leading-5\r\n tracking-wide\r\n ",
|
|
2098
|
+
children: /* @__PURE__ */ jsx("span", { className: "min-w-0 uppercase sm:normal-case", children: label })
|
|
2099
|
+
}
|
|
2100
|
+
),
|
|
2101
|
+
/* @__PURE__ */ jsx(
|
|
2102
|
+
"dd",
|
|
2103
|
+
{
|
|
2104
|
+
className: "\r\n text-sm sm:text-base text-gray-900\r\n break-words\r\n leading-relaxed\r\n min-w-0\r\n ",
|
|
2105
|
+
children: /* @__PURE__ */ jsx("div", { className: "min-w-0", children: renderFieldValue(rendered) })
|
|
2106
|
+
}
|
|
2107
|
+
)
|
|
2108
|
+
]
|
|
2109
|
+
},
|
|
2110
|
+
fieldName
|
|
2111
|
+
);
|
|
1905
2112
|
}) }) });
|
|
1906
2113
|
}
|
|
1907
2114
|
return null;
|
|
@@ -1978,28 +2185,35 @@ var DefaultDetailFeature = class extends BaseFeature {
|
|
|
1978
2185
|
fields: group.fields
|
|
1979
2186
|
};
|
|
1980
2187
|
});
|
|
1981
|
-
const
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2188
|
+
const fieldLabels2 = {};
|
|
2189
|
+
const fieldDefinitions2 = {};
|
|
2190
|
+
(this.fields || []).forEach((field) => {
|
|
2191
|
+
fieldLabels2[field.name] = field.label;
|
|
2192
|
+
fieldDefinitions2[field.name] = field;
|
|
2193
|
+
});
|
|
2194
|
+
const groupFields = groupSchemas.map(({ label, fields: fieldNames }) => {
|
|
2195
|
+
return {
|
|
2196
|
+
label,
|
|
2197
|
+
fields: fieldNames,
|
|
2198
|
+
values: fieldNames.reduce(
|
|
2199
|
+
(acc, fieldName) => {
|
|
2200
|
+
acc[fieldName] = item[fieldName];
|
|
2201
|
+
return acc;
|
|
2202
|
+
},
|
|
2203
|
+
{}
|
|
2204
|
+
)
|
|
2205
|
+
};
|
|
2206
|
+
});
|
|
2207
|
+
return /* @__PURE__ */ jsx(
|
|
2208
|
+
DetailPage,
|
|
2209
|
+
{
|
|
2210
|
+
item,
|
|
2211
|
+
groups: groupFields,
|
|
2212
|
+
fieldLabels: fieldLabels2,
|
|
2213
|
+
fieldDefinitions: fieldDefinitions2,
|
|
2214
|
+
fieldRenderers: this.fieldRenderers
|
|
2000
2215
|
}
|
|
2001
2216
|
);
|
|
2002
|
-
return /* @__PURE__ */ jsx(DetailPage, { item, groups: groupFields });
|
|
2003
2217
|
}
|
|
2004
2218
|
const detailFields = this.detailFieldNames ? filterFieldsByNames(this.fields || [], this.detailFieldNames) : this.fields || [];
|
|
2005
2219
|
if (this.detailFieldNames) {
|
|
@@ -2017,13 +2231,25 @@ var DefaultDetailFeature = class extends BaseFeature {
|
|
|
2017
2231
|
}
|
|
2018
2232
|
}
|
|
2019
2233
|
const detailFieldNames = getFieldNamesFromFields(detailFields);
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2234
|
+
const fieldLabels = {};
|
|
2235
|
+
const fieldDefinitions = {};
|
|
2236
|
+
detailFieldNames.forEach((fieldName) => {
|
|
2237
|
+
fieldLabels[fieldName] = getFieldLabelFromFields(this.fields || [], fieldName) || fieldName;
|
|
2238
|
+
const field = detailFields.find((f) => f.name === fieldName);
|
|
2239
|
+
if (field) {
|
|
2240
|
+
fieldDefinitions[fieldName] = field;
|
|
2241
|
+
}
|
|
2242
|
+
});
|
|
2243
|
+
return /* @__PURE__ */ jsx(
|
|
2244
|
+
DetailPage,
|
|
2245
|
+
{
|
|
2246
|
+
item,
|
|
2247
|
+
fields: detailFieldNames,
|
|
2248
|
+
fieldLabels,
|
|
2249
|
+
fieldDefinitions,
|
|
2250
|
+
fieldRenderers: this.fieldRenderers
|
|
2251
|
+
}
|
|
2252
|
+
);
|
|
2027
2253
|
}
|
|
2028
2254
|
async getActions(context) {
|
|
2029
2255
|
const id = context.params.id;
|
|
@@ -2082,6 +2308,7 @@ var DefaultEditFeature = class extends BaseFormFeature {
|
|
|
2082
2308
|
permission: options.permission || `${options.permissionPrefix}.edit`,
|
|
2083
2309
|
dialogSize: options.dialogSize,
|
|
2084
2310
|
closeOnBackdropClick: options.closeOnBackdropClick,
|
|
2311
|
+
schema: options.schema,
|
|
2085
2312
|
getTitle: options.getTitle ? (context, item) => {
|
|
2086
2313
|
if (item) {
|
|
2087
2314
|
return options.getTitle(item, context);
|
|
@@ -2095,8 +2322,6 @@ var DefaultEditFeature = class extends BaseFormFeature {
|
|
|
2095
2322
|
return void 0;
|
|
2096
2323
|
} : void 0
|
|
2097
2324
|
});
|
|
2098
|
-
this.schema = options.schema;
|
|
2099
|
-
this.fields = parseSchemaToFields(options.schema);
|
|
2100
2325
|
this.getItem = options.getItem;
|
|
2101
2326
|
this.updateItem = options.updateItem;
|
|
2102
2327
|
this.formFieldNames = options.formFieldNames;
|
|
@@ -2169,7 +2394,7 @@ function FilterForm(props) {
|
|
|
2169
2394
|
listPath,
|
|
2170
2395
|
currentFilters = {}
|
|
2171
2396
|
} = props;
|
|
2172
|
-
function
|
|
2397
|
+
function getFieldValue(field) {
|
|
2173
2398
|
const value = currentFilters[field.name];
|
|
2174
2399
|
if (value === null || value === void 0 || value === "") {
|
|
2175
2400
|
return "";
|
|
@@ -2206,10 +2431,10 @@ function FilterForm(props) {
|
|
|
2206
2431
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2207
2432
|
"data-testid": `filter-select-${field.name}`,
|
|
2208
2433
|
children: [
|
|
2209
|
-
/* @__PURE__ */ jsx("option", { value: "", selected:
|
|
2434
|
+
/* @__PURE__ */ jsx("option", { value: "", selected: getFieldValue(field) === "", children: "\u5168\u90E8" }),
|
|
2210
2435
|
field.options?.map((option) => {
|
|
2211
2436
|
const optionValue = String(option.value);
|
|
2212
|
-
const isSelected =
|
|
2437
|
+
const isSelected = getFieldValue(field) === optionValue;
|
|
2213
2438
|
return /* @__PURE__ */ jsx("option", { value: optionValue, selected: isSelected, children: option.label }, optionValue);
|
|
2214
2439
|
})
|
|
2215
2440
|
]
|
|
@@ -2220,7 +2445,7 @@ function FilterForm(props) {
|
|
|
2220
2445
|
id: `filter-${field.name}`,
|
|
2221
2446
|
name: field.name,
|
|
2222
2447
|
type: "date",
|
|
2223
|
-
value:
|
|
2448
|
+
value: getFieldValue(field),
|
|
2224
2449
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2225
2450
|
"data-testid": `filter-input-${field.name}`
|
|
2226
2451
|
}
|
|
@@ -2230,7 +2455,7 @@ function FilterForm(props) {
|
|
|
2230
2455
|
id: `filter-${field.name}`,
|
|
2231
2456
|
name: field.name,
|
|
2232
2457
|
type: "number",
|
|
2233
|
-
value:
|
|
2458
|
+
value: getFieldValue(field),
|
|
2234
2459
|
placeholder: field.placeholder || `\u8BF7\u8F93\u5165${field.label}`,
|
|
2235
2460
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2236
2461
|
"data-testid": `filter-input-${field.name}`
|
|
@@ -2241,7 +2466,7 @@ function FilterForm(props) {
|
|
|
2241
2466
|
id: `filter-${field.name}`,
|
|
2242
2467
|
name: field.name,
|
|
2243
2468
|
type: "text",
|
|
2244
|
-
value:
|
|
2469
|
+
value: getFieldValue(field),
|
|
2245
2470
|
placeholder: field.placeholder || `\u8BF7\u8F93\u5165${field.label}`,
|
|
2246
2471
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 bg-white",
|
|
2247
2472
|
"data-testid": `filter-input-${field.name}`
|
|
@@ -2739,12 +2964,26 @@ var DefaultListFeature = class extends BaseFeature {
|
|
|
2739
2964
|
const listFields = this.listFieldNames ? filterFieldsByNames(this.fields || [], this.listFieldNames) : this.fields || [];
|
|
2740
2965
|
const listFieldNames = getFieldNamesFromFields(listFields);
|
|
2741
2966
|
const filterFields = this.filterSchema ? modelFieldsToFormFields(parseSchemaToFields(this.filterSchema)) : [];
|
|
2742
|
-
const columns = listFieldNames.map((fieldName) =>
|
|
2743
|
-
|
|
2744
|
-
label
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2967
|
+
const columns = listFieldNames.map((fieldName) => {
|
|
2968
|
+
const field = this.fields?.find((f) => f.name === fieldName);
|
|
2969
|
+
const label = getFieldLabelFromFields(this.fields || [], fieldName);
|
|
2970
|
+
const customRenderer = this.columnRenderers?.[fieldName];
|
|
2971
|
+
return {
|
|
2972
|
+
key: fieldName,
|
|
2973
|
+
label,
|
|
2974
|
+
render: (value, item) => {
|
|
2975
|
+
if (customRenderer) {
|
|
2976
|
+
return customRenderer({
|
|
2977
|
+
value,
|
|
2978
|
+
item,
|
|
2979
|
+
name: fieldName,
|
|
2980
|
+
label
|
|
2981
|
+
});
|
|
2982
|
+
}
|
|
2983
|
+
return ColumnRenderer(value, field);
|
|
2984
|
+
}
|
|
2985
|
+
};
|
|
2986
|
+
});
|
|
2748
2987
|
const model = context.model;
|
|
2749
2988
|
const prefix = context.prefix || "";
|
|
2750
2989
|
const basePath = `${prefix}/${model.modelName}`;
|
|
@@ -3807,11 +4046,11 @@ function SortableList(props) {
|
|
|
3807
4046
|
function StringArrayEditor(props) {
|
|
3808
4047
|
const {
|
|
3809
4048
|
value,
|
|
3810
|
-
name,
|
|
3811
4049
|
placeholder = "\u8BF7\u8F93\u5165\u5185\u5BB9",
|
|
3812
4050
|
allowEmpty = false,
|
|
3813
4051
|
rows = 1
|
|
3814
4052
|
} = props;
|
|
4053
|
+
const name = props.name;
|
|
3815
4054
|
const initialItems = value || [];
|
|
3816
4055
|
const initialDataJson = JSON.stringify({
|
|
3817
4056
|
items: initialItems.map((item) => item || ""),
|
|
@@ -3978,7 +4217,8 @@ function ArrayItem({
|
|
|
3978
4217
|
] });
|
|
3979
4218
|
}
|
|
3980
4219
|
function TagsEditor(props) {
|
|
3981
|
-
const { value,
|
|
4220
|
+
const { value, placeholder = "\u8F93\u5165\u6807\u7B7E\u540E\u6309\u56DE\u8F66\u6DFB\u52A0" } = props;
|
|
4221
|
+
const name = props.name;
|
|
3982
4222
|
const initialTags = value || [];
|
|
3983
4223
|
const initialDataJson = JSON.stringify({
|
|
3984
4224
|
tags: initialTags.map((tag) => tag || ""),
|
|
@@ -4262,7 +4502,7 @@ function ObjectEditor(props) {
|
|
|
4262
4502
|
const initialValueJson = JSON.stringify(initialObject);
|
|
4263
4503
|
JSON.stringify(fields.map((f) => f.name));
|
|
4264
4504
|
const generateField = (field) => {
|
|
4265
|
-
const fieldId = `${name}-${field.name}`;
|
|
4505
|
+
const fieldId = `${String(name)}-${field.name}`;
|
|
4266
4506
|
const fieldValue = initialObject[field.name];
|
|
4267
4507
|
const fieldValueStr = fieldValue === void 0 || fieldValue === null ? "" : typeof fieldValue === "object" ? JSON.stringify(fieldValue) : String(fieldValue);
|
|
4268
4508
|
const requiredAttr = field.required ? "required" : "";
|
|
@@ -5331,4 +5571,4 @@ var HtmxAdminPlugin = class {
|
|
|
5331
5571
|
}
|
|
5332
5572
|
};
|
|
5333
5573
|
|
|
5334
|
-
export { BaseFeature, CustomFeature, DefaultCreateFeature, DefaultDeleteFeature, DefaultDetailFeature, DefaultEditFeature, DefaultListFeature, Dialog, ErrorAlert, HtmxAdminPlugin, LoadingBar, ObjectEditor, PageModel, SortableList, StringArrayEditor, TagsEditor, checkUserPermission, getUserInfo, modelNameToPath, parseListParams };
|
|
5574
|
+
export { BaseFeature, BaseFormFeature, Breadcrumb, Button, Card, ColumnRenderer, CustomFeature, DefaultCreateFeature, DefaultDeleteFeature, DefaultDetailFeature, DefaultEditFeature, DefaultListFeature, DetailFieldRenderer, Dialog, EmptyState, ErrorAlert, FilterForm, Header, HtmxAdminPlugin, LoadingBar, ObjectEditor, PageModel, Pagination, PermissionDeniedContent, PermissionDeniedPage, SortableList, StringArrayEditor, Table, TagsEditor, checkUserPermission, getUserInfo, modelNameToPath, parseListParams };
|