@schemx/vue 1.0.1 → 1.1.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.
Files changed (76) hide show
  1. package/README.md +491 -326
  2. package/dist/analyze.html +1 -1
  3. package/dist/bridge/formBridge.d.ts +4 -4
  4. package/dist/bridge/formBridge.d.ts.map +1 -1
  5. package/dist/bridge/formInstance.d.ts +4 -3
  6. package/dist/bridge/formInstance.d.ts.map +1 -1
  7. package/dist/bridge/index.d.ts +1 -2
  8. package/dist/bridge/index.d.ts.map +1 -1
  9. package/dist/bridge/types.d.ts +4 -6
  10. package/dist/bridge/types.d.ts.map +1 -1
  11. package/dist/components/Col/index.d.ts +29 -6
  12. package/dist/components/Col/index.d.ts.map +1 -1
  13. package/dist/components/ConfigProvider/index.d.ts +32 -5
  14. package/dist/components/ConfigProvider/index.d.ts.map +1 -1
  15. package/dist/components/Dynamic/index.d.ts +19 -15
  16. package/dist/components/Dynamic/index.d.ts.map +1 -1
  17. package/dist/components/Field/index.d.ts.map +1 -1
  18. package/dist/components/Field/slot.d.ts +2 -1
  19. package/dist/components/Field/slot.d.ts.map +1 -1
  20. package/dist/components/Group/index.d.ts +23 -4
  21. package/dist/components/Group/index.d.ts.map +1 -1
  22. package/dist/components/Icon/index.d.ts +29 -0
  23. package/dist/components/Icon/index.d.ts.map +1 -0
  24. package/dist/components/Row/index.d.ts +30 -0
  25. package/dist/components/Row/index.d.ts.map +1 -0
  26. package/dist/components/SchemaList/index.d.ts +8 -8
  27. package/dist/components/SchemaList/index.d.ts.map +1 -1
  28. package/dist/config/defaultVueSchemaConfig.d.ts +25 -3
  29. package/dist/config/defaultVueSchemaConfig.d.ts.map +1 -1
  30. package/dist/config/index.d.ts +0 -4
  31. package/dist/config/index.d.ts.map +1 -1
  32. package/dist/config/vueConfig.d.ts +10 -6
  33. package/dist/config/vueConfig.d.ts.map +1 -1
  34. package/dist/context/configProviderContext.d.ts +56 -5
  35. package/dist/context/configProviderContext.d.ts.map +1 -1
  36. package/dist/context/formContext.d.ts +127 -36
  37. package/dist/context/formContext.d.ts.map +1 -1
  38. package/dist/context/index.d.ts +2 -2
  39. package/dist/context/index.d.ts.map +1 -1
  40. package/dist/form.d.ts +2 -2
  41. package/dist/form.d.ts.map +1 -1
  42. package/dist/hooks/index.d.ts +2 -4
  43. package/dist/hooks/index.d.ts.map +1 -1
  44. package/dist/hooks/useDictionary.d.ts +1 -1
  45. package/dist/hooks/useForm.d.ts +4 -16
  46. package/dist/hooks/useForm.d.ts.map +1 -1
  47. package/dist/index.cjs +1 -1
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.ts +5 -5
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.mjs +554 -287
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/style.css +1 -1
  54. package/dist/types/definition.d.ts +116 -21
  55. package/dist/types/definition.d.ts.map +1 -1
  56. package/dist/types/field.d.ts +4 -27
  57. package/dist/types/field.d.ts.map +1 -1
  58. package/dist/types/form.d.ts +41 -6
  59. package/dist/types/form.d.ts.map +1 -1
  60. package/dist/types/icon.d.ts +15 -0
  61. package/dist/types/icon.d.ts.map +1 -0
  62. package/dist/types/index.d.ts +2 -0
  63. package/dist/types/index.d.ts.map +1 -1
  64. package/dist/types/layout.d.ts +73 -22
  65. package/dist/types/layout.d.ts.map +1 -1
  66. package/dist/utils/index.d.ts +4 -0
  67. package/dist/utils/index.d.ts.map +1 -1
  68. package/dist/utils/layout.d.ts +17 -0
  69. package/dist/utils/layout.d.ts.map +1 -0
  70. package/dist/utils/rendererProvider.d.ts +10 -3
  71. package/dist/utils/rendererProvider.d.ts.map +1 -1
  72. package/package.json +2 -2
  73. package/dist/config/appConfig.d.ts +0 -29
  74. package/dist/config/appConfig.d.ts.map +0 -1
  75. package/dist/utils/colProvider.d.ts +0 -22
  76. package/dist/utils/colProvider.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./style.css";
2
- import { shallowRef, computed, getCurrentScope, onScopeDispose, provide, inject, getCurrentInstance, onUnmounted, ref, onMounted, watchEffect, watch, readonly, createVNode, h, createTextVNode, defineComponent, mergeProps, useAttrs, openBlock, createElementBlock, unref, renderSlot, createCommentVNode, createStaticVNode, Fragment, toDisplayString, markRaw, toRaw, isVNode, useSlots, normalizeClass, normalizeStyle, createSlots, renderList, withCtx, normalizeProps, guardReactiveProps, createBlock, nextTick } from "vue";
3
- import { isViewGroupSchema, isViewDynamicSchema, mergeSchemxConfig, createPresetRuleRegistry, createForm, createField, createWatch, isSchemxViewFieldSchema, defaultSchemxConfigKeys, getGlobalSchemxConfig, resolveSchemxConfig, isSchemxSchemas } from "@schemx/core";
2
+ import { shallowRef, computed, getCurrentScope, onScopeDispose, provide, inject, getCurrentInstance, onUnmounted, ref, onMounted, watchEffect, watch, readonly, defineComponent, markRaw, toRaw, h, useAttrs, createVNode, Fragment, mergeProps, isVNode, openBlock, createElementBlock, unref, renderSlot, createCommentVNode, createStaticVNode, createTextVNode, toDisplayString, useSlots, normalizeClass, normalizeStyle, createSlots, renderList, withCtx, normalizeProps, guardReactiveProps, createBlock, nextTick } from "vue";
3
+ import { isViewGroupSchema, isViewDynamicSchema, mergeConfig, createPresetRuleRegistry, getGlobalSchemxConfig, createForm, createField, createWatch, isSchemxViewFieldSchema, defaultSchemxConfigKeys, resolveSchemxConfig, isSchemxSchemas } from "@schemx/core";
4
4
  export * from "@schemx/core";
5
5
  import classnames from "classnames";
6
6
  import { createFormStateAdapter, createRendererRegistry } from "@schemx/core/adapter";
@@ -339,76 +339,67 @@ function createVueFormRuntime(core) {
339
339
  };
340
340
  return runtime;
341
341
  }
342
- const SCHEMX_FORM_CONTEXT_KEY = Symbol("schemx:form-context");
343
- const LEGACY_FORM_INSTANCE_KEY = Symbol("schemx:instance");
344
- const LEGACY_FORM_CONFIG_KEY = Symbol("schemx:form-config");
345
- function provideFormContext(options) {
346
- const runtime = useVueFormRuntime(options.form);
347
- const context = {
348
- form: runtime.instance,
349
- get schemaConfig() {
350
- return options.schemaConfig;
351
- }
352
- };
353
- provide(
354
- SCHEMX_FORM_CONTEXT_KEY,
355
- context
356
- );
357
- return runtime.instance;
342
+ const SCHEMX_FORM_INSTANCE_KEY = Symbol("schemx:instance");
343
+ const SCHEMX_FORM_CONFIG_KEY = Symbol("schemx:form-config");
344
+ function provideFormContext(context) {
345
+ const form = useVueFormRuntime(context.form).instance;
346
+ provide(SCHEMX_FORM_INSTANCE_KEY, form);
347
+ provide(SCHEMX_FORM_CONFIG_KEY, context);
348
+ return form;
358
349
  }
359
350
  function useFormContextValue() {
360
- const context = inject(SCHEMX_FORM_CONTEXT_KEY, null);
351
+ const context = useOptionalFormContextValue();
361
352
  if (context) {
362
353
  return context;
363
354
  }
364
- const form = inject(LEGACY_FORM_INSTANCE_KEY, null);
365
- const config = inject(LEGACY_FORM_CONFIG_KEY, null);
355
+ throw new Error(
356
+ "[schemx] useFormContextValue() must be called inside a <SchemxForm> descendant. Ensure provideFormContext({ form, schemaConfig }) is called synchronously during setup()."
357
+ );
358
+ }
359
+ function useOptionalFormContextValue() {
360
+ const form = inject(SCHEMX_FORM_INSTANCE_KEY, null);
361
+ const config = inject(SCHEMX_FORM_CONFIG_KEY, null);
366
362
  if (form && config) {
367
363
  return {
368
364
  form,
369
- schemaConfig: config.schemaConfig
365
+ get schemaConfig() {
366
+ return config.schemaConfig;
367
+ },
368
+ get iconComponent() {
369
+ return config.iconComponent;
370
+ },
371
+ get rowComponent() {
372
+ return config.rowComponent;
373
+ },
374
+ get colComponent() {
375
+ return config.colComponent;
376
+ }
370
377
  };
371
378
  }
372
- throw new Error(
373
- "[schemx] useFormContextValue() must be called inside a <SchemxForm> descendant. Ensure provideFormContext({ form, schemaConfig }) is called synchronously during setup()."
374
- );
379
+ return void 0;
375
380
  }
376
381
  function createFormContext(instance) {
377
- const runtime = useVueFormRuntime(instance);
378
- provide(
379
- LEGACY_FORM_INSTANCE_KEY,
380
- runtime.instance
381
- );
382
- return runtime.instance;
382
+ const form = useVueFormRuntime(instance).instance;
383
+ provide(SCHEMX_FORM_INSTANCE_KEY, form);
384
+ return form;
383
385
  }
384
386
  function useFormContext() {
385
- const context = inject(SCHEMX_FORM_CONTEXT_KEY, null);
386
- if (context) {
387
- return context.form;
388
- }
389
- const instance = inject(
390
- LEGACY_FORM_INSTANCE_KEY,
391
- null
392
- );
387
+ const instance = inject(SCHEMX_FORM_INSTANCE_KEY, null);
393
388
  if (!instance) {
394
389
  throw new Error(
395
- "[schemx] useFormContext() must be called inside a <SchemxForm> descendant. Ensure createFormContext(form) is called synchronously during setup()."
390
+ "[schemx] useFormContext() must be called inside a <SchemxForm> descendant. Ensure provideFormContext({ form, schemaConfig }) is called synchronously during setup()."
396
391
  );
397
392
  }
398
393
  return instance;
399
394
  }
400
395
  function createFormConfigContext(props) {
401
- provide(LEGACY_FORM_CONFIG_KEY, props);
396
+ provide(SCHEMX_FORM_CONFIG_KEY, props);
402
397
  }
403
398
  function useFormConfigContext() {
404
- const context = inject(SCHEMX_FORM_CONTEXT_KEY, null);
405
- if (context) {
406
- return context;
407
- }
408
- const config = inject(LEGACY_FORM_CONFIG_KEY, null);
399
+ const config = inject(SCHEMX_FORM_CONFIG_KEY, null);
409
400
  if (!config) {
410
401
  throw new Error(
411
- "[schemx] useFormConfigContext() must be called inside a <SchemxForm> descendant. Ensure createFormConfigContext(props) is called synchronously during setup()."
402
+ "[schemx] useFormConfigContext() must be called inside a <SchemxForm> descendant. Ensure provideFormContext({ form, schemaConfig }) is called synchronously during setup()."
412
403
  );
413
404
  }
414
405
  return config;
@@ -432,43 +423,14 @@ function useFieldContext() {
432
423
  const SCHEMX_CONFIG_PROVIDER_KEY = Symbol(
433
424
  "schemx:config-provider"
434
425
  );
435
- function createConfigProviderContext(config) {
436
- const parentConfig = inject(SCHEMX_CONFIG_PROVIDER_KEY, void 0);
437
- const mergedConfig = computed(() => {
438
- const mergedCoreConfig = mergeSchemxConfig(config.value, (parentConfig == null ? void 0 : parentConfig.value) ?? {});
439
- return {
440
- ...mergedCoreConfig,
441
- colComponent: config.value.colComponent ?? (parentConfig == null ? void 0 : parentConfig.value.colComponent)
442
- };
443
- });
444
- provide(SCHEMX_CONFIG_PROVIDER_KEY, mergedConfig);
445
- }
446
- function useConfigProviderContext() {
447
- var _a;
448
- return (_a = useConfigProviderContextRef()) == null ? void 0 : _a.value;
449
- }
450
- function useConfigProviderContextRef() {
451
- if (getCurrentInstance() === null) {
452
- return void 0;
453
- }
454
- return inject(SCHEMX_CONFIG_PROVIDER_KEY, void 0);
455
- }
456
- const SCHEMX_APP_CONFIG_KEY = Symbol("schemx:app-config");
457
- const EMPTY_SCHEMX_CONFIG = Object.freeze({
458
- schemaConfig: Object.freeze({}),
459
- validatorAdapters: Object.freeze([])
460
- });
461
426
  function normalizeSchemxAppConfig(config) {
462
427
  const schemaConfig = Object.freeze({ ...config.schemaConfig ?? {} });
463
428
  const validatorAdapters = Object.freeze([...config.validatorAdapters ?? []]);
464
429
  return Object.freeze({
430
+ ...config,
465
431
  schemaConfig,
466
432
  rendererProps: normalizeRendererProps(config.rendererProps),
467
- validatorAdapters,
468
- defaultRendererType: config.defaultRendererType,
469
- rendererRegistry: config.rendererRegistry,
470
- presetRuleRegistry: config.presetRuleRegistry,
471
- colComponent: config.colComponent
433
+ validatorAdapters
472
434
  });
473
435
  }
474
436
  function normalizeRendererProps(source) {
@@ -482,23 +444,50 @@ function normalizeRendererProps(source) {
482
444
  }
483
445
  function provideSchemxAppConfig(app, config = {}) {
484
446
  const normalizedConfig = normalizeSchemxAppConfig(config);
485
- app.provide(SCHEMX_APP_CONFIG_KEY, normalizedConfig);
447
+ app.provide(
448
+ SCHEMX_CONFIG_PROVIDER_KEY,
449
+ computed(() => normalizedConfig)
450
+ );
486
451
  }
487
- function getSchemxAppConfig() {
452
+ function createConfigProviderContext(config) {
453
+ const parentConfig = inject(SCHEMX_CONFIG_PROVIDER_KEY, void 0);
454
+ const mergedConfig = computed(() => {
455
+ const mergedCoreConfig = mergeConfig(config.value, (parentConfig == null ? void 0 : parentConfig.value) ?? {});
456
+ const parentRow = parentConfig == null ? void 0 : parentConfig.value.row;
457
+ const localRow = config.value.row;
458
+ return {
459
+ ...mergedCoreConfig,
460
+ colComponent: config.value.colComponent ?? (parentConfig == null ? void 0 : parentConfig.value.colComponent),
461
+ rowComponent: config.value.rowComponent ?? (parentConfig == null ? void 0 : parentConfig.value.rowComponent),
462
+ iconComponent: config.value.iconComponent ?? (parentConfig == null ? void 0 : parentConfig.value.iconComponent),
463
+ row: localRow === void 0 ? parentRow : {
464
+ ...parentRow,
465
+ ...localRow
466
+ }
467
+ };
468
+ });
469
+ provide(SCHEMX_CONFIG_PROVIDER_KEY, mergedConfig);
470
+ }
471
+ function useConfigProviderContext() {
472
+ var _a;
473
+ return (_a = useConfigProviderContextRef()) == null ? void 0 : _a.value;
474
+ }
475
+ function useConfigProviderContextRef() {
488
476
  if (getCurrentInstance() === null) {
489
- return EMPTY_SCHEMX_CONFIG;
477
+ return void 0;
490
478
  }
491
- return inject(SCHEMX_APP_CONFIG_KEY, EMPTY_SCHEMX_CONFIG);
479
+ return inject(SCHEMX_CONFIG_PROVIDER_KEY, void 0);
492
480
  }
493
481
  const presetRuleRegistry = createPresetRuleRegistry();
494
482
  const rendererRegistry = createRendererRegistry("input");
495
483
  function mergeVueSchemxConfig(localConfig, fallbackConfig = {}) {
496
484
  const providerConfig = useConfigProviderContext();
497
- return mergeSchemxConfig(
485
+ const coreConfig = getGlobalSchemxConfig();
486
+ return mergeConfig(
498
487
  localConfig,
499
488
  providerConfig ?? {},
500
- getSchemxAppConfig(),
501
489
  fallbackConfig,
490
+ coreConfig,
502
491
  {
503
492
  rendererRegistry,
504
493
  presetRuleRegistry
@@ -513,7 +502,7 @@ const defaultVueSchemaConfig = Object.freeze({
513
502
  /**
514
503
  * 表单级标签对齐默认值。
515
504
  */
516
- labelAlign: "left",
505
+ labelAlign: "right",
517
506
  /**
518
507
  * 表单级标签位置默认值。
519
508
  */
@@ -525,7 +514,11 @@ const defaultVueSchemaConfig = Object.freeze({
525
514
  /**
526
515
  * 表单级内容对齐默认值。
527
516
  */
528
- contentAlign: "right",
517
+ contentAlign: "left",
518
+ /**
519
+ * 表单级校验错误对齐默认值。
520
+ */
521
+ errorAlign: "left",
529
522
  /**
530
523
  * 表单级标签冒号默认值。
531
524
  */
@@ -533,13 +526,30 @@ const defaultVueSchemaConfig = Object.freeze({
533
526
  /**
534
527
  * 表单级必填标记默认值。
535
528
  */
536
- showRequiredMark: void 0
529
+ showRequiredMark: void 0,
530
+ /**
531
+ * 字段默认 Col 配置。
532
+ */
533
+ col: { span: 24 },
534
+ /**
535
+ * 旧版字段默认布局配置。
536
+ *
537
+ * @deprecated 请改用 {@link import("../types/layout").SchemxColConfig} 与 `col` 字段。
538
+ */
539
+ layout: { span: 24 },
540
+ /**
541
+ * 是否在 field schema 后显示底部边框。
542
+ */
543
+ bordered: true
537
544
  });
538
545
  const defaultVueSchemaConfigKeys = Object.keys(
539
546
  defaultVueSchemaConfig
540
547
  );
541
548
  function useForm(options = {}) {
542
- const configuredOptions = mergeVueSchemxConfig(getUseFormSchemxConfig(options));
549
+ const configuredOptions = mergeVueSchemxConfig(
550
+ getUseFormSchemxConfig(options),
551
+ {}
552
+ );
543
553
  const mergedOptions = {
544
554
  ...options,
545
555
  ...configuredOptions
@@ -929,6 +939,146 @@ function hasPositionItemInSection(list, startIndex, step) {
929
939
  }
930
940
  return false;
931
941
  }
942
+ function normalizeSchemxGutter(gutter) {
943
+ if (gutter === void 0) {
944
+ return [0, 0, 0, 0];
945
+ }
946
+ if (typeof gutter === "number") {
947
+ return [gutter, gutter, gutter, gutter];
948
+ }
949
+ if (gutter.length === 2) {
950
+ const [vertical, horizontal] = gutter;
951
+ return [vertical, horizontal, vertical, horizontal];
952
+ }
953
+ return gutter;
954
+ }
955
+ const Col = /* @__PURE__ */ defineComponent({
956
+ name: "SchemxCol",
957
+ inheritAttrs: false,
958
+ props: {
959
+ col: {
960
+ type: Object,
961
+ required: false,
962
+ default: void 0
963
+ },
964
+ /**
965
+ * @deprecated 请在 Form 或 ConfigProvider 的 `colComponent` 中配置实现,见 {@link import("@schemx/core").SchemxConfig}。
966
+ */
967
+ component: {
968
+ type: [Object, Function],
969
+ required: false,
970
+ default: void 0
971
+ },
972
+ /**
973
+ * @deprecated 请改用 {@link import("../../types/layout").SchemxColProps.col}。
974
+ */
975
+ layout: {
976
+ type: Object,
977
+ required: false,
978
+ default: void 0
979
+ }
980
+ },
981
+ /**
982
+ * 根据 Col 配置和当前 Form Context 创建列组件。
983
+ *
984
+ * @param props - 列配置及兼容期的组件覆写属性。
985
+ * @param setupContext - 父级透传属性与默认插槽。
986
+ */
987
+ setup(props, setupContext) {
988
+ const {
989
+ attrs,
990
+ slots
991
+ } = setupContext;
992
+ const formContext = useOptionalFormContextValue();
993
+ const resolvedComponent = computed(() => {
994
+ const component = props.component ?? (formContext == null ? void 0 : formContext.colComponent);
995
+ return component ? markRaw(toRaw(component)) : void 0;
996
+ });
997
+ return () => {
998
+ const component = resolvedComponent.value;
999
+ const col = props.col ?? props.layout ?? {};
1000
+ const {
1001
+ block,
1002
+ span: configuredSpan,
1003
+ offset: configuredOffset,
1004
+ ...extensionProps
1005
+ } = col;
1006
+ const span = block ? 24 : configuredSpan ?? 24;
1007
+ const offset = block ? 0 : configuredOffset ?? 0;
1008
+ const {
1009
+ class: attrsClass,
1010
+ style: attrsStyle,
1011
+ ...restAttrs
1012
+ } = attrs;
1013
+ if (!component) {
1014
+ const width = `${span / 24 * 100}%`;
1015
+ const marginLeft = `${offset / 24 * 100}%`;
1016
+ return h("div", {
1017
+ ...restAttrs,
1018
+ class: ["schemx-col", attrsClass],
1019
+ style: [attrsStyle, {
1020
+ flex: `0 0 ${width}`,
1021
+ maxWidth: width,
1022
+ marginLeft,
1023
+ paddingTop: "var(--schemx-gutter-top, 0px)",
1024
+ paddingRight: "var(--schemx-gutter-right, 0px)",
1025
+ paddingBottom: "var(--schemx-gutter-bottom, 0px)",
1026
+ paddingLeft: "var(--schemx-gutter-left, 0px)"
1027
+ }]
1028
+ }, slots);
1029
+ }
1030
+ return h(component, {
1031
+ ...extensionProps,
1032
+ ...restAttrs,
1033
+ class: ["schemx-col", attrsClass],
1034
+ style: attrsStyle,
1035
+ span,
1036
+ offset
1037
+ }, slots);
1038
+ };
1039
+ }
1040
+ });
1041
+ const Col$1 = Col;
1042
+ const Icon = /* @__PURE__ */ defineComponent({
1043
+ name: "SchemxIcon",
1044
+ inheritAttrs: false,
1045
+ props: {
1046
+ icon: {
1047
+ type: [String, Object, Function],
1048
+ required: true
1049
+ },
1050
+ component: {
1051
+ type: [Object, Function],
1052
+ required: false,
1053
+ default: void 0
1054
+ }
1055
+ },
1056
+ /**
1057
+ * 渲染直接传入的组件,或将字符串名称交给 Icon Adapter。
1058
+ *
1059
+ * @param props - 当前图标值及可选的 Adapter 组件。
1060
+ */
1061
+ setup(props) {
1062
+ const attrs = useAttrs();
1063
+ return () => {
1064
+ if (typeof props.icon !== "string") {
1065
+ return h(markRaw(toRaw(props.icon)), attrs);
1066
+ }
1067
+ const adapter = props.component;
1068
+ if (adapter === void 0) {
1069
+ return h("span", {
1070
+ ...attrs,
1071
+ class: ["schemx-icon-text", attrs.class]
1072
+ }, props.icon);
1073
+ }
1074
+ return h(markRaw(toRaw(adapter)), {
1075
+ ...attrs,
1076
+ icon: props.icon
1077
+ });
1078
+ };
1079
+ }
1080
+ });
1081
+ const Icon$1 = Icon;
932
1082
  function createFieldSlotRenderers(options) {
933
1083
  const {
934
1084
  schemaRef,
@@ -938,15 +1088,19 @@ function createFieldSlotRenderers(options) {
938
1088
  componentProps,
939
1089
  slots
940
1090
  } = options;
941
- const renderRequired = () => {
942
- const showRequiredMark = schemaRef.value.showRequiredMark ?? Boolean(schemaRef.value.required);
943
- if (!showRequiredMark || schemaRef.value.disabled || schemaRef.value.readonly) {
944
- return null;
1091
+ const labelWidth = computed(() => {
1092
+ if (schemaRef.value.labelPosition === "top") {
1093
+ return "100%";
945
1094
  }
946
- return createVNode("span", {
947
- "class": "schemx-field__required"
948
- }, [createTextVNode("*")]);
949
- };
1095
+ const width = schemaRef.value.labelWidth ?? "auto";
1096
+ return /^\d+(?:\.\d+)?$/.test(String(width)) ? `${width}px` : width;
1097
+ });
1098
+ const labelAlign = computed(() => {
1099
+ if (schemaRef.value.labelPosition === "top") {
1100
+ return "left";
1101
+ }
1102
+ return schemaRef.value.labelAlign;
1103
+ });
950
1104
  const createSlotProps = (additionalProps = {}) => {
951
1105
  return {
952
1106
  schema: schemaRef.value,
@@ -963,56 +1117,63 @@ function createFieldSlotRenderers(options) {
963
1117
  };
964
1118
  const renderLabel = () => {
965
1119
  const labelSlot = resolveSlot(slots, `${normalizeNameKey(schemaRef.value.name)}Label`);
966
- if (labelSlot) {
967
- return labelSlot(createSlotProps());
968
- }
969
- const labelAlign = schemaRef.value.labelAlign || formContext.schemaConfig.labelAlign;
970
- const labelWidth = schemaRef.value.labelWidth || formContext.schemaConfig.labelWidth;
971
1120
  const colon = schemaRef.value.colon ?? formContext.schemaConfig.colon;
1121
+ const showRequiredMark = (schemaRef.value.showRequiredMark ?? Boolean(schemaRef.value.required)) && !schemaRef.value.disabled && !schemaRef.value.readonly;
972
1122
  return createVNode("label", {
973
1123
  "class": "schemx-field__label",
974
1124
  "style": {
975
- width: labelWidth,
976
- textAlign: labelAlign
1125
+ width: labelWidth.value,
1126
+ textAlign: labelAlign.value,
1127
+ marginLeft: labelAlign.value === "right" ? "auto" : ""
977
1128
  }
978
- }, [renderRequired(), schemaRef.value.labelIcon ? createVNode("span", {
1129
+ }, [labelSlot ? labelSlot(createSlotProps()) : createVNode(Fragment, null, [schemaRef.value.labelIcon && createVNode("span", {
979
1130
  "class": "schemx-field__label-icon"
980
- }, [schemaRef.value.labelIcon]) : null, createVNode("span", {
981
- "class": "schemx-field__label-text"
982
- }, [schemaRef.value.label, colon ? ":" : ""])]);
1131
+ }, [createVNode(Icon$1, {
1132
+ "icon": schemaRef.value.labelIcon,
1133
+ "component": formContext.iconComponent
1134
+ }, null)]), createVNode("span", {
1135
+ "class": classnames("schemx-field__label-text", {
1136
+ "is-required": showRequiredMark
1137
+ })
1138
+ }, [schemaRef.value.label, colon ? ":" : ""])])]);
983
1139
  };
984
1140
  const renderBefore = () => renderFieldSlot("Before");
985
1141
  const renderContent = () => {
986
- const component = form.getRenderer(schemaRef.value.componentType);
987
- if (!component) {
1142
+ const rendererEntry = form.getRendererEntry(schemaRef.value.componentType);
1143
+ if (!rendererEntry) {
988
1144
  throw new Error(`[schemx] Can not find component renderer of "${schemaRef.value.componentType}".`);
989
1145
  }
990
1146
  const childSlots = extractChildSlots(normalizeNameKey(schemaRef.value.name), slots);
991
- const columnElement = h(component, componentProps.value, childSlots);
1147
+ const transformedProps = rendererEntry.transformProps ? rendererEntry.transformProps(componentProps.value, {
1148
+ schema: schemaRef.value,
1149
+ form
1150
+ }) : componentProps.value;
1151
+ const columnElement = h(rendererEntry.component, transformedProps, childSlots);
992
1152
  const contentSlot = resolveSlot(slots, `${normalizeNameKey(schemaRef.value.name)}Content`);
993
- if (contentSlot) {
994
- return contentSlot(createSlotProps({
995
- columnElement
996
- }));
997
- }
998
1153
  return createVNode("div", {
999
- "class": "schemx-field__control"
1000
- }, [columnElement]);
1154
+ "class": "schemx-field__content",
1155
+ "style": {
1156
+ textAlign: schemaRef.value.contentAlign
1157
+ }
1158
+ }, [contentSlot ? contentSlot(createSlotProps({
1159
+ columnElement
1160
+ })) : columnElement]);
1001
1161
  };
1002
1162
  const renderAfter = () => renderFieldSlot("After");
1003
1163
  const renderError = () => {
1164
+ var _a;
1004
1165
  const errorSlot = resolveSlot(slots, `${normalizeNameKey(schemaRef.value.name)}Error`);
1005
- if (errorSlot) {
1006
- return errorSlot(createSlotProps({
1007
- errors: field.errors.value
1008
- }));
1009
- }
1010
- if (field.errors.value.length === 0) {
1166
+ if (!errorSlot && field.errors.value.length === 0) {
1011
1167
  return null;
1012
1168
  }
1013
1169
  return createVNode("div", {
1014
- "class": "schemx-field__error"
1015
- }, [field.errors.value[0]]);
1170
+ "class": "schemx-field__error",
1171
+ "style": {
1172
+ marginLeft: ((_a = schemaRef.value) == null ? void 0 : _a.labelPosition) === "top" ? "8px" : `calc(${labelWidth.value} + var(--schemx-field-gap))`
1173
+ }
1174
+ }, [errorSlot ? errorSlot(createSlotProps({
1175
+ errors: field.errors.value
1176
+ })) : field.errors.value[0]]);
1016
1177
  };
1017
1178
  return {
1018
1179
  createSlotProps,
@@ -1023,6 +1184,9 @@ function createFieldSlotRenderers(options) {
1023
1184
  renderLabel
1024
1185
  };
1025
1186
  }
1187
+ function _isSlot$3(s) {
1188
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
1189
+ }
1026
1190
  const Field = /* @__PURE__ */ defineComponent({
1027
1191
  name: "SchemxField",
1028
1192
  inheritAttrs: false,
@@ -1046,14 +1210,14 @@ const Field = /* @__PURE__ */ defineComponent({
1046
1210
  /**
1047
1211
  * 初始化字段上下文,并组合响应式 schema、校验处理器与插槽渲染器。
1048
1212
  *
1049
- * @param props - 当前字段项的 schema 属性。
1050
- * @param attrs - Vue setup 上下文提供的透传属性。
1051
- * @param slots - Vue setup 上下文提供的插槽集合。
1213
+ * @param props - 当前字段项的 Schema、class 和 style。
1214
+ * @param setupContext - Vue setup 上下文,包含透传属性和字段插槽。
1052
1215
  */
1053
- setup(props, {
1054
- attrs,
1055
- slots
1056
- }) {
1216
+ setup(props, setupContext) {
1217
+ const {
1218
+ attrs,
1219
+ slots
1220
+ } = setupContext;
1057
1221
  const formContext = useFormContextValue();
1058
1222
  const form = formContext.form;
1059
1223
  const inputSchema = computed(() => props.schema);
@@ -1066,9 +1230,7 @@ const Field = /* @__PURE__ */ defineComponent({
1066
1230
  const trigger = computed(() => mergeTrigger(schemaRef.value.validationTrigger, formContext.schemaConfig.validationTrigger, "onChange"));
1067
1231
  const canVerified = computed(() => {
1068
1232
  const isOperate = schemaRef.value.visible !== false && !schemaRef.value.readonly && !schemaRef.value.disabled;
1069
- const rules = schemaRef.value.rules;
1070
- const hasRules = Array.isArray(rules) ? (rules == null ? void 0 : rules.length) > 0 : !!schemaRef.value.rules;
1071
- return isOperate && (Boolean(schemaRef.value.required) || hasRules);
1233
+ return isOperate;
1072
1234
  });
1073
1235
  const handleChange = (v) => {
1074
1236
  var _a, _b, _c, _d;
@@ -1094,11 +1256,6 @@ const Field = /* @__PURE__ */ defineComponent({
1094
1256
  const currentComponentProps = schemaRef.value.componentProps ?? {};
1095
1257
  return {
1096
1258
  ...currentComponentProps,
1097
- align: schemaRef.value.readonly ? "right" : currentComponentProps.align ?? schemaRef.value.contentAlign,
1098
- readonly: schemaRef.value.readonly,
1099
- disabled: schemaRef.value.disabled,
1100
- placeholder: currentComponentProps.placeholder ?? schemaRef.value.placeholder,
1101
- readonlyPlaceholder: currentComponentProps.readonlyPlaceholder ?? schemaRef.value.readonlyPlaceholder,
1102
1259
  value: field.value.value,
1103
1260
  onChange: handleChange,
1104
1261
  onBlur: handleBlur,
@@ -1125,19 +1282,25 @@ const Field = /* @__PURE__ */ defineComponent({
1125
1282
  return null;
1126
1283
  }
1127
1284
  const fieldSlot = resolveSlot(slots, normalizeNameKey(schemaRef.value.name));
1128
- const labelPosition = schemaRef.value.labelPosition || formContext.schemaConfig.labelPosition;
1285
+ const labelPosition = schemaRef.value.labelPosition;
1129
1286
  const fieldContent = fieldSlot ? fieldSlot(createSlotProps()) : createVNode("div", {
1130
1287
  "class": classnames("schemx-field", `schemx-field--label-${labelPosition}`, {
1131
1288
  "is-readonly": schemaRef.value.readonly,
1132
1289
  "is-disabled": schemaRef.value.disabled
1133
1290
  })
1134
- }, [renderLabel(), createVNode("div", {
1135
- "class": "schemx-field__content"
1136
- }, [renderBefore(), renderContent(), renderAfter(), renderError()])]);
1137
- return createVNode("div", mergeProps(attrs, {
1138
- "class": classnames("schemx-field-wrapper", props.class, attrs.class, schemaRef.value.class),
1139
- "style": [attrs.style, props.style, schemaRef.value.style]
1140
- }), [fieldContent]);
1291
+ }, [renderLabel(), renderContent()]);
1292
+ const fieldWrapper = createVNode("div", mergeProps(attrs, {
1293
+ "class": classnames("schemx-field-wrapper", props.class, attrs.class, schemaRef.value.class, schemaRef.value.bordered ? "is-bordered" : ""),
1294
+ "style": [attrs.style, props.style, schemaRef.value.style, {
1295
+ "--schemx-content-align": schemaRef.value.contentAlign,
1296
+ "--schemx-error-align": schemaRef.value.errorAlign ?? formContext.schemaConfig.errorAlign ?? "left"
1297
+ }]
1298
+ }), [renderBefore(), fieldContent, renderError(), renderAfter()]);
1299
+ return createVNode(Col$1, {
1300
+ "col": schemaRef.value.col ?? schemaRef.value.layout
1301
+ }, _isSlot$3(fieldWrapper) ? fieldWrapper : {
1302
+ default: () => [fieldWrapper]
1303
+ });
1141
1304
  };
1142
1305
  }
1143
1306
  });
@@ -1201,58 +1364,59 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1201
1364
  };
1202
1365
  }
1203
1366
  });
1204
- const registeredColComponent = shallowRef();
1205
- function registerCol(component) {
1206
- registeredColComponent.value = component;
1367
+ function _isSlot$2(s) {
1368
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
1207
1369
  }
1208
- const Col = /* @__PURE__ */ defineComponent({
1209
- name: "SchemxCol",
1370
+ const Dynamic = /* @__PURE__ */ defineComponent({
1371
+ name: "SchemxDynamic",
1210
1372
  inheritAttrs: false,
1211
1373
  props: {
1212
- layout: {
1374
+ schema: {
1213
1375
  type: Object,
1214
- required: false,
1215
- default: void 0
1376
+ required: true
1216
1377
  },
1217
- component: {
1218
- type: [Object, Function],
1378
+ rowConfig: {
1379
+ type: Object,
1219
1380
  required: false,
1220
1381
  default: void 0
1382
+ },
1383
+ renderChildren: {
1384
+ type: Function,
1385
+ required: true
1221
1386
  }
1222
1387
  },
1223
- setup(props, {
1224
- attrs,
1225
- slots
1226
- }) {
1227
- const resolvedComponent = computed(() => {
1228
- const component = props.component ?? registeredColComponent.value;
1229
- return component ? markRaw(toRaw(component)) : void 0;
1230
- });
1388
+ /**
1389
+ * 初始化 Dynamic 的行模板渲染器。
1390
+ *
1391
+ * @param props - 当前 Dynamic ViewSchema、继承的 Row 配置和子级渲染回调。
1392
+ */
1393
+ setup(props) {
1231
1394
  return () => {
1232
- var _a;
1233
- const component = resolvedComponent.value;
1234
- if (!component) {
1235
- return ((_a = slots.default) == null ? void 0 : _a.call(slots)) ?? null;
1395
+ if (props.schema.visible === false) {
1396
+ return null;
1236
1397
  }
1237
- const layout = props.layout ?? {};
1238
- const span = layout.block ? 24 : layout.span ?? 24;
1239
- const offset = layout.block ? 0 : layout.offset ?? 0;
1240
- const {
1241
- class: attrsClass,
1242
- style: attrsStyle,
1243
- ...restAttrs
1244
- } = attrs;
1245
- return h(component, {
1246
- ...restAttrs,
1247
- class: ["schemx-col", attrsClass],
1248
- style: attrsStyle,
1249
- span,
1250
- offset
1251
- }, slots);
1398
+ const rowConfig = props.rowConfig || props.schema.row ? {
1399
+ ...props.rowConfig,
1400
+ ...props.schema.row
1401
+ } : void 0;
1402
+ const items = props.schema.items.map((item) => {
1403
+ const children = rowConfig === void 0 ? props.renderChildren(item.children) : props.renderChildren(item.children, rowConfig);
1404
+ return createVNode(Fragment, {
1405
+ "key": item.key
1406
+ }, [children]);
1407
+ });
1408
+ if (!props.schema.layout) {
1409
+ return items;
1410
+ }
1411
+ return createVNode(Col$1, {
1412
+ "col": props.schema.layout
1413
+ }, _isSlot$2(items) ? items : {
1414
+ default: () => [items]
1415
+ });
1252
1416
  };
1253
1417
  }
1254
1418
  });
1255
- const Col$1 = Col;
1419
+ const Dynamic$1 = Dynamic;
1256
1420
  function createGroupSlotRenderers(options) {
1257
1421
  const {
1258
1422
  schema,
@@ -1304,6 +1468,9 @@ function createGroupSlotRenderers(options) {
1304
1468
  renderHeaderContent
1305
1469
  };
1306
1470
  }
1471
+ function _isSlot$1(s) {
1472
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
1473
+ }
1307
1474
  const Group = /* @__PURE__ */ defineComponent({
1308
1475
  name: "SchemxGroup",
1309
1476
  inheritAttrs: false,
@@ -1312,6 +1479,11 @@ const Group = /* @__PURE__ */ defineComponent({
1312
1479
  type: Object,
1313
1480
  required: true
1314
1481
  },
1482
+ rowConfig: {
1483
+ type: Object,
1484
+ required: false,
1485
+ default: void 0
1486
+ },
1315
1487
  class: {
1316
1488
  type: [String, Object, Array, Boolean],
1317
1489
  required: false,
@@ -1329,11 +1501,18 @@ const Group = /* @__PURE__ */ defineComponent({
1329
1501
  }
1330
1502
  },
1331
1503
  slots: Object,
1332
- setup(props, {
1333
- attrs,
1334
- slots
1335
- }) {
1504
+ /**
1505
+ * 组合 Group 的折叠状态、子级渲染和插槽内容。
1506
+ *
1507
+ * @param props - 当前 Group Schema、布局和兼容渲染回调。
1508
+ * @param setupContext - 父级透传属性与 Group 插槽。
1509
+ */
1510
+ setup(props, setupContext) {
1336
1511
  var _a;
1512
+ const {
1513
+ attrs,
1514
+ slots
1515
+ } = setupContext;
1337
1516
  const internalCollapsed = ref(Boolean(props.schema.defaultCollapsed));
1338
1517
  const collapsed = computed(() => props.schema.collapsed ?? internalCollapsed.value);
1339
1518
  const componentId = ((_a = getCurrentInstance()) == null ? void 0 : _a.uid) ?? 0;
@@ -1368,12 +1547,16 @@ const Group = /* @__PURE__ */ defineComponent({
1368
1547
  const idBase = `schemx-group-${uniqueId}-${normalizeId(schema.key)}`;
1369
1548
  const headerId = `${idBase}-header`;
1370
1549
  const bodyId = `${idBase}-body`;
1550
+ const rowConfig = props.rowConfig || schema.row ? {
1551
+ ...props.rowConfig,
1552
+ ...schema.row
1553
+ } : void 0;
1371
1554
  const renderChild = (child) => {
1372
1555
  if (isViewDynamicSchema(child)) {
1373
1556
  if (child.visible === false) {
1374
1557
  return null;
1375
1558
  }
1376
- return child.items.map((item) => item.children.map((itemChild) => renderChild(itemChild)));
1559
+ return child.items.map((item) => item.children.map(renderChild));
1377
1560
  }
1378
1561
  if (isViewGroupSchema(child)) {
1379
1562
  return createVNode(Group, {
@@ -1388,6 +1571,12 @@ const Group = /* @__PURE__ */ defineComponent({
1388
1571
  "schema": child
1389
1572
  }, slots);
1390
1573
  };
1574
+ const renderGroupChildren = () => {
1575
+ if (!props.renderChildren) {
1576
+ return schema.children.map(renderChild);
1577
+ }
1578
+ return rowConfig === void 0 ? props.renderChildren(schema.children) : props.renderChildren(schema.children, rowConfig);
1579
+ };
1391
1580
  const {
1392
1581
  hasHeader,
1393
1582
  renderBodyContent,
@@ -1400,7 +1589,7 @@ const Group = /* @__PURE__ */ defineComponent({
1400
1589
  readonly: Boolean(schema.readonly),
1401
1590
  toggle,
1402
1591
  slots,
1403
- renderChildren: () => props.renderChildren ? props.renderChildren(schema.children) : schema.children.map(renderChild)
1592
+ renderChildren: renderGroupChildren
1404
1593
  });
1405
1594
  const body = createVNode("div", {
1406
1595
  "id": bodyId,
@@ -1412,7 +1601,7 @@ const Group = /* @__PURE__ */ defineComponent({
1412
1601
  display: "none"
1413
1602
  } : void 0
1414
1603
  }, [renderBodyContent()]);
1415
- return createVNode("div", mergeProps(attrs, {
1604
+ const groupWrapper = createVNode("div", mergeProps(attrs, {
1416
1605
  "class": classnames("schemx-group-wrapper", props.class, attrs.class, schema.class),
1417
1606
  "data-key": schema.key,
1418
1607
  "aria-disabled": schema.disabled || void 0,
@@ -1441,76 +1630,106 @@ const Group = /* @__PURE__ */ defineComponent({
1441
1630
  }
1442
1631
  }
1443
1632
  }, [renderHeaderContent()]), destroyOnCollapse ? !isCollapsed && body : body])]);
1633
+ if (!schema.layout) {
1634
+ return groupWrapper;
1635
+ }
1636
+ return createVNode(Col$1, {
1637
+ "col": schema.layout
1638
+ }, _isSlot$1(groupWrapper) ? groupWrapper : {
1639
+ default: () => [groupWrapper]
1640
+ });
1444
1641
  };
1445
1642
  }
1446
1643
  });
1447
1644
  const Group$1 = Group;
1448
- const Dynamic = /* @__PURE__ */ defineComponent({
1449
- name: "SchemxDynamic",
1645
+ const Row = /* @__PURE__ */ defineComponent({
1646
+ name: "SchemxRow",
1450
1647
  inheritAttrs: false,
1451
1648
  props: {
1452
- schema: {
1649
+ row: {
1453
1650
  type: Object,
1454
- required: true
1455
- },
1456
- viewSchemas: {
1457
- type: Array,
1458
- required: true
1459
- },
1460
- renderChildren: {
1461
- type: Function,
1462
1651
  required: false,
1463
1652
  default: void 0
1653
+ },
1654
+ enabled: {
1655
+ type: Boolean,
1656
+ required: false,
1657
+ default: true
1464
1658
  }
1465
1659
  },
1466
1660
  /**
1467
- * 初始化 Dynamic 的行模板渲染器。
1661
+ * 根据 Row 配置和当前 Form Context 创建行容器。
1468
1662
  *
1469
- * @param props - 当前 Dynamic ViewSchema 与 Form 根级 ViewSchema。
1470
- * @param slots - 父级透传的字段插槽。
1663
+ * @param props - Row 配置与启用状态。
1664
+ * @param setupContext - 父级透传属性与默认插槽。
1471
1665
  */
1472
- setup(props, {
1473
- slots
1474
- }) {
1475
- const getFieldRenderKey = (schema) => `${schema.key}:${normalizeNameKey(schema.name)}`;
1476
- const getFieldClass = (schema) => {
1666
+ setup(props, setupContext) {
1667
+ const {
1668
+ attrs,
1669
+ slots
1670
+ } = setupContext;
1671
+ const formContext = useOptionalFormContextValue();
1672
+ const resolvedComponent = computed(() => {
1673
+ const component = formContext == null ? void 0 : formContext.rowComponent;
1674
+ return component ? markRaw(toRaw(component)) : void 0;
1675
+ });
1676
+ return () => {
1677
+ var _a, _b;
1678
+ const component = resolvedComponent.value;
1679
+ const row = props.row ?? {};
1477
1680
  const {
1478
- isFirst,
1479
- isLast
1480
- } = getSectionPosition(props.viewSchemas, schema.key);
1481
- return {
1482
- "schemx-field-wrapper--first": isFirst,
1483
- "schemx-field-wrapper--last": isLast
1681
+ gutter,
1682
+ justify,
1683
+ align,
1684
+ ...extensionProps
1685
+ } = row;
1686
+ const {
1687
+ class: attrsClass,
1688
+ style: attrsStyle,
1689
+ ...restAttrs
1690
+ } = attrs;
1691
+ const componentAttrs = {
1692
+ ...extensionProps,
1693
+ ...restAttrs
1484
1694
  };
1485
- };
1486
- const renderItemSchema = (schema) => {
1487
- if (isViewGroupSchema(schema)) {
1488
- return createVNode(Group$1, {
1489
- "key": schema.key,
1490
- "schema": schema
1491
- }, slots);
1695
+ const rowClassValue = ["schemx-row", attrsClass];
1696
+ const justifyContent = justify === "start" ? "flex-start" : justify === "end" ? "flex-end" : justify;
1697
+ const alignItems = align === "top" ? "flex-start" : align === "middle" ? "center" : align === "bottom" ? "flex-end" : void 0;
1698
+ const [gutterTop, gutterRight, gutterBottom, gutterLeft] = normalizeSchemxGutter(gutter);
1699
+ const paddingTop = gutterTop / 2;
1700
+ const paddingRight = gutterRight / 2;
1701
+ const paddingBottom = gutterBottom / 2;
1702
+ const paddingLeft = gutterLeft / 2;
1703
+ const internalRowStyle = [attrsStyle, {
1704
+ "--schemx-gutter-top": `${paddingTop}px`,
1705
+ "--schemx-gutter-right": `${paddingRight}px`,
1706
+ "--schemx-gutter-bottom": `${paddingBottom}px`,
1707
+ "--schemx-gutter-left": `${paddingLeft}px`,
1708
+ margin: `-${paddingTop}px -${paddingRight}px -${paddingBottom}px -${paddingLeft}px`,
1709
+ justifyContent,
1710
+ alignItems
1711
+ }];
1712
+ if (!props.enabled) {
1713
+ return ((_a = slots.default) == null ? void 0 : _a.call(slots)) ?? null;
1492
1714
  }
1493
- const field = schema;
1494
- return createVNode(Field$1, {
1495
- "key": getFieldRenderKey(field),
1496
- "schema": field,
1497
- "class": getFieldClass(field)
1498
- }, slots);
1499
- };
1500
- return () => {
1501
- if (props.schema.visible === false) {
1502
- return null;
1715
+ if (!component) {
1716
+ return createVNode("div", mergeProps(restAttrs, {
1717
+ "class": rowClassValue,
1718
+ "style": internalRowStyle
1719
+ }), [(_b = slots.default) == null ? void 0 : _b.call(slots)]);
1503
1720
  }
1504
- return props.schema.items.map((item) => {
1505
- const children = props.renderChildren ? props.renderChildren(item.children) : item.children.map(renderItemSchema);
1506
- return createVNode(Fragment, {
1507
- "key": item.key
1508
- }, [children]);
1509
- });
1721
+ return h(component, {
1722
+ ...componentAttrs,
1723
+ gutter,
1724
+ justify,
1725
+ align,
1726
+ class: rowClassValue,
1727
+ style: internalRowStyle
1728
+ }, slots);
1510
1729
  };
1511
1730
  }
1512
1731
  });
1513
- const Dynamic$1 = Dynamic;
1732
+ const Row$1 = Row;
1514
1733
  function _isSlot(s) {
1515
1734
  return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
1516
1735
  }
@@ -1526,8 +1745,8 @@ const SchemaList = /* @__PURE__ */ defineComponent({
1526
1745
  type: Array,
1527
1746
  required: true
1528
1747
  },
1529
- colComponent: {
1530
- type: [Object, Function],
1748
+ rowConfig: {
1749
+ type: Object,
1531
1750
  required: false,
1532
1751
  default: void 0
1533
1752
  },
@@ -1541,17 +1760,12 @@ const SchemaList = /* @__PURE__ */ defineComponent({
1541
1760
  slots
1542
1761
  }) {
1543
1762
  const getFieldRenderKey = (schema) => `${schema.key}:${normalizeNameKey(schema.name)}`;
1544
- const getSchemaRenderKey = (schema) => {
1545
- if (isSchemxViewFieldSchema(schema)) {
1546
- return getFieldRenderKey(schema);
1547
- }
1548
- return schema.key;
1549
- };
1550
- const renderChildren = (schemas) => {
1763
+ const renderChildren = (schemas, rowConfig = props.rowConfig) => {
1551
1764
  return h(SchemaList, {
1552
1765
  schemas,
1553
1766
  viewSchemas: props.viewSchemas,
1554
- colComponent: props.colComponent
1767
+ rowConfig,
1768
+ fieldClassResolver: props.fieldClassResolver
1555
1769
  }, slots);
1556
1770
  };
1557
1771
  const renderSchema = (schema) => {
@@ -1564,13 +1778,14 @@ const SchemaList = /* @__PURE__ */ defineComponent({
1564
1778
  content = createVNode(Group$1, {
1565
1779
  "key": schema.key,
1566
1780
  "schema": schema,
1781
+ "rowConfig": props.rowConfig,
1567
1782
  "renderChildren": renderChildren
1568
1783
  }, slots);
1569
1784
  } else if (isViewDynamicSchema(schema)) {
1570
1785
  content = createVNode(Dynamic$1, {
1571
1786
  "key": schema.key,
1572
1787
  "schema": schema,
1573
- "viewSchemas": props.viewSchemas,
1788
+ "rowConfig": props.rowConfig,
1574
1789
  "renderChildren": renderChildren
1575
1790
  }, slots);
1576
1791
  } else {
@@ -1580,25 +1795,16 @@ const SchemaList = /* @__PURE__ */ defineComponent({
1580
1795
  "class": (_a = props.fieldClassResolver) == null ? void 0 : _a.call(props, schema)
1581
1796
  }, slots);
1582
1797
  }
1583
- if (!props.colComponent) {
1584
- return content;
1585
- }
1586
- return createVNode(Col$1, {
1587
- "key": getSchemaRenderKey(schema),
1588
- "component": props.colComponent,
1589
- "layout": schema.layout
1590
- }, _isSlot(content) ? content : {
1591
- default: () => [content]
1592
- });
1798
+ return content;
1593
1799
  };
1594
1800
  return () => {
1595
- const children = props.schemas.map(renderSchema);
1596
- if (!props.colComponent) {
1597
- return children;
1598
- }
1599
- return createVNode("div", {
1600
- "class": "schemx-row"
1601
- }, [children]);
1801
+ let _slot;
1802
+ return createVNode(Row$1, {
1803
+ "row": props.rowConfig,
1804
+ "class": "schemx-schema-list"
1805
+ }, _isSlot(_slot = props.schemas.map(renderSchema)) ? _slot : {
1806
+ default: () => [_slot]
1807
+ });
1602
1808
  };
1603
1809
  }
1604
1810
  });
@@ -1616,12 +1822,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1616
1822
  initialValues: { default: () => ({}) },
1617
1823
  modelValue: { default: () => ({}) },
1618
1824
  form: { default: void 0 },
1825
+ row: { default: void 0 },
1619
1826
  loading: { type: Boolean, default: void 0 },
1620
1827
  submitter: { type: [Boolean, Object], default: true },
1621
1828
  resetter: { type: [Boolean, Object], default: true },
1622
1829
  class: { type: [Boolean, null, String, Object, Array], default: "" },
1623
1830
  style: { type: [Boolean, null, String, Object, Array], default: () => ({}) },
1624
- colComponent: { default: void 0 },
1625
1831
  rendererProps: { default: void 0 },
1626
1832
  validatorAdapters: {},
1627
1833
  defaultRendererType: {},
@@ -1641,14 +1847,21 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1641
1847
  readonly: { type: Boolean, default: void 0 },
1642
1848
  disabled: { type: Boolean, default: void 0 },
1643
1849
  visible: { type: Boolean, default: void 0 },
1850
+ colComponent: { default: void 0 },
1851
+ rowComponent: { default: void 0 },
1852
+ iconComponent: { default: void 0 },
1853
+ col: { default: void 0 },
1854
+ layout: {},
1644
1855
  labelIcon: {},
1645
1856
  labelAlign: {},
1646
1857
  labelPosition: {},
1647
1858
  labelWidth: {},
1648
1859
  contentAlign: {},
1860
+ errorAlign: {},
1649
1861
  validationTrigger: { default: void 0 },
1650
1862
  colon: { type: Boolean, default: void 0 },
1651
- showRequiredMark: { type: Boolean, default: void 0 }
1863
+ showRequiredMark: { type: Boolean, default: void 0 },
1864
+ bordered: { type: Boolean, default: void 0 }
1652
1865
  },
1653
1866
  emits: ["update:modelValue"],
1654
1867
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -1667,7 +1880,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1667
1880
  };
1668
1881
  const isExternalForm = props.form !== void 0;
1669
1882
  const schemaConfigProps = computed(pickSchemaConfig);
1670
- const appConfig = getSchemxAppConfig();
1671
1883
  const providerConfig = useConfigProviderContextRef();
1672
1884
  const coreConfig = getGlobalSchemxConfig();
1673
1885
  const formFallbackConfig = {
@@ -1677,10 +1889,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1677
1889
  }
1678
1890
  };
1679
1891
  const mergedConfig = computed(
1680
- () => isExternalForm ? mergeSchemxConfig({ schemaConfig: schemaConfigProps.value }, formFallbackConfig) : mergeSchemxConfig(
1892
+ () => isExternalForm ? mergeConfig(
1893
+ { schemaConfig: schemaConfigProps.value },
1894
+ formFallbackConfig
1895
+ ) : mergeConfig(
1681
1896
  { schemaConfig: schemaConfigProps.value },
1682
1897
  (providerConfig == null ? void 0 : providerConfig.value) ?? {},
1683
- appConfig,
1684
1898
  formFallbackConfig,
1685
1899
  coreConfig
1686
1900
  )
@@ -1690,12 +1904,29 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1690
1904
  ...mergedConfig.value.schemaConfig
1691
1905
  }));
1692
1906
  const resolvedSchemaConfig = computed(
1693
- () => resolveSchemxConfig(mergedConfig.value).schemaConfig
1907
+ () => resolveSchemxConfig({ schemaConfig: contextSchemaConfig.value }).schemaConfig
1694
1908
  );
1695
1909
  const hasSchemaConfigKey = (config, key) => Object.prototype.hasOwnProperty.call(config, key);
1696
1910
  const resolvedColComponent = computed(
1697
- () => props.colComponent ?? (providerConfig == null ? void 0 : providerConfig.value.colComponent) ?? appConfig.colComponent ?? registeredColComponent.value
1911
+ () => props.colComponent ?? (providerConfig == null ? void 0 : providerConfig.value.colComponent) ?? coreConfig.colComponent
1912
+ );
1913
+ const resolvedRowComponent = computed(
1914
+ () => props.rowComponent ?? (providerConfig == null ? void 0 : providerConfig.value.rowComponent) ?? coreConfig.rowComponent
1915
+ );
1916
+ const resolvedIconComponent = computed(
1917
+ () => props.iconComponent ?? (providerConfig == null ? void 0 : providerConfig.value.iconComponent) ?? coreConfig.iconComponent
1698
1918
  );
1919
+ const resolvedRowConfig = computed(() => {
1920
+ const schemaConfigRow = resolvedSchemaConfig.value.row;
1921
+ const inheritedRowConfig = (providerConfig == null ? void 0 : providerConfig.value.row) ?? coreConfig.row ?? schemaConfigRow;
1922
+ if (inheritedRowConfig === void 0 && props.row === void 0) {
1923
+ return void 0;
1924
+ }
1925
+ return {
1926
+ ...inheritedRowConfig,
1927
+ ...props.row
1928
+ };
1929
+ });
1699
1930
  const providedForm = props.form ? props.form : useForm({
1700
1931
  schemas: props.schemas,
1701
1932
  schemaConfig: resolvedSchemaConfig.value,
@@ -1720,11 +1951,11 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1720
1951
  /**
1721
1952
  * 转发提交失败回调。
1722
1953
  *
1723
- * @param errors - 提交失败时的字段错误集合。
1954
+ * @param failure - 提交失败结果,包含本次表单值和校验错误。
1724
1955
  */
1725
- onFinishFailed: (errors) => {
1956
+ onFinishFailed: (failure) => {
1726
1957
  var _a;
1727
- return (_a = props.onFinishFailed) == null ? void 0 : _a.call(props, errors);
1958
+ return (_a = props.onFinishFailed) == null ? void 0 : _a.call(props, failure);
1728
1959
  },
1729
1960
  /**
1730
1961
  * 转发完整表单重置回调。
@@ -1769,6 +2000,15 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1769
2000
  form: providedForm,
1770
2001
  get schemaConfig() {
1771
2002
  return contextSchemaConfig.value;
2003
+ },
2004
+ get iconComponent() {
2005
+ return resolvedIconComponent.value;
2006
+ },
2007
+ get colComponent() {
2008
+ return resolvedColComponent.value;
2009
+ },
2010
+ get rowComponent() {
2011
+ return resolvedRowComponent.value;
1772
2012
  }
1773
2013
  });
1774
2014
  const effectiveLoading = computed(() => props.loading ?? formInstance.isLoading());
@@ -1907,7 +2147,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1907
2147
  createVNode(unref(SchemaList$1), {
1908
2148
  schemas: unref(viewSchemas),
1909
2149
  "view-schemas": unref(viewSchemas),
1910
- "col-component": resolvedColComponent.value,
2150
+ "row-component": resolvedRowComponent.value,
2151
+ "row-config": resolvedRowConfig.value,
1911
2152
  "field-class-resolver": getFieldClass
1912
2153
  }, createSlots({ _: 2 }, [
1913
2154
  renderList(fieldSlots.value, (_, slotName) => {
@@ -1918,7 +2159,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1918
2159
  ])
1919
2160
  };
1920
2161
  })
1921
- ]), 1032, ["schemas", "view-schemas", "col-component"]),
2162
+ ]), 1032, ["schemas", "view-schemas", "row-component", "row-config"]),
1922
2163
  isActionsVisible.value ? (openBlock(), createElementBlock("div", _hoisted_1, [
1923
2164
  isResetterVisible.value && unref(slots).resetter ? renderSlot(_ctx.$slots, "resetter", {
1924
2165
  form: unref(formInstance),
@@ -2085,11 +2326,31 @@ const ConfigProvider = /* @__PURE__ */ defineComponent({
2085
2326
  colComponent: {
2086
2327
  type: [Object, Function],
2087
2328
  default: void 0
2329
+ },
2330
+ rowComponent: {
2331
+ type: [Object, Function],
2332
+ default: void 0
2333
+ },
2334
+ iconComponent: {
2335
+ type: [Object, Function],
2336
+ default: void 0
2337
+ },
2338
+ row: {
2339
+ type: Object,
2340
+ default: void 0
2088
2341
  }
2089
2342
  },
2090
- setup(props, {
2091
- slots
2092
- }) {
2343
+ /**
2344
+ * 合并 Props 与 fallthrough attrs,并向后代提供配置上下文。
2345
+ *
2346
+ * @param props - 当前 ConfigProvider 的 Schemx 配置。
2347
+ * @param setupContext - 父级传入的默认插槽与额外配置属性。
2348
+ */
2349
+ setup(props, setupContext) {
2350
+ const {
2351
+ slots,
2352
+ attrs
2353
+ } = setupContext;
2093
2354
  const config = computed(() => ({
2094
2355
  schemaConfig: props.schemaConfig,
2095
2356
  rendererProps: props.rendererProps,
@@ -2097,7 +2358,11 @@ const ConfigProvider = /* @__PURE__ */ defineComponent({
2097
2358
  defaultRendererType: props.defaultRendererType,
2098
2359
  rendererRegistry: props.rendererRegistry,
2099
2360
  presetRuleRegistry: props.presetRuleRegistry,
2100
- colComponent: props.colComponent
2361
+ colComponent: props.colComponent,
2362
+ rowComponent: props.rowComponent,
2363
+ iconComponent: props.iconComponent,
2364
+ row: props.row,
2365
+ ...attrs
2101
2366
  }));
2102
2367
  createConfigProviderContext(config);
2103
2368
  return () => {
@@ -2112,6 +2377,8 @@ export {
2112
2377
  ConfigProvider$1 as ConfigProvider,
2113
2378
  Field$1 as Field,
2114
2379
  Group$1 as Group,
2380
+ Icon$1 as Icon,
2381
+ Row$1 as Row,
2115
2382
  WithRemoteOptions,
2116
2383
  _sfc_main as Wrapper,
2117
2384
  createConfigProviderContext,
@@ -2119,9 +2386,9 @@ export {
2119
2386
  createFormConfigContext,
2120
2387
  createFormContext,
2121
2388
  SchemxFormExport$1 as default,
2389
+ normalizeSchemxGutter,
2122
2390
  presetRuleRegistry,
2123
2391
  provideFormContext,
2124
- registerCol,
2125
2392
  rendererRegistry,
2126
2393
  SchemxFormExport$1 as schemxForm,
2127
2394
  useConfigProviderContext,